# Factory Version Workspace Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Allow a user to roll a project back by creating a new immutable ProjectSpec version, then inspect, validate, compare, regenerate, and review generated file fingerprints from a read-only Factory workspace. **Architecture:** Rollback copies a historical version into a new row whose parent is the current latest version; it never updates an existing version or writes the Spec back into legacy project tables. The Vue workspace consumes the existing Spec/version/diff/generation APIs plus the rollback endpoint and keeps generated manifests in page memory only. **Tech Stack:** Java 8, Spring MVC, MyBatis, JUnit 4, Mockito, Vue 3, Vue Router, Element Plus, Node test runner, Vite. --- ### Task 1: Immutable Version Rollback **Files:** - Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/factory/version/ProjectSpecVersionService.java` - Create: `ruoyi-generator/src/main/java/com/ruoyi/generator/factory/version/model/ProjectSpecRollbackRequest.java` - Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/factory/version/ProjectSpecVersionServiceTest.java` - [ ] **Step 1: Write failing rollback service tests** Add tests that call: ```java ProjectSpecVersionView result = service.rollback( 7L, 20L, 100L, "Restore stable design"); ``` Assert that the inserted row uses the target content, `versionNo = latest + 1`, `parentVersionId = latest.specVersionId`, `changeSource = ROLLBACK`, and never mutates the target row. Add rejection cases for rolling back to content already current and for a stored target hash that does not match its JSON. - [ ] **Step 2: Run the rollback tests and confirm the missing method fails compilation** Run: ```text mvn -pl ruoyi-generator -am "-Dtest=ProjectSpecVersionServiceTest" "-Dsurefire.failIfNoSpecifiedTests=false" test ``` Expected: test compilation fails because `rollback(...)` does not exist. - [ ] **Step 3: Implement the minimal transactional rollback** Add this public contract: ```java @Transactional public ProjectSpecVersionView rollback(Long userId, Long projectId, Long targetVersionId, String changeSummary) ``` The method must verify project ownership, load the target by user/project/version ID, lock the latest row, rebuild a `ProjectSpecDocument` through `ProjectSpecJsonCodec`, reject hash corruption or content already current, and call the existing immutable insert path with the latest row as parent. - [ ] **Step 4: Run the service tests and confirm they pass** Run the command from Step 2. Expected: all `ProjectSpecVersionServiceTest` tests pass. ### Task 2: Rollback HTTP and Frontend API Contracts **Files:** - Modify: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/front/FrontFactoryProjectController.java` - Modify: `ruoyi-admin/src/test/java/com/ruoyi/web/controller/front/FrontFactoryProjectControllerTest.java` - Modify: `easycode-web/src/api/project.js` - [ ] **Step 1: Write a failing controller delegation test** The controller test must authenticate user `7`, call: ```java controller.rollbackSpecVersion(20L, 100L, request); ``` and verify `projectSpecVersionService.rollback(7L, 20L, 100L, request.getChangeSummary())`. - [ ] **Step 2: Run the controller test and confirm the missing endpoint fails compilation** Run: ```text mvn -pl ruoyi-admin -am "-Dtest=FrontFactoryProjectControllerTest" "-Dsurefire.failIfNoSpecifiedTests=false" test ``` Expected: test compilation fails because `rollbackSpecVersion(...)` does not exist. - [ ] **Step 3: Add the endpoint and browser wrapper** Add: ```java @PostMapping("/{projectId}/versions/{specVersionId}/rollback") public AjaxResult rollbackSpecVersion(@PathVariable Long projectId, @PathVariable Long specVersionId, @RequestBody(required = false) ProjectSpecRollbackRequest request) ``` Add the browser API: ```js export function rollbackProjectSpecVersion(projectId, versionId, data) { return request({ url: `/front/factory/projects/${projectId}/versions/${versionId}/rollback`, method: 'post', data }).then(unwrap) } ``` - [ ] **Step 4: Run the controller test and confirm it passes** Run the command from Step 2. Expected: all controller tests pass. ### Task 3: Read-Only Factory Version Workspace **Files:** - Create: `easycode-web/src/views/FactoryProjectView.vue` - Create: `easycode-web/src/views/factoryProjectView.test.mjs` - Modify: `easycode-web/src/router/index.js` - Modify: `easycode-web/src/views/ProjectListView.vue` - [ ] **Step 1: Write source-contract tests for the workspace** Assert that the new route is `/project/:projectId/factory`, the project list exposes an icon-only history action with a tooltip, and the view imports and uses: ```js listProjectSpecVersions getProjectSpecVersion validateProjectSpec diffProjectSpecVersions generateProjectSpecVersion rollbackProjectSpecVersion ``` The test must also require three read-only tabs for Spec, semantic Diff, and generated manifest, plus a rollback confirmation dialog. - [ ] **Step 2: Run the Node test and confirm it fails before the view exists** Run: ```text node --test src/views/factoryProjectView.test.mjs ``` Expected: failure because `FactoryProjectView.vue` and its route do not exist. - [ ] **Step 3: Build the operational workspace** Implement a full-width project tool with: - a compact header with project name, refresh, and return-to-project controls; - a stable-width version history pane with source, time, hash, and current marker; - a detail pane with validation status and actions for generate and rollback; - a read-only formatted JSON view; - semantic diff selectors, counts, and a change table; - an in-memory generated manifest summary grouped by target and file path; - responsive stacking below 900 px without nested cards or overlapping controls. - [ ] **Step 4: Run the Node test and production build** Run: ```text node --test src/views/factoryProjectView.test.mjs npm run build ``` Expected: the new test passes and Vite completes successfully; existing chunk-size warnings may remain. ### Task 4: Regression, Visual Check, and Roadmap Record **Files:** - Modify: `docs/superpowers/specs/2026-07-10-ai-software-factory-roadmap.md` - [ ] **Step 1: Run the P1 Factory regression group** Run: ```text mvn -pl ruoyi-admin -am "-Dtest=ProjectSpec*Test,LegacyProjectProjectionTest,FrontProjectPreviewServiceImplTest,FrontFactoryProjectControllerTest,GenProjectServiceImplTest" "-Dsurefire.failIfNoSpecifiedTests=false" test ``` Expected: all selected generator and admin tests pass. - [ ] **Step 2: Start the frontend and inspect the workspace shell** Start Vite on an unused localhost port with a hidden background process. Verify desktop and mobile widths for fixed controls, readable JSON/diff tables, version selection, and absence of overlap. API-empty/error states must remain coherent when the backend is unavailable. - [ ] **Step 3: Check final diffs** Run: ```text git diff --check ``` Expected: no whitespace errors; the repository may continue to report its existing LF/CRLF warnings. - [ ] **Step 4: Record P1-F status and boundaries** Append the implementation, verification evidence, and remaining boundary that rollback creates a canonical version but does not deploy it into legacy tables. Record the next phase as persisted generation runs/artifact comparison or the P2 generation-kernel split. ## Plan Self-Review - The plan covers rollback semantics, ownership, corruption checks, HTTP delegation, the read-only UI, responsive behavior, test evidence, and roadmap updates. - Method names and routes match the existing Factory conventions and are consistent across backend, frontend, and tests. - No database schema is required because rollback inserts into the existing immutable version table. - No generated ZIP or artifact is persisted in P1-F, keeping this phase within the approved scope. - The current dirty worktree will not be staged, committed, reset, or cleaned as part of this plan.