9.8 KiB
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.
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:
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.
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.
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
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.
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.
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.
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
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
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.
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
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
mvn -pl ruoyi-generator -am test
Expected: BUILD SUCCESS.
- Step 3: Review the final diff without staging unrelated work
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.