get-shit-done Node Repair 工作流解析:任务验证失败后的自主修复算子
【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done
导读
本文深度剖析 get-shit-done 系统中的node-repair 工作流(get-shit-done/workflows/node-repair.md)——一个在计划任务(plan node)未通过完成标准(done-criteria)验证时自动介入的"自主修复算子"。它由 execute-plan.md 中的verification_failure_gate在任务验证失败时触发,在把问题抛回给用户之前,先按纪律尝试 RETRY(重试)、DECOMPOSE(拆分)、PRUNE(剪除)三种结构化修复策略。读完本文,你将掌握该工作流的触发条件、四类修复策略的选择逻辑、修复预算(REPAIR_BUDGET)的运作机制,以及如何通过config.json的两个配置键workflow.node_repair与workflow.node_repair_budget对它进行开关与调参,并理解其在 get-shit-done 自主执行体系中的位置。
一、为什么需要"自主修复算子":验证失败是执行流程的常态
在 get-shit-done 的规范驱动(spec-driven)执行模型中,每个任务都必须通过验收标准(<acceptance_criteria>)验证才能继续。在 execute-plan.md 的execute步骤中有一条 HARD GATE(硬性闸门):完成任务后若存在acceptance_criteria,必须运行验证循环,逐条执行 grep、文件检查或 CLI 命令来证明标准通过;任何一条标准失败,任务就被视为未完成,且被阻塞在下一任务之前。
现实世界的失败原因多种多样:命令路径写错、依赖缺失、环境变量未就绪、任务粒度过粗导致验收标准混杂了多个关注点、甚至前置条件根本不存在。若每次失败都直接中断并询问用户,会显著拖慢自主执行节奏;若让 Agent 无限重试,又可能陷入无效循环或擅自做出越权决策(例如悄悄修改架构方向)。
node-repair 工作流正是这两者之间的"纪律层":在预算(REPAIR_BUDGET)约束下,自主、有结构、可审计地尝试修复;预算耗尽或涉及架构决策时,才升级(ESCALATE)给用户。这一点与其在 FEATURES.md 中登记的需求REQ-REPAIR-06(系统必须可通过workflow.node_repair_budget与workflow.node_repair配置)相呼应。
二、触发场景与输入参数:谁在什么情况下调用它
node-repair 不是独立运行的命令,而是由执行编排器在任务验证失败这个精确时机调用的子工作流。调用入口位于 execute-plan.md 的verification_failure_gate步骤:
NODE_REPAIR=$(gsd-sdk query config-get workflow.node_repair 2>/dev/null || echo "true")- 若
workflow.node_repair为true(默认开启),则加载并调用 node-repair.md; - 若为
false,则跳过修复,直接进入面向用户的验证失败闸门; - 若 node-repair 返回ESCALATE(预算耗尽),同样会回到该闸门。
调用时需要向 node-repair 提供四个输入(对应文档中的<inputs>块):
| 输入 | 含义 | 来源 |
|---|---|---|
FAILED_TASK | 失败任务的任务编号、名称与 done-criteria | 计划(PLAN) |
ERROR | 验证产出:实际结果 vs 期望结果 | 验证循环输出 |
PLAN_CONTEXT | 相邻任务与阶段目标(用于约束感知) | 执行上下文 |
REPAIR_BUDGET | 剩余修复尝试次数(默认:2) | workflow.node_repair_budget |
PLAN_CONTEXT的用意很关键:修复不是孤立发生的,修复方案必须与相邻任务和当前阶段目标兼容,防止某个修复动作"修好了 A 却破坏了 B"。而REPAIR_BUDGET则从机制上防止无休止的自我修复。
三、四种修复策略:RETRY / DECOMPOSE / PRUNE / ESCALATE
node-repair 的核心是<repair_directive>:分析失败原因后,必须且只能选择一种修复策略。四种策略的语义、适用场景与输出格式如下:
| 策略 | 何时使用 | 典型触发场景 | 输出格式 |
|---|---|---|---|
| RETRY | 方法正确但执行失败 | 命令错误、依赖缺失、路径错误、环境问题、瞬时失败 | RETRY: [重试前需做的具体调整] |
| DECOMPOSE | 任务粒度过粗,实现缺口是结构性的 | done-criteria 覆盖多个关注点 | DECOMPOSE: [子任务1] \| [子任务2] \| ...(最多 3 个) |
| PRUNE | 当前约束下任务不可行 | 前置条件缺失且此处无法修复、超出范围、与先前决策矛盾 | PRUNE: [一句话理由] |
| ESCALATE | 修复预算耗尽,或涉及架构决策(对应偏差规则 Rule 4) | RETRY 用不同方案失败超过一次、修复需要结构性变更 | ESCALATE: [已尝试的内容] \| [需要做的决策] |
几个值得注意的设计要点:
- RETRY 不是盲目重试:它要求先给出"具体调整"再重试,即每次重试都必须携带一次实质性的修正,而非原地重跑。
- DECOMPOSE 的子任务必须有单一可验证结果,并且文档在
<constraints>中明确要求:拆出来的子任务必须比原任务更具体,而不是同义改写。这是防止"假拆分"(把一个失败任务换个说法拆成三个还是同样失败的任务)的关键约束。 - PRUNE 需要理由:跳过任务不是默许的,必须在 SUMMARY 中留下可审计的剪除理由。
- ESCALATE 对应偏差规则 Rule 4:在 execute-plan.md 的
<deviation_rules>中,Rule 1-3(bug、关键缺失、阻塞)允许自动修复,而Rule 4(架构性变更)必须 STOP 并等待用户批准。node-repair 的 ESCALATE 正是该规则在修复场景中的落地。
四、诊断决策流程:五问定策略
node-repair 的<process>以diagnose步骤开场,要求修复算子仔细阅读错误与 done-criteria,并按顺序自问四个问题:
- 这是瞬时/环境问题吗?→RETRY
- 任务是否可验证地过于宽泛?→DECOMPOSE
- 前置条件是否确实缺失且在范围内无法修复?→PRUNE
- 该任务是否已经尝试过 RETRY?检查
REPAIR_BUDGET,若为 0 →ESCALATE
这组问题构成一条明确的决策漏斗:先排除"擦一擦就能过"的表面问题,再判断是不是任务划分本身的问题,再排除不可行任务,最后才把真正啃不动的硬骨头交给用户。整个诊断过程强约束在计划上下文(PLAN_CONTEXT)内进行,避免修复动作越出当前阶段的边界。
五、四种策略的执行过程
5.1 RETRY:带着具体调整重来
- 应用指令中声明的具体调整;
- 重新运行任务实现;
- 重新运行验证;
- 通过 → 继续正常流程,并在日志中记录
[Node Repair - RETRY] Task [X]: [调整内容]; - 再次失败 →递减
REPAIR_BUDGET,携带更新后的上下文重新调用 node-repair。
注意第 5 步:RETRY 失败后会递归进入下一轮修复,但预算每轮递减,直至归零触发 ESCALATE。文档约束也写明:RETRY 用不同方案失败超过一次即应升级。
5.2 DECOMPOSE:在内存中拆分,绝不改盘上的 PLAN.md
- 就地用子任务替换失败任务(
<constraints>明确要求:绝不修改磁盘上的 PLAN.md,拆分的子任务仅在内存中存在); - 顺序执行各子任务,每个子任务独立验证;
- 全部通过 → 原任务视为成功,记录
[Node Repair - DECOMPOSE] Task [X] → [N] sub-tasks; - 某子任务失败 → 针对该子任务重新调用 node-repair(
REPAIR_BUDGET按子任务分别计数)。
"不落盘"这条约束意义重大:它把修复过程与计划文档的持久化状态解耦,避免 Agent 为了"让验证通过"而悄悄改写计划本身——计划是规范,修复是执行层的应变,两者不能混为一谈。
5.3 PRUNE:带理由地跳过
- 将任务标记为 skipped(跳过)并附理由;
- 在 SUMMARY 的 "Issues Encountered" 中记录
[Node Repair - PRUNE] Task [X]: [理由]; - 继续下一个任务。
5.4 ESCALATE:带着完整修复历史回到用户
- 通过
verification_failure_gate将问题呈现给用户,附完整修复历史; - 呈现内容:每次 RETRY/DECOMPOSE 尝试了什么、当前阻塞点是什么、有哪些可选方案;
- 等待用户指示后再继续——不允许自作主张。
升级到用户侧后,execute-plan.md 的verification_failure_gate会以固定格式呈现:
Verification failed for Task [X]: [name]. Expected: [criteria]. Actual: [result]. Repair attempted: [summary of what was tried].
并给出三个选项:Retry(重试)、Skip(标记为未完成,跳过)、Stop(停止调查)。若用户选择跳过,则记入 SUMMARY 的 "Issues Encountered"。
六、日志规范:每一次修复都必须可审计
node-repair 的<logging>块要求所有修复动作必须出现在SUMMARY.md的 "## Deviations from Plan" 小节下,格式统一:
| 类型 | 格式 |
|---|---|
| RETRY 成功 | [Node Repair - RETRY] Task X: [adjustment] — resolved |
| RETRY 失败 → ESCALATE | [Node Repair - RETRY] Task X: [N] attempts exhausted — escalated to user |
| DECOMPOSE | [Node Repair - DECOMPOSE] Task X split into [N] sub-tasks — all passed |
| PRUNE | [Node Repair - PRUNE] Task X skipped: [justification] |
这与 execute-plan 的<deviation_documentation>要求一致(SUMMARY 必须包含偏差小节,若无偏差则写None - plan executed exactly as written.)。统一格式的意义在于:无论是人工复盘还是后续的审计/verifier 流程,都能从 SUMMARY 中快速还原"每个任务失败后到底发生了什么"。
七、约束与配置:两个键控制整个修复机制
node-repair 的<constraints>块给出了三条硬性约束:
REPAIR_BUDGET每个任务默认 2,可通过config.json的workflow.node_repair_budget配置;- 绝不修改磁盘上的 PLAN.md,拆分的子任务仅存在于内存;
- 若
config.json中workflow.node_repair为false,直接跳到verification_failure_gate,保持用户原本的行为(即不做任何自主修复)。
配置默认值在整个仓库中保持一致,可以从多个层面交叉印证:
- docs/CONFIGURATION.md 中的默认配置片段:
"workflow": { ... "node_repair": true, "node_repair_budget": 2, ... }; - get-shit-done/references/planning-config.md 的配置参考表:
workflow.node_repair(boolean,默认true,取值true/false,"对失败的计划节点尝试自动修复")、workflow.node_repair_budget(number,默认2,任意正整数,"每个失败节点的最大修复重试次数"); - sdk/shared/config-defaults.manifest.json 中的 SDK 默认值清单同样登记
"node_repair": true与"node_repair_budget": 2; - 从源码结构看,sdk/src/query/config-gates.ts 通过
node_repair: workflowBool(wf.node_repair, true)读取该配置,缺省时回退为true;get-shit-done/bin/lib/config.cjs 中也以node_repair: true、node_repair_budget: 2作为默认值; - 测试侧,tests/config.test.cjs 显式断言默认配置中
config.workflow.node_repair === true且config.workflow.node_repair_budget === 2,tests/gsd-settings-advanced.test.cjs 也将这两个键列入高级设置默认值清单。
一个常见的调参场景:对于失败率较高但危害较小的探索性任务,可以把node_repair_budget从 2 调高到 3(planning-config.md 的配置示例中即展示了"node_repair_budget": 3的写法);反之,对于高风险的执行阶段(如发布流程),则可以将其调低,甚至将workflow.node_repair设为false,让每次验证失败都直接交由人工决策。
八、在更大执行体系中的位置:修复只是执行纪律的一环
node-repair 并非孤立存在,它嵌在 get-shit-done 的执行纪律链中:
- 验收硬门(acceptance_criteria HARD GATE):每个任务完成后强制验证,失败即阻塞;
- 偏差规则(deviation_rules):Rule 1-3 自动修复并记录偏差;Rule 4(架构变更)STOP 等待用户——与 ESCALATE 策略一一对应;
- 验证失败闸门(verification_failure_gate):作为 node-repair 的调用入口与升级出口,负责读取
workflow.node_repair配置、注入四个输入参数、接收 ESCALATE 结果并向用户呈现完整修复历史; - 修复算子(node-repair):本文主体,在闸门与用户之间插入一层受预算约束的自主修复。
从职责划分看:闸门管"要不要修、何时交回给人",node-repair 管"怎么修、修到什么程度算完"。两者配合,使 get-shit-done 在保持自主执行节奏的同时,始终把架构级决策权和最终判断权保留在用户手中——这正是其"轻量但强大"的执行体系设计意图的缩影。
总结
node-repair 工作流通过"诊断四问 + 四策略 + 预算约束 + 统一日志"的机制,把任务验证失败后的处理从"无限重试"或"直接打断用户"两个极端中解放出来:能擦的擦(RETRY)、能拆的拆(DECOMPOSE)、该弃的弃(PRUNE)、碰到底线的交人(ESCALATE)。配合workflow.node_repair/workflow.node_repair_budget两个配置键,团队可以按阶段风险自由调节自主程度。如果你正在使用或研究 get-shit-done 的规范驱动执行流程,node-repair.md 及其调用方 execute-plan.md 是理解其"自主但有纪律"哲学的最佳起点。
【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考