# 版本模块规则引擎与任务类型设计

## 背景

版本详情里的调研、产品方案、UI 设计、开发任务、测试用例已经形成一条执行链路，但有几处规则还散在 UI 组件里：

- 开发任务的任务类型太粗，测试用例还没有任务类型。
- AI 拆解只输出 `role`，不能稳定落到当前系统的任务类型字典。
- 计划任务可以通过右上角勾选直接完成，绕过子任务和成果提交。
- 关联需求的候选来源不够明确，容易误用全量需求池。
- 调研、产品方案、UI 设计的关联需求选择缺少全选能力。

这次设计的目标是把这些规则收敛到字典、选择器和工作流引擎里，而不是继续在页面组件里散写条件。

## 目标

1. 任务类型能支撑更细的开发与测试范围。
2. DevTask 和 TestCase 共用同一套任务类型字典。
3. AI 拆解必须输出任务类型，并能稳定映射到系统字典。
4. VersionPlan 的完成条件由统一规则函数判断。
5. 所有关联需求入口只从当前版本所属项目下的已采纳需求中选择，不从全量需求池选择。
6. 调研、产品方案、UI 设计的关联需求选择支持全选。
7. 项目文档明确约束：跨模块联动、状态流转、完成条件、AI 契约必须优先考虑引擎、状态机或统一规则函数。

## 非目标

- 不做本地数据导入导出。
- 不在这一步把 `app_data` 全量拆成关系表。
- 不让 AI 自动分配负责人。
- 不让 AI 直接写入正式 DevTask/TestCase；仍然只写入草案。

## 方案概览

新增或调整三个规则层：

1. `task-category.ts`：任务类型字典扩展为开发、测试、实施、其他，并增加稳定语义码。
2. `requirement-selector.ts`：统一筛选当前项目下可用于关联的需求。
3. `version-plan-workflow.ts`：统一计算计划进度、是否能提交成果、是否能完成、缺少什么条件。

页面组件只负责展示和触发动作，不直接决定业务规则。

## 任务类型字典

`TaskCategory` 继续作为开发任务和测试用例的共享字典，但增加一个稳定字段：

```ts
interface TaskCategory {
  id: string;          // 存储主键，仍用于 DevTask.categoryId / TestCase.categoryId
  code: string;        // 稳定语义码，给 AI 和映射逻辑使用
  name: string;        // 展示名称，可被管理员调整
  group: 'development' | 'testing' | 'implementation' | 'other';
  color?: string;
  sortOrder: number;
  isSystem: boolean;
}
```

推荐预置分类示例：

- 开发：前端页面、前端交互、后端接口、后端业务逻辑、数据库/数据结构、权限/流程、第三方集成、接口联调
- 测试：功能测试、接口测试、异常场景、兼容性测试、回归测试、数据校验
- 实施：数据处理、实施支持、配置部署
- 其他：文档、协调、待确认

`id` 用于系统存储，`code` 用于 AI 输出和迁移兼容。管理员可以改名称，但不建议随意修改系统预置 `code`。

## 测试用例任务类型

`TestCase` 增加 `categoryId`：

```ts
interface TestCase {
  categoryId: string;
}
```

影响范围：

- `TestCaseCreateModal` 增加任务类型必填项。
- `TestCaseRow` 和 `TestCaseDetailDrawer` 展示类型标签。
- `useTestCaseStore.fetchTestCases` 对旧数据做兼容补齐，默认映射到测试分组的第一个系统类型。
- AI 草案写入 TestCase 时也要映射 `categoryCode -> categoryId`。

## 关联需求选择规则

所有关联需求入口统一使用同一套候选规则：

```ts
requirements.filter((r) =>
  r.projectId === version.projectId &&
  r.status === 'adopted'
)
```

含义：

- 候选来自当前版本所属项目下的需求，不从产品级全量需求池直接取。
- 只有已采纳需求可被新选择。
- 如果历史计划已经关联了某条需求，但该需求后来不再满足候选条件，编辑时保留旧关联并标记为“历史关联”，避免悄悄丢数据。
- 版本需求 Tab、调研计划、产品方案、UI 设计、开发任务和测试用例中的需求选择都复用该规则函数。

调研、产品方案、UI 设计的关联需求控件增加：

- 全选当前候选。
- 清空选择。
- 已选数量 / 候选数量提示。
- 候选为空时说明需要先在项目下采纳需求。

## VersionPlan 工作流引擎

新增 `apps/web/lib/version-plan-workflow.ts`，作为计划完成规则的唯一入口。

建议导出：

```ts
interface PlanCompletionState {
  checklistTotal: number;
  checklistCompleted: number;
  requirementTotal: number;
  requirementCompleted: number;
  hasResult: boolean;
  canSubmitResult: boolean;
  canComplete: boolean;
  missingReasons: string[];
}

function getPlanCompletionState(plan: VersionPlan): PlanCompletionState;
function canTogglePlanChecklist(plan: VersionPlan, now?: Date): boolean;
function canEditPlanRequirementCoverage(plan: VersionPlan, now?: Date): boolean;
```

完成规则：

- 调研、产品方案、UI 设计都使用 `tasks` 作为子任务清单。
- 子任务必须全部勾选完成。
- 完成时必须提交成果，成果可以是链接或文件。
- 产品方案和 UI 设计如果有关联需求覆盖清单，也必须全部勾选覆盖完成。
- 右上角“直接完成”的勾选按钮取消。
- `PlanTab` 和 `PlanDetailDrawer` 都只调用工作流引擎，不再各自写完成条件。

状态写入仍保持：

- `pending -> in_progress -> completed`
- `actualStartAt` 在开始时写入。
- `completedAt` 只能通过提交成果完成时写入。

## AI 拆解契约

AI 输出不直接返回数据库 `categoryId`，而是返回稳定语义码：

```ts
interface AgentDevTaskDraft {
  title: string;
  description?: string;
  categoryCode: string;
  priority: 'P0' | 'P1' | 'P2' | 'P3';
  estimateHours: number;
  references: AgentReference[];
}

interface AgentTestCaseDraft {
  title: string;
  description: string;
  categoryCode: string;
  priority: 'P0' | 'P1' | 'P2' | 'P3';
  references: AgentReference[];
}
```

映射规则：

1. 优先按 `TaskCategory.code` 匹配。
2. 匹配不到时按名称做宽松匹配。
3. 仍匹配不到时，开发任务落到开发分组默认类型，测试用例落到测试分组默认类型。
4. 映射失败不阻断 AI 报告展示，但确认写入前必须能得到 `categoryId`。

`prompts/decompose.ts` 的 tool schema 要求 devTaskDrafts 和 testCaseDrafts 都必须带 `categoryCode`。

## UI 行为

- 计划卡片右上角不再显示直接完成的勾选按钮。
- 完成入口改为“提交成果”，按钮在条件不足时禁用并展示缺失原因。
- 完成弹窗保留链接/文件两种结果类型。
- 调研、产品方案、UI 设计新建/编辑时都展示关联需求选择，并支持全选。
- 测试用例新建弹窗增加任务类型选择。
- AI 草案确认弹窗展示每条任务/用例的任务类型。

## 兼容与迁移

当前业务数据仍存于 PostgreSQL `app_data` JSONB。

- 新增字段时在 store fetch 阶段做轻量兼容补齐。
- 旧 TestCase 没有 `categoryId` 时补齐默认测试类型。
- 旧 TaskCategory 没有 `code` 时按系统预置映射补齐；自定义类型生成稳定 code。
- 不恢复业务 localStorage 缓存。

## 验证计划

实现时至少覆盖：

- `version-plan-workflow` 单元测试：
  - 子任务未完成不能完成。
  - 未提交成果不能完成。
  - 子任务完成 + 成果存在才可完成。
  - 产品方案/UI 设计有关联需求覆盖时，未覆盖完不能完成。
- 任务类型映射测试：
  - `categoryCode` 能映射系统类型。
  - 未知 `categoryCode` 有合理 fallback。
  - TestCase 旧数据能补齐类型。
- AI schema 测试：
  - devTaskDrafts 和 testCaseDrafts 都要求 `categoryCode`。
- 手工 UI 验证：
  - 调研/产品/UI 关联需求全选可用。
  - 候选需求只来自当前项目已采纳需求。
  - 顶部直接完成按钮消失。
  - 测试用例创建必须选择任务类型。

## 后续实现顺序

1. 写规则引擎和选择器测试。
2. 实现任务类型字典扩展和旧数据兼容。
3. 给 TestCase 增加 `categoryId`。
4. 接入 VersionPlan 工作流引擎。
5. 接入需求选择器和全选 UI。
6. 升级 AI schema、共享类型和草案写入映射。
7. 跑类型检查和核心测试。
