get-shit-done Changeset 实战:解析 sunny-ibex-wave 片段与 gsd-intel-updater 布局检测门控修复(3290)
在 get-shit-done(GSD)仓库中,.changeset/ 目录下的每个 Markdown 片段都是"每 PR 一条 CHANGELOG"机制的最小单元,用于避免多个 PR 同时编辑 CHANGELOG.md 产生合并冲突。本文以真实存在的片段 .changeset/sunny-ibex-wave.md 为主体,拆解它的 frontmatter 格式与成文规范,并顺着它记录的修复内容深入源码:gsd-intel-updater 智能体中那段"运行时布局检测"bash 块,是如何被门控在"当前项目就是 GSD 框架自身仓库"这一前置条件之下的。读完本文,你将能读懂并校验一个 changeset 片段,并理解这类"死代码但吵闹"(dead-but-noisy)提示行的定位、修复与回归测试设计方法。
一、Changeset 片段的完整格式与生成方式
先给出被分析对象的全文(.changeset/sunny-ibex-wave.md):
---
type: Removed
pr: 3299
---
**`gsd-intel-updater` no longer emits a vestigial "Layout detection returned 'unknown'" line on non-GSD-framework projects** — the layout-detection bash block is now gated on a positive framework-repo check (package.json name = "get-shit-done-cc"), so ordinary user projects skip the step silently.
它由两部分构成:
| 组成 | 取值 | 说明 |
|---|---|---|
type |
Removed |
允许值遵循 Keep a Changelog 约定:Added、Changed、Deprecated、Removed、Fixed、Security(见 .changeset/README.md) |
pr |
3299 |
关联 PR 编号,用于溯源 |
| 正文 | 一句话 | 以加粗命令/符号名开头,说明用户可见的行为变化 |
之所以采用"每 PR 一个独立文件"而非直接改 CHANGELOG.md,.changeset/README.md 给出的理由是:两个 PR 同时编辑 ### Fixed 区块必然冲突,而各自新增一个唯一命名的 .changeset/<unique-name>.md 则互不共享行、永不冲突。片段文件名的 <形容词>-<名词>-<名词>.md(如 sunny-ibex-wave)也是随机生成,进一步降低并发冲突概率。
标准生成方式(来自 .changeset/README.md):
node scripts/changeset/new.cjs \
--type Fixed \
--pr 1234 \
--body "fix the thing — explain the user-visible change in one sentence"
对无用户可见影响的 PR,可用 no-changelog 标签豁免;拿不准时宁可加片段。
二、缺陷背景:gsd-intel-updater 在普通项目里的"幽灵输出"
片段正文里的 gsd-intel-updater 是 GSD 的代码库情报智能体,其指令定义在 agents/gsd-intel-updater.md。它的职责是读取项目源码、把结构化的"情报"写入 .planning/intel/(stack.json、files.json、apis.json、deps.json、arch.md 五个文件),供其他智能体以可查询的知识库代替昂贵的全库探索读取。该智能体由 /gsd:map-codebase --query 命令派生,且上游已确认 intel.enabled 为 true 才会启动。
修复前的问题(回归测试文件头部注释给出了完整定性):gsd-intel-updater.md 中的 "Runtime layout detection" 块在每一个被分析的项目上无条件执行,对所有普通(非 GSD 框架)用户项目都会输出一行:
Layout detection returned "unknown" — this project is not a GSD-system installation (no
.claude/get-shit-done/or.kilo/runtime root).
关键在于:这个"判定结果"在后续 Step 2–6 中对非 GSD 项目本来就会被忽略,所以这段输出是"死代码但吵闹"(dead-but-noisy)——无功能价值,只污染输出。这一点由回归测试 tests/bug-3290-intel-updater-layout-block.test.cjs 的文件头注释明确记录(第 10–17 行)。
三、修复方案:正向"框架仓库"门控
修复的核心是:把布局检测 bash 块门控在正向框架仓库检查之下——仅当 package.json 的 "name" 等于 "get-shit-done-cc"(即当前项目就是 GSD 框架自身仓库,这一点可以由本仓库根目录 package.json 的 "name": "get-shit-done-cc" 印证)时才运行检测。修复后的指令块位于 agents/gsd-intel-updater.md:
# Only run layout detection when analysing the GSD framework repo itself.
if [[ "$(jq -r '.name // ""' package.json 2>/dev/null)" == "get-shit-done-cc" ]]; then
ls -d .kilo 2>/dev/null && echo "kilo" || (ls -d .claude/get-shit-done 2>/dev/null && echo "claude") || echo "unknown"
fi
指令文本同时给出行为契约(同文件第 60、71 行):
- 检测块上方注释:
<!-- Layout detection: only meaningful when analysing the GSD framework's own repo (#3290). --> - 块下方说明:
For all other projects, skip this step and proceed directly to Step 1.
即普通用户项目会静默跳过该步骤,直接进入 Step 1(目录定位),不再产生任何 "Layout detection returned 'unknown'" 行。
布局检测在做什么:两套运行布局的规范路径
门控之内的那段检测,输出三种判定:kilo、claude、unknown,用于选择"规范源位置"。agents/gsd-intel-updater.md 给出的路径对照表是:
| 资源类型 | 标准 .claude 布局 |
.kilo 布局 |
|---|---|---|
| 智能体文件 | agents/*.md |
.kilo/agents/*.md |
| 命令文件 | commands/gsd/*.md |
.kilo/command/*.md |
| CLI 工具 | get-shit-done/bin/ |
.kilo/get-shit-done/bin/ |
| 工作流文件 | get-shit-done/workflows/ |
.kilo/get-shit-done/workflows/ |
| 参考文档 | get-shit-done/references/ |
.kilo/get-shit-done/references/ |
| Hook 文件 | hooks/*.js |
.kilo/hooks/*.js |
配套规则(同文件第 84–93 行):一旦检测到 .kilo 根,就只用 .kilo 下的规范位置,不回落标准布局——因为空路径会产生"语义空"的情报文件;组件计数必须通过对布局解析后的规范位置执行 Glob 得出,而不是凭记忆。
为什么选择"门控"而非"删除"
回归测试注释中列出了两个候选方案:方案 A 是用框架仓库守卫包住检测块;方案 B 是彻底删除。测试断言的逻辑(tests/bug-3290-intel-updater-layout-block.test.cjs)也对应这两条路径:若裸检测块已被整体删除则直接通过;若块仍存在,则验证它被框架仓库门控(检查内容中出现 get-shit-done-cc 或等价守卫语义)。当前仓库选择了方案 A,因为布局检测对"分析 GSD 框架自身仓库"这一真实场景仍有价值——框架自身的源码就分布在上述两套布局中,检测判定在该场景下是有效输入而非噪声。
四、回归测试设计:缺陷签名 + 孤儿消费者双重防线
tests/bug-3290-intel-updater-layout-block.test.cjs 是该修复的行为契约测试,注意其文件头声明的立场(第 1–3 行):agents/gsd-intel-updater.md 本身就是"部署产物"——它是交付给智能体的指令集,因此断言其文本内容就是在测试部署行为契约。测试分两组:
Group A — 门控契约(第 61–111 行):用正则 /ls -d \.kilo\b.*\|\|.*echo "?unknown"?/ 提取"缺陷签名"——那个无条件执行、会输出判定的 shell 单行。若签名缺席(块已删除),通过;若签名存在,则要求文件内容中存在框架仓库守卫(get-shit-done-cc、is-this-the-framework、Only run 等语义标记之一),否则以完整的修复示例(含 if [[ "$(jq -r ... 写法)给出失败信息。
Group B — 无孤儿下游消费者(第 113–187 行):递归扫描 agents/、commands/gsd/、get-shit-done/workflows/ 三个目录的全部 Markdown 文件,断言:
- 没有任何文件包含哨兵短语
Layout detection returned(这是那行吵闹输出的指纹); - 除产生方
gsd-intel-updater.md自身外,没有任何智能体或工作流指令去消费该判定输出(模式Layout detection returned.*(unknown|claude|kilo))。
第二组的意义在于:只要存在任何下游消费者,"删除该块"就会破坏功能,只能走"门控"路线——测试甚至在其失败信息里写明 If a consumer exists, use option A (gate) not option B (remove).,把方案选择逻辑固化进了断言本身。
五、发布时的 changeset 消费流程
type: Removed 的 sunny-ibex-wave 片段在发布时会被统一消费。.changeset/README.md 给出的发布命令:
node scripts/changeset/cli.cjs render --version vX.Y.Z --date YYYY-MM-DD
该命令读取全部片段,按 type: 分组生成条目,把 ## [Unreleased] 替换为新的 ## [vX.Y.Z] - YYYY-MM-DD 区块,在其上方新开一个空的 ## [Unreleased],并删除已消费的片段文件,全程幂等。仓库中 scripts/changeset/ 目录下的 new.cjs、cli.cjs 等脚本即为该工具链的实现,相关行为由 tests/changeset-new.test.cjs、tests/changeset-render.test.cjs、tests/changeset-lint.test.cjs 等测试覆盖。
六、要点回顾
- 片段格式:frontmatter(
type+pr)+ 一句用户可见变化描述;type取 Keep a Changelog 六值之一;用node scripts/changeset/new.cjs生成,发布时由node scripts/changeset/cli.cjs render合并进 CHANGELOG(见 .changeset/README.md)。 - 本次修复:
gsd-intel-updater的布局检测 bash 块被门控在package.json name == "get-shit-done-cc"的正向检查之下,普通项目静默跳过,不再输出残留的 "Layout detection returned 'unknown'" 行(片段原文 + agents/gsd-intel-updater.md)。 - 验证方式:回归测试以"缺陷签名正则 + 守卫语义检查 + 孤儿消费者全库扫描"三层结构锁住该行为(tests/bug-3290-intel-updater-layout-block.test.cjs)。
- 适用前提:以上行为对应当前仓库
package.json中1.50.0-canary.0版本下的智能体指令集;对 GSD 框架自身仓库运行map-codebase --query时,布局检测仍会按kilo/claude两种规范布局解析源路径。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00