207 lines
8.1 KiB
Markdown
207 lines
8.1 KiB
Markdown
# 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.
|