Files
yidaima/RuoYi-Vue/docs/superpowers/plans/2026-07-10-factory-version-workspace.md

207 lines
8.1 KiB
Markdown
Raw Normal View History

# 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.