首页
/ get-shit-done 为何放弃"安装期模板渲染 Agent 定义":一次基于确定性、Token 成本与补丁迁移风险的架构决策复盘

get-shit-done 为何放弃"安装期模板渲染 Agent 定义":一次基于确定性、Token 成本与补丁迁移风险的架构决策复盘

2026-09-07 21:10:53作者:房伟宁

导读

本文围绕 get-shit-done(GSD)仓库中一份以 wontfix 关闭的技术决策记录.out-of-scope/agent-template-rendering.md)展开,剖析"把 agents/*.md 中受配置门控的提示词文本抽成模板、在安装期与 .planning/config.json 变更时渲染"这一提案(#2758)为何被否决。你将看到 GSD 团队如何用"编排期确定性嵌入(orchestrator-time embedding)"替代"LLM 推断期解释条件分支",理解 workflow.* 开关的既定约定(缺失即启用)、gsd-sdk query config-get 的真实调用链、#2279 先行先例,以及一套"可复开条件(re-open criteria)"式的架构评审方法论——对需要向 Agent 提示工程与配置工程相结合的代码库做架构取舍的读者,具有直接的参考价值。


一、背景:GSD 的 Agent 定义与配置门控机制

get-shit-done 将大量行为逻辑承载在人类可读的提示词文档中:agents/*.md 定义各类角色 Agent(executor、planner、verifier、debugger 等),get-shit-done/workflows/get-shit-done/templates/ 定义分阶段工作流,而 .planning/config.json(其参考文档见 get-shit-done/references/planning-config.md)记录项目级规划配置。

当同一份 Agent 提示词需要同时服务多种运行形态时,自然会产生"这段文字该不该出现"的分支需求。目前仓库内的做法是在提示词中写条件散文(conditional prose),例如:

这类条件分支由 LLM 在推理期读取并解释。提案 #2758 认为这是不确定性(non-determinism)的暴露面,主张将其搬到编译期:把配置门控的散文抽到 agents/templates/*.md.tmpl,在安装时及 .planning/config.json 写入后,通过新的 gsd-sdk agents render 子命令渲染出最终 agents/*.md,使条件分支由确定性代码解析而非 LLM 解释。


二、提案的三个收益主张及其边界

.out-of-scope/agent-template-rendering.md 原文列出的三个收益主张如下,它们也是整场评审的论证靶心:

  1. 按功能关闭程度等比例削减 Token——被禁用的功能对应散文不再进入上下文;
  2. 确定性的功能门控——"结构上不可能违反"优于"测试后才可能发现问题"(impossible-by-construction vs. test-for);
  3. 面向贡献者的门控单一事实来源(single source of truth)——模板是唯一需要维护的开关文本。

提案同时引用 PR #2279(Codex/OpenCode 模型配置在安装期嵌入 Agent 文件)作为"编译期嵌入"的直接先例。

需要强调的是:这三点主张本身没有被全盘否定,被否定的是"引入模板渲染子系统"这一实现路线。从 CHANGELOG.md 可以确认,#2279 确实落地过——Codex/OpenCode model overrides — Embed model_overrides in agent files (#2279)(见 CHANGELOG.md),说明"把运行态配置确定性嵌入提示词"在 GSD 中是已被验证有效的模式;争论点始终是:同一问题是否需要第二套机制


三、为什么被否决:四条技术理由

3.1 确定性主张是"理论上的",而非"被观测到的"

提案最强论点是"Agent 散文中的配置分支 = 确定性失效面"。但评审指出,当前代码库中的实际模式已经做了大量缓解

  • gsd-executor 中的 worktree 分支并非由 LLM 解释,而是由 bash 中 gsd-sdk query config-get 确定性解析。在 agents/gsd-executor.md 可以看到同类调用:AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
  • "Skip if workflow.X is false" 这类散文短小、稳定,且遵循统一的"缺失键 = 启用"约定(missing key = enabled);
  • 仓库没有记录过 LLM 因这类散文而误关已启用检查或误开已禁用检查的案例。

也就是说:用一个理论上的失效面,去交换一个真实且高风险的补丁迁移面(见 3.4),在评审看来不是合理交易。记录中明确写道:曾要求提案者提供实证文档,但未获提供。

3.2 Token 浪费量小且有上限

提案称"跨多阶段里程碑的真实开销"可观,但评审依据仓库实测存量给出了相反的规模判断:

  • Agent 文件中的 workflow.* 开关引用大约 5 处
  • 全库"Skip if"条件散文约 20 条,绝大多数仅 1–2 句。

agents/ 目录中检索 Skip if 可以验证这一点:命中集中在 agents/gsd-plan-checker.md(4 处)、agents/gsd-phase-researcher.mdagents/gsd-debugger.mdagents/gsd-ui-researcher.md 等文件。评审进一步指出:"多阶段里程碑真实支出"这一说法没有对照 gsd-context-monitor 的输出做基线测量(对应实现见 hooks/gsd-context-monitor.js)。在缺少测量基线的前提下,~20 条短条件句的节省上限不足以支撑一个需要"CI 强制模板/生成产物分离"的全新子系统。

3.3 确定性门控需求已被既有机制满足

对于真正需要确定性解析的场景——模型选择、推理强度、worktree 模式——PR #2279 已经确立了编排期配置嵌入的做法,即在工作流层把配置值嵌入到子 Agent 的提示词中,而不是让子 Agent 自行读配置猜测。

get-shit-done/workflows/execute-plan.md 的 Pattern A 中可以清楚地看到这条既有路径的形态:编排器通过 config-get workflow.use_worktrees 读取开关,只有当其不为 false 时才附加 isolation="worktree" 参数,否则走主工作区顺序执行。换言之,开关在子 Agent 诞生之前就被编排器解析完毕,LLM 根本没有机会"误读"。

因此提案自身列出的 "Alternative #1(延续编排器嵌入模式)"虽因"Agent 内部条件句应归属 Agent 层"的理由被驳回,但其背后的诉求——确定性、低 Token 成本——完全可以通过沿既有路径逐开关扩展 #2279 得到满足。评审的核心担忧是:在编排器嵌入之上再叠加模板层,意味着同一问题被两套机制共同拥有,而提案没有给出任何分区规则(partition rule),被要求补充时也未回应。

3.4 补丁迁移风险与收益严重不成比例

这是压倒性的否决理由。GSD 的更新机制依赖 gsd-local-patches/ 的三方合并迁移(/gsd-reapply-patches,对应测试见 tests/reapply-patches.test.cjstests/bug-2969-verify-reapply-patches.test.cjs 等);一旦把 agents/*.md 从"手写散文"改成"渲染产物",任何贡献者的既有本地补丁都面临 rebase 逻辑失效的风险——提案者自己在记录中也承认这是"整个改动中风险最高的部分"

更关键的是:这笔风险纯粹来自内部重构——用户可见的功能面没有变化,换取的却只是"未经测量的 Token 节省 + 理论上的确定性提升"。这被明确判定为 wrong trade(错误的交易)。

记录还顺带评估了缩小范围后的变体 Alternative #5(仅对新安装生效,推迟迁移):它虽然规避了三方合并迁移的具体风险,但仍然会为一个收益未测量、且可被 #2279 既有路径吸收的问题,多交付一套并行机制,因此同样不可取。


四、复开条件:什么证据能推翻这次否决

这份记录最值得借鉴的是它把"否决"写成了可证伪的结论,而不是封闭的结论。以下任一条件满足即可重新讨论:

  1. 量化的 Token 差异:贡献者通过 gsd-context-monitor 对照"全部开关关闭"的代表性配置给出实测 Token 增量,且该增量显著大于沿 #2279 编排期嵌入路径逐开关扩展所能达到的效果;
  2. 真实的误解释案例:记录现存的某个开关条件被 LLM 误解的实例(例如 executor 无视 workflow.use_worktrees: false、verifier 在 workflow.verifier: false 时仍运行),而不是推测的失效模式;
  3. 清晰的分区规则:明确界定"编排期嵌入(#2279)"与"安装期模板层"各自的职责边界,使两套机制不重叠。

这套"先要证据、再谈方案;保留可复开入口"的处理方式,本身即是处理架构提案的高质量范本。


五、给贡献者的实践启示:今天如何新增一个确定性开关

如果你是一名希望为 GSD 增加新功能开关的贡献者,不要试图引入新的模板渲染层,而应沿评审指明的既有路径操作:

  1. 在规划配置中声明开关,参考 get-shit-done/references/planning-config.mdworkflow.use_worktrees(默认 true)与 workflow.verifier 的条目写法,给出类型、默认值、语义说明;
  2. 在编排层做确定性解析:工作流脚本通过 gsd-sdk query config-get workflow.<key> 读取(该子命令由 get-shit-done/bin/lib/core.cjs 的 config-get/config-set 区段实现,SDK 侧的 configGet()sdk/src/gsd-tools.ts),在 spawn 子 Agent 之前决定是否注入相关指令;
  3. 仅在 Agent 内部保留简短的"Skip if"散文,且遵循统一约定——例如"缺失键 = 启用",见 workflow.verifierworkflow.use_worktreesdocs/CONFIGURATION.mddocs/FEATURES.md 中的记录;
  4. 为"关闭态"补测试:仓库既有大量此类回归测试可作模板,例如 tests/config.test.cjsconfig-set workflow.use_worktrees false 后断言配置生效、tests/bug-2772-gitmodules-path-intersection.test.cjs 中验证子模块边界冲突时提示"re-run with workflow.use_worktrees=false",以及 tests/worktree-cleanup.test.cjs 中"use_worktrees 为 false 时跳过清理"的分支覆盖。

此外,workflow.use_worktrees: false 还承担着跨运行时兼容语义:例如 get-shit-done/workflows/execute-phase.md 在处理不支持 worktree 隔离的运行时(如 Codex)时明确报错并建议"设置 workflow.use_worktrees=false 或改用支持 worktree 隔离的运行时";get-shit-done/workflows/quick.md 则在检测到子模块边界时建议用户"以 workflow.use_worktrees=false 回退到主工作区顺序执行"。这说明单一开关 + 确定性读取的设计足以承载复杂的运行时分流,无需为此复制一份模板渲染管线。


六、结论与关联资料索引

agent-template-rendering 决策的核心结论可以压缩为一句话:当一个问题的收益未经测量、而其实现要为一个已被证明可行的机制再造一套平行子系统、并承担纯内部重构带来的补丁迁移风险时,正确的工程决策是拒绝它,并沿既有机制逐步演进。

后续读者可在以下位置继续深挖本决策所涉及的证据链:

换言之,这套架构并不拒绝"编译期确定化"这一方向——它只是拒绝在已被证明有效的路径之外另起炉灶;若日后有实测数据证明收益显著超出既有路径所能承载的范围,Re-open criteria 已为这场对话预留了明确、可操作的回归通道。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388