news 2026/9/25 1:16:13

gsd-core 将 RETROSPECTIVE.md 登记为 Canonical Artifact:彻底消除 gsd-health W019 误报

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
gsd-core 将 RETROSPECTIVE.md 登记为 Canonical Artifact:彻底消除 gsd-health W019 误报

【免费下载链接】gsd-core

Git. Ship. Done - Core

项目地址:https://gitcode.com/gh_mirrors/ge/gsd-core
点击查看免费下载

导读

本文围绕 gsd-core 仓库中一次针对健康诊断规则 W019 的修复展开:RETROSPECTIVE.md被正式写入CANONICAL_EXACT注册表(位于 src/artifacts.cts),使得gsd-health(底层为validate health)不再将其标记为「未识别的.planning/根文件」并抛出 W019 告警。读完本文,你将理解 GSD 的 canonical artifact 注册机制、W019 规则的判定逻辑、RETROSPECTIVE.md作为/gsd-complete-milestone活文档的产生与消费链路,以及如何用测试固化这类注册变更。

1. 修复背景:W019 的误报问题

.changeset/archived/3198-retrospective-canonical.md记录的变更中,一行描述点名了两个核心事实:

  1. gsd-health曾对RETROSPECTIVE.md抛出 W019「未识别文件」告警;
  2. 修复方式是把它注册进CANONICAL_EXACT,与它作为/gsd-complete-milestone产出活文档(living artifact)的既有地位对齐。

W019 属于健康诊断规则组「Milestone archive + root hygiene」,与 W018 同组,定义在 src/health-diagnostic-rules/milestone-archive-hygiene.cts。该规则的职责是:遍历.planning/根目录下的所有.md文件,凡是不在 canonical 工件清单之内的,一律发出 W019 告警,并附带修复建议:

Unrecognized .planning/ file: {filename} — not a canonical GSD artifact建议:「Move to .planning/milestones/ archive subdir or delete if stale. See templates/README.md for the canonical artifact list.」

问题在于:RETROSPECTIVE.md/gsd-complete-milestone在每次里程碑收尾时正式产出并持续维护的文档,但它此前并不在CANONICAL_EXACT集合里,于是每次运行健康检查都会收到一条「请归档或删除」的错误建议——明明该文件是工作流主动创建的,却被告知它不是规范工件,属于典型的自产文件误报。

2. 核心机制:Canonical Artifact 注册表

2.1CANONICAL_EXACT:精确匹配清单

修复落点位于 src/artifacts.cts 的CANONICAL_EXACT集合。该文件头部注释明确说明其定位:

Enumerates the file names that gsd workflows officially produce at the .planning/ root level. Used by gsd-health (W019) to flag unrecognized files so stale or misnamed artifacts don't silently mislead agents or reviewers. Add entries here whenever a new workflow produces a .planning/ root file.

注册表分为两套匹配规则:

精确匹配(CANONICAL_EXACT——目前包含 16 个条目:

文件名产出方 / 说明
PROJECT.md/gsd:new-project,项目身份与目标
ROADMAP.md/gsd:new-milestone/gsd:new-project
STATE.md/gsd:new-projectgsd-health --repair
REQUIREMENTS.md/gsd:new-milestone
MILESTONES.md/gsd:complete-milestone
BACKLOG.md/gsd-add-backlog
LEARNINGS.md/gsd:extract-learnings
THREADS.md/gsd:thread
config.json/gsd:new-project
CLAUDE.md/gsd-profile自动组装
RETROSPECTIVE.md/gsd:complete-milestone(本次修复新增语义)
WINDOWS.mdbroken-windows ledger(src/broken-windows.cts,#3224)
STATE-ARCHIVE.mdstate.ctscmdStatePrune
milestone.locksrc/milestone-lock.cts(#3311)
state.jsonsrc/state-contract.cts步骤边界发布(#3227)
skill-manifest.jsoninit.ctscmdSkillManifest --write(#3964)
PATTERNS.md跨阶段模式沉淀(#4282),区别于阶段内NN-PATTERNS.md

注意RETROSPECTIVE.md在源码中位于第 26 行,紧邻CLAUDE.mdWINDOWS.md之间,正是本次 changeset(PR 3200)所引入的登记。

模式匹配(CANONICAL_PATTERNS——针对带版本戳的文件名:

/^v\d+\.\d+(?:\.\d+)?-MILESTONE-AUDIT\.md$/i, // gsd-complete-milestone (pre-archive) /^v\d+\.\d+(?:\.\d+)?-.*\.md$/i, // other version-stamped planning docs

2.2 判定函数:isCanonicalPlanningFile

注册表的唯一消费入口是isCanonicalPlanningFile(filename)(src/artifacts.cts),它按「先精确、后正则」的顺序判定:

export function isCanonicalPlanningFile(filename: string): boolean { if (CANONICAL_EXACT.has(filename)) return true; for (const pattern of CANONICAL_PATTERNS) { if (pattern.test(filename)) return true; } return false; }

三个关键约束值得注意:

  • 只接受 basename:调用方传入的是不带路径的文件名,路径处理在上层完成;
  • 大小写敏感RETROSPECTIVE.md合法,而retrospective.mdRETROSPECTIVE.MD均会被拒绝(测试中有state.mdfalse的用例佐证);
  • 空串与无关文件返回false:保证 W019 对任何未登记文件照常触发。

3. W019 规则的实现链路

W019 的检查函数checkW019位于 src/health-diagnostic-rules/milestone-archive-hygiene.cts,实现逻辑清晰:

function checkW019(snapshot: PlanningSnapshot): Diagnostic[] { const diagnostics: Diagnostic[] = []; for (const filename of snapshot.planningRootFiles.value) { if (!filename.endsWith('.md')) continue; if (isCanonicalPlanningFile(filename)) continue; diagnostics.push({ code: 'W019', severity: SEVERITY.WARNING, message: `Unrecognized .planning/ file: ${filename} — not a canonical GSD artifact`, remedy: adviseRemedy( 'Move to .planning/milestones/ archive subdir or delete if stale. See templates/README.md for the canonical artifact list.', ), }); } return diagnostics; }

从实现可以提炼出几条明确的规则语义:

  • 只检查.planning/根目录:文件清单来自 planning snapshot 的planningRootFiles,阶段子目录(.planning/phases/NN-name/)内的文件不在检查范围;
  • 每个未识别文件产生一条独立告警:与 W018 的聚合式报告不同,W019 是「一文件一告警」,测试中两个杂散文件会产生两条 W019 即为此意;
  • 非自动修复(repairable: false:规则表(同文件第 98-113 行)中 W019 明确标注repairable: false,健康检查的--repair不会自动移动或删除文件,需要人工依据建议处理。

该文件头部还注明了来源:规则从cmdValidateHealth(原src/verify.cts)行为保持地移植而来,并遵循 ADR-457「build-at-publish」策略——源码是src/health-diagnostic-rules/milestone-archive-hygiene.cts,编译产物为 gitignored 的bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs

4. RETROSPECTIVE.md 的生产与消费:为什么它必须是 canonical

要理解本次修复的必要性,需要看清RETROSPECTIVE.md在完整里程碑收尾工作流中的角色。

4.1 模板:活文档的结构

模板位于 gsd-core/templates/retrospective.md,开篇即声明其定位:

A living document updated after each milestone. Lessons feed forward into future planning.

模板包含两大板块:

  • 单里程碑板块## Milestone: v{version} — {name},内含 Shipped/Phases/Plans/Sessions 元信息,以及What Was BuiltWhat WorkedWhat Was InefficientPatterns EstablishedKey LessonsCost Observations六个小节;
  • 跨里程碑趋势板块## Cross-Milestone Trends,用表格沉淀Process EvolutionCumulative QualityTop Lessons (Verified Across Milestones)

4.2 工作流:每次收尾都会写入

在 gsd-core/workflows/complete-milestone.md 的write_retrospective步骤中,流程完整定义了该文件的维护方式:

  1. 探测ls .planning/RETROSPECTIVE.md 2>/dev/null || true检查文件是否存在;
  2. 分支处理:已存在则读取并在## Cross-Milestone Trends之前追加新里程碑板块;不存在则从模板retrospective.md创建;
  3. 数据采集:从SUMMARY.md提取交付物、从VERIFICATION.md提取验证分数与缺口、从UAT.md提取测试结果、从 git log 统计提交与时间线,再结合里程碑过程反思;
  4. 提交gsd_run query commit "docs: update retrospective for v${VERSION}" --files .planning/RETROSPECTIVE.md,将更新固化到 git 历史。

同工作流的 checklist(第 727 行)也把RETROSPECTIVE.md updated with milestone section列为收尾必检项。这意味着:只要完整执行过/gsd-complete-milestone.planning/RETROSPECTIVE.md就必然存在——它既不是临时草稿,也不是残留杂物,而是一个被工作流持续维护的规范产物。

4.3 消费:里程碑总结的输入源

在 gsd-core/workflows/milestone-summary.md 中,RETROSPECTIVE.md被列为「Always available」的三个路径之一(与PROJECT.mdSTATE.md并列),其 lessons learned 是生成里程碑总结时「what to improve」部分的内容来源。此外 gsd-core/workflows/help/modes/full.md 在.planning/目录速览里也将其标注为 "Living retrospective (updated per milestone)"。

至此结论闭环:一个被工作流主动创建、每次收尾持续更新、被其他工作流当作权威输入读取的文档,理应属于 canonical artifact 清单。此前它不在CANONICAL_EXACT中,导致gsd-health给出「请归档或删除」的误导性建议——这正是本次 changeset 修复的实质。

5. 修复的验证:测试与文档联动

5.1 注册表单元测试

tests/artifacts.test.cjs 集中覆盖了注册表行为,其中对同类误报修复的回归用例提供了先例参照(如 #3227 的state.json、#3224 的WINDOWS.md、#4282 的PATTERNS.md),其模式完全适用于RETROSPECTIVE.md

  • 断言CANONICAL_EXACT.has('RETROSPECTIVE.md')为真;
  • 断言isCanonicalPlanningFile('RETROSPECTIVE.md')返回true
  • 断言isCanonicalPlanningFile('random-file.md')仍返回false(W019 的兜底能力不受影响)。

5.2 W019 集成测试

同一文件的gsd-health W019 — unrecognized .planning/ root files分组(第 187 行起)通过临时项目夹具验证了完整行为矩阵:

  • .planning/MY-NOTES.md→ 触发一条 W019,消息包含文件名,repairable === false
  • 仅标准BASE_FILES→ 无 W019;
  • 版本戳文件v1.0-MILESTONE-AUDIT.md→ 无 W019(命中CANONICAL_PATTERNS);
  • 阶段子目录文件 → 无 W019(根目录外不检查);
  • 两个杂散文件 → 产生两条 W019(一文件一告警)。

对应规则单测位于 tests/health-diagnostic-rules/milestone-archive-hygiene.test.cjs,明确标注其来源为 Phase 11、#3309、ADR-3180 §8.2/§8.3/§8.5。

5.3 权威清单文档同步

gsd-core/templates/README.md 是该机制的权威索引,开篇即声明:

if a.planning/root file is not listed here,gsd-healthwill flag it as W019 (unrecognized artifact).

其根工件表格第 25 行已列出RETROSPECTIVE.md,来源列标注为/gsd:complete-milestone,用途为 "Living milestone retrospective updated at each milestone close"。由于 W019 的修复建议文本会指引用户「See templates/README.md for the canonical artifact list」,文档、注册表、规则三者必须保持一致——本次变更正是这种一致性的又一次落地。同时第 45、66 行分别说明:阶段子目录文件与归档到.planning/milestones/的文件永远不会被 W019 检查。

6. 实践指引

6.1 运行健康检查观察效果

在项目根目录执行:

gsd-health

修复前:若.planning/根目录存在RETROSPECTIVE.md,会收到W019 — Unrecognized .planning/ file: RETROSPECTIVE.md告警及「归档或删除」的建议。修复后:该文件命中CANONICAL_EXACT,不再产生任何告警;而未登记的文件(如MY-NOTES.mdscratch.md)仍会被正常标记。

6.2 新增根工件时的正确姿势

参照src/artifacts.cts头部注释的指引,任何新工作流若要在.planning/根目录产出文件,应完成三件事:

  1. 注册:将文件名加入CANONICAL_EXACT(或符合语义时加入CANONICAL_PATTERNS);
  2. 文档化:在 gsd-core/templates/README.md 的根工件表格中登记产出方与用途;
  3. 测试固化:在 tests/artifacts.test.cjs 增加「注册表包含 + 判定为 canonical」的回归用例,并视需要在 W019 集成测试中补充「不误报」用例。

6.3 边界行为速查

场景W019 行为
.planning/RETROSPECTIVE.md(本次修复)不告警
.planning/PROJECT.md等精确匹配项不告警
.planning/v1.2.0-MILESTONE-AUDIT.md不告警(正则匹配)
.planning/phases/01-foundation/01-01-PLAN.md不告警(仅查根目录)
.planning/milestones/归档文件不告警(归档目录豁免)
.planning/scratch.md等未登记文件告警,且不可自动修复
大小写变体(如retrospective.md告警(精确匹配区分大小写)

7. 小结

本次 changeset(PR 3200)是一次典型而精准的「注册表遗漏」修复:RETROSPECTIVE.md作为/gsd-complete-milestone持续维护的活文档,其 canonical 地位此前只体现在工作流与文档层面,却未同步到 src/artifacts.cts 的CANONICAL_EXACT,导致gsd-health的 W019 规则对它误报。修复后,注册表、W019 判定、模板 README 权威清单三者达成一致,规则仍保留对真正杂散文件的告警能力。这一模式(注册 → 文档化 → 测试固化)为 gsd-core 中所有根级工件的管理提供了可复制的范本。

【免费下载链接】gsd-core

Git. Ship. Done - Core

项目地址:https://gitcode.com/gh_mirrors/ge/gsd-core
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 1:15:55

AT32单片机实战开发:环境搭建、外设驱动与产线级问题排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:15:25

边缘AI芯片选型:从场景需求反推算力匹配

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:13:33

STM32开源项目实战:代码、原理图与仿真三件套完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:13:29

PLCSIM Advanced与WinCC仿真连接6大陷阱,工程师必看

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:13:24

JESD204C 32Gb/s物理层实现核心挑战与工程落地要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:12:10

反激电源VDS尖峰根治:TVS管选型与实测,从732V降到508V

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华