* test: reproduce Windows SDK not found after fresh npx install (#3211) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: red — docs-parity live-registry tests fail against stub helper (#3049) Adds: - tests/helpers/live-command-registry.cjs (stub: returns empty Set) - tests/docs-parity-live-registry.test.cjs (new polarity-inverted test) - tests/fixtures/live-command-registry/ (fixture .md files) All parity and helper-contract tests fail because the stub returns an empty registry. This is the intentional RED state before GREEN implementation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(test-helpers): live-command-registry derives canonical tokens from commands/gsd/*.md (#3049) Implements GREEN phase: - tests/helpers/live-command-registry.cjs: walks commands/gsd/*.md, parses YAML frontmatter name: field, emits /gsd-slug, /gsd:slug, $gsd-slug per command. Memoized per process. Fails loud on malformed frontmatter (k302). - tests/docs-parity-live-registry.test.cjs: updated with INTERNAL_COMPONENT_SLUGS exemption for path-component and placeholder tokens (gsd-build from GitHub org URLs, gsd-workspaces from ~/gsd-workspaces/ paths, gsd-tools from bin/gsd-tools.cjs paths, etc.) Docs drift caught and fixed: - ns-* rename: /gsd-ns-workflow→/gsd-workflow etc. in COMMANDS, FEATURES, INVENTORY, USER-GUIDE (6 commands across 4 English files) - /gsd-scan → /gsd-map-codebase --fast (FEATURES, INVENTORY, USER-GUIDE) - /gsd-note → /gsd-capture (FEATURES, issue-driven-orchestration, ja-JP, ko-KR) - /gsd-do → /gsd-fast (FEATURES, ja-JP, ko-KR) - /gsd-from-gsd2 → /gsd-import --from-gsd2 (CLI-TOOLS, FEATURES, INVENTORY) - /gsd-verify-phase → /gsd-validate-phase (STATE-MD-LIFECYCLE) - /gsd-settings-integrations → /gsd-settings or /gsd-config --integrations (CLI-TOOLS) - /gsd-dev-preferences removed from profile-user artifact lists (AGENTS, COMMANDS, FEATURES in English, ja-JP, ko-KR) - /gsd-select-framework removed from gsd-framework-selector spawner list (AGENTS, INVENTORY) All 28 new tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(test): replace deny-list parity tests with polarity-inverted live-registry approach (#3049) - Delete bug-3010-reapply-patches-references.test.cjs (hardcoded deny-list) - Delete bug-3029-3034-stale-command-routes.test.cjs (hardcoded deny-list) - Delete bug-3042-3044-research-flag-and-stale-refs.test.cjs (deny-list + frontmatter checks) - Add tests/skill-frontmatter-contract.test.cjs (frontmatter structural checks extracted from deleted file) - Update tests/commands-doc-parity.test.cjs to derive slug from name: frontmatter field instead of filename, so ns-* commands resolve to their actual deployed tokens Closes #3049 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: annotate commands-doc-parity with source-text-is-the-product exemption (#3049 lint fix) The readFileSync on commands/gsd/*.md reads product markdown whose deployed text IS what the user sees — content.startsWith('---') detects YAML frontmatter in those files, not source-code structure. Add the allow-test-rule exemption matching the same rationale used in docs-parity-live-registry.test.cjs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: walk docs/** recursively to cover nested locale trees (CR finding 7) Replaced the non-recursive listMdFiles() with a hand-rolled DFS walker compatible with Node 20+. Surfaces unreadable-directory errors as stderr warnings (PRED.k302) rather than silently skipping. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: annotate live-command-registry helper and commands-doc-parity with source-text exemptions (CR findings 6, 8) Adds allow-test-rule comments to suppress lint-no-source-grep false positives on YAML frontmatter structure checks in both files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: anchor --research-phase assertions to arg-parsing section and verify combined refresh (CR findings 9, 10) Finding 9: scopes --research-phase check to within 1200 chars of the flag description section header, preventing false positives from prose mentions. Finding 10: tightens the force-refresh assertion to require BOTH --research and force/refresh semantics within the --research-phase description section, verifying the combined-mode contract rather than standalone --research presence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: fix execSync mock to accept opts parameter, forward to saved implementation (CR finding 5) The mock at line 212 dropped the options parameter when delegating to savedExecSync. Updated to (cmd, opts) signature and pass opts through. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: correct routing entrypoint, --fast default, /gsd-review collision, verifying-stage mapping (CR findings 1-4) Finding 1: Change Freeform Routing command from /gsd-fast to /gsd-progress --do. /gsd-fast is the inline trivial-task executor, not the routing entrypoint. Finding 2: Clarify that /gsd-map-codebase --fast REQ-SCAN-02 default (tech+arch) runs as a single combined-focus agent, resolving the contradiction with REQ-SCAN-01. Finding 3: Rename the namespace router /gsd-review to /gsd-quality across all docs, command file, and help.md to eliminate the naming collision with the concrete cross-AI peer-review command (review.md, name: gsd:review). Finding 4: Replace /gsd-validate-phase with /gsd-verify-work in the STATE-MD-LIFECYCLE.md verifying-stage table. /gsd-validate-phase is the retroactive Nyquist-validation flow, not the normal phase-verification step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs+test: fix locale doc drift surfaced by recursive walker (CR finding 7 follow-up) The recursive listMdFiles() walker newly covered docs/**/*.md subdirs. Stale command references in locale docs are now caught and fixed: - docs/zh-CN/references/model-profiles.md: remove /gsd-set-profile (deleted command); config.json is the current mechanism - docs/zh-CN/references/ui-brand.md: remove /gsd-alternative-1/2 template placeholders - docs/{ja-JP,ko-KR,pt-BR}/superpowers/specs/2026-03-20-*: replace /gsd-new-workspace, /gsd-list-workspaces, /gsd-remove-workspace with /gsd-workspace --new / --list / --remove (consolidated in #2790) Also adds smoke- and alternative-{1,2} to INTERNAL_COMPONENT_SLUGS (filesystem path and template placeholder patterns, not slash commands) and introduces listEnglishMdFiles() to scope the English parity check to docs/ excluding locale subdirectories (which have their own per-locale describe blocks). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add bash language tag to fenced code blocks in ja-JP and ko-KR workspace specs (CR round 2) Satisfies MD040 fenced-code-language requirement. These blocks contain shell commands and were missing the language specifier. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
180 lines
7.5 KiB
Markdown
180 lines
7.5 KiB
Markdown
# STATE.md Phase Lifecycle Frontmatter
|
|
|
|
> **Status:** Read-side shipped in v1.40.0 (issue
|
|
> [#2833](https://github.com/gsd-build/get-shit-done/issues/2833)).
|
|
> `parseStateMd()` reads the four frontmatter fields below and
|
|
> `formatGsdState()` renders the in-flight / idle / progress scenes.
|
|
> SDK write-side support to maintain the fields automatically is tracked
|
|
> separately.
|
|
|
|
GSD's `STATE.md` carries YAML frontmatter that the status-line hook reads on
|
|
every render. This document describes the **phase-lifecycle fields** and the
|
|
rendering scenes they trigger.
|
|
|
|
All four lifecycle fields are **optional and additive**. Existing `STATE.md`
|
|
files (without these fields) keep rendering exactly as they did before — no
|
|
visual change, no migration required.
|
|
|
|
---
|
|
|
|
## Frontmatter fields
|
|
|
|
```yaml
|
|
---
|
|
gsd_state_version: 1.0
|
|
milestone: v2.0 # existing
|
|
milestone_name: Code Quality # existing
|
|
status: in_progress # existing — see "status semantics" below
|
|
|
|
# Phase-lifecycle additions (issue #2833) — all optional
|
|
active_phase: null # phase number when an orchestrator is in flight
|
|
next_action: execute-phase # next recommended command when idle
|
|
next_phases: ["4.5"] # phases that next_action applies to (1-2 ids)
|
|
|
|
progress: # nested block (existing key, percent now opt-in for the bar)
|
|
total_phases: 17
|
|
completed_phases: 10
|
|
percent: 59
|
|
---
|
|
```
|
|
|
|
### Field reference
|
|
|
|
| Field | Type | When populated | When null/absent |
|
|
|---|---|---|---|
|
|
| `active_phase` | string (e.g. `"4.5"`) | An orchestrator command is in flight on this phase | Idle between phases |
|
|
| `next_action` | string | Idle, with a recommended command (`discuss-phase` / `plan-phase` / `execute-phase` / `verify-phase`) | An orchestrator is in flight, OR no recommendation available |
|
|
| `next_phases` | YAML flow array (e.g. `["4.5"]`) | Goes with `next_action` — phases the action applies to | Same as above |
|
|
| `progress.percent` | integer 0-100 | Milestone progress in **phase dimension** (`completed_phases / total_phases`) | Bar rendering is opt-in — absent → no bar |
|
|
|
|
### `next_phases` parser scope
|
|
|
|
Only **single-line YAML flow** is parsed: `next_phases: ["4.5", "4.6"]`.
|
|
|
|
Block sequences over multiple lines (`- 4.5\n - 4.6`) are intentionally
|
|
**not parsed** — the status-line only needs the primary recommendation, and a
|
|
single-line array keeps the regex-based parser predictable. If a project needs
|
|
to track many candidate next phases for documentation purposes, store the
|
|
extra ones in the `STATE.md` body.
|
|
|
|
### `progress.percent` dimension
|
|
|
|
The bar rendered next to the milestone version reflects **phase completion**
|
|
(`completed_phases / total_phases`), not plan completion.
|
|
|
|
Plan dimension (`completed_plans / total_plans`) trends optimistic for any
|
|
project where future phases haven't been planned yet — `total_plans` only
|
|
counts plans inside *already-planned* phases, so the denominator is
|
|
structurally smaller than reality. Reporting that number to stakeholders
|
|
overstates progress.
|
|
|
|
If a project wants to show plan-level progress somewhere, store it elsewhere
|
|
in frontmatter or the body — the status-line bar is reserved for the
|
|
phase-dimension number that matches `ROADMAP.md` progress tables and
|
|
`MILESTONES.md`.
|
|
|
|
---
|
|
|
|
## Status-line rendering scenes
|
|
|
|
`formatGsdState()` checks the lifecycle fields in the order below and emits
|
|
the **first matching scene**. If none match, the renderer falls through to
|
|
the original `<status> · <phase>` format (byte-for-byte unchanged from
|
|
v1.38.x).
|
|
|
|
| Scene | Trigger | Display |
|
|
|---|---|---|
|
|
| **1. Phase active** | `active_phase` populated | `v2.0 [██░░░] X% · Phase 4.5 executing` |
|
|
| **2. Idle, next recommended** | `active_phase` null AND `next_action` + `next_phases` populated | `v2.0 [██░░░] X% · next execute-phase 4.5` |
|
|
| **3. Milestone complete** | `percent: 100` OR `completed_phases == total_phases` | `v2.0 [██████████] 100% · milestone complete` |
|
|
| **4. Default fallback** | None of the above | `v1.9 Code Quality · executing · ph (1/5)` (existing format) |
|
|
|
|
### Scene priority example
|
|
|
|
When both `active_phase` and `next_action` are populated, **Scene 1 wins** —
|
|
an orchestrator is in flight, so any "next recommendation" would be misleading.
|
|
This is enforced by check order in `formatGsdState()` and by tests in
|
|
`tests/enh-2833-phase-lifecycle-statusline.test.cjs` (suite *"scene priority"*).
|
|
|
|
### Stage labels in Scene 1
|
|
|
|
In Scene 1, the second part of `Phase 4.5 <stage>` is whichever value is in
|
|
the `status` field at that moment. The convention proposed in issue #2833
|
|
is to use the lifecycle stage:
|
|
|
|
| Command | `status` value while in flight |
|
|
|---|---|
|
|
| `/gsd-discuss-phase` | `discussing` |
|
|
| `/gsd-plan-phase` | `planning` |
|
|
| `/gsd-execute-phase` | `executing` |
|
|
| `/gsd-verify-work` | `verifying` |
|
|
|
|
If `status` is left at `in_progress` (the milestone-level value), Scene 1
|
|
renders just `Phase 4.5` without the stage suffix.
|
|
|
|
---
|
|
|
|
## Frontmatter parsing constraints
|
|
|
|
The status-line hook uses regex-based parsing (no full YAML library), so a
|
|
few constraints apply:
|
|
|
|
1. **Frontmatter must start at the very first character of the file.**
|
|
Anything (including comments) above the opening `---` invalidates the
|
|
match. The opening `---` line must be exactly that — no trailing spaces.
|
|
|
|
2. **Comments inside nested blocks are not supported.**
|
|
The parser for `progress:` requires the next line to be `[ \t]+\w+:` —
|
|
inserting `# comment` between `progress:` and the first key breaks the
|
|
match and the bar disappears. Put any documentation in the body of
|
|
`STATE.md`, not inside frontmatter blocks.
|
|
|
|
3. **`next_phases` accepts only single-line flow format.**
|
|
See the parser scope note above.
|
|
|
|
These constraints are tested in
|
|
`tests/enh-2833-phase-lifecycle-statusline.test.cjs`. If a future change
|
|
swaps the regex parser for a real YAML library, the constraints can be
|
|
relaxed and the tests updated accordingly.
|
|
|
|
---
|
|
|
|
## Backward compatibility
|
|
|
|
This document describes additive fields. The promise is:
|
|
|
|
- A `STATE.md` file with **none** of the lifecycle fields populated renders
|
|
**byte-for-byte identically** to v1.38.x and earlier.
|
|
- Adding any lifecycle field is **opt-in per project** — the renderer falls
|
|
through to the existing format when fields are absent.
|
|
- The progress bar is opt-in even when `progress` block exists — only
|
|
`progress.percent` triggers the bar; `total_phases` / `completed_phases`
|
|
alone don't.
|
|
|
|
The `formatGsdState #2833 backward compatibility` test suite locks this
|
|
guarantee in: any change that breaks legacy `STATE.md` rendering will fail
|
|
the suite.
|
|
|
|
---
|
|
|
|
## Related issues / PRs
|
|
|
|
- **#1989** — *enhancement: surface GSD state in statusline.* The foundation
|
|
this proposal extends. Established that `STATE.md` frontmatter drives the
|
|
status-line.
|
|
- **#2833** — *enhancement: phase-lifecycle status-line — auto-rotate
|
|
STATE.md frontmatter as phase orchestrators progress.* This document
|
|
describes the read-side spec from that issue. Write-side SDK / workflow
|
|
changes to auto-maintain the fields are tracked separately so each piece
|
|
can be reviewed independently.
|
|
|
|
Companion read-side issues this proposal also helps close (each fixed a
|
|
specific symptom of the same gap):
|
|
|
|
- #1102 — STATE.md frontmatter plan counts only update on plan completion
|
|
- #1103 — STATE.md status / last_activity not updated when a phase starts
|
|
- #1446 / #1572 — phase complete doesn't update Plans column
|
|
- #612 — ROADMAP.md not updating
|
|
- #956 — planning document drift across core workflows
|
|
- #2018 — verify-work doesn't auto-transition (fixed for verify only)
|