Files
yidaima/RuoYi-Vue/docs/superpowers/plans/2026-07-12-one-click-reference-closure-repair.md

207 lines
9.8 KiB
Markdown

# One-Click Reference Closure Repair 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:** Preserve independent backend roles such as `librarian`, generate their profile pages deterministically, repair safe historical blueprints, and reject every unresolved ProjectSpec cross-reference before source rendering.
**Architecture:** Extend the existing menu DTO with optional page metadata, keep AI normalization backward compatible, and make admin page initialization resolve profile pages against the complete table catalog. Extend the existing consistency validator/repair service rather than adding a second validation stack, so Page Initialize remains the single pre-source closure gate.
**Tech Stack:** Java 8, Spring Boot, Jackson/Fastjson2, MyBatis, JUnit 4, Mockito, Maven.
---
### Task 1: Preserve independent backend roles and menu metadata
**Files:**
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/domain/front/dto/AppMenuDesign.java`
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java`
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerateServiceImplTest.java`
- [ ] **Step 1: Write failing role and menu metadata tests**
Add a fixture containing `admin`, `reader`, and `librarian/图书管理员`, plus an admin profile menu with `tableName=librarian` and `pageType=form`. Assert that all three roles survive normalization and the menu fields survive serialization.
```java
assertEquals("librarian", blueprint.getRoles().get(2).getCode());
assertEquals("librarian", blueprint.getAdminMenus().get(1).getTableName());
assertEquals("form", blueprint.getAdminMenus().get(1).getPageType());
```
- [ ] **Step 2: Run the new tests and verify RED**
Run:
```powershell
mvn -pl ruoyi-generator -am "-Dtest=AiGenerateServiceImplTest#generateAppBlueprintPreservesIndependentBackendRole" "-Dsurefire.failIfNoSpecifiedTests=false" test
```
Expected: FAIL because `librarian` is collapsed into `admin` and the menu DTO lacks metadata accessors.
- [ ] **Step 3: Add optional menu fields and exact admin classification**
Add `tableName` and `pageType` properties with getters/setters. Change the system-admin check to exact normalized code equality and normalize the optional fields.
```java
private boolean isAdminRole(String code, String name)
{
return "admin".equals(normalizeDatabaseName(code, "role"));
}
```
Update the application-blueprint prompt so admin menu examples include `pageCode`, `tableName`, and `pageType`, and state that business administrators remain independent roles.
- [ ] **Step 4: Run the targeted test and verify GREEN**
Run the command from Step 2. Expected: PASS.
### Task 2: Generate backend profile pages from shared account tables
**Files:**
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/FrontendPageDesignService.java`
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/FrontendPageDesignServiceTest.java`
- [ ] **Step 1: Write failing shared-table profile tests**
Create a blueprint with `librarian_admin_page` and `librarian_profile_page`, both bound to `librarian`, and assert that initialization returns both pages with `list` and `form` page types.
```java
assertEquals("list", responseByPageCode(designs, "librarian_admin_page").getPageType());
assertEquals("form", responseByPageCode(designs, "librarian_profile_page").getPageType());
assertEquals("librarian", responseByPageCode(designs, "librarian_profile_page").getTableName());
```
Add a second test asserting that an unresolvable admin menu throws `ServiceException` containing its menu and page codes.
- [ ] **Step 2: Run the tests and verify RED**
```powershell
mvn -pl ruoyi-generator -am "-Dtest=FrontendPageDesignServiceTest#initializeAdminDesignsAllowsProfileToReuseAccountTable+initializeAdminDesignsRejectsUnresolvableMenu" "-Dsurefire.failIfNoSpecifiedTests=false" test
```
Expected: profile page is absent and the unresolvable menu is silently skipped.
- [ ] **Step 3: Implement deterministic admin menu resolution**
Resolve `menu.tableName` first. For profile menus, derive the role prefix and look in the complete table catalog rather than `unmatchedTables`; do not consume the table twice. Use explicit `menu.pageType`, otherwise default profile pages to `form` and other admin pages to `list`.
```java
String pageType = StringUtils.isNotBlank(menu.getPageType())
? menu.getPageType() : isProfileMenu(menu) ? "form" : "list";
page.setPageType(pageType);
```
Replace the silent `continue` for a page-bearing admin menu with a detailed `ServiceException`.
- [ ] **Step 4: Run the targeted tests and verify GREEN**
Run the command from Step 2. Expected: both tests PASS.
### Task 3: Repair historical profile roles and enforce reference closure
**Files:**
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/FrontProjectConsistencyValidator.java`
- Modify: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/FrontProjectGenerationConsistencyService.java`
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/FrontProjectGenerationConsistencyServiceTest.java`
- Test: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/FrontProjectConsistencyValidatorTest.java` (create if no focused validator test exists)
- [ ] **Step 1: Write failing historical repair test**
Model project 104: roles `admin/reader`, a `librarian_profile` admin menu with empty visible roles and `CURRENT_USER`, a `librarian` table, and a generated `librarian_profile_page`. Assert repair adds the role and menu metadata and persists the blueprint.
```java
assertTrue(updatedBlueprint.contains("\"code\":\"librarian\""));
assertTrue(updatedBlueprint.contains("\"visibleRoles\":[\"librarian\"]"));
assertTrue(updatedBlueprint.contains("\"tableName\":\"librarian\""));
assertTrue(updatedBlueprint.contains("\"pageType\":\"form\""));
```
- [ ] **Step 2: Write failing closure validation tests**
Cover frontend menu to page, admin menu to page design, frontend parent page, and menu role references. Each assertion must check the precise blueprint path in the exception.
```java
assertFailure(project, "appBlueprint.adminMenus[librarian_profile].pageCode");
assertFailure(project, "appBlueprint.frontendPages[detail].parentPageCode");
assertFailure(project, "appBlueprint.adminMenus[librarian_profile].visibleRoles");
```
- [ ] **Step 3: Run the new tests and verify RED**
```powershell
mvn -pl ruoyi-generator -am "-Dtest=FrontProjectGenerationConsistencyServiceTest,FrontProjectConsistencyValidatorTest" "-Dsurefire.failIfNoSpecifiedTests=false" test
```
Expected: historical repair does not run and reference closure violations are accepted.
- [ ] **Step 4: Implement unique historical repair**
In `repairAppBlueprint`, detect `CURRENT_USER` profile menus whose prefix uniquely matches a non-admin table. Add the missing role, set `visibleRoles`, `tableName`, and `pageType=form`, then persist through the existing `updateProjectJson` path. Do not repair ambiguous prefixes.
- [ ] **Step 5: Implement scoped closure validation**
Build frontend/admin page-code sets, menu-code sets, and role-code sets from the blueprint plus page designs. Validate all menu page references, parent references, role references, and table references before returning from `validatePreviewReady`.
- [ ] **Step 6: Run the targeted tests and verify GREEN**
Run the command from Step 3. Expected: all tests PASS.
### Task 4: Close the AI database-generation regression suite
**Files:**
- Modify: `ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiGenerateServiceImplTest.java`
- Modify only if a production defect is proven: `ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiGenerateServiceImpl.java`
- [ ] **Step 1: Run the full AI generator test class**
```powershell
mvn -pl ruoyi-generator -am "-Dtest=AiGenerateServiceImplTest" "-Dsurefire.failIfNoSpecifiedTests=false" test
```
Expected baseline: 11 failures caused by the contract that always adds the `admin` account table and its columns.
- [ ] **Step 2: Update stale assertions to inspect tables by code**
Replace invocation-count assumptions with captor searches for the business table and separately assert the generated `admin` account table. Preserve all existing column, SQL-safety, and prompt assertions.
```java
FrontProjectTable car = capturedTable(tables, "car_info");
FrontProjectTable admin = capturedTable(tables, "admin");
assertNotNull(car);
assertNotNull(admin);
```
- [ ] **Step 3: Run the full class and verify GREEN**
Run the command from Step 1. Expected: all `AiGenerateServiceImplTest` tests PASS.
### Task 5: End-to-end regression verification
**Files:**
- Test: all files modified above
- Verify: project 104 reference audit through read-only SQL
- [ ] **Step 1: Run the focused one-click reference suite**
```powershell
mvn -pl ruoyi-generator -am "-Dtest=AiGenerateServiceImplTest,FrontendPageDesignServiceTest,FrontProjectGenerationConsistencyServiceTest,FrontProjectConsistencyValidatorTest,ProjectSpecAssemblerTest,ProjectSpecValidatorTest,ProjectSpecVersionServiceTest,OneClickProjectGenerationServiceImplTest" "-Dsurefire.failIfNoSpecifiedTests=false" test
```
Expected: zero failures.
- [ ] **Step 2: Run module tests and compile**
```powershell
mvn -pl ruoyi-generator -am test
```
Expected: BUILD SUCCESS.
- [ ] **Step 3: Review the final diff without staging unrelated work**
```powershell
git diff --check
git status --short
```
Expected: no whitespace errors; only planned files contain new edits. Because the checkout already contains user-owned modifications in the same files, do not stage or commit implementation files unless their ownership can be isolated safely.