- 人工智能
- AI Agent
- 代码智能体
- Agent 编排
- CLI
- AI 应用
【免费下载链接】gsd-2
A powerful meta-prompting, context engineering and spec-driven development system that enables agents to work for long periods of time autonomously without losing track of the big picture
本文基于docs/dev/ADR-001-branchless-worktree-architecture.md,系统拆解 gsd-2 早期为自治(Auto)编码会话设计的 Git 隔离架构:从「每个里程碑一个工作树 + 树内切片分支」到「完全消灭切片分支、单分支顺序提交」的演进逻辑。你将掌握 GSD 工作树/分支模型的设计动机、.gsd/状态归属(tracked vs gitignored)的分类治理原则、合并管线与smartStage()等关键函数的简化路径,以及该方案如何被后续 ADR-016 系列与 DB 权威(DB-authoritative)运行时模型取代的完整来龙去脉——这些知识对理解本仓库src/resources/extensions/gsd/下的工作树、合并与状态同步代码至关重要。
背景:GSD 如何用 Git 隔离自治编码会话
GSD(gsd-2)使用 Git 作为自治编码会话期间的隔离机制。该 ADR 记录的当前架构(在 M003、v2.13.0 中发布)为每个里程碑创建一个工作树(worktree),并在每个工作树内部使用切片分支(slice branch):每个切片(S01、S02、...)在自己的分支(gsd/M001/S01)上工作,切片完成时通过--no-ff合回里程碑分支(milestone/M001),里程碑完成时里程碑分支再 squash-merge 回main。
这套架构是为了取代更早的「每切片一分支(branch-per-slice)」模型——后者引发了严重的.gsd/合并冲突。M003 解决了合并冲突,却保留工作树内的切片分支,继承了大量复杂逻辑,并持续产生面向用户可见的失败。
从源码看,这一「每里程碑一个工作树」的模型至今仍是仓库的骨架:
src/resources/extensions/gsd/auto-worktree.ts拥有工作树的创建/进入/退出/合并生命周期,src/resources/extensions/gsd/git-service.ts提供底层 Git 原语与暂存逻辑。
五大问题:切片分支模型为什么必须被推翻
ADR-001 用五个层面的证据论证切片分支是「根因性的复杂度来源」。
1. 规划产物不可见(循环检测失败)
当research-slice或plan-slice分派时,Agent 在切片分支上写入产物(例如S02-RESEARCH.md)。Agent 完成后,handleAgentEnd会切回里程碑分支准备下一次分派——此时产物停留在切片分支上,里程碑分支看不到它。verifyExpectedArtifact()(当前实现于 auto-recovery.ts)检查的是里程碑分支,找不到文件就递增循环计数器并重试:3 次重试后硬停止,6 次生命周期分派后永久停止。结果就是烧掉预算、阻塞进度。
这个问题在 auto-stop 架构文档中被记录为"The Branch-Switching Problem"(分支切换问题)。
2..gsd/状态跨分支互相覆盖
.gsd/是 gitignored 的(.gitignore中的.gsd/),规划产物(roadmap、plans、summaries、decisions、requirements)位于.gsd/milestones/但对 Git 不可见。当多个分支或工作树在同一个仓库上运行时,它们共享磁盘上同一个.gsd/目录:分支 A 的 M001 roadmap 会覆盖分支 B 的 M001 roadmap。GSD 读取到损坏的状态,把错误的里程碑判为完成,或陷入无限分派循环。
该 ADR 还指出了代码库中的一个自相矛盾的 workaround:smartStage()(git-service.ts中的暂存逻辑)尽管.gitignore声明忽略.gsd/,仍会 force-addGSD_DURABLE_PATHS(milestones/、DECISIONS.md、PROJECT.md、REQUIREMENTS.md、QUEUE.md)。这意味着.gsd/milestones/在某些分支上确实被部分跟踪,而 gitignore 却声称相反——代码在与配置打架。
源码佐证(现状):这一「代码与配置打架」的张力在后续演进中被形式化而非消除——git-service.ts 定义了
RUNTIME_EXCLUSION_PATHS(.gsd/activity/、.gsd/runtime/、.gsd/worktrees/、.gsd/gsd.db*、.gsd/STATE.md、.gsd/DISCUSSION-MANIFEST.json等),其注释明确要求与 gitignore.ts 中的GSD_RUNTIME_PATTERNS保持同步,两者互为 canonical 来源。这意味着暂存时只排除运行时路径,而不是整体排除.gsd/。
3. 合并/冲突代码复杂度
切片分支模型需要一整套合并与冲突处理管线:
mergeSliceToMilestone()—— 98 行,带withMergeHeal包装的--no-ff合并mergeSliceToMain()—— 189 行,带冲突检测/分类/自动解决的 squash-mergegit-self-heal.ts—— 198 行,3 个针对合并失败的恢复函数fix-merge分派单元 —— 专门用一个 LLM 会话来解决自动解决器搞不定的冲突smartStage()—— 49 行运行时暂存排除逻辑- 冲突分类 —— 80 行,区分
.gsd/冲突、运行时冲突与代码冲突
总计约 582 行、分布在 3 个文件中的合并/分支/冲突代码,外加fix-merge提示词模板与分派逻辑——而这些代码的存在仅仅是为了服务切片分支。
4. 双隔离模式
分支模式(git-service.ts:mergeSliceToMain)与工作树模式(auto-worktree.ts:mergeSliceToMilestone)是两套并行实现:不同的合并策略、不同的冲突处理、不同的分支命名。两条路径都必须被维护和测试——共有 11 个测试文件覆盖合并/分支/工作树逻辑。
5. Bug 历史
- v2.11.1:因分支切换导致的解析缓存过期引发重复单元分派,发布 URGENT 修复
- v2.13.1:Windows 热修复
mergeSliceToMilestone中的多行提交信息 - M003 之前:15+ 个针对
.gsd/合并冲突的独立 bug 修复 - 持续的用户投诉:循环检测失败与状态损坏
决策:彻底消灭切片分支
ADR-001 的核心决策是:
Eliminate slice branches entirely.(彻底消除切片分支。)里程碑工作树内的所有工作都按顺序提交在同一条分支(
milestone/<MID>)上。没有分支创建、没有分支切换、没有切片合并、没有工作树内冲突解决。
同时把.gsd/规划产物纳入 Git 跟踪,只忽略运行时/临时状态。
目标架构
main ──────────────────────────────────────────── main │ ↑ └─ worktree (milestone/M001) │ │ │ commit: feat(M001): context + roadmap │ commit: feat(M001/S01): research │ commit: feat(M001/S01): plan │ commit: feat(M001/S01/T01): impl │ commit: feat(M001/S01/T02): impl │ commit: feat(M001/S01): summary + UAT │ commit: feat(M001/S02): research │ commit: ... │ commit: feat(M001): milestone complete │ │ │ └──────────── squash merge ──────────────────┘使用的 Git 原语
| 原语 | 用途 |
|---|---|
| Worktrees(工作树) | 每个活动里程碑一个。文件系统级隔离。 |
| Commits(提交) | 每次动作的粒度化顺序历史。 |
| Squash merge | 每个里程碑在main上留下一个干净的单一提交。 |
| Branches(分支) | 只有main和milestone/<MID>。没有其他分支。 |
不使用的 Git 原语
| 原语 | 原因 |
|---|---|
| 切片分支 | 切片是顺序执行的。分支只会增加复杂度,没有任何回滚收益。 |
--no-ff合并 | 工作树内没有分支需要合并。 |
| 分支切换 | 从不发生。所有工作都在一条分支上。 |
| 冲突解决 | 工作树内没有合并,就没有工作树内冲突。 |
状态归属模型:.gsd/从「整体忽略」到「分类治理」
ADR-001 对.gsd/的归属做了关键切分:
纳入 Git 跟踪(随分支流转):
.gsd/milestones/ — roadmaps, plans, summaries, research, contexts, task plans/summaries .gsd/PROJECT.md — project overview .gsd/DECISIONS.md — architectural decision register .gsd/REQUIREMENTS.md — requirements register .gsd/QUEUE.md — work queue保持 gitignored(临时、运行时、基础设施):
.gsd/runtime/ — dispatch records, timeout tracking .gsd/activity/ — JSONL session dumps .gsd/worktrees/ — git worktree working directories .gsd/auto.lock — crash detection sentinel .gsd/metrics.json — token/cost accumulator .gsd/completed-units.json — dispatch idempotency tracker .gsd/STATE.md — rendered state projection .gsd/gsd.db — authoritative runtime database (local, gitignored) .gsd/DISCUSSION-MANIFEST.json — discussion phase tracking .gsd/milestones/**/*-CONTINUE.md — interrupted-work markers .gsd/milestones/**/continue.md — legacy continue markers.gitignore更新方案
用显式的「仅运行时忽略」替代一刀切的.gsd/忽略:
# ── GSD: Runtime / Ephemeral ───────────────────────────────── .gsd/auto.lock .gsd/completed-units.json .gsd/STATE.md .gsd/metrics.json .gsd/gsd.db .gsd/activity/ .gsd/runtime/ .gsd/worktrees/ .gsd/DISCUSSION-MANIFEST.json .gsd/milestones/**/*-CONTINUE.md .gsd/milestones/**/continue.md规划产物(milestones/、PROJECT.md、DECISIONS.md、REQUIREMENTS.md、QUEUE.md)不在.gitignore中,按常规方式被跟踪。
现状对照:本仓库根目录 .gitignore 至今仍保留
# ── GSD project state (per-worktree, never committed) ── .gsd/以及.gsd/gsd.db的整体忽略——这正是该 ADR 的决策「未被采纳」的直接体现(详见下文「取代与演进」)。但GSD_RUNTIME_PATTERNS的精细化模式已在 gitignore.ts 落地为可编程的运行时路径清单。
落地后的代码形态变化(Consequences)
代码删除清单
| 文件 | 删除行数 | 移除内容 |
|---|---|---|
auto-worktree.ts | ~246 | mergeSliceToMilestone()、shouldUseWorktreeIsolation()、getMergeToMainMode()、切片合并守卫 |
git-service.ts | ~250 | mergeSliceToMain()、冲突解决、合并后运行时剥离、ensureSliceBranch()、switchToMain() |
git-self-heal.ts | ~86 | abortAndReset()、withMergeHeal()(合并专用恢复) |
auto.ts | ~150 | 合并分派守卫、fix-merge分派路径、分支模式路由 |
worktree.ts | ~40 | getSliceBranchName()、ensureSliceBranch()、mergeSliceToMain()委托 |
| 测试文件 | ~11 个文件 | auto-worktree-merge.test.ts、auto-worktree-milestone-merge.test.ts及相关合并测试用例 |
| 总计 | ~770+ 行 |
mergeMilestoneToMain()变成什么
该函数被大幅简化,流程变为六步:
- 自动提交工作树中的任何脏状态
chdir回到 main 仓库根git checkout maingit merge --squash milestone/<MID>- 用里程碑摘要
git commit - 移除工作树并删除分支
不再有冲突分类、不再有运行时文件剥离、不再有.gsd/特殊处理。规划产物能干净合并,是因为它们位于.gsd/milestones/M001/——在合并之前main上根本不存在这个目录。
源码佐证(现状):
mergeMilestoneToMain()至今仍存在于 auto-worktree.ts,其实现保留了 ADR 规划的第一要素——「自动提交脏状态」并增加了并行模式守卫(仅当 cwd 处于里程碑分支时才自动提交,防止在集成分支上误提交他里程碑的脏文件污染main,#2929),随后还会先把工作树 DB 回灌到 main DB 再离开工作树上下文。测试可参考 auto-worktree-milestone-merge.test.ts 与 all-milestones-complete-merge.test.ts。
smartStage()变成什么
GSD_DURABLE_PATHS的 force-add 不再需要——规划产物不再被 gitignore,git add -A自然收录它们。函数缩减为:
git add -Agit reset HEAD -- <runtime paths>(取消暂存运行时文件)
_runtimeFilesCleanedUp的一次性迁移逻辑也可以删除。
源码对照:当前 git-service.ts 的
smartStage()已经演进为「用 pathspec 排除暂存」模式:排除RUNTIME_EXCLUSION_PATHS而非整个.gsd/,以避免大型未跟踪产物树导致git add -A挂起(#1605),并防止里程碑中途整体排除.gsd/造成后半段产物永不提交的静默失败(#1326)。它还包含并行工作者的里程碑锁(GSD_MILESTONE_LOCK)逻辑:只暂存属于本里程碑的文件(#1991)。这验证了 ADR 判断——暂存逻辑的复杂度中心从「合并」转移到了「运行时路径排除与并行作用域」。
handleAgentEnd()变成什么
任一单元完成后:
- 使缓存失效
autoCommitCurrentBranch()—— 在唯一的分支上提交verifyExpectedArtifact()—— 文件总是在当前分支上(没有分支切换)- 持久化完成键
"Path A fix"(原 937-953 行)成为唯一路径,分支不匹配不可能发生。
fix-merge消亡
fix-merge分派单元类型被彻底消除。工作树内没有任何会产生冲突的合并。唯一的合并是里程碑→main(squash),万一冲突(罕见的并行里程碑边缘情况),就在里程碑完成时做一次性解决——而不是进入分派循环。
向后兼容
shouldUseWorktreeIsolation()的三级偏好解析被单一行为取代:始终使用工作树隔离。git.isolation: "branch"偏好被弃用。
拥有既有gsd/M001/S01切片分支的项目仍可被状态推导(state derivation)读取,但新工作不再创建切片分支。
风险与缓解(Risks)
1. 并行里程碑在 squash-merge 时的代码冲突
如果两个里程碑修改同一源文件,第二个 squash-merge 回main时会冲突。缓解:squash-merge 前先git fetch origin main && git rebase main。这是标准实践,在单用户工作流中很少见。
2. squash 后丢失逐切片 Git 历史
squash 合并把main上所有提交折叠成一个。缓解:
- 提交信息带切片标签(
feat(M001/S01/T01):)——可用git log --grep过滤 - 里程碑分支可以保留(不删除)以备需要历史
- 备选:用
merge --no-ff替代--squash以在main上保留历史
3.git reset后 SQLite DB 失同步
如果被跟踪的 markdown 通过git reset --hard回滚,被 gitignored 的gsd.db不会回滚。当前 GSD 在运行时把数据库视为权威,不会静默导入 markdown 投影。当数据库丢失或损坏、而 markdown 才是意图来源时,操作者应使用显式的恢复/导入命令。
4. 多工作树的磁盘占用
每个工作树都会复制工作目录(包括node_modules)。缓解:同一时间只保持一个活动里程碑(单用户工作流),完成后立即清理。
备选方案分析(Alternatives Considered)
A. 保留切片分支,用即时迷你合并修复可见性
research-slice或plan-slice后立即把切片分支合并回里程碑分支。这能修复循环检测 bug,但保留全部合并复杂度。被拒:新增一条合并路径而非移除根因,仍需要冲突解决、自愈、分支切换。
B. 保持.gsd/gitignored,对手动工作树从 Git 历史引导状态
当 GSD 在工作树中检测到空的.gsd/时,用git show <commit>:.gsd/...从分支的 Git 历史重建状态。被拒:这是恢复逻辑,不是架构。不解决分支无关状态的根本问题;Git 历史被重写时会失效。
C. 分支作用域的.gsd/目录(.gsd/branches/<branch-name>/milestones/...)
每个分支在.gsd/内的命名空间子目录中写入。被拒:增加复杂度而非移除复杂度;分支创建时需要重命名/移动目录,且与标准 Git 工具不兼容(git checkout不会重命名目录)。
验证:三方模型压力测试与 Codex 异议
该架构由三个独立模型压力测试过:
Gemini 2.5 Pro识别出 6 个攻击向量,无一击穿核心模型。建议:squash-merge 前预检 rebase(已采纳)、心跳锁(已存在)、启动时重建 DB(已通过 M001/S02 importers 采纳)。
GPT-5.4 (Codex)通读全代码库后确认模型健全,并指出smartStage()已经在 force-add 持久化路径(印证了「跟踪产物」思路),以及 PR #487 中的resolveMainWorktreeRoot在架构上是错误的(已采纳——PR 将关闭)。
代码库分析确认.gsd/milestones/尽管被.gitignore声明忽略,main上实际已被部分跟踪;GSD_DURABLE_PATHS的存在本身就是代码层面对「规划产物应当被跟踪」的承认;README 也已记录了正确的「仅运行时忽略」模式。
Codex 异议与逐条回应
异议 1:「切片完成后、集成前崩溃——今天运行时能检测孤儿切片分支并合并它们。」回应:无分支模型下没有可崩溃的集成步骤。切片工作直接提交在里程碑分支上,重启时deriveState()按原样读取分支状态。孤儿分支恢复路径的存在仅仅是因为切片分支——移除分支就移除了它要恢复的故障模式。
异议 2:「两个终端并发编辑共享根文档(PROJECT.md、DECISIONS.md)。」回应:有效的边缘情况。如果/gsd queue在main上编辑DECISIONS.md,同时 auto 模式在工作树中编辑它,squash-merge 时会有内容冲突。这是标准的 Git 内容冲突——与两个开发者编辑同一文件无异,交给常规合并解决处理。既不是切片分支导致的,也不能靠切片分支解决。
异议 3:「切片→里程碑合并提供了持续集成。移除它们会把冲突发现推迟到最后。」回应:在单用户顺序工作流中,工作树内没有东西需要集成——每个切片都构建在前一个之上。唯一冲突源是main分叉(例如另一个里程碑先合并),而切片→里程碑合并本来就抓不到这种冲突——它在工作树内合并,不是对main合并。squash-merge 前的预检 rebase 能更直接地捕获它。
异议 4:「用另一个显式的切片边界原语替代切片分支,而不是直接删除。」回应:精神上接受。带规范标签的提交(feat(M001/S01):、feat(M001/S01/T01):)就是切片边界原语;git log --grep="M001/S01"可隔离切片历史;git revert可定位特定提交;Git 标签(gsd/M001/S01-complete)可在需要时标记切片完成。边界原语是提交元数据,而不是分支。
行动清单回顾
- 关闭 PR #487(
resolveMainWorktreeRoot)——与该架构矛盾 - 作为一个带阶段的 GSD 里程碑实施:
- 更新
.gitignore并 force-add 既有规划产物 - 移除切片分支的创建/切换/合并代码
- 简化
mergeMilestoneToMain()与smartStage() - 移除
fix-merge分派单元 - 移除分支模式隔离(
git.isolation: "branch") - 更新/删除 11 个测试文件
- 更新 README 建议的 gitignore
- 为既有切片分支项目提供迁移路径
- 更新
取代与演进:ADR-001 的历史坐标
阅读本 ADR 必须注意其状态栏:Superseded(2026-05-08 被取代)。替代它的不是单一文档,而是一个「三胞胎 + 一」的决策簇:
- ADR-016-worktree-lifecycle-and-projection.md:把工作树处理拆成「生命周期」与「状态投影」两个模块,用
WorktreeLifecycle(enterMilestone/exitMilestone/restoreToProjectRoot等动词)与WorktreeStateProjection(projectRootToWorktree/projectWorktreeToRoot/finalizeProjectionForMerge)接口收拢s.basePath变更与process.chdir纪律,并把WorktreeResolver的 28 字段依赖接口退役 - ADR-016-worktree-safety-fail-closed.md:工作树状态的 fail-closed 校验
- ADR-016-worktree-lifecycle-and-projection 的 phase-2 设计
- ADR-017-state-reconciliation-drift-driven.md:漂移驱动的状态调和
取代的核心原因是问题定义变了:ADR-001 的原始动机(.gsd/合并冲突、规划产物可见性)被DB 权威运行时模型取代——项目根数据库(.gsd/gsd.db)成为权威,markdown 文件成为投影(projection),跨分支状态互相覆盖不再是该 ADR 试图修复的故障模式。这一点在源码中有明确印记:auto.ts 标注「DB status is the authoritative」、auto-recovery.ts 对execute-task/complete-slice以 DB 状态为权威;同时 query-tools.ts 提供「flush SQLite WAL 后再git add .gsd/gsd.db」的工具,说明gsd.db在部分路径下也会被提交。
剩余的与工作树相关的关切(生命周期归属、fail-closed 源码写入、漂移修复)由ADR-014(Auto Orchestration 深度模块)、ADR-015(运行时不变性模块)、ADR-016 三件套与 ADR-017 分别收敛。同时里程碑工作树内的切片分支被保留了下来——ADR-016 的 carve-out 清单中仍可见mergeSliceToMain(当前实现于 slice-cadence.ts,由git.collapse_cadence: "slice"配置驱动,#4765)等合并原语,说明「每切片即时合并回 main」的片节奏(slice-cadence)模式在现行版本中成为可选项。
一句话概括这个演进:ADR-001 的诊断(切片分支是复杂度的源头)和药方(更简单的合并面、更清晰的.gsd/归属、用提交元数据做切片边界)大部分被继承;但它的主攻方向——把规划产物变成被跟踪的 Git 状态——被「SQLite 数据库权威 + markdown 投影」的新模型取代,后者成为当前仓库处理自治编码状态的根本范式。因此本文第一部分的历史分析(§Decision 之前的全部内容)保留作上下文参考,而 §Decision 中的决策未被原样采纳。
延伸阅读
- PRD-branchless-worktree-architecture.md:该架构的产品需求文档,补充动机与验收标准
- ADR-016-worktree-lifecycle-and-projection.md:工作树生命周期与状态投影模块拆分(直接继任者)
- ADR-017-state-reconciliation-drift-driven.md:漂移驱动的状态调和
- ADR-002-external-state-directory.md:外部状态目录设计,理解
.gsd/归属争论的姊妹决策 - 核心实现:git-service.ts、auto-worktree.ts、gitignore.ts
- 关键测试:auto-worktree-milestone-merge.test.ts、gitignore-staging-2570.test.ts、git-service.test.ts(其中对
RUNTIME_EXCLUSION_PATHS的断言直接检验了「运行时路径永不入库」这一不变性)
- 人工智能
- AI Agent
- 代码智能体
- Agent 编排
- CLI
- AI 应用
【免费下载链接】gsd-2
A powerful meta-prompting, context engineering and spec-driven development system that enables agents to work for long periods of time autonomously without losing track of the big picture
相关推荐
GSD 无分支 Worktree 架构 PRD 全解析:从 slice 分支模型到单分支顺序提交的演进设计
GSD 无分支 Worktree 架构 PRD 全解析:从 slice 分支模型到单分支顺序提交的演进设计 本文围绕 docs/dev/PRD branchle
人工智能AI Agent代码智能体Agent 编排CLIAI 应用【亲测免费】 探索 Git 的无分支工作流:git-branchless
探索 Git 的无分支工作流:git branchless 项目介绍 git branchless 是一个增强 Git 工作流的工具套件,旨在使 Git 的使用
开发工具CWLateralSlide手势冲突解决方案:完美处理TableView侧滑删除问题
CWLateralSlide手势冲突解决方案:完美处理TableView侧滑删除问题 在iOS开发中,实现侧滑抽屉功能时经常会遇到与TableView原生侧滑删
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考