# 任务接续 / 血缘 DAG(PLAN-FOLLOWUP) > **状态(2026-09-22)**:已实现——协议 `basedOn`/`parentIds`/`depth`、宿主接续 > 建卡(守卫/pins 继承/逐父交接摘要/自动拆解注入)、客户端全量(接续表单、 > done 卡按钮、review 确认并接续、合同横幅、流程上一棒节点、链徽标、看板连线 > 层、族谱视图);测试 `test/unit/lineage.test.ts` + 客户端用例。 > 需求(2026-09-22 用户提出):任务完成后只有「打回 / 确认」,缺少两条路径—— > ① 接着已完成的任务继续做下一个任务;② 认为当前完成只是中间态,提新目标继续做。 > 用户补充三点:a) 血缘要**用线条直观展示**(看板连线);b) 同意先出方案文档再实现; > c) 必须支持**多个任务继承自一个**(分叉)和**一个任务继承自多个**(合流)。 > > 已确认的三个决策:**接续新卡片**(不改老卡片)+ **创建后立即自动拆解** + > **review 态验收面也提供「确认并接续」**。 ## 0. 核心裁决 - **接续 = 签一份新合同,不是重开老合同。** done → in-progress 回边会污染验收记录 (两期工作混进同一条时间线/终检证据),并牵连调度器、WIP、打回 triage 的语义。 本方案**状态机零改动**:接续任务走既有 draft → decomposing 路径。 - 两个用户场景(接力续做 / 中间态续做)是同一机制,只差接续表单的预填模板: - 接力:空白新目标; - 中间态:预填「原目标 + 已完成至 X + 本期继续:___」。 - **血缘是 DAG 不是链**:`parentIds: TaskId[]` 一步到位,单链 / 分叉 / 合流统一表达。 ## 1. 概念与语义 - **血缘(lineage)**:任务间的有向无环引用,边 = 上下文/交付物的承接方向(父 → 子)。 - **父任务资格**:必须 `done`。review 不行——终批前仍可能被打回,作血缘父不稳。 - **分叉**(1 父 → N 子):一个交付物派生多方向,无额外约束。 - **合流**(N 父 → 1 子):多交付物集成,允许;**交接摘要逐父独立、不合并** (父间终检结论可能矛盾,混合后无法解释 AI 拆解依据)。 - **禁环 / 禁自指**:新建任务天然无环;防御性校验仍做(父的祖先集不含自身)。 - **depth**:`max(父 depth) + 1`(合流取最大),徽标「链·N」与族谱分层用。 ## 2. 数据与协议 ```ts // protocol/types.ts interface Task { // …现有字段… parentIds?: TaskId[] // 血缘父任务 id 列表;缺省 = 无血缘(存量任务零迁移) depth?: number // 仅写不入读的派生值?否——落库缓存,创建时算好 } ``` - 创建请求(actions)新增 `basedOn?: TaskId[]`(字段名沿用口语,落库为 parentIds)。 - **子代反查**:ledger 全内存扫描(`parentIds.includes(id)`),不建冗余索引。 - **交接摘要事件**:接续任务创建时由宿主生成,落一条 note 事件 (`kind: 'handoff'`),内容为逐父分节摘要(见 §3)。事件追加模型不受影响。 ## 3. 宿主:接续 API 与交接摘要 - 端点:`POST /api/taskflow/tasks` 扩展 `basedOn`(或独立 `POST /api/taskflow/tasks/:id/followup`,实现时按现有路由风格二选一)。 - 宿主动作序列(原子性:任一步失败则 draft 连同 parentIds 一并清理): 1. 校验父任务全部存在且 `done`,禁环; 2. 复制 workspace / pins / 权限设置自首个父任务(合流时父间设置冲突 → 以第一个父为准并在表单中提示); 3. 生成**交接摘要**:复用终检证据卡素材,逐父一段——目标、交付物清单 (artifacts 路径)、终检结论、验收达成情况、上一棒遗留点; **每父设 token 封顶**(超限截断),逐父独立分节,永不互相融合; 4. 创建 draft(写入 parentIds / depth),注入 handoff note 事件; 5. **立即触发 decomposing**(用户已确认自动拆解)——拆解 prompt 的输入里 附带交接摘要,AI 因此「知道上下文从哪来」。 - 摘要生成失败不阻塞建卡:降级为骨架摘要(父任务名 + 目标 + 交付物路径), handoff 事件标注 `degraded: true`。 ## 4. 展示设计(用户要求:线条直观展示) ### 4.1 看板连线层 - `.tf-columns` 滚动容器内叠 `position:absolute` SVG 层(`pointer-events:none`), 按卡片 `data-task-id` 的 `getBoundingClientRect` 取锚点,三次 bezier: 跨列连右缘 → 左缘,同列连下缘 → 上缘;箭头 marker 复用流程 tab 现成方案。 - 状态着色随**子任务**状态(flow 动态虚线 / done 绿实线),与流程图语言一致。 - **交互降噪**:默认 30% 透明度;hover 任一链上卡片 → 本链高亮、其余压暗。 **层叠裁定(2026-09-22 用户确认)**:连线保持在卡片**上层**全程可见 (预览对比过「压到卡片下方」的版本,被卡片遮挡反而更难读);防穿卡干扰 依靠淡显 + hover 提亮,不改层叠。 - **护栏**:无血缘不挂 SVG 层;连线 > 30 条自动降级为仅徽标; ResizeObserver + scroll 监听重算锚点。 - 视口外父卡:线端画到画布边缘 + 方向箭头。 ### 4.2 卡片徽标 - 单父:`⛓ 链·N`(depth); - 分叉父卡:`⛓ ↗2`(后继数); - 合流子卡:`⛓ ↙2`(父数)。 - hover tooltip:逐行列出父/子任务名与状态;点击 → 链弹层(本链族谱 DAG 横排 时间线,节点可点开详情,末尾虚线 `+ 接续` 节点)。 ### 4.3 族谱视图(全貌兜底) - 血缘 DAG 弹层,复用流程 tab 蛇形布局与箭头代码:节点 = 任务卡(状态色), 虚线边 = 血缘;分叉/合流自动成图。 - 入口:工具栏「血缘」按钮(全量)+ 卡片徽标(本链)。看板连线管「顺眼看」, 族谱管「认真理」。 ### 4.4 任务详情弹窗 - **合同 tab**:头部「接续自」横幅,**逐父一行** (`⛓ 接续自:<名称> ✅ 已完成 · 终批于 <时间> [查看]`)。 - **流程 tab**:管线最左「上一棒」节点组——N 个灰调只读节点全部**虚线汇入 「拆解」**(虚线 = 上下文流入,区别于子任务 DAG 实线);N=1 渲染退化为单节点, 同一套代码一个分支。悬停汇入线提示来源父任务。 - **交接摘要卡**:轨迹面板展示 handoff 事件(AI 拆解的输入依据,可解释性)。 ### 4.5 创建侧 - 创建表单加「继承自」**可搜索多选下拉**(不整列枚举):输入即按名称/ID 模糊过滤, 仅列 `done` 任务;已选项呈可删除 tag;候选项带任务 ID 与状态徽标; done 卡「接续新任务」按钮 = 预选该卡后打开同一表单(预填模板按场景二选一)。 - review 验收面:**「确认并接续」**——approve 落 T6 成功后直接打开接续表单; approve 失败则不弹。 ## 5. 边界与容错 | 情形 | 处理 | |---|---| | 父任务被归档 | 徽标/节点灰显「已归档」,血缘保留,不可跳转 | | 父任务被删除 | 断边灰色虚线 + 「已删除」tooltip,血缘事实保留 | | 合流父间设置冲突 | 以第一个父为准,表单提示 | | 连线性能 | >30 条降级仅徽标;族谱视图不受限 | | 摘要 token 超限 | 逐父截断,degraded 标记 | ## 6. 测试要点 - 协议:parentIds/depth 序列化、存量任务(无字段)兼容。 - 宿主:接续建卡原子性(失败清理)、禁环校验、合流摘要逐父独立 + 截断、 自动 decomposing 触发、review 态确认并接续的 approve 失败不弹表单。 - 客户端:连线层挂载/降级/hover 高亮、多父汇入渲染、徽标三形态、族谱 DAG。 - 回归:状态机零改动断言(TASK_TRANSITIONS 快照)。 ## 7. 里程碑 1. **一期(机制 + 单链展示)**:协议字段、接续 API、交接摘要、done 卡按钮、 合同 tab 横幅、流程 tab 上一棒节点、卡片徽标 + 链弹层。 2. **二期(线条 + 拓扑)**:看板 SVG 连线层、族谱视图、「继承自」多选(分叉/合流)、 流程 tab 多父汇入、review「确认并接续」。