feat: analyze AI tests against explicit target ref

This commit is contained in:
张家训
2026-08-04 18:10:12 +08:00
parent 9676c81455
commit 5f9bd609c3
15 changed files with 301 additions and 37 deletions
@@ -0,0 +1,84 @@
# AI 单测目标引用与异步竞态修复实施计划
> **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 单测插件稳定按 `master...DEV_1156339215001460262` 分析真实 `ft-loancapital-core` 增量,并阻止较早的项目加载结果覆盖用户后来选择的项目。
**Architecture:** 将 Git 比较终点从隐式 `HEAD` 提升为 `AiTestRequest.targetRef`,增量分析和临时 worktree 均解析同一目标引用;工作区改动仅允许叠加在目标引用等于当前 `HEAD` 的场景。项目元数据加载使用单调递增的请求令牌,只有最新令牌可以更新 JavaFX 控件。
**Tech Stack:** Java 17(WorkUtils 运行时)、JavaFX、Spring、Maven、JUnit 5、Mockito、Git CLI
## Global Constraints
- 真实业务项目使用 `D:/bestpay-srdcloud/ft-loancapital-core`;该目录不存在时集成回归测试使用 JUnit assumption 跳过。
- 默认基线为 `master`;目标引用可填写分支或 Commit,并对当前真实场景使用 `DEV_1156339215001460262`。
- 不修改真实业务仓库、不切换其分支、不提交其文件。
- 不触碰 WorkUtils 中现有未跟踪的审计文档、截图和 SQL 文件。
- 全程单线程实施,不使用子代理。
---
### Task 1: 显式 baseline 与 targetRef 的增量分析
**Files:**
- Modify: `src/main/java/com/example/workutils/biz/aitest/git/GitIncrementAnalyzer.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/application/AiTestRequest.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/application/AiTestWorkflow.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/git/TemporaryWorktreeManager.java`
- Test: `src/test/java/com/example/workutils/biz/aitest/git/GitIncrementAnalyzerTest.java`
- Test: `src/test/java/com/example/workutils/biz/aitest/git/TemporaryWorktreeManagerTest.java`
- Test: `src/test/java/com/example/workutils/biz/aitest/application/AiTestWorkflowTest.java`
**Interfaces:**
- Produces: `GitIncrementAnalyzer.analyze(Path, String baseline, String targetRef, boolean includeWorkingTree)`
- Produces: `TemporaryWorktreeManager.create(Path, String targetRef, boolean includeWorkingTree)`
- Produces: `AiTestRequest.targetRef()`
- [ ] **Step 1: 写失败测试**:构造 `master` 与未检出的 `DEV_*` 分支,断言分析结果来自 DEV 而不是当前 HEAD;断言临时 worktree 检出目标引用。
- [ ] **Step 2: 运行聚焦测试确认 RED**:`mvn -Dtest=GitIncrementAnalyzerTest,TemporaryWorktreeManagerTest,AiTestWorkflowTest test`,预期因新签名或仍使用 HEAD 而失败。
- [ ] **Step 3: 最小实现**:解析 baseline/target commit,以其 merge-base 到 target commit 生成 patch;workflow 将 request 的 targetRef 贯穿到分析和 worktree。
- [ ] **Step 4: 运行聚焦测试确认 GREEN**:同一 Maven 命令全部通过。
### Task 2: 真实 ft-loancapital-core 回归
**Files:**
- Create: `src/test/java/com/example/workutils/biz/aitest/project/FtLoanCapitalCoreRegressionTest.java`
**Interfaces:**
- Consumes: `MavenProjectAnalyzer.analyze(Path)`
- Consumes: `GitIncrementAnalyzer.analyze(Path, "master", "DEV_1156339215001460262", false)`
- [ ] **Step 1: 写真实只读回归测试**:断言解析到 `ft-loancapital-core-start`,并断言 master 到 DEV 的增量包含已知 service Java 文件及新增行。
- [ ] **Step 2: 运行测试确认结果**:`mvn -Dtest=FtLoanCapitalCoreRegressionTest test`;真实仓库存在时必须通过,不存在时仅跳过。
### Task 3: 项目加载的最新请求获胜
**Files:**
- Create: `src/main/java/com/example/workutils/biz/aitest/LatestRequestGate.java`
- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPane.java`
- Create: `src/test/java/com/example/workutils/biz/aitest/LatestRequestGateTest.java`
- Modify: `src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java`
**Interfaces:**
- Produces: `LatestRequestGate.next()` 返回请求令牌。
- Produces: `LatestRequestGate.isLatest(long)` 仅对最后发出的令牌返回 true。
- [ ] **Step 1: 写失败测试**:先申请旧令牌再申请新令牌,断言旧令牌失效、新令牌有效;架构测试断言项目加载成功与失败回调都经过 gate。
- [ ] **Step 2: 运行聚焦测试确认 RED**:`mvn -Dtest=LatestRequestGateTest,AiTestPaneArchitectureTest test`,预期类不存在或 Pane 未使用 gate。
- [ ] **Step 3: 最小实现**:`loadProject` 发出令牌,清空旧模块;后台成功或失败回到 FX 线程时仅允许最新请求更新 UI。
- [ ] **Step 4: 运行聚焦测试确认 GREEN**:同一 Maven 命令全部通过。
### Task 4: UI 参数与完整验证
**Files:**
- Modify: `src/main/java/com/example/workutils/biz/aitest/AiTestPane.java`
- Modify: `src/test/java/com/example/workutils/biz/aitest/AiTestPaneArchitectureTest.java`
**Interfaces:**
- UI 提供 `baselineField`(默认 `master`)与 `targetRefField`(默认 `HEAD`,加载项目后显示当前分支)。
- [ ] **Step 1: 写失败测试**:断言 Pane 存在独立 targetRef 字段,且 baseline 默认 master。
- [ ] **Step 2: 最小实现**:把 targetRef 写入 `AiTestRequest`,校验 baseline、targetRef、项目和模块均已选择。
- [ ] **Step 3: 运行 AI 单测插件测试**:`mvn -Dtest='com.example.workutils.biz.aitest.**' test`。
- [ ] **Step 4: 运行全量验证**:`mvn test`、`mvn -DskipTests package`、`git diff --check`。
- [ ] **Step 5: 检查 `git status` 仅包含本次文件和用户原有未跟踪文件,然后提交到 WorkUtils `master`。**