首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
get-shit-done `/gsd:health` 一致性检查:归档里程碑阶段引发的 W002 误报(3652)修复全解析
📅 2026/9/8 23:55:26
✍️ 爱科研究院
👁 阅读 3,247
get-shit-done/gsd:health一致性检查归档里程碑阶段引发的 W002 误报#3652修复全解析【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done导读本文围绕 get-shit-done 仓库中的变更记录 lucky-lynx-wave.md 展开深入剖析健康检查工具/gsd:health在跨里程碑演进场景下的一处经典误报缺陷issue #3652随 PR #3655 修复当一个里程碑通过/gsd:complete-milestone归档后STATE.md 正文对历史阶段的引用曾持续触发 W002 告警导致项目长期处于degraded状态。读完本文你将理解 W002/W006 校验的合法性来源、里程碑归档目录milestones/vX.Y-phases/在源码与测试中的处理方式并掌握如何通过gsd-sdk query validate.health亲手验证该修复。一、背景健康检查如何判定.planning/的“阶段引用合法性”get-shit-done简称 gsd是一个面向 Claude Code 的轻量级元提示meta-prompting、上下文工程与规范驱动开发spec-driven development系统。它的核心工程工件集中在项目根目录的.planning/下PROJECT.md、ROADMAP.md、STATE.md、config.json以及按NN-name规范命名的阶段目录如01-setup。/gsd:health是用于诊断这一套目录结构完整性的斜杠命令其入口定义在 health.md实际流程委托给 health.md。工作流最终通过 SDK 查询接口执行底层诊断gsd-sdk query validate.health [--repair] [--backfill]输出为 JSON包含字段含义statushealthy/degraded/broken三态errors[]严重问题含code、message、fix、repairablewarnings[]非严重告警如 W002info[]信息性提示repairable_count可自动修复的问题数repairs_performed[]--repair模式下实际执行的动作状态判定逻辑非常直观见 validate.ts只要存在任意errors即为broken若没有错误但存在warnings则为degraded两者皆空才是healthy。这意味着任何一条本不该出现的告警都会让项目长期停留在degraded状态——这正是 #3652 缺陷影响如此显著的直接原因。二、W002 的判定规则STATE.md 中的阶段引用需要“来源背书”W002 属于健康检查中的 Check 4STATE.md exists and references valid phases。它从 STATE.md 全文中用正则抽取所有阶段引用/[Pp]hase\s(\d[A-Z]?(?:\.\d)*)/g也就是说STATE.md 的叙述性正文里只要出现Phase 19 shipped、Decision from Phase 12这类文字都会被视为一条“被引用的阶段号”并与一个**合法阶段集合validPhases**做比对。凡是不在集合内、且非前导零变体如03可等价于3的引用就会输出[W002] STATE.md references phase N, but only phases ... are declared这里的关键是validPhases由哪些来源构成。在本修复之前该集合由两部分并集组成磁盘上的活跃阶段目录即.planning/phases/下所有目录通过PHASE_TOKEN_FROM_DIR_RE抽取阶段号ROADMAP.md 中声明过的所有阶段标题用/#{2,4}\s*Phase\s(\d[A-Z]?(?:\.\d)*)\s*:/gi扫描全文件这一“以 ROADMAP 为阶段权威”的设计源于更早的 bug #2633 修复见 validate.test.ts 中的回归说明。三、缺陷复现跨里程碑归档后历史阶段引用“无处安放”项目的里程碑演进遵循固定的生命周期当一个里程碑收尾后/gsd:complete-milestone命令见 complete-milestone.md会把该里程碑的阶段目录整体搬移到归档路径.planning/ ├── phases/ # 当前里程碑的扁平阶段目录 │ └── 23-current/ └── milestones/ ├── v1.3a-phases/ # 归档里程碑 A │ └── 12-old-phase/ └── v1.3b-phases/ # 归档里程碑 B ├── 19-alpha/ ├── 20-beta/ └── ...与此同时ROADMAP.md 中已发布里程碑的#### Phase N:标题会被折叠进details折叠块甚至改写为- Phase 12: archived这种列表条目而不再是可被标题正则匹配的标题格式。问题随之而来STATE.md 的正文叙事段## Recent、## Decisions、## Deferred Items天然会保留跨里程碑的历史叙述——例如## Decisions里写着 “Decision from Phase 12 still applies”。而validPhases的两个来源此时都失效了磁盘扫描只看.planning/phases/活跃目录看不到已搬进milestones/v1.3a-phases/的12-old-phaseROADMAP 标题扫描匹配不到被折叠进details、或被改写成列表项的历史阶段。于是每提到一个历史阶段号就产生一条 W002而告警噪音会随着项目生命周期内累计的阶段总数线性增长——里程碑归档得越多degraded越成为常态。四、修复方案把“里程碑归档目录”并集进合法阶段集变更记录PR #3655给出的修复思路非常直接在 Check 4 的validPhases计算中额外并集所有里程碑归档目录下出现的阶段从而对 W002 也生效——此前的 W006ROADMAP 阶段在磁盘上找不到目录已经做过类似的归档回溯。实现上两条实现路径都新增/复用了同一个辅助函数forEachArchivedPhaseToken。以 SDK 端的 validate.ts 为例它先列出所有归档目录再逐个抽取其中的阶段号并回调// Check 4 (W002) 新增的归档并集任何 milestones/vX.Y-phases/ 下 // 的阶段目录都算合法阶段来源Bug #3652 await forEachArchivedPhaseToken(planBase, (token) validPhases.add(token));配合注释明确写道归档后#### Phase N:标题被折叠磁盘活跃阶段目录与 ROADMAP 标题扫描都覆盖不到因此需要把归档目录中的阶段目录视为合法位置。CJS 运行时端cmdValidateHealth位于 verify.cjs也做了完全对应的并集操作两条实现保持端口级对等port parity。归档阶段令牌如何抽取forEachArchivedPhaseToken的实现async function forEachArchivedPhaseToken( planBase: string, onPhase: (token: string) void, ): Promisevoid { for (const archiveDir of await listMilestoneArchiveDirs(planBase)) { try { const entries await readdir(archiveDir, { withFileTypes: true }); for (const e of entries) { if (!e.isDirectory()) continue; const m e.name.match(PHASE_TOKEN_FROM_DIR_RE); if (m) onPhase(m[1]); } } catch { /* archive dir absent/unreadable */ } } }listMilestoneArchiveDirs负责发现归档目录它列出.planning/milestones/下匹配MILESTONE_ARCHIVE_DIR_RE的子目录并按版本号做数值排序保证v1.10排在v1.2之后而非字典序排在前面。五、两个共享正则归档目录识别与项目代码前缀剥离修复的另一个关键点是强调对既有共享常量的复用而不是在 Check 4 里新写一套临时正则const PHASE_TOKEN_FROM_DIR_RE /^(?:[A-Z]{1,6}-)?(\d[A-Z]?(?:\.\d)*)(?:-|$)/i; const MILESTONE_ARCHIVE_DIR_RE /^v\d.*-phases$/i;常量用途匹配示例PHASE_TOKEN_FROM_DIR_RE从阶段目录名中剥离可选的项目代码前缀并抽出阶段令牌64-current→6464A-...→64A64.1-...→64.1CK-64-foo→64MILESTONE_ARCHIVE_DIR_RE识别归档里程碑目录v1.3a-phases、v2.0-phases项目代码前缀project-code prefix是这套系统里常见的命名约定例如某项目采用CK-64-prior-shipped这样的目录名CK-是项目代号真正的阶段号是64。旧实现如果临时用/^\d/-风格的正则去扫归档目录就会漏掉CK-64-...这类目录重新引入误报。因此在代码注释与回归测试中都强调了W002 与 W006 必须共享同一套常量防止 W006 原有的归档扫描在修改中退化为 ad-hoc 正则详见 validate.test.ts 的 #3652 用例说明。此外校验对阶段号的归一化仍然保留了历史宽容度整数前缀允许前导零03↔3、03.1↔3.1但带字母后缀的令牌如3A必须精确匹配、绝不折叠为3以免把不同阶段误判为同一个。六、W006/W007 的一致性闭环归档不仅是 W002 的“补丁”值得说明的是归档目录回溯在这套校验体系里是一以贯之的设计原则而非 W002 的专属补丁W006Phase N in ROADMAP.md but no directory on diskCheck 8很早就已把归档里程碑阶段目录并入diskPhases用于覆盖 ROADMAP 中指向历史已归档阶段的标题validate.test.ts 中的 #3473 回归用例对此有覆盖。W007磁盘存在但 ROADMAP 未声明的阶段则反向处理只对“活跃”磁盘阶段发告警避免归档阶段目录触发 W007对应 #3560。一致性检查处理器validateConsistency同样位于 validate.ts通过collectPhaseRoots同时把扁平.planning/phases/与“当前里程碑归档目录”由getActiveMilestoneArchiveDir依据 STATE.md 的 milestone 字段解析回退到版本号最高的归档都作为合法阶段根进行扫描。#3652 的修复只是把这条原则真正补全到了Check 4W002上使两条检查路径对归档阶段的认知完全对齐。七、回归测试两种典型归档形态都被覆盖本修复在 validate.test.ts 中有完整的回归测试构造了两个高度贴近真实场景的夹具用例一多个历史归档的 STATE.md 正文引用不再告警。测试创建活跃阶段23-current同时创建v1.3a-phases/12-old-phase与v1.3b-phases/19..22等归档目录ROADMAP 中历史里程碑被折叠进details并写成- Phase 12: archived列表项STATE.md 的## Recent/## Decisions/## Deferred Items分别引用 Phase 19、12、19。断言结果为 W002 列表为空。用例二项目代码前缀归档目录的识别。测试创建CK-65-current活跃与v2.0-phases/CK-64-prior-shipped归档ROADMAP 的details内保留#### Phase 64: Prior shipped标题STATE.md 记录- Phase 64 shipped。断言既不触发 W002也不触发指向 Phase 64 的 W006——证明归档扫描确实沿用了共享正则成功剥离了CK-前缀。这两个用例从“纯叙述引用”和“前缀命名 标题共存”两个维度锁死了 W002 误报的回归路径。八、实操验证如何确认你的项目处于修复后的行为无论你是想复现旧缺陷还是验证当前 SDK 行为都可以直接在项目根目录执行两种入口等价SDK 查询是现代实现# 无修复参数的完整健康诊断 gsd-sdk query validate.health # 若此前暴露过 W002 噪音确认它来自归档阶段而非真实问题 gsd-sdk query validate.health --repair # 仅修复可安全自动修复项输出解读要点关注status是否为healthy无degraded/broken若仍存在 W002检查message中的阶段号如果该阶段号确实存在于某个.planning/milestones/vX.Y-phases/目录下则说明运行的是修复前的旧版本 SDK构造与回归测试相同的目录形态在milestones/下手工放置一个vX.Y-phases/phase-...目录即可做一次“最小可复现验证”。对历史遗留噪音项目运行修复后的/gsd:health应当能一次性清除所有由归档阶段产生的 W002将状态从长期degraded恢复为healthy。注意W002 属于不可自动修复项见 health.md 的错误码表其建议动作为人工 Review STATE.md真正的解决之道就是让校验器正确认识归档阶段这正是 #3655 所完成的。九、总结把“归档”当作一等公民校验才不会误伤历史从 #2633以 ROADMAP 为阶段权威到 #3473/#3560W006/W007 对归档目录的识别再到 #3652/#3655W002 补全归档并集get-shit-done 的健康检查走过了一条清晰的演进路径STATE.md 是带历史包袱的“活文档”任何把“磁盘现状”误当“全部合法状态”的校验都会在里程碑归档后产生系统性误报。修复的关键不是简单放宽校验而是建立统一的“归档阶段目录”来源共享PHASE_TOKEN_FROM_DIR_RE/MILESTONE_ARCHIVE_DIR_RE常量 forEachArchivedPhaseToken遍历原语并让 W002 与 W006 在两侧实现TypeScript SDK 与 CJS 运行时共享同一套认知。对开发者而言这条修复同时提供了一个可复用的工程范式当你为“历史数据”编写一致性校验时应当先回答——历史数据在归档后的权威载体是什么再把它们显式并集进合法域而不是反复豁免特例。相关参考文件变更记录 lucky-lynx-wave.md、健康命令 health.md、工作流 health.md、SDK 实现 validate.ts、CJS 对等实现 verify.cjs、回归测试 validate.test.ts。【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/9/8 23:55:26
opencode终端AI编码代理:从安装配置到Skills与LSP进阶实战
2026/9/8 23:50:26
MATLAB图像处理实战:菌落自动计数与分割算法详解
2026/9/8 23:50:26
ip2region 完整指南:3 步搞定离线 IP 定位到城市级
2026/9/9 0:30:29
8051外部ROM/RAM扩展实战:Proteus仿真与Keil C51编程
2026/9/9 0:30:29
FPGA培训避坑指南:四把硬尺子筛选真工程能力
2026/9/9 0:30:29
STM32F4步进电机控制指南:从CubeMX配置到梯形加减速实战
2026/9/9 0:30:29
硬件工程师技能清单:从理论到实践的全链路学习路线
2026/9/9 0:30:29
网上作业批改系统JavaWeb项目全解析:从设计到部署避坑指南
2026/9/9 0:25:28
[数字安全]网络安全框架与监管标准全面解读:从合规到韧性的实战价值分析
2026/9/9 0:00:26
MHS模型硬件标准:让大模型像调用软件一样控制物理设备
2026/9/9 0:00:27
AI五大核心方向详解:从机器学习到大模型,零基础转行选哪条?
2026/9/9 0:00:27
从50行最小循环到生产级AI引擎:工程化改造全解析
2026/9/8 0:43:11
超人会飞不算本事:系统稳定依赖清晰规则与边界设计
2026/9/8 1:13:27
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
2026/9/8 2:18:22
基于CNN的调制信号识别:MATLAB实现时频图分类实战