dynamic-work-graph-design-skill-design.md 6.25 KB

跨 Org Agent 的动态 Work Graph 设计能力——详细设计(SDD)

日期: 2026-08-06 性质: 详细设计,对应需求文档 docs/done/dynamic-work-graph-design-skill-requirements.md(条目 E,已确认)。回答该需求文档第 8 节的开放问题。 依赖:条目 G(docs/work-graph-parallel-execution-design.md)已实现——topological_layers()/run_graph() 已经在生产代码里。 状态: 设计草案,待评审后实施。

1. G 已经回答了 FR-2(并行分组字段格式)

需求文档 FR-2 留空的"哪些节点属于同一个可并行分组"字段格式,G 的实际实现给出了确定答案:不需要新字段。topological_layers() 完全靠 depends_on/edges 结构本身推导独立性——没有相互依赖的节点自动落入同一层,run_graph() 自动并发执行同层节点。Planning Skill 的方法论职责因此简化为:"如实表达真正的依赖关系,不要为了图好看而人为加上并不存在的 depends_on"(14 步版对照笔记"边是数据契约"这条原则的直接应用),不需要额外发明一个"parallel_group"标记。

2. 新 Skill:design-dynamic-work-graph

skills/design-dynamic-work-graph/SKILL.md,与 planning-requirement-expansion、code-task-development 等现有 Skill 平级存放。内容方法论(不含代码):

  1. 节点边界怎么划:一个节点 = 一次独立的、有明确输入输出契约的 Work Node 执行(一次 claude -p 调用)。任务小到一次调用就能完成时不需要拆图(呼应需求文档第 6 节约束)。
  2. edge_type 怎么选:zero_token(纯聚合/规约,不需要 Agent 推理,比如"把三份判断投票汇总")vs needs_judgment(下游需要真正读懂上游内容才能继续,比如"PRD 依赖 BRD 的实际内容")。
  3. 如何识别可并行的候选点:如实列出每对节点之间是否存在真实数据流动——没有数据流动就不要加 depends_on,G 会自动把它们并发调度。
  4. 每个节点必须自带 task_prompt(该节点执行时使用的完整提示词,自包含,不依赖调用方另外拼接)——这是 Coder/Validator 场景与 Planner 场景的关键区别:Planner 的四个节点类型固定(brd/prd/sdd/benchmark...),下游代码用一个查表 _DOC_PROMPTS[artifact_type] 就能拿到提示词;Coder/Validator 的子任务没有固定的小词表,必须由 Claude 自己在规划阶段把每个节点的提示词写出来。

3. work_graph_plan.py 改造(FR-3)

不改动 Planner 现有路径:_PROMPT_TEMPLATE(brd/prd/sdd/benchmark 固定链)与 _normalize_graph_manifest 的 canonical-chain 强制逻辑完全保留,org_node == "planner" 时走原有分支,零回归风险。

新增:

  • _GENERIC_PROMPT_TEMPLATE:当 org_node != "planner" 时使用,要求 Claude 依据 design-dynamic-work-graph Skill 的方法论,把 goal_text 拆成一个 graph_manifest,每个节点除 node_id/depends_on 外必须包含 task_prompt(自包含提示词);输出格式(fenced ``json 块)跟现有约定一致,复用同一套_extract_graph_manifest` 解析逻辑。
  • plan_work_graph() 内部按 org_node == "planner" 二选一模板,函数签名/返回值不变(需求文档非目标 #2)。
  • generic_node_prompt_builder(graph_manifest):新增的公开辅助函数,返回一个 build_prompt(node, outputs) 闭包,直接读取 node["task_prompt"](run_graph() 的 build_prompt 约定不变,仍然是"给定 node + 已完成 outputs,返回这次调用的提示词")——之所以放在 work_graph_plan.py 而不是 e2e_pipeline.py,是因为它跟生成侧的字段约定(task_prompt 这个 key 名)强耦合,两者应该在同一个模块里维护,避免字段改名时两处不同步。

_normalize_graph_manifest 不需要改动——canonical-chain 强制分支本来就有 all(t in by_artifact_type for t in _CANONICAL_DOC_CHAIN) 前置判断,Coder/Validator 的动态图没有 brd/prd/sdd/benchmark 节点,天然不触发,其余的 id→node_id/depends_on 兜底逻辑对新路径同样适用,不需要区分。

4. Skill 接入 Coder/Validator

src/agent_profile.py::FRONTMATTER["coder"]["skills"]/["validator"]["skills"] 各自追加 "design-dynamic-work-graph"。.claude/agents/{coder,validator}.md 是从这里渲染出来的(render_agent_definition),不需要手改部署产物。

5. 验证范围(对应需求文档验收标准,按非目标 #1 收窄)

需求文档 FR-5/验收标准 1 优先级是"应该",且非目标 #1 明确"不要求第一版就覆盖 Coder/Validator 的全部真实工作场景,只需要证明机制本身走得通"。本轮实现范围:

  • 证明 plan_work_graph(conn, "coder", ...) 能生成一个正确带 task_prompt、互不依赖节点的 graph_manifest(mock claude 子进程返回一个"给三个独立模块各自补单元测试"的真实场景响应)。
  • 证明该 graph_manifest 经 topological_layers() 分层后,三个节点确实落在同一层(跟 G 的实现直接挂钩,不是空谈)。
  • 证明 generic_node_prompt_builder 生成的 build_prompt 能驱动 run_graph() 端到端跑完(mock execute_work_graph)。
  • 不改动 e2e_pipeline.py::implement_code() 的现有单节点生产路径——那是更大的、需要独立评估的改动(如何决定"这个 Coder 任务复杂到该规划成图"本身就是一个开放问题,需求文档风险第 3 条已经点出),留给后续任务。

6. 回答需求文档第 8 节开放问题

  • 新 Skill 命名:design-dynamic-work-graph,目录 skills/design-dynamic-work-graph/。
  • _PROMPT_TEMPLATE 改造方式:按 org_node 二选一模板(Planner 固定链 vs 通用动态规划),不是让 Claude 完全自由决定 Planner 要生成哪些节点——Planner 那条链是"架构常量",如 _normalize_graph_manifest 自己的注释所说,不应该变成每次都不同。
  • FR-2 并行分组字段格式:不需要,G 靠 depends_on/edges 结构自动推导(见第 1 节)。
  • Coder/Validator 第一个接入场景:mock 场景"给三个独立模块各自补一个单元测试",用于验证机制可用性,不接入真实生产路径。