fix(#3696): report the last_activity invariant and make the verdict gateable with --strict (#3844)

* test(#3696): failing-first coverage for the last_activity invariant and --strict exit status

* fix(#3696): report the last_activity invariant and make the verdict gateable with --strict

* fix(#3696): agree with the real reader on last_activity, and stop reporting structure as truncation

* chore(#3696): backfill changeset PR number

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-24 21:33:48 -04:00
committed by GitHub
parent 6905726d9c
commit 394bf384be
12 changed files with 954 additions and 46 deletions

View File

@@ -2023,6 +2023,24 @@ Detect drift between STATE.md and the actual filesystem.
node gsd-tools.cjs state validate
```
| Flag | Description |
|------|-------------|
| `--strict` | Exit non-zero when the report is not `valid: true`. Off by default. |
Without `--strict` the command always exits `0`, including when it reports
`valid: false` — so a CI step or git hook has to parse the JSON to decide whether
state is correct. `--strict` makes the verdict gateable directly:
```bash
node gsd-tools.cjs state validate --strict || echo "STATE.md needs attention"
```
The default is deliberately unchanged: the exit status is observable behavior that
reaches downstream consumers who cannot be enumerated, so opting in is a choice the
caller makes rather than one imposed on every existing script.
A missing or unreadable STATE.md exits non-zero under `--strict` too — those report
`error` or `valid: false` and are as gateable as any drift warning.
The report also carries a `scope` field reporting whether the drift derivation could actually run:
| `scope` | Meaning |
@@ -2045,6 +2063,8 @@ Each `warnings` entry is a coded diagnostic object (`{code, severity, message, r
| `S005` | warning | STATE.md's plan count disagrees with the plan count on disk |
| `S006` | warning | STATE.md still says "executing" but a `*-VERIFICATION.md` in the phase shows verification passed |
| `S007` | warning | Every plan in the phase has a summary, but STATE.md still says "executing" |
| `S008` | warning | STATE.md's `Last activity` value does not begin with a real calendar date, so no reader can date the project's activity |
| `S009` | warning | The `Last activity` description wrapped onto a second line, and every reader silently drops the remainder |
---