feat: 支持依赖(deps)创建后编辑 (tsk_UQ7sNRM0Yi1L)

deps 此前仅建任务时可设,本次让 PATCH /api/tasks/:id 受理 deps,
拆解后可随时调整任务依赖,无需删重建。

- API:PATCH /api/tasks/:id 受理 deps:string[](类型校验)
- Store.patchTask:写 deps 前复用建任务校验(存在/同项目/非自身)
  并加 DFS 环检测(拒绝 A→B→A);越权/缺失/成环 → StoreError(400)
- 仅允许在未进入执行链路的状态改 deps(与 complexity 同一组守卫)
- 写后调 reconcileDeps 重算:未满足 ready→blocked、刚补全 blocked→ready,
  广播 status.changed
- 看板:任务详情加依赖编辑器(多选当前项目其它任务,排除自身与会成环者),
  保存走 PATCH
- 测试:加/删 dep、已 done 依赖放行、环检测、跨项目/缺失拒绝、
  执行链路状态拒绝、status.changed 重算(test/patch.test.ts)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-13 10:33:39 +08:00
parent 872354cf7c
commit 72b174fd44
5 changed files with 262 additions and 15 deletions
+6
View File
@@ -183,6 +183,12 @@ export function buildServer(opts: ApiOptions): FastifyInstance {
if (!isComplexity(b.complexity)) throw new StoreError('complexity 必须是 hard|medium|easy');
patch.complexity = b.complexity;
}
if (b.deps !== undefined) {
if (!Array.isArray(b.deps) || !b.deps.every((d) => typeof d === 'string')) {
throw new StoreError('deps 必须是任务 id 字符串数组');
}
patch.deps = b.deps as string[];
}
return store.patchTask(id, patch);
});