feat(ai): 优化拆解重跑与结果展示

This commit is contained in:
Script Generator
2026-06-26 11:01:11 +08:00
parent 55e24442ab
commit 56e0fe562d
36 changed files with 1342 additions and 186 deletions

View File

@@ -29,6 +29,11 @@
- ❓ 注释含糊无法转化
- 对账报告先呈现给用户,用户审核后才执行写入
4. **AI 预估不等于执行人预估**
- AI 只能输出 `aiEstimateHours`
- `estimateHours` 留给负责人/执行人确认后填写
- AI 不输出预计开始/截止时间,排期由负责人后续维护
4. **历史版本不强制存储**
- 系统不要求历史原型 URL 作为基准
- 拆偏问题靠"对账报告"暴露给用户,由人工补救
@@ -45,7 +50,7 @@
- 当前版本关联需求列表(已被加进 Version 的 Requirement[]
- 版本成员清单(带角色:前端/后端/UI/测试)
**调用入口**:版本详情页 → 产品方案 Tab → 计划状态 = completed 后按钮「AI 拆解任务和用例」
**调用入口**:版本详情页 → 产品方案 Tab → 计划状态 = completed 后按钮「AI 拆解开发任务」或「AI 拆解测试用例」
**触发条件**
- 当前版本至少有 1 条 type=product 的 VersionPlan 处于 `completed` 且 resultUrl 非空(提交了原型)
@@ -53,12 +58,16 @@
**输出**
- 对账报告(结构化文本,含"完美对应/单边/含糊"三段)
- DevTask 草案数组(每条带 `aiDraft: true` + `references[]`
- TestCase 草案数组(每条带 `aiDraft: true` + `references[]`
- DevTask 草案数组(每条带 `aiDraft: true` + `references[]` + `aiEstimateHours`
- TestCase 草案数组(每条带 `aiDraft: true` + `references[]` + `aiEstimateHours`
- `target = dev_tasks``testCaseDrafts` 必须为空数组;`target = test_cases``devTaskDrafts` 必须为空数组
**写入**
- 用户确认后,调用 `useDevTaskStore.createTask``useTestCaseStore.createTestCase`
- 打开采纳弹窗前,前端先过滤当前版本已采纳过的重复 DevTask/TestCase 草案
- 写入字段中 `aiDraft: true``aiDraftAt: ISO时间戳`
- 写入 `aiEstimateHours`,不写入执行人预估 `estimateHours`
- DevTask 草案不写预计开始/截止时间,负责人后续排期时再填写
**权限**
-Version, Requirement, VersionPlan, Member
@@ -172,6 +181,7 @@ interface Reference {
aiDraft?: boolean;
aiDraftAt?: string; // ISO 时间戳
references?: Reference[];
aiEstimateHours?: number; // AI 预估耗时,单位小时
```
### Agent 输入预期
@@ -182,6 +192,7 @@ interface DecomposeInput {
prototypeUrl: string; // 从产品方案 completed 计划的 resultUrl 派生
requirements: Requirement[]; // 当前版本所属项目下已采纳、可用于本次拆解的需求
members: VersionMember[]; // 该版本参与人员(带角色)
target?: 'all' | 'dev_tasks' | 'test_cases';
}
```
@@ -197,12 +208,12 @@ interface DecomposeOutput {
noteOnly: string[]; // 原型注释 ID 列表
ambiguous: Array<{ noteId: string; reason: string }>;
};
devTaskDrafts: Array<Omit<DevTask, 'id' | 'taskNo' | 'createdAt' | 'updatedAt' | 'isBlocked' | 'categoryId'> & { categoryCode: string; aiDraft: true; aiDraftAt: string; references: Reference[] }>;
testCaseDrafts: Array<Omit<TestCase, 'id' | 'caseNo' | 'createdAt' | 'updatedAt' | 'status' | 'categoryId'> & { categoryCode: string; aiDraft: true; aiDraftAt: string; references: Reference[] }>;
devTaskDrafts: Array<{ title: string; description?: string; categoryCode: string; priority: Priority; aiEstimateHours: number; references: Reference[] }>;
testCaseDrafts: Array<{ title: string; description: string; categoryCode: string; priority: Priority; aiEstimateHours: number; references: Reference[] }>;
}
```
要求AI 不输出数据库 `categoryId`,只输出稳定 `categoryCode`。前端确认写入时按 `TaskCategory.code` 映射成 `categoryId`;映射失败时使用对应分组的默认类型兜底。
要求AI 不输出数据库 `categoryId`,只输出稳定 `categoryCode`。前端确认写入时按 `TaskCategory.code` 映射成 `categoryId`;映射失败时使用对应分组的默认类型兜底。AI 不输出 `estimateHours`、预计开始或预计截止。
## 视觉规范

View File

@@ -150,9 +150,11 @@ V2 接入后端后改为基于 `ProjectMember` 表的 RBACOwner/Admin/Member/
| DevTask | references | Reference[]? | 引用来源(需求/原型批注) |
| DevTask | aiDraft | boolean? | AI 草案标记 |
| DevTask | aiDraftAt | string? | AI 生成时间戳 |
| DevTask | aiEstimateHours | number? | AI 预估耗时;执行人预估仍写 estimateHours |
| TestCase | references | Reference[]? | 同上 |
| TestCase | aiDraft | boolean? | 同上 |
| TestCase | aiDraftAt | string? | 同上 |
| TestCase | aiEstimateHours | number? | AI 预估耗时;执行人预估仍写 estimateHours |
## 版本模块规则层V2.2 设计约束)

View File

@@ -12,7 +12,7 @@
- `testing` → 80%
- `submitted` → 100%
**理由**:客观、不允许造假。需求级/版本级进度 = `Σ(estimateHours × 状态推导%) / Σ(estimateHours)`
**理由**:客观、不允许造假。需求级/版本级进度 = `Σ(估算耗时 × 状态推导%) / Σ(估算耗时)`。估算耗时优先取执行人填写的 `estimateHours`,没有时才用 AI 草案的 `aiEstimateHours` 兜底
## 2. 实际工时 — 由开始/完成时间戳计算
@@ -269,3 +269,34 @@
- 需求候选来源属于领域边界;统一 selector 能避免从需求池、项目需求、版本需求之间误取数据。
- AI 不应该猜数据库 id稳定语义码能兼容管理员调整展示名称也方便后续扩展更多模型。
- 测试用例带任务类型后才能知道测试覆盖范围AI 拆解和人工创建的数据形状也一致。
## 24. AI 预估和执行人预估分离
**问题**AI 拆解写入 `estimateHours` 会让系统误以为负责人已经确认了工时和排期;同时 AI 会根据原型自动反推预计开始/截止,造成“计划已填”的错觉。
**决策**
- AI 输出字段统一改为 `aiEstimateHours`,不再输出/写入 `estimateHours`
- `estimateHours` 只表示执行人或负责人确认后的执行预估。
- 进度和统计口径优先使用 `estimateHours`;缺失时使用 `aiEstimateHours` 兜底;两者都没有时才从计划时间推导或按无估时处理。
- AI 采纳开发任务时不写预计开始/截止时间,由负责人后续填写计划排期。
- AI 重新拆解入口拆成“重新拆解开发任务”和“重新拆解测试用例”,请求通过 `target` 控制本次只生成哪类草案。
- AI 估时允许小于 0.5h,汇总时保留小数精度;实际耗时仍按状态时间戳计算并保持 0.5h 口径。
**理由**
- AI 给的是建议,不是负责人承诺。
- 排期属于执行人计划,不能由拆解 Agent 代填。
- 独立重拆能避免修改开发任务时顺手覆盖测试用例,降低误采纳风险。
## 25. AI 重新拆解先过滤已采纳重复草案
**问题**:第一次 AI 拆解的 DevTask/TestCase 已经被采纳后,用户再次重新拆解时,模型可能再次输出同一批草案。若直接展示给用户采纳,会造成开发任务和测试用例重复。
**决策**
- AI 返回结果后,前端在打开采纳弹窗前先做确定性去重。
- 开发任务比对范围是当前版本已关联需求下的现有 DevTask测试用例比对范围是当前版本下的现有 TestCase。
- 重复判定使用:任务类型 code + 标题规范化 + 引用来源(需求 / 原型批注)一致。
- 重复草案不进入采纳列表,只在弹窗提示已过滤数量。
**理由**
- 去重不能只依赖模型提示,必须有系统规则兜底。
- 标题也参与签名,避免同一需求/QY 下不同真实工作项被误过滤。

View File

@@ -135,21 +135,22 @@ Workspace 页面(树筛选 + tab 筛选 + 已完成开关)
4. 从当前项目已采纳需求中关联需求到本版本
5. 点击「AI 拆解任务和用例」按钮(位于产品方案 Tab
5. 点击「AI 拆解开发任务」或「AI 拆解测试用例」按钮(位于产品方案 Tab
6. Agent 从 product 类型的 completed 计划取 resultUrl 作为原型,
抓取原型 + 关联需求 + 版本成员,输出对账报告 + 任务/用例草案
7. 用户审核对账报告
├─ 系统先自动过滤已采纳过的重复 DevTask/TestCase 草案
├─ 报告全 ✅:直接确认写入
├─ 报告有 ⚠️/❓:选择性放弃部分草案 / 补充信息后重跑
└─ 报告全 ❓:放弃 AI 拆解,人工创建
8. 确认后DevTask / TestCase 草案写入对应 Tab标记 aiDraft: true
8. 确认后DevTask / TestCase 草案写入对应 Tab标记 aiDraft: true,并写入 aiEstimateHours
9. 团队成员在 DevTask Tab 看到紫色边的 AI 草案任务
10. 任意成员编辑任务(改标题/描述/负责人/优先级/时间/分类),保存后 aiDraft 自动清除
10. 任意成员编辑任务(改标题/描述/负责人/优先级/时间/分类/执行预估),保存后 aiDraft 自动清除
changeStatus / setBlocked 等用户主动操作也会清除)
```
@@ -179,6 +180,11 @@ Workspace 页面(树筛选 + tab 筛选 + 已完成开关)
- 多个组件共用的候选筛选规则进 selector/helper。
- AI 输入输出字段先更新 `agent-spec.md` 和 shared type再改 prompt/schema。
AI 估时约束:
- `aiEstimateHours` 是 AI 建议工时,只能由 AI 拆解写入。
- `estimateHours` 是执行人预估,只能由人工创建/编辑或负责人确认排期时写入。
- 统计进度优先取 `estimateHours`,没有时取 `aiEstimateHours`,避免 AI 草案在未确认前失去统计权重。
版本模块新增规则:
- `version-plan-workflow.ts` 是调研/产品方案/UI 设计完成条件的唯一入口。