This commit is contained in:
@@ -567,6 +567,8 @@ node gsd-tools.cjs validate context
|
||||
node gsd-tools.cjs validate context --json
|
||||
```
|
||||
|
||||
`validate consistency`'s `warnings` entries are coded diagnostics (`{code, message, fix, repairable}`), not bare strings. A phase declared in ROADMAP.md with no directory on disk, or a directory on disk with no ROADMAP.md entry, reports under `W006`/`W007` — the same codes `validate health` uses for the identical check, since it's one enumeration with two callers, not a separate check. The four subjects unique to this command (numbering gaps in phases or plans, orphan `*-SUMMARY.md` files, plans missing `wave` frontmatter) use a new `C0NN` code range (`C001`-`C004`).
|
||||
|
||||
`validate context` emits a structured envelope with `utilization`, `status`
|
||||
(`ok` / `warn` / `critical` at the 60 % / 70 % thresholds), and a
|
||||
`suggestion` string. The same data backs `/gsd-health --context`.
|
||||
|
||||
@@ -1835,7 +1835,7 @@ Presence and posture are separate verdicts: a missing agent is reported in `miss
|
||||
Detect drift between STATE.md and the actual filesystem.
|
||||
|
||||
**Prerequisites:** `.planning/STATE.md` exists
|
||||
**Produces:** Validation report showing any drift between STATE.md fields and filesystem reality
|
||||
**Produces:** Validation report showing any drift between STATE.md fields and filesystem reality, as coded diagnostics
|
||||
|
||||
```bash
|
||||
node gsd-tools.cjs state validate
|
||||
@@ -1845,12 +1845,24 @@ The report also carries a `scope` field reporting whether the drift derivation c
|
||||
|
||||
| `scope` | Meaning |
|
||||
|---|---|
|
||||
| `complete` | The derivation ran over usable input — a resolvable phase, a readable disk scan. `valid`/`warnings`/`drift` are a real answer. |
|
||||
| `complete` | The derivation ran over usable input — a resolvable phase, a readable disk scan. `valid`/`warnings` are a real answer. |
|
||||
| `truncated` | Part of the input was cut short (e.g. the phase's plan/summary scan hit its cap) — the answer may be incomplete. |
|
||||
| `unscoped` | `Current Phase` could not be resolved from either frontmatter or body — there was nothing to scope the disk lookup to, so the derivation never ran. |
|
||||
| `unreadable` | The frontmatter parse or a filesystem read (the phases directory scan) failed — the derivation could not consult its input. |
|
||||
|
||||
`valid` is **not** routed from `scope`: `valid` still means "no drift warnings were found," and `scope` says whether the scan could actually run. A freshly-initialized project reports `{valid:true, warnings:[], drift:{}, scope:'unscoped'}` — nothing was wrong, and the phase could not be checked. See [Interpret `state validate` results](how-to/interpret-state-validate-results.md) for how to act on each `scope` value.
|
||||
`valid` is **not** routed from `scope`: `valid` still means "no warnings were found," and `scope` says whether the scan could actually run. A freshly-initialized project reports `{valid:true, warnings:[], scope:'unscoped'}` — nothing was wrong, and the phase could not be checked. See [Interpret `state validate` results](how-to/interpret-state-validate-results.md) for how to act on each `scope` value.
|
||||
|
||||
Each `warnings` entry is a coded diagnostic object (`{code, severity, message, remedy}`), not a bare string. Every remedy is an `ADVISE` action naming the command or edit to make — none is auto-applied. `S001` is `severity: ERROR` (STATE.md could not be read at all); every other code is `severity: WARNING`:
|
||||
|
||||
| Code | Severity | Meaning |
|
||||
|---|---|---|
|
||||
| `S001` | error | STATE.md is unreadable/corrupt (embedded NUL or binary content) — reported with `valid:false` and no other checks run |
|
||||
| `S002` | warning | No usable `current_phase`/`Current Phase`/`Current Position Phase` value anywhere in STATE.md |
|
||||
| `S003` | warning | STATE.md's phase sources (frontmatter vs. body) disagree on the current phase |
|
||||
| `S004` | warning | The phases directory, or a directory matching the current phase, is missing or unreadable |
|
||||
| `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" |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -380,6 +380,7 @@
|
||||
"handshake-serialized.cjs",
|
||||
"health-diagnostic-rules/agent-install.cjs",
|
||||
"health-diagnostic-rules/config-validation.cjs",
|
||||
"health-diagnostic-rules/consistency.cjs",
|
||||
"health-diagnostic-rules/milestone-archive-hygiene.cjs",
|
||||
"health-diagnostic-rules/phase-structure.cjs",
|
||||
"health-diagnostic-rules/roadmap-disk-consistency.cjs",
|
||||
|
||||
@@ -485,6 +485,7 @@ Full listing: `gsd-core/bin/lib/*.cjs`.
|
||||
| `health-diagnostic-rules/config-validation.cjs` | Health-diagnostic rules: config.json validation checks (W003, W004, W022, E005, W008, W012-W016), reading only `snapshot.config`, ported behavior-preserving from `cmdValidateHealth` (ADR-3180 §8.2/§8.3/§8.5, Phase 11, #3309) |
|
||||
| `config.cjs` | `config.json` read/write, section initialization; imports validator from `config-schema.cjs` |
|
||||
| `configuration.cjs` | Configuration Module — legacy-key normalization, defaults merge, and explicit on-disk migration; pure normalization primitives consumed by `config-loader.cjs` and `config-schema.cjs` (loadConfig extracted to config-loader per ADR-857 #885) |
|
||||
| `health-diagnostic-rules/consistency.cjs` | Health-diagnostic rules for `validate.consistency` only (C001-C004: gap in disk phase numbering, gap in plan numbering within a phase, orphan SUMMARY with no matching live PLAN, PLAN missing `wave` frontmatter) — a new `C0NN` code namespace parallel to `validate.health`'s `E`/`W`/`I` space, ported behavior-preserving from `cmdValidateConsistency` (ADR-3180 §8.4, Phase 12, #3310) |
|
||||
| `context-composer.cjs` | Shared budget-composition seam (ADR-1671, #2929) — `composeWithinBudget` trims an ordered fragment list to a measured budget and returns a PLAN of surviving fragments, never rendered text, so one seam serves both the review pipeline and per-runtime emission. Closed strategy set: `verbatim`, `head-shrink`, `proportional-truncate` (with a per-fragment floor), `drop`. The budget unit is injected via `measure(text)` — tokens for `prompt-budget`, bytes for emission — with `charsPerUnit` as its inverse. Also exports `headShrink`/`tailTruncate`. Compiled from `src/context-composer.cts` |
|
||||
| `context-predicates.cjs` | CONTEXT.md predicate fact-store parser (ADR-1671, #2928) — pure `parsePredicates` (extracts every backtick-wrapped `CLASS.subkey=value` declaration, fence/HTML-comment-aware), `selectPredicates` (class/prefix/contains selectors, ANDed), and `buildIndex` (deterministic, line-free artifact shape); backs both `gsd_run query context-predicates` and `scripts/gen-context-index.cjs`'s docs/CONTEXT-INDEX.json drift guard. Compiled from `src/context-predicates.cts` |
|
||||
| `context-utilization.cjs` | Pure classifier for `gsd-health --context` — turns (tokensUsed, contextWindow) into a `{ percent, state }` triage result against the 60%/70% fracture-point thresholds (#2792) |
|
||||
|
||||
@@ -29,8 +29,8 @@ For the flag/output reference, see [`state validate`](../COMMANDS.md#state-valid
|
||||
|
||||
| `scope` | What it means | What caused it | What to do |
|
||||
|---|---|---|---|
|
||||
| `complete` | The derivation ran over usable input — a resolvable `Current Phase` and, if a matching phase directory exists, a readable disk scan of it. `valid`/`warnings`/`drift` are a real, trustworthy answer. | Normal operation: STATE.md's phase resolved (from frontmatter or body) and the filesystem was readable. | Trust the result as-is. If `valid:false`, act on the listed `warnings`/`drift` entries (typically `state sync`). |
|
||||
| `truncated` | Part of the input was cut short before the scan finished — the phase directory's plan/summary scan hit an internal cap partway through. The `valid`/`drift` answer may be **incomplete**, not necessarily wrong. | An unusually large phase directory (many plan/summary files) exceeded the scan's bounded window. | Do not treat `valid:true` here as a clean bill of health. Inspect the phase directory directly (`ls .planning/phases/<phase>/`) to confirm counts by hand, or reduce/split the phase's plan set if this recurs. |
|
||||
| `complete` | The derivation ran over usable input — a resolvable `Current Phase` and, if a matching phase directory exists, a readable disk scan of it. `valid`/`warnings` are a real, trustworthy answer. | Normal operation: STATE.md's phase resolved (from frontmatter or body) and the filesystem was readable. | Trust the result as-is. If `valid:false`, act on the listed `warnings` entries (typically `state sync`). |
|
||||
| `truncated` | Part of the input was cut short before the scan finished — the phase directory's plan/summary scan hit an internal cap partway through. The `valid` answer may be **incomplete**, not necessarily wrong. | An unusually large phase directory (many plan/summary files) exceeded the scan's bounded window. | Do not treat `valid:true` here as a clean bill of health. Inspect the phase directory directly (`ls .planning/phases/<phase>/`) to confirm counts by hand, or reduce/split the phase's plan set if this recurs. |
|
||||
| `unscoped` | `Current Phase` could not be resolved from **either** the frontmatter scalar or the body field — there was no phase to scope the disk lookup to, so the drift derivation never ran at all. | Most commonly a freshly-initialized project with no phase set yet (a genuine, supported state). Less commonly, a STATE.md whose `Current Phase` field was dropped or malformed. | If the project has not started a phase yet, this is expected — no action needed. If the project is active and you expect a phase to be set, open STATE.md and check the `current_phase` frontmatter key and the body's `**Current Phase:**` row; run `state sync` to reconstruct it from disk if it is missing. |
|
||||
| `unreadable` | An input the scan needed could not be consulted at all — either the frontmatter block failed to parse, or a filesystem read (the phases directory scan) failed mid-scan. | An unterminated/malformed YAML frontmatter fence, or a filesystem error (permissions, a race with a concurrent write) while reading `.planning/phases/`. | Treat `valid:true` here as **not trustworthy** — the scan degraded silently before this field existed, and now surfaces that instead of hiding it. Check that STATE.md's frontmatter fence (`---` / `---`) is well-formed, and that `.planning/phases/` is readable by the current user. Re-run `state validate` after fixing either. |
|
||||
|
||||
@@ -38,14 +38,14 @@ For the flag/output reference, see [`state validate`](../COMMANDS.md#state-valid
|
||||
|
||||
## The case this exists for: "`valid:true` — but is it trustworthy?"
|
||||
|
||||
If you only ever read `valid`, every one of the four `scope` values above looks identical: `true`. That collapse is the exact bug this field was added to close (#3162) — a STATE.md whose phase lived only in frontmatter used to silently skip the entire drift scan and report `{valid:true, warnings:[], drift:{}}`, indistinguishable from a phase that was checked and found clean.
|
||||
If you only ever read `valid`, every one of the four `scope` values above looks identical: `true`. That collapse is the exact bug this field was added to close (#3162) — a STATE.md whose phase lived only in frontmatter used to silently skip the entire drift scan and report `{valid:true, warnings:[]}`, indistinguishable from a phase that was checked and found clean.
|
||||
|
||||
So before trusting a green `state validate`, always inspect `scope`:
|
||||
|
||||
- **`scope:'complete'`** — trustworthy. The scan ran; `valid:true` means clean.
|
||||
- **Anything else** — not yet checked, or only partially checked. `valid:true` here means *"no problems were found in what could be looked at,"* which is a materially weaker claim. Use the table above to find out why, and whether that is expected (a fresh project, `unscoped`) or a problem worth fixing (`unreadable`, or a `truncated` scan on a large phase).
|
||||
|
||||
A freshly-initialized project is the clearest example of a **legitimate** non-`complete` scope: it reports `{valid:true, warnings:[], drift:{}, scope:'unscoped'}`, which reads as *"nothing was found wrong, and the phase could not be checked"* — not as a defect to fix.
|
||||
A freshly-initialized project is the clearest example of a **legitimate** non-`complete` scope: it reports `{valid:true, warnings:[], scope:'unscoped'}`, which reads as *"nothing was found wrong, and the phase could not be checked"* — not as a defect to fix.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user