diff --git a/docs/superpowers/plans/2026-08-05-ai-test-one-click-workflow.md b/docs/superpowers/plans/2026-08-05-ai-test-one-click-workflow.md new file mode 100644 index 0000000..4418a59 --- /dev/null +++ b/docs/superpowers/plans/2026-08-05-ai-test-one-click-workflow.md @@ -0,0 +1,233 @@ +# AI Test One-Click Workflow Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 在“项目与增量”Tab 内一键完成增量分析、单测生成、Maven/JaCoCo 验证与覆盖率展示,并在首次使用时自动发现和保存 JDK 8、Maven 与 CodeFree 配置。 + +**Architecture:** 新增独立的工具链发现器,只负责从保存值、环境、运行时和 Maven 输出解析路径;`AiTestPane` 通过单个后台任务串联现有 `analyze` 与 `generateAndVerify`,领域工作流保持不变。界面通过稳定的控件 ID 和状态转换测试验证第一 Tab 操作与结果自动定位。 + +**Tech Stack:** Java 17 编译、目标业务 JDK 8、JavaFX 17、Maven 3.8.6、JUnit 5、Mockito、CodeFree CLI 0.3.6、JaCoCo。 + +## Global Constraints + +- 不使用子代理,当前会话单线程实施。 +- 用户保存配置优先,自动探测仅补齐空值或不存在的首次配置。 +- Windows 兜底路径只有真实存在时才使用;macOS/Linux 不写入 Windows 路径。 +- 不修改 CodeFree CLI 协议、质量规范格式、合并审核规则和手机 UI 自动化插件。 +- 保留 `master...DEV_1156339215001460262` 与最新异步请求防覆盖逻辑。 +- 不暂存或修改现有未跟踪审计文件、截图目录和 SQL 文件。 + +--- + +### Task 1: 默认工具链自动发现 + +**Files:** +- Create: `src/main/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetector.java` +- Modify: `src/main/java/com/example/workutils/biz/aitest/config/AiTestSettingsService.java` +- Test: `src/test/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetectorTest.java` +- Test: `src/test/java/com/example/workutils/biz/aitest/config/AiTestSettingsServiceTest.java` + +**Interfaces:** +- Produces: `AiTestSettings ToolchainSettingsDetector.complete(AiTestSettings saved)`。 +- Consumes: 环境变量读取函数、系统属性读取函数、文件存在性函数,以及返回 `mvn -version` 输出的函数,均通过构造参数注入以便测试。 +- `AiTestSettingsService.load()` 在文件不存在时调用发现器;配置文件存在时只补齐空路径,不覆盖有效保存值。 + +- [ ] **Step 1: 写失败测试** + +```java +@Test +void discoversJdkRootFromJavaHomeJreAndParsesMavenHome() { + ToolchainSettingsDetector detector = fixture( + Map.of(), Map.of("java.home", "C:/Program Files/Java/jdk-1.8/jre"), + "Apache Maven 3.8.6\nMaven home: D:/bestpay-maven/apache-maven-3.8.6"); + AiTestSettings result = detector.complete(AiTestSettings.defaults()); + assertEquals(Path.of("C:/Program Files/Java/jdk-1.8"), result.jdk8Home()); + assertEquals(Path.of("D:/bestpay-maven/apache-maven-3.8.6"), result.mavenHome()); +} +``` + +同时覆盖:保存值优先、`JAVA_HOME`、`MAVEN_HOME`、`M2_HOME`、非 Windows 不使用 Windows 兜底、探测值被 `AiTestSettingsService` 保存。 + +- [ ] **Step 2: 运行测试并确认 RED** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=ToolchainSettingsDetectorTest,AiTestSettingsServiceTest test` + +Expected: FAIL,因为 `ToolchainSettingsDetector` 尚不存在且服务不会自动保存探测结果。 + +- [ ] **Step 3: 实现最小发现器** + +```java +public AiTestSettings complete(AiTestSettings saved) { + Path jdk = usable(saved.jdk8Home()) ? saved.jdk8Home() : detectJdk8(); + Path maven = usable(saved.mavenHome()) ? saved.mavenHome() : detectMaven(); + return new AiTestSettings(jdk, maven, saved.codeFreeCommand(), saved.coverageTarget(), + saved.maxRepairRounds(), saved.codeFreeTimeout(), saved.mavenTimeout()); +} +``` + +JDK 发现顺序为 `JAVA_HOME`、`java.home`、存在的 Windows 兜底;Maven 顺序为 `MAVEN_HOME`、`M2_HOME`、`mvn -version` 的 `Maven home:`、存在的 Windows 兜底。 + +- [ ] **Step 4: 运行聚焦测试并确认 GREEN** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=ToolchainSettingsDetectorTest,AiTestSettingsServiceTest test` + +Expected: 所有配置探测测试通过。 + +- [ ] **Step 5: 提交** + +```powershell +git add src/main/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetector.java src/main/java/com/example/workutils/biz/aitest/config/AiTestSettingsService.java src/test/java/com/example/workutils/biz/aitest/config/ToolchainSettingsDetectorTest.java src/test/java/com/example/workutils/biz/aitest/config/AiTestSettingsServiceTest.java +git commit -m "feat: discover default AI test toolchain" +``` + +### Task 2: 一键协调执行链 + +**Files:** +- Create: `src/main/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunner.java` +- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPlugin.java` +- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPane.java` +- Test: `src/test/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunnerTest.java` + +**Interfaces:** +- Produces: `AiTestRun AiTestOneClickRunner.run(AiTestRequest request, Consumer progress)`。 +- Consumes: `AiTestWorkflow.analyze` 与 `AiTestWorkflow.generateAndVerify`。 +- 当分析结果不是 `ANALYZED` 时原样返回且不调用生成;分析成功时继续生成验证。 + +- [ ] **Step 1: 写失败测试** + +```java +@Test +void generatesAndVerifiesAfterSuccessfulAnalysis() { + when(workflow.analyze(request, progress)).thenReturn(analyzed); + when(workflow.generateAndVerify(analyzed, progress)).thenReturn(ready); + assertSame(ready, runner.run(request, progress)); + verify(workflow).generateAndVerify(analyzed, progress); +} + +@Test +void stopsWhenAnalysisFails() { + when(workflow.analyze(request, progress)).thenReturn(failed); + assertSame(failed, runner.run(request, progress)); + verify(workflow, never()).generateAndVerify(any(), any()); +} +``` + +- [ ] **Step 2: 运行测试并确认 RED** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestOneClickRunnerTest test` + +Expected: FAIL,因为协调器尚不存在。 + +- [ ] **Step 3: 实现最小协调器并注入界面** + +```java +public AiTestRun run(AiTestRequest request, Consumer progress) { + AiTestRun analyzed = workflow.analyze(request, progress); + return analyzed.state() == AiTestRunState.ANALYZED + ? workflow.generateAndVerify(analyzed, progress) + : analyzed; +} +``` + +`AiTestPane` 一键操作必须只调用一次 `runAsync`,确保 busy/progress 在完整链路结束后才复位。 + +- [ ] **Step 4: 运行测试并确认 GREEN** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestOneClickRunnerTest,AiTestWorkflowTest test` + +Expected: 协调器与既有工作流测试通过。 + +- [ ] **Step 5: 提交** + +```powershell +git add src/main/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunner.java src/main/java/com/example/workutils/biz/aitest/AiTestPlugin.java src/main/java/com/example/workutils/biz/aitest/AiTestPane.java src/test/java/com/example/workutils/biz/aitest/application/AiTestOneClickRunnerTest.java +git commit -m "feat: run AI test generation and coverage in one action" +``` + +### Task 3: 第一 Tab 操作与结果自动定位 + +**Files:** +- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPane.java` +- Modify: `src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java` + +**Interfaces:** +- 主按钮 ID:`generate-and-cover-action`,文本“生成单测并分析覆盖率”。 +- 次按钮 ID:`analyze-only-action`,文本“仅分析增量”。 +- 主 TabPane ID:`ai-test-main-tabs`;结果 TabPane ID:`ai-test-result-tabs`。 +- 成功选择主 Tab“结果与合并”和内层 Tab“覆盖率”;失败选择内层 Tab“运行日志”。 + +- [ ] **Step 1: 写失败的 JavaFX 结构/状态测试** + +```java +assertEquals("项目与增量", mainTabs.getSelectionModel().getSelectedItem().getText()); +assertNotNull(pane.lookup("#generate-and-cover-action")); +assertNotNull(pane.lookup("#analyze-only-action")); +assertFalse(toolchainTab.isSelected()); +``` + +增加可直接调用的包内结果呈现测试入口或提取无状态 `AiTestResultSelection`,分别断言 `READY_FOR_REVIEW` 选覆盖率、`FAILED` 选运行日志。 + +- [ ] **Step 2: 运行测试并确认 RED** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestPaneArchitectureTest,AiTestResultSelectionTest test` + +Expected: FAIL,因为主操作仍位于结果 Tab 且没有结果选择策略。 + +- [ ] **Step 3: 实现第一 Tab 操作区与选择策略** + +```java +HBox projectActions = new HBox(10, generateAndCoverButton, analyzeOnlyButton); +VBox projectPage = page(selection, projectActions); +``` + +删除结果 Tab 中重复的“分析增量/生成并验证”操作,只保留执行中的“取消”。工具链异常时保持当前结果并提示进入“工具链”;正常成功或失败按状态切换结果子 Tab。 + +- [ ] **Step 4: 运行 UI 与插件聚焦测试并确认 GREEN** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest=AiTestPaneArchitectureTest,AiTestResultSelectionTest,AiTestPluginTest test` + +Expected: 第一 Tab 操作、默认选择及结果定位测试全部通过。 + +- [ ] **Step 5: 提交** + +```powershell +git add src/main/java/com/example/workutils/biz/aitest/AiTestPane.java src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java src/main/java/com/example/workutils/biz/aitest/ui/AiTestResultSelection.java src/test/java/com/example/workutils/biz/aitest/ui/AiTestResultSelectionTest.java +git commit -m "feat: expose one-click AI test workflow on project tab" +``` + +### Task 4: 真实项目回归与发布验证 + +**Files:** +- Modify only if a regression exposes a defect in files from Tasks 1-3. +- Verify: `src/test/java/com/example/workutils/biz/aitest/project/FtLoanCapitalCoreRegressionTest.java` + +**Interfaces:** +- `master...DEV_1156339215001460262` 必须继续定位 `ft-loancapital-core-start` 并分析显式目标引用。 +- 打包产物:`target/workutils-1.0.1-SNAPSHOT.jar`。 + +- [ ] **Step 1: 运行真实项目和 AI 插件测试** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -Dtest='com.example.workutils.biz.aitest.**,FtLoanCapitalCoreRegressionTest' test` + +Expected: AI 插件测试与真实项目回归全部通过。 + +- [ ] **Step 2: 运行全量测试** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn test` + +Expected: 0 failures、0 errors;仅允许既有 GUI 环境跳过项。 + +- [ ] **Step 3: 打包与差异检查** + +Run: `$env:JAVA_HOME='C:\Program Files\Java\jdk-17'; mvn -DskipTests package; git diff --check; git status --short` + +Expected: BUILD SUCCESS、`git diff --check` 无输出,用户未跟踪文件保持未暂存。 + +- [ ] **Step 4: 提交验证阶段必要修复(如有)** + +```powershell +git add -- +git commit -m "fix: complete AI test one-click regression" +``` + +若没有必要修复则不创建空提交。