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

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.