这是「GSD 全景代码解析」专题的第 3 篇。
任何成功的框架背后都有一组经得起推敲的设计原则。GSD 的五大原则并非纸上谈兵的空洞口号,而是从数百次真实项目迭代中沉淀下来的工程经验——每一条都对应着具体的代码实现、可量化的约束和明确的取舍边界。
这五大原则分别是:
- Fresh Context Per Agent —— 每个 Agent 拥有干净的上下文窗口
- Thin Orchestrators —— 工作流只做编排不做重活
- File-Based State —— 所有状态持久化到文件系统
- Absent = Enabled —— 配置缺失默认启用
- Defense in Depth —— 纵深防御的质量门控体系
它们之间并非孤立存在,而是构成了一个相互支撑的设计网络:
flowchart TD
A[Fresh Context Per Agent] --> B[Thin Orchestrators]
A --> C[File-Based State]
C --> B
C --> D[Absent = Enabled]
B --> E[Defense in Depth]
C --> E
D --> E
A -.->|"上下文隔离依赖状态外化"| C
B -.->|"编排器不干活,质量靠门控兜底"| E
D -.->|"简化配置,降低门控误触发"| E下面逐条深入解析。
一、Fresh Context Per Agent
概念解释
Fresh Context Per Agent 是 GSD 最核心的架构假设:每当 orchestrator(编排器)spawn 一个子 Agent 时,这个 Agent 获得的是一个全新、干净、经过精心筛选的上下文窗口,而非从父对话继承的累积上下文。
在 GSD 中,标准的上下文预算是 200K tokens(对于 Opus 4.6、Sonnet 4.6 等 1M 级模型可扩展至 1M)。这 200K 并非全部分配给代码,而是按照严格的协议进行预算拆分。
设计动机:Context Rot 问题
使用过 Claude Code 或类似工具的开发者的共同体验是:随着对话轮次增加,Agent 的响应质量明显下降——它会开始遗忘早期的约束条件、重复已经完成的决策、甚至对自相矛盾的指令无所适从。这个现象被称为 Context Rot(上下文衰减)。
Context Rot 的根本原因不是模型「变笨了」,而是:
- 注意力稀释:长序列中关键 token 的注意力权重被稀释
- 干扰累积:无关的试错过程、错误修正、探索路径占据了宝贵的上下文空间
- 状态污染:前面 Agent 的失败假设、错误结论被后续 Agent 当作事实继承
在单体 Agent 方案中,所有任务在一个对话中串行完成,Context Rot 几乎不可避免。GSD 的策略是主动切断传播链——每个 Agent 只活在自己的上下文宇宙中。
工程实现:200K Token 预算分配
GSD 的上下文预算由 context-budget.md 参考文档统一管理。典型的分配策略如下:
| 预算项 | 占比 | 内容 |
|---|---|---|
| 项目基础上下文 | ~20K | PROJECT.md + STATE.md 摘要 |
| 阶段上下文 | ~30K | XX-CONTEXT.md + XX-RESEARCH.md |
| 执行计划 | ~40K | XX-YY-PLAN.md 完整内容 |
| 代码基线 | ~80K | 相关源代码文件(按需读取) |
| 参考文档 | ~20K | references/*.md 中标记为必读的部分 |
| 输出缓冲区 | ~10K | Agent 输出预留 |
对于 1M 级模型,budget 自动扩展:
# orchestrator 读取 context_window 配置
INIT=$(gsd-sdk query config-get context_window)
# 当 >= 500000 时,启用自适应上下文增强
# Executor 接收前一波的 SUMMARY.md + 阶段 CONTEXT.md/RESEARCH.md
# Verifier 接收所有 PLAN.md + SUMMARY.md + REQUIREMENTS.md这种自适应机制使得 1M 模型能够在保持 Fresh Context 原则的同时,获得跨计划的 awareness,而非盲目执行孤立任务。
避免跨 Agent 污染
GSD 通过三层机制防止上下文污染:
- Spawn 隔离:每个 Agent 通过
Task或SubAgent调用创建,与父对话完全隔离 - 只读输入:Agent 接收的上下文 payload 由
gsd-sdk query init.<workflow>生成,是只读的 JSON 快照 - 单向输出:Agent 的输出写入文件系统(
SUMMARY.md、VERIFICATION.md等),而非返回给 orchestrator 对话
sequenceDiagram
participant O as Orchestrator
participant SDK as gsd-sdk
participant A1 as Agent-1
participant A2 as Agent-2
participant FS as File System
O->>SDK: query init.execute-phase "1"
SDK-->>O: JSON payload (project, state, phase)
O->>A1: spawn with fresh context
A1->>FS: write 01-SUMMARY.md
A1-->>O: done signal only
O->>A2: spawn with fresh context
Note over A2: A2 cannot see A1's reasoning
A2->>FS: write 02-SUMMARY.md
A2-->>O: done signal only与单体 Agent 方案的对比
| 维度 | 单体 Agent(传统模式) | GSD 多 Agent(Fresh Context) |
|---|---|---|
| 上下文窗口 | 持续累积,无上限 | 每次 spawn 严格控制在 200K |
| Context Rot | 严重,随时间递增 | 不存在,每次 fresh |
| 错误传播 | 错误结论持续影响后续 | 错误被隔离在单个 Agent 内 |
| 并行能力 | 伪并行,实际串行 | 真正并行(Wave 执行模型) |
| 调试难度 | 困难,需追溯整个对话 | 简单,每个 Agent 独立审计 |
| 成本模型 | 线性增长,后期昂贵 | 可预测,按 Agent 计费 |
当然,Fresh Context 并非没有代价:每次 spawn 有约 14K token 的固定开销(系统提示 + 工具定义 + 初始化握手)。GSD 通过 inline_plan_threshold(默认 2 个 task 以下内联执行,不 spawn 子 Agent)来优化小任务的性价比。
二、Thin Orchestrators
概念解释
Thin Orchestrators 是 GSD 对工作流层的核心约束:工作流文件(get-shit-done/workflows/*.md)只做编排不做重活。它们不生成代码、不做深度分析、不执行复杂推理——这些工作全部委托给专门的 Agent。
设计动机:为什么工作流文件可以那么大(69KB)但仍然是「Thin」的
这个看似矛盾的表述恰恰是 Thin Orchestrators 的精髓。以 execute-phase.md 为例,这个工作流文件可能达到 69KB,但其内容 90% 以上是:
- 条件分支规则:在什么情况下走哪条路径
- Agent 契约定义:spawn 谁、传什么上下文、期待什么输出
- 状态更新协议:如何将 Agent 输出同步到
STATE.md - 错误恢复模式:某个 Agent 失败后的回退策略
真正「重」的工作——代码生成、架构设计、安全审计——全部被外包给 agents/*.md 中定义的专门 Agent。
换句话说,工作流的「胖」是表面积的胖(覆盖所有边界情况和决策分支),而非体积的胖(包含重型计算逻辑)。
与 Agent 的职责边界
| 职责 | Orchestrator(工作流) | Agent |
|---|---|---|
| 决策路由 | ✅ 条件判断、分支选择 | ❌ |
| 上下文组装 | ✅ 调用 gsd-sdk query init | ❌ |
| Agent 调度 | ✅ spawn、收集结果、更新状态 | ❌ |
| 代码生成 | ❌ | ✅ executor、debugger |
| 架构设计 | ❌ | ✅ planner、researcher |
| 质量审查 | ❌ | ✅ plan-checker、verifier |
| 安全审计 | ❌ | ✅ security-auditor |
编排模式:顺序、并行、条件分支
GSD 工作流支持三种编排模式:
1. 顺序编排(Sequential)
plan-phase → execute-phase → verify-work每个阶段必须等待前一个阶段完成,状态文件(STATE.md)作为阶段间的接力棒。
2. 并行编排(Parallel / Wave)
在 execute-phase 中,plans 被分组为依赖 wave:
flowchart LR
subgraph Wave1 [Wave 1]
P1[Plan-01]
P2[Plan-02]
end
subgraph Wave2 [Wave 2]
P3[Plan-03
depends: 01]
P4[Plan-04
depends: 02]
end
subgraph Wave3 [Wave 3]
P5[Plan-05
depends: 03,04]
end
Wave1 --> Wave2 --> Wave3同一 wave 内的 plans 并行执行,每个 executor 拥有独立的上下文窗口。GSD 通过 --no-verify 提交 + STATE.md 文件锁(O_EXCL 原子创建 + 10s 超时)解决并行冲突。
3. 条件分支(Conditional)
if context_window >= 500000:
启用自适应上下文增强
else:
使用截断版 prompt
if commit_docs == true:
git add .planning/
else:
跳过提交条件分支全部在工作流层显式表达,不隐藏在 Agent 的黑盒推理中。
Progressive Disclosure:控制工作流体积
为了保持工作流的可管理性,GSD 实施了 workflow size budget:
| Tier | 行数上限 | 适用场景 |
|---|---|---|
| XL | 1700 | 顶级编排器(execute-phase、plan-phase、new-project) |
| LARGE | 1500 | 多步骤规划器和大型特性工作流 |
| DEFAULT | 1000 | 聚焦单一用途的工作流(目标 tier) |
当工作流超出 tier 限制时,GSD 使用 Progressive Disclosure 模式拆分:
workflows/discuss-phase.md # 父文件:thin dispatcher
workflows/discuss-phase/modes/
├── power.md
├── all.md
├── auto.md
├── chain.md
└── default.md
workflows/discuss-phase/templates/
├── CONTEXT.md
├── DISCUSSION-LOG.md
└── checkpoint.json父文件只在需要时读取对应的 mode 和 template,既控制了单次加载体积,又保持了功能的完整性。
三、File-Based State
概念解释
File-Based State 是 GSD 的状态持久化哲学:所有项目状态——从高层愿景到每日进度——全部以人类可读的 Markdown 和 JSON 文件形式存储在 .planning/ 目录中。没有数据库,没有服务端,没有外部依赖。
核心状态文件的作用
.planning/ 目录是 GSD 的「项目大脑」,核心文件各司其职:
| 文件 | 作用 | 更新频率 |
|---|---|---|
PROJECT.md | 项目愿景、约束条件、架构决策、演进规则 | 低频(里程碑级) |
REQUIREMENTS.md | 范围化的需求清单(v1/v2/out-of-scope) | 中频(phase 级) |
ROADMAP.md | 阶段分解与状态追踪 | 中频 |
STATE.md | 活记忆:当前位置、决策记录、阻塞项、指标 | 高频(每日多次) |
config.json | 工作流配置与功能开关 | 低频 |
这些文件形成了一条从「战略」到「战术」到「执行」的完整信息链:
flowchart TD
P[PROJECT.md
为什么做] --> R[REQUIREMENTS.md
做什么]
R --> RM[ROADMAP.md
分几步做]
RM --> S[STATE.md
现在做到哪了]
S --> C[config.json
用什么策略做]
style S fill:#f9f,stroke:#333无数据库设计的优势和限制
优势:
Context Reset 免疫:当用户执行
/clear重置对话时,所有状态安然无恙地躺在文件系统中。这是 Fresh Context Per Agent 能够成立的前提——如果状态存在数据库里,每次 spawn 新 Agent 都需要额外的连接和查询。人类可审计:任何开发者打开
.planning/目录就能理解项目全貌,无需学习数据库 schema 或查询语言。Git 原生版本控制:
commit_docs: true(默认)时,planning 文件随代码一起提交,形成决策历史的完整审计链。Agent 可读写:Agent 使用标准的
Read/Write/Edit工具即可操作状态,无需额外的数据库客户端或 API 调用。零运维成本:不需要部署数据库、不需要备份、不需要担心连接池耗尽。
限制与应对:
| 限制 | 应对方案 |
|---|---|
| 并发写入冲突 | STATE.md.lock 文件锁(O_EXCL 原子创建,10s 超时) |
| 大项目查询效率 | 按 phase 分目录存储,Agent 按需读取 |
| 结构化查询困难 | gsd-sdk query 提供封装好的查询接口,内部解析 Markdown |
| 状态膨胀 | auto_prune_state 选项(默认保留最近 3 个 phase) |
状态文件的读写协议
GSD 对状态文件的操作有严格的协议规范:
读取协议:
# 通过 gsd-sdk query 获取结构化数据
INIT=$(gsd-sdk query init.execute-phase "1")
# 返回 JSON:project info, config, state, phase details
# 或读取单个文件
cat .planning/STATE.md写入协议:
# 更新 STATE.md(自动处理锁和 commit_docs 检查)
gsd-sdk query state.update --position "phase-03" --status "in-progress"
# 或底层 writeStateMd() 调用(自动获取文件锁)所有写入操作必须遵守「读-改-写」的原子性原则。并行 Agent 通过文件锁机制避免 race condition:
1. 尝试创建 STATE.md.lock(O_EXCL 标志,原子操作)
2. 如果失败,spin-wait + jitter 重试(最多 10s)
3. 读取 STATE.md → 修改 → 写入
4. 删除 STATE.md.lock状态传播图
不同阶段产生的 artifact 向下游传递:
flowchart LR
PROJECT[PROJECT.md] --> ALL[所有 Agent]
REQ[REQUIREMENTS.md] --> PV[Planner + Verifier + Auditor]
ROAD[ROADMAP.md] --> ORCH[Orchestrators]
STATE[STATE.md] --> ALL
CTX[XX-CONTEXT.md] --> RPE[Researcher + Planner + Executor]
RES[XX-RESEARCH.md] --> PC[Planner + Plan Checker]
PLAN[XX-YY-PLAN.md] --> EP[Executor + Plan Checker]
SUM[XX-YY-SUMMARY.md] --> VSV[Verifier + State]四、Absent = Enabled
概念解释
Absent = Enabled 是 GSD 配置系统的核心约定:如果一个配置键在 config.json 中不存在,它的行为等同于 true(启用)。用户需要显式禁用某个功能,而不是显式启用它。
这与传统的 opt-in(显式启用)模式完全相反。
设计动机:降低认知负担
GSD 面向的用户是开发者,而非 DevOps 工程师。开发者的核心诉求是「打开就能用」,而非「读完 50 页文档才知道怎么开启基础功能」。
以 planning-config.md 中的默认配置为例:
{
"workflow": {
"research": true,
"plan_check": true,
"verifier": true,
"nyquist_validation": true
}
}在 Absent = Enabled 模式下,即使 config.json 完全为空,上述所有功能也会自动启用。只有当用户明确写入 "research": false 时,研究阶段才会被跳过。
在 gates.md 和 planning-config.md 中的体现
gates.md 中的 Gate 类型设计体现了同样的哲学:
- 如果一个 workflow 没有定义 gate,默认的质量检查仍然通过
references/gates.md中的 canonical types 生效 plan-checker和verifier默认启用(workflow.plan_check: true,workflow.verifier: true)
planning-config.md 中几乎所有布尔配置都遵循此模式:
| 配置项 | 默认值 | 说明 |
|---|---|---|
commit_docs | true | 自动提交 planning 文件到 git |
workflow.research | true | 规划前自动运行研究 Agent |
workflow.plan_check | true | 规划后自动检查计划质量 |
workflow.verifier | true | 执行后自动运行验证 Agent |
workflow.nyquist_validation | true | 启用 Nyquist 风格验证门控 |
workflow.node_repair | true | 自动修复失败的 plan 节点 |
workflow.ui_phase | true | 前端 phase 自动生成 UI-SPEC |
workflow.security_enforcement | true | 启用威胁模型锚定的安全验证 |
hooks.context_warnings | true | 上下文超预算时显示警告 |
与显式配置(Opt-in)模式的对比
| 维度 | Opt-in(显式启用) | Absent = Enabled(GSD) |
|---|---|---|
| 初始配置复杂度 | 高,需要了解所有选项 | 低,空配置即可工作 |
| 功能发现成本 | 高,容易错过有用功能 | 低,默认全开 |
| 意外行为风险 | 低,用户明确知道开了什么 | 中,需要了解如何关闭 |
| 配置文档依赖 | 高,必须阅读文档 | 低,只需了解如何禁用 |
| 升级兼容性 | 差,新增功能默认不启用 | 优,新增功能自动生效 |
| 安全场景适用性 | 更好(安全默认关闭) | 需要额外平衡 |
安全性的平衡
Absent = Enabled 在安全敏感场景下似乎有风险——如果默认启用潜在危险功能怎么办?GSD 通过三层机制平衡:
安全相关功能有独立门控:如
workflow.security_block_on默认"high",只有 high severity 才会 block phase 推进;用户可降级到"medium"或"low"destructive 操作需要 human-in-the-loop:
mode: "interactive"(默认)下,所有 gate 都会询问用户确认;只有mode: "yolo"才会全自动执行Auto-detection 兜底:如
commit_docs自动检测.planning/是否在.gitignore中,如果在则强制设为false,避免 git 报错
if .planning/ in .gitignore:
commit_docs = false # 覆盖任何显式配置五、Defense in Depth
概念解释
Defense in Depth(纵深防御)是 GSD 的质量保证哲学:不依赖单一检查点,而是在流水线的多个层级设置独立验证机制,任何一层发现问题都可以阻止缺陷向下游传播。
四大门控类型
GSD 的质量门控体系基于 references/gates.md 中定义的四种 canonical gate types:
flowchart TD
PF[Pre-flight Gate
预检门控] --> RG[Revision Gate
修订门控]
RG --> EG[Escalation Gate
升级门控]
EG --> AG[Abort Gate
中止门控]
PF -.->|"条件不满足直接阻断"| Block1[阻断进入]
RG -.->|"质量不达标循环修订"| Loop[返回生产者
max 3 次迭代]
EG -.->|"自动无法解决时升级"| Human[人工决策]
AG -.->|"继续执行有危险时停止"| Stop[保存状态
终止流程]| Gate 类型 | 目的 | 行为 | 恢复方式 |
|---|---|---|---|
| Pre-flight | 验证前置条件 | 条件不满足则阻断进入 | 修复条件后重试 |
| Revision | 评估产出质量 | 质量不足则循环修订 | 生产者处理反馈,重新提交 |
| Escalation | surfaced 无法自动解决的问题 | 暂停工作流,等待人工决策 | 开发者选择行动方案 |
| Abort | 防止继续执行造成损失 | 立即停止,保存状态 | 调查根因后从 checkpoint 重启 |
Pre-flight Gate 实例:
plan-phase入口处检查REQUIREMENTS.md是否存在execute-phase入口处检查PLAN.md是否已生成verify-work入口处检查SUMMARY.md是否完整
Revision Gate 实例:
plan-checker审查PLAN.md,最多 3 轮迭代,含 stall detection(连续两轮问题数不减少则提前升级)verifier检查 phase 交付物是否符合成功标准
Escalation Gate 实例:
- 修订循环耗尽 3 次迭代后 surfaced 给开发者
verify-work发现未满足的标准时展示 gap
Abort Gate 实例:
- 上下文窗口严重耗尽时停止执行
STATE.md处于 error state 时阻断/gsd:next
钩子系统的防御层
GSD 的 hooks(11 个 shipped)构成了运行时的被动防御网:
| Hook | 事件 | 防御目标 |
|---|---|---|
gsd-prompt-guard.js | PreToolUse | 扫描 .planning/ 写入内容的 prompt injection 模式 |
gsd-read-injection-scanner.js | PostToolUse | 扫描 Read 工具输出中是否包含注入指令 |
gsd-workflow-guard.js | PreToolUse | 检测非 GSD 工作流上下文的文件编辑(opt-in) |
gsd-read-guard.js | PreToolUse | 阻止未读取文件的 Edit/Write 操作 |
gsd-context-monitor.js | PostToolUse | 在上下文剩余 ≤35%/≤25% 时注入警告 |
gsd-validate-commit.sh | PostToolUse | 强制 conventional commit 规范 |
这些 hooks 全部是 advisory(建议性) 的——它们记录和警告,但不阻断用户意图。这是 Defense in Depth 的重要设计:自动门控负责阻断明确的流程违规,hooks 负责监控和提醒边缘风险。
测试覆盖 70% 线的意义
GSD 对关键路径有严格的测试覆盖要求,tests/workflow-size-budget.test.cjs 等工作流预算测试确保:
- 每个工作流文件不超过其 tier 的行数上限
- Agent 定义不超过 50K 字符(某些 runtime 的限制)
- CLI 模块的核心函数有单元测试覆盖
70% 覆盖线不是随意设定的数字,它对应着「核心编排逻辑 + 状态管理 + 安全校验」这三条关键路径的交集。低于此线意味着某个 gate 或 hook 可能在未经测试的情况下被绕过。
门控矩阵
综合 view:
| 工作流 | 阶段 | Gate 类型 | 检查对象 | 失败行为 |
|---|---|---|---|---|
| plan-phase | 入口 | Pre-flight | REQUIREMENTS.md、ROADMAP.md | 阻断,提示缺失文件 |
| plan-phase | 步骤 12 | Revision | PLAN.md 质量 | 循环至 planner(最多 3 次) |
| plan-phase | 修订后 | Escalation | 未解决问题 | surfaced 给开发者 |
| execute-phase | 入口 | Pre-flight | PLAN.md | 阻断,提示缺失计划 |
| execute-phase | 完成时 | Revision | SUMMARY.md 完整性 | 重跑不完整任务 |
| verify-work | 入口 | Pre-flight | SUMMARY.md | 阻断,提示缺失摘要 |
| verify-work | 评估时 | Escalation | 未满足标准 | surfaced gap |
| next | 入口 | Abort | Error state、checkpoints | 停止,输出诊断 |
总结:五大原则的协同效应
单独看每一条原则,都像是「显而易见的正确选择」。但 GSD 的真正力量在于它们之间的协同效应:
- Fresh Context 依赖 File-Based State 提供状态连续性——如果没有文件系统的持久化,每次 spawn 新 Agent 都会丢失项目上下文
- Thin Orchestrators 依赖 Defense in Depth 的质量门控来保证外包给 Agent 的工作质量——编排器不审查具体内容,但 gate 会
- Absent = Enabled 降低了 Defense in Depth 的误触发成本——默认启用的 verifier 和 plan-checker 构成了自动化的安全网
- File-Based State 让 Absent = Enabled 成为可能——配置就是 JSON 文件,没有数据库迁移或 schema 演进的负担
这五条原则共同定义了 GSD 的工程美学:简单、透明、可审计、可防御。
下一篇预告: 第 04 篇《多 Agent 编排模型与 Wave 执行机制》
我们将深入拆解 GSD 的 Agent 编排内核:从 orchestrator 如何通过 gsd-sdk query 组装上下文 payload,到 Wave 依赖分析算法,再到 1M 模型的自适应上下文增强策略。 敬请期待。