feat(#3840): generate docs/FEATURES.md from per-feature fragments (#3845)

* feat(#3840): generate docs/FEATURES.md from per-feature fragments

docs/FEATURES.md was hand-maintained, and every feature PR wrote into two
shared mutable cells: the '### N.' heading whose integer was hand-allocated at
authoring time, and the hand-maintained table of contents. Concurrent PRs all
picked the same next integer, and two PRs adding differently numbered features
still collided on the TOC. #3831 was renumbered 165 -> 166 -> 167 -> 168 across
successive rebases, each collision also costing a full matrix verification run
because the sha-keyed pass marker dies with the rebase.

Mechanism: one fragment per feature at docs/features/<slug>.md carrying
id/title/group (and an optional order) in frontmatter, consolidated by
scripts/gen-features.cjs --write|--check into a marker-delimited region of
docs/FEATURES.md that holds BOTH the TOC and every section body. Group headings
and their order are derived too - a group sorts by its lowest-ordered member -
so there is no shared registry to edit either; optional per-group prose lives in
docs/features/_groups/<slug>.md. A contributor adds exactly one new file.
Wired into regen:derived and lint:generated-sync alongside the eight existing
generators, matching gen-adr-index.cjs's CLI shape and typed-REASON reporting.

Migration froze all 168 existing numbers verbatim: identical section set,
identical order, identical bodies. Two defects found in the tree are fixed
inline rather than carried forward - the '## Related' block had been spliced
into the middle of the document, orphaning §142's Reference line, and four
inbound anchors were already broken on next (FEATURES.md#runtime-identity in
two files, and #143-spec-phase-edge-completeness-probe off by one). Since the
repo has no link checker, --check now validates every inbound
FEATURES.md#anchor by resolved target, so that class cannot ship silently
again; locale FEATURES.md files resolve elsewhere and stay out of scope.

Refs #3840

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(#3840): carry upstream §69 delta into its fragment and harden the generator

Review found section 69 missing '[--strict]' and REQ-STATE-05/06 versus
origin/next. Root cause was a stale base, not extraction loss: those lines
landed in 394bf384b (#3844) AFTER this branch forked at 63abcface, and
'git diff 63abcface origin/next -- docs/FEATURES.md' is exactly that hunk.
Merging origin/next auto-applied the hunk into the GENERATED region, which
--check immediately reported as stale; the delta is now carried in
docs/features/statemd-consistency-gates.md and regenerated from there.

--write is now fail-closed. It previously rendered the region even with
violations outstanding, warning only on stderr and exiting 0, so a
'--write && git commit' chain could commit a FEATURES.md carrying two
colliding sections. It now refuses and exits 1; --force is the explicit
override and says so in the report. The test that pinned the old behavior now
pins the refusal, plus the --force override and its scoping.

Marker forgery is rejected at two layers. A fragment body containing
'<!-- FEATURES:START' or '<!-- FEATURES:END' is a typed
body_forges_region_marker violation (fragments and group notes alike), and
spliceIntoFeatures anchors the end boundary with lastIndexOf instead of
indexOf, so a marker that reaches the document by any other route can only
make the generated region grow, never shrink. Matching is on marker PREFIXES,
so a decorated variant comment cannot slip past.

Symlinked corpus entries are refused with a typed dirent_not_regular_file
rather than read. A fork PR could otherwise commit docs/features/evil.md as a
symlink to any readable path and have the generator inline those bytes into
the committed docs/FEATURES.md on the next regen.

Equivalence re-verified with a method that cannot cancel out. The first
check extracted both operands with the same body-normalising helper, so
anything that helper dropped was dropped on both sides. The replacement runs
two independent passes: a global content-line multiset diff with no
per-section logic at all (0 gained, 19 lost, all 19 the stale hand-written
mini-TOC links this change deliberately deletes), and a per-section
byte-exact body diff carrying a coverage assertion that fails loudly per file
when the extractor accounts for fewer lines than the file contains. That
assertion caught two blind spots in the checker itself. 168/168 sections
present, order identical, one intended body difference (§142 regains the
Reference line orphaned by the misplaced '## Related' block).

Refs #3840

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(#3840): backfill changeset PR number

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: sim <sim@local>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-08-24 22:49:00 -04:00
committed by GitHub
parent 394bf384be
commit 36375513b9
180 changed files with 5319 additions and 80 deletions

View File

@@ -4,6 +4,8 @@
---
<!-- FEATURES:START — generated by scripts/gen-features.cjs; do not edit by hand -->
## Table of Contents
- [Core Features](#core-features)
@@ -13,6 +15,7 @@
- [Phase Planning](#4-phase-planning)
- [Phase Execution](#5-phase-execution)
- [Work Verification](#6-work-verification)
- [Ship](#65-ship)
- [UI Review](#7-ui-review)
- [Milestone Management](#8-milestone-management)
- [Planning Features](#planning-features)
@@ -39,6 +42,7 @@
- [Brownfield Features](#brownfield-features)
- [Codebase Mapping](#27-codebase-mapping)
- [Existing Codebase Onboarding](#27b-existing-codebase-onboarding)
- [Post-Execute Codebase Drift Detection](#27a-post-execute-codebase-drift-detection)
- [Utility Features](#utility-features)
- [Debug System](#28-debug-system)
- [Todo Management](#29-todo-management)
@@ -187,6 +191,12 @@
- [Archive Quick Tasks at Milestone Close](#160-archive-quick-tasks-at-milestone-close)
- [Verify-Command Path Grounding](#161-verify-command-path-grounding)
- [Statusline STATE.md Freshness Marker](#162-statusline-statemd-freshness-marker)
- [Read-Only Planning Snapshot (`planning inspect`)](#163-read-only-planning-snapshot-planning-inspect)
- [Live-DOM UAT Capability](#164-live-dom-uat-capability)
- [Opt-In Parallel Reviewer Lanes](#165-opt-in-parallel-reviewer-lanes)
- [Machine-Readable State Contract (`.planning/state.json`)](#166-machine-readable-state-contract-planningstatejson)
- [Stated Failing Direction](#167-stated-failing-direction)
- [Runtime Identity](#168-runtime-identity)
---
@@ -583,6 +593,7 @@
| Phase executed but no VERIFICATION.md | Run `/gsd-verify-work` |
| All phases complete | Suggest `/gsd-complete-milestone` |
---
## Quality Assurance Features
@@ -690,6 +701,7 @@
**When:** Runs automatically at the end of `/gsd-plan-phase` after the plan checker loop.
---
## Context Engineering Features
@@ -802,6 +814,7 @@
| gsd-integration-checker | Sonnet | Sonnet | Haiku | Inherit |
| gsd-nyquist-auditor | Sonnet | Sonnet | Haiku | Inherit |
---
## Brownfield Features
@@ -838,6 +851,8 @@ only the subtrees the phase actually changed. Each produced document carries
`last_mapped_commit` in its YAML frontmatter so drift can be measured
against the mapping point, not HEAD.
---
### 27b. Existing Codebase Onboarding
**Command:** `/gsd-onboard [--fast] [--text]`
@@ -859,6 +874,8 @@ against the mapping point, not HEAD.
| `.planning/PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` | Planning setup produced by `/gsd-new-project` or `/gsd-ingest-docs` |
| `.planning/onboarding/SUMMARY.md` | Onboarding status, artifact index, and next-command summary |
---
### 27a. Post-Execute Codebase Drift Detection
**Introduced by:** #2003
@@ -890,6 +907,7 @@ continues. Drift detection cannot fail verification.
- REQ-DRIFT-06: `last_mapped_commit` round-trip through YAML frontmatter
on each `.planning/codebase/*.md` file
---
## Utility Features
@@ -1006,6 +1024,7 @@ continues. Drift detection cannot fail verification.
- REQ-TEST-02: System MUST generate tests based on UAT criteria and acceptance criteria
- REQ-TEST-03: System MUST use existing test infrastructure patterns
---
## Infrastructure Features
@@ -1138,6 +1157,8 @@ GSD update available: 1.39.0 → 1.40.0. Run /gsd-update.
The banner is silent when up-to-date and rate-limits "check failed" diagnostics to once per 24 hours. Removed cleanly by `npx @opengsd/gsd-core --uninstall` or by deleting the SessionStart entry that references `gsd-update-banner.js`.
---
### 38. Developer Profiling
**Command:** `/gsd-profile-user [--questionnaire] [--refresh]`
@@ -1173,6 +1194,8 @@ The banner is silent when up-to-date and rate-limits "check failed" diagnostics
- REQ-PROF-03: Questionnaire MUST be available as fallback when no session history exists
- REQ-PROF-04: Generated artifacts MUST be discoverable by Claude Code (CLAUDE.md integration)
---
### 39. Execution Hardening
**Purpose:** Three additive quality improvements to the execution pipeline that catch cross-plan failures before they cascade.
@@ -1226,6 +1249,7 @@ When verification returns `human_needed`, items are persisted as a trackable HUM
- REQ-DEBT-05: System MUST warn (non-blocking) during phase completion and transition when verification debt exists
- REQ-DEBT-06: `/gsd-audit-uat` MUST scan all phases, categorize items by testability, and produce a human test plan
---
## v1.27 Features
@@ -1393,6 +1417,7 @@ Test suite that scans all agent, workflow, and command files for embedded inject
- REQ-DISCLOG-02: Log MUST capture questions asked, options presented, and decisions made
- REQ-DISCLOG-03: Decision IDs MUST enable traceability from discuss-phase to plan-phase
---
## v1.28 Features
@@ -1549,6 +1574,7 @@ Test suite that scans all agent, workflow, and command files for embedded inject
2. **Prompt** — Present multi-select interface for runtime selection
3. **Install** — Configure GSD for all selected runtimes in a single session
---
## v1.29 Features
@@ -1583,6 +1609,7 @@ Test suite that scans all agent, workflow, and command files for embedded inject
1. **Translate** — Convert core documentation into target languages
2. **Publish** — Make translated documentation accessible alongside English originals
---
## v1.31 Features
@@ -1790,6 +1817,7 @@ Test suite that scans all agent, workflow, and command files for embedded inject
3. **Clean** — Remove legacy `commands/gsd/` directory if skills are installed
4. **Fallback** — Maintain legacy `commands/gsd/` path compatibility for older Claude Code versions
---
## v1.32 Features
@@ -2101,28 +2129,11 @@ Test suite that scans all agent, workflow, and command files for embedded inject
|---------|------|---------|-------------|
| `hooks.community` | boolean | `false` | Enable optional community hooks for commit validation, session state, and phase boundaries |
---
## v1.34.0 Features
- [Global Learnings Store](#89-global-learnings-store)
- [Queryable Codebase Intelligence](#90-queryable-codebase-intelligence)
- [Execution Context Profiles](#91-execution-context-profiles)
- [Gates Taxonomy](#92-gates-taxonomy)
- [Code Review Pipeline](#93-code-review-pipeline)
- [Socratic Exploration](#94-socratic-exploration)
- [Safe Undo](#95-safe-undo)
- [Plan Import](#96-plan-import)
- [Rapid Codebase Scan](#97-rapid-codebase-scan)
- [Autonomous Audit-to-Fix](#98-autonomous-audit-to-fix)
- [Improved Prompt Injection Scanner](#99-improved-prompt-injection-scanner)
- [Stall Detection in Plan-Phase](#100-stall-detection-in-plan-phase)
- [Hard Stop Safety Gates in /gsd-progress --next](#101-hard-stop-safety-gates-in-gsd-progress---next)
- [Adaptive Model Preset](#102-adaptive-model-preset)
- [Post-Merge Hunk Verification](#103-post-merge-hunk-verification)
---
### 89. Global Learnings Store
**Commands:** Auto-triggered at phase completion; consumed by planner
@@ -2380,17 +2391,11 @@ v1 supports **directory-prefix matching only, not glob syntax**: no glob engine
- REQ-PATCH-VERIFY-02: Dropped or partial hunks MUST be reported to the user with file and line context
- REQ-PATCH-VERIFY-03: Verification MUST run after all patches are applied, not per-patch
---
## v1.35.0 Features
- [New Runtime Support (Cline, CodeBuddy, Qwen Code)](#104-new-runtime-support-cline-codebuddy-qwen-code)
- [GSD-2 Reverse Migration](#105-gsd-2-reverse-migration)
- [AI Integration Phase Wizard](#106-ai-integration-phase-wizard)
- [AI Eval Review](#107-ai-eval-review)
---
### 104. New Runtime Support (Cline, CodeBuddy, Qwen Code)
**Part of:** `npx @opengsd/gsd-core`
@@ -2465,6 +2470,7 @@ v1 supports **directory-prefix matching only, not glob syntax**: no glob engine
**Produces:** `{phase}-EVAL-REVIEW.md` with scored eval dimensions, gap analysis, and remediation steps
---
## v1.36.0 Features
@@ -2611,6 +2617,7 @@ With `features.global_learnings: true`, phase completion runs the extraction for
**Configuration:** `workflow.tdd_mode`
**Reference files:** `tdd.md`, `checkpoints.md`
---
## v1.37.0 Features
@@ -2708,6 +2715,7 @@ With `features.global_learnings: true`, phase completion runs the extraction for
**Configuration:** `graphify.enabled`, `graphify.build_timeout`, `graphify.graph_path`
**Reference files:** `commands/gsd/graphify.md`, `bin/lib/graphify.cjs`
---
## v1.40.0 Features
@@ -2760,7 +2768,6 @@ With `features.global_learnings: true`, phase completion runs the extraction for
---
### 124. Context-Window Utilization Guard
**Command:** `/gsd-health --context`
@@ -2791,6 +2798,7 @@ With `features.global_learnings: true`, phase completion runs the extraction for
**Reference issue:** [#2833](https://github.com/open-gsd/gsd-core/issues/2833) — see [`docs/STATE-MD-LIFECYCLE.md`](reference/state-md.md) for the full field reference and rendering rules.
---
## v1.41.0 Features
@@ -2919,6 +2927,7 @@ Source commit: abc1234 (3 commits behind HEAD)
**Reference issue:** [#3170](https://github.com/open-gsd/gsd-core/issues/3170)
---
## v1.42.1 Features
@@ -3131,6 +3140,8 @@ explicit reviewer flags -> --all -> review.default_reviewers -> all detected rev
- REQ-JSON-ERRORS-02: CLI exit code mapping MUST remain stable for automation callers.
- REQ-JSON-ERRORS-03: Human-readable output MUST remain the default when `--json-errors` is absent.
**Reference:** [JSON Error Mode](json-errors.md)
---
### 143. UAT-Passed Predicate
@@ -3165,16 +3176,6 @@ explicit reviewer flags -> --all -> review.default_reviewers -> all detected rev
---
## Related
- [Commands](COMMANDS.md)
- [Configuration](CONFIGURATION.md)
- [docs index](README.md)
**Reference:** [JSON Error Mode](json-errors.md)
---
### 144. Spec-Phase Edge-Completeness Probe
**Command:** `/gsd-spec-phase`
@@ -3213,6 +3214,7 @@ The load-bearing wire is the `plan-phase` lift: `covered` and `backstop` edges b
**Reference:** [Edge Probe](../gsd-core/references/edge-probe.md)
---
## v1.43.0 Features
@@ -3237,6 +3239,8 @@ The load-bearing wire is the `plan-phase` lift: `covered` and `backstop` edges b
See [Configuration Reference](CONFIGURATION.md#mempalace-settings) for full schema and [How to enable cross-session memory with MemPalace](how-to/enable-cross-session-memory-with-mempalace.md) for a setup walkthrough.
---
### 146. Spec-Phase Prohibition Probe
**Command:** `/gsd-spec-phase`
@@ -3273,6 +3277,7 @@ The load-bearing wire is the `plan-phase` lift into `must_haves.prohibitions`, s
**Reference:** [Prohibition Probe](../gsd-core/references/prohibition-probe.md)
---
### 147. Capability Management Command
@@ -3291,6 +3296,9 @@ The load-bearing wire is the `plan-phase` lift into `must_haves.prohibitions`, s
**Trust boundary:** install never executes capability code (copy-only staging); executable surfaces require explicit consent; sources are gated by the **project-scoped** `capabilities.strict_known_registries` policy (fail-closed on a malformed/unparseable value); every shared-config write/delete is realpath-confined to the scope root, and a name collision with a user's `mcpServers` entry is never clobbered.
**Reference:** [`gsd capability` command reference](reference/gsd-capability-command.md) · [ADR-1244](adr/1244-capability-ecosystem.md)
---
### 148. Smart Entry Launcher
**Command:** `/gsd-next`
@@ -3310,6 +3318,7 @@ The load-bearing wire is the `plan-phase` lift into `must_haves.prohibitions`, s
**Reference:** [Smart Entry Design](superpowers/specs/2026-06-27-gsd-smart-entry-design.md)
---
## v1.7.0 Features
@@ -3410,6 +3419,8 @@ The load-bearing wire is the `plan-phase` lift into `must_haves.prohibitions`, s
**Configuration:** `graphify.graph_path`
---
### 159. Complexity-Triggered Refactor
**Behavior:** An `execute:post` step measures the complexity of the files a phase touched (decision-point counting over comment- and literal-stripped source, no external dependency) and surfaces a scoped refactor proposal at `.planning/phases/<N>/<NN>-REFACTOR.md` when a function's score exceeds `refactor.complexity_threshold` or its growth over its recorded anchor exceeds `refactor.complexity_jump_delta` — whichever trips first, both reported. Trigger semantics are strictly greater (ESLint's `complexity: {max: N}` convention), so a score exactly equal to the threshold does not trigger. The anchor is set the first time a function is observed and moves only when the proposal is dispositioned via `refactor accept` or `refactor decline` — never when the score alone improves — so the jump delta is cumulative growth since the last conscious decision about that function, not the change made in a single phase. Advisory by default: the proposal is informational only, never edits code, and never blocks. Opt-in `refactor.trigger_strict` records an untriaged proposal as an open `deviation` entry in the broken-windows ledger (#1950) instead — it does not block on its own; ship-blocking is broken-windows' existing `ship:pre` gate, enabled separately with `workflow.windows_enforce`. Without broken-windows installed, strict mode still records the proposal locally and says so. Enabling `refactor.trigger_strict` without `workflow.windows_enforce` also on (or with broken-windows absent) surfaces a typed `refactor_strict_not_enforcing` warning on every triggering evaluate, naming the exact remediation, so this enforcement gap is never silent. A declined proposal resolves its ledger entry as `waived` with the recorded reason; an accepted one resolves as `fixed`. The metric is approximate by construction: biased against a flat `switch`, blind to nesting depth, JS/TS-family only, and a renamed function loses its anchor (issue #1953).
@@ -3487,6 +3498,8 @@ See [Resolve verify-command path findings](how-to/resolve-verify-command-path-fi
**Reference:** [Configuration](CONFIGURATION.md) · [Read the statusline freshness marker](how-to/read-the-statusline-freshness-marker.md) · [ADR-2164](adr/2164-statusline-scope-boundary.md)
---
### 163. Read-Only Planning Snapshot (`planning inspect`)
**Command:** `gsd-tools query planning inspect`
@@ -3510,6 +3523,8 @@ See [Resolve verify-command path findings](how-to/resolve-verify-command-path-fi
**Reference:** [CLI Tools](CLI-TOOLS.md#planning-inspect) · [Consume the planning snapshot](how-to/consume-the-planning-snapshot.md)
---
### 164. Live-DOM UAT Capability
**Config key:** `workflow.live_dom_uat` (default `false`)
@@ -3554,6 +3569,8 @@ See [Resolve verify-command path findings](how-to/resolve-verify-command-path-fi
**Reference:** [Configuration](CONFIGURATION.md#parallel-reviewer-lanes-for-gsd-review-3034) · [Enable parallel reviewer lanes](how-to/enable-parallel-reviewer-lanes.md) · [Commands](COMMANDS.md)
---
### 166. Machine-Readable State Contract (`.planning/state.json`)
**Purpose:** External tools that display GSD project state — a workbench, a dashboard, an editor extension — had to parse `STATE.md` and `ROADMAP.md` heuristically. Those are human surfaces: their shape drifts as the templates evolve, and every consumer ends up carrying a brittle second parser that silently reports wrong numbers after an upgrade. GSD now publishes a small, versioned JSON snapshot instead, so the reader binds to a contract rather than to markdown (#3227).
@@ -3608,6 +3625,7 @@ See [Resolve verify-command path findings](how-to/resolve-verify-command-path-fi
- The adjacent **vacuous pass** — a command that runs successfully and asserts nothing, such as a test-name filter matching zero tests and exiting 0 — is a distinct problem and is explicitly out of scope.
See [State a failing direction](how-to/state-a-failing-direction.md) and [`gsd-tools check verify-failure-directions`](COMMANDS.md#gsd-tools-check-verify-failure-directions).
---
### 168. Runtime Identity
@@ -3625,3 +3643,15 @@ See [State a failing direction](how-to/state-a-failing-direction.md) and [`gsd-t
**Known limits:** an installation of this package old enough to predate `bin/gsd_run` ([#381](https://github.com/open-gsd/gsd-core/issues/381)) is no longer reachable through the `PATH` branch and must be upgraded or invoked through one of the path-based branches. The `runtime-identity` verb is a manual diagnostic, not an automatic gate — nothing currently asserts identity on every invocation, which remains open for a future release now that the byte budget is understood. Path-based resolution branches are unchanged and still trust their configured location.
**Reference:** [`runtime-identity`](COMMANDS.md#runtime-identity) · [Diagnose which gsd-tools is running](how-to/diagnose-a-foreign-gsd-tools.md)
---
_Generated by `scripts/gen-features.cjs` — add a fragment under `docs/features/` and run `--write`._
<!-- FEATURES:END -->
## Related
- [Commands](COMMANDS.md)
- [Configuration](CONFIGURATION.md)
- [docs index](README.md)