Files
workutils/docs/superpowers/plans/2026-08-05-ai-test-plugin-ui-optimization.md
2026-08-05 11:16:38 +08:00

10 KiB
Raw Permalink Blame History

AI 单测插件完整 UI 优化实施计划

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: 将 AI 单测插件改为四个主 Tab 的低密度工作台,并提供目录选择、准确的模块反馈和只在主动任务期间出现的全局进度。

Architecture: AiTestPane 保留工作流编排,但把可独立验证的行为下沉到 DirectoryPathSelector、TaskProgressState 和现有 StartModuleSelector。项目加载继续使用 LatestRequestGate,Git 分析继续传递显式 baseline 与 targetRef。

Tech Stack: Java 17、JavaFX 17、Spring Boot 2.7、Maven、JUnit 5

Global Constraints

  • 主页面固定为 项目与增量、工具链、质量规范、结果与合并 四个不可关闭 Tab,不再使用 Accordion。
  • JDK 8 Home 与 Maven Home 必须通过目录选择器选择,路径框只读。
  • 基线默认 master,目标默认 HEAD;不得破坏任意 baseline...targetRef 分析能力。
  • 项目加载不得进入全局 busy,较早异步结果不得覆盖最新选择。
  • 空闲时全局进度条隐藏并重置;仅用户主动的分析、生成、验证、合并和工具链检查显示。
  • 真实 ft-loancapital-core 必须继续检出 ft-loancapital-core-start。
  • 不触碰现有未跟踪的审计文档、截图目录和 SQL 文件。
  • 全程单线程实施,不使用子代理。

Task 1: 可测试的目录选择组件

Files:

  • Create: src/main/java/com/example/workutils/biz/aitest/ui/DirectoryPathSelector.java
  • Test: src/test/java/com/example/workutils/biz/aitest/ui/DirectoryPathSelectorTest.java

Interfaces:

  • Produces: DirectoryPathSelector(String label, Supplier<Window> ownerSupplier)

  • Produces: Path getPath()、void setPath(Path)、TextField pathField()、Button chooseButton()

  • Internal test seam: package-private void applySelection(File selected),null 表示取消。

  • Step 1: 写失败测试

@Test
void pathIsReadOnlyAndCancelKeepsExistingValue() throws Exception {
    DirectoryPathSelector selector = FxTestSupport.fx(
            () -> new DirectoryPathSelector("JDK 8 Home", () -> null));
    FxTestSupport.fx(() -> selector.setPath(Path.of("C:/jdk8")));
    FxTestSupport.fx(() -> selector.applySelection(null));
    assertFalse(FxTestSupport.fx(() -> selector.pathField().isEditable()));
    assertEquals(Path.of("C:/jdk8"), FxTestSupport.fx(selector::getPath));
}

@Test
void selectedDirectoryUpdatesValue() throws Exception {
    DirectoryPathSelector selector = FxTestSupport.fx(
            () -> new DirectoryPathSelector("Maven Home", () -> null));
    FxTestSupport.fx(() -> selector.applySelection(new File("C:/maven")));
    assertEquals(Path.of("C:/maven"), FxTestSupport.fx(selector::getPath));
}
  • Step 2: 运行 RED

Run: mvn -Dtest=DirectoryPathSelectorTest test

Expected: FAIL,因为 DirectoryPathSelector 尚不存在。

  • Step 3: 实现组件

组件继承 HBox,内部包含只读 TextField 与文字按钮“选择目录”。按钮创建 DirectoryChooser;初始目录仅在当前路径存在且为目录时设置。applySelection(null) 不改变路径。

  • Step 4: 运行 GREEN

Run: mvn -Dtest=DirectoryPathSelectorTest test

Expected: 2 tests,0 failures。

  • Step 5: 提交
git add src/main/java/com/example/workutils/biz/aitest/ui/DirectoryPathSelector.java src/test/java/com/example/workutils/biz/aitest/ui/DirectoryPathSelectorTest.java
git commit -m "feat: add directory selectors for AI test toolchain"

Task 2: 进度状态与模块展示策略

Files:

  • Create: src/main/java/com/example/workutils/biz/aitest/ui/TaskProgressState.java
  • Create: src/main/java/com/example/workutils/biz/aitest/project/ModuleLoadPresentation.java
  • Test: src/test/java/com/example/workutils/biz/aitest/ui/TaskProgressStateTest.java
  • Test: src/test/java/com/example/workutils/biz/aitest/project/ModuleLoadPresentationTest.java

Interfaces:

  • Produces: TaskProgressState.start()、update(double)、finish(),以及 visible()、progress()。

  • Consumes: StartModuleSelector.autoSelect(MavenProjectModel)。

  • Produces: ModuleLoadPresentation.from(MavenProjectModel, String preferredArtifactId),返回 moduleCount()、selectedModule() 与 message()。

  • Step 1: 写失败测试

@Test
void taskProgressIsHiddenUntilStartedAndResetsWhenFinished() {
    TaskProgressState state = new TaskProgressState();
    assertFalse(state.visible());
    state.start();
    assertTrue(state.visible());
    state.update(0.5);
    assertEquals(0.5, state.progress());
    state.finish();
    assertFalse(state.visible());
    assertEquals(0.0, state.progress());
}

@Test
void uniqueStartModuleIsSelectedAndCountIsReported() {
    ModuleLoadPresentation view = ModuleLoadPresentation.from(model("core", "app-start"), "");
    assertEquals(2, view.moduleCount());
    assertEquals("app-start", view.selectedModule().orElseThrow().artifactId());
    assertEquals("已检出 2 个 Maven 模块,已选择 app-start", view.message());
}

@Test
void multipleStartModulesRequireManualSelection() {
    ModuleLoadPresentation view = ModuleLoadPresentation.from(model("a-start", "b-start"), "");
    assertTrue(view.selectedModule().isEmpty());
    assertEquals("已检出 2 个 Maven 模块,请选择生成模块", view.message());
}
  • Step 2: 运行 RED

Run: mvn -Dtest=TaskProgressStateTest,ModuleLoadPresentationTest test

Expected: FAIL,因为两个状态类型尚不存在。

  • Step 3: 实现最小状态类型

TaskProgressState 将进度约束在 0..1;finish() 固定恢复隐藏和 0。ModuleLoadPresentation 优先使用仍存在的用户偏好,否则调用 StartModuleSelector,并生成包含模块数量的中文状态。

  • Step 4: 运行 GREEN

Run: mvn -Dtest=TaskProgressStateTest,ModuleLoadPresentationTest,StartModuleSelectorTest test

Expected: 全部通过。

  • Step 5: 提交
git add src/main/java/com/example/workutils/biz/aitest/ui/TaskProgressState.java src/main/java/com/example/workutils/biz/aitest/project/ModuleLoadPresentation.java src/test/java/com/example/workutils/biz/aitest/ui/TaskProgressStateTest.java src/test/java/com/example/workutils/biz/aitest/project/ModuleLoadPresentationTest.java
git commit -m "feat: model AI test progress and module loading states"

Task 3: 四 Tab 页面与低密度表单

Files:

  • Modify: src/main/java/com/example/workutils/biz/aitest/AiTestPane.java
  • Replace: src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java

Interfaces:

  • Consumes: DirectoryPathSelector、TaskProgressState、ModuleLoadPresentation。

  • Preserves: AiTestRequest(project, module, baseline, targetRef, includeWorkingTree, settings)。

  • Step 1: 写失败的 JavaFX 结构测试

测试通过真实 AiTestPane 的节点树断言:中心是含四个指定 Tab 的 TabPane;不存在 Accordion;JDK/Maven 选择器路径框不可编辑;初始进度条不可见;基线和目标值分别为 master 与 HEAD。依赖使用 Mockito 返回空项目和空历史,测试只断言真实控件行为,不检查源码字符串。

  • Step 2: 运行 RED

Run: mvn -Dtest=AiTestPaneArchitectureTest test

Expected: FAIL,因为中心仍是包含 Accordion 的 VBox,且进度条初始可见。

  • Step 3: 重构 buildContent()

创建四个不可关闭主 Tab:项目页放项目、模块、baseline、targetRef、工作区选项和模块状态;工具链页放两个目录组件、CodeFree、覆盖率、修复轮次和检查按钮;质量规范页放左右 SplitPane;结果页放任务按钮、结果二级 Tab 与审核合并卡片。

  • Step 4: 接入目录组件

删除 jdk8Field、mavenField,settingsFromForm() 改读 jdkSelector.getPath() 与 mavenSelector.getPath();applySettings() 改调 setPath()。

  • Step 5: 接入模块展示

applyProjectData() 使用 ModuleLoadPresentation.from(...),一次性更新模块、选中值和状态文案;继续在成功和失败回调前检查 projectLoadGate.isLatest(projectRequest)。

  • Step 6: 接入进度展示

初始配置加载、项目加载和模块偏好保存使用静默后台任务;runAsync 仅供用户主动任务。setBusy(true) 显示进度,setBusy(false) 隐藏并重置。项目页状态展示项目加载,不触发全局进度。

  • Step 7: 运行 GREEN

Run: mvn -Dtest=AiTestPaneArchitectureTest,LatestRequestGateTest,DirectoryPathSelectorTest,TaskProgressStateTest,ModuleLoadPresentationTest test

Expected: 全部通过。

  • Step 8: 提交
git add src/main/java/com/example/workutils/biz/aitest/AiTestPane.java src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java
git commit -m "feat: reorganize AI test plugin into four tabs"

Task 4: 回归保护与最终验证

Files:

  • Modify only if a regression is exposed: files already listed in Tasks 1-3
  • Verify: src/test/java/com/example/workutils/biz/aitest/project/FtLoanCapitalCoreRegressionTest.java
  • Verify: src/test/java/com/example/workutils/biz/aitest/git/GitIncrementAnalyzerTest.java

Interfaces:

  • Preserves: master...DEV_1156339215001460262 real-repository regression.

  • Preserves: latest project request wins.

  • Step 1: 运行 AI 插件测试

Run: mvn -Dtest='com.example.workutils.biz.aitest.**' test

Expected: 0 failures;真实仓库存在时 FtLoanCapitalCoreRegressionTest 不跳过。

  • Step 2: 运行全量测试

Run: mvn test

Expected: 0 failures,0 errors;仅允许既有无显示环境 GUI 测试跳过。

  • Step 3: 打包

Run: mvn -DskipTests package

Expected: target/workutils-1.0.1-SNAPSHOT.jar 生成成功。

  • Step 4: 差异和工作树检查

Run: git diff --check 与 git status --short

Expected: 无空白错误;用户原有审计文档、截图目录和 SQL 仍保持未跟踪且未暂存。

  • Step 5: 提交验证修正(仅当 Step 1-4 暴露并修复问题时)
git add src/main/java/com/example/workutils/biz/aitest src/test/java/com/example/workutils/biz/aitest
git commit -m "fix: complete AI test plugin UI regression coverage"