Files
msd-core/CHANGELOG.md
Tom Boucher 94ce20089a chore: purify CHANGELOG parenthetical product descriptions (#1777)
The 1.5.0 release section rendered two product-name parentheticals that
the product-name-purity gate (#1777) forbids:

  Claude Code (background dispatch is kept ...)
  Claude (`~/.claude/skills/gsd-ns-<router>/skills/<stem>/SKILL.md`)

Rewritten to the already-accepted forms (semicolon clause; "Claude at
`path`") so the back-merge into next passes the gate next enforces.
No code or behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 11:38:05 -04:00

112 KiB
Raw Blame History

Changelog

All notable changes to GSD will be documented in this file.

Format follows Keep a Changelog.

Unreleased

[1.5.0] - 2026-06-17

Added

  • gen-capability-registry now rejects duplicate artifact producers at the same Loop Extension Point — if two capability steps declare produces: [<same artifact>] at the same point, the generator throws at gen time naming the artifact, the point, and the producing capability ids, instead of letting the topological sort pick a winner silently (which left ADR-857 Decision #6's data-flow contract undefined). The check counts distinct (capId, stepIdx) producer steps, so a single step listing an artifact twice does not false-positive. ADR-894 §4's enumerated cross-capability invariant list gains the artifact-production-uniqueness rule. (#1123) (#1131)
  • gsd-tools drift-guard — deterministic plan-drift severity/authority decisions (ADR-22). The plan-review source-grounding pass now classifies cited-symbol drift through a tested seam (5-rung authority ladder, grep→intel auto-upgrade, severity mapping, rung≥3 hard-block) instead of re-deriving the rules from workflow prose on each run. (#1190) (#1242)
  • /gsd-progress --next --auto --converge now routes planning through plan-review convergence. ADR-15's designated primary convergence surface is wired into the progress/next workflow (previously only /gsd-autonomous --converge honored it; on /gsd-progress the flag was silently dropped). Accepts --cross-ai as an alias plus reviewer flags and --max-cycles N, and is gated on workflow.plan_review_convergence. (#1190) (#1237)

gsd-tools query teams-status + a plan-phase warning detect claude-code agent-teams — GSD's multi-agent orchestration can stall under claude-code's experimental agent-teams (a subagent's completion can fail to route back to the orchestrator). A new read-only query teams-status command reports { active, runtime, env_present, source } (and --active for a clean shell guard), and /gsd:plan-phase now emits a single non-fatal warning when agent-teams is detected, recommending you disable it for GSD workflows. The detector only activates on the claude runtime with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS strictly truthy — every other runtime and the teams-off path are completely unaffected. (#1355) (#1371)

  • spec-phase: prohibition probe — a prose-orchestrated Step 5.6 that surfaces the unwritten must-NOT constraints (values/safety/ethics) a feature could silently become but the spec never forbids. Two stages per requirement: an adversarial recall question ("what could this silently become that the author would NOT want?") then a one-pass precision classifier that drops routine engineering and keeps genuine prohibitions. Confirmed prohibitions become NEGATIVE SPEC acceptance criteria carrying a test/judgment verification tier, which plan-phase lifts into the must_haves.prohibitions sibling block (truths untouched). Judgment-tier items soft-gate at verify time (never silent, never hard-halt); unwired test-tier items fail closed. The recall stage is model-driven (no compiled engine); canon-bound concerns (OWASP/GDPR/fairness) are referred to /gsd:secure-phase. Additive and optional: existing SPECs without a Prohibitions section remain valid. Second adapter of the probe-core resolution model (ADR-550 Decision 7). (#1149)
  • Optional ## Business Context section in the PROJECT.md template — a four-field block (Customer, Revenue model, Success metric, Strategy notes) for monetized or customer-facing projects, positioned between Core Value and Requirements. Optional by default (an HTML comment tells non-business projects to delete it), capped at four one-line fields to stay a constraint reference rather than a business plan, and reviewed at each milestone by /gsd-complete-milestone when present. (#72) (#756)
  • Async external jobs can now defer an Execute step legally (external_job_waiting). An Execute step that dispatches a long-running external job and commits a .planning/async-jobs/<job>.json manifest — deferring SUMMARY.md — is now recognized as a legal deferred state, not an illegal partial-plan state. execute-phase safe-resume, resume-project, and pause-work reconcile against the manifest instead of re-dispatching (which would duplicate the external compute). This defines the versioned, scheduler-agnostic manifest stability contract consumed by the core loop; the scheduler adapter that produces manifests is the capability half (#1164). (#1165) (#1221)
  • MemPalace memory capability (opt-in) — adds cross-session/cross-project recall and verbatim+temporal-KG capture at GSD loop boundaries via the MemPalace MCP server and CLI; disabled by default, skip-on-error. (#1201) (#1201)
  • spec-phase: spec-completeness edge-probe — a taxonomy-driven Step 5.5 that walks each SPEC requirement against a closed 8-category edge taxonomy (boundary, adjacency, empty/degenerate, encoding, ordering, precision, idempotency, concurrency), proposes concrete candidate edges, and resolves each to covered/dismissed/backstop/unresolved. covered edges add acceptance criteria the planner lifts into must_haves.truths; a soft gate flags unresolved edges. Additive and optional: existing SPECs without an Edge Coverage section remain valid. (#584)
  • phase uat-passed predicate — new runtime-neutral command evaluates HUMAN-UAT results with markdown-aware parsing (ignores frontmatter, fenced code, blockquotes, and HTML comments) and reports pass only when every required check passes. (#1063) (#1063)
  • Bug-report issues that lack a valid GSD Version are now auto-closed on open by a new version-gate.yml GitHub Actions workflow. GitHub Issue Forms only enforce required: true in the web UI, so issues filed via the REST API, gh issue create, or AI reporters can arrive without a version; values like idk, _No response_, or an empty field are treated as missing. Affected issues receive a closing comment with instructions to add the version (e.g. 1.18.0) and reopen; maintainers can add the version-exempt label to opt an issue out. (#1181)
  • Kimi CLI runtime support is now documented and installable — users can install global GSD Agent Skills with --kimi --global, invoke them as /skill:gsd-*, and launch the generated custom agent explicitly with kimi --agent-file. The custom-agent (--agent-file) surface targets the legacy/Python kimi-cli contract; newer Kimi Code (@moonshot-ai/kimi-code) consumes the same /skill:gsd-* skills via --skills-dir instead. (#743)
  • agent_skills can now reference Claude-Code plugin-provided skills via the namespaced global:<plugin>:<skill> form (e.g. global:coderabbit:code-review). On the Claude runtime the agent's skills block emits a by-name Skill-tool load directive that resolves the plugin skill (no plugin-cache path is read); path-resolvable skills keep the existing @-include unchanged; on non-Claude runtimes a namespaced entry is skipped with a warning. The 22 agent_skills-consumer agents now carry the Skill tool so they can load plugin-provided skills. (#1261)
  • gsd-tools capability set — turn capabilities on/off and gate hooks from one command. Adds the write side of the capability system (ADR-857/ADR-1213): capability set <id> --on|--off toggles a capability through the runtime surface (the canonical on/off switch) and --gate <key>=<true|false> toggles a hook within an enabled capability, then re-resolves and reports — so disabling a capability is consistent across surface and config ("off means off") as a write-time invariant. /gsd:settings capability hook-gates now route through it. (#1213) (#1225)

Changed

  • Added an opt-in anthropic-fable model policy provider preset for Claude Fable 5 high-budget routing while preserving the existing Anthropic Opus 4.8 defaults and anthropic provider preset. (#1014) (#1015)
  • Windsurf/Devin workspace skills now install to the canonical .devin/skills/ directory — fresh workspace installs write skills under .devin/skills/ (Devin Desktop's documented preferred location) instead of .windsurf/skills/; the legacy .windsurf/skills/ layout is still recognized. The global ~/.codeium/windsurf/skills/ path is unchanged. (#1093) (#1093)

loadCentralConfigKeys now fails loud on a malformed central config-schema instead of silently returning an empty Set — ENOENT (the schema legitimately absent) still returns an empty Set silently, but a JSON parse error or any other read failure now writes a prominent stderr warning naming the schema file and throws ExitError(1). Previously a single catch (_) swallowed parse errors too, so a merge-conflict marker or truncated write in config-schema.manifest.json made every capability config key look non-central — the config-key collision / pending-migration gate fired zero warnings and --check passed clean, defeating the gate invisibly. (#1124) (#1131)

  • Capability hook rendering now consumes resolved Capability State — gsd-tools loop render-hooks uses the same installed/surfaced/configured state reported by gsd-tools capability state, so disabling a migrated capability at the runtime surface removes its workflow hooks even when config defaults are enabled. Migrated capability config keys remain accepted through the generated capability registry/federated config path instead of duplicated central VALID_CONFIG_KEYS entries. (#1136) (#1153)

Added ADR-857 Phase 6 capstone conformance coverage so migrated Capability activation keys cannot be read directly from host loop workflows, Capability-owned config keys stay out of the central schema, and the host loop workflow size budgets remain documented. The verify-work UI automation preflight now resolves UI activation through the Capability hook registry instead of reading workflow.ui_phase directly. (#1158)

  • ADR-857 phase 6 complete: optional features are now Capabilities, not inline loop branches. tdd, schema-gate, drift, gap-analysis, and profile-pipeline are migrated out of the five-step host loop into declarative Capabilities (loop hooks + a command family); their config keys are federated to capability ownership; and the plan-phase/execute-phase workflow bodies shrink accordingly. Two previously-declared-but-dead capability gates now actually fire — the security ship-time gate (ship:pre) and the UI safety gate (execute:wave:post) — and the phase-6 conformance gate is hardened to be un-gameable (rejects empty stubs, requires loop-body shrink, verifies hook dispatch and gate-result contracts). Behavior is preserved, verified across five adversarial review passes. (#1139, #1167, #1168, #1169) (#1183)

Test-tier prohibitions are now a real, provable gate instead of a permanent, unsatisfiable gaps_found — the deferred ENFORCEMENT half of ADR-550 Decision 5d (the "heavy half" that #644 / PR #1149 deferred) has landed. A new deterministic check prohibition-enforcement sub-command (authored as src/prohibition-enforcement.cts, compiled by build:lib to the gitignored gsd-core/bin/lib/prohibition-enforcement.cjs) is the missing PRODUCER: it locates the wired mechanical check, runs it for a genuine non-vacuous pass, builds enforcementEvidence, and emits the dispositionForProhibition() verdict. The previously-unreachable green branch in dispositionForProhibition() is now reachable from the live pipeline — a test-tier prohibition with a genuinely-passing wired check disposes green and can reach passed, while a missing, non-attested, or non-passing check hard-gates (flagged, never green → gaps_found) in BOTH interactive and autonomous modes (ADR-550 D4 / D3). verify-phase.md wires the consumer; the green/fail-closed policy in src/probe-core.cts is untouched. Both wired-check kinds are accepted (ADR-550 D2): a node --test negative test (requiring a real reported test — an empty file, which node --test counts as one passing "test", does NOT green) AND a lint/AST rule run as eslint --format json filtered by ruleId (so plugin rules like local/* load — bare --rule cannot), anchored on the in-tree local/no-source-grep rule (dogfooding, ADR-550 D4). This enforcement seam is the concrete instance of ADR-857 open-question §147 and lands on the core verify rail, never in capabilities/ (D6). (#1259)

Honest scope — failFirst is caller-attested, not yet machine-proven. This lands the execution + non-vacuous-pass half: the producer requires the caller to attest failFirst: true and the check to genuinely run and pass. It does NOT yet independently prove the check fails-on-violation (the literal regression-must-fail-first property) — cheap proof of that at verify time needs running the check against a known violation fixture, which is a tracked follow-up (#1279). The red-first property currently rests on caller attestation, surfaced transparently in the evidence record.

Correction to the issue body (#1259): the issue's "96 invalid/error negative-proof cases" figure is wrong. For the no-source-grep anchor specifically, the genuine regression-must-fail-first proofs are its two invalid cases (the .includes() and .match() blocks) in tests/eslint-rules.test.cjs — not 96. The anchor argument is unaffected (those two cases ARE real fail-first proofs); only the count was off. (#1273)

  • The test-tier prohibition gate now has a deterministic SOURCE for its wired check — a resolved test-tier must_haves.prohibitions item MAY carry an optional check descriptor authored at spec-phase: the flat-scalar keys check_kind (node-test | lint-rule), check_target, and check_rule (lint-rule only). projectProhibitions projects these scalars deterministically and verify-phase reads them back (via descriptorFromProjection) to locate the check handed to check prohibition-enforcement — so a wired, passing test closes the gap with zero manual descriptor authoring (previously the verify-phase LLM had to invent {kind, target, rule} each run, #1259). This extends the ADR-550 Decision 3 prohibition-item shape (ratified in a dated 2026-06-15 ADR-550 addendum). The descriptor is optional and fully backward-compatible — a prohibition with no descriptor parses and disposes byte-identically to today — and fail-closed: a partial, invalid, or absent descriptor falls through to the producer's existing fail-closed locate, never a silent green. The descriptor is represented as flat scalars (not a nested check:{} object) to keep the shared parseMustHavesBlock round-trip regression-free. Out of scope: machine-proven fail-first (#1279) and the dispositionForProhibition policy stay unchanged. (#1278) (#1301)

Test-tier prohibition fail-first is now MACHINE-PROVEN, not caller-attested — the deferred literal regression-must-fail-first property of ADR-550 Decision 4 (the gap #1259 / PR #1273 left as a tracked follow-up) has landed. The check prohibition-enforcement producer (src/prohibition-enforcement.cts, compiled by build:lib to the gitignored gsd-core/bin/lib/prohibition-enforcement.cjs) no longer trusts the caller's failFirst attestation: before a clean, non-vacuous pass can dispose a test-tier prohibition green, the new defaultProveFailFirst prover independently RUNS the wired check against a KNOWN VIOLATION and confirms it goes RED. Attestation is gone from the green AND (passed = proof.provenFailFirst === true && run.passed === true); any other outcome — passes-on-violation, can't-prove, throws, times out, or no violation source — hard-gates in BOTH interactive and autonomous modes (ADR-550 D4 / D3). The evidence record gains a failFirstProof field recording HOW fail-first was proven (FF-07). A caller can no longer green a toothless check.

The violation is sourced from a new descriptor field, CheckDescriptor.violationFixture — an author-supplied path to a known-bad subject. For a lint-rule the prover lints that fixture and requires the rule id to appear in the JSON report (the rule must have teeth); for a node-test the prover spawns the negative test with the subject injected through the GSD_PROHIB_SUBJECT env convention and requires a NON-VACUOUS red — # fail >= 1 AND a failing test named distinctly from the file (isNonVacuousNodeTestRed), so a violation fixture that merely CRASHES the test at load is not mistaken for the negative assertion firing red (symmetric with the clean-pass non-vacuity guard). The node-test prover also requires the violationFixture to EXIST (resolved against cwd) before spawning — a missing/typo'd path fail-CLOSES rather than letting an honest test's ENOENT crash forge a green (symmetric with the lint path's file-result guard). The deterministic spec→verify path composes end-to-end: a fourth flat scalar check_violation_fixture is projected by projectProhibitions and read back by descriptorFromProjection (rides both kinds), so a prohibition authored with all four check_* scalars machine-proves fail-first and greens through the projection alone — zero hand-authoring at verify time (#1278 + #1279 + #1346; round-trip pinned by a fast-check property + CHK-03(D) + an end-to-end COMPOSE capstone). One documented residual remains under #1346: the node-test proof confirms the fixture exists and the check reds, but cannot generically prove the red was caused by the subject's content rather than by the env merely being set. The lint-rule path is fully shippable now and is dogfooded against the in-tree local/no-source-grep rule; the node-test path ships its mechanism (a fixture-bearing descriptor IS machine-proven) and is exercised by SYNTHETIC temp fixtures — there is no live in-tree node --test prohibition to dogfood. CheckDescriptor.failFirst is DEMOTED, not removed (FF-08): it is kept as a non-authoritative hint so the #1259 route-JSON shape and the CheckDescriptor type stay backward-compatible mid-migration, but no path greens on it alone. The green/fail-closed policy in src/probe-core.cts (dispositionForProhibition, reads only evidence.length > 0) is untouched; the evidence array shape is additive. This closes ADR-550's D5d follow-up — see the dated 2026-06-15 ADR-550 addendum. (#1279)

PR-review flag — GSD_PROHIB_SUBJECT + violationFixture are PROPOSED, renamable conventions. Both are net-new surface with ZERO live in-tree consumers (no in-tree node-test prohibition yet; node-test proof runs only on synthetic test fixtures, the real dogfood stays the lint-rule). They are forward-looking scaffolding, so a later rename — or replacing the env var with an argv — is a mechanical, zero-migration find/replace. Surfacing them here so the maintainer can ratify, rename, or replace them at PR review with no migration cost, exactly as #1278's ADR addendum was reviewed at PR time. The failFirst demotion is likewise open to weighing outright removal; the keep-as-hint rationale is recorded in the ADR addendum. (#1314)

  • Read-only verifier/auditor agents now ship a Claude-Code disallowedTools deny-list — the installer injects a framework-level write-tool deny-list into the Claude copies of the read-only verifier/auditor agents (gsd-verifier, gsd-plan-checker, gsd-integration-checker, gsd-doc-verifier, gsd-eval-auditor, gsd-ui-auditor, gsd-ui-checker) so write actions are blocked even if a tool grant is inherited. Injected for Claude only; other runtimes are unaffected. (#1081) (#1081)

Antigravity workspace skills now install to the canonical .agents/ directory — fresh installs write workspace artifacts under .agents/ (the Google-Codelabs-documented base) instead of .agent/; the legacy .agent/ layout is still recognized so existing installs keep working. The global ~/.gemini/antigravity/ path is unchanged. (#1090) (#1090)

devin-desktop runtime alias for the Windsurf→Devin Desktop rebrand — the windsurf runtime now also answers to devin-desktop (CLI --devin-desktop), aiding discoverability after Cognition rebranded Windsurf as Devin Desktop. All paths are unchanged — global skills still install to ~/.codeium/windsurf/skills/. (#1086) (#1086)

  • Remove dead loadConfig export from configuration.cts — superseded by config-loader.cts (ADR-857 phase 2e, #885). All live callers already import loadConfig from config-loader.cjs or the core.cjs back-compat re-export; exhaustive grep confirms zero callers importing it from configuration.cjs. configuration.cjs now provides only the pure normalization and defaults primitives (normalizeLegacyKeys, mergeDefaults, migrateOnDisk, CONFIG_DEFAULTS) that config-loader.cjs depends on. (#893) (#893)
  • audit(#779): correct stale model-catalog IDs verified against live provider sources. The gemini opus default gemini-3-pro → gemini-3.1-pro-preview (the bare gemini-3-pro ID is undefined in gemini-cli source — only gemini-3-pro-preview/gemini-3.1-pro-preview exist) and the codex sonnet default gpt-5.3-codex → gpt-5.4 (deprecated per OpenAI's Codex models page); the same two IDs are also updated in the google/openai provider-preset entries. qwen3-coder-next was verified valid (callable on Alibaba Model Studio) and left unchanged. Adds a regression guard against the retired IDs and a sourcing/verification note in CONFIGURATION.md. Catalog IDs are internal defaults; users who pinned the old IDs must update their config. (#1047)
  • INVENTORY.md no longer carries (N shipped) count scalars — the hand-maintained absolute counts collided silently on merge (two branches each bumping the same integer to N+1 while the merged tree held N+2), red-flagging CI on the merge commit across all platforms. The manifest's name-set is now the sole registry, anchors are count-free and stable, and a guard test blocks re-adding a count. (#1179) (#1179)
  • Edge-probe precision probe text now names tie-breaking / rounding-mode (half-up vs half-to-even, ceil/floor/truncate), so a surfaced precision edge cues the most common rounding failure mode. Prose-only; firing rule and the 8-category core unchanged. (#1108)
  • Capability manifests now declare runtime compatibility through a validated runtimeCompat contract, and runtime descriptor interpreters now read artifact layout, skills-home, and hook-surface facts directly from runtime Capability descriptors instead of parallel runtime-name allowlists or fallbacks. This preserves existing supported runtime behavior while making future descriptor-backed runtimes additive. (#1157)
  • Planning-time research, AI integration, and pattern mapping now participate through Capability declarations and rendered plan:pre hooks, with developer documentation for building GSD capabilities. (#1141)
  • The planner now blocks plans that would self-trip their own verify gate — when an acceptance criterion negative-greps for a literal (grep -c 'LIT' file == 0) and that same literal appears verbatim in an <action> body, plan creation now fails at write time instead of letting the executor waste cycles on a comment-text echo at commit time. Unquoted/ambiguous grep targets warn instead of failing; add <!-- planner-discipline-allow: LIT --> to allowlist a legitimate occurrence. (#1062) (#1062)
  • Namespace router skills now nest their concrete sub-skills at install time (#69). On runtimes with non-recursive skill loaders (Claude global, Cline, Qwen, Hermes, Augment, Trae, Antigravity) the installer emits the 6 gsd-ns-* routers as the only top-level skill bundles and nests the ~61 concrete skills under <router>/skills/<name>/SKILL.md, cutting the eager skill-listing overhead to ≈6 entries. Concrete skills stay reachable via the router's Read skills/<name>/SKILL.md routing table. Breaking: on those runtimes the concrete skills are no longer invocable by bare name through the Skill tool / top-level listing — route via the namespace router (or the unchanged /gsd-* slash command where a commands surface exists). Legacy top-level gsd-<concrete>/ skill dirs are removed on upgrade. Recursive/unconfirmed loaders (Cursor, Codex, Copilot, Windsurf, CodeBuddy, OpenCode, Kilo) keep the flat layout. (#883)
  • Graphify now respects surface/profile state, not just graphify.enabled — gsd-tools graphify is off unless graphify is installed AND surfaced AND graphify.enabled is true (previously only the config key was checked). The gate is now runtime-aware: Codex/Cursor/etc. read their own runtime's surface instead of ~/.claude. (#1313) (#1313)
  • Isolated-executor recovery now fails safe — when an isolated (worktree) executor run is rejected (you decline to merge it) or over-reached the requested scope, /gsd:execute-phase and /gsd:quick no longer default or propose recovery by editing the primary checkout (main). The orchestrator halts safely and offers a fresh, narrowly-scoped worktree or inspect/discard; editing the primary checkout requires explicit, clearly-labeled confirmation. (#1292) (#1303)
  • Migrate code review, security, and Nyquist verification workflows to ADR-857 capability hooks. (#1147)
  • Intel and loop-hook rendering now honor the single capability active state — gsd-tools intel gates through the shared resolver (consistency; intel stays governed by intel.enabled), and loop-hook rendering now suppresses a config-disabled capability's hooks via the capability-level active gate (fail-closed), not just per-hook when. (#1315) (#1315)
  • Added no-drift guard tests (tests/issue-57-runtime-install-no-drift.test.cjs) that protect the Runtime Install Policy Module boundary (ADR-58) and the explicit Runtime Config Adapter Registry (#60). They fail loudly when supported-runtime metadata is added to an installer call site (allRuntimes, the interactive runtimeMap menu) without a matching registry adapter entry, or when config-mutation dispatch escapes the registry's declared install surfaces — catching reintroduction of the scattered per-runtime branching those seams removed. (#867)
  • Edge-probe now surfaces a zero-classification requirement (non-empty prose, no shape cue matched, no shapes override) as a single soft unclassified — review manually candidate instead of silently dropping it. Dismissible like any edge; shapes: [] opt-out stays silent; TAXONOMY unchanged. (#1117)
  • Capability state now reports a tri-state active — gsd-tools capability state adds an active field per capability (installed && surfaced && config-enabled), alongside the existing enabled (installed && surfaced). Internal isCapabilityActive(capId, cwd) lets consumers honor the single resolved on/off answer. (#1311) (#1311)
  • gsd-verifier no longer marks behavior-dependent must-haves VERIFIED on symbol presence alone — a truth that asserts a state transition or a cancellation/cleanup/ordering invariant is marked PRESENT_BEHAVIOR_UNVERIFIED when no test exercises it: excluded from the verified_truths score, reported as a behavior_unverified count, and routed to human verification, so a clean N/N now certifies behavioral evidence rather than mere symbol presence. (#966) (#1271)
  • verify plan-structure warns on cross-task region-scope conflicts (#968) — when a plan task's file-wide negative grep (! grep -Eq 'PAT' file / grep -c 'PAT' file == 0) bans a construct a sibling task legitimately requires elsewhere in the same file, plan validation now surfaces a warning pointing to the new region/function-scoped negative-gate idiom (documented in the gsd-planner guidance and the planner-antipatterns reference, with a worked banned-in-X / required-in-Y example). Warn-only: it never errors and never changes valid. (#1320) (#1320)

Fixed

  • gsd-intel-updater now writes the canonical intel filenames the gsd-tools intel CLI actually reads — the agent was instructed to emit short names (files.json, apis.json, deps.json) and a markdown arch.md, but the intel library reads only file-roles.json, api-map.json, dependency-graph.json, and arch-decisions.json (JSON). After /gsd:map-codebase --query refresh the output was orphaned, so intel status/validate reported the files missing and intel query returned nothing. The agent now emits the canonical long names and structured arch-decisions.json. (#1000) (#1037)
  • Installer no longer appends a duplicate managed hook when it is registered via an HTTP route — a hook re-registered as a type:"http" entry (local hook-server routing) carries its identity only in url, which the installer's presence check ignored, so a stock command duplicate was appended on every install/update and the hook ran twice per event. The presence check now also inspects h.url. (#1004) (#1032)
  • /gsd-code-review's fallow structural pre-pass now actually runs and delivers findings — it invoked fallow with flags no published fallow version accepts (--json, --profile, --stdin-files), so the pre-pass failed on every run and silently degraded (the structural-findings feature never delivered on any fallow version). It now uses fallow's real CLI (audit --format json --quiet, --changed-since for phase scope, and --max-crap mapped from the code_quality.fallow.profile preset: minimal→50, standard→30, strict→15), treats fallow's exit code 1 ("issues found") as a successful run instead of a crash (gating on a valid JSON report, not the exit code), and normalizes fallow's real audit --format json schema (dead_code.*, duplication.clone_groups) into the reviewer's <structural_findings> contract. The report normalizer — previously dead code parsing a schema fallow never shipped — is wired to the real schema and exercised against real fallow output. (#1012) (#1044)
  • worktree base-check now honors a user/global worktree.baseRef:"head" (and CLAUDE_CONFIG_DIR) — base-check resolved baseRef from the project checkout's .claude/ only, so a machine-wide head set via /config (the layer the harness itself honors) was invisible. On any phase/feature lane it returned shouldDegrade:true and execute-phase silently forced sequential execution, losing the parallel worktree execution the user configured. Resolution now falls back to the user/global settings.json (via getGlobalConfigDir('claude'), honoring CLAUDE_CONFIG_DIR) below the existing project-local and project-shared layers. (#1013) (#1038)
  • Agent SDK/state/commit steps now resolve gsd-tools on shim-only installs for every runtime — source agents/*.md (gsd-planner, gsd-executor, gsd-verifier, gsd-plan-checker, …) invoked bare gsd-tools …, which fails with command not found on shim-only installs where the binary is only reachable as <runtime-home>/gsd-core/bin/gsd-tools.cjs and is not on PATH. The agent then silently skipped init/state/validate/commit ceremony. #725 fixed only Codex's conversion layer; the source agents were never migrated, so the bug persisted on Claude Code and every other runtime that consumes the source agents directly. All 12 gsd-tools-calling agents now carry the canonical multi-runtime gsd_run resolver (the same preamble the workflow launchers use — covering claude/codex/cursor/gemini/copilot/windsurf/augment/trae/qwen/cline/opencode/kilo/hermes/antigravity homes), gsd-phase-researcher's stale claude-only resolver is upgraded to the canonical one, and the launcher-parity + bare-call regression guards are extended to agents/ so no runtime can silently regress. (#1041) (#1045)
  • gsd-tools generate-claude-md no longer clobbers a hand-crafted CLAUDE.md, and defaults the Claude-runtime output to ./.claude/CLAUDE.md — /gsd-new-project wrote a repo-root CLAUDE.md full of broad project documentation, overwriting/diluting an existing hand-authored instruction file. Now: (1) an existing instruction file that contains no GSD section markers (a hand-crafted file) is left untouched and the command reports action: "skipped" — pass --force to overwrite intentionally (the flag was already parsed but ignored); (2) the default output for Claude-family runtimes is ./.claude/CLAUDE.md (a valid project-scoped memory location) instead of repo-root ./CLAUDE.md, so generated content does not pollute a repo-root file. The config default (claude_md_path), the project config template, and the new-project workflow are aligned to the new location. Codex projects still write AGENTS.md. (#1098) (#1118)
  • state record-session updates an existing ## Session Continuity section in place instead of appending a duplicate ## Session block — on a freshly bootstrapped project (workstream / gsd2-import / new-project templates all emit ## Session Continuity), the auto-create path recognised only the normalized ## Session heading, so it appended a second session block. It now inserts only the missing canonical fields after the ## Session Continuity heading, preserving the heading and any existing prose, and the snapshot / frontmatter readers recognise that heading. (The originally reported recorded:false-yet-mutated symptom was already resolved by #944/#948.) (#1101) (#1113)
  • roadmap annotate-dependencies no longer fuses the preceding summary line onto the Plans: header — when the match regex's (?:^|\n) anchor consumed a leading newline (mid-string match), the replacement dropped it, producing corrupted output like **Plans:** 3 plansPlans:. The replacement now re-emits the leading newline when present. (#1103) (#1111)
  • /gsd-progress no longer reports a phase as complete (and routes to the next phase) when its verification ended human_needed or gaps_found — routing derived completeness from plan/summary counts only and never consulted the verification.status query (the seam built in #651). A new Step 1.7 consults it for the current phase, and the routing table sends gaps_found to /gsd:plan-phase {phase} --gaps (Route V.gaps) and human_needed to /gsd:verify-work {phase} (Route V.human) before the generic complete row. passed, missing (unverified), and unknown still route as complete, so unverified phases are not falsely blocked. (#1107) (#1116)
  • write-profile now writes USER-PROFILE.md to the active runtime's config home instead of always ~/.claude — under Codex, gsd-tools query write-profile wrote ~/.claude/gsd-core/USER-PROFILE.md while Codex discuss-phase advisor-mode (installed under ~/.codex) checked the Codex home and never found it, so advisor-mode silently stayed disabled. The default output path is now resolved via the runtime-aware getGlobalConfigDir (GSD_RUNTIME / config.runtime → e.g. ~/.codex for Codex), matching how the runtime's own workflows resolve it — mirroring generate-dev-preferences. Claude is unchanged (~/.claude); an explicit --output still wins. (#1114) (#1119)
  • /gsd:review no longer produces a silent empty Codex review on codex-cli < 0.137 — the codex exec invocation passed --dangerously-bypass-hook-trust (added in codex 0.137.0) unconditionally and discarded stderr, so on older CLIs codex exited with unexpected argument before reading the prompt and the empty output was treated as a completed review. The flag is now capability-probed (codex exec --help | grep) and applied via $CODEX_BYPASS_FLAG only when supported, codex stderr is captured to a .err file instead of /dev/null, and an empty Codex output is replaced with a diagnostic so a broken reviewer is surfaced rather than silently skipped. (#1115) (#1122)
  • sandbox_mode emission in Codex TOML is now gated on the runtime descriptor's sandboxTier axis — previously installCodexConfig emitted sandbox_mode unconditionally from a hardcoded policy map regardless of whether the runtime descriptor declared a sandbox tier, making the descriptor field cosmetic. resolveInstallPlan now projects sandboxTier from the capability registry, and generateCodexAgentToml / installCodexConfig gate emission on sandboxTier !== 'none'. The per-agent mode table CODEX_AGENT_SANDBOX remains GSD agent policy (not a runtime-descriptor property). For codex (sandboxTier === 'codex-agent-sandbox') output is byte-identical to before; for all other runtimes (sandboxTier === 'none') sandbox_mode is correctly omitted. resolveInstallPlan now fails loud (throws TypeError) on a missing or invalid sandboxTier descriptor axis rather than silently coercing garbage to 'none', preventing a corrupt/stale registry from silently dropping sandbox enforcement. Full removal of the per-agent registration-tax map remains tracked under #1138. (#1151) (#1152)
  • Installed runtimes no longer silently disable verify:post gates — in a global skills-runtime install (e.g. Codex at ~/.codex), the commands/gsd source tree is absent, so capability-state resolved an empty skill manifest. The full-profile * sentinel then materialized to an empty surfaced set, marking every capability surfaced=false → enabled=false. The result: gsd-tools loop render-hooks verify:post returned activeHooks: [] even with security_enforcement and nyquist_validation enabled, so the security and Nyquist gates never fired. Capability-state now falls back to the installed <configDir>/skills/gsd-*/SKILL.md layout when the source tree is unreachable, so verify:post again includes security -> secure-phase and nyquist -> validate-phase. (#1206) (#1206)
  • gsd install no longer warns that settings.local.json "may be malformed" when the file contains a valid JSON null. readSettings now treats a successfully-parsed null as empty settings ({}) instead of collapsing it into the parse-failure path, so a literal-null settings file is preserved silently; genuinely unparseable files still emit the warning. (#1191) (#1233)
  • gsd-tools no longer crashes at load on a fresh install — the installer omitted scripts/fix-slash-commands.cjs, which command-roster requires at module load, so every gsd-tools command failed with MODULE_NOT_FOUND. The installer now ships it (with a smoke assertion), and readCmdNames() tolerates a missing commands directory. (#1240) (#1240)
  • state begin-phase / complete-phase now advance the frontmatter status for pipe-table STATE.md, not only inline Status: files. The status update matched the YAML frontmatter status: line first and never updated a body | Status | … | cell, so the frontmatter status froze (e.g. stuck at planning); it now transitions correctly (planning → executing → completed) regardless of whether the body Status is inline or pipe-table. (#1255) (#1256)
  • state planned-phase now advances the pipe-table Status cell (and frontmatter status), and state begin-phase now updates the Current Position | Phase | / | Plan | cells instead of prepending stray inline lines. Systemic follow-up to #1255: planned-phase ran its body-field replacements on the full file content, so the YAML frontmatter status: line was matched before the body | Status | … | cell and the status never reached Ready to execute; and begin-phase had pipe-table branches only for Status/Last activity, so for pipe-table STATE.md the Phase/Plan rows were left stale while a spurious inline Phase: N — EXECUTING line was prepended. Both handlers now strip frontmatter before body-field replacement and update pipe-table cells in place, matching the inline-format behaviour. (#1257) (#1260)

Parallel worktree execution now has executor-authored cleanup metadata — executor agents capture their worktree path, branch, and expected base before task commits and return a parseable metadata block for execute-phase to prefer over runtime harness metadata. (#1297) (#1349)

UAT resume now accepts paused checkpoints — uat render-checkpoint treats a non-structured paused Current Test placeholder as a resume signal and derives the checkpoint from the first pending UAT test instead of failing as malformed. (#1300) (#1350)

phase complete now preserves prose-block STATE phase names — template-shaped Current Position prose now advances with the next phase name, avoids missing-field warnings, and keeps Last activity: on the template em-dash delimiter. (#1316) (#1351)

Claude skill installs now avoid rejected xhigh effort frontmatter — heavyweight GSD skills now ship with portable effort: max, and the Claude skill converter normalizes any remaining xhigh source effort before writing SKILL.md. (#1319) (#1352)

Glued letter-prefix phase directories now resolve correctly -- phase lookup now recognizes tokens like P0.3 and M1-2 from directory names, so phase commands can find their plans instead of reporting none found. (#1324) (#1353)

Update backups now ignore preserved shared skills and hooks -- /gsd-update custom-file detection now mirrors installer cleanup scope for shared runtime roots, so non-gsd-* skills and hooks are not copied into backup folders unnecessarily. (#1325) (#1354)

Codex skills no longer show up twice in autocomplete — GSD's Codex install wrote an agents/openai.yaml sidecar under every managed gsd-* skill directory, and recent Codex builds index both SKILL.md and the sidecar, so each skill appeared twice (once as gsd-foo, once as a humanized foo display name). The installer now stops emitting these sidecars and removes stale ones left by prior installs (pruning the empty agents/ directory), while preserving user-owned skill directories. Codex discovers GSD skills via SKILL.md alone. (#1326) (#1360)

The worktree path guard no longer blocks ordinary writes in non-GSD git worktrees — the gsd-worktree-path-guard PreToolUse hook fired for every Write/Edit in any linked git worktree, so Claude Code plan-mode writing its plan to ~/.claude/plans/<slug>.md from a manually-created worktree was hard-blocked. The hook now only enforces inside a GSD isolated-executor worktree (branch worktree-agent-*) and fails open when a target resolves to no git repository, while still blocking writes that escape to a different git root (the #260 protection) or into a repository's .git internals. (#1342) (#1361)

check.decision-coverage-plan no longer reports a false pass when a D-NN decision header has text before the colon — parseDecisions previously dropped any - **D-NN …:** bullet whose header contained a (parenthetical), em-dash, or other prose before the :**, silently narrowing the trackable set so the blocking coverage gate green-lit a phase whose dropped decisions were never checked. The parser now tolerates a freeform run before the colon (preserving [bracket] tags) and warns on any D-NN bullet it still cannot parse instead of dropping it. (#1343) (#1358)

Codex hooks.json is now always written in the nested { "hooks": { … } } shape Codex expects — the writer previously echoed back whatever shape it read, so an empty, absent, or legacy top-level hooks.json ({ "SessionStart": [...] }) stayed in the legacy shape that current Codex can reject or warn on. Every write now canonicalizes to the nested form, lifting any legacy top-level event entries (including mixed nested+top-level files) under hooks without dropping user-owned entries. Managed-hook dedup/removal is unchanged. (#1348) (#1363)

gsd install --cursor no longer leaves bare ~/.claude paths in installed artifacts — the Cursor install branch only rewrote the trailing-slash .claude forms, so bare ~/.claude / $HOME/.claude references survived into installed skills and workflows (e.g. gsd-surface, gsd-graphify, plan-phase, autonomous) and tripped the post-install "unreplaced .claude path reference(s)" warning, pointing at a directory that doesn't exist on a Cursor-only install. The Cursor branch now rewrites bare forms too (mirroring the Trae/Augment/Copilot branches), using a (?![\w-]) lookahead so .claude-plugin / .claudeignore are not corrupted. (#1356) (#1368)

  • /gsd-new-project and /gsd-new-milestone now self-heal when the research synthesizer returns SUMMARY.md inline instead of writing it — under some context loads the gsd-research-synthesizer agent hits an LLM false-refusal (fabricating a non-existent write restriction) and returns the SUMMARY.md content in its reply rather than writing .planning/research/SUMMARY.md. Prompt hardening (#240) reduced but did not eliminate this. Both workflows now verify the file exists after the synthesizer returns and, if it is missing but content came back inline, the orchestrator persists it before spawning gsd-roadmapper — so the roadmapper never fails with "SUMMARY.md not found". (#222) (#1042)
  • Codex agent TOML generation no longer pins model_reasoning_effort when the agent is intentionally inheriting the active Codex chat model. GSD still emits both model and model_reasoning_effort when a per-agent model override or runtime: "codex" resolver pins the model, avoiding the confusing partial state where the model followed Codex UI selection while effort followed GSD catalog defaults. (#838) (#842)
  • profile-pipeline temp output now lands under the reaped GSD temp root. cmdExtractMessages and cmdProfileSample previously created their output directories directly in os.tmpdir() root (gsd-pipeline-* / gsd-profile-*), which reapStaleTempFiles never scans (it only scans GSD_TEMP_DIR = os.tmpdir()/gsd). The directories accumulated forever. Both sites now call ensureGsdTempDir() and create under GSD_TEMP_DIR. Also adds missing after/afterEach teardown to four test fixtures that leaked gsd-* temp dirs on every npm test run. (#866) (#879)
  • getMilestonePhaseFilter now excludes phase headings inside fenced code blocks ( ``` or ~~~) — consistent with the fence-aware behavior of extractCurrentMilestone. Previously, a ### Phase N: line inside a fenced block was wrongly counted as a real phase. (#875) (#880)
  • gsd_run launcher shim now probes all non-Claude runtime homes before failing. The shim's last-resort detection previously stopped at $HOME/.claude, causing a false-positive fatal error on every non-Claude runtime (Hermes, Cursor, Codex, Copilot, Windsurf, Augment, Trae, Qwen, CodeBuddy, Cline, Grok, Antigravity, OpenCode, Kilo) when RUNTIME_DIR was unset and gsd-tools was not on PATH. The snippet now probes each runtime's config directory (respecting HERMES_HOME, CURSOR_CONFIG_DIR, CODEX_HOME, etc. with sensible $HOME-relative defaults) before emitting the install error. (#903)
  • validate health and validate consistency no longer emit false-positive W007 warnings for projects using checklist-style ROADMAP.md phases. buildRoadmapPhaseVariants() in src/validate.cts previously used only a heading-style regex (## Phase N: name), silently ignoring the supported checklist format (- [x] **Phase N: name**). This caused every on-disk phase directory to trigger W007 ("exists on disk but not in ROADMAP.md") when the project's ROADMAP used checklist-only notation. The fix adds a second regex pass mirroring the existing buildNotStartedPhaseVariants() approach. Additionally, cmdValidateConsistency() in src/verify.cts had a duplicate inline heading-only regex with the same gap — refactored to delegate to buildRoadmapPhaseVariants() (DRY). (#892) (#893)
  • init execute-phase and cmdCommit now produce correct branch_name when project_code is set — the {phase} substitution in phase_branch_template now calls normalizePhaseName(), stripping the project-code prefix and zero-padding the number, so the generated branch is e.g. gsd/phase-01-foundation instead of gsd/phase-CK-01-foundation. Both the execute-phase output path (src/init.cts) and the pre-execution commit path (src/commands.cts) are fixed. (#904) (#904)
  • syncStateFrontmatter no longer strips current_phase, current_phase_name, current_plan, and progress from STATE.md — when body annotations are absent (e.g. after an agent rewrites the body), the existing frontmatter values for those scalars are now preserved, mirroring the fallback already applied in cmdStateJson. (#905) (#905)
  • Top-level Claude Code /gsd-plan-phase now always spawns the researcher/planner/plan-checker agents instead of collapsing them inline — a <runtime_compatibility> block after </available_agent_types> makes the Agent-availability requirement explicit and documents that the workflow fails-closed (stops with a clear log message) in genuinely Agent-less contexts; seven "ORCHESTRATOR RULE — CODEX RUNTIME" labels are renamed to "ALL RUNTIMES" so the guard applies universally; execute-phase.md scopes its existing "Other runtimes" inline-fallback prose to non-Claude contexts, preserving the #853 backgrounded-agent behaviour. (#913) (#913)
  • /gsd-plan-phase, /gsd-execute-phase, /gsd-autonomous no longer carry context: fork — these are spawning orchestrators; a forked subagent context has no Agent tool, preventing them from spawning the subagents they require. effort: xhigh is preserved. Fixes /gsd:autonomous halting with "running as a forked subagent" on 1.4.1 (#921). Also replaces the introspection-based Agent-availability check in plan-phase's <runtime_compatibility> block with an attempt-based gate: the workflow now always attempts the Agent() call and only stops if a real tool-unavailable error is returned, eliminating false-negative aborts in top-level sessions (#922). (#921)
  • Claude global install reverted to flat skill layout so concrete skills are discoverable. PR #883 introduced nested skill layout for Claude at ~/.claude/skills/gsd-ns-<router>/skills/<stem>/SKILL.md, but Claude Code's skill discovery scans only one level under ~/.claude/skills/ — nested concrete skills were never listed in the Skill-tool available-skills list and direct Skill(skill="gsd-plan-phase") calls stopped working. This fix reverts Claude to the flat layout (~/.claude/skills/gsd-<name>/SKILL.md) so all ~61 concrete skills are top-level and immediately discoverable. The 6 other runtimes that confirmed non-recursive scanning (cline, qwen, hermes, augment, trae, antigravity) retain their nested layout. (#924) (#924)
  • gsd-context-monitor.js now echoes the actual invoking hook event name — instead of hardcoding hookEventName: "PostToolUse" (or "AfterTool" for Gemini), the hook reads data.hook_event_name from the stdin payload and falls back to the runtime heuristic only when the field is absent or blank; this fixes Claude Code rejecting hook output with "expected Stop but got PostToolUse" when the monitor is invoked by the Stop, SubagentStop, or PreCompact hooks registered in PR #821. (#925) (#926)
  • Fix --reapply verifier false-positives on post-#604-rename installs caused by two gaps in pristine-baseline handling:

Gap 1 (verify-reapply-patches.cjs): when backup-meta.json records a pristine_hash for a file but gsd-pristine/ has no corresponding snapshot on disk, the verifier fell to over-broad mode (every upstream-changed line treated as a user-added requirement) and produced FAIL_USER_LINES_MISSING false positives. Fix: return advisory OK_NO_BASELINE reason (non-blocking, exit 0) when a recorded hash is present but the pristine file is absent — the verifier cannot reason correctly without a baseline and must not block.

Gap 2 (new migration 004-prune-stale-pristine-get-shit-done): migration 003 removed legacy get-shit-done/ runtime files but left gsd-pristine/get-shit-done/ orphan snapshots in place. Those stale snapshots referenced get-shit-done/... key paths that no longer match the active gsd-core/... layout, contributing to FAIL_INSTALLED_MISSING false reports. Fix: add a new migration (not editing 003, to preserve its checksum) that removes all files under gsd-pristine/get-shit-done/. (#934) (#935)

  • /gsd-update changelog preview no longer silently fails — the installer now copies scripts/changeset/ and scripts/lib/ into the runtime config dir so $GSD_DIR/scripts/changeset/cli.cjs resolves at runtime; update.md was updated to use the correct installed path and to surface an explicit error if the CLI is missing rather than swallowing it. (#935)
  • plan-review-convergence now runs gsd-plan-phase inline instead of inside Agent() — both sites that previously wrapped gsd-plan-phase in Agent() (initial planning + replan loop) have been changed to bare Skill() calls at depth 0. On Claude Code, a depth-1 Agent has no Agent tool, so a wrapped plan-phase could never spawn gsd-planner or gsd-plan-checker — the replan loop silently failed to produce a revised plan whenever HIGH concerns were found. Running plan-phase inline from the depth-0 orchestrator (which retains the Agent tool) restores the full planner→checker sub-agent chain. A new structural guard test (bug-936-no-nested-spawner-wrap.test.cjs) statically scans all workflow files and fails if any workflow wraps a spawner orchestrator in Agent() without a RUNTIME != claude carve-out, preventing regression. (#936) (#939)
  • --json-errors now emits a structured error even when a handler throws unexpectedly — an unexpected (non-ExitError) throw fell through to a raw stack trace on stderr, breaking SDK structured-error parsing. (#965) (#987)
  • verify key-links docs now correctly state from:/to: are relative file paths — the reference implied component/endpoint values the verifier never supported, so locator-style links failed with a misleading 'Source file not found' and the author's pattern: was never evaluated. (#967) (#990)
  • Fixed a test-infrastructure regression (#996) where bug-969 hardening tests deleted the shared gsd-core/bin/lib/core.cjs during concurrent runs and the build tsbuildinfo lived inside the copied install tree, intermittently failing CI with MODULE_NOT_FOUND/ENOENT. The destructive tests now run hermetically against a temp project, and the tsbuildinfo moved out of gsd-core/bin/. (#969) (#1002)
  • gsd-planner now ships the Edit tool, so it can no longer destroy ROADMAP.md via a whole-file Write — the planner had Write but not Edit (the #571/#581 writer-agent gap), so an in-place ROADMAP edit fell back to a full overwrite that truncated committed milestone history. The update_roadmap step now directs scoped Edit calls and explicitly forbids passing the full file to Write. (#973) (#989)
  • graphify query --budget with no value now errors instead of silently ignoring the budget — a trailing --budget parsed as NaN and was treated as 'no budget', so the query ran unbounded with no warning. (#974) (#986)
  • The installer now resolves a stable fnm node path instead of the ephemeral multishell shim on Windows — managed .js hooks were pinned to fnm_multishells/<id>/node.exe, a per-shell-session path fnm later deletes, breaking every managed hook until reinstall. (#977) (#992)
  • gsd-tools milestone complete --force now actually overrides the unstarted-phase guard — the dispatcher never parsed --force, so the guard's own documented escape hatch was inert. (#978) (#982)

Trae and Windsurf installs no longer leak unreplaced ~/.claude / $HOME/.claude paths — both converters only rewrote trailing-slash .claude/ forms, so bare home-path references survived conversion and pointed users at the wrong config dir; bare forms are now rewritten (Codex/Cline #570/#782 parity) and CLAUDE_CONFIG_DIR maps to the runtime's own var, with .claude-plugin preserved. (#983) (#995)

  • Claude Code plugin installs no longer fail with empty @~/.claude/gsd-core/... includes — agents, commands, and templates @-include the canonical ~/.claude/gsd-core/ path, but a marketplace plugin install (claude plugin install) never creates that directory, so every include resolved to nothing and agents (e.g. the executor) failed. A new SessionStart hook (gsd-ensure-canonical-path.js) symlinks the canonical path's immutable subdirs (bin, contexts, references, templates, workflows) to the plugin's bundled tree. It is a no-op in classic bin/install.js installs, preserves user-generated files (e.g. USER-PROFILE.md), prunes stale links so it self-heals after claude plugin update, and uses Windows junctions. (#1207) (#1207)
  • /gsd-code-review, /gsd-code-review --fix, and /gsd-eval-review now inject configured agent_skills into their subagents — these review-family workflows previously spawned their reviewer/fixer/auditor agents (including the --auto re-review/re-fix loops) without the project-configured skill and rule context, so any agent_skills set for gsd-code-reviewer, gsd-code-fixer, or gsd-eval-auditor were silently ignored. They now query and inject those skills like the ~20 sibling workflows. (#1005)
  • phase complete no longer rewrites an existing roadmap completion date — repeat runs on an already-Complete phase preserve the recorded YYYY-MM-DD date (4- and 5-column layouts); empty/-/non-date cells are still stamped with the current date. (#1177)
  • Legacy ROADMAP projects no longer get deprecation-warning spam — the free-form ROADMAP warning fired on every command regardless of phase_id_convention; it now only warns when the milestone-prefixed convention is explicitly set and unmet. (#1218) (#1218)
  • Forking workflows target wrong base branch on master repos when origin/HEAD is unset — execute-phase, quick, ship, complete-milestone, and pr-branch detection bash fell through to a hardcoded main fallback whenever origin/HEAD was absent (common in git init + remote add + fetch without set-head, CI checkouts, and worktrees), causing GSD to fork phase branches off a non-existent main on master repos. Replaced with a single gsd_run query git.base-branch resolver that walks the full precedence ladder: config override → origin/HEAD symref → git remote show origin → local branch presence → "main". (#1198) (#1198)
  • query user-story.validate now works — mvp-phase and verify-work workflows both invoked this command to validate "As a / I want to / so that" user stories, but no CJS handler existed; every call errored with "Unknown command: user-story". (#1193) (#1193)
  • Context meter no longer sticks at 100% — the statusline reserved-buffer math was inverted, pinning usage at 100% whenever CLAUDE_CODE_AUTO_COMPACT_WINDOW equalled the total window. (#1194) (#1211)
  • Roadmapper honors phase_id_convention — new-project roadmaps now use milestone-prefixed phase IDs when phase_id_convention is set, instead of ignoring the default. (#1205) (#1215)

phase complete no longer emits false warnings from historical verification metadata or deferred requirement IDs — two distinct false-positive warning bugs: (A) the verification-status check used a full-text regex that matched previous_status: gaps_found in the file body, triggering an "unresolved gaps" warning even when the current frontmatter status: passed; the check now reads only the frontmatter status key via extractFrontmatter. (B) requirement IDs under explicitly deferred/backlog/future/v2 section headings in REQUIREMENTS.md were flagged as missing from the Traceability table; the check now skips any section whose heading matches those terms. (#1197) (#1197)

  • verify key-links no longer fails on planned future files — a from: link whose file is declared in a current/upcoming wave plan’s files_modified is now reported pending instead of a hard missing-file failure. (#1202) (#1219)
  • state patch and state record-session no longer corrupt STATE.md — a no-match patch no longer rewrites the file (was resetting milestone_name and resurrecting a stale stopped_at), and record-session now persists --stopped-at/--resume-file even when the body lacks the exact labels. (#952)
  • /gsd-update no longer flags managed-hooks-registry.cjs as a custom file — the shipped hook is now recorded in the file manifest, eliminating a perpetual false-positive custom-file warning. (#953)
  • gsd-tools no longer throws EAGAIN or truncates output under heavy load — the CLI's stdout/stderr writes now retry the transient EAGAIN/EINTR errnos and handle short writes when the output stream is a full non-blocking pipe (e.g. the parallel test runner), instead of throwing or silently dropping bytes. (#1009)
  • Quick worktree execution now accepts parent-or-plan bases for pre-dispatch plan commits — quick mode records the parent and plan commit around the pre-dispatch PLAN.md commit, lets the worktree guard accept either approved base, materializes the plan from git objects when a runtime forks from the parent, and teaches cleanup to validate the same allowed-base set. (#1265) (#1347)
  • phase add no longer reuses an existing phase number when that phase exists only as a roadmap bullet — the next-number scan now counts phases listed only as - [ ] **Phase N: ...** bullets (all checkbox variants, with or without a title), in addition to ### Phase N: section headers and on-disk phase directories, so a bullet-only phase is no longer shadowed and phase add appends after the highest used number. (#1249)
  • Preserve curated STATE.md progress frontmatter when state patch updates non-progress fields, while still allowing progress-related fields to resync from disk-derived project state. (#1345)
  • The installer no longer re-adds a duplicate managed hook when the user registered it in command+args (wrapped) form — the presence checks only inspected h.command, so an args-form wrapper (a common Windows windowless-launcher mitigation) was invisible and a stock entry was appended on every install/update, running the hook twice. (#976) (#994)
  • cmdSkillManifest now discovers concrete skills nested under gsd-ns-* routers (<root>/gsd-ns-<router>/skills/<stem>/SKILL.md), so gsd-health and gsd-settings report the correct count on nested-layout runtimes (cline, qwen, hermes, augment, trae, antigravity). The scan is scoped to gsd-ns-* router dirs only — unrelated user dirs that happen to have a skills/ subdirectory are not traversed. Dual-routed concretes (same skill installed under two routers) are deduped by name within each root. (#929) (#929)
  • state record-session no longer pins a CPU core forever — acquireStateLock busy-spun at 100% CPU when a recoverable errno (e.g. ENOENT from a removed worktree) persisted, because that retry path skipped the backoff sleep and the 30s time budget. Every retry path is now bounded and backed off. (#1236) (#1236)
  • /gsd-manager and /gsd-autonomous --interactive no longer silently skip worktree isolation and independent verification on Claude Code. They dispatched plan/execute as background agents, but a backgrounded Claude Code agent has no Agent/Task tool and cannot spawn the nested executors, plan-checker, or verifier — so isolation and verification silently never ran. Both workflows now resolve the runtime and run plan/execute inline on Claude Code; background dispatch is kept on runtimes that support nested subagents. (#863)
  • Researcher agents can now invoke Perplexity — gsd-phase-researcher and gsd-project-researcher referenced mcp__perplexity__* in their provider dispatch tables but never granted it in their tools: allowlist, so Perplexity web research silently fell through to the next provider. The grant is now generated from the researcher profiles, with a parity guard that fails if a future dispatch-table provider is added without its tool grant. (#1284) (#1288)
  • Init phase lookups now resolve active phases whose canonical details live in a flat Phase Details block outside the current milestone summary, restoring requirement coverage for plan/execute/phase-op flows. (#1344)
  • Installer no longer leaks gsd-cmd-rewrites-* temp directories. Each install that emitted slash commands left one fs.mkdtempSync directory under the system temp root; on tmpfs /tmp hosts these accumulated and consumed RAM-backed storage. installRuntimeArtifacts() now removes the temp copy in a finally once command files are copied. (#862)
  • validate agents (and validate health) now cross-reference the install manifest to detect manifest-backed Codex agent pair drift: when a generated agents/gsd-*.md / agents/gsd-*.toml pair has one side missing on disk, the agent is reported as incomplete and agents_found is false (previously a false-healthy agents_found: true, missing: []). validate health names the incomplete agents and recommends re-running the installer. The check no-ops when no manifest is present. (#1058) (#1079)
  • The map-codebase and docs-update workflows no longer collect background sub-agent results with the deprecated Claude Code TaskOutput tool — they keep run_in_background=true on the spawn and Read each agent's outputFile (from the async_launched result) once it reports completion, removing the TaskOutput(block=true) main-session hang surface (anthropics/claude-code#20236). Completion-marker contracts and on-disk verification are unchanged, and the non-Claude runtime fallbacks are preserved. (#1362)
  • model_policy is now honored on the default claude runtime — including the anthropic-fable Claude Fable 5 preset. Policy-resolved model IDs map to Claude Code agent aliases (e.g. claude-fable-5 → fable), and IDs without a Claude alias warn and fall back to the configured tier. Forward-port of #1133 (originally shipped on the 1.4.5 hotfix line). (#1133) (#1133)
  • /gsd-plan-review-convergence now blocks on actionable review findings outside PLAN.md (#724). The convergence summary contract includes current_actionable alongside current_high, and reviews-mode planning/checking requires actionable MEDIUM/LOW feedback to be incorporated or explicitly deferred in executable PLAN.md content. (#728)
  • Config docs/prompts now match the consumers — workflow.subagent_timeout is documented in milliseconds (default 300000), not "seconds (default 600)" (a user who entered 600 got a 600 ms timeout); review.models.<cli> is documented as a bare model id injected into --model/-m, not a shell command; and workflow.test_command / workflow.build_command (consumed by verify-phase, execute-phase, audit-fix, and the post-merge gate) are now accepted by config set and documented. (#1296) (#1299)
  • changeset new --pr 0 now accepted at creation — the required-field guard treated the integer 0 as a missing --pr flag, so the documented pr: 0 placeholder could not be authored via the CLI. (#1231) (#1231)
  • $gsd-quick Codex adapter no longer assumes typed spawn_agent(agent_type=...) — documents that typed planner/executor spawning needs the agent_type-capable Codex schema and provides a clearly-labeled generic-subagent fallback when only multi_agent_v1 is exposed. (#958)
  • state update and roadmap update-plan-progress now handle current Markdown artifact shapes — state field read/replace works on table-format STATE.md (| Status | … |), and roadmap update-plan-progress inserts missing per-plan checklist rows (filling partial gaps), tolerates Plans:/**Plans:**/**Plans**:, and scopes changes to the active milestone. (#1172)
  • state planned-phase now advances the Status field when the prior phase left a Complete ✓ (checkmark) or bare Complete terminal status. Previously such a status matched no known template default, so the transition was silently skipped and the state machine stayed stuck on the prior phase. Caveat-bearing statuses (e.g. Complete but needs manual QA) remain preserved. (#1070) (#1078)
  • state.* writes no longer silently revert the STATE.md frontmatter status/stopped_at — an incidental write (e.g. state record-session) that doesn't change the body's Status:/Stopped at: source field now preserves the existing frontmatter value instead of re-deriving it from possibly-stale body text. Legitimate transitions (e.g. begin-phase/complete-phase, which do update the body Status) still re-derive normally, so a verified-complete phase can no longer be flipped back to verifying by an unrelated write. (#1252)
  • audit-open no longer false-flags completed quick tasks — quick-task SUMMARYs now carry status: complete in frontmatter by construction, so the milestone-close auditor stops reporting finished quick tasks as [unknown]. (#951)
  • Workspace (local) Antigravity and Copilot skill installs no longer point at the global config home — a local install rewrote ~/.claude/ references in SKILL.md bodies to the global ~/.gemini/antigravity/ / ~/.copilot/ paths instead of the workspace-relative .agent/ / .github/, because the skills layout wrapper passed the runtime name into the converter's isGlobal parameter slot. (#1092) (#1092)
  • Fix the workflow gsd_run launcher being unreachable in later bash blocks on runtimes that run each fenced block in a fresh shell (e.g. Claude Code): ship a standalone gsd-core/bin/gsd_run executable and have the per-file preamble persist the launcher's bin dir onto PATH via CLAUDE_ENV_FILE, with the inline function definition kept as the fallback for all other runtimes. (#1084)
  • /gsd:phase insert and /gsd:phase --edit no longer dead-end recording Roadmap Evolution — query state.add-roadmap-evolution was rejected as "SDK-only" with an error that pointed back at the very command that just failed, and no CJS handler existed after the SDK retirement. The handler is now implemented in CJS, so the insert/edit phase workflows append the ### Roadmap Evolution entry under ## Accumulated Context (creating the subsection if missing, deduping identical entries) as documented. (#1148) (#1148)
  • Corrected the installer --help profile skill counts: core now shows 8 (was 7) and standard shows 14 (was 13), both derived from PROFILES so they can't drift again; the full line drops the stale hardcoded 66 for all skills. (#834) (#847)
  • Codex-installed GSD skills and agents no longer rely on a bare gsd-tools executable — generated Codex surfaces now call the bundled shim, and workflow launchers can resolve the Codex shim-only install path. (#731)

Wire the discuss loop step for capability hooks — capabilities can now register discuss:pre/discuss:post hooks (e.g. discuss-time context recall and CONTEXT capture); previously discuss was contract-declared but structurally unwireable. Also collapses the host-loop file set to a single source of truth and adds an authoring-time guard rejecting hooks at unwired extension points. (#1199) (#1199)

  • /gsd-autonomous --converge now routes phase planning through plan-review convergence instead of silently ignoring the flag. (#711) (#729)
  • Hermes skills now install at skills/gsd/gsd-/SKILL.md with name gsd-, restoring canonical /gsd- dispatch that was broken by the bare-stem prefix introduced in #3664. (#955)

[1.4.5] - 2026-06-12

Fixed

  • model_policy is now honored on the default claude runtime — including the anthropic-fable Claude Fable 5 preset. Policy-resolved model IDs map to Claude Code agent aliases (e.g. claude-fable-5 → fable), and IDs without a Claude alias warn and fall back to the configured tier. Previously the entire model_policy block was silently ignored on claude. (#1133) (#1133)

[1.4.4] - 2026-06-11

Changed

  • Added an opt-in anthropic-fable model policy provider preset for Claude Fable 5 high-budget routing while preserving the existing Anthropic Opus 4.8 defaults and anthropic provider preset. (#1014) (#1015)

[1.4.3] - 2026-06-09

Fixed

  • Fix --reapply verifier false-positives on post-#604-rename installs caused by two gaps in pristine-baseline handling:

Gap 1 (verify-reapply-patches.cjs): when backup-meta.json records a pristine_hash for a file but gsd-pristine/ has no corresponding snapshot on disk, the verifier fell to over-broad mode (every upstream-changed line treated as a user-added requirement) and produced FAIL_USER_LINES_MISSING false positives. Fix: return advisory OK_NO_BASELINE reason (non-blocking, exit 0) when a recorded hash is present but the pristine file is absent — the verifier cannot reason correctly without a baseline and must not block.

Gap 2 (new migration 004-prune-stale-pristine-snapshots): migration 003 removed legacy get-shit-done/ runtime files but left gsd-pristine/get-shit-done/ orphan snapshots in place. Those stale snapshots referenced get-shit-done/... key paths that no longer match the active gsd-core/... layout, contributing to FAIL_INSTALLED_MISSING false reports. Fix: add a new migration (not editing 003, to preserve its checksum) that removes all files under gsd-pristine/get-shit-done/. (#934) (#937)

  • /gsd-update changelog preview no longer silently fails — the installer now copies scripts/changeset/ and scripts/lib/ into the runtime config dir so $GSD_DIR/scripts/changeset/cli.cjs resolves at runtime; update.md was updated to use the correct installed path and to surface an explicit error if the CLI is missing rather than swallowing it. (#938)
  • plan-review-convergence now runs gsd-plan-phase inline instead of inside Agent() — both sites that previously wrapped gsd-plan-phase in Agent() (initial planning + replan loop) have been changed to bare Skill() calls at depth 0. On Claude Code, a depth-1 Agent has no Agent tool, so a wrapped plan-phase could never spawn gsd-planner or gsd-plan-checker — the replan loop silently failed to produce a revised plan whenever HIGH concerns were found. Running plan-phase inline from the depth-0 orchestrator (which retains the Agent tool) restores the full planner→checker sub-agent chain. A new structural guard test (bug-936-no-nested-spawner-wrap.test.cjs) statically scans all workflow files and fails if any workflow wraps a spawner orchestrator in Agent() without a RUNTIME != claude carve-out, preventing regression. (#936) (#939)

[1.4.2] - 2026-06-09

Fixed

  • /gsd-plan-phase, /gsd-execute-phase, /gsd-autonomous no longer carry context: fork — these are spawning orchestrators; a forked subagent context has no Agent tool, preventing them from spawning the subagents they require. effort: xhigh is preserved. Fixes /gsd:autonomous halting with "running as a forked subagent" on 1.4.1 (#921). Also replaces the introspection-based Agent-availability check in plan-phase's <runtime_compatibility> block with an attempt-based gate: the workflow now always attempts the Agent() call and only stops if a real tool-unavailable error is returned, eliminating false-negative aborts in top-level sessions (#922). (#921)
  • gsd-context-monitor.js now echoes the actual invoking hook event name — instead of hardcoding hookEventName: "PostToolUse" (or "AfterTool" for Gemini), the hook reads data.hook_event_name from the stdin payload and falls back to the runtime heuristic only when the field is absent or blank; this fixes Claude Code rejecting hook output with "expected Stop but got PostToolUse" when the monitor is invoked by the Stop, SubagentStop, or PreCompact hooks registered in PR #821. (#925) (#926)

[1.4.1] - 2026-06-09

Changed

  • Added no-drift guard tests (tests/issue-57-runtime-install-no-drift.test.cjs) that protect the Runtime Install Policy Module boundary (ADR-58) and the explicit Runtime Config Adapter Registry (#60). They fail loudly when supported-runtime metadata is added to an installer call site (allRuntimes, the interactive runtimeMap menu) without a matching registry adapter entry, or when config-mutation dispatch escapes the registry's declared install surfaces — catching reintroduction of the scattered per-runtime branching those seams removed. (#867)

Fixed

  • profile-pipeline temp output now lands under the reaped GSD temp root. cmdExtractMessages and cmdProfileSample previously created their output directories directly in os.tmpdir() root (gsd-pipeline-* / gsd-profile-*), which reapStaleTempFiles never scans (it only scans GSD_TEMP_DIR = os.tmpdir()/gsd). The directories accumulated forever. Both sites now call ensureGsdTempDir() and create under GSD_TEMP_DIR. Also adds missing after/afterEach teardown to four test fixtures that leaked gsd-* temp dirs on every npm test run. (#866) (#879)
  • gsd_run launcher shim now probes all non-Claude runtime homes before failing. The shim's last-resort detection previously stopped at $HOME/.claude, causing a false-positive fatal error on every non-Claude runtime (Hermes, Cursor, Codex, Copilot, Windsurf, Augment, Trae, Qwen, CodeBuddy, Cline, Grok, Antigravity, OpenCode, Kilo) when RUNTIME_DIR was unset and gsd-tools was not on PATH. The snippet now probes each runtime's config directory (respecting HERMES_HOME, CURSOR_CONFIG_DIR, CODEX_HOME, etc. with sensible $HOME-relative defaults) before emitting the install error. (#903)
  • validate health and validate consistency no longer emit false-positive W007 warnings for projects using checklist-style ROADMAP.md phases. buildRoadmapPhaseVariants() in src/validate.cts previously used only a heading-style regex (## Phase N: name), silently ignoring the supported checklist format (- [x] **Phase N: name**). This caused every on-disk phase directory to trigger W007 ("exists on disk but not in ROADMAP.md") when the project's ROADMAP used checklist-only notation. The fix adds a second regex pass mirroring the existing buildNotStartedPhaseVariants() approach. Additionally, cmdValidateConsistency() in src/verify.cts had a duplicate inline heading-only regex with the same gap — refactored to delegate to buildRoadmapPhaseVariants() (DRY). (#892) (#893)
  • init execute-phase and cmdCommit now produce correct branch_name when project_code is set — the {phase} substitution in phase_branch_template now calls normalizePhaseName(), stripping the project-code prefix and zero-padding the number, so the generated branch is e.g. gsd/phase-01-foundation instead of gsd/phase-CK-01-foundation. Both the execute-phase output path (src/init.cts) and the pre-execution commit path (src/commands.cts) are fixed. (#904) (#904)
  • syncStateFrontmatter no longer strips current_phase, current_phase_name, current_plan, and progress from STATE.md — when body annotations are absent (e.g. after an agent rewrites the body), the existing frontmatter values for those scalars are now preserved, mirroring the fallback already applied in cmdStateJson. (#905) (#905)
  • Top-level Claude Code /gsd-plan-phase now always spawns the researcher/planner/plan-checker agents instead of collapsing them inline — a <runtime_compatibility> block after </available_agent_types> makes the Agent-availability requirement explicit and documents that the workflow fails-closed (stops with a clear log message) in genuinely Agent-less contexts; seven "ORCHESTRATOR RULE — CODEX RUNTIME" labels are renamed to "ALL RUNTIMES" so the guard applies universally; execute-phase.md scopes its existing "Other runtimes" inline-fallback prose to non-Claude contexts, preserving the #853 backgrounded-agent behaviour. (#913) (#913)
  • /gsd-manager and /gsd-autonomous --interactive no longer silently skip worktree isolation and independent verification on Claude Code. They dispatched plan/execute as background agents, but a backgrounded Claude Code agent has no Agent/Task tool and cannot spawn the nested executors, plan-checker, or verifier — so isolation and verification silently never ran. Both workflows now resolve the runtime and run plan/execute inline on Claude Code; background dispatch is kept on runtimes that support nested subagents. (#863)
  • Installer no longer leaks gsd-cmd-rewrites-* temp directories. Each install that emitted slash commands left one fs.mkdtempSync directory under the system temp root; on tmpfs /tmp hosts these accumulated and consumed RAM-backed storage. installRuntimeArtifacts() now removes the temp copy in a finally once command files are copied. (#862)
  • Corrected the installer --help profile skill counts: core now shows 8 (was 7) and standard shows 14 (was 13), both derived from PROFILES so they can't drift again; the full line drops the stale hardcoded 66 for all skills. (#834) (#847)

[1.4.0] - 2026-06-08

Added

  • Research is now cached, curated-first, and code-governed — a content-addressed Research Store (per-source TTL), a single provider waterfall with confidence tiers, and registry-API package legitimacy replace the per-agent prose waterfall and the slopcheck bolt-on. (#664) Confidence is now verification-evidence-driven: provider identity alone no longer yields HIGH; HIGH requires ground-truth corroboration (e.g. legitimacyVerdict: 'OK'), authority alone caps at MEDIUM, and SLOP caps at LOW. (#664)
  • /gsd:plan-phase now accepts a --granularity <coarse|standard|fine> flag to override the configured planning granularity for a single invocation. The flag takes precedence over granularities.planning, top-level granularity, and planning.granularity config. Invalid values are rejected. (#703) (#750)
  • gsd-core can now be installed as a native Claude Code plugin — a new .claude-plugin/plugin.json manifest enables installing gsd-core via claude plugin install or the zero-friction ~/.claude/skills/ auto-load path (gsd-core@skills-dir), with slash commands auto-namespaced as /gsd-core:<command> (e.g. /gsd-core:plan-phase) and lifecycle management via claude plugin enable|disable|update. gsd-core's always-on guard and update hooks are wired for the plugin path through hooks/hooks.json using ${CLAUDE_PLUGIN_ROOT}. This is additive — the existing npm / file-copy installer is unchanged. (#797)
  • Installer pre-populates permissions.allow/deny for Claude Code — fresh Claude Code installs now receive GSD's known-safe tool-call patterns (Bash(npx gsd-core *), Read(.planning/*), Write(.planning/*), Read(STATE.md), Write(STATE.md)) in settings.json out of the box, eliminating first-run approval prompts. A deny block for credential files (Read(.env), Read(.env.*), Read(.secrets)) is also added for defense-in-depth. The merge is additive and idempotent; existing user-set entries are preserved. Uninstall removes only GSD-owned entries. (#768) (#819)

Added: register newly-available Claude Code lifecycle hooks — SubagentStop, Stop, PreCompact (all wired to gsd-context-monitor for context-headroom warnings), and FileChanged (matcher: config.json, wired to new gsd-config-reload.js hook that hot-reloads .planning/config.json context mid-session). Also updates hooks/hooks.json (plugin manifest) and managed-hooks-registry for drift-guard coverage (#770). (#821)

  • Gemini installs now register three additional hook events — BeforeAgent, AfterAgent, and BeforeModel — wired to gsd-context-monitor.js for per-turn context headroom tracking. Previously only SessionStart, BeforeTool, and AfterTool were registered. The installer also detects hooksConfig.enabled: false in the user's Gemini settings.json and emits a clear warning, surfacing the silent failure mode where all hooks are registered but never execute. (#776) (#829)
  • Cross-runtime command enrichment in the installer. Gemini CLI commands now use native {{args}} interpolation (translated from Claude's $ARGUMENTS) so typed arguments interpolate into the prompt body, and /gsd:progress injects live project state via a fixed, injection-safe !{cat .planning/STATE.md 2>/dev/null} shell block. Qwen Code skills now carry a numeric priority field so the most-used main-loop workflows (new-project, plan-phase, execute-phase, …) surface first in the /skills list. The OpenCode per-command model/agent/subtask enrichment was evaluated and intentionally not implemented — model would reintroduce the ProviderModelNotFoundError regression that the converter deliberately guards against for non-Anthropic providers (#1156), subtask/agent change execution semantics for GSD's interactive commands, and variant is not in the OpenCode command schema. (#778) (#825)
  • Emit native on-demand skills (skills/<name>/SKILL.md) for the OpenCode-family runtimes (OpenCode and Kilo) at install time, in addition to the existing flat command/ and file-based agents/ surfaces. OpenCode and Kilo share a config schema and both discover skills from skills/<name>/SKILL.md; the installer now stages each GSD command as a skill with minimal, spec-compliant frontmatter (name matching the directory, description 1–1024 chars) via a shared OpenCode-family skill writer. Skills respect the active install profile (core/minimal stage only their subset) and are removed on uninstall. (#784) (#810)
  • gsd install --cursor now writes .cursor/commands/gsd-<name>.md in addition to the existing .cursor/skills/ surface. Cursor 1.6 introduced plain-markdown slash commands (no frontmatter) in .cursor/commands/; they appear in the / menu in the Agent input. Each command file is generated from the same source as the skill but with frontmatter stripped and Cursor-specific content transforms applied (convertClaudeCommandToCursorCommand). The skills surface is unchanged — both surfaces are written on every install. (#803)
  • The GitHub Copilot installer now reaches lifecycle-hook and instruction parity with other first-class runtimes. It emits a self-contained sessionStart hook config (.github/hooks/gsd-session.json for local installs, ~/.copilot/hooks/gsd-session.json for global) and writes AGENTS.md at the repository root (which Copilot CLI reads as primary instructions) alongside copilot-instructions.md. The hook is an inline command hook with no separate script file, so it cannot dangle. Both artifacts are removed — with user-authored content preserved — on --uninstall. (#786) (#804)
  • Elevate the Cline runtime to hook parity. The installer now emits the Cline .clinerules/ directory form (.clinerules/gsd.md) instead of a single .clinerules file, adds a .clinerules/hooks/PreToolUse lifecycle hook (Cline v3.36+ JSON stdin → {cancel,errorMessage,contextModification} protocol; guards .planning/ artifacts and fails open), and merges GSD instructions into the cross-tool global ~/.agents/AGENTS.md target on global installs. A legacy single-file .clinerules is migrated to the directory form in place, and --uninstall removes the new artifacts and strips the GSD block from ~/.agents/AGENTS.md. (#787) (#803)
  • Qwen Code installs now register three additional hook events that Qwen Code supports beyond Claude Code: SubagentStop, Stop, and PreCompact — all wired to gsd-context-monitor.js for context headroom tracking at subagent completion, model stop, and pre-compaction. These events are Qwen-only; Claude Code installs are unchanged. UserPromptSubmit is deferred: gsd-prompt-guard exits unless tool_name is Write|Edit, making it a no-op for that payload shape. (#788) (#807)
  • CodeBuddy (Tencent) installs now emit /gsd-* slash commands. A --codebuddy install writes commands/gsd-<name>.md files to ~/.codebuddy/commands/ so GSD workflows are invokable from CodeBuddy's / menu (/gsd-phase, /gsd-ship, etc.), matching the integration depth of other fully-elevated runtimes (#789). The existing skills/gsd-<name>/SKILL.md files are now emitted with user-invocable: false so they stay out of the / menu — the commands surface is the single / entry point (no duplicate entries) and skills remain available for model invocation. Subagents (~/.codebuddy/agents/) were already emitted and are unchanged. Uninstall removes the gsd-* command files while preserving user-owned commands. No mcp.json is written — gsd ships no MCP server and CodeBuddy's mcp.json only registers external MCP servers.
(#830)
  • Augment installs now emit slash command definitions alongside skills. A global --augment install writes commands/gsd-<name>.md files to ~/.augment/commands/ in addition to the existing skills/gsd-<name>/SKILL.md files, matching the integration depth of other fully-elevated runtimes and allowing Auggie users to invoke GSD as slash commands (/gsd-phase, /gsd-ship, etc.) without manual configuration (#790). Content rewrites (path normalisation and Augment-specific branding) are applied at install time. Uninstall removes the gsd-* command files while preserving user-owned commands. mcpServers registration is explicitly excluded — gsd ships no MCP server and does not register third-party servers. (#801)
  • Issues are now checked for duplicates when opened: a no-LLM title-similarity check posts a challenge comment and applies a possible-duplicate label when a new issue closely matches existing open ones. Flagged issues that go unanswered for 24h are auto-closed as duplicates (reply, or react 👎 to the bot comment, to keep one open); a reply clears the label and routes to needs-maintainer-review. (#836) (#843)
  • Cursor now receives GSD lifecycle hooks via .cursor/hooks.json — a sessionStart hook injects the current workflow state as context at session start, and a postToolUse hook nudges the agent to update .planning/ after write-class operations, bringing Cursor to baseline hook parity with Gemini and Claude Code. (#777)
  • Gemini CLI extension package — gsd-core now ships a gemini-extension.json manifest (plus a GEMINI.md context payload) at the repository root, so Gemini CLI users can install, update, and remove GSD through Gemini's own extension lifecycle: gemini extensions install https://github.com/open-gsd/gsd-core, gemini extensions update gsd-core, gemini extensions uninstall gsd-core, and gemini extensions link <path> for local dev. The extension is discoverable in gemini extensions list and loads GSD's operating context into every session. Additive — the existing npx gsd-core --gemini installer (which provides the /gsd:* slash commands) is unchanged. (#775) (#775)
  • New agent_skills_security.trusted_global_roots config — opt-in allowlist of trusted root directories so symlinked global: agent skills whose real path resolves outside the default skills dir (e.g. ~/.claude/skills) are accepted; default [] is byte-identical and preserves the symlink-escape guard. (#754)
  • Added /gsd-update --next (alias --rc) to install or refresh from the @next RC dist-tag (ADR #660). A new parse_update_channel workflow step resolves the channel from $ARGUMENTS; the version check and all three npx install invocations thread $TAG instead of hardcoding @latest. When --next is used the version-comparison output gains a Channel: next (RC) banner so the user knows they are leaving the stable line; omitting the flag keeps @latest behavior byte-for-byte unchanged. check-latest-version.cjs gains ALLOWED_TAGS, buildViewArgs, and resolveTag exports, with an allowlist guard (enforced at both the CLI and function boundary) that rejects any dist-tag other than latest/next. (#815) (#839)

Changed

  • /gsd:plan-phase --research-phase <N> now auto-uses an existing RESEARCH.md instead of prompting update/view/skip. When research already exists and neither --research nor --view is passed, it emits a one-line notice and exits cleanly, matching the promptless behavior of standard /gsd:plan-phase <N>. Pass --research to force-refresh or --view to print the existing research. (#159) (#718)
  • Retire the installer's one-off runtime directory helpers (getGlobalDir/getOpencodeGlobalDir/getKiloGlobalDir) and consolidate per-runtime global config-dir resolution onto the single canonical projection runtime-homes:getGlobalConfigDir, extended with the --config-dir override and the opencode/kilo *_CONFIG file-path precedence. Behavior-preserving across all 15 install runtimes. (#56) (#802)
  • Make per-runtime config-mutation dispatch in the installer explicit: a new runtime config adapter registry maps each supported runtime to a typed config intent (install surface, shared-settings gate, finish-phase permission writer), and install()/finishInstall() dispatch by resolved intent instead of inline runtime === '...' branching. Behavior-preserving; unknown runtimes now fail loudly. (#60) (#795)
  • Verification status routing is now owned by a single queryable seam — ship.md and execute-phase.md both consume gsd_run query verification.status instead of re-deriving the passed/gaps_found/human_needed routing independently; the query returns next_action and next_command so per-status prose no longer needs to be kept in sync across files. This also fixes the broad-grep status misread in execute-phase.md where a body status: line (in a code block or copied artifact) could concatenate with the frontmatter value and misroute a valid passed phase; a parity test fails if a new verifier status value lacks a route. (#651) (#755)
  • Agent color: frontmatter now uses Claude Code's documented named colors (red/blue/green/yellow/purple/orange/pink/cyan) instead of hex values or the undocumented magenta, so the intended per-agent TUI color differentiation renders reliably across the Claude Code runtime. Display-only metadata; no behavior change. (#771) (#823)
  • Codex installs now register three additional stable hook events (SubagentStart, Stop, PostToolUse) wired to gsd-context-monitor.js, matching the full event coverage available since Codex CLI stabilised these hooks. The SessionStart hook entry gains a commandWindows field on Windows installs so the .cmd shim is used for native execution (Git Bash/MSYS cannot POSIX-exec node.exe directly). Both new-event registration and uninstall paths handle the flat { "EventName": [...] } and nested { "hooks": { "EventName": [...] } } hooks.json shapes. gsd-context-monitor.js and its Windows .cmd sibling are added to the managed-hook allowlist so idempotent re-runs de-duplicate entries correctly. (#772) (#827)
  • Codex CLI installs now emit two enrichments per agent and skill. Agent TOML enrichment: light-tier agents (haiku-equivalent, routingTier: "light" in model-catalog.json) get service_tier = "flex" and model_verbosity = "low" appended to their agent TOML, telling the Codex scheduler to use the flex tier (lower cost, background processing) and suppress verbose token output. Skill TUI chip: each installed gsd-* skill directory now receives an agents/openai.yaml file with interface.display_name and interface.short_description, making the skill appear in the Codex /skills picker with a human-readable name and description drawn from the skill's existing short-description frontmatter. Both enrichments are additive and backward-compatible with Codex CLI ≥ 0.130.0. (#774) (#828)
  • Cline global installs now emit skills, not just rules: gsd writes skills to ~/.cline/skills/<name>/SKILL.md for Cline ≥ v3.48.0 (see Cline skills docs), in addition to the existing .clinerules file. Each SKILL.md carries name/description frontmatter (agentskills.io) with paths rewritten to the .cline/ convention. Local installs remain .clinerules-only. The .clinerules rules file continues to be emitted for compatibility, and upgrading over an existing rules-only install emits the new skills on the next run. (#809)
  • Workflow size budget now measures bytes, not lines (#717). tests/workflow-size-budget.test.cjs re-bases its tier ceilings (XL/LARGE/DEFAULT) from line counts to byte counts — deterministic, no tokenizer, and matching the unit vendors bound on (Codex's 32,768-byte project_doc_max_bytes cap). The #597 tighten-only ratchet and per-file semantics are unchanged; the budget's caching-independent quality rationale (context rot / attention budget) is now documented. (#719)
  • The gsd-verifier agent no longer re-runs the full workspace test suite once per must-have during Step 7b spot-checks — it enumerates tests to prove existence and runs a single named test to prove a pass, invoking the full suite at most once per verification. (#753)
  • /gsd-plan-phase, /gsd-execute-phase, /gsd-autonomous now run in an isolated forked context on Claude Code — context: fork in skill frontmatter protects the main session's context budget. These three heavy skills also declare effort: xhigh; quick-status skills /gsd-progress and /gsd-stats declare effort: low. The installer preserves both fields when converting commands to Claude SKILL.md files. Runtimes that do not recognise these fields silently ignore them — no behaviour change on non-Claude runtimes. (#769)
  • /gsd:plan-phase and /gsd:execute-phase no longer eagerly load MVP-only guidance on non-MVP runs — the MVP planner rules, user-story template, Walking-Skeleton template, and MVP+TDD halt-report reference are now Read lazily by the planner/executor only when MVP / Walking-Skeleton / MVP+TDD mode is active, in both the workflow files and the gsd-planner/gsd-executor agent definitions, instead of being @-imported into every run. Behaviour is unchanged; non-MVP planning/execution simply carries less context. (#720) (#746)

Automated codex exec invocations in the review workflow now include --ephemeral (no session-state accumulation across automated/CI runs) and --dangerously-bypass-hook-trust (skip hook-trust prompts for hooks managed by gsd-core itself). These flags apply only to the non-interactive reviewer invocations in gsd-core/workflows/review.md. (#773) (#824)

  • Codex slash-command conversion no longer corrupts inline-wrapped /gsd-… file paths — the install-time converter now identifies a real /gsd-<command> mention by positive boundaries (opening delimiter + no path continuation) instead of an unbounded preceding-character denylist, closing the path-corruption class (#637 → #704) by construction while still converting legitimate backtick-wrapped mentions. (#747)
  • The release pipeline now automatically runs changeset render during the finalize job, promoting .changeset/ fragments into a dated CHANGELOG.md section before publishing — previously a manual step that was routinely skipped (leaving v1.3.0 and v1.3.1 unpromoted, #690). A new --allow-empty flag prevents the verify gate from hard-failing on no-change releases by emitting a dated heading with a _No notable changes._ placeholder when there are zero fragments. (#715)

Fixed

  • /gsd-review --cursor now actually invokes the Cursor agent. Detection probes the cursor-agent headless binary instead of the cursor IDE launcher, the invocation calls the single cursor-agent binary in print mode (not the two-token cursor agent, which the IDE treats as a file path), and the review prompt is passed as a file-path argument rather than piped to stdin (which cursor-agent -p ignores). On failure the captured stderr is surfaced instead of a silent empty result. (#686)
  • No more "gsd-core" console-window flash on Windows. Every gsd-core child process now passes windowsHide: true: the context monitor's record-session spawn, the execGit / execNpm / execTool helpers in shell-command-projection, the gsd-worktree-path-guard and gsd-workflow-guard hook git probes, check-command-router's git log call, and the roadmap-upgrade git status/rev-parse/reset/clean calls — matching the existing gsd-check-update spawn. execNpm (which uses shell: true → cmd.exe and runs on every SessionStart, i.e. every /clear) and the worktree-path guard (which runs on every Edit/Write in a worktree) were the most visible offenders. No behavior change on macOS/Linux, where the flag is ignored. (#688)
  • /gsd-review --agy no longer hangs the whole review on large prompts. On a big, file-path-rich prompt Antigravity's agy -p agentic Cascade can loop on its code_search/grep steps and never converge. The invocation now passes agy's own --print-timeout flag (its native print-mode cap) so a stalled run self-terminates through the tool's own mechanism; on a non-zero exit any partial output is discarded so the existing transcript fallback / "review failed" stub take over. (#689)
  • The roadmap parser now resolves fresh phases of the current milestone in multi-milestone roadmaps. extractCurrentMilestone() scoped the current-milestone window to its ## Phases checklist subsection and stopped at the milestone's own ## Milestone … (Phase Details) heading, so the ### Phase N: detail headers fell out of scope. Any command backed by the parser — init.phase-op (and therefore /gsd:discuss-phase and /gsd:plan-phase), state, roadmap list, and validate health (W006) — could not resolve phases of any milestone after the first until a .planning/phases/ directory already existed, blocking discuss/plan. The parser now also includes the current milestone's (Phase Details) section in scope, anchored to the selected milestone's version token so sibling sub-milestones do not cross-pollinate. (#730) (#748)
  • getGlobalSkillsBase('kilo') now resolves to ~/.kilo/skills — where Kilo Code actually discovers global skills — instead of ~/.config/kilo/skills. Per Kilo Code docs, global skills live in the .kilo directory within HOME (~/.kilo/skills/), independent of the XDG-based config dir at ~/.config/kilo. The kilo.jsonc config dir (~/.config/kilo) and the command/ path used by the installer are correct and unchanged. Blast radius: this corrects the resolved skills-base path used by doctor/status checks and agent-skills-block resolution (init.cjs); the installer writes commands (not skills) for Kilo, so no files were previously being written to the wrong location. (#806)
  • Honor the COPILOT_HOME environment variable when resolving the GitHub Copilot global config directory. Previously a global --copilot install ignored COPILOT_HOME and wrote all artifacts (skills, agents, copilot-instructions.md, the session hook) to ~/.copilot even when the user had relocated their Copilot home, making them undiscoverable by Copilot CLI. Resolution now follows --config-dir > COPILOT_CONFIG_DIR > COPILOT_HOME > ~/.copilot, mirroring the existing CODEX_HOME handling. Uninstall uses the same resolver and stays symmetric. (#812) (#814)
  • Release version bumps now keep runtime manifest versions in sync — .claude-plugin/plugin.json and gemini-extension.json are stamped to match package.json on every npm version, unblocking RC/finalize releases. New version-bearing manifests must be registered in scripts/sync-manifest-versions.cjs (enforced by a regression test). (#845)
  • npx @opengsd/gsd-core upgrades no longer abort with "applied migration checksum changed" — an already-applied installer migration whose recorded checksum drifted (e.g. a shipped body was edited) is now detected and reconciled automatically on the next install, instead of hard-failing the upgrade. Replaces the published-checksum allowlist with general self-healing recovery plus a CI baseline lock. (#675)
  • /gsd-import, /gsd-plan-review-convergence, and /gsd-spec-phase now run on global installs — these workflows resolve gsd-tools via the runtime launcher instead of a hardcoded $HOME path, so they no longer falsely report the tool as "not found" (and stop short) when only a global/shim install is present and no project-local runtime exists. (#642)
  • Worktree wave-cleanup no longer fails when the phase SUMMARY is committed — rescueSummaryArtifacts no longer copies an already-committed SUMMARY into the main checkout, which previously caused git merge --no-ff to abort with a permanent merge_failed (#706). (#709)
  • Phase execution no longer halts with exit 42 (worktree base mismatch) when run on a branch diverged from the default branch (#683). Claude Code forks worktree-isolated executors off the repository default branch (origin/HEAD), so running /gsd-execute-phase on an unmerged milestone/feature branch left every executor without the phase's plan files and tripped the worktree-branch-check guard (100% reproducible, all OSes). Execute-phase now detects this before dispatch and automatically degrades to sequential execution on the main working tree, recommending the permanent fix worktree.baseRef:"head". Both fresh installs and upgrades of GSD Core set worktree.baseRef:"head" in .claude/settings.local.json automatically (no-clobber) when workflow.use_worktrees is enabled (the default); gsd-tools worktree set-baseref remains available for manual use (e.g. after toggling worktrees on later). The exit 42 guard remains as a backstop. (#749)
  • Codex install no longer corrupts launcher paths — shell path segments like ${VAR}/gsd-core/ and $(cmd)/gsd-local-patches are no longer rewritten into a literal $gsd-core token during Codex markdown conversion (#704). (#710)
  • /gsd:surface no longer corrupts installed skill paths — re-surfacing (profile/enable/disable/reset) now applies the same per-runtime path rewrites as install, so SKILL.md bodies keep the correct install target instead of reverting to the converter's default ~/.claude paths. (#817)
  • /gsd:graphify, /gsd:import, and planning agents now resolve gsd-tools on global/shim-only installs — agent and command surfaces that invoked a hardcoded $HOME/.claude/...gsd-tools.cjs path now route through the resolved gsd_run launcher, so the step no longer reports the tool "not found" when there is no project-local runtime. (#707)
  • /gsd:surface no longer mis-names or orphans runtime command files — re-surfacing now writes the same gsd--prefixed command filenames as a fresh install for flat command dirs (Cursor, Augment, OpenCode, Kilo) and preserves user-authored command files instead of deleting them. (#822)
  • /gsd:update reliably previews release notes again — promotes the 1.3.x changelog into dated [1.3.0]/[1.3.1] sections, stops deleting the temp changelog before the human-readable render (no more (changelog unavailable)), and adds a release gate that blocks publishing a version whose CHANGELOG.md section was never promoted. (#694)

Security

  • gsd-tools config-set prototype-pollution guard hardened and regression-tested. The guard that blocks __proto__, prototype, and constructor segments in dotted config keys now uses inline literal comparisons at each property-write site (instead of a pre-loop Set check), so CodeQL's js/prototype-pollution-utility analysis recognises it as a sanitising barrier and code-scanning alert #26 clears. Runtime behaviour is unchanged from #663. Added regression tests that drive schema-valid dynamic-prefix keys (agent_skills.__proto__, agent_skills.constructor, features.__proto__, review.models.constructor) all the way to the guard — these reach setConfigValue past the schema gate and were previously the guard's only untested attack surface. (#751) (#752)
  • Hardened roadmap-phase parsing and config writes — resolved ReDoS in phase-heading/plan-filename regexes (validate/verify/commands/phase), blocked prototype-pollution through dotted config keys in config-set, and pinned qs >= 6.15.2 (DoS advisory). (#665)

1.3.1 - 2026-06-04

Security

  • Bumped hono to clear a moderate npm advisory carried transitively in the dependency tree. (#670)

Fixed

  • Installer-migration checksum drift no longer blocks upgrades — the updater now self-heals when a shipped migration's recorded checksum has drifted, reconciling the stored checksum instead of aborting. Restores upgrades across all OSes after shipped migration bodies were edited in a prior release. (#670)

1.3.0 - 2026-06-04

Added

  • Vertical MVP Slice mode — --mvp flag on /gsd-plan-phase switches the planner from horizontal layer decomposition to vertical feature-slice decomposition (UI→API→DB in one task sequence). On Phase 1 of a new project with no prior phase summaries, also emits SKELETON.md via Walking Skeleton mode. Composable with --tdd: --mvp --tdd produces vertical slices where every behavior-adding task starts with a failing test. Phase-level persistence via **Mode:** mvp in ROADMAP.md applies --mvp automatically without the flag. (#78)
  • /gsd-mvp-phase command — guided MVP planning: prompts for a user story (As a / I want to / So that), runs SPIDR story-splitting check (Spike/Paths/Interfaces/Data/Rules axes), writes **Mode:** mvp to ROADMAP.md, then delegates to /gsd-plan-phase. (#78)
  • MVP-aware UAT framing in verify-phase — when a phase has mode: mvp, the verifier generates a user-flow-first UAT script (walks the feature as a user would) before any technical checks. (#78)
  • MVP progress and stats display — progress and stats commands show Walking Skeleton completion status and per-feature-slice status lines for MVP-mode phases. (#78)
  • Six MVP reference files — planner-mvp-mode.md, skeleton-template.md, user-story-template.md, spidr-splitting.md, execute-mvp-tdd.md, verify-mvp-mode.md — loaded by the planner, executor, and verifier agents when MVP mode is active. (#78)
  • Milestone-prefixed phase ID convention (M-NN) for globally unique phase IDs within a project (#39)
  • getMilestoneFromPhaseId() and getPhaseDirFromPhaseId() helpers in core.cjs (#39)
  • W021 validation rule: fires when a phase ID's integer prefix mismatches its enclosing milestone section (#39)
  • gsd-tools roadmap validate subcommand for convention compliance checking (#39)
  • gsd-tools roadmap upgrade --convention milestone-prefixed migration tool (dry-run by default, --apply to mutate) (#39)
  • phase_id_convention config field (null | 'milestone-prefixed' | 'free-form'), defaults to null (legacy free-form, no breaking change) (#39)

Fixed

  • isDirInMilestone now correctly matches M-NN-style phase directories against milestone-prefixed ROADMAP headings (#39)
  • searchPhaseInContent heading regex now tolerates [bracket-token] scope prefix (e.g., ### [GSD] Phase 2-01:) (#39)
  • README version guidance now uses npm/package metadata as the source of truth — README, localized READMEs, and the docs index no longer present archived release-note or canary-stream numbers as the current GSD Core package version. (#545)

1.2.0 - 2026-05-31

1.2.0 is the current stable @opengsd/gsd-core release. It resumes the public package line after the release-version validation recovery documented in ADR 218 and makes @opengsd/gsd-core / gsd-core the canonical package and CLI identity.

Added

  • Plan-vs-codebase drift guard — plan review can verify generated plans against live source symbols before execution so hallucinated files, APIs, or commands are caught earlier. (#487)
  • Single Package Identity seam — package name, CLI identity, update checks, and installer identity are centralized so @opengsd/gsd-core stays consistent across runtime surfaces. (#499, #517, #521)
  • Cross-provider effort controls and fast-mode-aware routing — model-effort selection works across providers and can adjust routing for faster workflows. (#463)
  • Current public docs and install identity — README/docs now advertise GSD Core, @opengsd/gsd-core, and the gsd-core binary as the canonical user-facing surface. (#519, #523, #540)

Changed

  • SDK shim retired from installer/runtime docs — workflows now route through gsd-tools; dead SDK-shim verification and stale SDK-generated banners were removed. (#522, #515, #510)
  • Release numbering recovered at 1.2.0 — leading-zero release inputs are invalid and duplicate-version checks fail early before publish work begins. See ADR 218.
  • CI/test selection is more precise — affected-test selection now widens docs/test-impact correctly and avoids under-testing relevant PRs. (#495)

Fixed

  • Planning writes are more reliable — phase completion writes are transactional and no longer corrupt milestone progress counters. (#465, #514)
  • Roadmap and milestone parsing no longer leak stale phase details into active milestone state. (#513)
  • /gsd:update detects local Antigravity .agent installs and repo-local Claude installs correctly. (#512, #476)
  • Package identity registration no longer regresses update/runtime detection. (#521)

Legacy Release History

Release notes for every version published before the project was renamed to @opengsd/gsd-core — the retired get-shit-done-cc / get-shit-done-redux lineage, versions 1.0.0 → 1.42.x plus pre-release and canary builds — have been rolled up into a single archive:

➡️ docs/RELEASE-NOTES-LEGACY.md

Those legacy 1.x numbers belong to the previous package line and predate the current @opengsd/gsd-core versioning, which restarts at 1.0.0. They are preserved verbatim-in-spirit (condensed) in the archive and intentionally kept out of this file so the two version streams cannot collide.