enhance(#2572): run the verify-summary artifact check against phase SUMMARYs (#2685)

* enhance(#2572): run the verify-summary artifact check against phase SUMMARYs (W025)

The artifact<->git check has existed since the beginning but was only ever
pointed at .planning/research/SUMMARY.md (new-project.md:1145,
new-milestone.md:425). Phase summaries -- the ones that actually claim
"I created these files" -- were never checked.

- extract verifySummaryCore from cmdVerifySummary: same checks, lifted out of
  the output() wrapper so callers consume {passed, checks, errors} directly
  instead of shelling out and re-parsing JSON; cmdVerifySummary is now a thin
  adapter over it
- validate.health gains advisory W025 per phase SUMMARY with missing files

Advisory only: appends to warnings[], never touches status escalation beyond
the channel's own warning semantics, the repair set, or readVerificationStatus.

Resolves both open questions from triage: (a) commits_exist is deliberately NOT
surfaced -- its hash pattern matches any hex-shaped token in prose, too loose to
show a user; (b) a phase carries N per-plan summaries plus a legacy bare
SUMMARY.md, so all of them are checked via the repo-wide filter.

* chore(#2572): add changeset fragment

* feat(#2572): move the SUMMARY artifact check to phase completion

Responds to the #2685 review. Three substantive changes.

Seam (Blocker 2). The check now runs in cmdPhaseComplete, the seam the
issue body cited (src/phase.cts:~1745), not validate.health. That channel
does exist: cmdPhaseComplete declares warnings[], populates it from the
UAT/VERIFICATION pre-scan, and emits it. The cycle objection raised
against the earlier deviation holds for state.cts only -- verify.cts has
no transitive import path to phase.cts, so phase.cts -> verify.cjs adds
no cycle (verified over every src/*.cts). Moving it also retires the
retroactive firing across all historical phases: this fires once, at
completion, for the phase being completed.

Extraction (Blocker 1). Pattern 2 now excludes [ and ] from its path
class. The SUMMARY templates prescribe a YAML flow sequence
(key-files.created: [a.ts, b.ts]) and the label matches case-insensitively,
so the class previously captured the literal [ and produced a candidate
that can never exist on disk -- firing on healthy projects built from the
templates GSD itself ships. Stripping frontmatter was the other offered
remedy; measured across all three shipped templates it is a no-op on top
of the exclusion, so it is not carried. Consequence named in-code: the
key-files block still is not read, which needs a real frontmatter parse.

Also narrowed to the noise classes confirmed in review -- globs, bare
hostnames, and paths resolving outside the project are skipped rather
than reported, and the containment guard the old comment claimed now
actually exists.

Budget (Majors 1 and 3). verifySummaryCore takes a checkCommits option;
phase completion passes false, so the discarded git cat-file probes are
not spawned at all. It also passes Infinity, so every referenced file is
reported instead of the first two -- a summary listing twelve files of
which nine are missing now says nine, not zero. The verb keeps its
historical 2-file default.

Tests (Major 2). The vacuous fixtures are gone with the health block.
The replacements use /-bearing paths that genuinely extract, and each
fix was mutation-checked: un-anchoring pattern 2, dropping the glob,
hostname or containment filter, forcing commit checking on, and
re-capping at 2 each fail at least one test.

* docs(#2572): describe the phase-completion SUMMARY artifact check

The W025 text under /gsd-health is withdrawn with the health seam; the
check is documented where it now runs, under `phase complete` in
docs/CLI-TOOLS.md.

Both the docs and the changeset previously overclaimed: they said a
referenced file not on disk is warned about, while at most two candidates
per SUMMARY were ever examined. The cap is gone at this seam, so the
claim now holds -- and the text states the limits that remain, rather
than leaving them to be discovered: the key-files frontmatter block is
not read, commit hashes are not resolved, and globs, URLs, bare
hostnames and out-of-project paths are skipped rather than reported.

---------

Co-authored-by: CI Rebase Check <ci@gsd-redux>
This commit is contained in:
Rezolv
2026-07-28 18:31:33 -04:00
committed by GitHub
parent 6932fb16d7
commit 7e8f6a6d7d
6 changed files with 567 additions and 17 deletions

View File

@@ -127,6 +127,8 @@ node gsd-tools.cjs phase insert <after> <description>
node gsd-tools.cjs phase remove <phase> [--force]
# Mark phase complete, update state + roadmap
# Also emits advisory `warnings[]` when a phase SUMMARY references a file that
# is not on disk — see "Phase SUMMARY artifact check" below.
node gsd-tools.cjs phase complete <phase>
# Evaluate HUMAN-UAT results for a phase (markdown-aware; ignores false-positive contexts)
@@ -140,6 +142,31 @@ node gsd-tools.cjs phase-plan-index <phase>
node gsd-tools.cjs phases list [--type planned|executed|all] [--phase N] [--include-archived]
```
### Phase SUMMARY artifact check
A phase `SUMMARY.md` asserts which files the phase created or modified. On
`phase complete`, each SUMMARY in the phase is scanned for referenced file paths
and any path that is not on disk is reported in the command's existing
`warnings[]` array — the case where a summary reports work that never landed.
**Advisory only.** Findings never block completion; the completion gate is the
phase's `VERIFICATION.md` status, which this does not touch. `/gsd-execute-phase`
surfaces the warnings before advancing.
Scope and limits, so the output is not read as more than it is:
- Paths are recovered heuristically from the SUMMARY body — backticked paths and
`Created:`/`Modified:`-style lines. Globs, URLs, bare hostnames, and paths
resolving outside the project are skipped rather than reported.
- The `key-files:` frontmatter block is **not** read. Its YAML flow-sequence form
(`created: [a.ts, b.ts]`) is not matched by the prose scan, so a summary whose
only file claims live there produces no findings.
- Commit hashes in the SUMMARY are **not** resolved here. The pattern matches any
hex-shaped token in prose, which is too loose to surface.
Every path the scan does recover is checked — there is no cap. The standalone
`verify-summary` verb keeps its historical default of checking the first two.
---
## Roadmap Commands