五大设计原则深度解析

📑 目录

这是「GSD 全景代码解析」专题的第 3 篇。


任何成功的框架背后都有一组经得起推敲的设计原则。GSD 的五大原则并非纸上谈兵的空洞口号,而是从数百次真实项目迭代中沉淀下来的工程经验——每一条都对应着具体的代码实现、可量化的约束和明确的取舍边界。

这五大原则分别是:

  1. Fresh Context Per Agent —— 每个 Agent 拥有干净的上下文窗口
  2. Thin Orchestrators —— 工作流只做编排不做重活
  3. File-Based State —— 所有状态持久化到文件系统
  4. Absent = Enabled —— 配置缺失默认启用
  5. 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 参考文档统一管理。典型的分配策略如下:

预算项占比内容
项目基础上下文~20KPROJECT.md + STATE.md 摘要
阶段上下文~30KXX-CONTEXT.md + XX-RESEARCH.md
执行计划~40KXX-YY-PLAN.md 完整内容
代码基线~80K相关源代码文件(按需读取)
参考文档~20Kreferences/*.md 中标记为必读的部分
输出缓冲区~10KAgent 输出预留

对于 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 通过三层机制防止上下文污染:

  1. Spawn 隔离:每个 Agent 通过 TaskSubAgent 调用创建,与父对话完全隔离
  2. 只读输入:Agent 接收的上下文 payload 由 gsd-sdk query init.<workflow> 生成,是只读的 JSON 快照
  3. 单向输出:Agent 的输出写入文件系统(SUMMARY.mdVERIFICATION.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行数上限适用场景
XL1700顶级编排器(execute-phase、plan-phase、new-project)
LARGE1500多步骤规划器和大型特性工作流
DEFAULT1000聚焦单一用途的工作流(目标 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

无数据库设计的优势和限制

优势:

  1. Context Reset 免疫:当用户执行 /clear 重置对话时,所有状态安然无恙地躺在文件系统中。这是 Fresh Context Per Agent 能够成立的前提——如果状态存在数据库里,每次 spawn 新 Agent 都需要额外的连接和查询。

  2. 人类可审计:任何开发者打开 .planning/ 目录就能理解项目全貌,无需学习数据库 schema 或查询语言。

  3. Git 原生版本控制commit_docs: true(默认)时,planning 文件随代码一起提交,形成决策历史的完整审计链。

  4. Agent 可读写:Agent 使用标准的 Read/Write/Edit 工具即可操作状态,无需额外的数据库客户端或 API 调用。

  5. 零运维成本:不需要部署数据库、不需要备份、不需要担心连接池耗尽。

限制与应对:

限制应对方案
并发写入冲突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.mdplanning-config.md 中的体现

gates.md 中的 Gate 类型设计体现了同样的哲学:

  • 如果一个 workflow 没有定义 gate,默认的质量检查仍然通过 references/gates.md 中的 canonical types 生效
  • plan-checkerverifier 默认启用(workflow.plan_check: true, workflow.verifier: true

planning-config.md 中几乎所有布尔配置都遵循此模式:

配置项默认值说明
commit_docstrue自动提交 planning 文件到 git
workflow.researchtrue规划前自动运行研究 Agent
workflow.plan_checktrue规划后自动检查计划质量
workflow.verifiertrue执行后自动运行验证 Agent
workflow.nyquist_validationtrue启用 Nyquist 风格验证门控
workflow.node_repairtrue自动修复失败的 plan 节点
workflow.ui_phasetrue前端 phase 自动生成 UI-SPEC
workflow.security_enforcementtrue启用威胁模型锚定的安全验证
hooks.context_warningstrue上下文超预算时显示警告

与显式配置(Opt-in)模式的对比

维度Opt-in(显式启用)Absent = Enabled(GSD)
初始配置复杂度高,需要了解所有选项低,空配置即可工作
功能发现成本高,容易错过有用功能低,默认全开
意外行为风险低,用户明确知道开了什么中,需要了解如何关闭
配置文档依赖高,必须阅读文档低,只需了解如何禁用
升级兼容性差,新增功能默认不启用优,新增功能自动生效
安全场景适用性更好(安全默认关闭)需要额外平衡

安全性的平衡

Absent = Enabled 在安全敏感场景下似乎有风险——如果默认启用潜在危险功能怎么办?GSD 通过三层机制平衡:

  1. 安全相关功能有独立门控:如 workflow.security_block_on 默认 "high",只有 high severity 才会 block phase 推进;用户可降级到 "medium""low"

  2. destructive 操作需要 human-in-the-loopmode: "interactive"(默认)下,所有 gate 都会询问用户确认;只有 mode: "yolo" 才会全自动执行

  3. 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评估产出质量质量不足则循环修订生产者处理反馈,重新提交
Escalationsurfaced 无法自动解决的问题暂停工作流,等待人工决策开发者选择行动方案
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.jsPreToolUse扫描 .planning/ 写入内容的 prompt injection 模式
gsd-read-injection-scanner.jsPostToolUse扫描 Read 工具输出中是否包含注入指令
gsd-workflow-guard.jsPreToolUse检测非 GSD 工作流上下文的文件编辑(opt-in)
gsd-read-guard.jsPreToolUse阻止未读取文件的 Edit/Write 操作
gsd-context-monitor.jsPostToolUse在上下文剩余 ≤35%/≤25% 时注入警告
gsd-validate-commit.shPostToolUse强制 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-flightREQUIREMENTS.mdROADMAP.md阻断,提示缺失文件
plan-phase步骤 12RevisionPLAN.md 质量循环至 planner(最多 3 次)
plan-phase修订后Escalation未解决问题surfaced 给开发者
execute-phase入口Pre-flightPLAN.md阻断,提示缺失计划
execute-phase完成时RevisionSUMMARY.md 完整性重跑不完整任务
verify-work入口Pre-flightSUMMARY.md阻断,提示缺失摘要
verify-work评估时Escalation未满足标准surfaced gap
next入口AbortError 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 StateAbsent = Enabled 成为可能——配置就是 JSON 文件,没有数据库迁移或 schema 演进的负担

这五条原则共同定义了 GSD 的工程美学:简单、透明、可审计、可防御

下一篇预告: 第 04 篇《多 Agent 编排模型与 Wave 执行机制》

我们将深入拆解 GSD 的 Agent 编排内核:从 orchestrator 如何通过 gsd-sdk query 组装上下文 payload,到 Wave 依赖分析算法,再到 1M 模型的自适应上下文增强策略。 敬请期待。