fix(#3224): register WINDOWS.md as a canonical .planning/ artifact (#3369)

* test(#3224): assert WINDOWS.md is a canonical .planning/ artifact

The broken-windows ledger (.planning/WINDOWS.md, written by gsd-core's own
windows command) was absent from CANONICAL_EXACT, so validate health flagged
it W019 'Unrecognized' with advice to delete a file that can gate /gsd-ship.
Add WINDOWS.md to the expected-canonical list + a dedicated predicate test.

RED — fails on next; fix follows.

* fix(#3224): register WINDOWS.md as a canonical .planning/ artifact

CANONICAL_EXACT (src/artifacts.cts) was never updated when the broken-windows
capability (#1950/#2441) started writing .planning/WINDOWS.md. validate health
therefore flagged the ledger W019 'Unrecognized' with fix advice to archive or
delete it — a file gsd-core itself produces (src/broken-windows.cts,
LEDGER_FILE_NAME) and that can gate /gsd-ship under workflow.windows_enforce.

Add WINDOWS.md to CANONICAL_EXACT, per the registry header's own maintenance
mandate ('Add entries here whenever a new workflow produces a .planning/ root
file'). isCanonicalPlanningFile now returns true for it, suppressing the false
W019. Existing W019 behavior for genuinely-unrecognized files is unchanged.

* chore(#3224): add changeset fragment

* chore(#3224): backfill changeset PR number (#3369)

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-11 20:06:23 -04:00
committed by GitHub
parent bfd749cb9a
commit 62f5f3b39e
3 changed files with 16 additions and 1 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 3369
---
**`gsd-tools validate health` no longer flags `.planning/WINDOWS.md` as an unrecognized file** — the broken-windows ledger that gsd-core's own `windows` command writes is now registered as a canonical `.planning/` artifact. Previously the W019 warning advised archiving or deleting a file that, with `workflow.windows_enforce` on, gates `/gsd-ship`. (#3224)

View File

@@ -24,6 +24,7 @@ export const CANONICAL_EXACT: ReadonlySet<string> = new Set([
'config.json',
'CLAUDE.md',
'RETROSPECTIVE.md',
'WINDOWS.md', // #3224: broken-windows ledger (src/broken-windows.cts, LEDGER_FILE_NAME)
]);
// Pattern-match canonical file names (regex tests on the basename)

View File

@@ -23,7 +23,7 @@ describe('CANONICAL_EXACT', () => {
const expected = [
'PROJECT.md', 'ROADMAP.md', 'STATE.md', 'REQUIREMENTS.md',
'MILESTONES.md', 'BACKLOG.md', 'LEARNINGS.md', 'THREADS.md',
'config.json', 'CLAUDE.md', 'RETROSPECTIVE.md',
'config.json', 'CLAUDE.md', 'RETROSPECTIVE.md', 'WINDOWS.md',
];
for (const name of expected) {
assert.ok(CANONICAL_EXACT.has(name), `expected ${name} in CANONICAL_EXACT`);
@@ -58,6 +58,15 @@ describe('isCanonicalPlanningFile', () => {
assert.strictEqual(isCanonicalPlanningFile('config.json'), true);
});
test('#3224: WINDOWS.md (broken-windows ledger) is a canonical .planning/ artifact', () => {
// gsd-core itself writes .planning/WINDOWS.md (src/broken-windows.cts,
// LEDGER_FILE_NAME = 'WINDOWS.md'). Before #3224 it was absent from the
// registry, so validate health flagged it W019 "Unrecognized" with advice to
// delete a ledger that can gate /gsd-ship under workflow.windows_enforce.
assert.ok(CANONICAL_EXACT.has('WINDOWS.md'), 'WINDOWS.md must be in CANONICAL_EXACT');
assert.strictEqual(isCanonicalPlanningFile('WINDOWS.md'), true);
});
test('returns false for unrecognized file', () => {
assert.strictEqual(isCanonicalPlanningFile('random-file.md'), false);
});