From e4df05126deaf5ad1c29bf35b9dfe2193c80cb0b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 00:05:31 +0000 Subject: [PATCH] chore: promote CHANGELOG for v1.8.0 --- .../1143-claude-orchestration-capability.md | 5 - ...verify-work-security-blocked-next-phase.md | 5 - .changeset/1562-api-coverage-gate.md | 5 - .../1580-999-sentinel-milestone-roadmap.md | 5 - .changeset/1581-config-set-coercion.md | 5 - ...hase-complete-details-wrapped-checklist.md | 6 - .changeset/1682-opencode-mcp-binding.md | 6 - .changeset/1682-opencode-subset-dialect.md | 6 - .changeset/1688-stale-bake-guard.md | 5 - .../1733-windows-agent-skills-path-leak.md | 5 - .../1747-new-project-search-provider-keys.md | 5 - ...tate-json-unbounded-milestone-read-path.md | 5 - ...1772-graphify-update-multi-line-command.md | 5 - ...78-thread-workflow-frontmatter-set-args.md | 5 - .changeset/1817-state-rebuild.md | 5 - .changeset/1821-kilo-zcode-dead-hooks.md | 5 - .changeset/1825-graphify-graph-path.md | 5 - .../1847-claude-sonnet-5-standard-tier.md | 7 - .../1857-test-gate-watch-mode-timeout.md | 5 - .changeset/1864-settings-step-balance.md | 5 - .changeset/1865-launcher-claude-config-dir.md | 5 - .../1906-node-test-causation-mandatory.md | 5 - ...ller-capability-generators-host-version.md | 5 - .changeset/1921-verify-work-gap-recovery.md | 5 - .../1958-debugger-fix-acceptance-guardrail.md | 5 - .changeset/1959-sbfl-fault-localization.md | 5 - .changeset/1960-rca-branching.md | 5 - .changeset/1961-bug-taxonomy-routing.md | 5 - .changeset/1962-repro-hardening.md | 5 - .changeset/1963-prevention-postmortem.md | 5 - .changeset/1964-semantic-kb-recall.md | 5 - .../1988-roadmap-stray-summary-count.md | 5 - .../1993-milestone-ws-requirements-header.md | 5 - .../2002-cli-self-healing-runtime-build.md | 6 - .changeset/2008-command-exit-zero-gate.md | 5 - .../2009-load-failed-capability-fail-open.md | 5 - .../2012-phase-complete-progress-row.md | 5 - .../2017-context7-plugin-grant-prefix.md | 5 - ...2018-applysurface-empty-manifest-agents.md | 5 - .../2019-planning-config-learnings-path.md | 5 - .changeset/2020-executor-dead-sdk-ref.md | 5 - .changeset/2022-roadmap-verify-gate.md | 5 - ...complete-milestone-end-workstream-guard.md | 5 - .../2043-phase-token-single-digit-slug.md | 5 - .changeset/2046-config-set-null-unset.md | 5 - .changeset/2056-plan-phase-foreign-prefix.md | 5 - .../2067-phase-complete-checkbox-regex.md | 5 - .../2071-effort-sync-installed-runtime.md | 5 - ...2-thread-model-into-routed-agent-spawns.md | 5 - .changeset/2073-antigravity-reviewer-block.md | 5 - .../2086-eos-claude-imperative-adapter.md | 5 - .../2087-eos-opencode-imperative-adapter.md | 5 - .../2088-eos-codex-declarative-adapter.md | 5 - .../2089-eos-cursor-imperative-adapter.md | 5 - .../2090-eos-cline-imperative-adapter.md | 5 - .../2091-eos-hermes-imperative-adapter.md | 5 - .../2092-eos-qwen-imperative-adapter.md | 5 - .../2093-eos-kilo-imperative-adapter.md | 5 - .../2094-eos-trae-imperative-adapter.md | 5 - .../2095-eos-kimi-imperative-adapter.md | 5 - ...2096-eos-antigravity-imperative-adapter.md | 5 - .../2097-eos-augment-imperative-adapter.md | 6 - .changeset/2098-eos-codebuddy.md | 6 - .changeset/2099-eos-copilot.md | 6 - .changeset/2100-eos-windsurf.md | 5 - .changeset/2101-eos-zcode.md | 5 - .changeset/2102-eos-pi.md | 5 - .../2104-foreign-prefix-sibling-commands.md | 5 - ...orchestrator-honors-blocking-human-gate.md | 5 - .changeset/2112-commit-files-pathspec.md | 5 - .changeset/2116-surface-bare-require.md | 5 - .changeset/2118-milestone-complete-dry-run.md | 5 - .changeset/2119-secure-phase-single-writer.md | 5 - .changeset/2122-codex-gpt56-model-defaults.md | 5 - .changeset/2198-security-dead-scan-exports.md | 5 - .changeset/2351-portable-timeout.md | 5 - ...ncode-kilo-capability-skill-materialize.md | 5 - .changeset/2388-shared-requirement-gate.md | 5 - .changeset/2390-phase-add-autodetect.md | 5 - ...response-language-orchestrator-coverage.md | 5 - ...06-codex-agent-role-double-registration.md | 5 - .changeset/2496-production-advisories.md | 5 - .changeset/agile-newts-roar.md | 7 - .changeset/agile-pandas-dance.md | 5 - .changeset/agile-rams-climb.md | 5 - .changeset/bold-deer-zip.md | 5 - .changeset/bold-finches-leap.md | 5 - .changeset/bold-goats-wave.md | 5 - .changeset/bold-orcas-wander.md | 7 - .changeset/bold-ravens-wake.md | 7 - .changeset/bold-seals-chatter.md | 5 - .changeset/brave-hawks-fly.md | 5 - .changeset/brave-koalas-glide.md | 5 - .changeset/bright-otters-embed.md | 5 - .changeset/broken-windows-ledger.md | 5 - .changeset/calm-eagles-tumble.md | 6 - .changeset/clever-cats-howl.md | 7 - .changeset/clever-cats-roar.md | 5 - .changeset/clever-eagles-romp.md | 5 - .changeset/clever-lemurs-march.md | 5 - .changeset/clever-moles-frolic.md | 5 - .changeset/clever-orcas-squeak.md | 5 - .changeset/clever-rams-march.md | 5 - .changeset/clever-voles-swim.md | 5 - .changeset/curious-koalas-gather.md | 5 - .changeset/curious-pandas-howl.md | 5 - .changeset/curious-quails-caper.md | 5 - .changeset/curious-rams-run.md | 5 - .changeset/daring-badgers-forage.md | 5 - .changeset/daring-cats-snooze.md | 5 - .changeset/daring-deer-leap.md | 7 - .changeset/daring-otters-dart.md | 5 - .changeset/daring-otters-roar.md | 5 - .changeset/eager-bears-wander.md | 5 - .changeset/eager-elks-frolic.md | 7 - .changeset/eager-ibex-bark.md | 5 - .changeset/eager-pandas-jump.md | 5 - .changeset/eager-tunas-swim.md | 5 - .changeset/eager-wasps-swim.md | 5 - .changeset/eight-foxes-cheer.md | 5 - .changeset/expand-tilde-review-2352.md | 5 - .changeset/external-job-config-wiring.md | 5 - .changeset/fierce-bears-gather.md | 5 - .changeset/fierce-pumas-gather.md | 5 - .changeset/fierce-ravens-dance.md | 5 - .changeset/gallant-cats-hum.md | 5 - .changeset/gallant-foxes-bark.md | 5 - .changeset/gallant-herons-rest.md | 5 - .changeset/gallant-rams-rally.md | 5 - .changeset/gallant-wasps-wave.md | 5 - .changeset/gentle-badgers-roar.md | 5 - .changeset/gentle-koalas-hum.md | 5 - .changeset/gentle-tigers-greet.md | 5 - .changeset/graceful-badgers-click.md | 5 - .changeset/graceful-badgers-dance.md | 5 - .changeset/graceful-geese-click.md | 7 - .changeset/graceful-koalas-forage.md | 5 - .changeset/graceful-koalas-greet.md | 5 - .changeset/graceful-moles-gather.md | 5 - .changeset/graceful-wasps-caper.md | 5 - .changeset/happy-bears-gather.md | 5 - .changeset/happy-birds-chatter.md | 5 - .changeset/happy-jays-travel.md | 7 - .changeset/happy-seals-roam.md | 5 - .changeset/hooks-dist-scoped-ci-race.md | 5 - .changeset/humble-dogs-gather.md | 5 - .changeset/humble-geese-roam.md | 7 - .changeset/humble-jaguars-swim.md | 5 - .changeset/humble-seals-rest.md | 5 - .changeset/humble-sloths-jump.md | 5 - .changeset/humble-tunas-munch.md | 5 - .changeset/humble-tunas-travel.md | 5 - .changeset/humble-voles-glide.md | 5 - .changeset/humble-zebras-zip.md | 5 - .changeset/jolly-jaguars-swim.md | 5 - .changeset/jolly-jays-hop.md | 5 - .changeset/jolly-jays-march.md | 5 - .changeset/kind-lynx-munch.md | 7 - .changeset/kind-tigers-dart.md | 5 - .changeset/kind-tigers-romp.md | 5 - .changeset/lazy-lemurs-jump.md | 5 - .changeset/lively-elks-romp.md | 5 - .changeset/lively-hawks-caper.md | 5 - .changeset/lively-lynx-snooze.md | 5 - .changeset/loud-guard-hooks.md | 5 - .changeset/lucky-mice-wake.md | 5 - .changeset/lucky-quails-greet.md | 5 - .changeset/lucky-tigers-leap.md | 6 - .changeset/mellow-eagles-chatter.md | 5 - .changeset/merry-hawks-swim.md | 5 - .changeset/merry-mice-travel.md | 5 - .changeset/merry-newts-travel.md | 5 - .changeset/merry-tigers-parade.md | 5 - .changeset/nimble-ibex-tumble.md | 7 - .changeset/nimble-jays-roar.md | 5 - .changeset/nimble-ravens-dart.md | 5 - .changeset/nimble-yaks-climb.md | 5 - .changeset/noble-elks-chatter.md | 5 - .changeset/noble-foxes-purr.md | 5 - .changeset/noble-newts-roam.md | 5 - .changeset/noble-wasps-greet.md | 5 - .changeset/patient-geese-howl.md | 5 - .changeset/patient-mice-greet.md | 5 - .changeset/patient-otters-wave.md | 5 - .changeset/patient-voles-chatter.md | 5 - .changeset/phase-id-redos-hardening.md | 5 - .changeset/plucky-bears-snooze.md | 5 - .changeset/plucky-jays-dart.md | 5 - .changeset/plucky-moles-sing.md | 7 - .changeset/plucky-sloths-forage.md | 5 - .changeset/plucky-wasps-sprint.md | 5 - .changeset/plucky-yaks-roar.md | 5 - .changeset/plucky-zebras-jump.md | 5 - .changeset/proud-bears-purr.md | 5 - .changeset/proud-bears-roam.md | 5 - .changeset/proud-cranes-click.md | 5 - .changeset/proud-geese-caper.md | 5 - .changeset/proud-rams-greet.md | 5 - .changeset/proud-ravens-jump.md | 5 - .changeset/proud-zebras-bark.md | 5 - .changeset/quick-elks-climb.md | 5 - .changeset/quick-hawks-bark.md | 5 - .changeset/quick-ibex-bark.md | 5 - .changeset/quick-seals-parade.md | 5 - .changeset/rapid-elks-rest.md | 5 - .changeset/rapid-jays-bark.md | 5 - .changeset/rapid-orcas-sing.md | 7 - .changeset/rapid-pumas-click.md | 5 - .changeset/serene-birds-rest.md | 5 - .changeset/serene-herons-rally.md | 5 - .changeset/serene-koalas-hum.md | 5 - .changeset/serene-lemurs-march.md | 5 - .changeset/sharp-otters-romp.md | 5 - .changeset/silly-moles-romp.md | 5 - .changeset/silly-pandas-gather.md | 5 - .changeset/silly-sloths-dart.md | 5 - .changeset/silly-voles-snooze.md | 5 - .changeset/steady-ibex-run.md | 5 - .changeset/steady-lemurs-run.md | 5 - .changeset/steady-lynx-fly.md | 5 - .changeset/steady-mice-frolic.md | 5 - .changeset/sturdy-cranes-jump.md | 5 - .changeset/sturdy-goats-parade.md | 5 - .changeset/sturdy-ibex-jump.md | 5 - .changeset/sturdy-jays-tumble.md | 5 - .changeset/sturdy-lemurs-forage.md | 5 - .changeset/sturdy-pumas-snooze.md | 5 - .changeset/sturdy-seals-fly.md | 5 - .changeset/sturdy-voles-dart.md | 7 - .changeset/sturdy-voles-tumble.md | 5 - .changeset/sturdy-wasps-run.md | 5 - .changeset/sturdy-wolves-gather.md | 5 - .changeset/sturdy-yaks-caper.md | 5 - .changeset/tidy-badgers-caper.md | 5 - .changeset/tidy-bears-swim.md | 5 - .changeset/tidy-elks-sing.md | 5 - .changeset/tidy-goats-hop.md | 5 - .changeset/tidy-goats-wake.md | 5 - .changeset/tidy-mice-cheer.md | 5 - .changeset/tidy-pumas-munch.md | 5 - .changeset/tidy-tunas-click.md | 5 - .changeset/tidy-voles-glide.md | 5 - .changeset/tidy-zebras-hum.md | 5 - .changeset/vivid-badgers-gather.md | 5 - .changeset/vivid-foxes-click.md | 5 - .changeset/vivid-goats-run.md | 5 - .changeset/vivid-orcas-chatter.md | 5 - .changeset/vivid-seals-purr.md | 5 - .changeset/wise-elks-caper.md | 7 - .changeset/witty-badgers-hum.md | 5 - .changeset/witty-dogs-hop.md | 5 - .changeset/witty-jaguars-gather.md | 5 - .changeset/witty-seals-snooze.md | 7 - .changeset/zcode-runtime-1925.md | 5 - .changeset/zesty-finches-jump.md | 5 - .changeset/zesty-pumas-forage.md | 5 - .changeset/zesty-rams-march.md | 5 - CHANGELOG.md | 275 ++++++++++++++++++ 258 files changed, 275 insertions(+), 1328 deletions(-) delete mode 100644 .changeset/1143-claude-orchestration-capability.md delete mode 100644 .changeset/1528-verify-work-security-blocked-next-phase.md delete mode 100644 .changeset/1562-api-coverage-gate.md delete mode 100644 .changeset/1580-999-sentinel-milestone-roadmap.md delete mode 100644 .changeset/1581-config-set-coercion.md delete mode 100644 .changeset/1591-phase-complete-details-wrapped-checklist.md delete mode 100644 .changeset/1682-opencode-mcp-binding.md delete mode 100644 .changeset/1682-opencode-subset-dialect.md delete mode 100644 .changeset/1688-stale-bake-guard.md delete mode 100644 .changeset/1733-windows-agent-skills-path-leak.md delete mode 100644 .changeset/1747-new-project-search-provider-keys.md delete mode 100644 .changeset/1761-state-json-unbounded-milestone-read-path.md delete mode 100644 .changeset/1772-graphify-update-multi-line-command.md delete mode 100644 .changeset/1778-thread-workflow-frontmatter-set-args.md delete mode 100644 .changeset/1817-state-rebuild.md delete mode 100644 .changeset/1821-kilo-zcode-dead-hooks.md delete mode 100644 .changeset/1825-graphify-graph-path.md delete mode 100644 .changeset/1847-claude-sonnet-5-standard-tier.md delete mode 100644 .changeset/1857-test-gate-watch-mode-timeout.md delete mode 100644 .changeset/1864-settings-step-balance.md delete mode 100644 .changeset/1865-launcher-claude-config-dir.md delete mode 100644 .changeset/1906-node-test-causation-mandatory.md delete mode 100644 .changeset/1920-installer-capability-generators-host-version.md delete mode 100644 .changeset/1921-verify-work-gap-recovery.md delete mode 100644 .changeset/1958-debugger-fix-acceptance-guardrail.md delete mode 100644 .changeset/1959-sbfl-fault-localization.md delete mode 100644 .changeset/1960-rca-branching.md delete mode 100644 .changeset/1961-bug-taxonomy-routing.md delete mode 100644 .changeset/1962-repro-hardening.md delete mode 100644 .changeset/1963-prevention-postmortem.md delete mode 100644 .changeset/1964-semantic-kb-recall.md delete mode 100644 .changeset/1988-roadmap-stray-summary-count.md delete mode 100644 .changeset/1993-milestone-ws-requirements-header.md delete mode 100644 .changeset/2002-cli-self-healing-runtime-build.md delete mode 100644 .changeset/2008-command-exit-zero-gate.md delete mode 100644 .changeset/2009-load-failed-capability-fail-open.md delete mode 100644 .changeset/2012-phase-complete-progress-row.md delete mode 100644 .changeset/2017-context7-plugin-grant-prefix.md delete mode 100644 .changeset/2018-applysurface-empty-manifest-agents.md delete mode 100644 .changeset/2019-planning-config-learnings-path.md delete mode 100644 .changeset/2020-executor-dead-sdk-ref.md delete mode 100644 .changeset/2022-roadmap-verify-gate.md delete mode 100644 .changeset/2028-phase-complete-milestone-end-workstream-guard.md delete mode 100644 .changeset/2043-phase-token-single-digit-slug.md delete mode 100644 .changeset/2046-config-set-null-unset.md delete mode 100644 .changeset/2056-plan-phase-foreign-prefix.md delete mode 100644 .changeset/2067-phase-complete-checkbox-regex.md delete mode 100644 .changeset/2071-effort-sync-installed-runtime.md delete mode 100644 .changeset/2072-thread-model-into-routed-agent-spawns.md delete mode 100644 .changeset/2073-antigravity-reviewer-block.md delete mode 100644 .changeset/2086-eos-claude-imperative-adapter.md delete mode 100644 .changeset/2087-eos-opencode-imperative-adapter.md delete mode 100644 .changeset/2088-eos-codex-declarative-adapter.md delete mode 100644 .changeset/2089-eos-cursor-imperative-adapter.md delete mode 100644 .changeset/2090-eos-cline-imperative-adapter.md delete mode 100644 .changeset/2091-eos-hermes-imperative-adapter.md delete mode 100644 .changeset/2092-eos-qwen-imperative-adapter.md delete mode 100644 .changeset/2093-eos-kilo-imperative-adapter.md delete mode 100644 .changeset/2094-eos-trae-imperative-adapter.md delete mode 100644 .changeset/2095-eos-kimi-imperative-adapter.md delete mode 100644 .changeset/2096-eos-antigravity-imperative-adapter.md delete mode 100644 .changeset/2097-eos-augment-imperative-adapter.md delete mode 100644 .changeset/2098-eos-codebuddy.md delete mode 100644 .changeset/2099-eos-copilot.md delete mode 100644 .changeset/2100-eos-windsurf.md delete mode 100644 .changeset/2101-eos-zcode.md delete mode 100644 .changeset/2102-eos-pi.md delete mode 100644 .changeset/2104-foreign-prefix-sibling-commands.md delete mode 100644 .changeset/2107-orchestrator-honors-blocking-human-gate.md delete mode 100644 .changeset/2112-commit-files-pathspec.md delete mode 100644 .changeset/2116-surface-bare-require.md delete mode 100644 .changeset/2118-milestone-complete-dry-run.md delete mode 100644 .changeset/2119-secure-phase-single-writer.md delete mode 100644 .changeset/2122-codex-gpt56-model-defaults.md delete mode 100644 .changeset/2198-security-dead-scan-exports.md delete mode 100644 .changeset/2351-portable-timeout.md delete mode 100644 .changeset/2362-opencode-kilo-capability-skill-materialize.md delete mode 100644 .changeset/2388-shared-requirement-gate.md delete mode 100644 .changeset/2390-phase-add-autodetect.md delete mode 100644 .changeset/2402-response-language-orchestrator-coverage.md delete mode 100644 .changeset/2406-codex-agent-role-double-registration.md delete mode 100644 .changeset/2496-production-advisories.md delete mode 100644 .changeset/agile-newts-roar.md delete mode 100644 .changeset/agile-pandas-dance.md delete mode 100644 .changeset/agile-rams-climb.md delete mode 100644 .changeset/bold-deer-zip.md delete mode 100644 .changeset/bold-finches-leap.md delete mode 100644 .changeset/bold-goats-wave.md delete mode 100644 .changeset/bold-orcas-wander.md delete mode 100644 .changeset/bold-ravens-wake.md delete mode 100644 .changeset/bold-seals-chatter.md delete mode 100644 .changeset/brave-hawks-fly.md delete mode 100644 .changeset/brave-koalas-glide.md delete mode 100644 .changeset/bright-otters-embed.md delete mode 100644 .changeset/broken-windows-ledger.md delete mode 100644 .changeset/calm-eagles-tumble.md delete mode 100644 .changeset/clever-cats-howl.md delete mode 100644 .changeset/clever-cats-roar.md delete mode 100644 .changeset/clever-eagles-romp.md delete mode 100644 .changeset/clever-lemurs-march.md delete mode 100644 .changeset/clever-moles-frolic.md delete mode 100644 .changeset/clever-orcas-squeak.md delete mode 100644 .changeset/clever-rams-march.md delete mode 100644 .changeset/clever-voles-swim.md delete mode 100644 .changeset/curious-koalas-gather.md delete mode 100644 .changeset/curious-pandas-howl.md delete mode 100644 .changeset/curious-quails-caper.md delete mode 100644 .changeset/curious-rams-run.md delete mode 100644 .changeset/daring-badgers-forage.md delete mode 100644 .changeset/daring-cats-snooze.md delete mode 100644 .changeset/daring-deer-leap.md delete mode 100644 .changeset/daring-otters-dart.md delete mode 100644 .changeset/daring-otters-roar.md delete mode 100644 .changeset/eager-bears-wander.md delete mode 100644 .changeset/eager-elks-frolic.md delete mode 100644 .changeset/eager-ibex-bark.md delete mode 100644 .changeset/eager-pandas-jump.md delete mode 100644 .changeset/eager-tunas-swim.md delete mode 100644 .changeset/eager-wasps-swim.md delete mode 100644 .changeset/eight-foxes-cheer.md delete mode 100644 .changeset/expand-tilde-review-2352.md delete mode 100644 .changeset/external-job-config-wiring.md delete mode 100644 .changeset/fierce-bears-gather.md delete mode 100644 .changeset/fierce-pumas-gather.md delete mode 100644 .changeset/fierce-ravens-dance.md delete mode 100644 .changeset/gallant-cats-hum.md delete mode 100644 .changeset/gallant-foxes-bark.md delete mode 100644 .changeset/gallant-herons-rest.md delete mode 100644 .changeset/gallant-rams-rally.md delete mode 100644 .changeset/gallant-wasps-wave.md delete mode 100644 .changeset/gentle-badgers-roar.md delete mode 100644 .changeset/gentle-koalas-hum.md delete mode 100644 .changeset/gentle-tigers-greet.md delete mode 100644 .changeset/graceful-badgers-click.md delete mode 100644 .changeset/graceful-badgers-dance.md delete mode 100644 .changeset/graceful-geese-click.md delete mode 100644 .changeset/graceful-koalas-forage.md delete mode 100644 .changeset/graceful-koalas-greet.md delete mode 100644 .changeset/graceful-moles-gather.md delete mode 100644 .changeset/graceful-wasps-caper.md delete mode 100644 .changeset/happy-bears-gather.md delete mode 100644 .changeset/happy-birds-chatter.md delete mode 100644 .changeset/happy-jays-travel.md delete mode 100644 .changeset/happy-seals-roam.md delete mode 100644 .changeset/hooks-dist-scoped-ci-race.md delete mode 100644 .changeset/humble-dogs-gather.md delete mode 100644 .changeset/humble-geese-roam.md delete mode 100644 .changeset/humble-jaguars-swim.md delete mode 100644 .changeset/humble-seals-rest.md delete mode 100644 .changeset/humble-sloths-jump.md delete mode 100644 .changeset/humble-tunas-munch.md delete mode 100644 .changeset/humble-tunas-travel.md delete mode 100644 .changeset/humble-voles-glide.md delete mode 100644 .changeset/humble-zebras-zip.md delete mode 100644 .changeset/jolly-jaguars-swim.md delete mode 100644 .changeset/jolly-jays-hop.md delete mode 100644 .changeset/jolly-jays-march.md delete mode 100644 .changeset/kind-lynx-munch.md delete mode 100644 .changeset/kind-tigers-dart.md delete mode 100644 .changeset/kind-tigers-romp.md delete mode 100644 .changeset/lazy-lemurs-jump.md delete mode 100644 .changeset/lively-elks-romp.md delete mode 100644 .changeset/lively-hawks-caper.md delete mode 100644 .changeset/lively-lynx-snooze.md delete mode 100644 .changeset/loud-guard-hooks.md delete mode 100644 .changeset/lucky-mice-wake.md delete mode 100644 .changeset/lucky-quails-greet.md delete mode 100644 .changeset/lucky-tigers-leap.md delete mode 100644 .changeset/mellow-eagles-chatter.md delete mode 100644 .changeset/merry-hawks-swim.md delete mode 100644 .changeset/merry-mice-travel.md delete mode 100644 .changeset/merry-newts-travel.md delete mode 100644 .changeset/merry-tigers-parade.md delete mode 100644 .changeset/nimble-ibex-tumble.md delete mode 100644 .changeset/nimble-jays-roar.md delete mode 100644 .changeset/nimble-ravens-dart.md delete mode 100644 .changeset/nimble-yaks-climb.md delete mode 100644 .changeset/noble-elks-chatter.md delete mode 100644 .changeset/noble-foxes-purr.md delete mode 100644 .changeset/noble-newts-roam.md delete mode 100644 .changeset/noble-wasps-greet.md delete mode 100644 .changeset/patient-geese-howl.md delete mode 100644 .changeset/patient-mice-greet.md delete mode 100644 .changeset/patient-otters-wave.md delete mode 100644 .changeset/patient-voles-chatter.md delete mode 100644 .changeset/phase-id-redos-hardening.md delete mode 100644 .changeset/plucky-bears-snooze.md delete mode 100644 .changeset/plucky-jays-dart.md delete mode 100644 .changeset/plucky-moles-sing.md delete mode 100644 .changeset/plucky-sloths-forage.md delete mode 100644 .changeset/plucky-wasps-sprint.md delete mode 100644 .changeset/plucky-yaks-roar.md delete mode 100644 .changeset/plucky-zebras-jump.md delete mode 100644 .changeset/proud-bears-purr.md delete mode 100644 .changeset/proud-bears-roam.md delete mode 100644 .changeset/proud-cranes-click.md delete mode 100644 .changeset/proud-geese-caper.md delete mode 100644 .changeset/proud-rams-greet.md delete mode 100644 .changeset/proud-ravens-jump.md delete mode 100644 .changeset/proud-zebras-bark.md delete mode 100644 .changeset/quick-elks-climb.md delete mode 100644 .changeset/quick-hawks-bark.md delete mode 100644 .changeset/quick-ibex-bark.md delete mode 100644 .changeset/quick-seals-parade.md delete mode 100644 .changeset/rapid-elks-rest.md delete mode 100644 .changeset/rapid-jays-bark.md delete mode 100644 .changeset/rapid-orcas-sing.md delete mode 100644 .changeset/rapid-pumas-click.md delete mode 100644 .changeset/serene-birds-rest.md delete mode 100644 .changeset/serene-herons-rally.md delete mode 100644 .changeset/serene-koalas-hum.md delete mode 100644 .changeset/serene-lemurs-march.md delete mode 100644 .changeset/sharp-otters-romp.md delete mode 100644 .changeset/silly-moles-romp.md delete mode 100644 .changeset/silly-pandas-gather.md delete mode 100644 .changeset/silly-sloths-dart.md delete mode 100644 .changeset/silly-voles-snooze.md delete mode 100644 .changeset/steady-ibex-run.md delete mode 100644 .changeset/steady-lemurs-run.md delete mode 100644 .changeset/steady-lynx-fly.md delete mode 100644 .changeset/steady-mice-frolic.md delete mode 100644 .changeset/sturdy-cranes-jump.md delete mode 100644 .changeset/sturdy-goats-parade.md delete mode 100644 .changeset/sturdy-ibex-jump.md delete mode 100644 .changeset/sturdy-jays-tumble.md delete mode 100644 .changeset/sturdy-lemurs-forage.md delete mode 100644 .changeset/sturdy-pumas-snooze.md delete mode 100644 .changeset/sturdy-seals-fly.md delete mode 100644 .changeset/sturdy-voles-dart.md delete mode 100644 .changeset/sturdy-voles-tumble.md delete mode 100644 .changeset/sturdy-wasps-run.md delete mode 100644 .changeset/sturdy-wolves-gather.md delete mode 100644 .changeset/sturdy-yaks-caper.md delete mode 100644 .changeset/tidy-badgers-caper.md delete mode 100644 .changeset/tidy-bears-swim.md delete mode 100644 .changeset/tidy-elks-sing.md delete mode 100644 .changeset/tidy-goats-hop.md delete mode 100644 .changeset/tidy-goats-wake.md delete mode 100644 .changeset/tidy-mice-cheer.md delete mode 100644 .changeset/tidy-pumas-munch.md delete mode 100644 .changeset/tidy-tunas-click.md delete mode 100644 .changeset/tidy-voles-glide.md delete mode 100644 .changeset/tidy-zebras-hum.md delete mode 100644 .changeset/vivid-badgers-gather.md delete mode 100644 .changeset/vivid-foxes-click.md delete mode 100644 .changeset/vivid-goats-run.md delete mode 100644 .changeset/vivid-orcas-chatter.md delete mode 100644 .changeset/vivid-seals-purr.md delete mode 100644 .changeset/wise-elks-caper.md delete mode 100644 .changeset/witty-badgers-hum.md delete mode 100644 .changeset/witty-dogs-hop.md delete mode 100644 .changeset/witty-jaguars-gather.md delete mode 100644 .changeset/witty-seals-snooze.md delete mode 100644 .changeset/zcode-runtime-1925.md delete mode 100644 .changeset/zesty-finches-jump.md delete mode 100644 .changeset/zesty-pumas-forage.md delete mode 100644 .changeset/zesty-rams-march.md diff --git a/.changeset/1143-claude-orchestration-capability.md b/.changeset/1143-claude-orchestration-capability.md deleted file mode 100644 index d87aae625..000000000 --- a/.changeset/1143-claude-orchestration-capability.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2044 ---- -**A default-off, BETA, claude-only "Claude orchestration" capability** — adopts Claude Code's Workflow tool (`/effort ultracode`, Agent SDK ≥ v0.3.149) as an optional parallel-execution backend for the GSD loop, restoring the wave parallelism + plan-checker + verifier that the #853 backgrounded-agent nesting limitation forces inline on Claude Code, and folding the existing `gsd-ultraplan-phase` plan-offload under the same runtime gate. When `claude_orchestration.enabled` is on AND the runtime is Claude AND the Workflow tool is detected AND the Agent SDK meets the floor (`claude_orchestration.min_agent_sdk_version`, default `0.3.149`), `execute-phase` emits a generated Workflow script (`waves → parallel() barriers`, `plans → agent({ agentType: 'gsd-executor', isolation: 'worktree' })`, `files_modified overlap → separate sequential stages`, `resumeFromRunId` wired to the phase run id, shared `budget` pool) that composes the SAME executor agent + worktree isolation the inline path uses, so artifacts/commits are produced identically. Detection is pure and fail-closed (any miss → inline), so on any runtime lacking the Workflow tool behaviour is byte-identical to today. Adds a pure module `gsd-core/bin/lib/claude-orchestration.cjs` (`detectWorkflowBackend`, `emitWorkflowScript`), the `capabilities/claude-orchestration/` declaration with two gated loop contributions (`execute:wave:post`, `plan:post`) and a `claude-orchestration` command family (`gsd-tools claude-orchestration detect-backend|emit-workflow`), federated config keys, and an ADR-1143 implementation amendment. (#1143) diff --git a/.changeset/1528-verify-work-security-blocked-next-phase.md b/.changeset/1528-verify-work-security-blocked-next-phase.md deleted file mode 100644 index 2525e0ef4..000000000 --- a/.changeset/1528-verify-work-security-blocked-next-phase.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1687 ---- -The `verify-work` security-blocked presentation no longer offers next-phase planning. When security enforcement blocks phase advancement (no `SECURITY.md` produced), the workflow now routes only to the current-phase fix instead of competing `/gsd:plan-phase {next}` and `/gsd:execute-phase {next}` options. diff --git a/.changeset/1562-api-coverage-gate.md b/.changeset/1562-api-coverage-gate.md deleted file mode 100644 index 9abfb1f52..000000000 --- a/.changeset/1562-api-coverage-gate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2065 ---- -**Phases that integrate an external API/SDK/service can no longer seal without a decided coverage matrix** — a new `api-coverage` gate on the `ai-integration` capability blocks `/gsd:verify-work` until the phase produces a `COVERAGE.md` enumerating the API's full capability surface, with every non-integrated capability an explicit, reasoned opt-out. Full coverage is the default; the matrix is the subtraction record, so "we integrated the API" can no longer silently mean "we integrated whatever the first use case exercised." Toggleable via `workflow.api_coverage_gate` (on by default). (#1562) diff --git a/.changeset/1580-999-sentinel-milestone-roadmap.md b/.changeset/1580-999-sentinel-milestone-roadmap.md deleted file mode 100644 index 2ddf49e5f..000000000 --- a/.changeset/1580-999-sentinel-milestone-roadmap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1691 ---- -`milestone complete` and `roadmap analyze` now exclude the Phase 0 / Phase 999 backlog sentinels. A milestone whose only directory-less ROADMAP heading is a backlog sentinel can be completed without `--force`, and `roadmap analyze` no longer counts the sentinel in `phase_count` or routes `next_phase` into it. Completes the `^999` exclusion #1445 added to the progress denominators. diff --git a/.changeset/1581-config-set-coercion.md b/.changeset/1581-config-set-coercion.md deleted file mode 100644 index f035d15b2..000000000 --- a/.changeset/1581-config-set-coercion.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2023 ---- -**`config-set` no longer silently coerces values into something the disk never sees** — `Number.isFinite` replaced `!isNaN` in the value parser so `Infinity`/`-Infinity` are no longer coerced to non-finite numbers that `JSON.stringify` then renders as `null` on disk while the CLI echoes `Infinity` (output ≠ disk). `context_window` now has a per-key validator requiring a finite positive integer (rejects `Infinity`, `0`, negatives, non-integers with a non-zero exit), and `project_code` is always persisted as a string so a leading-zero code like `007` survives verbatim instead of collapsing to `7`. Numeric coercion for genuine numeric keys (e.g. `granularity 42`) is unchanged. (#1581) diff --git a/.changeset/1591-phase-complete-details-wrapped-checklist.md b/.changeset/1591-phase-complete-details-wrapped-checklist.md deleted file mode 100644 index 1c2ef3625..000000000 --- a/.changeset/1591-phase-complete-details-wrapped-checklist.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Fixed -pr: 1819 ---- -**`phase.complete` no longer reports a false `is_last_phase` on a `
`-wrapped checkbox checklist (#1591, #1752)** — when the active milestone's phase checklist was written as `- [ ] Phase N:` checkbox items inside a `
` block and the next phase had no directory on disk yet (still in planning), `phase.complete`'s `isLastPhase` roadmap-enumeration fallback used a heading-only pattern (`/#{2,4}\s*Phase…/`) that never matched checkbox items. It returned `is_last_phase: true, next_phase: null` on a mid-milestone phase and — via the milestone-complete cascade — wrongly flipped STATE.md to `Milestone complete` and decremented `progress.total_phases` (e.g. 8 → 7). The pattern now matches heading-style (`### Phase N:`), plain checkbox-list phases (`- [ ] Phase N:` / `- [x] Phase N:`), and the canonical **bold** checklist form the roadmap template emits (`- [ ] **Phase N: Name**`); `extractCurrentMilestone` already surfaces the `
`-wrapped checklist correctly, so no parser change was needed. Only the reproduced `phase.complete` fallback is changed; the heading-only sibling patterns elsewhere in `phase.cts` are untouched. - diff --git a/.changeset/1682-opencode-mcp-binding.md b/.changeset/1682-opencode-mcp-binding.md deleted file mode 100644 index 4b71a79c5..000000000 --- a/.changeset/1682-opencode-mcp-binding.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Added -pr: 1929 ---- - -**OpenCode installs now auto-register the GSD companion MCP server (`mcp.gsd`)** — `--opencode` install writes a `mcp.gsd` entry (local stdio → `gsd-mcp-server`) into `opencode.json`, so OpenCode drives GSD's command + planning-state surface over MCP with no bespoke plugin (ADR-1239 Phase D / #1682). Idempotent and non-clobbering; a user-defined `mcp.gsd` is preserved. (#1682) diff --git a/.changeset/1682-opencode-subset-dialect.md b/.changeset/1682-opencode-subset-dialect.md deleted file mode 100644 index ef9e18138..000000000 --- a/.changeset/1682-opencode-subset-dialect.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Added -pr: 1930 ---- - -**OpenCode plugin handles `session.idle` + the `opencode-subset` hook dialect is implemented** — the GSD OpenCode plugin now recognizes `session.idle` (↔ Claude `Stop` lifecycle point), completing the compaction/idle pair (#1914 shipped compaction). The reserved `opencode-subset` dialect gains a consumer — `hookEventSurfaceFor()` in `host-integration.cts` — describing OpenCode's session/tool/file event subset (no workflow-phase events; the engine owns phase sequencing, ADR-1239 §OpenCode binding). Adds a Claude-parity test asserting the plugin covers the full declared subset. (#1682) diff --git a/.changeset/1688-stale-bake-guard.md b/.changeset/1688-stale-bake-guard.md deleted file mode 100644 index 63e5af983..000000000 --- a/.changeset/1688-stale-bake-guard.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1692 ---- -**GSD now warns when model config changed without re-running the installer on static-frontmatter runtimes** — on `codex` and `opencode`, editing `model_overrides` or `model_profile_overrides` or `model_policy.runtime_tiers` in `.planning/config.json` or `~/.gsd/defaults.json` previously had no effect until the user re-ran `gsd install `, and the failure was silent: the sub-agent kept using the base model. Workflow entry points like `gsd-tools init *` now emit a one-line stderr warning naming the changed config file and the exact remediation command when they detect the config is newer than the baked agent files. The guard is read-only and warning-only by default, dedup'd per session, and skipped entirely on Claude Code because Claude Code resolves models at spawn time. Resolves #1688 as the structural follow-up to #1650. diff --git a/.changeset/1733-windows-agent-skills-path-leak.md b/.changeset/1733-windows-agent-skills-path-leak.md deleted file mode 100644 index 6c40bb8bc..000000000 --- a/.changeset/1733-windows-agent-skills-path-leak.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1736 ---- -The `` block emitted by `gsd init` no longer leaks backslash paths into `@`-reference skill paths on Windows. The global skill directory (a native `path.join` result) was interpolated into the generated markdown without POSIX normalization, producing references like `@C:\…\skills\name/SKILL.md`; the reference is now normalized at the emit site so skill references use forward slashes on every platform. diff --git a/.changeset/1747-new-project-search-provider-keys.md b/.changeset/1747-new-project-search-provider-keys.md deleted file mode 100644 index 08f8fdbe0..000000000 --- a/.changeset/1747-new-project-search-provider-keys.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1814 ---- -**`/gsd-settings` no longer warns about four search-provider keys on fresh projects (#1747)** — `buildNewProjectConfig` emits seven search-provider availability flags and `research-provider.cts` `providerAvailability()` consumes all seven, but only three were registered in `VALID_CONFIG_KEYS` (`config-schema.manifest.json`). Running `/gsd-settings` on a freshly generated `.planning/config.json` printed `unknown config key(s) … tavily_search, ref_search, perplexity, jina — these will be ignored` even though the user never hand-edited the config. The four missing keys are now registered alongside `brave_search`/`firecrawl`/`exa_search` and documented in `docs/CONFIGURATION.md`; a drift guard in `tests/bug-2530-valid-config-keys.test.cjs` now requires every config-driven research-provider flag to be in the schema, so a future provider addition cannot reintroduce the drift. diff --git a/.changeset/1761-state-json-unbounded-milestone-read-path.md b/.changeset/1761-state-json-unbounded-milestone-read-path.md deleted file mode 100644 index bd1c4f043..000000000 --- a/.changeset/1761-state-json-unbounded-milestone-read-path.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1818 ---- -**`gsd-tools state json` no longer reports conflated progress for an unversioned milestone (#1761)** — the ADR-1769 Phase 7 fix (#1794) taught `state sync` to leave Progress untouched when a milestone version is asserted but the ROADMAP has no versioned heading for it, but the `state json` **read** path still rebuilt progress via `buildStateFrontmatter`, whose phase-heading count fell back to the whole document and summed sibling milestones. `state json` therefore reported a conflated `total_phases` (e.g. 8 = 4+4 across two milestones) plus a derived `percent`, contradicting the sync guard on the very same project. The read path now mirrors the sync guard: when the asserted milestone cannot be bounded to a versioned ROADMAP heading, `total_phases` falls back to the on-disk phase-dir count and `percent` is omitted. Bounded milestones (versioned ROADMAP, or no milestone asserted) are unchanged; the signal rides on the existing `_diskScanCache` so `extractCurrentMilestone`'s return contract and its other callers are untouched. diff --git a/.changeset/1772-graphify-update-multi-line-command.md b/.changeset/1772-graphify-update-multi-line-command.md deleted file mode 100644 index 7e188785c..000000000 --- a/.changeset/1772-graphify-update-multi-line-command.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1815 ---- -**`gsd-graphify-update.sh` now reads the full multi-line command in Gate 2 (#1772)** — the PostToolUse auto-update hook joined `tool_name` + `\n` + `tool_input.command` and extracted the command with `sed -n '2p'` (line 2 only). Agent runtimes (Claude Code's Bash tool among them) routinely emit HEAD-advancing commits as multi-line scripts (`cd /path`, then `git add`, then `git commit …`), so line 2 was the `cd`, Gate 2's `*"git commit"*` match failed, and the rebuild silently no-op'd on real commits even with `graphify.auto_update: true`. The failure was invisible in manual probes because a single-line `git commit -m x` passes line 2 verbatim. The hook now captures line 2 through EOF (`sed -n '2,$p'`) so the `case` glob sees the full command string; single-line behavior is unchanged and multi-line commands without a HEAD-advancing op still no-op cleanly. diff --git a/.changeset/1778-thread-workflow-frontmatter-set-args.md b/.changeset/1778-thread-workflow-frontmatter-set-args.md deleted file mode 100644 index 5117b9fae..000000000 --- a/.changeset/1778-thread-workflow-frontmatter-set-args.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1816 ---- -**`/gsd-thread close|resume` now writes the thread status/updated frontmatter (#1778)** — the thread workflow's CLOSE and RESUME branches invoked `frontmatter.set` with the pre-1.6 fully-positional shape (`frontmatter.set `), but since 1.6 the dispatcher parses the file positionally and reads `field`/`value` from the named flags `--field`/`--value` via `parseNamedArgs`. The positional form left `field`/`value` undefined, `cmdFrontmatterSet` errored `file, field, and value required`, and the writes were silently skipped — so closing a thread never marked it `status: resolved` and resuming never marked it `status: in_progress`, with the error scrolling past on every thread command. All four sites (CLOSE `status`+`updated`, RESUME `status`+`updated`) now use the 1.6 hybrid form that `verify-work.md` already uses (`frontmatter.set --field --value `). diff --git a/.changeset/1817-state-rebuild.md b/.changeset/1817-state-rebuild.md deleted file mode 100644 index 8a7ddd6a3..000000000 --- a/.changeset/1817-state-rebuild.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1830 ---- -**`gsd-tools state rebuild`** — new subcommand that re-derives STATE.md body structure from canonical sources (frontmatter + `.planning/phases/` disk scan), reconciling drifted `## Current Position` prose, dropping orphaned rows from the `**By Phase:**` table, clearing template-placeholder field values, and de-duplicating `## Session Continuity Archive` blocks. Every mutation is recorded in a `## Rebuild Log` audit section. Idempotent (running twice on a clean file is a no-op). Supports `--dry-run` (preview) and `--verbose` (tee log to stderr). Heavier, manual counterpart to the lightweight auto-triggered `state sync`. diff --git a/.changeset/1821-kilo-zcode-dead-hooks.md b/.changeset/1821-kilo-zcode-dead-hooks.md deleted file mode 100644 index 30058bea0..000000000 --- a/.changeset/1821-kilo-zcode-dead-hooks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2057 ---- -**The installer no longer copies dead lifecycle hook scripts for ZCode** — it declares `hooksSurface: 'none'` and has no plugin surface, so the staged `hooks/*.js`, `hooks/*.sh`, `hooks/lib/` and the CommonJS `package.json` marker were dead weight in `~/.zcode/`. The hook-copy guards in `install.js` now exclude ZCode alongside the other no-hook runtimes. OpenCode, which also declares `hooksSurface: 'none'`, is deliberately kept: its native plugin adapter (#1914) spawns those staged hooks via OpenCode's event bus and needs both them and the marker. (This fix originally excluded Kilo too, on the premise that it had no plugin surface; that premise was wrong — Kilo's native plugin spawns the staged guard hooks, exactly like OpenCode's — and #2327 reverses the Kilo half.) diff --git a/.changeset/1825-graphify-graph-path.md b/.changeset/1825-graphify-graph-path.md deleted file mode 100644 index f260e261d..000000000 --- a/.changeset/1825-graphify-graph-path.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2013 ---- -**`graphify.graph_path` makes the knowledge-graph location configurable so one umbrella graph can serve multiple projects** — a new `.planning/config.json` key (path relative to project root, or absolute) overrides where `/gsd-graphify query|status|diff` read the graph, letting a single curated cross-repo umbrella graph serve every sibling sub-project without N drifting ~5 MB mirror copies. Previously the graph location was hardcoded to `/.planning/graphs/` with no override; the only workaround was copying the umbrella `graph.json` into each project (which drifted, wasted disk, and could be silently overwritten by an in-project build). The diff snapshot travels with the configured graph; build stays project-scoped; unset → byte-identical default; a configured-but-missing file yields an actionable error naming the path. (#1825) diff --git a/.changeset/1847-claude-sonnet-5-standard-tier.md b/.changeset/1847-claude-sonnet-5-standard-tier.md deleted file mode 100644 index 34682694f..000000000 --- a/.changeset/1847-claude-sonnet-5-standard-tier.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Added -pr: 1848 ---- -**Claude Sonnet 5 is now the `standard` (sonnet) tier model.** The model catalog and provider presets resolve the sonnet/standard tier to `claude-sonnet-5` (GA 2026-06-30) across the Anthropic-backed runtimes (`claude`, `copilot`, and the `anthropic`/`anthropic-fable` presets), plus the OpenRouter-style `anthropic/claude-sonnet-5` for `opencode`/`hermes`, replacing the superseded `claude-sonnet-4-6`. Opus and Haiku tier defaults are unchanged (the `haiku` high-effort preset's escalation slot tracks the current sonnet model). Shipped in 1.6.1. (#1847) - - diff --git a/.changeset/1857-test-gate-watch-mode-timeout.md b/.changeset/1857-test-gate-watch-mode-timeout.md deleted file mode 100644 index 7d9054ff7..000000000 --- a/.changeset/1857-test-gate-watch-mode-timeout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2060 ---- -**Test gates can no longer hang forever on a watch-mode test runner.** vitest defaults to watch mode in an interactive terminal (exactly where `gsd-execute-phase` runs), so a resolved `npm test` / `pnpm test` that maps to vitest never exited and the orchestrator waited indefinitely until the user manually intervened. Every GSD test-command gate — the regression gate, the post-merge gate, the audit-fix gate, and the verify-phase gate — now routes the resolved command through a shared `normalize-test-command` helper that rewrites it to a one-shot form (direct vitest → `vitest run`; jest `--watch` → `--watchAll=false`; a package-manager `test` script backed by watch-vitest → `CI=true` prefix; already-one-shot commands are left unchanged). The three gates that previously hung or silently continued — the regression, post-merge, and audit-fix gates — additionally bound execution with a configurable `workflow.test_gate_timeout` (default 600s), aborting or surfacing the cause on timeout instead of hanging; the verify-phase gate was already bounded (a fixed 5-minute limit) and keeps it, now naming watch mode on timeout. The normalizer only rewrites a runner named as a standalone command token (so paths/targets like `run-vitest.js` are never mangled), is length-capped and linear-time on adversarial input, and only reads a regular-file `package.json`. diff --git a/.changeset/1864-settings-step-balance.md b/.changeset/1864-settings-step-balance.md deleted file mode 100644 index 1dcbdced0..000000000 --- a/.changeset/1864-settings-step-balance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2014 ---- -**`settings-advanced.md` no longer has an orphan `` around §8 Model Policy** — the §8 Model Policy block ended with a closing `` but had no matching opening tag (5 opens / 6 closes), leaving its content as loose inter-step prose that could fail to execute reliably. Added the missing `` opener so the section is a proper step. A new workflow ``-tag-balance regression guard (fenced-code-stripped) now blocks any future orphan tag across all top-level workflows. (#1864) diff --git a/.changeset/1865-launcher-claude-config-dir.md b/.changeset/1865-launcher-claude-config-dir.md deleted file mode 100644 index 4828fb14f..000000000 --- a/.changeset/1865-launcher-claude-config-dir.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2024 ---- -**The runtime launcher now honors `CLAUDE_CONFIG_DIR`** — the `gsd_run` preamble embedded in every workflow/agent resolved the Claude global install only at `$HOME/.claude/gsd-core/bin/`, while the installer honored `CLAUDE_CONFIG_DIR`, so a global install redirected via `CLAUDE_CONFIG_DIR` was invisible to every `gsd_run` call (every GSD command failed with `gsd-tools.cjs not found`). The Claude resolver arm now uses `${CLAUDE_CONFIG_DIR:-$HOME/.claude}` — matching the installer and the other runtimes' `${VAR:-default}` pattern — so a custom `CLAUDE_CONFIG_DIR` is found and the default `$HOME/.claude` path is unchanged. Re-synced into all 95 workflows/agents; two capped workflows trimmed to stay under their byte budgets. (#1865) diff --git a/.changeset/1906-node-test-causation-mandatory.md b/.changeset/1906-node-test-causation-mandatory.md deleted file mode 100644 index 4c6fc413e..000000000 --- a/.changeset/1906-node-test-causation-mandatory.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2001 ---- -**Node-test prohibition proofs now require a clean-fixture causation control** — a `node-test` prohibition's fail-first proof no longer accepts a deceptive content-independent negative test (one that reds merely because `GSD_PROHIB_SUBJECT` is *set*, ignoring the subject's content). The `check_clean_fixture` control is now **mandatory** for the `node-test` kind: a descriptor that omits it is un-provable and hard-gates, rather than greening on the violation alone. **Breaking (Hyrum):** a previously-green node-test prohibition with no clean fixture now hard-gates — blast radius is zero in-tree (no `node-test` prohibition ships today). The `lint-rule` kind is unchanged (its subject IS the linted file, no `GSD_PROHIB_SUBJECT` indirection). (#1906) diff --git a/.changeset/1920-installer-capability-generators-host-version.md b/.changeset/1920-installer-capability-generators-host-version.md deleted file mode 100644 index 37d491fe0..000000000 --- a/.changeset/1920-installer-capability-generators-host-version.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1938 ---- -**Third-party capabilities now work on installed layouts.** `capability install` no longer rejects capabilities with a real `engines.gsd` range as "incompatible with GSD 0.0.0" — the host version is now read from the authoritative `gsd-core/VERSION` file across every runtime and the `capability install` CLI. The installer also now ships the registry generator scripts (`gen-capability-registry.cjs`, `gen-loop-host-contract.cjs`), so installed third-party capabilities actually compose into the loop instead of being silently discarded. diff --git a/.changeset/1921-verify-work-gap-recovery.md b/.changeset/1921-verify-work-gap-recovery.md deleted file mode 100644 index 776f031bb..000000000 --- a/.changeset/1921-verify-work-gap-recovery.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2025 ---- -**`/gsd:verify-work` preserves verification state across gap-closure execution and no longer auto-promotes deferred follow-ups into blocking gaps** — resuming after `/gsd:execute-phase --gaps-only` used to lose the verification state: the UAT `## Gaps` still read `status: failed` even after their fix plans executed, so verify-work re-diagnosed them as fresh blockers, spawned a new gap plan, and reported only the new plan as verified. A state contract now links each gap to its fix plan: every UAT gap carries a stable `gap_id` (`G-{phase}-{N}`), gap-closure plans tag the ids they address in their frontmatter (`gap_ids: […]`), and a new `reconcile_gaps` step on resume marks a gap `status: resolved` when its plan has a matching `*-SUMMARY.md` — so fixed gaps aren't re-diagnosed and the phase can close. Separately, a deferred-follow-up branch captures future-work ideas (signals like "later", "next version", "out of scope") into a `## Deferred Follow-Ups` section instead of creating a blocking gap/plan. (#1921) diff --git a/.changeset/1958-debugger-fix-acceptance-guardrail.md b/.changeset/1958-debugger-fix-acceptance-guardrail.md deleted file mode 100644 index e1e35299c..000000000 --- a/.changeset/1958-debugger-fix-acceptance-guardrail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2396 ---- -**`gsd-debugger` now guards fix acceptance with a multi-signal anti-overfitting gate** — a fix that greens the target test can no longer be silently accepted. The debugger now runs a five-signal guardrail before accepting a fix (target test, mutation check via Stryker, no-op/behavior-deleting diff detector, adjacent/held-out tests, and revert-and-reconfirm), degrades gracefully when Stryker or a test suite is absent (each skip is logged, never a silent pass), records every signal's result under `Resolution.verification` in the debug file, and returns a `FIX REJECTED BY GUARDRAIL` outcome that `gsd-debug-session-manager` surfaces for revise / accept-as-documented-debt / abandon. Full rules live in `gsd-core/references/debugger-fix-acceptance.md`. (#1958) diff --git a/.changeset/1959-sbfl-fault-localization.md b/.changeset/1959-sbfl-fault-localization.md deleted file mode 100644 index e01ce733c..000000000 --- a/.changeset/1959-sbfl-fault-localization.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2403 ---- -**`gsd-debugger` now ranks suspect code by Ochiai suspiciousness before forming hypotheses** — when a runnable test suite with per-test coverage exists (≥1 failing and ≥1 passing test), the debugger computes a spectrum-based fault-localization (Ochiai) ranking over the coverage and seeds the top-N suspicious locations into the Evidence section as first-class hypothesis candidates, narrowing the search space deterministically before any LLM reasoning. Tarantula is documented as a fallback formula. The step degrades cleanly (logged, never a silent pass) when there is no test suite, no failing tests, or no per-test coverage, and it is explicitly not trusted on flaky/Heisenbug spectra (pairs with the Phase 2B bug-taxonomy routing). Full rules live in `gsd-core/references/debugger-sbfl.md`. (#1959) diff --git a/.changeset/1960-rca-branching.md b/.changeset/1960-rca-branching.md deleted file mode 100644 index 0409ece55..000000000 --- a/.changeset/1960-rca-branching.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2405 ---- -**`gsd-debugger` now branches root-cause analysis instead of chaining, guarding against 5-Whys single-cause bias** — before committing `root_cause`, the debugger enumerates candidate causes across ≥2 Ishikawa categories (code / config / environment / data) rather than a single linear "why" chain, and explicitly answers an AND-gate question ("could this failure require more than one contributing condition simultaneously?"). When the AND-gate fires, every contributing cause is recorded — so a multi-cause fix no longer recurs via the unaddressed second cause. `Resolution.root_cause` may now hold one OR a small set of contributing causes (additive; a single-cause session still records exactly one root_cause while the reasoning_checkpoint gains two RCA fields populated in every session). The Structured Reasoning Checkpoint gains `candidate_causes` + `and_gate` fields, and `debugger-philosophy.md` adds the single-cause-bias trap to its cognitive-bias table. Full rules live in `gsd-core/references/debugger-rca-branching.md`. (#1960) diff --git a/.changeset/1961-bug-taxonomy-routing.md b/.changeset/1961-bug-taxonomy-routing.md deleted file mode 100644 index d539d5dc1..000000000 --- a/.changeset/1961-bug-taxonomy-routing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2407 ---- -**`gsd-debugger` now classifies each failure by bug class and routes the investigation technique accordingly, replacing the flat 11-technique menu with selection-by-class** — at a new Phase 1.75 the debugger assigns a `bug_class` (Bohrbug / Heisenbug-Mandelbug / Concurrency) and consults an explicit, inspectable routing table: Bohrbugs route to deterministic reproduction + SBFL (Phase 1.25) + git bisect; Heisenbugs/Mandelbugs route to record-replay (`rr`) + stability-stress + statistical sampling and **explicitly skip SBFL** (a flaky spectrum poisons the ranking); Concurrency bugs surface the atomicity/order/deadlock checklist before general techniques. The 11 techniques remain as routed targets, not an undifferentiated list (supersede, not append). `bug_class` + chosen strategy are written to the debug file; the common-bug-patterns catalog is cross-referenced to the taxonomy. Full rules live in `gsd-core/references/debugger-bug-taxonomy.md`. (#1961) diff --git a/.changeset/1962-repro-hardening.md b/.changeset/1962-repro-hardening.md deleted file mode 100644 index fad2798bf..000000000 --- a/.changeset/1962-repro-hardening.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2409 ---- -**`gsd-debugger` now hardens regression tests via PBT shrinking, explicit oracle classification, and boundary neighbors** — extending Minimal Reproduction and Test-First Debugging. When a bug triggers on a class of inputs, the debugger wraps the failing input in a property (fast-check for JS/TS, Hypothesis for Python) and lets the shrinker auto-minimize the counterexample, storing the **minimized** input as the regression seed; before writing the assertion it classifies the oracle as `specified` / `derived` (contract/model) / `metamorphic` / `implicit` (crash — weakest, never the silent default) and records it under `Resolution.oracle_type`; and it generates **boundary neighbors** (off-by-one, min/max, empty/singleton) around the fixed defect's equivalence class. Together they turn the regression test into a root-cause check — which is what the Phase 1A mutation guardrail needs to bite. Degrades gracefully to manual minimization when no PBT framework is present. Full rules live in `gsd-core/references/debugger-repro-hardening.md`. (#1962) diff --git a/.changeset/1963-prevention-postmortem.md b/.changeset/1963-prevention-postmortem.md deleted file mode 100644 index de018f481..000000000 --- a/.changeset/1963-prevention-postmortem.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2410 ---- -**`gsd-debugger` now emits a blameless-postmortem Prevention block at resolution, closing the loop on bug-class prevention** — at `archive_session` the debugger produces three blame-free components: a **branching 5-Whys** causal chain (branching per the Phase 2A RCA discipline, not a single linear chain; "agent error" prompts "why was that error possible?", never blame), a **"why wasn't this caught?"** answer naming the existing gate (test/typecheck/lint/review/verify) that missed it, and a **concrete recurrence guard** (a regression test / assertion / lint rule / knowledge-base pattern). The knowledge-base entry gains two structured fields — `why_not_caught` and `recurrence_guard` — so a future Phase-0 recall surfaces not just the prior fix but the prior *prevention* (additive; old entries without the fields still load). The session-manager's compact summary surfaces a one-line prevention summary. Full rules live in `gsd-core/references/debugger-prevention.md`; kept minimal — a block, not an incident-management subsystem. (#1963) diff --git a/.changeset/1964-semantic-kb-recall.md b/.changeset/1964-semantic-kb-recall.md deleted file mode 100644 index 5a4b542ec..000000000 --- a/.changeset/1964-semantic-kb-recall.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2416 ---- -**`gsd-debugger` now recalls prior resolved sessions semantically via MemPalace instead of keyword overlap** — at Phase 0 the debugger queries MemPalace with the current symptoms and surfaces the top-k meaning-similar prior resolutions as candidate hypotheses, catching the same-root-cause / different-wording cases keyword overlap missed (a prior "requests hang under load" now surfaces for "API times out when many users connect"). Resolved sessions are indexed into MemPalace at archive (symptoms + root cause(s) + fix + recurrence guard). `knowledge-base.md` remains the durable plain-text source of truth; when MemPalace is absent the debugger falls back to keyword-overlap matching against it (logged, never a silent skip). No new embedding/vector infrastructure — MemPalace is reused. Full rules live in `gsd-core/references/debugger-semantic-recall.md`. (#1964) diff --git a/.changeset/1988-roadmap-stray-summary-count.md b/.changeset/1988-roadmap-stray-summary-count.md deleted file mode 100644 index 4662bee37..000000000 --- a/.changeset/1988-roadmap-stray-summary-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2016 ---- -**`roadmap update-plan-progress` no longer counts stray non-plan `*-SUMMARY.md` files against phase completion** — remediation/gap-closure summaries (e.g. `30-FIX-CR02-SUMMARY.md`, `30-GAPCLOSURE-SUMMARY.md`) inflated `summary_count`, and once `summary_count >= plan_count` the phase silently flipped to `Complete` (checkbox checked, date stamped) even though several plans had no summary. A new `countMatchedSummaries` helper (core-utils) pairs summaries to plans via the `PLAN→SUMMARY` marker swap + the `-SUMMARY.md` form (layout-agnostic across root, bare, and nested layouts), so only a summary that corresponds to a real plan counts. Wired into `scanPhasePlans` (fixing roadmap listing, state sync, verification, workstream inventory at once) and `cmdRoadmapUpdatePlanProgress`. (#1988) diff --git a/.changeset/1993-milestone-ws-requirements-header.md b/.changeset/1993-milestone-ws-requirements-header.md deleted file mode 100644 index aa53bf197..000000000 --- a/.changeset/1993-milestone-ws-requirements-header.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2015 ---- -**`milestone complete --ws` requirements archive header now points at the workstream REQUIREMENTS.md** — the archive header string hardcoded the root path (`` `…see .planning/REQUIREMENTS.md` ``), so a workstream archive directed readers at the wrong file even though #1917 had already fixed the archive *locations* to land inside the workstream. The display path is now derived from the same workstream-aware `reqPath` the writer uses (`path.relative(cwd, reqPath)`), so root behavior is byte-identical and the workstream case correctly reads `.planning/workstreams//REQUIREMENTS.md`. (#1993) diff --git a/.changeset/2002-cli-self-healing-runtime-build.md b/.changeset/2002-cli-self-healing-runtime-build.md deleted file mode 100644 index 3e2f35507..000000000 --- a/.changeset/2002-cli-self-healing-runtime-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Changed -pr: 2036 ---- - -**The GSD CLI now self-heals a missing runtime build.** The compiled `gsd-core/bin/lib/*.cjs` modules are gitignored build artifacts (ADR-457) that ship prebuilt in the npm tarball but are absent on a Claude Code plugin-marketplace / git-clone install, which never runs `npm run build:lib`. Previously every command died at load with `Cannot find module './lib/cli-exit.cjs'`. The `gsd-tools` entrypoint now detects the missing output and compiles it once, on demand (lock-guarded so parallel invocations don't race), then proceeds — a single no-op check on the already-built npm path. When TypeScript is genuinely unavailable it prints an actionable `npm install && npm run build:lib` message instead of crashing. diff --git a/.changeset/2008-command-exit-zero-gate.md b/.changeset/2008-command-exit-zero-gate.md deleted file mode 100644 index 49151b5c2..000000000 --- a/.changeset/2008-command-exit-zero-gate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2011 ---- -**Third-party capability gates now actually fire via a generic `command-exit-zero` predicate.** — a capability's declared `check.predicate` gate was rendered for display but never evaluated (only built-in `check.query` gates were enforced, and the `security` capability's gate worked solely via a hard-coded `ship.md` branch). A new generic evaluator (`gsd_run check predicate`) now evaluates `check.predicate` blocks by `kind`; the first built-in kind `command-exit-zero` runs a bounded `sh -c` command at the project root and blocks the loop on non-zero exit (timeout → block, fail-closed). The `execute:wave:post`, `execute:post`, and `plan:post` gate-dispatch sites route `predicate` gates to the new evaluator automatically. (#2008) diff --git a/.changeset/2009-load-failed-capability-fail-open.md b/.changeset/2009-load-failed-capability-fail-open.md deleted file mode 100644 index 22ce740cf..000000000 --- a/.changeset/2009-load-failed-capability-fail-open.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2075 ---- -**Load-failed capability gates now fail open with a loud warning instead of blocking the whole project** — when an installed overlay (third-party) capability failed to load (e.g. an incompatible `engines.gsd` range) but had declared a `gate`-kind loop hook, the loop resolver injected a blocking synthetic gate (`blocking:true`, `onError:halt`) at every point where that capability declared a gate. A single incompatible capability therefore halted every `ship:pre` and `verify:post` in the project — unrelated to what the gate would have checked, and with no remediation surfaced. The resolver now injects no gate and instead emits a loud warning — to stderr and in the `loop render-hooks` envelope's `warnings` array — naming the load-failure reason and the exact `gsd capability remove ` remediation, and the loop proceeds (fail open). The capability id embedded in that remediation is validated against the canonical id shape first, so a malformed overlay directory name cannot inject shell metacharacters into the surfaced command. The loader still records `_overlay.blockedGates`; only the consequence changes from block to warn. `step`/`contribution` overlays were already skip-open. (#2009) diff --git a/.changeset/2012-phase-complete-progress-row.md b/.changeset/2012-phase-complete-progress-row.md deleted file mode 100644 index 3bc84044c..000000000 --- a/.changeset/2012-phase-complete-progress-row.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2032 ---- -**`phase.complete` now updates the `## Progress` rollup row even when an earlier phase-numbered table precedes it** — the Progress-row writer used a non-global regex that matched *any* table row starting with the phase number, so it bound to the first such row (e.g. a `| Phase | Requirements | Count |` coverage table), no-op'd on the wrong 3-column row, and never reached the real Progress row. The regex is now scoped to the `## Progress` section so it binds to the correct table. The command still returned `roadmap_updated: true` (that field is `fs.existsSync(ROADMAP.md)`), masking the silent failure. (#2012) diff --git a/.changeset/2017-context7-plugin-grant-prefix.md b/.changeset/2017-context7-plugin-grant-prefix.md deleted file mode 100644 index 91eb0250b..000000000 --- a/.changeset/2017-context7-plugin-grant-prefix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2029 ---- -**context7 now works for plugin-marketplace installs (8 agents regained doc lookup)** — the agents granted only `mcp__context7__*`, which matches a standalone context7 MCP server but not the official Claude Code plugin-marketplace install (`context7@claude-plugins-official`), whose tools are named `mcp__plugin_context7_context7__*`. The grant never matched, so advisor/ai/domain/phase/project/ui-researcher + planner + executor silently lost documentation lookup and fell back to WebSearch. All 8 agents now grant both forms, the researcher profile table is updated, and a parity guard asserts no agent grants the standalone form without the plugin form. (#2017) diff --git a/.changeset/2018-applysurface-empty-manifest-agents.md b/.changeset/2018-applysurface-empty-manifest-agents.md deleted file mode 100644 index 68ddf4024..000000000 --- a/.changeset/2018-applysurface-empty-manifest-agents.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2031 ---- -**`applySurface` no longer deletes every `gsd-*` agent when the skills manifest resolves empty** — the agent-prune loop in `_syncGsdDir` deleted any `gsd-*.md` not in the staged set, and when the manifest was empty/unresolvable (null manifest, no array entries, no `files` key, or an unresolvable install source root), the staged set was empty → every agent was pruned. Skills were guarded by `pruneSkillDirs`'s manifest-membership check (conservative preservation on empty manifest); agents had no equivalent. The agent-prune loop is now skipped when the manifest is empty/absent, so agents are preserved while copy (adding genuinely new agents) still runs. (#2018) diff --git a/.changeset/2019-planning-config-learnings-path.md b/.changeset/2019-planning-config-learnings-path.md deleted file mode 100644 index 110e8ef95..000000000 --- a/.changeset/2019-planning-config-learnings-path.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2026 ---- -**`planning-config.md` global-learnings path corrected to `~/.gsd/knowledge/`** — the `features.global_learnings` row directed users to `~/.gsd/learnings/`, but the implementation (`src/learnings.cts`, `execute-phase.md`) stores and reads global learnings from `~/.gsd/knowledge/`. Anyone following the docs to inspect, back up, or seed their global learnings looked in a directory the code never touches. (#2019) diff --git a/.changeset/2020-executor-dead-sdk-ref.md b/.changeset/2020-executor-dead-sdk-ref.md deleted file mode 100644 index 2491f753e..000000000 --- a/.changeset/2020-executor-dead-sdk-ref.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2027 ---- -**Removed dead SDK file references from runtime-loaded markdown that triggered an infinite `find.exe` storm on Windows** — `agents/gsd-executor.md` pointed at `sdk/src/query/QUERY-HANDLERS.md` and `gsd-core/workflows/reapply-patches.md` at `sdk/dist/cli.js`, both retired with the SDK package (ADR-0174). AI runtimes that resolve doc references by filesystem search ran `find / -iname …`; on Git Bash for Windows `/` maps to the drive root, so `find.exe` traversed the whole disk (14h+, orphaned processes, 4M+ open handles each, unkillable). The references now resolve to live paths, and a new regression guard asserts no `sdk/src|sdk/dist|sdk/handlers` file references remain in agents/workflows/references markdown. (#2020) diff --git a/.changeset/2022-roadmap-verify-gate.md b/.changeset/2022-roadmap-verify-gate.md deleted file mode 100644 index bd31bfd92..000000000 --- a/.changeset/2022-roadmap-verify-gate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2030 ---- -**`roadmap update-plan-progress` no longer checks the phase checkbox without verification** — the command stamped the phase-level ROADMAP checkbox and completion date the moment the last plan summary landed (called routinely after every wave and every plan), with **no verification gate** — unlike `phase.complete` which correctly requires `readVerificationStatus(...).status === 'passed'`. Now `isComplete` requires both all plan summaries AND a passed verification, matching the `cmdPhaseComplete` contract, so the checkbox only fires after `gsd-verifier` has confirmed the phase. (#2022) diff --git a/.changeset/2028-phase-complete-milestone-end-workstream-guard.md b/.changeset/2028-phase-complete-milestone-end-workstream-guard.md deleted file mode 100644 index 3f1f184e2..000000000 --- a/.changeset/2028-phase-complete-milestone-end-workstream-guard.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2066 ---- -**`phase complete` no longer marks a milestone done out of order, nor silently writes root state in workstream mode.** Completing the numerically-highest phase while an earlier phase was still outstanding wrongly flipped STATE.md to `Status: Milestone complete` (the milestone-end check only looked for higher-numbered phases, so an out-of-order completion — e.g. Phase 10 before Phase 9 — read as the end). It now reports milestone-end only when every lower-numbered phase in the milestone is checked complete. Separately, in workstream mode with no active workstream, `phase complete` previously fell back to root `.planning` and wrote STATE.md/ROADMAP.md (and the mislabel) into the shared root other workstreams read; it now fails safe — asking for `--ws ` or an active workstream — mirroring the existing `init progress` guard. (#2066) diff --git a/.changeset/2043-phase-token-single-digit-slug.md b/.changeset/2043-phase-token-single-digit-slug.md deleted file mode 100644 index ce7b100ac..000000000 --- a/.changeset/2043-phase-token-single-digit-slug.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2059 ---- -**Phase directories whose slug begins with a single digit now resolve correctly.** A phase like `46-6-rs-pipeline-orchestrator` (roadmap name "6 Rs Pipeline Orchestrator") had its phase token over-collected as `46-6` instead of `46`, so `gsd-tools` phase-by-number lookups resolved `phase_dir=null` / `has_context=false` (breaking `init.plan-phase`, `init.phase-op`, and downstream execute/verify/ship). Numeric phase-token components must now be zero-padded (≥2 digits), so a single-digit slug word is no longer absorbed into the token. Fixed consistently across every same-class implementation — `extractPhaseToken`, `PHASE_TOKEN_FROM_DIR_RE` and `canonicalPlanStem` (health checks / plan pairing), `isDirInMilestone`'s numeric matcher (milestone filtering), and `extractCanonicalPlanId` — so the health-check and milestone-filter subsystems are fixed alongside phase resolution. diff --git a/.changeset/2046-config-set-null-unset.md b/.changeset/2046-config-set-null-unset.md deleted file mode 100644 index 1272e73da..000000000 --- a/.changeset/2046-config-set-null-unset.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2058 ---- -**`gsd-tools config-set null` now clears (removes) the key instead of persisting the literal string `"null"`.** The documented "Clear" action previously fell through the value parser and stored `"null"` — a truthy value — so "cleared" keys stayed set and `config-get` returned `"null"`; for secret keys (`brave_search`/`firecrawl`/`exa_search`) a masked success line hid a truthy value on disk that integrations could pass along as a real credential. `config-set null` now deletes the key (short-circuiting the typed per-key validators so clearing an enum/boolean/number key removes it rather than being rejected), making the "Clear" flows in `settings-integrations.md` / `settings-advanced.md` actually clear. diff --git a/.changeset/2056-plan-phase-foreign-prefix.md b/.changeset/2056-plan-phase-foreign-prefix.md deleted file mode 100644 index 38f905fec..000000000 --- a/.changeset/2056-plan-phase-foreign-prefix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2105 ---- -**`init plan-phase` no longer collapses foreign-prefixed task/workstream IDs into numeric phases** — a query like `MEM-01` (where `MEM` is not the configured `project_code`) used to have its prefix stripped and resolve to the unrelated numeric Phase 01; it now reports `phase_found: false` unless a phase directory or roadmap entry literally carries that prefix. The configured `project_code`'s own prefixed phases (e.g. `LKML-01` under `project_code: LKML`) continue to resolve as before. (#2056) diff --git a/.changeset/2067-phase-complete-checkbox-regex.md b/.changeset/2067-phase-complete-checkbox-regex.md deleted file mode 100644 index 892a3763a..000000000 --- a/.changeset/2067-phase-complete-checkbox-regex.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2079 ---- -**`phase complete` no longer ticks the wrong phase's ROADMAP checkbox** — completing a phase whose number also appears in a later phase's description (e.g. an idempotent re-run of an already-complete phase) used to mark the *wrong* phase done, because the checkbox-matching regex greedily spanned from `]` to any later "Phase N" mention instead of only the immediately-following phase title. (#2067) diff --git a/.changeset/2071-effort-sync-installed-runtime.md b/.changeset/2071-effort-sync-installed-runtime.md deleted file mode 100644 index 2c9a0b663..000000000 --- a/.changeset/2071-effort-sync-installed-runtime.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2076 ---- -**`gsd-tools effort sync` no longer crashes in an installed runtime.** In any global install (e.g. `~/.claude/gsd-core/`), `effort sync` threw `Cannot find module '../../../bin/install.js'` — the command reached into the package-root `bin/install.js` for its install-time effort resolvers, but the installer only copies the `gsd-core/` subtree into a runtime home, so that file is never present there. As a result, `effort` config changes (`routing_tier_defaults` / `agent_overrides`) silently never reached installed agents without a full reinstall. The two resolvers (`readGsdEffectiveEffortConfig` + `resolveInstallTimeEffort`, with their helpers) are now extracted into a shipped `gsd-core/bin/lib/install-effort-resolver.cjs` that both `effort sync` and the installer import — a single source of truth that is always present in the installed tree. (#2076) diff --git a/.changeset/2072-thread-model-into-routed-agent-spawns.md b/.changeset/2072-thread-model-into-routed-agent-spawns.md deleted file mode 100644 index a74b21ff9..000000000 --- a/.changeset/2072-thread-model-into-routed-agent-spawns.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2074 ---- -**`model_overrides` and per-phase-type models now actually apply to the assumptions-analyzer, code-reviewer, and code-fixer agents on Claude Code.** Previously `model_overrides["gsd-code-reviewer"]` / `["gsd-assumptions-analyzer"]` / `["gsd-code-fixer"]` (and `models.verification` / `models.discuss` / `models.execution`) were accepted and resolved but silently dropped — the workflows spawned these agents with no model, so they inherited the session model and the configured routing never took effect (no warning). Every spawn now threads its resolved model: `discuss-phase-assumptions`, `code-review`, and `code-review-fix` (both the re-review and the two fixer spawns) resolve it inline, and `quick`'s review step uses the code-reviewer's own resolved model instead of the executor's. The stale "`discuss` — reserved, no subagent" model-profile docs are corrected to list `gsd-assumptions-analyzer`, and the `verification` row now includes `gsd-code-reviewer`. (#2074) diff --git a/.changeset/2073-antigravity-reviewer-block.md b/.changeset/2073-antigravity-reviewer-block.md deleted file mode 100644 index 009c6cd5e..000000000 --- a/.changeset/2073-antigravity-reviewer-block.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2109 ---- -**`/gsd-review`'s Antigravity CLI reviewer no longer fails silently on large prompts, unavailable pinned models, or pre-session stalls** — the `agy` invocation now uses a file-reference prompt to avoid exec arg-list overflow, is wrapped in an external wall-clock `timeout` paired with `--print-timeout` because `--print-timeout` cannot fire before `agy` creates a session, passes `--model` from `review.models.agy` when set as an escape hatch for a 404'd pinned model, and its empty-output stub now surfaces an `agy` cli.log diagnostic instead of a bare generic message. Supersedes the #687 "no external killer / inline `$(cat)`" contract, which predated `agy` gaining `--model` and predated its own guidance to pair `--print-timeout` with a terminal timeout. (#2073) diff --git a/.changeset/2086-eos-claude-imperative-adapter.md b/.changeset/2086-eos-claude-imperative-adapter.md deleted file mode 100644 index 73ab37742..000000000 --- a/.changeset/2086-eos-claude-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2106 ---- -**Internal: Claude Code's installer is now driven through the public Host-Integration Interface (ADR-1239 / EoS).** `bin/install.js` routes `claude` install/uninstall through the imperative adapter (`createImperativeAdapter`) instead of calling the engine directly, and its 13 hardcoded `runtime === 'claude'` / `runtime !== 'claude'` branches are folded into descriptor-driven `runtime.hostBehaviors` on `capabilities/claude/capability.json` (permission schema, `settings.local.json` scope routing, `.gsd-source` marker, effort frontmatter, canonical-workflow authorship, and more). Install/uninstall output is **byte-identical** for both the global skills layout and the local legacy layout (golden-parity asserted for both scopes); no other runtime changes. Removes the "add-a-host tax" of scattered string-equality checks for the tier-1 reference host. No user-facing change. (#2086) diff --git a/.changeset/2087-eos-opencode-imperative-adapter.md b/.changeset/2087-eos-opencode-imperative-adapter.md deleted file mode 100644 index 82b18defb..000000000 --- a/.changeset/2087-eos-opencode-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2108 ---- -**OpenCode is now driven through the public Host-Integration Interface, with two capability upgrades (ADR-1239 / EoS).** OpenCode and its Kilo sibling previously installed via a bespoke `runtime === 'opencode'`/`isOpencode` branch in `bin/install.js`; its commands+skills+plugin install now runs through the imperative adapter → the engine's combined-family install path (`installRuntimeArtifacts`), and every hardcoded `runtime === 'opencode'` branch is folded into descriptor-driven `runtime.hostBehaviors`. Install/uninstall output is **byte-identical** (golden parity asserted for all 16 runtimes). Two Context7-verified upgrades land: (1) **background dispatch** — OpenCode shipped experimental background subagents in v1.15 and made them default-on in v1.17, so `dispatch.background`/`backgroundDispatch` flip to `true`; GSD no longer force-flattens OpenCode-hosted wave dispatch (`shouldFlattenDispatch` now returns `false`), letting agents run concurrently where the host supports it. (2) **expanded event surface** — the OpenCode plugin now subscribes to `permission.asked`, `permission.replied`, and `session.error` (added to `EXTENSION_EVENT_SURFACES.opencode`), wiring the declared surface for future permission/error-aware bindings. (#2087) diff --git a/.changeset/2088-eos-codex-declarative-adapter.md b/.changeset/2088-eos-codex-declarative-adapter.md deleted file mode 100644 index e929c3ddc..000000000 --- a/.changeset/2088-eos-codex-declarative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2110 ---- -**Codex is now driven through the public Host-Integration Interface, with three capability upgrades (ADR-1239 / EoS).** Codex previously installed via hardcoded `runtime === 'codex'`/`isCodex` projection in `bin/install.js`; its `config.toml` / agent-`.toml` / `hooks.json` install now runs through the declarative embedding adapter and descriptor-driven `runtime.hostBehaviors`, with **zero** positive `isCodex` gates and **zero** `runtime === 'codex'` branches remaining (source-guarded). Install/uninstall output stays byte-parity-gated (`tests/fixtures/golden-install-parity/codex.json`). Three Context7-verified upgrades land, each with a test driving the user-reachable surface: (1) **skill root** — GSD skills now install to Codex's canonical `$HOME/.agents/skills` (via a skills-kind `home` override) instead of the deprecated `$CODEX_HOME/skills` fallback, and pre-move installs are migrated (stale `~/.codex/skills/gsd-*` cleaned on both install and uninstall, user-owned content preserved); (2) **hook events** — GSD registers the six documented Codex lifecycle events it previously skipped (`PreToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SubagentStop`, `UserPromptSubmit`, in addition to the existing `SessionStart`/`SubagentStart`/`Stop`/`PostToolUse`) in `hooks.json`, so `gsd-context-monitor` fires at the same points as in Claude Code, and the descriptor `extendedHookEvents` is reconciled from `[]` to the schema-valid wired subset; (3) **dispatch tuning** — `[agents] max_depth = 1` is written explicitly into the managed `config.toml` block to pin the negotiated `dispatch.maxDepth: 1` axis (`degradationFor` flattens GSD-hosted waves to single-level), and `validateCodexConfigSchema` now permits a known-scalar-only `[agents]` AgentsToml table (coexisting with the flattened `[agents.gsd-*]` role sub-tables) while still rejecting the `[[agents]]` and unknown-key break-forms from #2760. (#2088) diff --git a/.changeset/2089-eos-cursor-imperative-adapter.md b/.changeset/2089-eos-cursor-imperative-adapter.md deleted file mode 100644 index 870d57748..000000000 --- a/.changeset/2089-eos-cursor-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2120 ---- -**Cursor is now driven through the public Host-Integration Interface, with two capability upgrades (ADR-1239 / EoS).** Cursor previously installed via hardcoded `runtime === 'cursor'`/`isCursor` branches in `bin/install.js`; its install/uninstall now runs through the imperative adapter, and every hardcoded cursor branch is folded into descriptor-driven `runtime.hostBehaviors` (reapplyCommand, frontmatterDialect, hooksJsonSurface, skipSharedHooksInstall, reportCommandsDir, managedHookEvents). Install/uninstall output is **byte-identical** (golden parity asserted for all 16 runtimes). Two Context7-verified upgrades land: (1) **expanded hook-bus coverage** — GSD registers all 6 managed lifecycle events in Cursor's `hooks.json` (`preToolUse`, `stop`, `subagentStart`, `subagentStop` in addition to the original `sessionStart`/`postToolUse`), driven by a new descriptor-driven adapter module (`src/host-integration-adapters/imperative-hook-bus.cts`) that reads `hostBehaviors.managedHookEvents` instead of a hardcoded event pair; cite https://cursor.com/docs/hooks. (2) **named/background nested subagent dispatch** — Cursor's `dispatch.background`/`backgroundDispatch`/`nested` are all `true` with `maxDepth: 2`, so `shouldFlattenDispatch(cursor)` returns `false` and GSD's wave-based execution drives Cursor's native background + depth-2 nested subagent invocation instead of flattening to inline sequential calls; cite https://cursor.com/docs/subagents + https://cursor.com/docs/sdk/typescript. (#2089) diff --git a/.changeset/2090-eos-cline-imperative-adapter.md b/.changeset/2090-eos-cline-imperative-adapter.md deleted file mode 100644 index b6109ac51..000000000 --- a/.changeset/2090-eos-cline-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2132 ---- -**Cline is now driven through the public Host-Integration Interface, with two capability upgrades (ADR-1239 / EoS).** Cline previously installed via hardcoded `runtime === 'cline'`/`isCline` branches in `bin/install.js`; its install/uninstall now runs through the imperative adapter, and every hardcoded cline branch is folded into descriptor-driven `runtime.hostBehaviors` (reapplyCommand, frontmatterDialect, skipSharedHooksInstall, localTargetIsProjectRoot, clineRulesSurface, localCommandsViaRules). Install/uninstall output is **byte-identical** (golden parity asserted for cline + claude/cursor/codex/opencode). Two Context7-verified upgrades land: (1) **`AgentPlugin.hooks.beforeTool` planning guard** — the `.clinerules/hooks/PreToolUse` file-convention hook (#787) is re-implemented as a real Cline SDK `AgentPlugin` that cancels write-class calls targeting `.planning/` (same fail-open semantics), driven by a new descriptor-driven adapter module (`src/host-integration-adapters/cline-sdk-binding.cts`); cite https://github.com/cline/cline/blob/main/docs/sdk/plugins.mdx. (2) **`createAgentModel` model overrides** — `DefaultGateway.createAgentModel({providerId, modelId})` is wired so GSD's per-subagent `model_overrides`/`model_profile_overrides` resolution applies to Cline subagents (`modelMode: active`); cite https://github.com/cline/cline/blob/main/docs/sdk/reference/gateway.mdx. Cline's dispatch deliberately stays **degraded/flat** (`maxDepth: 1`, read-only, no nested spawning) per the documented host restriction — never silently upgraded to full nested/background. (#2090) diff --git a/.changeset/2091-eos-hermes-imperative-adapter.md b/.changeset/2091-eos-hermes-imperative-adapter.md deleted file mode 100644 index 00aadd9ed..000000000 --- a/.changeset/2091-eos-hermes-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2134 ---- -**Hermes Agent is now driven through the public Host-Integration Interface, with three capability upgrades (ADR-1239 / EoS).** Hermes previously installed via hardcoded `runtime === 'hermes'`/`isHermes` branches in `bin/install.js`; its install/uninstall now runs through the imperative adapter, and every hardcoded hermes branch is folded into descriptor-driven `runtime.hostBehaviors`. Three upgrades land: (1) **real plugin hook vocabulary** — GSD registers a new `extensionEvents: "hermes"` dialect carrying the 13 documented Hermes plugin events (`pre_tool_call`, `post_tool_call`, `pre_llm_call`, `post_llm_call`, `on_session_start`, `on_session_end`, `on_session_finalize`, `on_session_reset`, `subagent_start`, `subagent_stop`, `pre_gateway_dispatch`, `pre_approval_request`, `transform_tool_result`), replacing the borrowed `hookEvents: "claude"` 6-event surface that silently never fired; cite https://github.com/nousresearch/hermes-agent/blob/main/website/docs/user-guide/features/hooks.md. (2) **dispatch posture** — Hermes' `dispatch.nested: true` with `maxDepth: 1` is correctly negotiated (not silently flattened). (3) **branding/category metadata** — `DESCRIPTION.md` category descriptions, `version:` frontmatter, and branding rewrites are now descriptor-driven rather than hardcoded. Install/uninstall output is byte-identical (golden parity asserted for all runtimes). (#2091) diff --git a/.changeset/2092-eos-qwen-imperative-adapter.md b/.changeset/2092-eos-qwen-imperative-adapter.md deleted file mode 100644 index d85dcc8af..000000000 --- a/.changeset/2092-eos-qwen-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2153 ---- -**Qwen Code now projects GSD's specialist agents as native subagents** — installing GSD into Qwen Code writes `~/.qwen/agents/gsd-*.md` files you can invoke directly (planner, executor, code-reviewer, …) instead of reaching them only through skill prose, and a `SubagentStart` hook now fires alongside `SubagentStop`. Qwen's install is driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2092) diff --git a/.changeset/2093-eos-kilo-imperative-adapter.md b/.changeset/2093-eos-kilo-imperative-adapter.md deleted file mode 100644 index e02477881..000000000 --- a/.changeset/2093-eos-kilo-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2156 ---- -**Kilo Code now supports native hooks, active-model routing, and named subagent dispatch** — installing GSD into Kilo wires a lifecycle-hook plugin, keeps each agent's requested model instead of dropping it, projects GSD's specialist agents as invokable subagents, and documents the GSD MCP companion. Kilo's install is driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2093) diff --git a/.changeset/2094-eos-trae-imperative-adapter.md b/.changeset/2094-eos-trae-imperative-adapter.md deleted file mode 100644 index 8139f82bd..000000000 --- a/.changeset/2094-eos-trae-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2157 ---- -**GSD skills installed for Trae now carry SOLO stage metadata** — Trae's SOLO Agent can recognize GSD skills as workflow-stage skills for auto-invocation instead of requiring manual triggering. Several of Trae's install branches (shared-hooks gating, path rewrites) also move onto its capability descriptor. Note: the stage-metadata field is a best-effort/inferred shape — Trae publishes no formal schema. (#2094) diff --git a/.changeset/2095-eos-kimi-imperative-adapter.md b/.changeset/2095-eos-kimi-imperative-adapter.md deleted file mode 100644 index 123cde5a7..000000000 --- a/.changeset/2095-eos-kimi-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2159 ---- -**GSD's lifecycle hooks now run under Kimi CLI** — installing GSD into Kimi wires its session-state, phase-boundary, graphify, and guard hooks into Kimi's own native `config.toml` `[[hooks]]` bus (Beta on Kimi's side) instead of silently no-op'ing, and GSD's Kimi subagents can now run in the background. Kimi's install is driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2095) diff --git a/.changeset/2096-eos-antigravity-imperative-adapter.md b/.changeset/2096-eos-antigravity-imperative-adapter.md deleted file mode 100644 index 5e5828552..000000000 --- a/.changeset/2096-eos-antigravity-imperative-adapter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2165 ---- -**Installing GSD into Antigravity now writes the `permissions.allow` rules its CLI documents** — so GSD's own reads and hooks aren't stuck on interactive prompts — and registers GSD's companion MCP server via a standalone `mcp_config.json` (best-effort: Antigravity's raw config schema isn't published, so this uses the Gemini-CLI-successor format). Antigravity's install is now driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2096) diff --git a/.changeset/2097-eos-augment-imperative-adapter.md b/.changeset/2097-eos-augment-imperative-adapter.md deleted file mode 100644 index fe67b40f2..000000000 --- a/.changeset/2097-eos-augment-imperative-adapter.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Changed -pr: 2166 ---- - -**Augment Code now installs through its capability descriptor, with a native MCP companion** — installing GSD into Augment registers the GSD companion server in Augment's `settings.json` `mcpServers` and drives command/skill/agent conversion from Augment's negotiated descriptor instead of hardcoded runtime special-cases. (#2097) diff --git a/.changeset/2098-eos-codebuddy.md b/.changeset/2098-eos-codebuddy.md deleted file mode 100644 index 66cf3cb78..000000000 --- a/.changeset/2098-eos-codebuddy.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Changed -pr: 2169 ---- - -**CodeBuddy now wires GSD's full extended lifecycle hook set and is driven by its capability descriptor** — installing GSD into CodeBuddy now registers `SubagentStart`, `SubagentStop`, `Stop`, and `PreCompact` hooks in its `settings.json` (it previously had none of these), matching the coverage Qwen/Kimi already ship, and CodeBuddy's install is fully descriptor-driven instead of via residual hardcoded runtime branches. (#2098) diff --git a/.changeset/2099-eos-copilot.md b/.changeset/2099-eos-copilot.md deleted file mode 100644 index a08e5dcba..000000000 --- a/.changeset/2099-eos-copilot.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Changed -pr: 2172 ---- - -**GitHub Copilot now wires GSD's full lifecycle hook bus and is driven by its capability descriptor** — installing GSD into Copilot registers `preToolUse`, `postToolUse`, `userPromptSubmitted`, and `sessionEnd` handlers in its `hooks/gsd-session.json` (beyond today's `sessionStart`-only advisory), and Copilot's residual hardcoded runtime branches are folded onto descriptor-driven `hostBehaviors`. (#2099) diff --git a/.changeset/2100-eos-windsurf.md b/.changeset/2100-eos-windsurf.md deleted file mode 100644 index 8e78f64f9..000000000 --- a/.changeset/2100-eos-windsurf.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2190 ---- -**Windsurf now enforces GSD's write/command safety guards through Cascade's native hook bus** — installing GSD into Windsurf registers blocking `pre_write_code`/`pre_run_command` hooks in `.windsurf/hooks.json` (exit-code-2 blocking) and drives Windsurf's install from its capability descriptor instead of hardcoded runtime branches. (#2100) diff --git a/.changeset/2101-eos-zcode.md b/.changeset/2101-eos-zcode.md deleted file mode 100644 index e3770c283..000000000 --- a/.changeset/2101-eos-zcode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2195 ---- -**ZCode's install is now driven and regression-tested through its capability descriptor** — ZCode joins the dogfooded declarative-adapter reference hosts with a byte-identical install, and its shared-hooks exclusion is folded onto `hostBehaviors` instead of a hardcoded runtime branch. (Hook-automation and MCP upgrades remain blocked on ZCode publishing its on-disk config formats.) (#2101) diff --git a/.changeset/2102-eos-pi.md b/.changeset/2102-eos-pi.md deleted file mode 100644 index 4cbebe59e..000000000 --- a/.changeset/2102-eos-pi.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2205 ---- -**GSD is now installable on pi** — `npx @opengsd/gsd-core --pi` installs the GSD extension to `~/.pi/agent/extensions/gsd.cjs`, and `/gsd ` now dispatches real commands through the embedded engine (the reference binding previously could only run `query help`). Drives pi through the negotiated imperative Host-Integration adapter, with active-model steering and the full pi lifecycle-event surface. (#2102) diff --git a/.changeset/2104-foreign-prefix-sibling-commands.md b/.changeset/2104-foreign-prefix-sibling-commands.md deleted file mode 100644 index 9662fe629..000000000 --- a/.changeset/2104-foreign-prefix-sibling-commands.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2149 ---- -**`init execute-phase`, `init verify-work`, and `init phase-op` no longer collapse foreign-prefixed task IDs to numeric phases** — `MEM-01` under `project_code: LKML` was silently stripped to `01` and resolved to the unrelated numeric Phase 01, because the #2056 guard was applied only to `init plan-phase`. The guard is now extracted into shared helpers (`guardedFindPhase` / `guardedGetRoadmapPhase`) that delegate to the canonical `isForeignPrefixedPhaseQuery` from `phase-id.cts`, and all four init commands route through them. (#2104) diff --git a/.changeset/2107-orchestrator-honors-blocking-human-gate.md b/.changeset/2107-orchestrator-honors-blocking-human-gate.md deleted file mode 100644 index a4d745e9b..000000000 --- a/.changeset/2107-orchestrator-honors-blocking-human-gate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 2113 ---- -**`gate="blocking-human"` checkpoints are no longer auto-approved by the execute-phase orchestrator** — the package-legitimacy gate (#2827) spans two layers: `gsd-executor` refuses to auto-approve a `gate="blocking-human"` checkpoint and escalates it via `checkpoint_return_format` so a human can vet the package, and `execute-phase`'s `checkpoint_handling` step decides what happens next. That step dispatched purely on checkpoint *type* and never read `gate`, so under `--auto` / `--chain` it immediately auto-approved the very checkpoint the executor had just refused to auto-approve (`human-verify → {user_response} = "approved"`). The slopsquatting defence was therefore inert in exactly the unattended mode where nobody is watching: an `[ASSUMED]`/`[SUS]` package reached install with no human ever seeing the verification prompt. `checkpoint_handling` now carves out `gate="blocking-human"` (and the package-legitimacy `what-built` markers) ahead of every auto-mode branch, routing those checkpoints to the standard present-to-user flow regardless of type. `references/checkpoints.md` documents the `gate` attribute and its two values for the first time — previously `blocking-human` appeared nowhere outside `agents/gsd-executor.md`, so no planner had a documented way to author a checkpoint that auto-mode could not bypass. The existing regression test asserted the executor half only; it now asserts the orchestrator half too, which is why it stayed green while the gate was open. (#2107) diff --git a/.changeset/2112-commit-files-pathspec.md b/.changeset/2112-commit-files-pathspec.md deleted file mode 100644 index 1e8a1118d..000000000 --- a/.changeset/2112-commit-files-pathspec.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2148 ---- -**`commit --files` now commits only the declared paths** — `gsd-tools commit --files A B` previously ran a bare `git commit` that absorbed the entire staged index, silently sweeping in unrelated files the caller never named. The commit now appends a pathspec (`-- `) so only the staged subset of `--files` lands in the commit; the no-`--files` default path is unchanged. Missing tracked files are still skipped (not committed as deletions, #2014), and when all declared files are missing the function short-circuits to `nothing_to_commit` instead of absorbing the index. (#2112) diff --git a/.changeset/2116-surface-bare-require.md b/.changeset/2116-surface-bare-require.md deleted file mode 100644 index f48850120..000000000 --- a/.changeset/2116-surface-bare-require.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2213 ---- -**Fixed unresolvable bare `require('gsd-core/...')` in `gsd-surface` command doc** — the four `require()` examples now derive the engine path from `runtimeConfigDir` (resolvable at runtime), and the reinstall hint corrects `npm i -g gsd-core` to `npm i -g @opengsd/gsd-core`. (#2116) diff --git a/.changeset/2118-milestone-complete-dry-run.md b/.changeset/2118-milestone-complete-dry-run.md deleted file mode 100644 index d0f3d2659..000000000 --- a/.changeset/2118-milestone-complete-dry-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2155 ---- -**`milestone complete --dry-run` now prints a preview plan instead of silently mutating** — `gsd-tools milestone complete --dry-run` was neither parsed nor rejected, so a caller expecting a preview triggered the full destructive mutation (archive phases, move audit artifacts, rewrite STATE.md) with no way to back out. The `--dry-run` flag is now honored: it returns a JSON plan listing `would_archive` (roadmap, requirements, audit, phase dirs) and `would_update` (MILESTONES.md, STATE.md) targets with zero filesystem mutations. (#2118) diff --git a/.changeset/2119-secure-phase-single-writer.md b/.changeset/2119-secure-phase-single-writer.md deleted file mode 100644 index 172b29463..000000000 --- a/.changeset/2119-secure-phase-single-writer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2154 ---- -**`/gsd-secure-phase` now has a single SECURITY.md writer** — the `gsd-security-auditor` subagent previously held `Write`/`Edit` tools and was instructed to "write SECURITY.md" with no padded `-` prefix and no template frontmatter, while the orchestrator's Step 6 also wrote the phase-scoped `-SECURITY.md` from `templates/SECURITY.md`. The auditor is now return-only (drops `Write`/`Edit`, returns a structured verdict with `threats_open`); the orchestrator is the sole file writer. The workflow's Step 5 spawn constraints explicitly forbid the auditor from writing SECURITY.md. (#2119) diff --git a/.changeset/2122-codex-gpt56-model-defaults.md b/.changeset/2122-codex-gpt56-model-defaults.md deleted file mode 100644 index 4da36b5c0..000000000 --- a/.changeset/2122-codex-gpt56-model-defaults.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2146 ---- -**Codex/OpenAI default models advance to the GPT-5.6 family (Sol/Terra/Luna)** — the Codex runtime tier defaults and the `openai` provider preset now resolve to current-generation model IDs instead of the superseded GPT-5.4/5.5 line, so Codex users on default profiles get improved agentic coding (Sol) and lower costs (Terra/Luna) without changing any config. (#2122) diff --git a/.changeset/2198-security-dead-scan-exports.md b/.changeset/2198-security-dead-scan-exports.md deleted file mode 100644 index a28eb2c42..000000000 --- a/.changeset/2198-security-dead-scan-exports.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2211 ---- -**Dead security scan exports removed; injection-scan docs corrected to match reality** — `scanEntropyAnomalies` and `shannonEntropy` were dead code with zero production callers (live hooks inline their own patterns for independence). REQ-SCAN-INJ-02/-03 now accurately describe what runs live (injection patterns, invisible Unicode) vs CI-only (base64-decode, codebase scan). (#2198) diff --git a/.changeset/2351-portable-timeout.md b/.changeset/2351-portable-timeout.md deleted file mode 100644 index 5768aa17a..000000000 --- a/.changeset/2351-portable-timeout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2426 ---- -**Post-merge, regression, and other GSD test/build gates no longer fail with a spurious "command not found" on stock macOS.** These gates hardcoded GNU coreutils' `timeout`, which stock macOS ships neither as `timeout` nor `gtimeout`; a passing build or test run now completes under a portable, coreutils-independent `run-with-timeout` wrapper instead of exiting 127 and being misreported as a failure. (#2351) diff --git a/.changeset/2362-opencode-kilo-capability-skill-materialize.md b/.changeset/2362-opencode-kilo-capability-skill-materialize.md deleted file mode 100644 index 209e2f43e..000000000 --- a/.changeset/2362-opencode-kilo-capability-skill-materialize.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2434 ---- -**Installed third-party capability skills now materialize on OpenCode and Kilo** — `capability install` + `capability set --runtime opencode` (or `kilo`) could report a capability as `installed: true, surfaced: true, active: true` while its skill was never written to `skills/gsd-/SKILL.md`: the OpenCode/Kilo combined-family install path never called the seam #2322 fixed for other runtimes. Installed capability skills now materialize the same way there too, bound to their declaring capability, with first-party skills always winning a name collision. (#2362) diff --git a/.changeset/2388-shared-requirement-gate.md b/.changeset/2388-shared-requirement-gate.md deleted file mode 100644 index 9e19c4058..000000000 --- a/.changeset/2388-shared-requirement-gate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2424 ---- -**Shared requirement IDs across multiple plans no longer read `Complete` before every declaring plan (and phase verification) has finished** — `execute-plan.md` now gates completion on sibling plans' `SUMMARY.md` files via a new read-only `requirements ready-ids` check, and a `gaps_found` phase verification reverts any requirement ID this phase owns back out of `Complete` before the gap report renders. Single-plan requirement IDs are unaffected — no added latency. (#2388) diff --git a/.changeset/2390-phase-add-autodetect.md b/.changeset/2390-phase-add-autodetect.md deleted file mode 100644 index 6a7d520f4..000000000 --- a/.changeset/2390-phase-add-autodetect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2425 ---- -**`phase.add` no longer silently mistakes a goal-shaped description for a phase title** — a long or multi-sentence description used to land verbatim in the `### Phase N:` header with no signal anything was off; `phase.add` now returns a `warning` field when the description looks goal-shaped, and the phase-number auto-detect docs now correctly point callers at the orchestrating workflow instead of implying `gsd-tools.cjs` resolves it itself. (#2390) diff --git a/.changeset/2402-response-language-orchestrator-coverage.md b/.changeset/2402-response-language-orchestrator-coverage.md deleted file mode 100644 index 5395b989b..000000000 --- a/.changeset/2402-response-language-orchestrator-coverage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2457 ---- -**`response_language` now reaches orchestrator-owned prompts across most workflows and the UAT verification checkpoint frame** — previously only subagent prompts honored a configured `response_language`; the orchestrator's own questions (verify-work, new-project, new-milestone, quick, manager, and others) and the hardcoded English UAT checkpoint banner stayed in English regardless of configuration. Both now render in the configured language, with output byte-identical to before when unset. (#2402) diff --git a/.changeset/2406-codex-agent-role-double-registration.md b/.changeset/2406-codex-agent-role-double-registration.md deleted file mode 100644 index 90ffdc442..000000000 --- a/.changeset/2406-codex-agent-role-double-registration.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2432 ---- -**Codex installer no longer double-registers each agent role in `config.toml`, eliminating one duplicate-role startup warning per agent** — `generateCodexConfigBlock` stopped emitting `[agents.gsd-*]` tables whose `config_file` pointed back at the same standalone TOMLs Codex already auto-discovers under `$CODEX_HOME/agents/`; reinstalling over an existing config also drops any legacy managed role tables left by a prior install while preserving unrelated user config and the user's own AgentsToml scalars. (#2406) diff --git a/.changeset/2496-production-advisories.md b/.changeset/2496-production-advisories.md deleted file mode 100644 index 5bb10fb4f..000000000 --- a/.changeset/2496-production-advisories.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2497 ---- -**Production dependency tree carries no known advisories** — five advisories disclosed against the transitive tree under `@anthropic-ai/claude-agent-sdk` → `@modelcontextprotocol/sdk` were cleared: `fast-uri` (GHSA-4c8g-83qw-93j6, high) and `hono` (GHSA-xgm2-5f3f-mvvc, GHSA-hvrm-45r6-mjfj, GHSA-w62v-xxxg-mg59) re-resolved to patched releases inside their already-declared ranges with no `package.json` change, and `@hono/node-server` (GHSA-frvp-7c67-39w9) pinned to `>=2.0.5` via `overrides` because `@modelcontextprotocol/sdk@1.29.0` — already the latest published version — still declares the vulnerable `^1.19.9` range. `npm audit --omit=dev` reports zero advisories. (#2496) diff --git a/.changeset/agile-newts-roar.md b/.changeset/agile-newts-roar.md deleted file mode 100644 index a767ec9c2..000000000 --- a/.changeset/agile-newts-roar.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1813 ---- -**Internal: the installer's `program` (display-name) + `command` (slash-invocation) chains are now single-source lookups** — the 14-line `program` chain (an exact duplicate of `runtimeLabel`) → `getRuntimeLabel`, and the 14-line `command` chain (the per-runtime `/gsd-new-project` syntax: gemini `/gsd:`, codex `$`, cursor skill-mention, kimi `/skill:`, default `/gsd-new-project`) → new `getRuntimeNewProjectCommand(runtime)` helper (ADR-1239 Phase B / #1679 AC2 slice 4). `runtime ===` count in `bin/install.js`: 53 → 25 (cumulative this session: 129 → 25). Stdout strings preserved byte-for-byte; no install-output change (golden-parity 16/16). No user-facing change. - - diff --git a/.changeset/agile-pandas-dance.md b/.changeset/agile-pandas-dance.md deleted file mode 100644 index 5041d24ea..000000000 --- a/.changeset/agile-pandas-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2233 ---- -**Custom STATE.md frontmatter keys are no longer dropped on every mutating verb** — syncStateFrontmatter rebuilt the frontmatter from a fixed schema, silently dropping any custom key. It now carries forward existing keys the schema does not own. (#2202) diff --git a/.changeset/agile-rams-climb.md b/.changeset/agile-rams-climb.md deleted file mode 100644 index d91050d43..000000000 --- a/.changeset/agile-rams-climb.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2222 ---- -**Non-frontend phases with `UI hint: no` are no longer blocked by the UI-SPEC gate** — the UI safety gate's token list included the bare token `UI`, which matched GSD's own `**UI hint**: no` metadata line and false-detected a UI, blocking backend/infra phases at /gsd-plan-phase. An explicit `UI hint: yes|no` is now authoritative and the hint line is no longer token-sniffed. (#2150) diff --git a/.changeset/bold-deer-zip.md b/.changeset/bold-deer-zip.md deleted file mode 100644 index 065cc968b..000000000 --- a/.changeset/bold-deer-zip.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1992 ---- -**OpenCode reviewer no longer silently yields an empty review on large prompts** — `/gsd-review --opencode` now invokes `opencode run --format json` and reconstructs the review from the assistant text parts, so a large-prompt run where the default `build` agent ends its turn with zero output tokens no longer produces an empty stub. When the agent genuinely emits no text, the stub now reports the stop reason, output-token count, and captured stderr instead of a generic message. (#1936) diff --git a/.changeset/bold-finches-leap.md b/.changeset/bold-finches-leap.md deleted file mode 100644 index 131cf2e70..000000000 --- a/.changeset/bold-finches-leap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2354 ---- -**OpenCode's first-time install baseline now protects pre-existing files under the `commands/` directory, not just the legacy `command/` alias** — after #2329 moved OpenCode command materialization to `commands/`, the baseline scan that guards a machine's very first GSD-tracked install still only knew about the legacy `command/` directory, so a pre-existing, unrelated `commands/gsd-*.md` file was silently deleted by ordinary command materialization instead of blocking the install for an explicit keep/remove choice — the same protection `command/` already had. The scan now covers both directories. Kilo is unaffected and keeps using `command/`. diff --git a/.changeset/bold-goats-wave.md b/.changeset/bold-goats-wave.md deleted file mode 100644 index 42c21584f..000000000 --- a/.changeset/bold-goats-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2397 ---- -**api-coverage detector no longer false-positives non-API phases (and no longer fails open)** — the external-API-integration detector behind the blocking `verify:pre` seal gate required only same-line co-occurrence of an integration verb and an API noun, treated `/` as a word boundary (so first-party Next.js `src/app/api/…` route paths matched), and read any capitalized word before API/SDK/REST/GraphQL as a service name (so threat-model prose like "Resolver-only API" fired). It is now **fail-closed**: the compound rule requires the integration verb and API noun to share one clause (the clause boundary is the whole relationship test — no fragile word-gap cap that a genuine long integration clause would trip); fenced code, inline code spans, and path-shaped tokens are excluded before matching while external hosts like `api.stripe.com/v1` still count; and the ` API` surface rule rejects stopwords, locality/protocol descriptors ("Internal API", "REST API"), compound modifiers, and first-party-qualified services, so a real vendor name (`Stripe API`) fires from any clause position. A phase that integrates no external API can declare it first-class in `COVERAGE.md` — `No external API integration: ` — instead of fabricating a matrix row; when the detector still finds signals, the declaration overrides but the gate surfaces the overridden signals so the contradiction is visible. Because a false positive is cheaply dismissed by that declaration while a false negative silently slips a real API phase past the gate, the detector deliberately leans toward detecting. (#2365) diff --git a/.changeset/bold-orcas-wander.md b/.changeset/bold-orcas-wander.md deleted file mode 100644 index dbdce1386..000000000 --- a/.changeset/bold-orcas-wander.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1811 ---- -**Internal: the installer's per-function `is` flag-declaration blocks are now a single `runtimeFlags` lookup** — the four duplicated `const isX = runtime === 'x'` blocks in `bin/install.js` (uninstall / writeManager / install / a fourth helper — 48 branches) are collapsed into one `runtimeFlags(runtime)` helper in `runtime-name-policy.cts` (ADR-1239 Phase B / #1679 AC2 slice 3). The add-a-host tax for flags is removed (one `RUNTIME_FLAG_IDS` entry, not four declaration blocks). Install output is byte-identical for all 16 runtimes (golden-parity asserted); `runtime ===` count in `bin/install.js`: 101 → 53. No user-facing change. - - diff --git a/.changeset/bold-ravens-wake.md b/.changeset/bold-ravens-wake.md deleted file mode 100644 index 0d1b55798..000000000 --- a/.changeset/bold-ravens-wake.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1808 ---- -**Internal: third-party descriptor loader enforces `configHome` write-confinement at load time** — `loadRegistry({includeInstalled:true, configHome})` now rejects (skip + warn, fail-closed) any installed third-party host-plugin descriptor whose declared `destSubpath` resolves outside the supplied `configHome`, before it is composed into the registry (ADR-1239 Phase C-2 / #1681 slice 2). The `configHome` option is optional and backward-compatible (omitted → no load-time check; install-time gate still bounds writes). No user-facing change for existing flows. - - diff --git a/.changeset/bold-seals-chatter.md b/.changeset/bold-seals-chatter.md deleted file mode 100644 index 2f98cafcf..000000000 --- a/.changeset/bold-seals-chatter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2223 ---- -**`stale-bake-guard` hermeticity fix (test-isolation)** — the readGsdEffectiveModelOverrides subtest no longer reads the developer's real `~/.gsd/defaults.json`; the resolver now accepts a homedir seam so the test sandboxes HOME. (#2152) diff --git a/.changeset/brave-hawks-fly.md b/.changeset/brave-hawks-fly.md deleted file mode 100644 index b07b243e8..000000000 --- a/.changeset/brave-hawks-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1487 ---- -**`/gsd-surface` (`list`/`status`) works on Claude Code global installs** — the installer now writes a `.gsd-source` marker pointing at its `commands/gsd` source, so `findInstallSourceRoot` resolves on the global skills layout (which ships no `commands/gsd` tree) instead of throwing `could not locate commands/gsd`. (#1487) diff --git a/.changeset/brave-koalas-glide.md b/.changeset/brave-koalas-glide.md deleted file mode 100644 index c074d4da4..000000000 --- a/.changeset/brave-koalas-glide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2386 ---- -**Cursor no longer shows every `/gsd-*` command twice** — a `--cursor` install wrote both a skill and a slash command for each action, so every GSD entry appeared twice in Cursor's `/` menu. GSD now installs Cursor skills as `user-invocable: false` (matching the existing CodeBuddy behavior), so the slash command is the single `/` entry point while skills remain model-invocable. (#2341) diff --git a/.changeset/bright-otters-embed.md b/.changeset/bright-otters-embed.md deleted file mode 100644 index d8ffb1b3f..000000000 --- a/.changeset/bright-otters-embed.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2448 ---- -**The EoS Registry now lists GSD for Oh My Pi** — discover the independently maintained `tchivs/gsd-omp` protocol-v1 host integration, including exact install and uninstall commands, supported interface points, and negotiated host axes. diff --git a/.changeset/broken-windows-ledger.md b/.changeset/broken-windows-ledger.md deleted file mode 100644 index 9d0c45bdd..000000000 --- a/.changeset/broken-windows-ledger.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2441 ---- -**Broken-windows ledger** — `/gsd:ship` now blocks (when `workflow.windows_enforce=true`, opt-in) while `.planning/WINDOWS.md` has any `open` entry, and the executor auto-populates the ledger with stubs, skipped tests, and unrun verifies as it works. Each window can be `waived` only with a recorded reason (auditable) or `fixed` (removed from the blocking set); `/gsd:progress` surfaces the open + waived counts. Backward-compatible: projects with no ledger ship cleanly (open_count starts at 0), and enforcement is off by default so tracking can precede the gate. Enable with `gsd config-set workflow.windows_enforce true`. (#1950) diff --git a/.changeset/calm-eagles-tumble.md b/.changeset/calm-eagles-tumble.md deleted file mode 100644 index d2131759c..000000000 --- a/.changeset/calm-eagles-tumble.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Added -pr: 1965 ---- - -**GSD now ships a pi extension** — a real, jiti-loadable ExtensionAPI module (`pi/gsd.cjs`) that registers `/gsd` (dispatches through the GSD command-routing hub) + `gsd_invoke` tool + `tool_call` event, installable at `~/.pi/agent/extensions/`. A reachability test proves the `/gsd` handler dispatches through the engine (keystone wired, not just registered on a mock). (#1965) diff --git a/.changeset/clever-cats-howl.md b/.changeset/clever-cats-howl.md deleted file mode 100644 index af82bb000..000000000 --- a/.changeset/clever-cats-howl.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1764 ---- -**Internal: agent install for cursor/windsurf/augment/trae/codebuddy now flows through the descriptor path** — ADR-1235 step 1 routes the trivial-converter runtime group's agents off the inline install() loop onto the descriptor-driven `installRuntimeArtifacts` path, applying the cross-cutting steps uniformly (pre-converter, no workflow-stamp). Agent output is byte-identical for all 16 runtimes (golden-parity asserted, global + local verified); no user-facing change. - - diff --git a/.changeset/clever-cats-roar.md b/.changeset/clever-cats-roar.md deleted file mode 100644 index d625246b2..000000000 --- a/.changeset/clever-cats-roar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1584 ---- -**gsd-ui-checker gains an adversarial FORCE stance (LLM-playbook principle 16)** — the only verdict-producing critic that lacked one now resists rubber-stamping UI-SPEC contracts, with BLOCK/FLAG/PASS classification. Based on arXiv 2505.23840 (third-person objective persona), 2506.04975 (objective-not-hostile persona). diff --git a/.changeset/clever-eagles-romp.md b/.changeset/clever-eagles-romp.md deleted file mode 100644 index 423a3ae27..000000000 --- a/.changeset/clever-eagles-romp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2231 ---- -**`phase complete --phase N` now works alongside the positional form** — the phase verb family treated the first positional as the phase number, so `--phase 12` was passed as the literal phase name and failed with 'Phase --phase not found'. The phase family now accepts the --phase flag consistently with the state family, and unrecognized flags yield a usage error. (#2201) diff --git a/.changeset/clever-lemurs-march.md b/.changeset/clever-lemurs-march.md deleted file mode 100644 index d585f6d7d..000000000 --- a/.changeset/clever-lemurs-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2054 ---- -**Third-party capability skills now surface correctly after install** — a skills-only `role: feature` capability installed `active` but its skills never reached the runtime surface, `capability enable`/`set` rejected it as `unknown capability`, and `capability list` disagreed with `capability state`. `resolveSurface` now unions the composed registry's `capabilityClusters` into the surfaced skill set (no on-disk linking), the writer validates against the composed overlay-aware registry, and `capability list` carries a `surfaced` field matching `capability state`. diff --git a/.changeset/clever-moles-frolic.md b/.changeset/clever-moles-frolic.md deleted file mode 100644 index 68748de28..000000000 --- a/.changeset/clever-moles-frolic.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2467 ---- -**`/gsd-ship` no longer emits a 100%-missing TDD Audit noise table** — the TDD Audit PR-body section was always emitted, but the execute pipeline only writes `gate_status:` git trailers when TDD mode is active. Without TDD mode (the default), every commit was counted `missing` and the table was pure noise with no way to disable it. The section is now gated behind `workflow.tdd_mode`: when TDD mode is off, both the TDD Audit section and the aggregate `gate_status:` trailer are skipped entirely; when on, the existing behavior is preserved. diff --git a/.changeset/clever-orcas-squeak.md b/.changeset/clever-orcas-squeak.md deleted file mode 100644 index cbc3ba19a..000000000 --- a/.changeset/clever-orcas-squeak.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2323 ---- -**`phases.clear` now archives phase history under the outgoing milestone version, not the newly-switched one** — because `new-milestone` advances the milestone before clearing leftover phases, the phase-history archive was silently misfiled under the new milestone's `-phases/` directory. A new `--archive-version` override on `phases.clear` (threaded from the new-milestone workflow) files the archive under the previous milestone's version; without it, behavior is unchanged. (#2288) diff --git a/.changeset/clever-rams-march.md b/.changeset/clever-rams-march.md deleted file mode 100644 index 3912be397..000000000 --- a/.changeset/clever-rams-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1910 ---- -Fixed: probe-core's runProbeCli now fails closed on per-item adapter garbage inside a well-shaped report envelope, matching its documented 'fails closed on adapter garbage' contract. diff --git a/.changeset/clever-voles-swim.md b/.changeset/clever-voles-swim.md deleted file mode 100644 index d5adcdf15..000000000 --- a/.changeset/clever-voles-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2318 ---- -**Deferred out-of-scope findings logged to `deferred-items.md` are now surfaced** — the executor's SCOPE BOUNDARY convention writes discoveries to a phase directory's `deferred-items.md`, but nothing read it back, so those items were permanently invisible. `/gsd-progress`'s forensic audit and `audit-uat` now glob `.planning/phases/*/deferred-items.md` and surface unresolved entries. (#2287) diff --git a/.changeset/curious-koalas-gather.md b/.changeset/curious-koalas-gather.md deleted file mode 100644 index 263a88a61..000000000 --- a/.changeset/curious-koalas-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1722 ---- -**`/gsd:verify-work` no longer silently terminates when all remaining UAT tests are blocked** — sessions with `blocked_count > 0` and `pending_count == 0` now route to `complete_session` as expected, enabling the zero-issues auto-transition path. diff --git a/.changeset/curious-pandas-howl.md b/.changeset/curious-pandas-howl.md deleted file mode 100644 index fbbc13626..000000000 --- a/.changeset/curious-pandas-howl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2253 ---- -**state record-metric no longer appends per-plan rows into the By-Phase velocity table** — it now maintains its own Per-Plan Metrics table (self-created on first use), and its auto-create scaffold header is corrected. (#2253) diff --git a/.changeset/curious-quails-caper.md b/.changeset/curious-quails-caper.md deleted file mode 100644 index c00abc08b..000000000 --- a/.changeset/curious-quails-caper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2334 ---- -**Dynamic routing now escalates the model, not just effort** — with `dynamic_routing.enabled`, retry attempts advanced the reasoning effort but the model stayed pinned to the default tier because `resolve-execution` resolved the model without consulting `dynamic_routing`. `resolve-execution` now resolves the model per-attempt through the tier ladder (e.g. standard→heavy on attempt 1, capped at `max_escalations`); resolution is unchanged when dynamic routing is disabled. (#2068) diff --git a/.changeset/curious-rams-run.md b/.changeset/curious-rams-run.md deleted file mode 100644 index 2835428a4..000000000 --- a/.changeset/curious-rams-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2466 ---- -**`/gsd-next` no longer reports a project as complete while phases are still unchecked** — `smart-entry`'s completion check now grounds in ROADMAP.md's actual Progress table (global, authoritative) instead of STATE.md's stale milestone-scoped total_phases, and its status regex requires milestone-level language (`milestone complete` / `all phases complete` / `complete`) instead of matching any per-phase `shipped` or `done` substring. Together these fix the false-complete misclassification that could route `/gsd-next` toward `/gsd-new-milestone` — which archives still-pending phase directories. diff --git a/.changeset/daring-badgers-forage.md b/.changeset/daring-badgers-forage.md deleted file mode 100644 index f644f7212..000000000 --- a/.changeset/daring-badgers-forage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1709 ---- -Codex reviewer now captures the review via codex's --output-last-message flag instead of redirecting stdout, so Windows process-teardown output no longer pollutes the review file and slips past the empty-output guard. diff --git a/.changeset/daring-cats-snooze.md b/.changeset/daring-cats-snooze.md deleted file mode 100644 index eb1c797ce..000000000 --- a/.changeset/daring-cats-snooze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2216 ---- -**`last_activity` now shows your local calendar day** — the clock seam derived the date by slicing a UTC instant, so in negative-UTC-offset zones during UTC's early evening the date-only `last_activity` field jumped a day ahead of the operator's actual date (and of `last_updated`'s local date). Operator-facing date fields now use a host-local calendar day while internal/cosmetic stamps stay UTC. (#2136) diff --git a/.changeset/daring-deer-leap.md b/.changeset/daring-deer-leap.md deleted file mode 100644 index 310fb39bd..000000000 --- a/.changeset/daring-deer-leap.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1802 ---- -**Internal: the declarative embedding adapter is now named + bound behind a minimal `HostIntegrationInterface`** — `createDeclarativeAdapter({runtime})` (new `src/adapter-declarative.cts`) delegates in-process to `install-engine`'s `installRuntimeArtifacts`/`uninstallRuntimeArtifacts`, formalizing today's projection path as one of the two embedding adapters behind a common contract (ADR-1239 Phase C-1 / #1680 AC1). Output is byte-identical to today's install (gated by `golden-install-parity`). The full 6-point interface binding surface is deferred until the imperative adapter (AC2) fixes the shape (ADR-1239 open wire-shape question). No user-facing change — the adapter is not yet wired to any runtime path. - - diff --git a/.changeset/daring-otters-dart.md b/.changeset/daring-otters-dart.md deleted file mode 100644 index 54f340c3a..000000000 --- a/.changeset/daring-otters-dart.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1757 ---- -**Internal: getDirName is now derived from a documented `runtime.localConfigDir` descriptor field** — each runtime's local content-rewrite directory (e.g. `cursor`→`.cursor`, `copilot`→`.github`) moved from a hand-maintained if-chain into its capability descriptor (ADR-1239 Phase B), so it can no longer drift from the registry. Install output is byte-identical for all 16 runtimes (golden-parity asserted); no user-facing change. diff --git a/.changeset/daring-otters-roar.md b/.changeset/daring-otters-roar.md deleted file mode 100644 index 6959d835b..000000000 --- a/.changeset/daring-otters-roar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2404 ---- -**A phase with a deliberately-unexecuted (superseded) plan no longer stays stuck below 100%** — a plan reassigned or dropped mid-phase can never gain a matching SUMMARY, yet plan-scan counted it forever, so the phase read In Progress and the milestone sat below 100% permanently — the plan-level analogue of the retired-phase bug (#1514). Mark such a plan `status: superseded` in its PLAN.md frontmatter and it is now excluded from both the plan and summary counts, so the phase completes honestly (a 13-plan phase with 2 superseded reads 11/11). Plans without the marker are unchanged. (#2349) diff --git a/.changeset/eager-bears-wander.md b/.changeset/eager-bears-wander.md deleted file mode 100644 index 32094114e..000000000 --- a/.changeset/eager-bears-wander.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2215 ---- -**`milestone_name` is no longer clobbered with a delimiter-led fragment** — getMilestoneInfo's `##` heading regex was unanchored, so it matched a heading quoted inside backticks in the Milestones bullet and wrote garbage like `— Active Milestone` over the curated milestone name on every phase transition. Now consults the 🚧 marker first, anchors the regex to line start, strips the leading delimiter, and widens the preserve guard so a bad derive keeps the existing name. (#2135) diff --git a/.changeset/eager-elks-frolic.md b/.changeset/eager-elks-frolic.md deleted file mode 100644 index de18b72a0..000000000 --- a/.changeset/eager-elks-frolic.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1759 ---- -**Internal: copyWithPathReplacement converter selection is now data-driven** — the installer's back-compat content-copy path replaced its 13 hardcoded `runtime === 'x'` flag chains with a single per-runtime dispatch table (ADR-1239 Phase B). Install output is byte-identical for all 16 runtimes (golden-parity asserted); no user-facing change. - - diff --git a/.changeset/eager-ibex-bark.md b/.changeset/eager-ibex-bark.md deleted file mode 100644 index 467e97c0e..000000000 --- a/.changeset/eager-ibex-bark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1844 ---- -**`init milestone-op` now counts project_code-prefixed phase directories correctly** — fully shipped milestones using the standard prefixed directory layout no longer report `completed_phases: 0` or stay falsely incomplete. (#1844) diff --git a/.changeset/eager-pandas-jump.md b/.changeset/eager-pandas-jump.md deleted file mode 100644 index 7d4f0f39b..000000000 --- a/.changeset/eager-pandas-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2464 ---- -**`/gsd-mempalace-capture` no longer crashes on first invocation** — the skill's own documented `rooms:` example wrote a flat list of bare strings, but mempalace's miner expects each entry as a dict with a `name` key, so following the example verbatim and running `mempalace mine` crashed with `TypeError: string indices must be integers, not 'str'`. Both `skills/gsd-mempalace-capture/SKILL.md` and `commands/gsd/mempalace-capture.md` now ship the corrected `- name: ` shape, so the documented example runs successfully end-to-end. diff --git a/.changeset/eager-tunas-swim.md b/.changeset/eager-tunas-swim.md deleted file mode 100644 index 5a77fc331..000000000 --- a/.changeset/eager-tunas-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1991 ---- -**`/gsd-quick` no longer halts with a stale-base worktree mismatch** — the worktree executor now degrades to sequential execution when its fork base has diverged from origin/HEAD, instead of spawning a worktree guaranteed to fail the base-mismatch guard. diff --git a/.changeset/eager-wasps-swim.md b/.changeset/eager-wasps-swim.md deleted file mode 100644 index 5b3750d56..000000000 --- a/.changeset/eager-wasps-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2445 ---- -**`GSD_ALLOW_SYMLINKED_DEST=1` lets users with intentional symlinked configHome layouts install/update again** — v1.7.0's destSubpath write-confinement (ADR-1239 Phase B) refused install/update whenever CLAUDE_CONFIG_DIR (or an artifact-kind child like `skills/` or `hooks/`) was a pre-existing symlink, with no opt-out. Three legitimate user-owned layouts were blocked: multi-account configs with symlinked shared skills/hooks (POSIX symlinks), Windows Junctions to shared skills dirs, and dotfiles-managed configHome (e.g. nix-darwin symlinking `~/.claude` itself to a version-controlled dir). The new env var follows user-owned symlinks instead of refusing them, while preserving the two load-bearing refusals from the original threat model: path-traversal in the destSubpath string itself (`../../etc`-style), and a symlink resolving to the install root itself (would let the prune pass wipe it). (#2393) diff --git a/.changeset/eight-foxes-cheer.md b/.changeset/eight-foxes-cheer.md deleted file mode 100644 index d674babc7..000000000 --- a/.changeset/eight-foxes-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2482 ---- -**`state record-session` no longer silently drops inserted fields on a CRLF `STATE.md`** — the section-rewrite regexes in `cmdStateRecordSession` used literal `\n` which couldn't match a CRLF STATE.md (`---\r\n`), so when a canonical session field (`Resume file` / `Stopped at` / `Last session`) was missing and had to be **inserted** via the section-rewrite path, the CRLF-tolerant detector entered the branch, the writer regex silently no-op'd, but `updated.push(...)` ran unconditionally. The command returned `{"recorded": true, "updated": ["Resume File"]}` while the field was never written to disk. With `core.autocrlf=input`, the CRLF working-tree file produced no `git diff`/`git status` change, so the bug was invisible. Both regexes now use the CRLF-tolerant `\r?\n` form (same canonical pattern already in use elsewhere), and a new defensive invariant gates `updated.push(...)` on the replace callback actually firing — so a future detector/writer drift will surface as missing `updated` entries rather than re-arming this silent-success class. diff --git a/.changeset/expand-tilde-review-2352.md b/.changeset/expand-tilde-review-2352.md deleted file mode 100644 index 7a4edc628..000000000 --- a/.changeset/expand-tilde-review-2352.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2419 ---- -**`/code-review` no longer skips a phase whose SUMMARY.md records `~/`-prefixed file paths** — such a path was silently dropped as "deleted" (bash never tilde-expands a `~` that arrives as a variable's value), emptying the review scope and reporting "no source files changed" as a false success. Tilde paths are now expanded to `$HOME/…` before the deleted-file filter runs. diff --git a/.changeset/external-job-config-wiring.md b/.changeset/external-job-config-wiring.md deleted file mode 100644 index 8b06a03cd..000000000 --- a/.changeset/external-job-config-wiring.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2006 ---- -**Setting `external_job.submit_timeout_ms` / `poll_timeout_ms` / `artifact_dir` in `.planning/config.json` now actually configures the SLURM adapter** — the keys were declared by the external-job capability but the adapter only read env vars, so config edits silently had no effect. The adapter now resolves them through the canonical capability-config seam (env override > config > registry default), surfaces the resolved `artifact_dir` in `submit` output, documents why the contribution registers at `execute:wave:post` (#1164 asks for `wave:pre`, which `execute-phase.md` does not dispatch today; wiring it is a core-loop change #1164 explicitly defers), and gains unit coverage for the CLI surface (`parseFlags`, `findPlanningDir`, `resolveExternalJobSettings`, `formatShowReport`). (#1164) diff --git a/.changeset/fierce-bears-gather.md b/.changeset/fierce-bears-gather.md deleted file mode 100644 index ade0d2278..000000000 --- a/.changeset/fierce-bears-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1835 ---- -`plan-phase` now authors edge and prohibition predicates into PLAN.md `must_haves` when a phase SPEC omits `## Edge Coverage` / `## Prohibitions`, so goal-backward verification still has predicates to check on a spec-less phase (ADR-857 Phase 6). Gated by the new default-on `workflow.specless_probe_fallback` toggle — disable it to skip the fallback (the skip is recorded visibly in the plan). Spec-less prohibitions are authored descriptor-less and disposed flagged/unverified (honest verifier #1154), never a silent pass. diff --git a/.changeset/fierce-pumas-gather.md b/.changeset/fierce-pumas-gather.md deleted file mode 100644 index 352163e1e..000000000 --- a/.changeset/fierce-pumas-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2184 ---- -**The Antigravity reviewer in `/gsd-review` no longer reviews blind** — `agy -p` never granted the agent the repo under review, so it frequently anchored on its own scratch directory and returned plan-text-only verdicts counted at full consensus weight. The reviewer is now granted the repo (capability-probed `--add-dir`) and anchored to the absolute repo root; a review that still runs without repo access is stamped `[reviewed-without-repo-access]` and down-weighted in the Consensus Summary. The cursor-agent prompt gains the same absolute-root anchor. (#2176) diff --git a/.changeset/fierce-ravens-dance.md b/.changeset/fierce-ravens-dance.md deleted file mode 100644 index 71cca0b6a..000000000 --- a/.changeset/fierce-ravens-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2446 ---- -**Non-Claude installs no longer brand all GSD output as Claude** — the installer never persisted `runtime: ` into `~/.gsd/defaults.json` for non-Claude runtimes, so `resolveRuntime()` (precedence: `GSD_RUNTIME` env > `config.runtime` > `'claude'`) fell through to the hard-coded `'claude'` default. A non-Claude install showed `agent_runtime: "claude"` and Claude-formatted `/gsd-*` slash hints with no env or config hand-set. The installer now persists `runtime: ` into `~/.gsd/defaults.json` for non-Claude runtimes, mirroring the existing `resolve_model_ids: "omit"` write at the same call site. Claude is the fallback so it needs no write; an explicit pre-existing `runtime` value is always preserved. (#2395) diff --git a/.changeset/gallant-cats-hum.md b/.changeset/gallant-cats-hum.md deleted file mode 100644 index e795dba0b..000000000 --- a/.changeset/gallant-cats-hum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1846 ---- -**Autonomous reruns now skip phases with deferred verification until you resume them explicitly** — if a prior `/gsd-autonomous` run recorded `verification_deferred_human` or `verification_deferred_gaps`, later reruns no longer drop back into the same prompt loop and instead point you at the saved resume command. (#1846) diff --git a/.changeset/gallant-foxes-bark.md b/.changeset/gallant-foxes-bark.md deleted file mode 100644 index 51e5c2741..000000000 --- a/.changeset/gallant-foxes-bark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2259 ---- -**Phase-completion now writes `Status: All phases complete` instead of the overloaded bare `Milestone complete`** — the phase-level completion verb (`completePhaseCore`) was writing the same bare 'Milestone complete' string that the milestone-close verb uses for terminal state, causing a phase-level verb to own a milestone-level field. Per ADR-2207, phase-completion now writes the existing intermediate value 'All phases complete' (already used in gsd2-import.cts); milestone termination (' milestone complete' / 'Awaiting next milestone') remains solely with the milestone-close verb. (#2204) diff --git a/.changeset/gallant-herons-rest.md b/.changeset/gallant-herons-rest.md deleted file mode 100644 index 54ef34c5e..000000000 --- a/.changeset/gallant-herons-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2219 ---- -**`requirements mark-complete` no longer reports silent success when the traceability row is missing** — it OR-ed its checkbox and table-row writes into one flag, so a checkbox-only reconcile returned a payload byte-identical to a full reconcile while the traceability row stayed Pending (and re-run masked it as already-complete). It now surfaces `table_unmatched` for IDs whose checkbox reconciled but whose table row is absent, and treats a checked box with no table row as partial rather than done. (#2140) diff --git a/.changeset/gallant-rams-rally.md b/.changeset/gallant-rams-rally.md deleted file mode 100644 index 84f759dc1..000000000 --- a/.changeset/gallant-rams-rally.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2188 ---- -**Discover third-party GSD Capabilities in a new Community Capability Registry.** — A non-endorsing discoverability catalog where authors register a Capability via a documentation PR; each entry carries a live latest-release badge and a per-entry GitHub Discussion for community ranking and comments. (#2188) diff --git a/.changeset/gallant-wasps-wave.md b/.changeset/gallant-wasps-wave.md deleted file mode 100644 index 118c6ddc1..000000000 --- a/.changeset/gallant-wasps-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1832 ---- -state prune now resolves the current phase from the canonical location — frontmatter current_phase, the Current Phase field, or the prose Phase: line scoped to the ## Current Position section — instead of extracting Phase over the whole document, where stateExtractField's pipe-table fallback could latch onto an unrelated | Phase | N | row (e.g. a historical verification table) and compute a wrong prune cutoff. diff --git a/.changeset/gentle-badgers-roar.md b/.changeset/gentle-badgers-roar.md deleted file mode 100644 index a20eb5765..000000000 --- a/.changeset/gentle-badgers-roar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2048 ---- -**`model_overrides` Claude model IDs now resolve to Agent-tool aliases on the claude runtime** — a full Claude model ID (e.g. `claude-sonnet-5`) in `model_overrides` was returned verbatim and silently dropped by the Claude Agent tool (whose `model` parameter documents only tier aliases), causing the spawned subagent to inherit the parent session model instead of the configured one. It now maps to the tier alias (`sonnet`/`opus`/`haiku`/`fable`), consistent with the `model_policy` path (#1144). Bare aliases, non-Claude values, and non-Claude runtimes are unchanged; a Claude ID with no alias warns once and falls through to tier resolution. (#2041) diff --git a/.changeset/gentle-koalas-hum.md b/.changeset/gentle-koalas-hum.md deleted file mode 100644 index fdb5564c6..000000000 --- a/.changeset/gentle-koalas-hum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2336 ---- -**`validate health` no longer false-flags the `adaptive` model profile, and now warns when a `models.` tier is invalid** — health reported `W004 invalid model_profile "adaptive"` for a profile that has been valid since v1.40, and a typo like `"planning": "opuss"` was accepted in silence while the resolver quietly ignored it. Health now sources its profile list from the model catalog and emits `W022` for unknown phase types and invalid tier values. diff --git a/.changeset/gentle-tigers-greet.md b/.changeset/gentle-tigers-greet.md deleted file mode 100644 index d7d88129b..000000000 --- a/.changeset/gentle-tigers-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2254 ---- -**Phase dirs whose slug leads with a multi-digit number (e.g. a year) resolve again** — a phase like `14-2026-photos-performance` (roadmap name "2026 Photos & Performance") had its phase token over-collected as `14-2026`, so `init.plan-phase`, `init.execute-phase`, `phase-plan-index`, `state.planned-phase`, and `roadmap.annotate-dependencies` reported `phase_dir=null` / `plan_count=0` while the directory existed. Continuation segments of a phase token are now capped at the exactly-2-digit zero-padded form the write side emits, via a single shared grammar source consumed by all five parsing sites (the residual case from #2043). (#2232) diff --git a/.changeset/graceful-badgers-click.md b/.changeset/graceful-badgers-click.md deleted file mode 100644 index cec90ae43..000000000 --- a/.changeset/graceful-badgers-click.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1765 ---- -Phase headers that place a parenthetical tag before the colon (`### Phase 26 (Cluster B): Title`) now resolve and enumerate the same as untagged headers. Previously the resolver returned not-found and `roadmap analyze`/listing silently dropped the phase (wrong phase_count, progress, and next_phase). Tag tolerance is applied at every phase-header read site; untagged and all existing header formats parse unchanged. diff --git a/.changeset/graceful-badgers-dance.md b/.changeset/graceful-badgers-dance.md deleted file mode 100644 index 0f8d58286..000000000 --- a/.changeset/graceful-badgers-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1719 ---- -**#853 dispatch-flatten is now data-driven (ADR-1239 Phase B)** — whether GSD backgrounds the plan/execute orchestrator is decided from a documentation-sourced `backgroundDispatch` capability per host (via `gsd_run query dispatch-should-flatten`) instead of a hardcoded `runtime === 'codex'` check. **Cursor now backgrounds the orchestrator** (its docs document backgrounded subagent nesting); codex unchanged; all other hosts run inline. Fail-closed to inline on any uncertainty. diff --git a/.changeset/graceful-geese-click.md b/.changeset/graceful-geese-click.md deleted file mode 100644 index 6f65b9056..000000000 --- a/.changeset/graceful-geese-click.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1809 ---- -**Internal: companion MCP server module (interface points 1 + 5)** — `handleMessage`/`runServer` (new `src/mcp-server.cts`) is a minimal, dependency-free stdio JSON-RPC 2.0 server exposing `gsd_invoke_command` (→ the command-routing hub) + `gsd_read_state`/`gsd_write_state` (→ the Phase 3 stateIO seam), so any MCP-consuming host can drive GSD with no bespoke plugin (ADR-1239 Phase C-2 / #1681 slice 3a). Bin entry / packaging deferred to slice 3b. No user-facing change — the server is not yet wired to a bin entry. - - diff --git a/.changeset/graceful-koalas-forage.md b/.changeset/graceful-koalas-forage.md deleted file mode 100644 index 20936f8ea..000000000 --- a/.changeset/graceful-koalas-forage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2461 ---- -**`/gsd-stats` no longer misreports a phase as Not Started when two directories collide on the same phase key** — `cmdStats` now folds colliding statuses by precedence (Complete > Needs Review > Executed > In Progress > Planned > Not Started) instead of overwriting last-write-wins, so the furthest-along status wins regardless of `fs.readdirSync` order. Separately, `/gsd-health` now emits a new W023 warning whenever two or more real phase directories collide on the same normalized phase key, naming both directories and their independently-computed statuses (neutral wording — never guesses which is the real one). diff --git a/.changeset/graceful-koalas-greet.md b/.changeset/graceful-koalas-greet.md deleted file mode 100644 index 7fad1c6a8..000000000 --- a/.changeset/graceful-koalas-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2251 ---- -**`requirements mark-complete` reports a per-surface write-set** — the command now returns a per-requirement `write_set` (checkbox + traceability surfaces) and a `write_set_complete` that is true only when every surface of every requirement applied, so a partial (checkbox-only) reconcile can no longer masquerade as full success even inside a multi-ID batch. Introduces the reusable ADR-2143 §5/§6 `Result` / `WriteSet` contract. (#2251) diff --git a/.changeset/graceful-moles-gather.md b/.changeset/graceful-moles-gather.md deleted file mode 100644 index fbc0e4a1a..000000000 --- a/.changeset/graceful-moles-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1873 ---- -Executor and milestone-summary/forensics workflows now call state.* commands with named flags so the named-only router records metrics, decisions, blockers, and session continuity instead of silently dropping positional args. diff --git a/.changeset/graceful-wasps-caper.md b/.changeset/graceful-wasps-caper.md deleted file mode 100644 index a0eadf8dd..000000000 --- a/.changeset/graceful-wasps-caper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1927 ---- -**bug-1367 install test no longer fails on Windows CI when hooks/dist isn't pre-built** — the test ran install.js without building its hooks/dist precondition (a gitignored build artifact the unit lane doesn't build), so on a lane without pre-built hooks the installer hit "Failed to install hooks: directory is empty" and the before-hook threw. The test now builds hooks in its own before() (mirroring golden-install-parity). (#1926) diff --git a/.changeset/happy-bears-gather.md b/.changeset/happy-bears-gather.md deleted file mode 100644 index dd4170e4c..000000000 --- a/.changeset/happy-bears-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 2478 ---- -**Patched a transitive denial-of-service advisory in the production dependency tree** — `body-parser` reached GSD via the Claude Agent SDK's MCP dependency and, on versions through 2.2.2, silently stopped enforcing request size limits when given an invalid limit value (GHSA-v422-hmwv-36x6). Pinned to >=2.3.0. (#2470) diff --git a/.changeset/happy-birds-chatter.md b/.changeset/happy-birds-chatter.md deleted file mode 100644 index 414063327..000000000 --- a/.changeset/happy-birds-chatter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1755 ---- -**GSD now warns when a stale global CLI (e.g. a retired @gsd-build/sdk canary) shadows your project-local install** — the gsd-tools CLI startup detects when the running binary is outside the project root while a project-local install exists, and prints a remediation warning to stderr (non-blocking). (#1754) diff --git a/.changeset/happy-jays-travel.md b/.changeset/happy-jays-travel.md deleted file mode 100644 index c580ce023..000000000 --- a/.changeset/happy-jays-travel.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1803 ---- -**Internal: the imperative embedding adapter now composes the capability registry behind the same `HostIntegrationInterface`** — `createImperativeAdapter({runtime})` (new `src/adapter-imperative.cts`) calls `loadRegistry({includeInstalled:true})` (first-party-wins + consent + fail-closed — identical trust semantics to the CLI) and binds the engine surface behind the same contract the declarative adapter (AC1) satisfies, plus a `registry` accessor for an in-process host to bind its primitives to (ADR-1239 Phase C-1 / #1680 AC2). Concrete host binding is deferred to Phase 5. No user-facing change — the adapter is not yet wired to any runtime path. - - diff --git a/.changeset/happy-seals-roam.md b/.changeset/happy-seals-roam.md deleted file mode 100644 index 10d8f7d65..000000000 --- a/.changeset/happy-seals-roam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2214 ---- -**`/gsd-fast` now appends Quick Task rows to STATE.md again** — the log_to_state column-count guard used an off-by-one awk formula (`NF-1`) that was always one too high, so the schema gate rejected the very table quick.md creates and silently skipped the STATE.md update. Also now supports the 6-column validate-mode table. (#2133) diff --git a/.changeset/hooks-dist-scoped-ci-race.md b/.changeset/hooks-dist-scoped-ci-race.md deleted file mode 100644 index 906946dfd..000000000 --- a/.changeset/hooks-dist-scoped-ci-race.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1968 ---- -Build the gitignored `hooks/dist/` artifact once upfront in `scripts/run-tests.cjs` (the same chokepoint as `ensureBuiltArtifacts`), before any concurrent install test spawns `install.js`. Closes the scoped-CI first-build empty-dir race that intermittently failed install tests with `Failed to install hooks: directory is empty` (e.g. `bug-3683-workflow-colon-namespace-leak`). (#1967) diff --git a/.changeset/humble-dogs-gather.md b/.changeset/humble-dogs-gather.md deleted file mode 100644 index 6a0cc0e60..000000000 --- a/.changeset/humble-dogs-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1916 ---- -**workstream progress no longer reports shipped milestones as `executing`** — `gsd-tools workstream progress` now derives each workstream's status from authoritative shipped signals (an archived milestone snapshot under milestones/, or a SHIPPED marker in the workstream ROADMAP) instead of trusting the mutable STATE.md `Status` field, so a stale field can never hide a shipped/archived milestone. The output adds `status_source` (`field` | `derived`) and `status_conflict` (true when the derived value disagrees with the stale field). (#1913) diff --git a/.changeset/humble-geese-roam.md b/.changeset/humble-geese-roam.md deleted file mode 100644 index a3789d05a..000000000 --- a/.changeset/humble-geese-roam.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1804 ---- -**Internal: the model adapter seam exposes `passive` + `active` adapters selected by `modelMode`** — `createModelAdapter({modelMode})` (new `src/model-adapter.cts`): `passive` formalizes today's tier routing (delegates to `model-resolver.resolveModelForTier`), `active` is a host-supplied `sendRequest` seam (VS Code `vscode.lm` / pi providers), fail-closed until Phase 5 binds a concrete provider (ADR-1239 Phase C-1 / #1680 AC3). No user-facing change — the seam is not yet wired to any runtime path. - - diff --git a/.changeset/humble-jaguars-swim.md b/.changeset/humble-jaguars-swim.md deleted file mode 100644 index f44f48c72..000000000 --- a/.changeset/humble-jaguars-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 2323 ---- -**`phases.clear --archive-version` and `milestone complete ` now reject version labels containing path separators or `..`** — the milestone version becomes a filesystem directory name that phase directories are moved into, so an unvalidated value could relocate phase history outside `.planning/milestones/`. Both now validate against a strict version-token pattern and fail loudly. (#2288) diff --git a/.changeset/humble-seals-rest.md b/.changeset/humble-seals-rest.md deleted file mode 100644 index e5392f53a..000000000 --- a/.changeset/humble-seals-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1810 ---- -**`gsd-mcp-server` — companion MCP server (interface points 1 + 5)** — a new bin command (`npx @opengsd/gsd-core gsd-mcp-server`) runs a stdio JSON-RPC 2.0 MCP server exposing `gsd_invoke_command` (→ the GSD command-routing hub) + `gsd_read_state` / `gsd_write_state` (→ `.planning/` state), so any MCP-consuming host (Claude Code, Codex, OpenCode, VS Code, Gemini CLI, Cursor, Cline, Hermes) can drive GSD with no bespoke plugin (ADR-1239 Phase C-2 / #1681). Dependency-free (hand-rolled JSON-RPC). How-to: `docs/how-to/connect-gsd-mcp-server.md`. diff --git a/.changeset/humble-sloths-jump.md b/.changeset/humble-sloths-jump.md deleted file mode 100644 index 88e081286..000000000 --- a/.changeset/humble-sloths-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1742 ---- -**Windows install/upgrade/state-write operations no longer fail on transient antivirus/indexer file locks** — the fs.renameSync atomic-publish sites (install state, hooks config, capability ledger/lifecycle, phase/workstream/milestone dirs, roadmap, planning/state locks) now retry EPERM/EBUSY/EACCES via retryRenameSync instead of propagating the transient lock; enforced by the new local/require-fs-op-fallback lint rule (ADR-1703 Phase 6). (#1740) diff --git a/.changeset/humble-tunas-munch.md b/.changeset/humble-tunas-munch.md deleted file mode 100644 index 0c5430279..000000000 --- a/.changeset/humble-tunas-munch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1807 ---- -reconstructFrontmatter now emits valid YAML for scalars and block-array items that were previously serialized unescaped. Values carrying a YAML indicator plus a literal quote/backslash, embedded control characters, the empty string, a leading YAML indicator, or leading/trailing whitespace are now routed through a properly escaped double-quoted form, so frontmatter round-trips through strict parsers (js-yaml, PyYAML) instead of corrupting the block on the next state sync. diff --git a/.changeset/humble-tunas-travel.md b/.changeset/humble-tunas-travel.md deleted file mode 100644 index 0b4cc9104..000000000 --- a/.changeset/humble-tunas-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2253 ---- -**`phase remove` no longer destroys the Progress table when removing the last phase** — deleting a phase used a whole-document regex whose scan, on the final phase, ran past the section and swept away the `## Progress` heading and its entire tracking table; the deletion is now structurally bounded to the phase’s own section. (#2253) diff --git a/.changeset/humble-voles-glide.md b/.changeset/humble-voles-glide.md deleted file mode 100644 index 2e07df349..000000000 --- a/.changeset/humble-voles-glide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2428 ---- -**Subagent prompts embedding orchestrator-relative planning paths now resolve correctly when the spawned subagent's own working directory differs from the orchestrator's (e.g. a git worktree)** — `init.*` (and `state.load`) command handlers now emit `state_path`, `roadmap_path`, `phase_dir`, `project_path`, `research_dir`, `codebase_dir`, `intel_dir`, `conflicts_path`, `debug_dir`, and similar fields as absolute paths anchored on the project root, and the planner/checker/verifier/synthesizer/roadmapper/debugger/mapper/classifier subagent-prompt blocks that previously hardcoded bare `.planning/...` literals now reference those fields instead; a subagent spawned into a different cwd would previously report real, already-committed files as missing. (#2376) diff --git a/.changeset/humble-zebras-zip.md b/.changeset/humble-zebras-zip.md deleted file mode 100644 index 593da8622..000000000 --- a/.changeset/humble-zebras-zip.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1919 ---- -**`phases clear` archives phase directories instead of destroying them** — at a milestone switch, committed phase directories were hard-deleted (`rmSync`) with no archive, silently losing browsable phase history (the #1447 dirty-tree guard was a no-op for the common committed case). Phase directories are now moved to `milestones/-phases/` (collision-safe; timestamp fallback when no version resolves), so history survives the switch. The #1447 uncommitted-changes guard is retained as a secondary backstop. (#1871) diff --git a/.changeset/jolly-jaguars-swim.md b/.changeset/jolly-jaguars-swim.md deleted file mode 100644 index d1ae730e6..000000000 --- a/.changeset/jolly-jaguars-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2433 ---- -**`/gsd-review` and `/gsd:ship` temp files are now scoped to a single per-run directory** — both workflows previously wrote prompt, section, and reviewer-output files to `/tmp/gsd-review-*-{phase}.*` keyed only on the bare phase number, so two projects sharing a phase number (or a crashed run's leftover file) could collide and silently feed a reviewer another project's stale content with no error; every temp path now lives under one `mktemp`-created run directory that's removed after the review completes. (#2358) diff --git a/.changeset/jolly-jays-hop.md b/.changeset/jolly-jays-hop.md deleted file mode 100644 index e820a2bf6..000000000 --- a/.changeset/jolly-jays-hop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2226 ---- -**Cross-AI review no longer silently drops the Codex/Claude/Gemini lanes on large plan sets** — the prompt-fed reviewer blocks in review.md invoked each CLI with no explicit timeout, so a slow source-grounded review was killed at the host default (~2 min) and the lane was silently lost. The workflow now directs a high Bash timeout and frames an empty output as a timeout (not the crash it was misdiagnosed as). (#2194) diff --git a/.changeset/jolly-jays-march.md b/.changeset/jolly-jays-march.md deleted file mode 100644 index 430f1cd44..000000000 --- a/.changeset/jolly-jays-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2174 ---- -**Opt-in absolute token count on the statusline context meter** — new `statusline.show_context_tokens` config (default `false`). When enabled, the meter shows the absolute context total after the percentage, e.g. "████░░░░░░ 46% (156k)", summing input, cache-creation, cache-read, and output tokens from the hook payload (a broader basis than the meter's percentage, which is derived from `used_percentage` and excludes output tokens — the two figures can diverge slightly). Default meter output is unchanged. (#2161) diff --git a/.changeset/kind-lynx-munch.md b/.changeset/kind-lynx-munch.md deleted file mode 100644 index d9190ea41..000000000 --- a/.changeset/kind-lynx-munch.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1728 ---- -**Internal: derive the non-Claude runtime list from the capability registry** — `NON_CLAUDE_RUNTIMES` is now computed from the capability registry instead of a hand-maintained literal, so it can no longer drift from the per-runtime descriptors. No user-visible behavior change (the list is identical). - - diff --git a/.changeset/kind-tigers-dart.md b/.changeset/kind-tigers-dart.md deleted file mode 100644 index 88eab7510..000000000 --- a/.changeset/kind-tigers-dart.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2309 ---- -**Runtime brand-swap no longer mislabels `` comparison tables** — every runtime installer that rebrands "Claude Code" to its own name (Cursor, Windsurf, Trae, Cline, CodeBuddy, Qwen, Hermes) also swapped it inside the runtime-comparison tables in shipped workflows, where "Claude Code" is a compared-runtime label, not a host self-reference — corrupting the comparison. Branding now protects `` regions while still rebranding genuine self-references. (#2284) diff --git a/.changeset/kind-tigers-romp.md b/.changeset/kind-tigers-romp.md deleted file mode 100644 index 7ff5f7fc5..000000000 --- a/.changeset/kind-tigers-romp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1998 ---- -**Long-running compute can now be externalized as async external jobs instead of blocking the agent turn** — a default-off external-job capability lets executors submit SLURM jobs, commit a .planning/async-jobs manifest, defer SUMMARY.md, and return external_job_waiting; the core loop already reconciles these manifests (#1165), so this adds the producer half (SLURM adapter, pure manifest module, planner/executor fragments, operation policy). (#1105) diff --git a/.changeset/lazy-lemurs-jump.md b/.changeset/lazy-lemurs-jump.md deleted file mode 100644 index dcc0f768a..000000000 --- a/.changeset/lazy-lemurs-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2477 ---- -**`check tdd.review-checkpoint` no longer silently skips TDD plans with CRLF line endings** — the frontmatter regex at `src/check-command-router.cts:751` used literal `\n` which couldn't match a CRLF PLAN.md delimiter (`---\r\n`), so a Windows-authored `type: tdd` plan was silently classified as "no type:tdd plans found" and the advisory gate short-circuited to a confident pass with no violations table. The regex now uses the same CRLF-tolerant form (`/^---\r?\n([\s\S]*?)\r?\n---/`) already in use elsewhere in the same file (line 205, `extractPlanDesignatedSections`). With `core.autocrlf=input`, the triggering CRLF was invisible to `git diff`/`git status`, so the contributor had no way to tell their plan was being misclassified. diff --git a/.changeset/lively-elks-romp.md b/.changeset/lively-elks-romp.md deleted file mode 100644 index 500fb5d0a..000000000 --- a/.changeset/lively-elks-romp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2394 ---- -**Phase verification no longer reads `stale` from filesystem timestamps alone** — staleness is now derived from git commit times instead of file mtimes, so a phase whose report declares `status: passed` stays passed across a fresh `git clone`, `cp -R`, or an unrelated `touch`/reformat, instead of being silently downgraded to `stale` by a checkout-order mtime skew. (#2348) diff --git a/.changeset/lively-hawks-caper.md b/.changeset/lively-hawks-caper.md deleted file mode 100644 index 984e4c34e..000000000 --- a/.changeset/lively-hawks-caper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 2299 ---- -**`query config-get` no longer leaks secret values or walks the prototype chain** — the `--default` fallback path printed secret-named keys (e.g. `brave_search`) in plaintext instead of masking them, and dotted-key traversal used raw property access so `config-get __proto__`/`constructor` resolved to JavaScript internals at exit 0 instead of erroring. Both absent-key resolution and traversal are now masked and own-property-gated. (#2256) diff --git a/.changeset/lively-lynx-snooze.md b/.changeset/lively-lynx-snooze.md deleted file mode 100644 index 084679130..000000000 --- a/.changeset/lively-lynx-snooze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1918 ---- -**`/gsd-progress` no longer reports a stale root milestone in workstream mode** — in a multi-workstream project with no active workstream set, `gsd-tools query init.progress` silently fell back to root `.planning/STATE.md` (often stale) and reported it confidently. It now fails safe with an actionable error naming the available workstreams and the `--ws`/`workstream set` fix, so a stale root value is never reported. Flat mode and `--ws ` are unchanged. (#1912) diff --git a/.changeset/loud-guard-hooks.md b/.changeset/loud-guard-hooks.md deleted file mode 100644 index 896759953..000000000 --- a/.changeset/loud-guard-hooks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2327 ---- -**Kilo installs now stage the shared PreToolUse guard hooks the native plugin spawns** — Kilo's capability descriptor declared both a `nativePlugin` (which spawns `gsd-prompt-guard`, `gsd-read-guard`, and `gsd-worktree-path-guard` as subprocesses) and `skipSharedHooksInstall: true` (which suppressed staging those scripts into the Kilo config dir), so every guard silently no-opped on every Kilo install. The skip flag is removed (Kilo now stages the same hooks bundle as OpenCode, whose byte-identical plugin was unaffected), and the plugin's `runHook` now warns loudly — once per hook file — when a guard script is missing instead of treating the absence as a silent allow. Resolves #2305. diff --git a/.changeset/lucky-mice-wake.md b/.changeset/lucky-mice-wake.md deleted file mode 100644 index 22426cc52..000000000 --- a/.changeset/lucky-mice-wake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2389 ---- -**The decision-coverage gate no longer fails open on unrecognized decision-ID prefixes** — `check.decision-coverage-plan` classified a populated `` block as "no trackable decisions" (a clean pass) whenever its IDs used a prefix the parser couldn't read (e.g. `D5-01` instead of `D-01`), silently skipping the gate on real decisions. The gate now recognizes any bold-lead-in decision bullet as evidence and fails loud (`could-not-parse`) when it can't read a populated block, instead of passing. (#2347) diff --git a/.changeset/lucky-quails-greet.md b/.changeset/lucky-quails-greet.md deleted file mode 100644 index 5ef8dc1ea..000000000 --- a/.changeset/lucky-quails-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1746 ---- -Windows: stop double-quoting $CLAUDE_PROJECT_DIR-anchored managed node hook paths during the #2979 legacy rewrite, which produced "\"$CLAUDE_PROJECT_DIR\"/..." and broke every node managed hook with MODULE_NOT_FOUND (PreToolUse-guard deadlock). diff --git a/.changeset/lucky-tigers-leap.md b/.changeset/lucky-tigers-leap.md deleted file mode 100644 index ee7b80a21..000000000 --- a/.changeset/lucky-tigers-leap.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: Added -pr: 1966 ---- - -**GSD now ships a repo-local VS Code extension** — a buildable extension (`vscode/extension.js` + `vscode/package.json`) that registers `gsd.invoke` (dispatches through the GSD command-routing hub) in the VS Code command palette. A reachability test proves the handler dispatches through the engine (keystone wired). Not Marketplace-published; mirrors the OpenCode plugin's bar. (#1966) diff --git a/.changeset/mellow-eagles-chatter.md b/.changeset/mellow-eagles-chatter.md deleted file mode 100644 index 673eb585d..000000000 --- a/.changeset/mellow-eagles-chatter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2468 ---- -**`/gsd-stats` and STATE.md progress no longer freeze stale `total_plans`** — the progress ratchet was applied to the whole progress record, so any single counter decreasing (e.g. `completed_plans`) froze every field including `total_plans`. Now `total_plans` always takes the freshly derived value (joining `total_phases` from #1446), so it corrects in both directions — upward when a new phase adds plans, downward when a milestone reorganization removes phases. The write-path `applyStatePreservation` also switched from wholesale block restore to per-field merge, so `state planned-phase` writes a consistent `total_plans` instead of the pre-transform stale value. diff --git a/.changeset/merry-hawks-swim.md b/.changeset/merry-hawks-swim.md deleted file mode 100644 index 9f795dd85..000000000 --- a/.changeset/merry-hawks-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2168 ---- -**phase complete now updates STATE progress on milestone-grouped roadmaps** — deriveProgressFromRoadmap parses the ## Progress table by header (column-by-name) instead of a fixed 4-column layout, so the 5-column milestone-grouped shape is no longer silently unparsed. diff --git a/.changeset/merry-mice-travel.md b/.changeset/merry-mice-travel.md deleted file mode 100644 index 544e94c8e..000000000 --- a/.changeset/merry-mice-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1738 ---- -**Honest verifier — verify-phase now abstains on non-inferable `backstop` truths instead of confidently false-passing them (#1154).** When the spec's edge-probe marks a truth non-inferable (`verification: backstop`) and the verifier cannot confirm it with explicit evidence (a passing wired held-out/property test, or a directly-observed behavior), it now reports `human_needed` with reason `insufficient_spec` ("unverified — held-out test recommended") rather than a silent `passed`. Autonomous runs complete with "N unverified non-inferable checks"; interactive runs route to the end-of-phase human checkpoint. Inferable truths are never abstained (over-abstention guard); abstention is exogenous (driven by the tag, not self-judgment). Truth-axis mirror of the prohibition judgment-tier (ADR-550 D4). diff --git a/.changeset/merry-newts-travel.md b/.changeset/merry-newts-travel.md deleted file mode 100644 index a87a5b1b8..000000000 --- a/.changeset/merry-newts-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2261 ---- -**Windows Claude Code hooks now work under PowerShell** — when Claude Code's hook runner resolves to PowerShell (not Git Bash), every GSD-installed hook failed with `Unexpected token` because the installer emitted bare quoted paths with no PowerShell call operator. The fix adds a `hookShell` parameter to the hook-command projection chain; when `hookShell='powershell'`, the `&` call operator is prepended. Default behavior (Git Bash, no prefix) is unchanged. (#2236) diff --git a/.changeset/merry-tigers-parade.md b/.changeset/merry-tigers-parade.md deleted file mode 100644 index a790c738a..000000000 --- a/.changeset/merry-tigers-parade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2193 ---- -**Discover third-party GSD Embeddable Orchestration System (EoS) integrations in a new EoS Registry.** — A non-endorsing discoverability catalog where host-integration authors register via a documentation PR; each entry declares its Host-Integration interface points, negotiated axes, and protocol version, with a live release badge and a per-entry GitHub Discussion for ranking and comments. (#2193) diff --git a/.changeset/nimble-ibex-tumble.md b/.changeset/nimble-ibex-tumble.md deleted file mode 100644 index d9665dbae..000000000 --- a/.changeset/nimble-ibex-tumble.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1922 ---- -Document Claude Code's advisor-tool inheritance in the model-profiles reference: the session-level advisor is inherited by all GSD subagents and composes with per-agent tiering, with candidate executor/advisor pairings, when it is worth enabling, and the session-level (no per-agent control) constraint. - - diff --git a/.changeset/nimble-jays-roar.md b/.changeset/nimble-jays-roar.md deleted file mode 100644 index 104f03d4d..000000000 --- a/.changeset/nimble-jays-roar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1861 ---- -GSD Core ships a `.claude-plugin/marketplace.json` marketplace manifest so Claude-plugin-compatible runtimes (ZCODE et al.) can discover and install gsd-core from a custom marketplace source. Additive — the existing `.claude-plugin/plugin.json` and the Claude Code install path are unchanged. The catalog version (`plugins[0].version`) tracks `package.json` via the release version-sync. diff --git a/.changeset/nimble-ravens-dart.md b/.changeset/nimble-ravens-dart.md deleted file mode 100644 index f854ef145..000000000 --- a/.changeset/nimble-ravens-dart.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2300 ---- -**`/gsd-debug` now auto-resumes instead of stopping mid-investigation** — when the debug session-manager's own turn ended before the investigation was complete, the orchestrator treated the intermediate progress summary as completion and returned control to the user. It now recognizes a non-terminal `CONTINUE_REQUIRED` return, auto-resumes from the on-disk checkpoint, and only stops for genuine terminal conditions (with a no-progress anti-loop guard). (#2257) diff --git a/.changeset/nimble-yaks-climb.md b/.changeset/nimble-yaks-climb.md deleted file mode 100644 index bf75a33b5..000000000 --- a/.changeset/nimble-yaks-climb.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2332 ---- -**Installing a non-Claude runtime no longer breaks Claude's model resolution in no-project sessions** — the installer writes `resolve_model_ids:"omit"` for non-alias runtimes into the machine-wide `~/.gsd/defaults.json`, which any runtime read back, so install order silently flipped Claude's adaptive tier aliases (executor→sonnet, planner→opus) to an empty model string. Resolution is now scoped to the runtime actually resolving, via a per-install `.gsd-runtime` marker: Claude ignores a global-defaults omit and keeps its tier aliases, non-alias runtimes still omit, and an explicit project-level `omit`/`true` is always honored. (#2297) diff --git a/.changeset/noble-elks-chatter.md b/.changeset/noble-elks-chatter.md deleted file mode 100644 index b988337b9..000000000 --- a/.changeset/noble-elks-chatter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2443 ---- -**`check.decision-coverage-plan` no longer false-blocks on decisions cited in ``/``/``/``/``** — the gate scanned only ``/``/``/`` tag bodies while its remediation message claimed "(or body)". A decision faithfully cited in any of the five other planner-canonical tags (the natural place for "read this CONTEXT decision before editing" pointers, verification steps, acceptance criteria, etc.) was reported as uncovered with a misleading fix-hint that sent the fixer to "the body" — where a re-citation still failed. The scan now covers all nine planner-canonical tag bodies AND the message names the surfaces it actually scans, so message and behavior cannot drift apart again. (#2372) diff --git a/.changeset/noble-foxes-purr.md b/.changeset/noble-foxes-purr.md deleted file mode 100644 index e53da8a32..000000000 --- a/.changeset/noble-foxes-purr.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2051 ---- -**`capability state` and `loop render-hooks` now accept `--runtime` to override the auto-detected runtime** — previously both commands parsed only `--config-dir`, so the runtime config dir was derived from the persisted `.planning/config.json` runtime (precedence `GSD_RUNTIME` → `config.runtime` → `claude`). A repo that persisted `runtime:"codex"` resolved the config dir to `~/.codex`, where the Claude skill isn't installed, so every skill-bearing capability reported `surfaced:false` and `execute:post`/`verify:post` hooks silently no-op'd when the operator drove GSD from Claude Code. `--runtime ` (canonicalized, so aliases like `codex-app` work) now bypasses that fallback so the config dir resolves to the explicitly-named runtime's home. Behavior without the flag is unchanged. (#2003) diff --git a/.changeset/noble-newts-roam.md b/.changeset/noble-newts-roam.md deleted file mode 100644 index 8362aeccc..000000000 --- a/.changeset/noble-newts-roam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2478 ---- -**`/gsd` now registers on pi** — installing GSD for pi wrote its extension as `gsd.cjs`, a suffix pi's extension auto-discovery skips silently, so `/gsd` never appeared and nothing reported an error. The extension now installs as `gsd.js`, and upgrading removes the stale `gsd.cjs`. (#2470) diff --git a/.changeset/noble-wasps-greet.md b/.changeset/noble-wasps-greet.md deleted file mode 100644 index c89e3b5ca..000000000 --- a/.changeset/noble-wasps-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2234 ---- -**`phase complete` no longer false-reports REQ-IDs as missing when the traceability table leads with a status column** — the parser required the REQ-ID in the first column, so a table shaped `| ☐ | REQ-01 | …` matched zero rows and every body REQ-ID was reported missing. It now matches REQ-IDs in any column. (#2203) diff --git a/.changeset/patient-geese-howl.md b/.changeset/patient-geese-howl.md deleted file mode 100644 index 8a1bb8eb3..000000000 --- a/.changeset/patient-geese-howl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1584 ---- -**Extraction discipline for strict-format agents (LLM-playbook principle 8)** — gsd-doc-classifier and gsd-doc-synthesizer apply taxonomy/precedence rules directly without inventing content, reducing reasoning-induced format drift. Based on arXiv 2504.05081 (few-shot beats CoT for pattern tasks), 2506.00069 (terminal instruction placement), 2505.14810, 2505.11423. diff --git a/.changeset/patient-mice-greet.md b/.changeset/patient-mice-greet.md deleted file mode 100644 index efd8cba58..000000000 --- a/.changeset/patient-mice-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1843 ---- -**`init milestone-op` now ignores backlog `999.x` headings when counting milestone phases** — parked backlog items no longer inflate `phase_count` or pin `all_phases_complete` false for an otherwise finished milestone. (#1843) diff --git a/.changeset/patient-otters-wave.md b/.changeset/patient-otters-wave.md deleted file mode 100644 index a6800caef..000000000 --- a/.changeset/patient-otters-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1735 ---- -**Internal: extracted the runtime-artifact install engine from `bin/install.js`** — `installRuntimeArtifacts`/`uninstallRuntimeArtifacts`/`installOpencodeFamilySkills` and their helpers now live in a dedicated `gsd-core/bin/lib/install-engine.cjs` module (ADR-1239 Phase B), so adapters can import the install pipeline instead of reaching into the 12k-line installer. Install output is byte-identical for all 16 runtimes (golden-parity asserted); no user-facing behaviour change. diff --git a/.changeset/patient-voles-chatter.md b/.changeset/patient-voles-chatter.md deleted file mode 100644 index f26c07e8e..000000000 --- a/.changeset/patient-voles-chatter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2010 ---- -**MemPalace `memory_mode` `kg_backend` and `replace` are now functional** — selecting either mode now routes recall through the palace instead of silently behaving like `augment`: `kg_backend` treats the palace temporal KG as the primary knowledge-graph source (native `.planning/graphs/` as fallback), and `replace` resolves recall through the palace as the source of truth. Every mode stays default-resilient — an unreachable palace falls back to native memory and no memory is lost. (#2010) diff --git a/.changeset/phase-id-redos-hardening.md b/.changeset/phase-id-redos-hardening.md deleted file mode 100644 index df9878105..000000000 --- a/.changeset/phase-id-redos-hardening.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 2141 ---- -**Hardened phase/roadmap/plan markdown parsing against quadratic-time (ReDoS) CPU exhaustion** — a crafted `ROADMAP.md`, `STATE.md`, or `PLAN.md` with large runs of unclosed `(`, `[`, ``, ` diff --git a/.changeset/plucky-sloths-forage.md b/.changeset/plucky-sloths-forage.md deleted file mode 100644 index e69b9210d..000000000 --- a/.changeset/plucky-sloths-forage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2224 ---- -**`state update-progress` no longer mangles the frontmatter and discards the progress suffix** — its Progress: regex matched the raw STATE.md including frontmatter, so the YAML `progress:` key was hit first (corrupting the frontmatter) while the body line stayed stale and was silently reverted on the next write, and any descriptive suffix after the progress bar was destroyed. It now targets the body line only and preserves the suffix. (#2177) diff --git a/.changeset/plucky-wasps-sprint.md b/.changeset/plucky-wasps-sprint.md deleted file mode 100644 index c0a10e0cb..000000000 --- a/.changeset/plucky-wasps-sprint.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2210 ---- -**GSD now drives VS Code through the Embeddable Orchestration System** — the VS Code extension is rewired through the negotiated imperative Host-Integration adapter (active `vscode.lm` model, engine hook bus, sandboxed storage), gains native Language Model Tools (GSD skills as `#gsd-*` tools) and `#runSubagent` dispatch, and runs as a Web Extension (no Node APIs). (#2103) diff --git a/.changeset/plucky-yaks-roar.md b/.changeset/plucky-yaks-roar.md deleted file mode 100644 index 21234eb73..000000000 --- a/.changeset/plucky-yaks-roar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2451 ---- -**`/gsd-plan-review-convergence` no longer silently overrides configured reviewers with Codex** — a bare invocation (no reviewer flags) now respects `review.default_reviewers` (and, transitively, `review.reviewer_instances`) per ADR-0011/ADR-0015, instead of always injecting `--codex` and bypassing the configured default. Users without `review.default_reviewers` configured still get `--codex` as before. The startup banner now shows what will actually run. diff --git a/.changeset/plucky-zebras-jump.md b/.changeset/plucky-zebras-jump.md deleted file mode 100644 index 4e59eb443..000000000 --- a/.changeset/plucky-zebras-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2217 ---- -**`/gsd-ship` no longer silently drops the ship-status note from STATE on merge** — the track_shipping step committed the STATE ship-note after creating the PR but never pushed it, so on a fast merge the note stayed local-only and never reached the default branch. The ship-note is now pushed onto the PR branch with a `[ci skip]` trailer so it lands on merge without a redundant pipeline. (#2138) diff --git a/.changeset/proud-bears-purr.md b/.changeset/proud-bears-purr.md deleted file mode 100644 index d59c07316..000000000 --- a/.changeset/proud-bears-purr.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1798 ---- -**`/gsd:next` smart-entry workflow** — adds a state-aware entry point that classifies the current project situation (no-project, blocked, verify-failed, planning, executing, verify-pending, complete, and more) and recommends the right next GSD command. The `gsd-tools smart-entry [--json]` classifier handles phase ordering including decimal phase IDs; the `/gsd:next` skill surfaces the workflow with tiered fallback behavior. diff --git a/.changeset/proud-bears-roam.md b/.changeset/proud-bears-roam.md deleted file mode 100644 index 69728b6ee..000000000 --- a/.changeset/proud-bears-roam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1923 ---- -OpenCode now runs GSD's lifecycle safety hooks (prompt-injection guard, read-before-edit guard, injection scanner, worktree/workflow guards, context monitor) via a native plugin installed to `~/.config/opencode/plugins/gsd-core.js`. OpenCode declares `hooksSurface: 'none'`, so these hooks were previously inert; the plugin bridges OpenCode's event bus onto GSD's existing hook scripts. Installed automatically by `npx @opengsd/gsd-core --opencode` and removed on uninstall. diff --git a/.changeset/proud-cranes-click.md b/.changeset/proud-cranes-click.md deleted file mode 100644 index 81133bff2..000000000 --- a/.changeset/proud-cranes-click.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2173 ---- -**Long-context model names render compactly in the statusline** — the verbose " (1M context)" suffix Claude Code appends to the model display name now collapses to a compact " (1M)" badge (tolerant of future window sizes and the abbreviated "ctx" variant: "(500K context)" → "(500K)", "(1M ctx)" → "(1M)"). Lossless — the long-context signal stays, the 12 characters of width don't. (#2160) diff --git a/.changeset/proud-geese-caper.md b/.changeset/proud-geese-caper.md deleted file mode 100644 index d925cf412..000000000 --- a/.changeset/proud-geese-caper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2227 ---- -**`/gsd-debug` no longer stalls on a phantom background handoff** — the orchestrator treated the foreground session-manager spawn as a background task and queried its agent ID via TaskOutput (which needs a task ID), then waited on a handoff that was never queryable. The workflow now states the spawn is foreground/blocking, forbids passing an agent ID to TaskOutput, and gives a lost-handoff recovery path. (#2196) diff --git a/.changeset/proud-rams-greet.md b/.changeset/proud-rams-greet.md deleted file mode 100644 index ac8930ac3..000000000 --- a/.changeset/proud-rams-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1845 ---- -**Roadmap phase lookup now ignores fenced examples and the backlog sentinel lane** — `roadmap get-phase` and `init plan-phase` no longer return fenced sample headings as real phases or treat `999.x` backlog items as active milestone work. (#1845) diff --git a/.changeset/proud-ravens-jump.md b/.changeset/proud-ravens-jump.md deleted file mode 100644 index 94beacdfd..000000000 --- a/.changeset/proud-ravens-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2229 ---- -**`phase complete` no longer checks the wrong ROADMAP checkbox or writes the plan count into a shipped milestone** — the roadmap mutators ran unanchored and un-milestone-scoped, so they could flip a bullet inside a backticked prose literal or a Backlog entry instead of the closing phase's, and write the plan count into a same-numbered phase in a shipped milestone. The checkbox flip is now line-anchored and both writers are scoped to the current milestone. (#2200) diff --git a/.changeset/proud-zebras-bark.md b/.changeset/proud-zebras-bark.md deleted file mode 100644 index 15e16ad21..000000000 --- a/.changeset/proud-zebras-bark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2175 ---- -**Opt-in compact GSD-state statusline format** — new `statusline.state_format` config, enum `full`|`compact` (default `full`, the existing rendering). `compact` renders " · P/ · " (e.g. "v1.12 · P7/12 · executing"), dropping the milestone name and progress bar and collapsing narrative statuses to the canonical vocabulary from `normalizeStateStatus()` — the canonical stuck state `paused` renders uppercase as `PAUSED`. Solves the unbounded-width problem where free-text status sentences push the context meter off the line. (#2162) diff --git a/.changeset/quick-elks-climb.md b/.changeset/quick-elks-climb.md deleted file mode 100644 index d1c83556f..000000000 --- a/.changeset/quick-elks-climb.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2317 ---- -**`audit-uat` no longer reports a false-clean `total_items: 0` when real items exist** — the parsers ignored two artifact shapes: a `## Gaps` section recording open findings, and verification items declared in frontmatter (`human_verification:` array) or as `### N.`+bold-paragraph blocks. audit-uat now surfaces unresolved `## Gaps` entries and reads the frontmatter array / heading shape, so a phase with outstanding UAT/verification work is no longer waved through as clean. (#2286) diff --git a/.changeset/quick-hawks-bark.md b/.changeset/quick-hawks-bark.md deleted file mode 100644 index ec7a8af7f..000000000 --- a/.changeset/quick-hawks-bark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2422 ---- -**`` task element (Design by Contract)** — plans may now declare a runnable/checkable fact a task assumes (env var set, prior-phase artifact present, external-setup done) that plan ordering does not guarantee; the executor asserts it before running the task and halts with a checkpoint on unmet instead of building on a broken assumption. Plans that omit `` behave exactly as today. (#1949) diff --git a/.changeset/quick-ibex-bark.md b/.changeset/quick-ibex-bark.md deleted file mode 100644 index aea89b137..000000000 --- a/.changeset/quick-ibex-bark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2314 ---- -**`claude_orchestration.enabled: true` now actually routes execute-phase waves through the Workflow backend** — the capability shipped registered-but-inert: nothing in `/gsd-execute-phase` ever called its backend detection, and the `execute:wave:pre` hook it needed was declared but never rendered, so enabling it had zero effect. execute-phase now renders `execute:wave:pre` before each wave and, when the capability is enabled and all gates pass, dispatches independent plans via the generated Workflow script; any gate miss or disabled config falls back to byte-identical inline dispatch. (#2285) diff --git a/.changeset/quick-seals-parade.md b/.changeset/quick-seals-parade.md deleted file mode 100644 index 37b152184..000000000 --- a/.changeset/quick-seals-parade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2139 ---- -**`roadmap get-phase` resolves project-code-prefixed headings by bare number** — a bare-number query (e.g. `29`) now resolves a drifted `### Phase AB-29:` heading, matching the internal resolver used by `init.phase-op`; previously the CLI returned empty. A bare sibling (`### Phase 29:`) still takes precedence. A project-code-prefixed heading present only as a summary/checklist line (no matching detail section) now reports a `malformed_roadmap` diagnostic — for both prefixed and bare-number queries — instead of a silent empty result. (#2114) diff --git a/.changeset/rapid-elks-rest.md b/.changeset/rapid-elks-rest.md deleted file mode 100644 index 98a3a1adb..000000000 --- a/.changeset/rapid-elks-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2299 ---- -**`query config-get` now returns capability-registry defaults for absent keys** — keys declared with a default in the capability registry (e.g. `workflow.security_enforcement`, which defaults to `true`) previously reported "Key not found" (exit 1) when missing from config.json, diverging from the runtime's own resolver and letting `... || echo false` guards silently read the security gate as disabled. config-get now resolves these through the same registry defaults the runtime uses. (#2256) diff --git a/.changeset/rapid-jays-bark.md b/.changeset/rapid-jays-bark.md deleted file mode 100644 index fe1667cde..000000000 --- a/.changeset/rapid-jays-bark.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2458 ---- -**Config-gated provider escalation when a run hits a quota or rate limit** — an executor killed by a provider throttle stopped the phase and waited for a manual restart; escalating a tier did not help because the same throttled provider was still in play. Set `dynamic_routing.provider_escalation` to an ordered list of fallback model IDs and GSD now switches provider on a quota-exceeded failure, logs the swap (`sonnet → gpt-5`), honors the provider's `Retry-After`, caps the walk at `max_escalations`, and names every model tried once the list is spent. Opt-in — unset, quota failures keep today's manual recovery prompt. (#2296) diff --git a/.changeset/rapid-orcas-sing.md b/.changeset/rapid-orcas-sing.md deleted file mode 100644 index 1689b63e7..000000000 --- a/.changeset/rapid-orcas-sing.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1934 ---- -**Lazy-split `plan-phase.md` into a `steps/` directory** — ~4.7 KB lighter eager context per `/gsd-plan-phase` call via byte-invariant progressive disclosure (ADR-1610). (#1852) - - diff --git a/.changeset/rapid-pumas-click.md b/.changeset/rapid-pumas-click.md deleted file mode 100644 index 6b057bcb7..000000000 --- a/.changeset/rapid-pumas-click.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1917 ---- -**`milestone complete --ws` now archives into the workstream instead of root** — the archive paths (MILESTONES.md, the milestones/ archive dir, and the per-version MILESTONE-AUDIT.md) were hardcoded to root `.planning/`, so a workstream milestone close scattered its artifacts into root and never produced a workstream-local archive. They now derive from the workstream-aware planning base (`planningPaths(cwd).planning`); flat-mode (no --ws) is unchanged. (#1911) diff --git a/.changeset/serene-birds-rest.md b/.changeset/serene-birds-rest.md deleted file mode 100644 index b5ecf5a08..000000000 --- a/.changeset/serene-birds-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1946 ---- -**Host-integration descriptors now carry an `extensionEvents` vocabulary** — the extension-system event surface (OpenCode, pi) is a separate descriptor field from managed `hookEvents`, so OpenCode declares `extensionEvents:opencode` without conflicting with the hooksSurface:none invariant. (#1946) diff --git a/.changeset/serene-herons-rally.md b/.changeset/serene-herons-rally.md deleted file mode 100644 index 2f2356975..000000000 --- a/.changeset/serene-herons-rally.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2338 ---- -**`/gsd:new-milestone --ws ` no longer overwrites the shared PROJECT.md milestone heading** — in workstream mode the shared `.planning/PROJECT.md` had its `## Current Milestone` heading rewritten with one workstream's milestone, so with parallel workstreams whichever ran last silently won the shared heading. The milestone-state write in Step 4 is now skipped when a workstream is active, and the commit no longer stages PROJECT.md. The `--ws` flag is also now parsed into `${GSD_WS}`, which previously expanded to empty and silently dropped workstream scope from the suggested next-step routing hints. diff --git a/.changeset/serene-koalas-hum.md b/.changeset/serene-koalas-hum.md deleted file mode 100644 index df6fe75eb..000000000 --- a/.changeset/serene-koalas-hum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2324 ---- -**The context-monitor hook no longer fails Codex's Stop hook** — GSD wires `gsd-context-monitor` to Codex lifecycle events including `Stop`, but the hook emitted a `hookSpecificOutput.additionalContext` envelope that Codex's Stop schema rejects ("hook returned invalid stop hook JSON output") exactly when context was low. The hook now emits that envelope only for context-injection events (PostToolUse / AfterTool) and exits silently for Stop and every other lifecycle event, while its debounce and critical-session bookkeeping still run. (#2289) diff --git a/.changeset/serene-lemurs-march.md b/.changeset/serene-lemurs-march.md deleted file mode 100644 index 8f2b0a678..000000000 --- a/.changeset/serene-lemurs-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 1868 ---- -**GSD subagents now self-load configured agent_skills regardless of orchestrator bash** — projects that map skills via `.planning/config.json` `agent_skills.` no longer silently lose them on `/gsd-autonomous` or Cursor, where `Skill()`-delegated workflow bash init did not reliably run. Each of the 22 consumer agents queries its own type at init and reads the listed skills, with a dedup guard so runtimes that also inject orchestrator-side (Claude Code) never carry two copies. (#1866) diff --git a/.changeset/sharp-otters-romp.md b/.changeset/sharp-otters-romp.md deleted file mode 100644 index 24193c9cc..000000000 --- a/.changeset/sharp-otters-romp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1766 ---- -**`/gsd-review` now supports custom reviewer instances** — run one model-capable adapter (e.g. OpenCode) as several independent reviewer identities via a bounded `review.reviewer_instances` config, so two different models can review in a single pass without manually swapping config or hand-merging REVIEWS.md. (#1517) diff --git a/.changeset/silly-moles-romp.md b/.changeset/silly-moles-romp.md deleted file mode 100644 index b8f463969..000000000 --- a/.changeset/silly-moles-romp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2183 ---- -**Opt-in git branch and working-state segment in the statusline** — the shell prompt's branch/dirty-state signal is hidden for the whole session under the Claude Code TUI, so wrong-branch commits and ship-time push rejections surface only after the fact. New `statusline.show_git` config (default `false`) renders the branch name plus staged/unstaged/untracked/ahead/behind markers (or ✓ when clean and in sync) after the directory segment. When disabled, no git subprocess is spawned and output is unchanged. (#2163) diff --git a/.changeset/silly-pandas-gather.md b/.changeset/silly-pandas-gather.md deleted file mode 100644 index 075f7e276..000000000 --- a/.changeset/silly-pandas-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2248 ---- -**`phase complete` now reads milestone-grouped ROADMAP progress tables** — progress reported 0% on projects whose Progress table carries a Milestone column, because the reader assumed a fixed column position; it now resolves progress columns by name so both flat and milestone-grouped tables work (#2137). Quick Tasks logging via `/gsd:fast` also appends schema-correct, lock-safe rows instead of guessing the column count in shell (#2133). (#2248) diff --git a/.changeset/silly-sloths-dart.md b/.changeset/silly-sloths-dart.md deleted file mode 100644 index 8e8336d81..000000000 --- a/.changeset/silly-sloths-dart.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2375 ---- -**Managed hooks no longer break after a volta node upgrade or prune** — on machines using volta to manage Node, the installer baked a version-pinned node path into every managed hook command. Once volta pruned that node version, every hook failed to spawn with `No such file or directory` at the start of each session, until the installer was re-run. Hook commands now resolve through volta's stable shim, which survives version changes. (#2335) diff --git a/.changeset/silly-voles-snooze.md b/.changeset/silly-voles-snooze.md deleted file mode 100644 index 579a4a7c4..000000000 --- a/.changeset/silly-voles-snooze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2381 ---- -**Todo severity is now captured and surfaced end-to-end** — `/gsd-capture` (add-todo) now confirms a severity (blocker/major/minor/cosmetic) before writing a todo instead of silently omitting it, and `gsd-tools list-todos` / `init todos` now include the `severity` field in their JSON output (omitted for older todos that have none), so a backlog can be triaged by severity instead of by re-reading every file. (#2337) diff --git a/.changeset/steady-ibex-run.md b/.changeset/steady-ibex-run.md deleted file mode 100644 index bf1b37a3b..000000000 --- a/.changeset/steady-ibex-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2049 ---- -**Skill-bearing capabilities now surface correctly on flat command-layout installs** — on an install using the flat `commands/gsd-.md` source layout (e.g. a Claude Code local project install with no `commands/gsd/` subdir), every skill-bearing capability (`nyquist`, `code-review`, `security`, `ui`, `mempalace`, `ai-integration`, `profile-pipeline`) was silently reported `surfaced:false`/`enabled:false`/`active:false`, so their loop hooks (`verify:post`, `execute:post`, etc.) never fired even with the corresponding `workflow.*` toggle on. The skill-manifest resolver now detects the flat layout and produces the same stems the nested `commands/gsd/*.md` loader does. (#1858) diff --git a/.changeset/steady-lemurs-run.md b/.changeset/steady-lemurs-run.md deleted file mode 100644 index 08367a2ae..000000000 --- a/.changeset/steady-lemurs-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2302 ---- -**Claude Code installs now pre-approve `.planning/` and `STATE.md` writes** — the installer wrote `Write(.planning/*)`/`Write(STATE.md)` permission rules, but Claude Code has no standalone `Write` gate (file edits are gated via `Edit(pattern)`), so those rules never matched and every fresh install still hit first-run approval prompts (and a session-start warning). The installer now writes `Edit(...)` rules and migrates the stale `Write(...)` entries away on the next run. (#2278) diff --git a/.changeset/steady-lynx-fly.md b/.changeset/steady-lynx-fly.md deleted file mode 100644 index ef8bc0678..000000000 --- a/.changeset/steady-lynx-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2253 ---- -**Roadmap, requirements, and state table edits are confined to the right table** — the last ad-hoc table writers (phase completion updating roadmap progress, `requirements mark-complete`, and `state record-metric`/velocity) now route through the shared markdown-table seam, so a stray decoy table elsewhere in a document can no longer swallow a phase-progress update, a single ragged neighbouring row no longer silently aborts the whole edit, and per-plan metric recording no longer drops trailing section content or duplicates the section. (#2253) diff --git a/.changeset/steady-mice-frolic.md b/.changeset/steady-mice-frolic.md deleted file mode 100644 index d5bb4f8d6..000000000 --- a/.changeset/steady-mice-frolic.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1994 ---- -**`/gsd:onboard` guides brownfield setup** — existing repos now have a top-level onboarding command that routes through codebase mapping, docs ingest, project initialization, and an onboarding summary without silently overwriting planning files. diff --git a/.changeset/sturdy-cranes-jump.md b/.changeset/sturdy-cranes-jump.md deleted file mode 100644 index 629dcee99..000000000 --- a/.changeset/sturdy-cranes-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2340 ---- -**Installed third-party capability skills now materialize as real slash commands** — a capability could pass every check (`installed: true, surfaced: true, active: true`) and still never exist on disk: the registry layer counted the capability's skill as surfaced, but the file-copy step only ever scanned gsd-core's own bundled commands, so nothing was ever written to the runtime's `skills/` directory and the command was never invocable. Installed capability skills are now staged from where they live, bound to the capability that actually declared and registered them (never inferred from directory listing order), and are subject to the same runtime-targeted body rewrites as first-party skills — first-party skills still win any name collision. diff --git a/.changeset/sturdy-goats-parade.md b/.changeset/sturdy-goats-parade.md deleted file mode 100644 index af459e4db..000000000 --- a/.changeset/sturdy-goats-parade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2325 ---- -**`/gsd:plan-review-convergence` can now use the Antigravity CLI reviewer** — its reviewer-flag whitelist predated the 1.7.0 Antigravity adapter and silently dropped `--agy`/`--antigravity`, so convergence fell back to `--codex` only and the working adapter was unreachable (especially after Gemini CLI's upstream shutdown). Both flags are now recognized and passed through to `/gsd-review` unchanged. (#2293) diff --git a/.changeset/sturdy-ibex-jump.md b/.changeset/sturdy-ibex-jump.md deleted file mode 100644 index 6e4f40a0e..000000000 --- a/.changeset/sturdy-ibex-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2437 ---- -**`npm run lint:ci` (and every npm script banner) on `next` and feature branches cut from `next` no longer reports a stale pre-release version after a final release** — the release pipeline's `finalize` job shipped `X.Y.0` to npm `latest` but never bumped `next` to match, so `next` carried the last `rc.N` placeholder indefinitely (observed: `1.7.0-rc.6` lingering after `1.7.0` shipped). The `finalize` job now runs `scripts/sync-next-version.cjs` — the same step the `rc` job already ran — keeping `next` at the last published release for every release type as `scripts/sync-next-version.cjs:6-9` always promised. (#2423) diff --git a/.changeset/sturdy-jays-tumble.md b/.changeset/sturdy-jays-tumble.md deleted file mode 100644 index 68b57ca47..000000000 --- a/.changeset/sturdy-jays-tumble.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2473 ---- -**`verify plan-structure` no longer false-flags checkpoint tasks for missing ``/``/``** — every `` was reported as a structural error because the verifier unconditionally required the auto-task fields. It now branches on the task's `type` attribute: `checkpoint:human-verify` requires its canonical triple (``/``/``), `checkpoint:decision` requires ``/``/``, `checkpoint:human-action` requires ``/``/``/`` (per `gsd-core/references/checkpoints.md`), and unknown `checkpoint:*` subtypes require only the universal ``. Non-checkpoint tasks keep the historical ``/``/``/`` requirements unchanged. diff --git a/.changeset/sturdy-lemurs-forage.md b/.changeset/sturdy-lemurs-forage.md deleted file mode 100644 index 9a70a6269..000000000 --- a/.changeset/sturdy-lemurs-forage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2309 ---- -**Hermes installs now project named-agent dispatch onto `delegate_task` instead of asserting a nonexistent `Agent` tool** — installed Hermes workflows brand-swapped "Claude Code"→"Hermes Agent" but kept literal `Agent(...)` calls and falsely claimed "The Agent tool IS available", which Hermes doesn't expose. A Hermes `.md` converter now rewrites named dispatch onto Hermes's `delegate_task` contract (embedding the resolved role prompt since Hermes has no named-agent lookup, mapping background dispatch, dropping unsupported per-call model), driven by the runtime's documented dispatch facts, and fails closed if a referenced role prompt is missing. (#2284) diff --git a/.changeset/sturdy-pumas-snooze.md b/.changeset/sturdy-pumas-snooze.md deleted file mode 100644 index 9ee20d115..000000000 --- a/.changeset/sturdy-pumas-snooze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2339 ---- -**`phase complete` no longer silently drops requirement IDs the roadmap cites but REQUIREMENTS.md never defined** — completing a phase whose `**Requirements**:` line named an unregistered REQ-ID reported `requirements_updated: true` with zero warnings while the file was left byte-for-byte unchanged, indistinguishable from a run that wrote everything. Ghost IDs now raise a warning, `requirements_updated` reflects whether a write actually landed, an active heading like `## v1 Requirements` is no longer mistaken for a deferred section, and a phase whose every cited ID is unregistered still reports its missing-requirement rows instead of "No requirements or decisions to check." diff --git a/.changeset/sturdy-seals-fly.md b/.changeset/sturdy-seals-fly.md deleted file mode 100644 index 798b1daa6..000000000 --- a/.changeset/sturdy-seals-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2442 ---- -**`~/.gsd/defaults.json` no longer silently drops `model_policy`, `model_profile_overrides`, and `runtime`** — the global-defaults path of config load now forwards these three keys identically to a project's `.planning/config.json`, so a machine-wide model policy / runtime / overrides specified globally is honored even outside a project. (#2069) diff --git a/.changeset/sturdy-voles-dart.md b/.changeset/sturdy-voles-dart.md deleted file mode 100644 index 608c1b962..000000000 --- a/.changeset/sturdy-voles-dart.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1800 ---- -**Internal: install/uninstall runtime labels are now sourced from a single `getRuntimeLabel` lookup** — the two duplicated `runtimeLabel` assignment chains in `bin/install.js` (uninstall + install) are collapsed into one curated label table in `runtime-name-policy.cts`, sibling to the registry-derived `getDirName` (ADR-1239 Phase B, #1679). Install output is byte-identical for all 16 runtimes (golden-parity asserted). Two console-label inconsistencies are normalized as a side effect: `kimi` shows 'Kimi CLI' in both sites, and `cline` uninstall no longer falls through to 'Claude Code'. - - diff --git a/.changeset/sturdy-voles-tumble.md b/.changeset/sturdy-voles-tumble.md deleted file mode 100644 index 0a6c36ead..000000000 --- a/.changeset/sturdy-voles-tumble.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2250 ---- -**ROADMAP phase edits can no longer escape their section** — completing a phase updated its plan count and per-plan checkboxes with whole-document regexes that could bleed into a neighbouring phase; those per-phase writes are now structurally bounded to the phase own section via a new `withSection` / `withPhaseSection` seam (#2130, #2067, #2080). (#2250) diff --git a/.changeset/sturdy-wasps-run.md b/.changeset/sturdy-wasps-run.md deleted file mode 100644 index 6e7a17db1..000000000 --- a/.changeset/sturdy-wasps-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2447 ---- -**`close_phase_todos` no longer leaves moved todos as phantom unstaged deletions in `git status`** — the workflow step moved resolved todos from `.planning/todos/pending/` to `.planning/todos/completed/` with a plain `mv`, then committed by listing only the destination directory in `--files`. Git's index still tracked the moved file at its old `pending/` path, so the deletion was never staged and the moved-away file lingered as an unstaged deletion in `git status` until some later broad `git add -A` happened to catch it. The step's commit `--files` list now includes BOTH directories so `git add .planning/todos/pending/` stages the deletion atomically with the new `completed/` copy in the same commit. (#2415) diff --git a/.changeset/sturdy-wolves-gather.md b/.changeset/sturdy-wolves-gather.md deleted file mode 100644 index ec4efcef9..000000000 --- a/.changeset/sturdy-wolves-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2253 ---- -**STATE.md `## Session` fields now resolve on Windows** — the session-section reader used a `\n`-only heading regex that silently failed on a CRLF `## Session` heading, nulling all session state on Windows checkouts; it now reads through the CRLF-safe section seam. (#2253) diff --git a/.changeset/sturdy-yaks-caper.md b/.changeset/sturdy-yaks-caper.md deleted file mode 100644 index f453fcf0d..000000000 --- a/.changeset/sturdy-yaks-caper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2228 ---- -**Bullet/em-dash ROADMAP phases no longer resolve to `Phase null`** — the roadmap phase lookup matched only ATX headings with a colon, so a bullet entry like `- [ ] **Phase N — Name**` (which the roadmapper emits) failed to resolve and `Phase null` landed in STATE.md; a bullet-only ROADMAP also broke the milestone phase count. Phase lookup and the milestone filter now accept bullet/checkbox entries with an em-dash/en-dash/hyphen/colon separator. (#2199) diff --git a/.changeset/tidy-badgers-caper.md b/.changeset/tidy-badgers-caper.md deleted file mode 100644 index e94bdb89c..000000000 --- a/.changeset/tidy-badgers-caper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2225 ---- -**Linuxbrew users no longer lose all GSD-managed hooks after `brew upgrade node`** — normalizeNodePath only recognized macOS Homebrew Cellar paths, so on Linux the version-pinned node path stayed baked into hook commands and 404'd after a node bump (and reinstall couldn't repair it). It now rewrites any Homebrew Cellar path — Intel, Apple Silicon, Linuxbrew, custom HOMEBREW_PREFIX — to the stable `/bin/node` symlink. (#2185) diff --git a/.changeset/tidy-bears-swim.md b/.changeset/tidy-bears-swim.md deleted file mode 100644 index a20786cd2..000000000 --- a/.changeset/tidy-bears-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2131 ---- -**`milestone complete` no longer corrupts the recorded phase** — closing a milestone (e.g. `v0.5`) previously overwrote `current_phase` in STATE.md with the version's minor digit, and a follow-up `state complete-phase` mined a bogus `0.5` token and rewrote the file; phase resolution is now anchored so the real phase is preserved and a milestone-closure line is rejected. (#2111) diff --git a/.changeset/tidy-elks-sing.md b/.changeset/tidy-elks-sing.md deleted file mode 100644 index 3a5ca61c0..000000000 --- a/.changeset/tidy-elks-sing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2260 ---- -**Headless MemPalace capture no longer fails silently** — the headless invocation `mempalace mine --wing --room ` used a `--room` flag that does not exist on the `mine` subcommand (only `search` accepts `--room`), causing every headless/no-MCP capture run to fail with `unrecognized arguments: --room` and silently skip (onError: skip). The fix replaces the flag with MemPalace's documented room-assignment mechanism: stage the artifact under a room-named subfolder with a `mempalace.yaml` taxonomy so `detect_room()` assigns it via folder-path match. (#2220) diff --git a/.changeset/tidy-goats-hop.md b/.changeset/tidy-goats-hop.md deleted file mode 100644 index 12d5df8ae..000000000 --- a/.changeset/tidy-goats-hop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2312 ---- -**Codex agents no longer fail to launch with an unsupported-model error** — GSD was writing an Anthropic tier name (`opus`/`sonnet`/`haiku`/`fable`) or a `claude-*` id into each Codex agent's `.toml` `model` field, which Codex rejects — fatally on a ChatGPT account (`The 'sonnet' model is not supported when using Codex with a ChatGPT account`). GSD now never writes an Anthropic-flavored model to a Codex agent: an explicit real-Codex model pin is kept, anything else is omitted so the agent inherits the working session model. (#2310) diff --git a/.changeset/tidy-goats-wake.md b/.changeset/tidy-goats-wake.md deleted file mode 100644 index 0c0d774f4..000000000 --- a/.changeset/tidy-goats-wake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Changed -pr: 2294 ---- -**Phase plans now lead with a verified end-to-end "tracer" slice by default** — every plan starts with one thin, production-quality slice wired through every layer, which the executor verifies before building out the remaining tasks, so an architectural dead-end surfaces after one commit instead of after ten. Pass `--no-tracer` to restore the previous horizontal-layer default; `--mvp` now layers user-story framing and the Walking Skeleton on top of the tracer-first ordering. (#1945) diff --git a/.changeset/tidy-mice-cheer.md b/.changeset/tidy-mice-cheer.md deleted file mode 100644 index 7bb88d225..000000000 --- a/.changeset/tidy-mice-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1767 ---- -**Plural/optional/chosen assumption-delta checkpoint during planning** — when a phase makes something plural, optional, or chosen that used to be singular, required, or derived, the planner is now prompted to re-ask whether the primary key / identity model still names the right thing, preventing silent architectural drift from accumulating into a later user-facing bug. Advisory (non-blocking); fires only on a detected signal. Toggle with workflow.assumption_delta. (#1561) diff --git a/.changeset/tidy-pumas-munch.md b/.changeset/tidy-pumas-munch.md deleted file mode 100644 index 5fa63d5a3..000000000 --- a/.changeset/tidy-pumas-munch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 1909 ---- -Fixed: a hand-authored non-inferable backstop truth with a stray trailing space or surrounding quotes no longer silently grades green — it correctly abstains (insufficient_spec), restoring the #1154 honest-verifier guarantee. diff --git a/.changeset/tidy-tunas-click.md b/.changeset/tidy-tunas-click.md deleted file mode 100644 index 68724cb7e..000000000 --- a/.changeset/tidy-tunas-click.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 1725 ---- -**Installer writes are now confined to the declared config home** — the workflow/skill emit path (`copyWithPathReplacement`) and the Codex config writer (`installCodexConfig`) now reject any destination that escapes the install root: crafted or absolute paths, path-separator agent names, and pre-existing symlinks are refused before any delete or write. Fail-closed: an install write with no declared root is rejected rather than written unconfined. diff --git a/.changeset/tidy-voles-glide.md b/.changeset/tidy-voles-glide.md deleted file mode 100644 index 92bd662ce..000000000 --- a/.changeset/tidy-voles-glide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2235 ---- -**`commit_docs` no longer silently disables on CRLF `.gitignore` repos** — git check-ignore falsely reports a trailing-slash path (e.g. `.planning/`) as ignored when the .gitignore has CRLF line endings with blank lines. isGitIgnored now strips trailing slashes before querying, so the false positive cannot occur. (#2206) diff --git a/.changeset/tidy-zebras-hum.md b/.changeset/tidy-zebras-hum.md deleted file mode 100644 index 53dcfd099..000000000 --- a/.changeset/tidy-zebras-hum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2262 ---- -**Phase-directory resolution fails loud on cross-project collisions** — when two unrelated GSD projects share a `.planning/phases/` tree, a bare phase number silently resolved to the first `0N-*` directory found. The fix detects multiple matches and surfaces an `ambiguous_matches` result. (#2237) diff --git a/.changeset/vivid-badgers-gather.md b/.changeset/vivid-badgers-gather.md deleted file mode 100644 index 5c8570fb4..000000000 --- a/.changeset/vivid-badgers-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2399 ---- -**Build/test gates no longer report a false failure on repos with no detectable build/test tooling** — the post-merge, regression, verify-phase, and audit-fix gates read `config-get workflow.build_command`/`workflow.test_command` without `--raw`, so an unset key returned the literal 2-byte string `""` rather than empty output. The `[ -z "$CMD" ]` guard then saw a non-empty value, skipped the Makefile/Cargo/go.mod/package.json auto-detection cascade, and executed the literal `""` as a command → exit 127, misread as a build/test failure (docs-only or planning-only repos, or any repo before its first build file). All of these reads now pass `--raw`, restoring the intended "no command detected — skip" no-op. (#2350) diff --git a/.changeset/vivid-foxes-click.md b/.changeset/vivid-foxes-click.md deleted file mode 100644 index e814c6865..000000000 --- a/.changeset/vivid-foxes-click.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Removed -pr: 1996 ---- -**Removed the sunset Gemini CLI runtime — use Antigravity CLI instead** — Google discontinued Gemini CLI on 2026-06-18, so `npx gsd-core --gemini` now prints a deprecation notice and points you to Antigravity CLI (the official successor), which GSD already ships as a first-class runtime. (#1928) diff --git a/.changeset/vivid-goats-run.md b/.changeset/vivid-goats-run.md deleted file mode 100644 index 7cf65dbbc..000000000 --- a/.changeset/vivid-goats-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2263 ---- -**`scanPhasePlans` no longer counts PLAN-REVIEW artifacts as executable plans** — `*-PLAN-REVIEW.md` files were counted by the loose `/PLAN/i` fallback. The fix adds a `PLAN_REVIEW_RE` exclusion before the fallback. (#2252) diff --git a/.changeset/vivid-orcas-chatter.md b/.changeset/vivid-orcas-chatter.md deleted file mode 100644 index f04fbade6..000000000 --- a/.changeset/vivid-orcas-chatter.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1979 ---- -**`/gsd-ui-phase` now probes UI state coverage** — a new `ui-consideration-probe` (the third `probe-core` adapter) enumerates the shape-rooted UI states a UI-SPEC must resolve (empty/loading/error/populated/partial/overflow/zero-one-many/long-text). After the UI checker approves, the probe surfaces applicable considerations for each element, records a `## UI Considerations` section in the UI-SPEC, and plan-phase lifts each resolved consideration into `must_haves` — so a purely-visual state with no wired test routes to `insufficient_spec → human_needed` at verify rather than a silent pass. diff --git a/.changeset/vivid-seals-purr.md b/.changeset/vivid-seals-purr.md deleted file mode 100644 index 63c2649d7..000000000 --- a/.changeset/vivid-seals-purr.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 1690 ---- -**Host-Integration Interface (ADR-1239 Phase A)** — a versioned, negotiated capability contract (`runtime.hostIntegration`) over the six host-integration points (command, dispatch, model, hooks, state, artifact). Adds an in-process `negotiateHostCapabilities` handshake that fail-closes on undeclared/unknown/`undocumented` values (`effective ⊆ host-declared ∩ engine-known`), a typed degradation ladder, host-capability profiles, and a documentation-sourced per-CLI capability matrix for all 16 runtimes. Interface-definition only — no change to install behaviour. diff --git a/.changeset/wise-elks-caper.md b/.changeset/wise-elks-caper.md deleted file mode 100644 index 6fe2c999f..000000000 --- a/.changeset/wise-elks-caper.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1806 ---- -**Internal: external-descriptor trust gate — load-time `configHome` confinement** — `assertDescriptorConfined(descriptor, configHome)` (new `src/external-descriptor-trust.cts`) fail-closed rejects any installed third-party host-plugin descriptor whose declared `destSubpath` resolves outside the user-approved `configHome`, before its install plan runs (ADR-1239 Phase C-2 / #1681 slice 1). Defense-in-depth load-time twin of Phase 2's install-time `assertDestWithinConfigHome`. Not yet wired into the loader (slice 2). No user-facing change. - - diff --git a/.changeset/witty-badgers-hum.md b/.changeset/witty-badgers-hum.md deleted file mode 100644 index 7b8d9f05d..000000000 --- a/.changeset/witty-badgers-hum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2473 ---- -**Dependency tree no longer carries a known body-parser advisory** — GHSA-v422-hmwv-36x6 (low-severity DoS via invalid `limit` value, published 2026-07-20) in `body-parser@2.2.2` was pulled transitively via `@anthropic-ai/claude-agent-sdk` → `@modelcontextprotocol/sdk` → `express` and surfaced by `npm audit --omit=dev`. Re-resolved `body-parser` to 2.3.0 in `package-lock.json` within `express`'s already-declared `^2.2.1` range; no `overrides` block needed, `package.json` is unchanged. diff --git a/.changeset/witty-dogs-hop.md b/.changeset/witty-dogs-hop.md deleted file mode 100644 index 98c5f1d13..000000000 --- a/.changeset/witty-dogs-hop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2209 ---- -**Milestone audit no longer flags a not-yet-validated phase as a Nyquist failure** — a phase that was planned but never run through `validate-phase` now reports as NOT-VALIDATED (a "run validate-phase" TODO) instead of collapsing into PARTIAL alongside phases whose validation genuinely failed. (#2117) diff --git a/.changeset/witty-jaguars-gather.md b/.changeset/witty-jaguars-gather.md deleted file mode 100644 index 385f79538..000000000 --- a/.changeset/witty-jaguars-gather.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2485 ---- -**CI gates no longer fail with `no merge base` on branches behind the base.** The mutation, changeset-required, and docs-required workflows shallow-fetched the base *ref*, truncating the ancestry their three-dot `origin/...HEAD` diffs depend on — so the mutation gate reported failure and silently skipped its Stryker shards, leaving the 80% threshold unverified on any PR not already level with `next`. (#2452) diff --git a/.changeset/witty-seals-snooze.md b/.changeset/witty-seals-snooze.md deleted file mode 100644 index 31d48e0d7..000000000 --- a/.changeset/witty-seals-snooze.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -type: Changed -pr: 1801 ---- -**Internal: the installer's runtime → global-config-home hook-pathogen fragment is now a single `getGlobalConfigHomeFragment` lookup** — the 14-branch `if (runtime === 'x') return "'...'"` chain in `getConfigDirFromHome` (`bin/install.js`, the hook `path.join()` codegen mapping) is collapsed into one table in `runtime-name-policy.cts`, sibling to `getRuntimeLabel` (ADR-1239 Phase B, #1679 AC2 slice 2). Generated hook output is byte-identical for all 16 runtimes (golden-parity asserted); antigravity's dynamic env-overridable resolution is preserved in the caller. No user-facing change. - - diff --git a/.changeset/zcode-runtime-1925.md b/.changeset/zcode-runtime-1925.md deleted file mode 100644 index 16adbc0e4..000000000 --- a/.changeset/zcode-runtime-1925.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2039 ---- -**ZCode (Z.ai) is now an installable runtime** — a desktop Agentic Development Environment for the GLM-5.2 model can now be targeted with `--zcode`, landing GSD skills at `~/.zcode/skills//SKILL.md` plus slash commands and subagents. ZCode ships as a pure declarative capability descriptor (`capabilities/zcode/capability.json`) with zero hardcoded `runtime === 'zcode'` branches, reusing the Claude skill converter — the de-hardcoded, data-driven runtime path that 1.7.0 (ADR-1016 / ADR-1239) enables. (#1925) diff --git a/.changeset/zesty-finches-jump.md b/.changeset/zesty-finches-jump.md deleted file mode 100644 index 96b75f1c4..000000000 --- a/.changeset/zesty-finches-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Fixed -pr: 2354 ---- -**OpenCode slash commands now install to the supported `commands/` directory instead of OpenCode's legacy `command/` alias** — GSD wrote all ~71 `/gsd-*` commands to `command/` (singular), which OpenCode's docs list only as a backwards-compatibility alias for the documented `commands/` (plural) convention. Commands now land in `~/.config/opencode/commands/` (global) and `.opencode/commands/` (local), and upgrading migrates the legacy directory, preserving any files you put there yourself. OpenCode currently resolves both names, so this is an alignment rather than a rescue — it takes GSD off a path the vendor may withdraw. Kilo is unaffected. diff --git a/.changeset/zesty-pumas-forage.md b/.changeset/zesty-pumas-forage.md deleted file mode 100644 index fd5d0a013..000000000 --- a/.changeset/zesty-pumas-forage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Added -pr: 2471 ---- -**Reversibility tagging for planning decisions** — decisions can now be rated `reversible`, `costly`, or `one-way` by how expensive they are to undo. A `one-way` decision (one whose undo needs a data migration, breaks a published contract, or is impossible) earns a `checkpoint:decision` before the task that implements it, so an unattended run pauses for your sign-off instead of walking through the door. `costly` decisions are flagged in the plan without blocking; `reversible` ones flow as before. Pass `--no-reversibility-gates` to `/gsd:plan-phase` to suppress the checkpoint on runs you mean to leave unattended — ratings are still recorded either way. (#1951) diff --git a/.changeset/zesty-rams-march.md b/.changeset/zesty-rams-march.md deleted file mode 100644 index 1b66f6a2e..000000000 --- a/.changeset/zesty-rams-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -type: Security -pr: 1706 ---- -**Install write-confinement (ADR-1239 Phase B)** — the installer now rejects any runtime-descriptor `destSubpath` that would write or delete outside the user's config home (path traversal, the config root itself, NUL bytes) and refuses to follow a pre-existing symlink that escapes it. Hardening only; no change to legitimate installs. diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a64f2189..ba79a96e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,281 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +## [1.8.0] - 2026-07-22 + +### Added + +- **A default-off, BETA, claude-only "Claude orchestration" capability** — adopts Claude Code's Workflow tool (`/effort ultracode`, Agent SDK ≥ v0.3.149) as an optional parallel-execution backend for the GSD loop, restoring the wave parallelism + plan-checker + verifier that the #853 backgrounded-agent nesting limitation forces inline on Claude Code, and folding the existing `gsd-ultraplan-phase` plan-offload under the same runtime gate. When `claude_orchestration.enabled` is on AND the runtime is Claude AND the Workflow tool is detected AND the Agent SDK meets the floor (`claude_orchestration.min_agent_sdk_version`, default `0.3.149`), `execute-phase` emits a generated Workflow script (`waves → parallel() barriers`, `plans → agent({ agentType: 'gsd-executor', isolation: 'worktree' })`, `files_modified overlap → separate sequential stages`, `resumeFromRunId` wired to the phase run id, shared `budget` pool) that composes the SAME executor agent + worktree isolation the inline path uses, so artifacts/commits are produced identically. Detection is pure and fail-closed (any miss → inline), so on any runtime lacking the Workflow tool behaviour is byte-identical to today. Adds a pure module `gsd-core/bin/lib/claude-orchestration.cjs` (`detectWorkflowBackend`, `emitWorkflowScript`), the `capabilities/claude-orchestration/` declaration with two gated loop contributions (`execute:wave:post`, `plan:post`) and a `claude-orchestration` command family (`gsd-tools claude-orchestration detect-backend|emit-workflow`), federated config keys, and an ADR-1143 implementation amendment. (#1143) (#2044) +- **Phases that integrate an external API/SDK/service can no longer seal without a decided coverage matrix** — a new `api-coverage` gate on the `ai-integration` capability blocks `/gsd:verify-work` until the phase produces a `COVERAGE.md` enumerating the API's full capability surface, with every non-integrated capability an explicit, reasoned opt-out. Full coverage is the default; the matrix is the subtraction record, so "we integrated the API" can no longer silently mean "we integrated whatever the first use case exercised." Toggleable via `workflow.api_coverage_gate` (on by default). (#1562) (#2065) +- **OpenCode installs now auto-register the GSD companion MCP server (`mcp.gsd`)** — `--opencode` install writes a `mcp.gsd` entry (local stdio → `gsd-mcp-server`) into `opencode.json`, so OpenCode drives GSD's command + planning-state surface over MCP with no bespoke plugin (ADR-1239 Phase D / #1682). Idempotent and non-clobbering; a user-defined `mcp.gsd` is preserved. (#1682) (#1929) +- **OpenCode plugin handles `session.idle` + the `opencode-subset` hook dialect is implemented** — the GSD OpenCode plugin now recognizes `session.idle` (↔ Claude `Stop` lifecycle point), completing the compaction/idle pair (#1914 shipped compaction). The reserved `opencode-subset` dialect gains a consumer — `hookEventSurfaceFor()` in `host-integration.cts` — describing OpenCode's session/tool/file event subset (no workflow-phase events; the engine owns phase sequencing, ADR-1239 §OpenCode binding). Adds a Claude-parity test asserting the plugin covers the full declared subset. (#1682) (#1930) +- **GSD now warns when model config changed without re-running the installer on static-frontmatter runtimes** — on `codex` and `opencode`, editing `model_overrides` or `model_profile_overrides` or `model_policy.runtime_tiers` in `.planning/config.json` or `~/.gsd/defaults.json` previously had no effect until the user re-ran `gsd install `, and the failure was silent: the sub-agent kept using the base model. Workflow entry points like `gsd-tools init *` now emit a one-line stderr warning naming the changed config file and the exact remediation command when they detect the config is newer than the baked agent files. The guard is read-only and warning-only by default, dedup'd per session, and skipped entirely on Claude Code because Claude Code resolves models at spawn time. Resolves #1688 as the structural follow-up to #1650. (#1692) +- **`gsd-tools state rebuild`** — new subcommand that re-derives STATE.md body structure from canonical sources (frontmatter + `.planning/phases/` disk scan), reconciling drifted `## Current Position` prose, dropping orphaned rows from the `**By Phase:**` table, clearing template-placeholder field values, and de-duplicating `## Session Continuity Archive` blocks. Every mutation is recorded in a `## Rebuild Log` audit section. Idempotent (running twice on a clean file is a no-op). Supports `--dry-run` (preview) and `--verbose` (tee log to stderr). Heavier, manual counterpart to the lightweight auto-triggered `state sync`. (#1830) +- **`graphify.graph_path` makes the knowledge-graph location configurable so one umbrella graph can serve multiple projects** — a new `.planning/config.json` key (path relative to project root, or absolute) overrides where `/gsd-graphify query|status|diff` read the graph, letting a single curated cross-repo umbrella graph serve every sibling sub-project without N drifting ~5 MB mirror copies. Previously the graph location was hardcoded to `/.planning/graphs/` with no override; the only workaround was copying the umbrella `graph.json` into each project (which drifted, wasted disk, and could be silently overwritten by an in-project build). The diff snapshot travels with the configured graph; build stays project-scoped; unset → byte-identical default; a configured-but-missing file yields an actionable error naming the path. (#1825) (#2013) +- **Claude Sonnet 5 is now the `standard` (sonnet) tier model.** The model catalog and provider presets resolve the sonnet/standard tier to `claude-sonnet-5` (GA 2026-06-30) across the Anthropic-backed runtimes (`claude`, `copilot`, and the `anthropic`/`anthropic-fable` presets), plus the OpenRouter-style `anthropic/claude-sonnet-5` for `opencode`/`hermes`, replacing the superseded `claude-sonnet-4-6`. Opus and Haiku tier defaults are unchanged (the `haiku` high-effort preset's escalation slot tracks the current sonnet model). Shipped in 1.6.1. (#1847) (#1848) +- **`gsd-debugger` now guards fix acceptance with a multi-signal anti-overfitting gate** — a fix that greens the target test can no longer be silently accepted. The debugger now runs a five-signal guardrail before accepting a fix (target test, mutation check via Stryker, no-op/behavior-deleting diff detector, adjacent/held-out tests, and revert-and-reconfirm), degrades gracefully when Stryker or a test suite is absent (each skip is logged, never a silent pass), records every signal's result under `Resolution.verification` in the debug file, and returns a `FIX REJECTED BY GUARDRAIL` outcome that `gsd-debug-session-manager` surfaces for revise / accept-as-documented-debt / abandon. Full rules live in `gsd-core/references/debugger-fix-acceptance.md`. (#1958) (#2396) +- **`gsd-debugger` now ranks suspect code by Ochiai suspiciousness before forming hypotheses** — when a runnable test suite with per-test coverage exists (≥1 failing and ≥1 passing test), the debugger computes a spectrum-based fault-localization (Ochiai) ranking over the coverage and seeds the top-N suspicious locations into the Evidence section as first-class hypothesis candidates, narrowing the search space deterministically before any LLM reasoning. Tarantula is documented as a fallback formula. The step degrades cleanly (logged, never a silent pass) when there is no test suite, no failing tests, or no per-test coverage, and it is explicitly not trusted on flaky/Heisenbug spectra (pairs with the Phase 2B bug-taxonomy routing). Full rules live in `gsd-core/references/debugger-sbfl.md`. (#1959) (#2403) +- **`gsd-debugger` now branches root-cause analysis instead of chaining, guarding against 5-Whys single-cause bias** — before committing `root_cause`, the debugger enumerates candidate causes across ≥2 Ishikawa categories (code / config / environment / data) rather than a single linear "why" chain, and explicitly answers an AND-gate question ("could this failure require more than one contributing condition simultaneously?"). When the AND-gate fires, every contributing cause is recorded — so a multi-cause fix no longer recurs via the unaddressed second cause. `Resolution.root_cause` may now hold one OR a small set of contributing causes (additive; a single-cause session still records exactly one root_cause while the reasoning_checkpoint gains two RCA fields populated in every session). The Structured Reasoning Checkpoint gains `candidate_causes` + `and_gate` fields, and `debugger-philosophy.md` adds the single-cause-bias trap to its cognitive-bias table. Full rules live in `gsd-core/references/debugger-rca-branching.md`. (#1960) (#2405) +- **`gsd-debugger` now classifies each failure by bug class and routes the investigation technique accordingly, replacing the flat 11-technique menu with selection-by-class** — at a new Phase 1.75 the debugger assigns a `bug_class` (Bohrbug / Heisenbug-Mandelbug / Concurrency) and consults an explicit, inspectable routing table: Bohrbugs route to deterministic reproduction + SBFL (Phase 1.25) + git bisect; Heisenbugs/Mandelbugs route to record-replay (`rr`) + stability-stress + statistical sampling and **explicitly skip SBFL** (a flaky spectrum poisons the ranking); Concurrency bugs surface the atomicity/order/deadlock checklist before general techniques. The 11 techniques remain as routed targets, not an undifferentiated list (supersede, not append). `bug_class` + chosen strategy are written to the debug file; the common-bug-patterns catalog is cross-referenced to the taxonomy. Full rules live in `gsd-core/references/debugger-bug-taxonomy.md`. (#1961) (#2407) +- **`gsd-debugger` now hardens regression tests via PBT shrinking, explicit oracle classification, and boundary neighbors** — extending Minimal Reproduction and Test-First Debugging. When a bug triggers on a class of inputs, the debugger wraps the failing input in a property (fast-check for JS/TS, Hypothesis for Python) and lets the shrinker auto-minimize the counterexample, storing the **minimized** input as the regression seed; before writing the assertion it classifies the oracle as `specified` / `derived` (contract/model) / `metamorphic` / `implicit` (crash — weakest, never the silent default) and records it under `Resolution.oracle_type`; and it generates **boundary neighbors** (off-by-one, min/max, empty/singleton) around the fixed defect's equivalence class. Together they turn the regression test into a root-cause check — which is what the Phase 1A mutation guardrail needs to bite. Degrades gracefully to manual minimization when no PBT framework is present. Full rules live in `gsd-core/references/debugger-repro-hardening.md`. (#1962) (#2409) +- **`gsd-debugger` now emits a blameless-postmortem Prevention block at resolution, closing the loop on bug-class prevention** — at `archive_session` the debugger produces three blame-free components: a **branching 5-Whys** causal chain (branching per the Phase 2A RCA discipline, not a single linear chain; "agent error" prompts "why was that error possible?", never blame), a **"why wasn't this caught?"** answer naming the existing gate (test/typecheck/lint/review/verify) that missed it, and a **concrete recurrence guard** (a regression test / assertion / lint rule / knowledge-base pattern). The knowledge-base entry gains two structured fields — `why_not_caught` and `recurrence_guard` — so a future Phase-0 recall surfaces not just the prior fix but the prior *prevention* (additive; old entries without the fields still load). The session-manager's compact summary surfaces a one-line prevention summary. Full rules live in `gsd-core/references/debugger-prevention.md`; kept minimal — a block, not an incident-management subsystem. (#1963) (#2410) +- **Third-party capability gates now actually fire via a generic `command-exit-zero` predicate.** — a capability's declared `check.predicate` gate was rendered for display but never evaluated (only built-in `check.query` gates were enforced, and the `security` capability's gate worked solely via a hard-coded `ship.md` branch). A new generic evaluator (`gsd_run check predicate`) now evaluates `check.predicate` blocks by `kind`; the first built-in kind `command-exit-zero` runs a bounded `sh -c` command at the project root and blocks the loop on non-zero exit (timeout → block, fail-closed). The `execute:wave:post`, `execute:post`, and `plan:post` gate-dispatch sites route `predicate` gates to the new evaluator automatically. (#2008) (#2011) +- **GSD's lifecycle hooks now run under Kimi CLI** — installing GSD into Kimi wires its session-state, phase-boundary, graphify, and guard hooks into Kimi's own native `config.toml` `[[hooks]]` bus (Beta on Kimi's side) instead of silently no-op'ing, and GSD's Kimi subagents can now run in the background. Kimi's install is driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2095) (#2159) +- **GSD is now installable on pi** — `npx @opengsd/gsd-core --pi` installs the GSD extension to `~/.pi/agent/extensions/gsd.cjs`, and `/gsd ` now dispatches real commands through the embedded engine (the reference binding previously could only run `query help`). Drives pi through the negotiated imperative Host-Integration adapter, with active-model steering and the full pi lifecycle-event surface. (#2102) (#2205) +- **The EoS Registry now lists GSD for Oh My Pi** — discover the independently maintained `tchivs/gsd-omp` protocol-v1 host integration, including exact install and uninstall commands, supported interface points, and negotiated host axes. (#2448) +- **Broken-windows ledger** — `/gsd:ship` now blocks (when `workflow.windows_enforce=true`, opt-in) while `.planning/WINDOWS.md` has any `open` entry, and the executor auto-populates the ledger with stubs, skipped tests, and unrun verifies as it works. Each window can be `waived` only with a recorded reason (auditable) or `fixed` (removed from the blocking set); `/gsd:progress` surfaces the open + waived counts. Backward-compatible: projects with no ledger ship cleanly (open_count starts at 0), and enforcement is off by default so tracking can precede the gate. Enable with `gsd config-set workflow.windows_enforce true`. (#1950) (#2441) +- **GSD now ships a pi extension** — a real, jiti-loadable ExtensionAPI module (`pi/gsd.cjs`) that registers `/gsd` (dispatches through the GSD command-routing hub) + `gsd_invoke` tool + `tool_call` event, installable at `~/.pi/agent/extensions/`. A reachability test proves the `/gsd` handler dispatches through the engine (keystone wired, not just registered on a mock). (#1965) (#1965) +- `plan-phase` now authors edge and prohibition predicates into PLAN.md `must_haves` when a phase SPEC omits `## Edge Coverage` / `## Prohibitions`, so goal-backward verification still has predicates to check on a spec-less phase (ADR-857 Phase 6). Gated by the new default-on `workflow.specless_probe_fallback` toggle — disable it to skip the fallback (the skip is recorded visibly in the plan). Spec-less prohibitions are authored descriptor-less and disposed flagged/unverified (honest verifier #1154), never a silent pass. (#1835) +- **Discover third-party GSD Capabilities in a new Community Capability Registry.** — A non-endorsing discoverability catalog where authors register a Capability via a documentation PR; each entry carries a live latest-release badge and a per-entry GitHub Discussion for community ranking and comments. (#2188) (#2188) +- **GSD now warns when a stale global CLI (e.g. a retired @gsd-build/sdk canary) shadows your project-local install** — the gsd-tools CLI startup detects when the running binary is outside the project root while a project-local install exists, and prints a remediation warning to stderr (non-blocking). (#1754) (#1755) +- **`gsd-mcp-server` — companion MCP server (interface points 1 + 5)** — a new bin command (`npx @opengsd/gsd-core gsd-mcp-server`) runs a stdio JSON-RPC 2.0 MCP server exposing `gsd_invoke_command` (→ the GSD command-routing hub) + `gsd_read_state` / `gsd_write_state` (→ `.planning/` state), so any MCP-consuming host (Claude Code, Codex, OpenCode, VS Code, Gemini CLI, Cursor, Cline, Hermes) can drive GSD with no bespoke plugin (ADR-1239 Phase C-2 / #1681). Dependency-free (hand-rolled JSON-RPC). How-to: `docs/how-to/connect-gsd-mcp-server.md`. (#1810) +- **Opt-in absolute token count on the statusline context meter** — new `statusline.show_context_tokens` config (default `false`). When enabled, the meter shows the absolute context total after the percentage, e.g. "████░░░░░░ 46% (156k)", summing input, cache-creation, cache-read, and output tokens from the hook payload (a broader basis than the meter's percentage, which is derived from `used_percentage` and excludes output tokens — the two figures can diverge slightly). Default meter output is unchanged. (#2161) (#2174) +- **Long-running compute can now be externalized as async external jobs instead of blocking the agent turn** — a default-off external-job capability lets executors submit SLURM jobs, commit a .planning/async-jobs manifest, defer SUMMARY.md, and return external_job_waiting; the core loop already reconciles these manifests (#1165), so this adds the producer half (SLURM adapter, pure manifest module, planner/executor fragments, operation policy). (#1105) (#1998) +- **GSD now ships a repo-local VS Code extension** — a buildable extension (`vscode/extension.js` + `vscode/package.json`) that registers `gsd.invoke` (dispatches through the GSD command-routing hub) in the VS Code command palette. A reachability test proves the handler dispatches through the engine (keystone wired). Not Marketplace-published; mirrors the OpenCode plugin's bar. (#1966) (#1966) +- **Discover third-party GSD Embeddable Orchestration System (EoS) integrations in a new EoS Registry.** — A non-endorsing discoverability catalog where host-integration authors register via a documentation PR; each entry declares its Host-Integration interface points, negotiated axes, and protocol version, with a live release badge and a per-entry GitHub Discussion for ranking and comments. (#2193) (#2193) +- GSD Core ships a `.claude-plugin/marketplace.json` marketplace manifest so Claude-plugin-compatible runtimes (ZCODE et al.) can discover and install gsd-core from a custom marketplace source. Additive — the existing `.claude-plugin/plugin.json` and the Claude Code install path are unchanged. The catalog version (`plugins[0].version`) tracks `package.json` via the release version-sync. (#1861) +- **GSD now drives VS Code through the Embeddable Orchestration System** — the VS Code extension is rewired through the negotiated imperative Host-Integration adapter (active `vscode.lm` model, engine hook bus, sandboxed storage), gains native Language Model Tools (GSD skills as `#gsd-*` tools) and `#runSubagent` dispatch, and runs as a Web Extension (no Node APIs). (#2103) (#2210) +- **`/gsd:next` smart-entry workflow** — adds a state-aware entry point that classifies the current project situation (no-project, blocked, verify-failed, planning, executing, verify-pending, complete, and more) and recommends the right next GSD command. The `gsd-tools smart-entry [--json]` classifier handles phase ordering including decimal phase IDs; the `/gsd:next` skill surfaces the workflow with tiered fallback behavior. (#1798) +- OpenCode now runs GSD's lifecycle safety hooks (prompt-injection guard, read-before-edit guard, injection scanner, worktree/workflow guards, context monitor) via a native plugin installed to `~/.config/opencode/plugins/gsd-core.js`. OpenCode declares `hooksSurface: 'none'`, so these hooks were previously inert; the plugin bridges OpenCode's event bus onto GSD's existing hook scripts. Installed automatically by `npx @opengsd/gsd-core --opencode` and removed on uninstall. (#1923) +- **Opt-in compact GSD-state statusline format** — new `statusline.state_format` config, enum `full`|`compact` (default `full`, the existing rendering). `compact` renders " · P/ · " (e.g. "v1.12 · P7/12 · executing"), dropping the milestone name and progress bar and collapsing narrative statuses to the canonical vocabulary from `normalizeStateStatus()` — the canonical stuck state `paused` renders uppercase as `PAUSED`. Solves the unbounded-width problem where free-text status sentences push the context meter off the line. (#2162) (#2175) +- **`` task element (Design by Contract)** — plans may now declare a runnable/checkable fact a task assumes (env var set, prior-phase artifact present, external-setup done) that plan ordering does not guarantee; the executor asserts it before running the task and halts with a checkpoint on unmet instead of building on a broken assumption. Plans that omit `` behave exactly as today. (#1949) (#2422) +- **Config-gated provider escalation when a run hits a quota or rate limit** — an executor killed by a provider throttle stopped the phase and waited for a manual restart; escalating a tier did not help because the same throttled provider was still in play. Set `dynamic_routing.provider_escalation` to an ordered list of fallback model IDs and GSD now switches provider on a quota-exceeded failure, logs the swap (`sonnet → gpt-5`), honors the provider's `Retry-After`, caps the walk at `max_escalations`, and names every model tried once the list is spent. Opt-in — unset, quota failures keep today's manual recovery prompt. (#2296) (#2458) +- **Host-integration descriptors now carry an `extensionEvents` vocabulary** — the extension-system event surface (OpenCode, pi) is a separate descriptor field from managed `hookEvents`, so OpenCode declares `extensionEvents:opencode` without conflicting with the hooksSurface:none invariant. (#1946) (#1946) +- **`/gsd-review` now supports custom reviewer instances** — run one model-capable adapter (e.g. OpenCode) as several independent reviewer identities via a bounded `review.reviewer_instances` config, so two different models can review in a single pass without manually swapping config or hand-merging REVIEWS.md. (#1517) (#1766) +- **Opt-in git branch and working-state segment in the statusline** — the shell prompt's branch/dirty-state signal is hidden for the whole session under the Claude Code TUI, so wrong-branch commits and ship-time push rejections surface only after the fact. New `statusline.show_git` config (default `false`) renders the branch name plus staged/unstaged/untracked/ahead/behind markers (or ✓ when clean and in sync) after the directory segment. When disabled, no git subprocess is spawned and output is unchanged. (#2163) (#2183) +- **`/gsd:onboard` guides brownfield setup** — existing repos now have a top-level onboarding command that routes through codebase mapping, docs ingest, project initialization, and an onboarding summary without silently overwriting planning files. (#1994) +- **Plural/optional/chosen assumption-delta checkpoint during planning** — when a phase makes something plural, optional, or chosen that used to be singular, required, or derived, the planner is now prompted to re-ask whether the primary key / identity model still names the right thing, preventing silent architectural drift from accumulating into a later user-facing bug. Advisory (non-blocking); fires only on a detected signal. Toggle with workflow.assumption_delta. (#1561) (#1767) +- **`/gsd-ui-phase` now probes UI state coverage** — a new `ui-consideration-probe` (the third `probe-core` adapter) enumerates the shape-rooted UI states a UI-SPEC must resolve (empty/loading/error/populated/partial/overflow/zero-one-many/long-text). After the UI checker approves, the probe surfaces applicable considerations for each element, records a `## UI Considerations` section in the UI-SPEC, and plan-phase lifts each resolved consideration into `must_haves` — so a purely-visual state with no wired test routes to `insufficient_spec → human_needed` at verify rather than a silent pass. (#1979) +- **Host-Integration Interface (ADR-1239 Phase A)** — a versioned, negotiated capability contract (`runtime.hostIntegration`) over the six host-integration points (command, dispatch, model, hooks, state, artifact). Adds an in-process `negotiateHostCapabilities` handshake that fail-closes on undeclared/unknown/`undocumented` values (`effective ⊆ host-declared ∩ engine-known`), a typed degradation ladder, host-capability profiles, and a documentation-sourced per-CLI capability matrix for all 16 runtimes. Interface-definition only — no change to install behaviour. (#1690) +- **ZCode (Z.ai) is now an installable runtime** — a desktop Agentic Development Environment for the GLM-5.2 model can now be targeted with `--zcode`, landing GSD skills at `~/.zcode/skills//SKILL.md` plus slash commands and subagents. ZCode ships as a pure declarative capability descriptor (`capabilities/zcode/capability.json`) with zero hardcoded `runtime === 'zcode'` branches, reusing the Claude skill converter — the de-hardcoded, data-driven runtime path that 1.7.0 (ADR-1016 / ADR-1239) enables. (#1925) (#2039) +- **Reversibility tagging for planning decisions** — decisions can now be rated `reversible`, `costly`, or `one-way` by how expensive they are to undo. A `one-way` decision (one whose undo needs a data migration, breaks a published contract, or is impossible) earns a `checkpoint:decision` before the task that implements it, so an unattended run pauses for your sign-off instead of walking through the door. `costly` decisions are flagged in the plan without blocking; `reversible` ones flow as before. Pass `--no-reversibility-gates` to `/gsd:plan-phase` to suppress the checkpoint on runs you mean to leave unattended — ratings are still recorded either way. (#1951) (#2471) + +### Changed + +- **`gsd-debugger` now recalls prior resolved sessions semantically via MemPalace instead of keyword overlap** — at Phase 0 the debugger queries MemPalace with the current symptoms and surfaces the top-k meaning-similar prior resolutions as candidate hypotheses, catching the same-root-cause / different-wording cases keyword overlap missed (a prior "requests hang under load" now surfaces for "API times out when many users connect"). Resolved sessions are indexed into MemPalace at archive (symptoms + root cause(s) + fix + recurrence guard). `knowledge-base.md` remains the durable plain-text source of truth; when MemPalace is absent the debugger falls back to keyword-overlap matching against it (logged, never a silent skip). No new embedding/vector infrastructure — MemPalace is reused. Full rules live in `gsd-core/references/debugger-semantic-recall.md`. (#1964) (#2416) +- **The GSD CLI now self-heals a missing runtime build.** The compiled `gsd-core/bin/lib/*.cjs` modules are gitignored build artifacts (ADR-457) that ship prebuilt in the npm tarball but are absent on a Claude Code plugin-marketplace / git-clone install, which never runs `npm run build:lib`. Previously every command died at load with `Cannot find module './lib/cli-exit.cjs'`. The `gsd-tools` entrypoint now detects the missing output and compiles it once, on demand (lock-guarded so parallel invocations don't race), then proceeds — a single no-op check on the already-built npm path. When TypeScript is genuinely unavailable it prints an actionable `npm install && npm run build:lib` message instead of crashing. (#2036) +- **Internal: Claude Code's installer is now driven through the public Host-Integration Interface (ADR-1239 / EoS).** `bin/install.js` routes `claude` install/uninstall through the imperative adapter (`createImperativeAdapter`) instead of calling the engine directly, and its 13 hardcoded `runtime === 'claude'` / `runtime !== 'claude'` branches are folded into descriptor-driven `runtime.hostBehaviors` on `capabilities/claude/capability.json` (permission schema, `settings.local.json` scope routing, `.gsd-source` marker, effort frontmatter, canonical-workflow authorship, and more). Install/uninstall output is **byte-identical** for both the global skills layout and the local legacy layout (golden-parity asserted for both scopes); no other runtime changes. Removes the "add-a-host tax" of scattered string-equality checks for the tier-1 reference host. No user-facing change. (#2086) (#2106) +- **OpenCode is now driven through the public Host-Integration Interface, with two capability upgrades (ADR-1239 / EoS).** OpenCode and its Kilo sibling previously installed via a bespoke `runtime === 'opencode'`/`isOpencode` branch in `bin/install.js`; its commands+skills+plugin install now runs through the imperative adapter → the engine's combined-family install path (`installRuntimeArtifacts`), and every hardcoded `runtime === 'opencode'` branch is folded into descriptor-driven `runtime.hostBehaviors`. Install/uninstall output is **byte-identical** (golden parity asserted for all 16 runtimes). Two Context7-verified upgrades land: (1) **background dispatch** — OpenCode shipped experimental background subagents in v1.15 and made them default-on in v1.17, so `dispatch.background`/`backgroundDispatch` flip to `true`; GSD no longer force-flattens OpenCode-hosted wave dispatch (`shouldFlattenDispatch` now returns `false`), letting agents run concurrently where the host supports it. (2) **expanded event surface** — the OpenCode plugin now subscribes to `permission.asked`, `permission.replied`, and `session.error` (added to `EXTENSION_EVENT_SURFACES.opencode`), wiring the declared surface for future permission/error-aware bindings. (#2087) (#2108) +- **Codex is now driven through the public Host-Integration Interface, with three capability upgrades (ADR-1239 / EoS).** Codex previously installed via hardcoded `runtime === 'codex'`/`isCodex` projection in `bin/install.js`; its `config.toml` / agent-`.toml` / `hooks.json` install now runs through the declarative embedding adapter and descriptor-driven `runtime.hostBehaviors`, with **zero** positive `isCodex` gates and **zero** `runtime === 'codex'` branches remaining (source-guarded). Install/uninstall output stays byte-parity-gated (`tests/fixtures/golden-install-parity/codex.json`). Three Context7-verified upgrades land, each with a test driving the user-reachable surface: (1) **skill root** — GSD skills now install to Codex's canonical `$HOME/.agents/skills` (via a skills-kind `home` override) instead of the deprecated `$CODEX_HOME/skills` fallback, and pre-move installs are migrated (stale `~/.codex/skills/gsd-*` cleaned on both install and uninstall, user-owned content preserved); (2) **hook events** — GSD registers the six documented Codex lifecycle events it previously skipped (`PreToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SubagentStop`, `UserPromptSubmit`, in addition to the existing `SessionStart`/`SubagentStart`/`Stop`/`PostToolUse`) in `hooks.json`, so `gsd-context-monitor` fires at the same points as in Claude Code, and the descriptor `extendedHookEvents` is reconciled from `[]` to the schema-valid wired subset; (3) **dispatch tuning** — `[agents] max_depth = 1` is written explicitly into the managed `config.toml` block to pin the negotiated `dispatch.maxDepth: 1` axis (`degradationFor` flattens GSD-hosted waves to single-level), and `validateCodexConfigSchema` now permits a known-scalar-only `[agents]` AgentsToml table (coexisting with the flattened `[agents.gsd-*]` role sub-tables) while still rejecting the `[[agents]]` and unknown-key break-forms from #2760. (#2088) (#2110) +- **Cursor is now driven through the public Host-Integration Interface, with two capability upgrades (ADR-1239 / EoS).** Cursor previously installed via hardcoded `runtime === 'cursor'`/`isCursor` branches in `bin/install.js`; its install/uninstall now runs through the imperative adapter, and every hardcoded cursor branch is folded into descriptor-driven `runtime.hostBehaviors` (reapplyCommand, frontmatterDialect, hooksJsonSurface, skipSharedHooksInstall, reportCommandsDir, managedHookEvents). Install/uninstall output is **byte-identical** (golden parity asserted for all 16 runtimes). Two Context7-verified upgrades land: (1) **expanded hook-bus coverage** — GSD registers all 6 managed lifecycle events in Cursor's `hooks.json` (`preToolUse`, `stop`, `subagentStart`, `subagentStop` in addition to the original `sessionStart`/`postToolUse`), driven by a new descriptor-driven adapter module (`src/host-integration-adapters/imperative-hook-bus.cts`) that reads `hostBehaviors.managedHookEvents` instead of a hardcoded event pair; cite https://cursor.com/docs/hooks. (2) **named/background nested subagent dispatch** — Cursor's `dispatch.background`/`backgroundDispatch`/`nested` are all `true` with `maxDepth: 2`, so `shouldFlattenDispatch(cursor)` returns `false` and GSD's wave-based execution drives Cursor's native background + depth-2 nested subagent invocation instead of flattening to inline sequential calls; cite https://cursor.com/docs/subagents + https://cursor.com/docs/sdk/typescript. (#2089) (#2120) +- **Cline is now driven through the public Host-Integration Interface, with two capability upgrades (ADR-1239 / EoS).** Cline previously installed via hardcoded `runtime === 'cline'`/`isCline` branches in `bin/install.js`; its install/uninstall now runs through the imperative adapter, and every hardcoded cline branch is folded into descriptor-driven `runtime.hostBehaviors` (reapplyCommand, frontmatterDialect, skipSharedHooksInstall, localTargetIsProjectRoot, clineRulesSurface, localCommandsViaRules). Install/uninstall output is **byte-identical** (golden parity asserted for cline + claude/cursor/codex/opencode). Two Context7-verified upgrades land: (1) **`AgentPlugin.hooks.beforeTool` planning guard** — the `.clinerules/hooks/PreToolUse` file-convention hook (#787) is re-implemented as a real Cline SDK `AgentPlugin` that cancels write-class calls targeting `.planning/` (same fail-open semantics), driven by a new descriptor-driven adapter module (`src/host-integration-adapters/cline-sdk-binding.cts`); cite https://github.com/cline/cline/blob/main/docs/sdk/plugins.mdx. (2) **`createAgentModel` model overrides** — `DefaultGateway.createAgentModel({providerId, modelId})` is wired so GSD's per-subagent `model_overrides`/`model_profile_overrides` resolution applies to Cline subagents (`modelMode: active`); cite https://github.com/cline/cline/blob/main/docs/sdk/reference/gateway.mdx. Cline's dispatch deliberately stays **degraded/flat** (`maxDepth: 1`, read-only, no nested spawning) per the documented host restriction — never silently upgraded to full nested/background. (#2090) (#2132) +- **Hermes Agent is now driven through the public Host-Integration Interface, with three capability upgrades (ADR-1239 / EoS).** Hermes previously installed via hardcoded `runtime === 'hermes'`/`isHermes` branches in `bin/install.js`; its install/uninstall now runs through the imperative adapter, and every hardcoded hermes branch is folded into descriptor-driven `runtime.hostBehaviors`. Three upgrades land: (1) **real plugin hook vocabulary** — GSD registers a new `extensionEvents: "hermes"` dialect carrying the 13 documented Hermes plugin events (`pre_tool_call`, `post_tool_call`, `pre_llm_call`, `post_llm_call`, `on_session_start`, `on_session_end`, `on_session_finalize`, `on_session_reset`, `subagent_start`, `subagent_stop`, `pre_gateway_dispatch`, `pre_approval_request`, `transform_tool_result`), replacing the borrowed `hookEvents: "claude"` 6-event surface that silently never fired; cite https://github.com/nousresearch/hermes-agent/blob/main/website/docs/user-guide/features/hooks.md. (2) **dispatch posture** — Hermes' `dispatch.nested: true` with `maxDepth: 1` is correctly negotiated (not silently flattened). (3) **branding/category metadata** — `DESCRIPTION.md` category descriptions, `version:` frontmatter, and branding rewrites are now descriptor-driven rather than hardcoded. Install/uninstall output is byte-identical (golden parity asserted for all runtimes). (#2091) (#2134) +- **Qwen Code now projects GSD's specialist agents as native subagents** — installing GSD into Qwen Code writes `~/.qwen/agents/gsd-*.md` files you can invoke directly (planner, executor, code-reviewer, …) instead of reaching them only through skill prose, and a `SubagentStart` hook now fires alongside `SubagentStop`. Qwen's install is driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2092) (#2153) +- **Kilo Code now supports native hooks, active-model routing, and named subagent dispatch** — installing GSD into Kilo wires a lifecycle-hook plugin, keeps each agent's requested model instead of dropping it, projects GSD's specialist agents as invokable subagents, and documents the GSD MCP companion. Kilo's install is driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2093) (#2156) +- **GSD skills installed for Trae now carry SOLO stage metadata** — Trae's SOLO Agent can recognize GSD skills as workflow-stage skills for auto-invocation instead of requiring manual triggering. Several of Trae's install branches (shared-hooks gating, path rewrites) also move onto its capability descriptor. Note: the stage-metadata field is a best-effort/inferred shape — Trae publishes no formal schema. (#2094) (#2157) +- **Installing GSD into Antigravity now writes the `permissions.allow` rules its CLI documents** — so GSD's own reads and hooks aren't stuck on interactive prompts — and registers GSD's companion MCP server via a standalone `mcp_config.json` (best-effort: Antigravity's raw config schema isn't published, so this uses the Gemini-CLI-successor format). Antigravity's install is now driven by its negotiated capability descriptor instead of hardcoded runtime special-cases. (#2096) (#2165) +- **Augment Code now installs through its capability descriptor, with a native MCP companion** — installing GSD into Augment registers the GSD companion server in Augment's `settings.json` `mcpServers` and drives command/skill/agent conversion from Augment's negotiated descriptor instead of hardcoded runtime special-cases. (#2097) (#2166) +- **CodeBuddy now wires GSD's full extended lifecycle hook set and is driven by its capability descriptor** — installing GSD into CodeBuddy now registers `SubagentStart`, `SubagentStop`, `Stop`, and `PreCompact` hooks in its `settings.json` (it previously had none of these), matching the coverage Qwen/Kimi already ship, and CodeBuddy's install is fully descriptor-driven instead of via residual hardcoded runtime branches. (#2098) (#2169) +- **GitHub Copilot now wires GSD's full lifecycle hook bus and is driven by its capability descriptor** — installing GSD into Copilot registers `preToolUse`, `postToolUse`, `userPromptSubmitted`, and `sessionEnd` handlers in its `hooks/gsd-session.json` (beyond today's `sessionStart`-only advisory), and Copilot's residual hardcoded runtime branches are folded onto descriptor-driven `hostBehaviors`. (#2099) (#2172) +- **Windsurf now enforces GSD's write/command safety guards through Cascade's native hook bus** — installing GSD into Windsurf registers blocking `pre_write_code`/`pre_run_command` hooks in `.windsurf/hooks.json` (exit-code-2 blocking) and drives Windsurf's install from its capability descriptor instead of hardcoded runtime branches. (#2100) (#2190) +- **ZCode's install is now driven and regression-tested through its capability descriptor** — ZCode joins the dogfooded declarative-adapter reference hosts with a byte-identical install, and its shared-hooks exclusion is folded onto `hostBehaviors` instead of a hardcoded runtime branch. (Hook-automation and MCP upgrades remain blocked on ZCode publishing its on-disk config formats.) (#2101) (#2195) +- **Codex/OpenAI default models advance to the GPT-5.6 family (Sol/Terra/Luna)** — the Codex runtime tier defaults and the `openai` provider preset now resolve to current-generation model IDs instead of the superseded GPT-5.4/5.5 line, so Codex users on default profiles get improved agentic coding (Sol) and lower costs (Terra/Luna) without changing any config. (#2122) (#2146) +- **Internal: the installer's `program` (display-name) + `command` (slash-invocation) chains are now single-source lookups** — the 14-line `program` chain (an exact duplicate of `runtimeLabel`) → `getRuntimeLabel`, and the 14-line `command` chain (the per-runtime `/gsd-new-project` syntax: gemini `/gsd:`, codex `$`, cursor skill-mention, kimi `/skill:`, default `/gsd-new-project`) → new `getRuntimeNewProjectCommand(runtime)` helper (ADR-1239 Phase B / #1679 AC2 slice 4). `runtime ===` count in `bin/install.js`: 53 → 25 (cumulative this session: 129 → 25). Stdout strings preserved byte-for-byte; no install-output change (golden-parity 16/16). No user-facing change. (#1813) +- **Internal: the installer's per-function `is` flag-declaration blocks are now a single `runtimeFlags` lookup** — the four duplicated `const isX = runtime === 'x'` blocks in `bin/install.js` (uninstall / writeManager / install / a fourth helper — 48 branches) are collapsed into one `runtimeFlags(runtime)` helper in `runtime-name-policy.cts` (ADR-1239 Phase B / #1679 AC2 slice 3). The add-a-host tax for flags is removed (one `RUNTIME_FLAG_IDS` entry, not four declaration blocks). Install output is byte-identical for all 16 runtimes (golden-parity asserted); `runtime ===` count in `bin/install.js`: 101 → 53. No user-facing change. (#1811) +- **Internal: third-party descriptor loader enforces `configHome` write-confinement at load time** — `loadRegistry({includeInstalled:true, configHome})` now rejects (skip + warn, fail-closed) any installed third-party host-plugin descriptor whose declared `destSubpath` resolves outside the supplied `configHome`, before it is composed into the registry (ADR-1239 Phase C-2 / #1681 slice 2). The `configHome` option is optional and backward-compatible (omitted → no load-time check; install-time gate still bounds writes). No user-facing change for existing flows. (#1808) +- **Internal: agent install for cursor/windsurf/augment/trae/codebuddy now flows through the descriptor path** — ADR-1235 step 1 routes the trivial-converter runtime group's agents off the inline install() loop onto the descriptor-driven `installRuntimeArtifacts` path, applying the cross-cutting steps uniformly (pre-converter, no workflow-stamp). Agent output is byte-identical for all 16 runtimes (golden-parity asserted, global + local verified); no user-facing change. (#1764) +- **gsd-ui-checker gains an adversarial FORCE stance (LLM-playbook principle 16)** — the only verdict-producing critic that lacked one now resists rubber-stamping UI-SPEC contracts, with BLOCK/FLAG/PASS classification. Based on arXiv 2505.23840 (third-person objective persona), 2506.04975 (objective-not-hostile persona). (#1584) +- **Internal: the declarative embedding adapter is now named + bound behind a minimal `HostIntegrationInterface`** — `createDeclarativeAdapter({runtime})` (new `src/adapter-declarative.cts`) delegates in-process to `install-engine`'s `installRuntimeArtifacts`/`uninstallRuntimeArtifacts`, formalizing today's projection path as one of the two embedding adapters behind a common contract (ADR-1239 Phase C-1 / #1680 AC1). Output is byte-identical to today's install (gated by `golden-install-parity`). The full 6-point interface binding surface is deferred until the imperative adapter (AC2) fixes the shape (ADR-1239 open wire-shape question). No user-facing change — the adapter is not yet wired to any runtime path. (#1802) +- **Internal: getDirName is now derived from a documented `runtime.localConfigDir` descriptor field** — each runtime's local content-rewrite directory (e.g. `cursor`→`.cursor`, `copilot`→`.github`) moved from a hand-maintained if-chain into its capability descriptor (ADR-1239 Phase B), so it can no longer drift from the registry. Install output is byte-identical for all 16 runtimes (golden-parity asserted); no user-facing change. (#1757) +- **Internal: copyWithPathReplacement converter selection is now data-driven** — the installer's back-compat content-copy path replaced its 13 hardcoded `runtime === 'x'` flag chains with a single per-runtime dispatch table (ADR-1239 Phase B). Install output is byte-identical for all 16 runtimes (golden-parity asserted); no user-facing change. (#1759) +- **Phase-completion now writes `Status: All phases complete` instead of the overloaded bare `Milestone complete`** — the phase-level completion verb (`completePhaseCore`) was writing the same bare 'Milestone complete' string that the milestone-close verb uses for terminal state, causing a phase-level verb to own a milestone-level field. Per ADR-2207, phase-completion now writes the existing intermediate value 'All phases complete' (already used in gsd2-import.cts); milestone termination (' milestone complete' / 'Awaiting next milestone') remains solely with the milestone-close verb. (#2204) (#2259) +- **#853 dispatch-flatten is now data-driven (ADR-1239 Phase B)** — whether GSD backgrounds the plan/execute orchestrator is decided from a documentation-sourced `backgroundDispatch` capability per host (via `gsd_run query dispatch-should-flatten`) instead of a hardcoded `runtime === 'codex'` check. **Cursor now backgrounds the orchestrator** (its docs document backgrounded subagent nesting); codex unchanged; all other hosts run inline. Fail-closed to inline on any uncertainty. (#1719) +- **Internal: companion MCP server module (interface points 1 + 5)** — `handleMessage`/`runServer` (new `src/mcp-server.cts`) is a minimal, dependency-free stdio JSON-RPC 2.0 server exposing `gsd_invoke_command` (→ the command-routing hub) + `gsd_read_state`/`gsd_write_state` (→ the Phase 3 stateIO seam), so any MCP-consuming host can drive GSD with no bespoke plugin (ADR-1239 Phase C-2 / #1681 slice 3a). Bin entry / packaging deferred to slice 3b. No user-facing change — the server is not yet wired to a bin entry. (#1809) +- **`requirements mark-complete` reports a per-surface write-set** — the command now returns a per-requirement `write_set` (checkbox + traceability surfaces) and a `write_set_complete` that is true only when every surface of every requirement applied, so a partial (checkbox-only) reconcile can no longer masquerade as full success even inside a multi-ID batch. Introduces the reusable ADR-2143 §5/§6 `Result` / `WriteSet` contract. (#2251) (#2251) +- **Internal: the imperative embedding adapter now composes the capability registry behind the same `HostIntegrationInterface`** — `createImperativeAdapter({runtime})` (new `src/adapter-imperative.cts`) calls `loadRegistry({includeInstalled:true})` (first-party-wins + consent + fail-closed — identical trust semantics to the CLI) and binds the engine surface behind the same contract the declarative adapter (AC1) satisfies, plus a `registry` accessor for an in-process host to bind its primitives to (ADR-1239 Phase C-1 / #1680 AC2). Concrete host binding is deferred to Phase 5. No user-facing change — the adapter is not yet wired to any runtime path. (#1803) +- **Internal: the model adapter seam exposes `passive` + `active` adapters selected by `modelMode`** — `createModelAdapter({modelMode})` (new `src/model-adapter.cts`): `passive` formalizes today's tier routing (delegates to `model-resolver.resolveModelForTier`), `active` is a host-supplied `sendRequest` seam (VS Code `vscode.lm` / pi providers), fail-closed until Phase 5 binds a concrete provider (ADR-1239 Phase C-1 / #1680 AC3). No user-facing change — the seam is not yet wired to any runtime path. (#1804) +- **Internal: derive the non-Claude runtime list from the capability registry** — `NON_CLAUDE_RUNTIMES` is now computed from the capability registry instead of a hand-maintained literal, so it can no longer drift from the per-runtime descriptors. No user-visible behavior change (the list is identical). (#1728) +- **Honest verifier — verify-phase now abstains on non-inferable `backstop` truths instead of confidently false-passing them (#1154).** When the spec's edge-probe marks a truth non-inferable (`verification: backstop`) and the verifier cannot confirm it with explicit evidence (a passing wired held-out/property test, or a directly-observed behavior), it now reports `human_needed` with reason `insufficient_spec` ("unverified — held-out test recommended") rather than a silent `passed`. Autonomous runs complete with "N unverified non-inferable checks"; interactive runs route to the end-of-phase human checkpoint. Inferable truths are never abstained (over-abstention guard); abstention is exogenous (driven by the tag, not self-judgment). Truth-axis mirror of the prohibition judgment-tier (ADR-550 D4). (#1738) +- Document Claude Code's advisor-tool inheritance in the model-profiles reference: the session-level advisor is inherited by all GSD subagents and composes with per-agent tiering, with candidate executor/advisor pairings, when it is worth enabling, and the session-level (no per-agent control) constraint. (#1922) +- **Extraction discipline for strict-format agents (LLM-playbook principle 8)** — gsd-doc-classifier and gsd-doc-synthesizer apply taxonomy/precedence rules directly without inventing content, reducing reasoning-induced format drift. Based on arXiv 2504.05081 (few-shot beats CoT for pattern tasks), 2506.00069 (terminal instruction placement), 2505.14810, 2505.11423. (#1584) +- **Internal: extracted the runtime-artifact install engine from `bin/install.js`** — `installRuntimeArtifacts`/`uninstallRuntimeArtifacts`/`installOpencodeFamilySkills` and their helpers now live in a dedicated `gsd-core/bin/lib/install-engine.cjs` module (ADR-1239 Phase B), so adapters can import the install pipeline instead of reaching into the 12k-line installer. Install output is byte-identical for all 16 runtimes (golden-parity asserted); no user-facing behaviour change. (#1735) +- **MemPalace `memory_mode` `kg_backend` and `replace` are now functional** — selecting either mode now routes recall through the palace instead of silently behaving like `augment`: `kg_backend` treats the palace temporal KG as the primary knowledge-graph source (native `.planning/graphs/` as fallback), and `replace` resolves recall through the palace as the source of truth. Every mode stays default-resilient — an unreachable palace falls back to native memory and no memory is lost. (#2010) (#2010) +- **`/gsd:surface` and `--materialize` now produce byte-identical agent output to a fresh install** — surface-path agents for descriptor-driven runtimes (cursor, windsurf, augment, trae, codebuddy, copilot, antigravity) now receive the same path-prefix rewrite, Co-Authored-By attribution, runtime-specific conversion, and body normalization as the install path. Copilot and Antigravity agents are now installed via the descriptor-driven path (copilot agents get the `.agent.md` filename rename). Cline remains on the inline loop (rules-only local branch). (#1575) (#2040) +- **Internal: hook-bus + stateIO adapter seams** — `createHookBus({bus})` (new `src/hook-bus.cts`, `host`/`engine`/`none` — engine is in-process pub/sub, host fail-closed, none silent) + `createStateIO({io})` (new `src/state-io.cts`, `filesystem`/`sandboxed-storage`/`session-log-append` — filesystem delegates to fs, the rest are fail-closed seams) (ADR-1239 Phase C-1 / #1680 AC4). Completes the Phase 3 adapter seam layer; concrete host binding is Phase 5. No user-facing change. (#1805) +- **Long-context model names render compactly in the statusline** — the verbose " (1M context)" suffix Claude Code appends to the model display name now collapses to a compact " (1M)" badge (tolerant of future window sizes and the abbreviated "ctx" variant: "(500K context)" → "(500K)", "(1M ctx)" → "(1M)"). Lossless — the long-context signal stays, the 12 characters of width don't. (#2160) (#2173) +- **Lazy-split `plan-phase.md` into a `steps/` directory** — ~4.7 KB lighter eager context per `/gsd-plan-phase` call via byte-invariant progressive disclosure (ADR-1610). (#1852) (#1934) +- **GSD subagents now self-load configured agent_skills regardless of orchestrator bash** — projects that map skills via `.planning/config.json` `agent_skills.` no longer silently lose them on `/gsd-autonomous` or Cursor, where `Skill()`-delegated workflow bash init did not reliably run. Each of the 22 consumer agents queries its own type at init and reads the listed skills, with a dedup guard so runtimes that also inject orchestrator-side (Claude Code) never carry two copies. (#1866) (#1868) +- **Internal: install/uninstall runtime labels are now sourced from a single `getRuntimeLabel` lookup** — the two duplicated `runtimeLabel` assignment chains in `bin/install.js` (uninstall + install) are collapsed into one curated label table in `runtime-name-policy.cts`, sibling to the registry-derived `getDirName` (ADR-1239 Phase B, #1679). Install output is byte-identical for all 16 runtimes (golden-parity asserted). Two console-label inconsistencies are normalized as a side effect: `kimi` shows 'Kimi CLI' in both sites, and `cline` uninstall no longer falls through to 'Claude Code'. (#1800) +- **Phase plans now lead with a verified end-to-end "tracer" slice by default** — every plan starts with one thin, production-quality slice wired through every layer, which the executor verifies before building out the remaining tasks, so an architectural dead-end surfaces after one commit instead of after ten. Pass `--no-tracer` to restore the previous horizontal-layer default; `--mvp` now layers user-story framing and the Walking Skeleton on top of the tracer-first ordering. (#1945) (#2294) +- **Internal: external-descriptor trust gate — load-time `configHome` confinement** — `assertDescriptorConfined(descriptor, configHome)` (new `src/external-descriptor-trust.cts`) fail-closed rejects any installed third-party host-plugin descriptor whose declared `destSubpath` resolves outside the user-approved `configHome`, before its install plan runs (ADR-1239 Phase C-2 / #1681 slice 1). Defense-in-depth load-time twin of Phase 2's install-time `assertDestWithinConfigHome`. Not yet wired into the loader (slice 2). No user-facing change. (#1806) +- **Internal: the installer's runtime → global-config-home hook-pathogen fragment is now a single `getGlobalConfigHomeFragment` lookup** — the 14-branch `if (runtime === 'x') return "'...'"` chain in `getConfigDirFromHome` (`bin/install.js`, the hook `path.join()` codegen mapping) is collapsed into one table in `runtime-name-policy.cts`, sibling to `getRuntimeLabel` (ADR-1239 Phase B, #1679 AC2 slice 2). Generated hook output is byte-identical for all 16 runtimes (golden-parity asserted); antigravity's dynamic env-overridable resolution is preserved in the caller. No user-facing change. (#1801) + +### Removed + +- **Removed the sunset Gemini CLI runtime — use Antigravity CLI instead** — Google discontinued Gemini CLI on 2026-06-18, so `npx gsd-core --gemini` now prints a deprecation notice and points you to Antigravity CLI (the official successor), which GSD already ships as a first-class runtime. (#1928) (#1996) + +### Fixed + +- The `verify-work` security-blocked presentation no longer offers next-phase planning. When security enforcement blocks phase advancement (no `SECURITY.md` produced), the workflow now routes only to the current-phase fix instead of competing `/gsd:plan-phase {next}` and `/gsd:execute-phase {next}` options. (#1687) +- `milestone complete` and `roadmap analyze` now exclude the Phase 0 / Phase 999 backlog sentinels. A milestone whose only directory-less ROADMAP heading is a backlog sentinel can be completed without `--force`, and `roadmap analyze` no longer counts the sentinel in `phase_count` or routes `next_phase` into it. Completes the `^999` exclusion #1445 added to the progress denominators. (#1691) +- **`config-set` no longer silently coerces values into something the disk never sees** — `Number.isFinite` replaced `!isNaN` in the value parser so `Infinity`/`-Infinity` are no longer coerced to non-finite numbers that `JSON.stringify` then renders as `null` on disk while the CLI echoes `Infinity` (output ≠ disk). `context_window` now has a per-key validator requiring a finite positive integer (rejects `Infinity`, `0`, negatives, non-integers with a non-zero exit), and `project_code` is always persisted as a string so a leading-zero code like `007` survives verbatim instead of collapsing to `7`. Numeric coercion for genuine numeric keys (e.g. `granularity 42`) is unchanged. (#1581) (#2023) +- **`phase.complete` no longer reports a false `is_last_phase` on a `
`-wrapped checkbox checklist (#1591, #1752)** — when the active milestone's phase checklist was written as `- [ ] Phase N:` checkbox items inside a `
` block and the next phase had no directory on disk yet (still in planning), `phase.complete`'s `isLastPhase` roadmap-enumeration fallback used a heading-only pattern (`/#{2,4}\s*Phase…/`) that never matched checkbox items. It returned `is_last_phase: true, next_phase: null` on a mid-milestone phase and — via the milestone-complete cascade — wrongly flipped STATE.md to `Milestone complete` and decremented `progress.total_phases` (e.g. 8 → 7). The pattern now matches heading-style (`### Phase N:`), plain checkbox-list phases (`- [ ] Phase N:` / `- [x] Phase N:`), and the canonical **bold** checklist form the roadmap template emits (`- [ ] **Phase N: Name**`); `extractCurrentMilestone` already surfaces the `
`-wrapped checklist correctly, so no parser change was needed. Only the reproduced `phase.complete` fallback is changed; the heading-only sibling patterns elsewhere in `phase.cts` are untouched. + (#1819) +- The `` block emitted by `gsd init` no longer leaks backslash paths into `@`-reference skill paths on Windows. The global skill directory (a native `path.join` result) was interpolated into the generated markdown without POSIX normalization, producing references like `@C:\…\skills\name/SKILL.md`; the reference is now normalized at the emit site so skill references use forward slashes on every platform. (#1736) +- **`/gsd-settings` no longer warns about four search-provider keys on fresh projects (#1747)** — `buildNewProjectConfig` emits seven search-provider availability flags and `research-provider.cts` `providerAvailability()` consumes all seven, but only three were registered in `VALID_CONFIG_KEYS` (`config-schema.manifest.json`). Running `/gsd-settings` on a freshly generated `.planning/config.json` printed `unknown config key(s) … tavily_search, ref_search, perplexity, jina — these will be ignored` even though the user never hand-edited the config. The four missing keys are now registered alongside `brave_search`/`firecrawl`/`exa_search` and documented in `docs/CONFIGURATION.md`; a drift guard in `tests/bug-2530-valid-config-keys.test.cjs` now requires every config-driven research-provider flag to be in the schema, so a future provider addition cannot reintroduce the drift. (#1814) +- **`gsd-tools state json` no longer reports conflated progress for an unversioned milestone (#1761)** — the ADR-1769 Phase 7 fix (#1794) taught `state sync` to leave Progress untouched when a milestone version is asserted but the ROADMAP has no versioned heading for it, but the `state json` **read** path still rebuilt progress via `buildStateFrontmatter`, whose phase-heading count fell back to the whole document and summed sibling milestones. `state json` therefore reported a conflated `total_phases` (e.g. 8 = 4+4 across two milestones) plus a derived `percent`, contradicting the sync guard on the very same project. The read path now mirrors the sync guard: when the asserted milestone cannot be bounded to a versioned ROADMAP heading, `total_phases` falls back to the on-disk phase-dir count and `percent` is omitted. Bounded milestones (versioned ROADMAP, or no milestone asserted) are unchanged; the signal rides on the existing `_diskScanCache` so `extractCurrentMilestone`'s return contract and its other callers are untouched. (#1818) +- **`gsd-graphify-update.sh` now reads the full multi-line command in Gate 2 (#1772)** — the PostToolUse auto-update hook joined `tool_name` + `\n` + `tool_input.command` and extracted the command with `sed -n '2p'` (line 2 only). Agent runtimes (Claude Code's Bash tool among them) routinely emit HEAD-advancing commits as multi-line scripts (`cd /path`, then `git add`, then `git commit …`), so line 2 was the `cd`, Gate 2's `*"git commit"*` match failed, and the rebuild silently no-op'd on real commits even with `graphify.auto_update: true`. The failure was invisible in manual probes because a single-line `git commit -m x` passes line 2 verbatim. The hook now captures line 2 through EOF (`sed -n '2,$p'`) so the `case` glob sees the full command string; single-line behavior is unchanged and multi-line commands without a HEAD-advancing op still no-op cleanly. (#1815) +- **`/gsd-thread close|resume` now writes the thread status/updated frontmatter (#1778)** — the thread workflow's CLOSE and RESUME branches invoked `frontmatter.set` with the pre-1.6 fully-positional shape (`frontmatter.set `), but since 1.6 the dispatcher parses the file positionally and reads `field`/`value` from the named flags `--field`/`--value` via `parseNamedArgs`. The positional form left `field`/`value` undefined, `cmdFrontmatterSet` errored `file, field, and value required`, and the writes were silently skipped — so closing a thread never marked it `status: resolved` and resuming never marked it `status: in_progress`, with the error scrolling past on every thread command. All four sites (CLOSE `status`+`updated`, RESUME `status`+`updated`) now use the 1.6 hybrid form that `verify-work.md` already uses (`frontmatter.set --field --value `). (#1816) +- **The installer no longer copies dead lifecycle hook scripts for ZCode** — it declares `hooksSurface: 'none'` and has no plugin surface, so the staged `hooks/*.js`, `hooks/*.sh`, `hooks/lib/` and the CommonJS `package.json` marker were dead weight in `~/.zcode/`. The hook-copy guards in `install.js` now exclude ZCode alongside the other no-hook runtimes. OpenCode, which also declares `hooksSurface: 'none'`, is deliberately kept: its native plugin adapter (#1914) spawns those staged hooks via OpenCode's event bus and needs both them and the marker. (This fix originally excluded Kilo too, on the premise that it had no plugin surface; that premise was wrong — Kilo's native plugin spawns the staged guard hooks, exactly like OpenCode's — and #2327 reverses the Kilo half.) (#2057) +- **Test gates can no longer hang forever on a watch-mode test runner.** vitest defaults to watch mode in an interactive terminal (exactly where `gsd-execute-phase` runs), so a resolved `npm test` / `pnpm test` that maps to vitest never exited and the orchestrator waited indefinitely until the user manually intervened. Every GSD test-command gate — the regression gate, the post-merge gate, the audit-fix gate, and the verify-phase gate — now routes the resolved command through a shared `normalize-test-command` helper that rewrites it to a one-shot form (direct vitest → `vitest run`; jest `--watch` → `--watchAll=false`; a package-manager `test` script backed by watch-vitest → `CI=true` prefix; already-one-shot commands are left unchanged). The three gates that previously hung or silently continued — the regression, post-merge, and audit-fix gates — additionally bound execution with a configurable `workflow.test_gate_timeout` (default 600s), aborting or surfacing the cause on timeout instead of hanging; the verify-phase gate was already bounded (a fixed 5-minute limit) and keeps it, now naming watch mode on timeout. The normalizer only rewrites a runner named as a standalone command token (so paths/targets like `run-vitest.js` are never mangled), is length-capped and linear-time on adversarial input, and only reads a regular-file `package.json`. (#2060) +- **`settings-advanced.md` no longer has an orphan `` around §8 Model Policy** — the §8 Model Policy block ended with a closing `` but had no matching opening tag (5 opens / 6 closes), leaving its content as loose inter-step prose that could fail to execute reliably. Added the missing `` opener so the section is a proper step. A new workflow ``-tag-balance regression guard (fenced-code-stripped) now blocks any future orphan tag across all top-level workflows. (#1864) (#2014) +- **The runtime launcher now honors `CLAUDE_CONFIG_DIR`** — the `gsd_run` preamble embedded in every workflow/agent resolved the Claude global install only at `$HOME/.claude/gsd-core/bin/`, while the installer honored `CLAUDE_CONFIG_DIR`, so a global install redirected via `CLAUDE_CONFIG_DIR` was invisible to every `gsd_run` call (every GSD command failed with `gsd-tools.cjs not found`). The Claude resolver arm now uses `${CLAUDE_CONFIG_DIR:-$HOME/.claude}` — matching the installer and the other runtimes' `${VAR:-default}` pattern — so a custom `CLAUDE_CONFIG_DIR` is found and the default `$HOME/.claude` path is unchanged. Re-synced into all 95 workflows/agents; two capped workflows trimmed to stay under their byte budgets. (#1865) (#2024) +- **Node-test prohibition proofs now require a clean-fixture causation control** — a `node-test` prohibition's fail-first proof no longer accepts a deceptive content-independent negative test (one that reds merely because `GSD_PROHIB_SUBJECT` is *set*, ignoring the subject's content). The `check_clean_fixture` control is now **mandatory** for the `node-test` kind: a descriptor that omits it is un-provable and hard-gates, rather than greening on the violation alone. **Breaking (Hyrum):** a previously-green node-test prohibition with no clean fixture now hard-gates — blast radius is zero in-tree (no `node-test` prohibition ships today). The `lint-rule` kind is unchanged (its subject IS the linted file, no `GSD_PROHIB_SUBJECT` indirection). (#1906) (#2001) +- **Third-party capabilities now work on installed layouts.** `capability install` no longer rejects capabilities with a real `engines.gsd` range as "incompatible with GSD 0.0.0" — the host version is now read from the authoritative `gsd-core/VERSION` file across every runtime and the `capability install` CLI. The installer also now ships the registry generator scripts (`gen-capability-registry.cjs`, `gen-loop-host-contract.cjs`), so installed third-party capabilities actually compose into the loop instead of being silently discarded. (#1938) +- **`/gsd:verify-work` preserves verification state across gap-closure execution and no longer auto-promotes deferred follow-ups into blocking gaps** — resuming after `/gsd:execute-phase --gaps-only` used to lose the verification state: the UAT `## Gaps` still read `status: failed` even after their fix plans executed, so verify-work re-diagnosed them as fresh blockers, spawned a new gap plan, and reported only the new plan as verified. A state contract now links each gap to its fix plan: every UAT gap carries a stable `gap_id` (`G-{phase}-{N}`), gap-closure plans tag the ids they address in their frontmatter (`gap_ids: […]`), and a new `reconcile_gaps` step on resume marks a gap `status: resolved` when its plan has a matching `*-SUMMARY.md` — so fixed gaps aren't re-diagnosed and the phase can close. Separately, a deferred-follow-up branch captures future-work ideas (signals like "later", "next version", "out of scope") into a `## Deferred Follow-Ups` section instead of creating a blocking gap/plan. (#1921) (#2025) +- **`roadmap update-plan-progress` no longer counts stray non-plan `*-SUMMARY.md` files against phase completion** — remediation/gap-closure summaries (e.g. `30-FIX-CR02-SUMMARY.md`, `30-GAPCLOSURE-SUMMARY.md`) inflated `summary_count`, and once `summary_count >= plan_count` the phase silently flipped to `Complete` (checkbox checked, date stamped) even though several plans had no summary. A new `countMatchedSummaries` helper (core-utils) pairs summaries to plans via the `PLAN→SUMMARY` marker swap + the `-SUMMARY.md` form (layout-agnostic across root, bare, and nested layouts), so only a summary that corresponds to a real plan counts. Wired into `scanPhasePlans` (fixing roadmap listing, state sync, verification, workstream inventory at once) and `cmdRoadmapUpdatePlanProgress`. (#1988) (#2016) +- **`milestone complete --ws` requirements archive header now points at the workstream REQUIREMENTS.md** — the archive header string hardcoded the root path (`` `…see .planning/REQUIREMENTS.md` ``), so a workstream archive directed readers at the wrong file even though #1917 had already fixed the archive *locations* to land inside the workstream. The display path is now derived from the same workstream-aware `reqPath` the writer uses (`path.relative(cwd, reqPath)`), so root behavior is byte-identical and the workstream case correctly reads `.planning/workstreams//REQUIREMENTS.md`. (#1993) (#2015) +- **Load-failed capability gates now fail open with a loud warning instead of blocking the whole project** — when an installed overlay (third-party) capability failed to load (e.g. an incompatible `engines.gsd` range) but had declared a `gate`-kind loop hook, the loop resolver injected a blocking synthetic gate (`blocking:true`, `onError:halt`) at every point where that capability declared a gate. A single incompatible capability therefore halted every `ship:pre` and `verify:post` in the project — unrelated to what the gate would have checked, and with no remediation surfaced. The resolver now injects no gate and instead emits a loud warning — to stderr and in the `loop render-hooks` envelope's `warnings` array — naming the load-failure reason and the exact `gsd capability remove ` remediation, and the loop proceeds (fail open). The capability id embedded in that remediation is validated against the canonical id shape first, so a malformed overlay directory name cannot inject shell metacharacters into the surfaced command. The loader still records `_overlay.blockedGates`; only the consequence changes from block to warn. `step`/`contribution` overlays were already skip-open. (#2009) (#2075) +- **`phase.complete` now updates the `## Progress` rollup row even when an earlier phase-numbered table precedes it** — the Progress-row writer used a non-global regex that matched *any* table row starting with the phase number, so it bound to the first such row (e.g. a `| Phase | Requirements | Count |` coverage table), no-op'd on the wrong 3-column row, and never reached the real Progress row. The regex is now scoped to the `## Progress` section so it binds to the correct table. The command still returned `roadmap_updated: true` (that field is `fs.existsSync(ROADMAP.md)`), masking the silent failure. (#2012) (#2032) +- **context7 now works for plugin-marketplace installs (8 agents regained doc lookup)** — the agents granted only `mcp__context7__*`, which matches a standalone context7 MCP server but not the official Claude Code plugin-marketplace install (`context7@claude-plugins-official`), whose tools are named `mcp__plugin_context7_context7__*`. The grant never matched, so advisor/ai/domain/phase/project/ui-researcher + planner + executor silently lost documentation lookup and fell back to WebSearch. All 8 agents now grant both forms, the researcher profile table is updated, and a parity guard asserts no agent grants the standalone form without the plugin form. (#2017) (#2029) +- **`applySurface` no longer deletes every `gsd-*` agent when the skills manifest resolves empty** — the agent-prune loop in `_syncGsdDir` deleted any `gsd-*.md` not in the staged set, and when the manifest was empty/unresolvable (null manifest, no array entries, no `files` key, or an unresolvable install source root), the staged set was empty → every agent was pruned. Skills were guarded by `pruneSkillDirs`'s manifest-membership check (conservative preservation on empty manifest); agents had no equivalent. The agent-prune loop is now skipped when the manifest is empty/absent, so agents are preserved while copy (adding genuinely new agents) still runs. (#2018) (#2031) +- **`planning-config.md` global-learnings path corrected to `~/.gsd/knowledge/`** — the `features.global_learnings` row directed users to `~/.gsd/learnings/`, but the implementation (`src/learnings.cts`, `execute-phase.md`) stores and reads global learnings from `~/.gsd/knowledge/`. Anyone following the docs to inspect, back up, or seed their global learnings looked in a directory the code never touches. (#2019) (#2026) +- **Removed dead SDK file references from runtime-loaded markdown that triggered an infinite `find.exe` storm on Windows** — `agents/gsd-executor.md` pointed at `sdk/src/query/QUERY-HANDLERS.md` and `gsd-core/workflows/reapply-patches.md` at `sdk/dist/cli.js`, both retired with the SDK package (ADR-0174). AI runtimes that resolve doc references by filesystem search ran `find / -iname …`; on Git Bash for Windows `/` maps to the drive root, so `find.exe` traversed the whole disk (14h+, orphaned processes, 4M+ open handles each, unkillable). The references now resolve to live paths, and a new regression guard asserts no `sdk/src|sdk/dist|sdk/handlers` file references remain in agents/workflows/references markdown. (#2020) (#2027) +- **`roadmap update-plan-progress` no longer checks the phase checkbox without verification** — the command stamped the phase-level ROADMAP checkbox and completion date the moment the last plan summary landed (called routinely after every wave and every plan), with **no verification gate** — unlike `phase.complete` which correctly requires `readVerificationStatus(...).status === 'passed'`. Now `isComplete` requires both all plan summaries AND a passed verification, matching the `cmdPhaseComplete` contract, so the checkbox only fires after `gsd-verifier` has confirmed the phase. (#2022) (#2030) +- **`phase complete` no longer marks a milestone done out of order, nor silently writes root state in workstream mode.** Completing the numerically-highest phase while an earlier phase was still outstanding wrongly flipped STATE.md to `Status: Milestone complete` (the milestone-end check only looked for higher-numbered phases, so an out-of-order completion — e.g. Phase 10 before Phase 9 — read as the end). It now reports milestone-end only when every lower-numbered phase in the milestone is checked complete. Separately, in workstream mode with no active workstream, `phase complete` previously fell back to root `.planning` and wrote STATE.md/ROADMAP.md (and the mislabel) into the shared root other workstreams read; it now fails safe — asking for `--ws ` or an active workstream — mirroring the existing `init progress` guard. (#2066) (#2066) +- **Phase directories whose slug begins with a single digit now resolve correctly.** A phase like `46-6-rs-pipeline-orchestrator` (roadmap name "6 Rs Pipeline Orchestrator") had its phase token over-collected as `46-6` instead of `46`, so `gsd-tools` phase-by-number lookups resolved `phase_dir=null` / `has_context=false` (breaking `init.plan-phase`, `init.phase-op`, and downstream execute/verify/ship). Numeric phase-token components must now be zero-padded (≥2 digits), so a single-digit slug word is no longer absorbed into the token. Fixed consistently across every same-class implementation — `extractPhaseToken`, `PHASE_TOKEN_FROM_DIR_RE` and `canonicalPlanStem` (health checks / plan pairing), `isDirInMilestone`'s numeric matcher (milestone filtering), and `extractCanonicalPlanId` — so the health-check and milestone-filter subsystems are fixed alongside phase resolution. (#2059) +- **`gsd-tools config-set null` now clears (removes) the key instead of persisting the literal string `"null"`.** The documented "Clear" action previously fell through the value parser and stored `"null"` — a truthy value — so "cleared" keys stayed set and `config-get` returned `"null"`; for secret keys (`brave_search`/`firecrawl`/`exa_search`) a masked success line hid a truthy value on disk that integrations could pass along as a real credential. `config-set null` now deletes the key (short-circuiting the typed per-key validators so clearing an enum/boolean/number key removes it rather than being rejected), making the "Clear" flows in `settings-integrations.md` / `settings-advanced.md` actually clear. (#2058) +- **`init plan-phase` no longer collapses foreign-prefixed task/workstream IDs into numeric phases** — a query like `MEM-01` (where `MEM` is not the configured `project_code`) used to have its prefix stripped and resolve to the unrelated numeric Phase 01; it now reports `phase_found: false` unless a phase directory or roadmap entry literally carries that prefix. The configured `project_code`'s own prefixed phases (e.g. `LKML-01` under `project_code: LKML`) continue to resolve as before. (#2056) (#2105) +- **`phase complete` no longer ticks the wrong phase's ROADMAP checkbox** — completing a phase whose number also appears in a later phase's description (e.g. an idempotent re-run of an already-complete phase) used to mark the *wrong* phase done, because the checkbox-matching regex greedily spanned from `]` to any later "Phase N" mention instead of only the immediately-following phase title. (#2067) (#2079) +- **`gsd-tools effort sync` no longer crashes in an installed runtime.** In any global install (e.g. `~/.claude/gsd-core/`), `effort sync` threw `Cannot find module '../../../bin/install.js'` — the command reached into the package-root `bin/install.js` for its install-time effort resolvers, but the installer only copies the `gsd-core/` subtree into a runtime home, so that file is never present there. As a result, `effort` config changes (`routing_tier_defaults` / `agent_overrides`) silently never reached installed agents without a full reinstall. The two resolvers (`readGsdEffectiveEffortConfig` + `resolveInstallTimeEffort`, with their helpers) are now extracted into a shipped `gsd-core/bin/lib/install-effort-resolver.cjs` that both `effort sync` and the installer import — a single source of truth that is always present in the installed tree. (#2076) (#2076) +- **`model_overrides` and per-phase-type models now actually apply to the assumptions-analyzer, code-reviewer, and code-fixer agents on Claude Code.** Previously `model_overrides["gsd-code-reviewer"]` / `["gsd-assumptions-analyzer"]` / `["gsd-code-fixer"]` (and `models.verification` / `models.discuss` / `models.execution`) were accepted and resolved but silently dropped — the workflows spawned these agents with no model, so they inherited the session model and the configured routing never took effect (no warning). Every spawn now threads its resolved model: `discuss-phase-assumptions`, `code-review`, and `code-review-fix` (both the re-review and the two fixer spawns) resolve it inline, and `quick`'s review step uses the code-reviewer's own resolved model instead of the executor's. The stale "`discuss` — reserved, no subagent" model-profile docs are corrected to list `gsd-assumptions-analyzer`, and the `verification` row now includes `gsd-code-reviewer`. (#2074) (#2074) +- **`/gsd-review`'s Antigravity CLI reviewer no longer fails silently on large prompts, unavailable pinned models, or pre-session stalls** — the `agy` invocation now uses a file-reference prompt to avoid exec arg-list overflow, is wrapped in an external wall-clock `timeout` paired with `--print-timeout` because `--print-timeout` cannot fire before `agy` creates a session, passes `--model` from `review.models.agy` when set as an escape hatch for a 404'd pinned model, and its empty-output stub now surfaces an `agy` cli.log diagnostic instead of a bare generic message. Supersedes the #687 "no external killer / inline `$(cat)`" contract, which predated `agy` gaining `--model` and predated its own guidance to pair `--print-timeout` with a terminal timeout. (#2073) (#2109) +- **`init execute-phase`, `init verify-work`, and `init phase-op` no longer collapse foreign-prefixed task IDs to numeric phases** — `MEM-01` under `project_code: LKML` was silently stripped to `01` and resolved to the unrelated numeric Phase 01, because the #2056 guard was applied only to `init plan-phase`. The guard is now extracted into shared helpers (`guardedFindPhase` / `guardedGetRoadmapPhase`) that delegate to the canonical `isForeignPrefixedPhaseQuery` from `phase-id.cts`, and all four init commands route through them. (#2104) (#2149) +- **`commit --files` now commits only the declared paths** — `gsd-tools commit --files A B` previously ran a bare `git commit` that absorbed the entire staged index, silently sweeping in unrelated files the caller never named. The commit now appends a pathspec (`-- `) so only the staged subset of `--files` lands in the commit; the no-`--files` default path is unchanged. Missing tracked files are still skipped (not committed as deletions, #2014), and when all declared files are missing the function short-circuits to `nothing_to_commit` instead of absorbing the index. (#2112) (#2148) +- **Fixed unresolvable bare `require('gsd-core/...')` in `gsd-surface` command doc** — the four `require()` examples now derive the engine path from `runtimeConfigDir` (resolvable at runtime), and the reinstall hint corrects `npm i -g gsd-core` to `npm i -g @opengsd/gsd-core`. (#2116) (#2213) +- **`milestone complete --dry-run` now prints a preview plan instead of silently mutating** — `gsd-tools milestone complete --dry-run` was neither parsed nor rejected, so a caller expecting a preview triggered the full destructive mutation (archive phases, move audit artifacts, rewrite STATE.md) with no way to back out. The `--dry-run` flag is now honored: it returns a JSON plan listing `would_archive` (roadmap, requirements, audit, phase dirs) and `would_update` (MILESTONES.md, STATE.md) targets with zero filesystem mutations. (#2118) (#2155) +- **`/gsd-secure-phase` now has a single SECURITY.md writer** — the `gsd-security-auditor` subagent previously held `Write`/`Edit` tools and was instructed to "write SECURITY.md" with no padded `-` prefix and no template frontmatter, while the orchestrator's Step 6 also wrote the phase-scoped `-SECURITY.md` from `templates/SECURITY.md`. The auditor is now return-only (drops `Write`/`Edit`, returns a structured verdict with `threats_open`); the orchestrator is the sole file writer. The workflow's Step 5 spawn constraints explicitly forbid the auditor from writing SECURITY.md. (#2119) (#2154) +- **Dead security scan exports removed; injection-scan docs corrected to match reality** — `scanEntropyAnomalies` and `shannonEntropy` were dead code with zero production callers (live hooks inline their own patterns for independence). REQ-SCAN-INJ-02/-03 now accurately describe what runs live (injection patterns, invisible Unicode) vs CI-only (base64-decode, codebase scan). (#2198) (#2211) +- **Post-merge, regression, and other GSD test/build gates no longer fail with a spurious "command not found" on stock macOS.** These gates hardcoded GNU coreutils' `timeout`, which stock macOS ships neither as `timeout` nor `gtimeout`; a passing build or test run now completes under a portable, coreutils-independent `run-with-timeout` wrapper instead of exiting 127 and being misreported as a failure. (#2351) (#2426) +- **Installed third-party capability skills now materialize on OpenCode and Kilo** — `capability install` + `capability set --runtime opencode` (or `kilo`) could report a capability as `installed: true, surfaced: true, active: true` while its skill was never written to `skills/gsd-/SKILL.md`: the OpenCode/Kilo combined-family install path never called the seam #2322 fixed for other runtimes. Installed capability skills now materialize the same way there too, bound to their declaring capability, with first-party skills always winning a name collision. (#2362) (#2434) +- **Shared requirement IDs across multiple plans no longer read `Complete` before every declaring plan (and phase verification) has finished** — `execute-plan.md` now gates completion on sibling plans' `SUMMARY.md` files via a new read-only `requirements ready-ids` check, and a `gaps_found` phase verification reverts any requirement ID this phase owns back out of `Complete` before the gap report renders. Single-plan requirement IDs are unaffected — no added latency. (#2388) (#2424) +- **`phase.add` no longer silently mistakes a goal-shaped description for a phase title** — a long or multi-sentence description used to land verbatim in the `### Phase N:` header with no signal anything was off; `phase.add` now returns a `warning` field when the description looks goal-shaped, and the phase-number auto-detect docs now correctly point callers at the orchestrating workflow instead of implying `gsd-tools.cjs` resolves it itself. (#2390) (#2425) +- **`response_language` now reaches orchestrator-owned prompts across most workflows and the UAT verification checkpoint frame** — previously only subagent prompts honored a configured `response_language`; the orchestrator's own questions (verify-work, new-project, new-milestone, quick, manager, and others) and the hardcoded English UAT checkpoint banner stayed in English regardless of configuration. Both now render in the configured language, with output byte-identical to before when unset. (#2402) (#2457) +- **Codex installer no longer double-registers each agent role in `config.toml`, eliminating one duplicate-role startup warning per agent** — `generateCodexConfigBlock` stopped emitting `[agents.gsd-*]` tables whose `config_file` pointed back at the same standalone TOMLs Codex already auto-discovers under `$CODEX_HOME/agents/`; reinstalling over an existing config also drops any legacy managed role tables left by a prior install while preserving unrelated user config and the user's own AgentsToml scalars. (#2406) (#2432) +- **Production dependency tree carries no known advisories** — five advisories disclosed against the transitive tree under `@anthropic-ai/claude-agent-sdk` → `@modelcontextprotocol/sdk` were cleared: `fast-uri` (GHSA-4c8g-83qw-93j6, high) and `hono` (GHSA-xgm2-5f3f-mvvc, GHSA-hvrm-45r6-mjfj, GHSA-w62v-xxxg-mg59) re-resolved to patched releases inside their already-declared ranges with no `package.json` change, and `@hono/node-server` (GHSA-frvp-7c67-39w9) pinned to `>=2.0.5` via `overrides` because `@modelcontextprotocol/sdk@1.29.0` — already the latest published version — still declares the vulnerable `^1.19.9` range. `npm audit --omit=dev` reports zero advisories. (#2496) (#2497) +- **Custom STATE.md frontmatter keys are no longer dropped on every mutating verb** — syncStateFrontmatter rebuilt the frontmatter from a fixed schema, silently dropping any custom key. It now carries forward existing keys the schema does not own. (#2202) (#2233) +- **Non-frontend phases with `UI hint: no` are no longer blocked by the UI-SPEC gate** — the UI safety gate's token list included the bare token `UI`, which matched GSD's own `**UI hint**: no` metadata line and false-detected a UI, blocking backend/infra phases at /gsd-plan-phase. An explicit `UI hint: yes|no` is now authoritative and the hint line is no longer token-sniffed. (#2150) (#2222) +- **OpenCode reviewer no longer silently yields an empty review on large prompts** — `/gsd-review --opencode` now invokes `opencode run --format json` and reconstructs the review from the assistant text parts, so a large-prompt run where the default `build` agent ends its turn with zero output tokens no longer produces an empty stub. When the agent genuinely emits no text, the stub now reports the stop reason, output-token count, and captured stderr instead of a generic message. (#1936) (#1992) +- **OpenCode's first-time install baseline now protects pre-existing files under the `commands/` directory, not just the legacy `command/` alias** — after #2329 moved OpenCode command materialization to `commands/`, the baseline scan that guards a machine's very first GSD-tracked install still only knew about the legacy `command/` directory, so a pre-existing, unrelated `commands/gsd-*.md` file was silently deleted by ordinary command materialization instead of blocking the install for an explicit keep/remove choice — the same protection `command/` already had. The scan now covers both directories. Kilo is unaffected and keeps using `command/`. (#2354) +- **api-coverage detector no longer false-positives non-API phases (and no longer fails open)** — the external-API-integration detector behind the blocking `verify:pre` seal gate required only same-line co-occurrence of an integration verb and an API noun, treated `/` as a word boundary (so first-party Next.js `src/app/api/…` route paths matched), and read any capitalized word before API/SDK/REST/GraphQL as a service name (so threat-model prose like "Resolver-only API" fired). It is now **fail-closed**: the compound rule requires the integration verb and API noun to share one clause (the clause boundary is the whole relationship test — no fragile word-gap cap that a genuine long integration clause would trip); fenced code, inline code spans, and path-shaped tokens are excluded before matching while external hosts like `api.stripe.com/v1` still count; and the ` API` surface rule rejects stopwords, locality/protocol descriptors ("Internal API", "REST API"), compound modifiers, and first-party-qualified services, so a real vendor name (`Stripe API`) fires from any clause position. A phase that integrates no external API can declare it first-class in `COVERAGE.md` — `No external API integration: ` — instead of fabricating a matrix row; when the detector still finds signals, the declaration overrides but the gate surfaces the overridden signals so the contradiction is visible. Because a false positive is cheaply dismissed by that declaration while a false negative silently slips a real API phase past the gate, the detector deliberately leans toward detecting. (#2365) (#2397) +- **`stale-bake-guard` hermeticity fix (test-isolation)** — the readGsdEffectiveModelOverrides subtest no longer reads the developer's real `~/.gsd/defaults.json`; the resolver now accepts a homedir seam so the test sandboxes HOME. (#2152) (#2223) +- **`/gsd-surface` (`list`/`status`) works on Claude Code global installs** — the installer now writes a `.gsd-source` marker pointing at its `commands/gsd` source, so `findInstallSourceRoot` resolves on the global skills layout (which ships no `commands/gsd` tree) instead of throwing `could not locate commands/gsd`. (#1487) (#1487) +- **Cursor no longer shows every `/gsd-*` command twice** — a `--cursor` install wrote both a skill and a slash command for each action, so every GSD entry appeared twice in Cursor's `/` menu. GSD now installs Cursor skills as `user-invocable: false` (matching the existing CodeBuddy behavior), so the slash command is the single `/` entry point while skills remain model-invocable. (#2341) (#2386) +- **`phase complete --phase N` now works alongside the positional form** — the phase verb family treated the first positional as the phase number, so `--phase 12` was passed as the literal phase name and failed with 'Phase --phase not found'. The phase family now accepts the --phase flag consistently with the state family, and unrecognized flags yield a usage error. (#2201) (#2231) +- **Third-party capability skills now surface correctly after install** — a skills-only `role: feature` capability installed `active` but its skills never reached the runtime surface, `capability enable`/`set` rejected it as `unknown capability`, and `capability list` disagreed with `capability state`. `resolveSurface` now unions the composed registry's `capabilityClusters` into the surfaced skill set (no on-disk linking), the writer validates against the composed overlay-aware registry, and `capability list` carries a `surfaced` field matching `capability state`. (#2054) +- **`/gsd-ship` no longer emits a 100%-missing TDD Audit noise table** — the TDD Audit PR-body section was always emitted, but the execute pipeline only writes `gate_status:` git trailers when TDD mode is active. Without TDD mode (the default), every commit was counted `missing` and the table was pure noise with no way to disable it. The section is now gated behind `workflow.tdd_mode`: when TDD mode is off, both the TDD Audit section and the aggregate `gate_status:` trailer are skipped entirely; when on, the existing behavior is preserved. (#2467) +- **`phases.clear` now archives phase history under the outgoing milestone version, not the newly-switched one** — because `new-milestone` advances the milestone before clearing leftover phases, the phase-history archive was silently misfiled under the new milestone's `-phases/` directory. A new `--archive-version` override on `phases.clear` (threaded from the new-milestone workflow) files the archive under the previous milestone's version; without it, behavior is unchanged. (#2288) (#2323) +- Fixed: probe-core's runProbeCli now fails closed on per-item adapter garbage inside a well-shaped report envelope, matching its documented 'fails closed on adapter garbage' contract. (#1910) +- **Deferred out-of-scope findings logged to `deferred-items.md` are now surfaced** — the executor's SCOPE BOUNDARY convention writes discoveries to a phase directory's `deferred-items.md`, but nothing read it back, so those items were permanently invisible. `/gsd-progress`'s forensic audit and `audit-uat` now glob `.planning/phases/*/deferred-items.md` and surface unresolved entries. (#2287) (#2318) +- **`/gsd:verify-work` no longer silently terminates when all remaining UAT tests are blocked** — sessions with `blocked_count > 0` and `pending_count == 0` now route to `complete_session` as expected, enabling the zero-issues auto-transition path. (#1722) +- **state record-metric no longer appends per-plan rows into the By-Phase velocity table** — it now maintains its own Per-Plan Metrics table (self-created on first use), and its auto-create scaffold header is corrected. (#2253) (#2253) +- **Dynamic routing now escalates the model, not just effort** — with `dynamic_routing.enabled`, retry attempts advanced the reasoning effort but the model stayed pinned to the default tier because `resolve-execution` resolved the model without consulting `dynamic_routing`. `resolve-execution` now resolves the model per-attempt through the tier ladder (e.g. standard→heavy on attempt 1, capped at `max_escalations`); resolution is unchanged when dynamic routing is disabled. (#2068) (#2334) +- **`/gsd-next` no longer reports a project as complete while phases are still unchecked** — `smart-entry`'s completion check now grounds in ROADMAP.md's actual Progress table (global, authoritative) instead of STATE.md's stale milestone-scoped total_phases, and its status regex requires milestone-level language (`milestone complete` / `all phases complete` / `complete`) instead of matching any per-phase `shipped` or `done` substring. Together these fix the false-complete misclassification that could route `/gsd-next` toward `/gsd-new-milestone` — which archives still-pending phase directories. (#2466) +- Codex reviewer now captures the review via codex's --output-last-message flag instead of redirecting stdout, so Windows process-teardown output no longer pollutes the review file and slips past the empty-output guard. (#1709) +- **`last_activity` now shows your local calendar day** — the clock seam derived the date by slicing a UTC instant, so in negative-UTC-offset zones during UTC's early evening the date-only `last_activity` field jumped a day ahead of the operator's actual date (and of `last_updated`'s local date). Operator-facing date fields now use a host-local calendar day while internal/cosmetic stamps stay UTC. (#2136) (#2216) +- **A phase with a deliberately-unexecuted (superseded) plan no longer stays stuck below 100%** — a plan reassigned or dropped mid-phase can never gain a matching SUMMARY, yet plan-scan counted it forever, so the phase read In Progress and the milestone sat below 100% permanently — the plan-level analogue of the retired-phase bug (#1514). Mark such a plan `status: superseded` in its PLAN.md frontmatter and it is now excluded from both the plan and summary counts, so the phase completes honestly (a 13-plan phase with 2 superseded reads 11/11). Plans without the marker are unchanged. (#2349) (#2404) +- **`milestone_name` is no longer clobbered with a delimiter-led fragment** — getMilestoneInfo's `##` heading regex was unanchored, so it matched a heading quoted inside backticks in the Milestones bullet and wrote garbage like `— Active Milestone` over the curated milestone name on every phase transition. Now consults the 🚧 marker first, anchors the regex to line start, strips the leading delimiter, and widens the preserve guard so a bad derive keeps the existing name. (#2135) (#2215) +- **`init milestone-op` now counts project_code-prefixed phase directories correctly** — fully shipped milestones using the standard prefixed directory layout no longer report `completed_phases: 0` or stay falsely incomplete. (#1844) (#1844) +- **`/gsd-mempalace-capture` no longer crashes on first invocation** — the skill's own documented `rooms:` example wrote a flat list of bare strings, but mempalace's miner expects each entry as a dict with a `name` key, so following the example verbatim and running `mempalace mine` crashed with `TypeError: string indices must be integers, not 'str'`. Both `skills/gsd-mempalace-capture/SKILL.md` and `commands/gsd/mempalace-capture.md` now ship the corrected `- name: ` shape, so the documented example runs successfully end-to-end. (#2464) +- **`/gsd-quick` no longer halts with a stale-base worktree mismatch** — the worktree executor now degrades to sequential execution when its fork base has diverged from origin/HEAD, instead of spawning a worktree guaranteed to fail the base-mismatch guard. (#1991) +- **`GSD_ALLOW_SYMLINKED_DEST=1` lets users with intentional symlinked configHome layouts install/update again** — v1.7.0's destSubpath write-confinement (ADR-1239 Phase B) refused install/update whenever CLAUDE_CONFIG_DIR (or an artifact-kind child like `skills/` or `hooks/`) was a pre-existing symlink, with no opt-out. Three legitimate user-owned layouts were blocked: multi-account configs with symlinked shared skills/hooks (POSIX symlinks), Windows Junctions to shared skills dirs, and dotfiles-managed configHome (e.g. nix-darwin symlinking `~/.claude` itself to a version-controlled dir). The new env var follows user-owned symlinks instead of refusing them, while preserving the two load-bearing refusals from the original threat model: path-traversal in the destSubpath string itself (`../../etc`-style), and a symlink resolving to the install root itself (would let the prune pass wipe it). (#2393) (#2445) +- **`state record-session` no longer silently drops inserted fields on a CRLF `STATE.md`** — the section-rewrite regexes in `cmdStateRecordSession` used literal `\n` which couldn't match a CRLF STATE.md (`---\r\n`), so when a canonical session field (`Resume file` / `Stopped at` / `Last session`) was missing and had to be **inserted** via the section-rewrite path, the CRLF-tolerant detector entered the branch, the writer regex silently no-op'd, but `updated.push(...)` ran unconditionally. The command returned `{"recorded": true, "updated": ["Resume File"]}` while the field was never written to disk. With `core.autocrlf=input`, the CRLF working-tree file produced no `git diff`/`git status` change, so the bug was invisible. Both regexes now use the CRLF-tolerant `\r?\n` form (same canonical pattern already in use elsewhere), and a new defensive invariant gates `updated.push(...)` on the replace callback actually firing — so a future detector/writer drift will surface as missing `updated` entries rather than re-arming this silent-success class. (#2482) +- **`/code-review` no longer skips a phase whose SUMMARY.md records `~/`-prefixed file paths** — such a path was silently dropped as "deleted" (bash never tilde-expands a `~` that arrives as a variable's value), emptying the review scope and reporting "no source files changed" as a false success. Tilde paths are now expanded to `$HOME/…` before the deleted-file filter runs. (#2419) +- **Setting `external_job.submit_timeout_ms` / `poll_timeout_ms` / `artifact_dir` in `.planning/config.json` now actually configures the SLURM adapter** — the keys were declared by the external-job capability but the adapter only read env vars, so config edits silently had no effect. The adapter now resolves them through the canonical capability-config seam (env override > config > registry default), surfaces the resolved `artifact_dir` in `submit` output, documents why the contribution registers at `execute:wave:post` (#1164 asks for `wave:pre`, which `execute-phase.md` does not dispatch today; wiring it is a core-loop change #1164 explicitly defers), and gains unit coverage for the CLI surface (`parseFlags`, `findPlanningDir`, `resolveExternalJobSettings`, `formatShowReport`). (#1164) (#2006) +- **The Antigravity reviewer in `/gsd-review` no longer reviews blind** — `agy -p` never granted the agent the repo under review, so it frequently anchored on its own scratch directory and returned plan-text-only verdicts counted at full consensus weight. The reviewer is now granted the repo (capability-probed `--add-dir`) and anchored to the absolute repo root; a review that still runs without repo access is stamped `[reviewed-without-repo-access]` and down-weighted in the Consensus Summary. The cursor-agent prompt gains the same absolute-root anchor. (#2176) (#2184) +- **Non-Claude installs no longer brand all GSD output as Claude** — the installer never persisted `runtime: ` into `~/.gsd/defaults.json` for non-Claude runtimes, so `resolveRuntime()` (precedence: `GSD_RUNTIME` env > `config.runtime` > `'claude'`) fell through to the hard-coded `'claude'` default. A non-Claude install showed `agent_runtime: "claude"` and Claude-formatted `/gsd-*` slash hints with no env or config hand-set. The installer now persists `runtime: ` into `~/.gsd/defaults.json` for non-Claude runtimes, mirroring the existing `resolve_model_ids: "omit"` write at the same call site. Claude is the fallback so it needs no write; an explicit pre-existing `runtime` value is always preserved. (#2395) (#2446) +- **Autonomous reruns now skip phases with deferred verification until you resume them explicitly** — if a prior `/gsd-autonomous` run recorded `verification_deferred_human` or `verification_deferred_gaps`, later reruns no longer drop back into the same prompt loop and instead point you at the saved resume command. (#1846) (#1846) +- **`requirements mark-complete` no longer reports silent success when the traceability row is missing** — it OR-ed its checkbox and table-row writes into one flag, so a checkbox-only reconcile returned a payload byte-identical to a full reconcile while the traceability row stayed Pending (and re-run masked it as already-complete). It now surfaces `table_unmatched` for IDs whose checkbox reconciled but whose table row is absent, and treats a checked box with no table row as partial rather than done. (#2140) (#2219) +- state prune now resolves the current phase from the canonical location — frontmatter current_phase, the Current Phase field, or the prose Phase: line scoped to the ## Current Position section — instead of extracting Phase over the whole document, where stateExtractField's pipe-table fallback could latch onto an unrelated | Phase | N | row (e.g. a historical verification table) and compute a wrong prune cutoff. (#1832) +- **`model_overrides` Claude model IDs now resolve to Agent-tool aliases on the claude runtime** — a full Claude model ID (e.g. `claude-sonnet-5`) in `model_overrides` was returned verbatim and silently dropped by the Claude Agent tool (whose `model` parameter documents only tier aliases), causing the spawned subagent to inherit the parent session model instead of the configured one. It now maps to the tier alias (`sonnet`/`opus`/`haiku`/`fable`), consistent with the `model_policy` path (#1144). Bare aliases, non-Claude values, and non-Claude runtimes are unchanged; a Claude ID with no alias warns once and falls through to tier resolution. (#2041) (#2048) +- **`validate health` no longer false-flags the `adaptive` model profile, and now warns when a `models.` tier is invalid** — health reported `W004 invalid model_profile "adaptive"` for a profile that has been valid since v1.40, and a typo like `"planning": "opuss"` was accepted in silence while the resolver quietly ignored it. Health now sources its profile list from the model catalog and emits `W022` for unknown phase types and invalid tier values. (#2336) +- **Phase dirs whose slug leads with a multi-digit number (e.g. a year) resolve again** — a phase like `14-2026-photos-performance` (roadmap name "2026 Photos & Performance") had its phase token over-collected as `14-2026`, so `init.plan-phase`, `init.execute-phase`, `phase-plan-index`, `state.planned-phase`, and `roadmap.annotate-dependencies` reported `phase_dir=null` / `plan_count=0` while the directory existed. Continuation segments of a phase token are now capped at the exactly-2-digit zero-padded form the write side emits, via a single shared grammar source consumed by all five parsing sites (the residual case from #2043). (#2232) (#2254) +- Phase headers that place a parenthetical tag before the colon (`### Phase 26 (Cluster B): Title`) now resolve and enumerate the same as untagged headers. Previously the resolver returned not-found and `roadmap analyze`/listing silently dropped the phase (wrong phase_count, progress, and next_phase). Tag tolerance is applied at every phase-header read site; untagged and all existing header formats parse unchanged. (#1765) +- **`/gsd-stats` no longer misreports a phase as Not Started when two directories collide on the same phase key** — `cmdStats` now folds colliding statuses by precedence (Complete > Needs Review > Executed > In Progress > Planned > Not Started) instead of overwriting last-write-wins, so the furthest-along status wins regardless of `fs.readdirSync` order. Separately, `/gsd-health` now emits a new W023 warning whenever two or more real phase directories collide on the same normalized phase key, naming both directories and their independently-computed statuses (neutral wording — never guesses which is the real one). (#2461) +- Executor and milestone-summary/forensics workflows now call state.* commands with named flags so the named-only router records metrics, decisions, blockers, and session continuity instead of silently dropping positional args. (#1873) +- **bug-1367 install test no longer fails on Windows CI when hooks/dist isn't pre-built** — the test ran install.js without building its hooks/dist precondition (a gitignored build artifact the unit lane doesn't build), so on a lane without pre-built hooks the installer hit "Failed to install hooks: directory is empty" and the before-hook threw. The test now builds hooks in its own before() (mirroring golden-install-parity). (#1926) (#1927) +- **`/gsd-fast` now appends Quick Task rows to STATE.md again** — the log_to_state column-count guard used an off-by-one awk formula (`NF-1`) that was always one too high, so the schema gate rejected the very table quick.md creates and silently skipped the STATE.md update. Also now supports the 6-column validate-mode table. (#2133) (#2214) +- Build the gitignored `hooks/dist/` artifact once upfront in `scripts/run-tests.cjs` (the same chokepoint as `ensureBuiltArtifacts`), before any concurrent install test spawns `install.js`. Closes the scoped-CI first-build empty-dir race that intermittently failed install tests with `Failed to install hooks: directory is empty` (e.g. `bug-3683-workflow-colon-namespace-leak`). (#1967) (#1968) +- **workstream progress no longer reports shipped milestones as `executing`** — `gsd-tools workstream progress` now derives each workstream's status from authoritative shipped signals (an archived milestone snapshot under milestones/, or a SHIPPED marker in the workstream ROADMAP) instead of trusting the mutable STATE.md `Status` field, so a stale field can never hide a shipped/archived milestone. The output adds `status_source` (`field` | `derived`) and `status_conflict` (true when the derived value disagrees with the stale field). (#1913) (#1916) +- **Windows install/upgrade/state-write operations no longer fail on transient antivirus/indexer file locks** — the fs.renameSync atomic-publish sites (install state, hooks config, capability ledger/lifecycle, phase/workstream/milestone dirs, roadmap, planning/state locks) now retry EPERM/EBUSY/EACCES via retryRenameSync instead of propagating the transient lock; enforced by the new local/require-fs-op-fallback lint rule (ADR-1703 Phase 6). (#1740) (#1742) +- reconstructFrontmatter now emits valid YAML for scalars and block-array items that were previously serialized unescaped. Values carrying a YAML indicator plus a literal quote/backslash, embedded control characters, the empty string, a leading YAML indicator, or leading/trailing whitespace are now routed through a properly escaped double-quoted form, so frontmatter round-trips through strict parsers (js-yaml, PyYAML) instead of corrupting the block on the next state sync. (#1807) +- **`phase remove` no longer destroys the Progress table when removing the last phase** — deleting a phase used a whole-document regex whose scan, on the final phase, ran past the section and swept away the `## Progress` heading and its entire tracking table; the deletion is now structurally bounded to the phase’s own section. (#2253) (#2253) +- **Subagent prompts embedding orchestrator-relative planning paths now resolve correctly when the spawned subagent's own working directory differs from the orchestrator's (e.g. a git worktree)** — `init.*` (and `state.load`) command handlers now emit `state_path`, `roadmap_path`, `phase_dir`, `project_path`, `research_dir`, `codebase_dir`, `intel_dir`, `conflicts_path`, `debug_dir`, and similar fields as absolute paths anchored on the project root, and the planner/checker/verifier/synthesizer/roadmapper/debugger/mapper/classifier subagent-prompt blocks that previously hardcoded bare `.planning/...` literals now reference those fields instead; a subagent spawned into a different cwd would previously report real, already-committed files as missing. (#2376) (#2428) +- **`phases clear` archives phase directories instead of destroying them** — at a milestone switch, committed phase directories were hard-deleted (`rmSync`) with no archive, silently losing browsable phase history (the #1447 dirty-tree guard was a no-op for the common committed case). Phase directories are now moved to `milestones/-phases/` (collision-safe; timestamp fallback when no version resolves), so history survives the switch. The #1447 uncommitted-changes guard is retained as a secondary backstop. (#1871) (#1919) +- **`/gsd-review` and `/gsd:ship` temp files are now scoped to a single per-run directory** — both workflows previously wrote prompt, section, and reviewer-output files to `/tmp/gsd-review-*-{phase}.*` keyed only on the bare phase number, so two projects sharing a phase number (or a crashed run's leftover file) could collide and silently feed a reviewer another project's stale content with no error; every temp path now lives under one `mktemp`-created run directory that's removed after the review completes. (#2358) (#2433) +- **Cross-AI review no longer silently drops the Codex/Claude/Gemini lanes on large plan sets** — the prompt-fed reviewer blocks in review.md invoked each CLI with no explicit timeout, so a slow source-grounded review was killed at the host default (~2 min) and the lane was silently lost. The workflow now directs a high Bash timeout and frames an empty output as a timeout (not the crash it was misdiagnosed as). (#2194) (#2226) +- **Runtime brand-swap no longer mislabels `` comparison tables** — every runtime installer that rebrands "Claude Code" to its own name (Cursor, Windsurf, Trae, Cline, CodeBuddy, Qwen, Hermes) also swapped it inside the runtime-comparison tables in shipped workflows, where "Claude Code" is a compared-runtime label, not a host self-reference — corrupting the comparison. Branding now protects `` regions while still rebranding genuine self-references. (#2284) (#2309) +- **`check tdd.review-checkpoint` no longer silently skips TDD plans with CRLF line endings** — the frontmatter regex at `src/check-command-router.cts:751` used literal `\n` which couldn't match a CRLF PLAN.md delimiter (`---\r\n`), so a Windows-authored `type: tdd` plan was silently classified as "no type:tdd plans found" and the advisory gate short-circuited to a confident pass with no violations table. The regex now uses the same CRLF-tolerant form (`/^---\r?\n([\s\S]*?)\r?\n---/`) already in use elsewhere in the same file (line 205, `extractPlanDesignatedSections`). With `core.autocrlf=input`, the triggering CRLF was invisible to `git diff`/`git status`, so the contributor had no way to tell their plan was being misclassified. (#2477) +- **Phase verification no longer reads `stale` from filesystem timestamps alone** — staleness is now derived from git commit times instead of file mtimes, so a phase whose report declares `status: passed` stays passed across a fresh `git clone`, `cp -R`, or an unrelated `touch`/reformat, instead of being silently downgraded to `stale` by a checkout-order mtime skew. (#2348) (#2394) +- **`/gsd-progress` no longer reports a stale root milestone in workstream mode** — in a multi-workstream project with no active workstream set, `gsd-tools query init.progress` silently fell back to root `.planning/STATE.md` (often stale) and reported it confidently. It now fails safe with an actionable error naming the available workstreams and the `--ws`/`workstream set` fix, so a stale root value is never reported. Flat mode and `--ws ` are unchanged. (#1912) (#1918) +- **Kilo installs now stage the shared PreToolUse guard hooks the native plugin spawns** — Kilo's capability descriptor declared both a `nativePlugin` (which spawns `gsd-prompt-guard`, `gsd-read-guard`, and `gsd-worktree-path-guard` as subprocesses) and `skipSharedHooksInstall: true` (which suppressed staging those scripts into the Kilo config dir), so every guard silently no-opped on every Kilo install. The skip flag is removed (Kilo now stages the same hooks bundle as OpenCode, whose byte-identical plugin was unaffected), and the plugin's `runHook` now warns loudly — once per hook file — when a guard script is missing instead of treating the absence as a silent allow. Resolves #2305. (#2327) +- **The decision-coverage gate no longer fails open on unrecognized decision-ID prefixes** — `check.decision-coverage-plan` classified a populated `` block as "no trackable decisions" (a clean pass) whenever its IDs used a prefix the parser couldn't read (e.g. `D5-01` instead of `D-01`), silently skipping the gate on real decisions. The gate now recognizes any bold-lead-in decision bullet as evidence and fails loud (`could-not-parse`) when it can't read a populated block, instead of passing. (#2347) (#2389) +- Windows: stop double-quoting $CLAUDE_PROJECT_DIR-anchored managed node hook paths during the #2979 legacy rewrite, which produced "\"$CLAUDE_PROJECT_DIR\"/..." and broke every node managed hook with MODULE_NOT_FOUND (PreToolUse-guard deadlock). (#1746) +- **`/gsd-stats` and STATE.md progress no longer freeze stale `total_plans`** — the progress ratchet was applied to the whole progress record, so any single counter decreasing (e.g. `completed_plans`) froze every field including `total_plans`. Now `total_plans` always takes the freshly derived value (joining `total_phases` from #1446), so it corrects in both directions — upward when a new phase adds plans, downward when a milestone reorganization removes phases. The write-path `applyStatePreservation` also switched from wholesale block restore to per-field merge, so `state planned-phase` writes a consistent `total_plans` instead of the pre-transform stale value. (#2468) +- **phase complete now updates STATE progress on milestone-grouped roadmaps** — deriveProgressFromRoadmap parses the ## Progress table by header (column-by-name) instead of a fixed 4-column layout, so the 5-column milestone-grouped shape is no longer silently unparsed. (#2168) +- **Windows Claude Code hooks now work under PowerShell** — when Claude Code's hook runner resolves to PowerShell (not Git Bash), every GSD-installed hook failed with `Unexpected token` because the installer emitted bare quoted paths with no PowerShell call operator. The fix adds a `hookShell` parameter to the hook-command projection chain; when `hookShell='powershell'`, the `&` call operator is prepended. Default behavior (Git Bash, no prefix) is unchanged. (#2236) (#2261) +- **`/gsd-debug` now auto-resumes instead of stopping mid-investigation** — when the debug session-manager's own turn ended before the investigation was complete, the orchestrator treated the intermediate progress summary as completion and returned control to the user. It now recognizes a non-terminal `CONTINUE_REQUIRED` return, auto-resumes from the on-disk checkpoint, and only stops for genuine terminal conditions (with a no-progress anti-loop guard). (#2257) (#2300) +- **Installing a non-Claude runtime no longer breaks Claude's model resolution in no-project sessions** — the installer writes `resolve_model_ids:"omit"` for non-alias runtimes into the machine-wide `~/.gsd/defaults.json`, which any runtime read back, so install order silently flipped Claude's adaptive tier aliases (executor→sonnet, planner→opus) to an empty model string. Resolution is now scoped to the runtime actually resolving, via a per-install `.gsd-runtime` marker: Claude ignores a global-defaults omit and keeps its tier aliases, non-alias runtimes still omit, and an explicit project-level `omit`/`true` is always honored. (#2297) (#2332) +- **`check.decision-coverage-plan` no longer false-blocks on decisions cited in ``/``/``/``/``** — the gate scanned only ``/``/``/`` tag bodies while its remediation message claimed "(or body)". A decision faithfully cited in any of the five other planner-canonical tags (the natural place for "read this CONTEXT decision before editing" pointers, verification steps, acceptance criteria, etc.) was reported as uncovered with a misleading fix-hint that sent the fixer to "the body" — where a re-citation still failed. The scan now covers all nine planner-canonical tag bodies AND the message names the surfaces it actually scans, so message and behavior cannot drift apart again. (#2372) (#2443) +- **`capability state` and `loop render-hooks` now accept `--runtime` to override the auto-detected runtime** — previously both commands parsed only `--config-dir`, so the runtime config dir was derived from the persisted `.planning/config.json` runtime (precedence `GSD_RUNTIME` → `config.runtime` → `claude`). A repo that persisted `runtime:"codex"` resolved the config dir to `~/.codex`, where the Claude skill isn't installed, so every skill-bearing capability reported `surfaced:false` and `execute:post`/`verify:post` hooks silently no-op'd when the operator drove GSD from Claude Code. `--runtime ` (canonicalized, so aliases like `codex-app` work) now bypasses that fallback so the config dir resolves to the explicitly-named runtime's home. Behavior without the flag is unchanged. (#2003) (#2051) +- **`/gsd` now registers on pi** — installing GSD for pi wrote its extension as `gsd.cjs`, a suffix pi's extension auto-discovery skips silently, so `/gsd` never appeared and nothing reported an error. The extension now installs as `gsd.js`, and upgrading removes the stale `gsd.cjs`. (#2470) (#2478) +- **`phase complete` no longer false-reports REQ-IDs as missing when the traceability table leads with a status column** — the parser required the REQ-ID in the first column, so a table shaped `| ☐ | REQ-01 | …` matched zero rows and every body REQ-ID was reported missing. It now matches REQ-IDs in any column. (#2203) (#2234) +- **`init milestone-op` now ignores backlog `999.x` headings when counting milestone phases** — parked backlog items no longer inflate `phase_count` or pin `all_phases_complete` false for an otherwise finished milestone. (#1843) (#1843) +- **Phase archival is now wired end-to-end across the milestone lifecycle** — finishes the #1871 follow-up: `phases archive` is now a real command (the half-wired alias is routed, no longer errors Unknown), `milestone complete` archives phase dirs by default (`--no-archive-phases` opts out), and `new-milestone` §6 stages the archive move + source removal in the same commit so history is preserved atomically rather than left as orphaned uncommitted deletions. (#1871) (#1924) +- **`state update-progress` no longer mangles the frontmatter and discards the progress suffix** — its Progress: regex matched the raw STATE.md including frontmatter, so the YAML `progress:` key was hit first (corrupting the frontmatter) while the body line stayed stale and was silently reverted on the next write, and any descriptive suffix after the progress bar was destroyed. It now targets the body line only and preserves the suffix. (#2177) (#2224) +- **`/gsd-plan-review-convergence` no longer silently overrides configured reviewers with Codex** — a bare invocation (no reviewer flags) now respects `review.default_reviewers` (and, transitively, `review.reviewer_instances`) per ADR-0011/ADR-0015, instead of always injecting `--codex` and bypassing the configured default. Users without `review.default_reviewers` configured still get `--codex` as before. The startup banner now shows what will actually run. (#2451) +- **`/gsd-ship` no longer silently drops the ship-status note from STATE on merge** — the track_shipping step committed the STATE ship-note after creating the PR but never pushed it, so on a fast merge the note stayed local-only and never reached the default branch. The ship-note is now pushed onto the PR branch with a `[ci skip]` trailer so it lands on merge without a redundant pipeline. (#2138) (#2217) +- **`/gsd-debug` no longer stalls on a phantom background handoff** — the orchestrator treated the foreground session-manager spawn as a background task and queried its agent ID via TaskOutput (which needs a task ID), then waited on a handoff that was never queryable. The workflow now states the spawn is foreground/blocking, forbids passing an agent ID to TaskOutput, and gives a lost-handoff recovery path. (#2196) (#2227) +- **Roadmap phase lookup now ignores fenced examples and the backlog sentinel lane** — `roadmap get-phase` and `init plan-phase` no longer return fenced sample headings as real phases or treat `999.x` backlog items as active milestone work. (#1845) (#1845) +- **`phase complete` no longer checks the wrong ROADMAP checkbox or writes the plan count into a shipped milestone** — the roadmap mutators ran unanchored and un-milestone-scoped, so they could flip a bullet inside a backticked prose literal or a Backlog entry instead of the closing phase's, and write the plan count into a same-numbered phase in a shipped milestone. The checkbox flip is now line-anchored and both writers are scoped to the current milestone. (#2200) (#2229) +- **`audit-uat` no longer reports a false-clean `total_items: 0` when real items exist** — the parsers ignored two artifact shapes: a `## Gaps` section recording open findings, and verification items declared in frontmatter (`human_verification:` array) or as `### N.`+bold-paragraph blocks. audit-uat now surfaces unresolved `## Gaps` entries and reads the frontmatter array / heading shape, so a phase with outstanding UAT/verification work is no longer waved through as clean. (#2286) (#2317) +- **`claude_orchestration.enabled: true` now actually routes execute-phase waves through the Workflow backend** — the capability shipped registered-but-inert: nothing in `/gsd-execute-phase` ever called its backend detection, and the `execute:wave:pre` hook it needed was declared but never rendered, so enabling it had zero effect. execute-phase now renders `execute:wave:pre` before each wave and, when the capability is enabled and all gates pass, dispatches independent plans via the generated Workflow script; any gate miss or disabled config falls back to byte-identical inline dispatch. (#2285) (#2314) +- **`roadmap get-phase` resolves project-code-prefixed headings by bare number** — a bare-number query (e.g. `29`) now resolves a drifted `### Phase AB-29:` heading, matching the internal resolver used by `init.phase-op`; previously the CLI returned empty. A bare sibling (`### Phase 29:`) still takes precedence. A project-code-prefixed heading present only as a summary/checklist line (no matching detail section) now reports a `malformed_roadmap` diagnostic — for both prefixed and bare-number queries — instead of a silent empty result. (#2114) (#2139) +- **`query config-get` now returns capability-registry defaults for absent keys** — keys declared with a default in the capability registry (e.g. `workflow.security_enforcement`, which defaults to `true`) previously reported "Key not found" (exit 1) when missing from config.json, diverging from the runtime's own resolver and letting `... || echo false` guards silently read the security gate as disabled. config-get now resolves these through the same registry defaults the runtime uses. (#2256) (#2299) +- **`milestone complete --ws` now archives into the workstream instead of root** — the archive paths (MILESTONES.md, the milestones/ archive dir, and the per-version MILESTONE-AUDIT.md) were hardcoded to root `.planning/`, so a workstream milestone close scattered its artifacts into root and never produced a workstream-local archive. They now derive from the workstream-aware planning base (`planningPaths(cwd).planning`); flat-mode (no --ws) is unchanged. (#1911) (#1917) +- **`/gsd:new-milestone --ws ` no longer overwrites the shared PROJECT.md milestone heading** — in workstream mode the shared `.planning/PROJECT.md` had its `## Current Milestone` heading rewritten with one workstream's milestone, so with parallel workstreams whichever ran last silently won the shared heading. The milestone-state write in Step 4 is now skipped when a workstream is active, and the commit no longer stages PROJECT.md. The `--ws` flag is also now parsed into `${GSD_WS}`, which previously expanded to empty and silently dropped workstream scope from the suggested next-step routing hints. (#2338) +- **The context-monitor hook no longer fails Codex's Stop hook** — GSD wires `gsd-context-monitor` to Codex lifecycle events including `Stop`, but the hook emitted a `hookSpecificOutput.additionalContext` envelope that Codex's Stop schema rejects ("hook returned invalid stop hook JSON output") exactly when context was low. The hook now emits that envelope only for context-injection events (PostToolUse / AfterTool) and exits silently for Stop and every other lifecycle event, while its debounce and critical-session bookkeeping still run. (#2289) (#2324) +- **`phase complete` now reads milestone-grouped ROADMAP progress tables** — progress reported 0% on projects whose Progress table carries a Milestone column, because the reader assumed a fixed column position; it now resolves progress columns by name so both flat and milestone-grouped tables work (#2137). Quick Tasks logging via `/gsd:fast` also appends schema-correct, lock-safe rows instead of guessing the column count in shell (#2133). (#2248) (#2248) +- **Managed hooks no longer break after a volta node upgrade or prune** — on machines using volta to manage Node, the installer baked a version-pinned node path into every managed hook command. Once volta pruned that node version, every hook failed to spawn with `No such file or directory` at the start of each session, until the installer was re-run. Hook commands now resolve through volta's stable shim, which survives version changes. (#2335) (#2375) +- **Todo severity is now captured and surfaced end-to-end** — `/gsd-capture` (add-todo) now confirms a severity (blocker/major/minor/cosmetic) before writing a todo instead of silently omitting it, and `gsd-tools list-todos` / `init todos` now include the `severity` field in their JSON output (omitted for older todos that have none), so a backlog can be triaged by severity instead of by re-reading every file. (#2337) (#2381) +- **Skill-bearing capabilities now surface correctly on flat command-layout installs** — on an install using the flat `commands/gsd-.md` source layout (e.g. a Claude Code local project install with no `commands/gsd/` subdir), every skill-bearing capability (`nyquist`, `code-review`, `security`, `ui`, `mempalace`, `ai-integration`, `profile-pipeline`) was silently reported `surfaced:false`/`enabled:false`/`active:false`, so their loop hooks (`verify:post`, `execute:post`, etc.) never fired even with the corresponding `workflow.*` toggle on. The skill-manifest resolver now detects the flat layout and produces the same stems the nested `commands/gsd/*.md` loader does. (#1858) (#2049) +- **Claude Code installs now pre-approve `.planning/` and `STATE.md` writes** — the installer wrote `Write(.planning/*)`/`Write(STATE.md)` permission rules, but Claude Code has no standalone `Write` gate (file edits are gated via `Edit(pattern)`), so those rules never matched and every fresh install still hit first-run approval prompts (and a session-start warning). The installer now writes `Edit(...)` rules and migrates the stale `Write(...)` entries away on the next run. (#2278) (#2302) +- **Roadmap, requirements, and state table edits are confined to the right table** — the last ad-hoc table writers (phase completion updating roadmap progress, `requirements mark-complete`, and `state record-metric`/velocity) now route through the shared markdown-table seam, so a stray decoy table elsewhere in a document can no longer swallow a phase-progress update, a single ragged neighbouring row no longer silently aborts the whole edit, and per-plan metric recording no longer drops trailing section content or duplicates the section. (#2253) (#2253) +- **Installed third-party capability skills now materialize as real slash commands** — a capability could pass every check (`installed: true, surfaced: true, active: true`) and still never exist on disk: the registry layer counted the capability's skill as surfaced, but the file-copy step only ever scanned gsd-core's own bundled commands, so nothing was ever written to the runtime's `skills/` directory and the command was never invocable. Installed capability skills are now staged from where they live, bound to the capability that actually declared and registered them (never inferred from directory listing order), and are subject to the same runtime-targeted body rewrites as first-party skills — first-party skills still win any name collision. (#2340) +- **`/gsd:plan-review-convergence` can now use the Antigravity CLI reviewer** — its reviewer-flag whitelist predated the 1.7.0 Antigravity adapter and silently dropped `--agy`/`--antigravity`, so convergence fell back to `--codex` only and the working adapter was unreachable (especially after Gemini CLI's upstream shutdown). Both flags are now recognized and passed through to `/gsd-review` unchanged. (#2293) (#2325) +- **`npm run lint:ci` (and every npm script banner) on `next` and feature branches cut from `next` no longer reports a stale pre-release version after a final release** — the release pipeline's `finalize` job shipped `X.Y.0` to npm `latest` but never bumped `next` to match, so `next` carried the last `rc.N` placeholder indefinitely (observed: `1.7.0-rc.6` lingering after `1.7.0` shipped). The `finalize` job now runs `scripts/sync-next-version.cjs` — the same step the `rc` job already ran — keeping `next` at the last published release for every release type as `scripts/sync-next-version.cjs:6-9` always promised. (#2423) (#2437) +- **`verify plan-structure` no longer false-flags checkpoint tasks for missing ``/``/``** — every `` was reported as a structural error because the verifier unconditionally required the auto-task fields. It now branches on the task's `type` attribute: `checkpoint:human-verify` requires its canonical triple (``/``/``), `checkpoint:decision` requires ``/``/``, `checkpoint:human-action` requires ``/``/``/`` (per `gsd-core/references/checkpoints.md`), and unknown `checkpoint:*` subtypes require only the universal ``. Non-checkpoint tasks keep the historical ``/``/``/`` requirements unchanged. (#2473) +- **Hermes installs now project named-agent dispatch onto `delegate_task` instead of asserting a nonexistent `Agent` tool** — installed Hermes workflows brand-swapped "Claude Code"→"Hermes Agent" but kept literal `Agent(...)` calls and falsely claimed "The Agent tool IS available", which Hermes doesn't expose. A Hermes `.md` converter now rewrites named dispatch onto Hermes's `delegate_task` contract (embedding the resolved role prompt since Hermes has no named-agent lookup, mapping background dispatch, dropping unsupported per-call model), driven by the runtime's documented dispatch facts, and fails closed if a referenced role prompt is missing. (#2284) (#2309) +- **`phase complete` no longer silently drops requirement IDs the roadmap cites but REQUIREMENTS.md never defined** — completing a phase whose `**Requirements**:` line named an unregistered REQ-ID reported `requirements_updated: true` with zero warnings while the file was left byte-for-byte unchanged, indistinguishable from a run that wrote everything. Ghost IDs now raise a warning, `requirements_updated` reflects whether a write actually landed, an active heading like `## v1 Requirements` is no longer mistaken for a deferred section, and a phase whose every cited ID is unregistered still reports its missing-requirement rows instead of "No requirements or decisions to check." (#2339) +- **`~/.gsd/defaults.json` no longer silently drops `model_policy`, `model_profile_overrides`, and `runtime`** — the global-defaults path of config load now forwards these three keys identically to a project's `.planning/config.json`, so a machine-wide model policy / runtime / overrides specified globally is honored even outside a project. (#2069) (#2442) +- **ROADMAP phase edits can no longer escape their section** — completing a phase updated its plan count and per-plan checkboxes with whole-document regexes that could bleed into a neighbouring phase; those per-phase writes are now structurally bounded to the phase own section via a new `withSection` / `withPhaseSection` seam (#2130, #2067, #2080). (#2250) (#2250) +- **`close_phase_todos` no longer leaves moved todos as phantom unstaged deletions in `git status`** — the workflow step moved resolved todos from `.planning/todos/pending/` to `.planning/todos/completed/` with a plain `mv`, then committed by listing only the destination directory in `--files`. Git's index still tracked the moved file at its old `pending/` path, so the deletion was never staged and the moved-away file lingered as an unstaged deletion in `git status` until some later broad `git add -A` happened to catch it. The step's commit `--files` list now includes BOTH directories so `git add .planning/todos/pending/` stages the deletion atomically with the new `completed/` copy in the same commit. (#2415) (#2447) +- **STATE.md `## Session` fields now resolve on Windows** — the session-section reader used a `\n`-only heading regex that silently failed on a CRLF `## Session` heading, nulling all session state on Windows checkouts; it now reads through the CRLF-safe section seam. (#2253) (#2253) +- **Bullet/em-dash ROADMAP phases no longer resolve to `Phase null`** — the roadmap phase lookup matched only ATX headings with a colon, so a bullet entry like `- [ ] **Phase N — Name**` (which the roadmapper emits) failed to resolve and `Phase null` landed in STATE.md; a bullet-only ROADMAP also broke the milestone phase count. Phase lookup and the milestone filter now accept bullet/checkbox entries with an em-dash/en-dash/hyphen/colon separator. (#2199) (#2228) +- **Linuxbrew users no longer lose all GSD-managed hooks after `brew upgrade node`** — normalizeNodePath only recognized macOS Homebrew Cellar paths, so on Linux the version-pinned node path stayed baked into hook commands and 404'd after a node bump (and reinstall couldn't repair it). It now rewrites any Homebrew Cellar path — Intel, Apple Silicon, Linuxbrew, custom HOMEBREW_PREFIX — to the stable `/bin/node` symlink. (#2185) (#2225) +- **`milestone complete` no longer corrupts the recorded phase** — closing a milestone (e.g. `v0.5`) previously overwrote `current_phase` in STATE.md with the version's minor digit, and a follow-up `state complete-phase` mined a bogus `0.5` token and rewrote the file; phase resolution is now anchored so the real phase is preserved and a milestone-closure line is rejected. (#2111) (#2131) +- **Headless MemPalace capture no longer fails silently** — the headless invocation `mempalace mine --wing --room ` used a `--room` flag that does not exist on the `mine` subcommand (only `search` accepts `--room`), causing every headless/no-MCP capture run to fail with `unrecognized arguments: --room` and silently skip (onError: skip). The fix replaces the flag with MemPalace's documented room-assignment mechanism: stage the artifact under a room-named subfolder with a `mempalace.yaml` taxonomy so `detect_room()` assigns it via folder-path match. (#2220) (#2260) +- **Codex agents no longer fail to launch with an unsupported-model error** — GSD was writing an Anthropic tier name (`opus`/`sonnet`/`haiku`/`fable`) or a `claude-*` id into each Codex agent's `.toml` `model` field, which Codex rejects — fatally on a ChatGPT account (`The 'sonnet' model is not supported when using Codex with a ChatGPT account`). GSD now never writes an Anthropic-flavored model to a Codex agent: an explicit real-Codex model pin is kept, anything else is omitted so the agent inherits the working session model. (#2310) (#2312) +- Fixed: a hand-authored non-inferable backstop truth with a stray trailing space or surrounding quotes no longer silently grades green — it correctly abstains (insufficient_spec), restoring the #1154 honest-verifier guarantee. (#1909) +- **`commit_docs` no longer silently disables on CRLF `.gitignore` repos** — git check-ignore falsely reports a trailing-slash path (e.g. `.planning/`) as ignored when the .gitignore has CRLF line endings with blank lines. isGitIgnored now strips trailing slashes before querying, so the false positive cannot occur. (#2206) (#2235) +- **Phase-directory resolution fails loud on cross-project collisions** — when two unrelated GSD projects share a `.planning/phases/` tree, a bare phase number silently resolved to the first `0N-*` directory found. The fix detects multiple matches and surfaces an `ambiguous_matches` result. (#2237) (#2262) +- **Build/test gates no longer report a false failure on repos with no detectable build/test tooling** — the post-merge, regression, verify-phase, and audit-fix gates read `config-get workflow.build_command`/`workflow.test_command` without `--raw`, so an unset key returned the literal 2-byte string `""` rather than empty output. The `[ -z "$CMD" ]` guard then saw a non-empty value, skipped the Makefile/Cargo/go.mod/package.json auto-detection cascade, and executed the literal `""` as a command → exit 127, misread as a build/test failure (docs-only or planning-only repos, or any repo before its first build file). All of these reads now pass `--raw`, restoring the intended "no command detected — skip" no-op. (#2350) (#2399) +- **`scanPhasePlans` no longer counts PLAN-REVIEW artifacts as executable plans** — `*-PLAN-REVIEW.md` files were counted by the loose `/PLAN/i` fallback. The fix adds a `PLAN_REVIEW_RE` exclusion before the fallback. (#2252) (#2263) +- **Dependency tree no longer carries a known body-parser advisory** — GHSA-v422-hmwv-36x6 (low-severity DoS via invalid `limit` value, published 2026-07-20) in `body-parser@2.2.2` was pulled transitively via `@anthropic-ai/claude-agent-sdk` → `@modelcontextprotocol/sdk` → `express` and surfaced by `npm audit --omit=dev`. Re-resolved `body-parser` to 2.3.0 in `package-lock.json` within `express`'s already-declared `^2.2.1` range; no `overrides` block needed, `package.json` is unchanged. (#2473) +- **Milestone audit no longer flags a not-yet-validated phase as a Nyquist failure** — a phase that was planned but never run through `validate-phase` now reports as NOT-VALIDATED (a "run validate-phase" TODO) instead of collapsing into PARTIAL alongside phases whose validation genuinely failed. (#2117) (#2209) +- **CI gates no longer fail with `no merge base` on branches behind the base.** The mutation, changeset-required, and docs-required workflows shallow-fetched the base *ref*, truncating the ancestry their three-dot `origin/...HEAD` diffs depend on — so the mutation gate reported failure and silently skipped its Stryker shards, leaving the 80% threshold unverified on any PR not already level with `next`. (#2452) (#2485) +- **OpenCode slash commands now install to the supported `commands/` directory instead of OpenCode's legacy `command/` alias** — GSD wrote all ~71 `/gsd-*` commands to `command/` (singular), which OpenCode's docs list only as a backwards-compatibility alias for the documented `commands/` (plural) convention. Commands now land in `~/.config/opencode/commands/` (global) and `.opencode/commands/` (local), and upgrading migrates the legacy directory, preserving any files you put there yourself. OpenCode currently resolves both names, so this is an alignment rather than a rescue — it takes GSD off a path the vendor may withdraw. Kilo is unaffected. (#2354) + +### Security + +- **`gate="blocking-human"` checkpoints are no longer auto-approved by the execute-phase orchestrator** — the package-legitimacy gate (#2827) spans two layers: `gsd-executor` refuses to auto-approve a `gate="blocking-human"` checkpoint and escalates it via `checkpoint_return_format` so a human can vet the package, and `execute-phase`'s `checkpoint_handling` step decides what happens next. That step dispatched purely on checkpoint *type* and never read `gate`, so under `--auto` / `--chain` it immediately auto-approved the very checkpoint the executor had just refused to auto-approve (`human-verify → {user_response} = "approved"`). The slopsquatting defence was therefore inert in exactly the unattended mode where nobody is watching: an `[ASSUMED]`/`[SUS]` package reached install with no human ever seeing the verification prompt. `checkpoint_handling` now carves out `gate="blocking-human"` (and the package-legitimacy `what-built` markers) ahead of every auto-mode branch, routing those checkpoints to the standard present-to-user flow regardless of type. `references/checkpoints.md` documents the `gate` attribute and its two values for the first time — previously `blocking-human` appeared nowhere outside `agents/gsd-executor.md`, so no planner had a documented way to author a checkpoint that auto-mode could not bypass. The existing regression test asserted the executor half only; it now asserts the orchestrator half too, which is why it stayed green while the gate was open. (#2107) (#2113) +- **Patched a transitive denial-of-service advisory in the production dependency tree** — `body-parser` reached GSD via the Claude Agent SDK's MCP dependency and, on versions through 2.2.2, silently stopped enforcing request size limits when given an invalid limit value (GHSA-v422-hmwv-36x6). Pinned to >=2.3.0. (#2470) (#2478) +- **`phases.clear --archive-version` and `milestone complete ` now reject version labels containing path separators or `..`** — the milestone version becomes a filesystem directory name that phase directories are moved into, so an unvalidated value could relocate phase history outside `.planning/milestones/`. Both now validate against a strict version-token pattern and fail loudly. (#2288) (#2323) +- **`query config-get` no longer leaks secret values or walks the prototype chain** — the `--default` fallback path printed secret-named keys (e.g. `brave_search`) in plaintext instead of masking them, and dotted-key traversal used raw property access so `config-get __proto__`/`constructor` resolved to JavaScript internals at exit 0 instead of erroring. Both absent-key resolution and traversal are now masked and own-property-gated. (#2256) (#2299) +- **Hardened phase/roadmap/plan markdown parsing against quadratic-time (ReDoS) CPU exhaustion** — a crafted `ROADMAP.md`, `STATE.md`, or `PLAN.md` with large runs of unclosed `(`, `[`, ``, `