From 9d15ccbb026d72109857c324a58120cf8d3c20f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 00:47:00 +0000 Subject: [PATCH 01/14] chore: bump version to 1.6.1 for hotfix --- .claude-plugin/plugin.json | 2 +- capabilities/ai-integration/capability.json | 2 +- capabilities/antigravity/capability.json | 2 +- capabilities/audit/capability.json | 2 +- capabilities/augment/capability.json | 2 +- capabilities/claude/capability.json | 2 +- capabilities/cline/capability.json | 2 +- capabilities/code-review/capability.json | 2 +- capabilities/codebuddy/capability.json | 2 +- capabilities/codex/capability.json | 2 +- capabilities/copilot/capability.json | 2 +- capabilities/cursor/capability.json | 2 +- capabilities/drift/capability.json | 2 +- capabilities/gap-analysis/capability.json | 2 +- capabilities/gemini/capability.json | 2 +- capabilities/graphify/capability.json | 2 +- capabilities/hermes/capability.json | 2 +- capabilities/intel/capability.json | 2 +- capabilities/kilo/capability.json | 2 +- capabilities/kimi/capability.json | 2 +- capabilities/mempalace/capability.json | 2 +- capabilities/nyquist/capability.json | 2 +- capabilities/opencode/capability.json | 2 +- capabilities/pattern-mapper/capability.json | 2 +- capabilities/profile-pipeline/capability.json | 2 +- capabilities/qwen/capability.json | 2 +- capabilities/research/capability.json | 2 +- capabilities/schema-gate/capability.json | 2 +- capabilities/security/capability.json | 2 +- capabilities/tdd/capability.json | 2 +- capabilities/trae/capability.json | 2 +- capabilities/ui/capability.json | 2 +- capabilities/windsurf/capability.json | 2 +- gemini-extension.json | 2 +- gsd-core/bin/lib/capability-registry.cjs | 96 +++++++++---------- package-lock.json | 4 +- package.json | 2 +- 37 files changed, 85 insertions(+), 85 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 26dad411a..a2f8ce964 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "gsd-core", "displayName": "GSD Core", - "version": "1.6.0", + "version": "1.6.1", "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.", "author": { "name": "open-gsd", diff --git a/capabilities/ai-integration/capability.json b/capabilities/ai-integration/capability.json index 4e7405ba3..4a46bd661 100644 --- a/capabilities/ai-integration/capability.json +++ b/capabilities/ai-integration/capability.json @@ -1,7 +1,7 @@ { "id": "ai-integration", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "AI design contract", "description": "AI-SPEC design contract workflow for phases that build AI systems; owns the AI integration command, agents, and workflow.ai_integration_phase activation key.", "tier": "full", diff --git a/capabilities/antigravity/capability.json b/capabilities/antigravity/capability.json index 3ad49e14d..4cee91d71 100644 --- a/capabilities/antigravity/capability.json +++ b/capabilities/antigravity/capability.json @@ -1,7 +1,7 @@ { "id": "antigravity", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.", "tier": "core", diff --git a/capabilities/audit/capability.json b/capabilities/audit/capability.json index 293381326..b9b410820 100644 --- a/capabilities/audit/capability.json +++ b/capabilities/audit/capability.json @@ -1,7 +1,7 @@ { "id": "audit", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Audit", "description": "Open-artifact audit and UAT-gap audit for milestone close gates; exposes `gsd-tools audit-uat` (cross-phase UAT outstanding items) and `gsd-tools audit-open` (structured open-artifact scan across debug, tasks, threads, todos, seeds, UAT, verification, context-questions).", "tier": "full", diff --git a/capabilities/augment/capability.json b/capabilities/augment/capability.json index 5fa6e875f..379a1ecc7 100644 --- a/capabilities/augment/capability.json +++ b/capabilities/augment/capability.json @@ -1,7 +1,7 @@ { "id": "augment", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Augment Code", "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/claude/capability.json b/capabilities/claude/capability.json index f2f12751c..e0b286220 100644 --- a/capabilities/claude/capability.json +++ b/capabilities/claude/capability.json @@ -1,7 +1,7 @@ { "id": "claude", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Claude Code", "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.", "tier": "core", diff --git a/capabilities/cline/capability.json b/capabilities/cline/capability.json index 1c0d85403..ca1ac84db 100644 --- a/capabilities/cline/capability.json +++ b/capabilities/cline/capability.json @@ -1,7 +1,7 @@ { "id": "cline", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Cline", "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.", "tier": "core", diff --git a/capabilities/code-review/capability.json b/capabilities/code-review/capability.json index 153f433ff..b63792b3f 100644 --- a/capabilities/code-review/capability.json +++ b/capabilities/code-review/capability.json @@ -1,7 +1,7 @@ { "id": "code-review", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Code review", "description": "Source-file code review and review-fix workflow support for completed execution work.", "tier": "full", diff --git a/capabilities/codebuddy/capability.json b/capabilities/codebuddy/capability.json index 76538c71f..f2e398443 100644 --- a/capabilities/codebuddy/capability.json +++ b/capabilities/codebuddy/capability.json @@ -1,7 +1,7 @@ { "id": "codebuddy", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/codex/capability.json b/capabilities/codex/capability.json index 893b9afeb..8116403e7 100644 --- a/capabilities/codex/capability.json +++ b/capabilities/codex/capability.json @@ -1,7 +1,7 @@ { "id": "codex", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "OpenAI Codex CLI", "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.", "tier": "core", diff --git a/capabilities/copilot/capability.json b/capabilities/copilot/capability.json index 73af7b196..9db1ce110 100644 --- a/capabilities/copilot/capability.json +++ b/capabilities/copilot/capability.json @@ -1,7 +1,7 @@ { "id": "copilot", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "GitHub Copilot", "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.", "tier": "core", diff --git a/capabilities/cursor/capability.json b/capabilities/cursor/capability.json index cea99308c..a2b22e1c9 100644 --- a/capabilities/cursor/capability.json +++ b/capabilities/cursor/capability.json @@ -1,7 +1,7 @@ { "id": "cursor", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Cursor", "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.", "tier": "core", diff --git a/capabilities/drift/capability.json b/capabilities/drift/capability.json index c69ad521a..5ad1731f0 100644 --- a/capabilities/drift/capability.json +++ b/capabilities/drift/capability.json @@ -1,7 +1,7 @@ { "id": "drift", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Drift detection gates", "description": "Drift detection gates for the planning loop. At execute:wave:post: a blocking schema drift gate (detects schema files changed without a database push) and a non-blocking codebase drift gate (detects structural additions not reflected in STRUCTURE.md). At plan:pre: a non-blocking, warn-only codebase drift gate (gated on workflow.plan_drift_precheck) that flags a stale codebase map before planning, so plans are authored against a fresh STRUCTURE.md instead of discovering drift mid-execution.", "tier": "full", diff --git a/capabilities/gap-analysis/capability.json b/capabilities/gap-analysis/capability.json index e4926ef85..46fcc01b3 100644 --- a/capabilities/gap-analysis/capability.json +++ b/capabilities/gap-analysis/capability.json @@ -1,7 +1,7 @@ { "id": "gap-analysis", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Post-planning gap analysis", "description": "Proactive, non-blocking post-planning coverage report. After all PLAN.md files are generated, cross-references every REQ-ID and D-ID from REQUIREMENTS.md and CONTEXT.md against plan bodies. Emits a Source | Item | Status table. Does not block phase advancement.", "tier": "standard", diff --git a/capabilities/gemini/capability.json b/capabilities/gemini/capability.json index 65cd8aaff..180917b8b 100644 --- a/capabilities/gemini/capability.json +++ b/capabilities/gemini/capability.json @@ -1,7 +1,7 @@ { "id": "gemini", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Gemini CLI", "description": "Google Gemini CLI — commands-only artifact layout (TOML); Gemini hook event dialect; settings-json hook surface; tier-2 support.", "tier": "core", diff --git a/capabilities/graphify/capability.json b/capabilities/graphify/capability.json index cff231e46..f69c2ef9b 100644 --- a/capabilities/graphify/capability.json +++ b/capabilities/graphify/capability.json @@ -1,7 +1,7 @@ { "id": "graphify", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Knowledge graph", "description": "Build, query, and inspect the project knowledge graph in `.planning/graphs/`; exposes graphify CLI subcommands (build, query, status, diff) and the /gsd-graphify skill.", "tier": "full", diff --git a/capabilities/hermes/capability.json b/capabilities/hermes/capability.json index c2f861741..d66847898 100644 --- a/capabilities/hermes/capability.json +++ b/capabilities/hermes/capability.json @@ -1,7 +1,7 @@ { "id": "hermes", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Hermes Agent", "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/intel/capability.json b/capabilities/intel/capability.json index 69c14bcc7..f12315289 100644 --- a/capabilities/intel/capability.json +++ b/capabilities/intel/capability.json @@ -1,7 +1,7 @@ { "id": "intel", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Codebase intelligence", "description": "Code-intelligence store for codebase querying, diff, snapshot, and API-surface extraction; exposes `gsd-tools intel` subcommands (query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface) and backs `/gsd-map-codebase` and `gsd-intel-updater`.", "tier": "full", diff --git a/capabilities/kilo/capability.json b/capabilities/kilo/capability.json index 59a1d6899..0c6858d14 100644 --- a/capabilities/kilo/capability.json +++ b/capabilities/kilo/capability.json @@ -1,7 +1,7 @@ { "id": "kilo", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Kilo Code", "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.", "tier": "core", diff --git a/capabilities/kimi/capability.json b/capabilities/kimi/capability.json index a4e74e4e3..fa66b7d2c 100644 --- a/capabilities/kimi/capability.json +++ b/capabilities/kimi/capability.json @@ -1,7 +1,7 @@ { "id": "kimi", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Kimi CLI", "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; no hook surface; no hook events; tier-2 support.", "tier": "core", diff --git a/capabilities/mempalace/capability.json b/capabilities/mempalace/capability.json index a2e80c04a..d5ed38d7b 100644 --- a/capabilities/mempalace/capability.json +++ b/capabilities/mempalace/capability.json @@ -1,7 +1,7 @@ { "id": "mempalace", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "MemPalace memory", "description": "Cross-session, cross-project memory: deliberate recall before discuss/plan and verbatim capture + temporal-KG sync at phase boundaries, via the MemPalace MCP server and CLI.", "tier": "full", diff --git a/capabilities/nyquist/capability.json b/capabilities/nyquist/capability.json index 589402fa3..0f517f692 100644 --- a/capabilities/nyquist/capability.json +++ b/capabilities/nyquist/capability.json @@ -1,7 +1,7 @@ { "id": "nyquist", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Nyquist validation", "description": "Validation coverage audit that maps executed work back to tests and manual-only evidence.", "tier": "full", diff --git a/capabilities/opencode/capability.json b/capabilities/opencode/capability.json index 1ad177037..560783f67 100644 --- a/capabilities/opencode/capability.json +++ b/capabilities/opencode/capability.json @@ -1,7 +1,7 @@ { "id": "opencode", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "OpenCode", "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.", "tier": "core", diff --git a/capabilities/pattern-mapper/capability.json b/capabilities/pattern-mapper/capability.json index 259f48d84..740d48c94 100644 --- a/capabilities/pattern-mapper/capability.json +++ b/capabilities/pattern-mapper/capability.json @@ -1,7 +1,7 @@ { "id": "pattern-mapper", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Pattern mapping", "description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.", "tier": "full", diff --git a/capabilities/profile-pipeline/capability.json b/capabilities/profile-pipeline/capability.json index cc0b58c34..88062612e 100644 --- a/capabilities/profile-pipeline/capability.json +++ b/capabilities/profile-pipeline/capability.json @@ -1,7 +1,7 @@ { "id": "profile-pipeline", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Developer profiling pipeline", "description": "Developer behavioral profiling from Claude Code session history; scans session JSONL files, extracts and samples user messages, and generates profile artifacts (USER-PROFILE.md, dev-preferences.md, CLAUDE.md sections). Exposes eight `gsd-tools` commands: scan-sessions, extract-messages, profile-sample (pipeline phase) and write-profile, profile-questionnaire, generate-dev-preferences, generate-claude-profile, generate-claude-md (output phase). Backs the /gsd-profile-user skill and gsd-user-profiler agent.", "tier": "full", diff --git a/capabilities/qwen/capability.json b/capabilities/qwen/capability.json index 9da38ac16..0b17c1041 100644 --- a/capabilities/qwen/capability.json +++ b/capabilities/qwen/capability.json @@ -1,7 +1,7 @@ { "id": "qwen", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Qwen Code", "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/research/capability.json b/capabilities/research/capability.json index 63ecab84d..b6800db9f 100644 --- a/capabilities/research/capability.json +++ b/capabilities/research/capability.json @@ -1,7 +1,7 @@ { "id": "research", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Phase research", "description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.", "tier": "standard", diff --git a/capabilities/schema-gate/capability.json b/capabilities/schema-gate/capability.json index 254a160cf..0d9e88cae 100644 --- a/capabilities/schema-gate/capability.json +++ b/capabilities/schema-gate/capability.json @@ -1,7 +1,7 @@ { "id": "schema-gate", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Schema push detection gate", "description": "Detects ORM schema-relevant files in the phase scope during planning and injects a mandatory [BLOCKING] schema push task into the plan. Prevents false-positive verification where build/types pass because TypeScript types come from config, not the live database.", "tier": "full", diff --git a/capabilities/security/capability.json b/capabilities/security/capability.json index e9599ed0e..1521a7775 100644 --- a/capabilities/security/capability.json +++ b/capabilities/security/capability.json @@ -1,7 +1,7 @@ { "id": "security", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Security enforcement", "description": "Threat mitigation verification and ship-time security blocking for phases with security enforcement enabled.", "tier": "full", diff --git a/capabilities/tdd/capability.json b/capabilities/tdd/capability.json index c2f99c57b..b9e1782b3 100644 --- a/capabilities/tdd/capability.json +++ b/capabilities/tdd/capability.json @@ -1,7 +1,7 @@ { "id": "tdd", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Test-driven development", "description": "Injects TDD heuristics into the planner and enforces RED/GREEN gate compliance on type:tdd plans after execution. Owns workflow.tdd_mode; the --tdd CLI flag is the ephemeral override.", "tier": "full", diff --git a/capabilities/trae/capability.json b/capabilities/trae/capability.json index 3713c8300..dab1a679a 100644 --- a/capabilities/trae/capability.json +++ b/capabilities/trae/capability.json @@ -1,7 +1,7 @@ { "id": "trae", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", diff --git a/capabilities/ui/capability.json b/capabilities/ui/capability.json index 903477c89..899d9ba7b 100644 --- a/capabilities/ui/capability.json +++ b/capabilities/ui/capability.json @@ -1,7 +1,7 @@ { "id": "ui", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "UI design contracts", "description": "UI-SPEC design contract + retrospective UI audit for frontend phases.", "tier": "full", diff --git a/capabilities/windsurf/capability.json b/capabilities/windsurf/capability.json index 293e18b5f..50605bc9d 100644 --- a/capabilities/windsurf/capability.json +++ b/capabilities/windsurf/capability.json @@ -1,7 +1,7 @@ { "id": "windsurf", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Windsurf", "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; no hook surface; no hook events; tier-2 support.", "tier": "core", diff --git a/gemini-extension.json b/gemini-extension.json index a93e82557..d08c5e4a9 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "gsd-core", - "version": "1.6.0", + "version": "1.6.1", "description": "GSD Core — a meta-prompting, context engineering, and spec-driven development system for AI coding agents. Loads gsd's operating context into every Gemini CLI session.", "contextFileName": "GEMINI.md" } diff --git a/gsd-core/bin/lib/capability-registry.cjs b/gsd-core/bin/lib/capability-registry.cjs index 79de051b7..ad28a6c46 100644 --- a/gsd-core/bin/lib/capability-registry.cjs +++ b/gsd-core/bin/lib/capability-registry.cjs @@ -10,7 +10,7 @@ const capabilities = { "ai-integration": { "id": "ai-integration", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "AI design contract", "description": "AI-SPEC design contract workflow for phases that build AI systems; owns the AI integration command, agents, and workflow.ai_integration_phase activation key.", "tier": "full", @@ -63,7 +63,7 @@ const capabilities = { "antigravity": { "id": "antigravity", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.", "tier": "core", @@ -123,7 +123,7 @@ const capabilities = { "audit": { "id": "audit", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Audit", "description": "Open-artifact audit and UAT-gap audit for milestone close gates; exposes `gsd-tools audit-uat` (cross-phase UAT outstanding items) and `gsd-tools audit-open` (structured open-artifact scan across debug, tasks, threads, todos, seeds, UAT, verification, context-questions).", "tier": "full", @@ -160,7 +160,7 @@ const capabilities = { "augment": { "id": "augment", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Augment Code", "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -229,7 +229,7 @@ const capabilities = { "claude": { "id": "claude", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Claude Code", "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.", "tier": "core", @@ -295,7 +295,7 @@ const capabilities = { "cline": { "id": "cline", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Cline", "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.", "tier": "core", @@ -338,7 +338,7 @@ const capabilities = { "code-review": { "id": "code-review", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Code review", "description": "Source-file code review and review-fix workflow support for completed execution work.", "tier": "full", @@ -399,7 +399,7 @@ const capabilities = { "codebuddy": { "id": "codebuddy", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -468,7 +468,7 @@ const capabilities = { "codex": { "id": "codex", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "OpenAI Codex CLI", "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.", "tier": "core", @@ -521,7 +521,7 @@ const capabilities = { "copilot": { "id": "copilot", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "GitHub Copilot", "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.", "tier": "core", @@ -574,7 +574,7 @@ const capabilities = { "cursor": { "id": "cursor", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Cursor", "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.", "tier": "core", @@ -643,7 +643,7 @@ const capabilities = { "drift": { "id": "drift", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Drift detection gates", "description": "Drift detection gates for the planning loop. At execute:wave:post: a blocking schema drift gate (detects schema files changed without a database push) and a non-blocking codebase drift gate (detects structural additions not reflected in STRUCTURE.md). At plan:pre: a non-blocking, warn-only codebase drift gate (gated on workflow.plan_drift_precheck) that flags a stale codebase map before planning, so plans are authored against a fresh STRUCTURE.md instead of discovering drift mid-execution.", "tier": "full", @@ -721,7 +721,7 @@ const capabilities = { "gap-analysis": { "id": "gap-analysis", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Post-planning gap analysis", "description": "Proactive, non-blocking post-planning coverage report. After all PLAN.md files are generated, cross-references every REQ-ID and D-ID from REQUIREMENTS.md and CONTEXT.md against plan bodies. Emits a Source | Item | Status table. Does not block phase advancement.", "tier": "standard", @@ -762,7 +762,7 @@ const capabilities = { "gemini": { "id": "gemini", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Gemini CLI", "description": "Google Gemini CLI — commands-only artifact layout (TOML); Gemini hook event dialect; settings-json hook surface; tier-2 support.", "tier": "core", @@ -819,7 +819,7 @@ const capabilities = { "graphify": { "id": "graphify", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Knowledge graph", "description": "Build, query, and inspect the project knowledge graph in `.planning/graphs/`; exposes graphify CLI subcommands (build, query, status, diff) and the /gsd-graphify skill.", "tier": "full", @@ -860,7 +860,7 @@ const capabilities = { "hermes": { "id": "hermes", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Hermes Agent", "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -913,7 +913,7 @@ const capabilities = { "intel": { "id": "intel", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Codebase intelligence", "description": "Code-intelligence store for codebase querying, diff, snapshot, and API-surface extraction; exposes `gsd-tools intel` subcommands (query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface) and backs `/gsd-map-codebase` and `gsd-intel-updater`.", "tier": "full", @@ -965,7 +965,7 @@ const capabilities = { "kilo": { "id": "kilo", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Kilo Code", "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -1040,7 +1040,7 @@ const capabilities = { "kimi": { "id": "kimi", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Kimi CLI", "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; no hook surface; no hook events; tier-2 support.", "tier": "core", @@ -1096,7 +1096,7 @@ const capabilities = { "mempalace": { "id": "mempalace", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "MemPalace memory", "description": "Cross-session, cross-project memory: deliberate recall before discuss/plan and verbatim capture + temporal-KG sync at phase boundaries, via the MemPalace MCP server and CLI.", "tier": "full", @@ -1270,7 +1270,7 @@ const capabilities = { "nyquist": { "id": "nyquist", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Nyquist validation", "description": "Validation coverage audit that maps executed work back to tests and manual-only evidence.", "tier": "full", @@ -1320,7 +1320,7 @@ const capabilities = { "opencode": { "id": "opencode", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "OpenCode", "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -1390,7 +1390,7 @@ const capabilities = { "pattern-mapper": { "id": "pattern-mapper", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Pattern mapping", "description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.", "tier": "full", @@ -1444,7 +1444,7 @@ const capabilities = { "profile-pipeline": { "id": "profile-pipeline", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Developer profiling pipeline", "description": "Developer behavioral profiling from Claude Code session history; scans session JSONL files, extracts and samples user messages, and generates profile artifacts (USER-PROFILE.md, dev-preferences.md, CLAUDE.md sections). Exposes eight `gsd-tools` commands: scan-sessions, extract-messages, profile-sample (pipeline phase) and write-profile, profile-questionnaire, generate-dev-preferences, generate-claude-profile, generate-claude-md (output phase). Backs the /gsd-profile-user skill and gsd-user-profiler agent.", "tier": "full", @@ -1521,7 +1521,7 @@ const capabilities = { "qwen": { "id": "qwen", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Qwen Code", "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -1578,7 +1578,7 @@ const capabilities = { "research": { "id": "research", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Phase research", "description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.", "tier": "standard", @@ -1630,7 +1630,7 @@ const capabilities = { "schema-gate": { "id": "schema-gate", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Schema push detection gate", "description": "Detects ORM schema-relevant files in the phase scope during planning and injects a mandatory [BLOCKING] schema push task into the plan. Prevents false-positive verification where build/types pass because TypeScript types come from config, not the live database.", "tier": "full", @@ -1676,7 +1676,7 @@ const capabilities = { "security": { "id": "security", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Security enforcement", "description": "Threat mitigation verification and ship-time security blocking for phases with security enforcement enabled.", "tier": "full", @@ -1775,7 +1775,7 @@ const capabilities = { "tdd": { "id": "tdd", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "Test-driven development", "description": "Injects TDD heuristics into the planner and enforces RED/GREEN gate compliance on type:tdd plans after execution. Owns workflow.tdd_mode; the --tdd CLI flag is the ephemeral override.", "tier": "full", @@ -1828,7 +1828,7 @@ const capabilities = { "trae": { "id": "trae", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", @@ -1880,7 +1880,7 @@ const capabilities = { "ui": { "id": "ui", "role": "feature", - "version": "1.6.0", + "version": "1.6.1", "title": "UI design contracts", "description": "UI-SPEC design contract + retrospective UI audit for frontend phases.", "tier": "full", @@ -1975,7 +1975,7 @@ const capabilities = { "windsurf": { "id": "windsurf", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Windsurf", "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; no hook surface; no hook events; tier-2 support.", "tier": "core", @@ -2743,7 +2743,7 @@ const runtimes = { "antigravity": { "id": "antigravity", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.", "tier": "core", @@ -2803,7 +2803,7 @@ const runtimes = { "augment": { "id": "augment", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Augment Code", "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -2872,7 +2872,7 @@ const runtimes = { "claude": { "id": "claude", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Claude Code", "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.", "tier": "core", @@ -2938,7 +2938,7 @@ const runtimes = { "cline": { "id": "cline", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Cline", "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.", "tier": "core", @@ -2981,7 +2981,7 @@ const runtimes = { "codebuddy": { "id": "codebuddy", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -3050,7 +3050,7 @@ const runtimes = { "codex": { "id": "codex", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "OpenAI Codex CLI", "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.", "tier": "core", @@ -3103,7 +3103,7 @@ const runtimes = { "copilot": { "id": "copilot", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "GitHub Copilot", "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.", "tier": "core", @@ -3156,7 +3156,7 @@ const runtimes = { "cursor": { "id": "cursor", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Cursor", "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.", "tier": "core", @@ -3225,7 +3225,7 @@ const runtimes = { "gemini": { "id": "gemini", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Gemini CLI", "description": "Google Gemini CLI — commands-only artifact layout (TOML); Gemini hook event dialect; settings-json hook surface; tier-2 support.", "tier": "core", @@ -3282,7 +3282,7 @@ const runtimes = { "hermes": { "id": "hermes", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Hermes Agent", "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -3335,7 +3335,7 @@ const runtimes = { "kilo": { "id": "kilo", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Kilo Code", "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -3410,7 +3410,7 @@ const runtimes = { "kimi": { "id": "kimi", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Kimi CLI", "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; no hook surface; no hook events; tier-2 support.", "tier": "core", @@ -3466,7 +3466,7 @@ const runtimes = { "opencode": { "id": "opencode", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "OpenCode", "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -3536,7 +3536,7 @@ const runtimes = { "qwen": { "id": "qwen", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Qwen Code", "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -3593,7 +3593,7 @@ const runtimes = { "trae": { "id": "trae", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", @@ -3645,7 +3645,7 @@ const runtimes = { "windsurf": { "id": "windsurf", "role": "runtime", - "version": "1.6.0", + "version": "1.6.1", "title": "Windsurf", "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; no hook surface; no hook events; tier-2 support.", "tier": "core", diff --git a/package-lock.json b/package-lock.json index 8e8f15205..fe39eb0c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@opengsd/gsd-core", - "version": "1.6.0", + "version": "1.6.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@opengsd/gsd-core", - "version": "1.6.0", + "version": "1.6.1", "license": "MIT", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.84", diff --git a/package.json b/package.json index d99ca54ac..cb0781744 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@opengsd/gsd-core", - "version": "1.6.0", + "version": "1.6.1", "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.", "bin": { "gsd-core": "bin/install.js", From 33260555b4a88a405aaf992c107d6c2fbedfd435 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 30 Jun 2026 20:20:53 -0400 Subject: [PATCH 02/14] fix(#1847): resolve standard tier to claude sonnet 5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Point the sonnet/standard tier at Claude Sonnet 5 (`claude-sonnet-5`, GA 2026-06-30) across the Anthropic-backed runtimes and provider presets, replacing the superseded `claude-sonnet-4-6`. Mirrors the change into the CONFIGURATION.md and settings-advanced.md runtime-defaults tables (the #3229 catalog↔docs parity gate) plus the pt-BR/zh-CN translations, and updates the tests that pin the old ID. Regenerates the workflow size baseline for the (smaller) settings-advanced.md. Scope is Sonnet only — opus/haiku IDs are untouched. Prepared as a 1.6.1 hotfix off the v1.6.0 tag. Co-Authored-By: Claude Opus 4.8 --- docs/CONFIGURATION.md | 8 ++++---- docs/pt-BR/CONFIGURATION.md | 8 ++++---- docs/zh-CN/CONFIGURATION.md | 8 ++++---- gsd-core/bin/shared/model-catalog.json | 16 +++++++-------- gsd-core/workflows/settings-advanced.md | 20 +++++++++---------- tests/feat-49-model-policy-presets.test.cjs | 4 ++-- ...issue-2517-runtime-aware-profiles.test.cjs | 10 +++++----- tests/model-alias-map.test.cjs | 4 ++-- tests/workflow-size-baseline.json | 2 +- 9 files changed, 40 insertions(+), 40 deletions(-) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 544d3f988..ce4c15fcd 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -1355,13 +1355,13 @@ When `runtime` is set, profile tiers (`opus`/`sonnet`/`haiku`) resolve to runtim | Runtime | `opus` | `sonnet` | `haiku` | reasoning_effort | |---------|--------|----------|---------|------------------| -| `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (not used) | +| `claude` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | (not used) | | `codex` | `gpt-5.5` | `gpt-5.4` | `gpt-5.4-mini` | `xhigh` / `medium` / `medium` | | `gemini` | `gemini-3.1-pro-preview` | `gemini-3-flash` | `gemini-2.5-flash-lite` | (not used) | | `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` | (not used) | -| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (not used) | -| `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (not used) | -| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (not used) | +| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | (not used) | +| `copilot` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | (not used) | +| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | (not used) | | Group B (`kilo`, `cline`, `cursor`, `windsurf` (alias: `devin-desktop`), `augment`, `trae`, `codebuddy`, `antigravity`) | (no built-in default — your runtime handles model selection) | | | | > **How these model IDs are sourced.** The catalog (`bin/shared/model-catalog.json`) pins each runtime's tier defaults to that provider's current frontier IDs, and may intentionally carry forward-dated IDs ahead of a provider's public docs. To verify an ID is live before changing it, check the provider's own source/API — e.g. Gemini: gemini-cli `packages/core/src/config/models.ts` or `gemini --model --prompt ping`; Codex: `codex debug models` or the OpenAI Codex models page; Qwen: Alibaba Model Studio model list. Only change an ID that the provider actually rejects — absence from documentation alone is not proof of invalidity. diff --git a/docs/pt-BR/CONFIGURATION.md b/docs/pt-BR/CONFIGURATION.md index c64c815e2..9510927f6 100644 --- a/docs/pt-BR/CONFIGURATION.md +++ b/docs/pt-BR/CONFIGURATION.md @@ -1139,13 +1139,13 @@ A saída JSON de `resolve-model` inclui `reasoning_effort` quando o nível de ru | Runtime | `opus` | `sonnet` | `haiku` | reasoning_effort | |---------|--------|----------|---------|------------------| -| `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (não usado) | +| `claude` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | (não usado) | | `codex` | `gpt-5.5` | `gpt-5.3-codex` | `gpt-5.4-mini` | `xhigh` / `medium` / `medium` | | `gemini` | `gemini-3-pro` | `gemini-3-flash` | `gemini-2.5-flash-lite` | (não usado) | | `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` | (não usado) | -| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (não usado) | -| `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (não usado) | -| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (não usado) | +| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | (não usado) | +| `copilot` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | (não usado) | +| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | (não usado) | | Grupo B (`kilo`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`, `antigravity`) | (sem padrão integrado — seu runtime trata da seleção de modelo) | | | | **Exemplo Codex** — uma configuração, modelos em nível, sem bloco grande de `model_overrides`: diff --git a/docs/zh-CN/CONFIGURATION.md b/docs/zh-CN/CONFIGURATION.md index 07aff134a..2b49cf333 100644 --- a/docs/zh-CN/CONFIGURATION.md +++ b/docs/zh-CN/CONFIGURATION.md @@ -1108,13 +1108,13 @@ minimal < low < medium < high < xhigh < max | 运行时 | `opus` | `sonnet` | `haiku` | reasoning_effort | |---------|--------|----------|---------|------------------| -| `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (不使用) | +| `claude` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | (不使用) | | `codex` | `gpt-5.5` | `gpt-5.3-codex` | `gpt-5.4-mini` | `xhigh` / `medium` / `medium` | | `gemini` | `gemini-3-pro` | `gemini-3-flash` | `gemini-2.5-flash-lite` | (不使用) | | `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` | (不使用) | -| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (不使用) | -| `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | (不使用) | -| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | (不使用) | +| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | (不使用) | +| `copilot` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | (不使用) | +| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | (不使用) | | B 组(`kilo`、`cline`、`cursor`、`windsurf`、`augment`、`trae`、`codebuddy`、`antigravity`) | (无内置默认——您的运行时处理模型选择) | | | | **Codex 示例** — 单个配置,分层模型,无大型 `model_overrides` 块: diff --git a/gsd-core/bin/shared/model-catalog.json b/gsd-core/bin/shared/model-catalog.json index 308f1bcc8..6f2a28011 100644 --- a/gsd-core/bin/shared/model-catalog.json +++ b/gsd-core/bin/shared/model-catalog.json @@ -9,7 +9,7 @@ "runtimeTierDefaults": { "claude": { "opus": { "model": "claude-opus-4-8" }, - "sonnet": { "model": "claude-sonnet-4-6" }, + "sonnet": { "model": "claude-sonnet-5" }, "haiku": { "model": "claude-haiku-4-5" } }, "codex": { @@ -29,17 +29,17 @@ }, "opencode": { "opus": { "model": "anthropic/claude-opus-4-8" }, - "sonnet": { "model": "anthropic/claude-sonnet-4-6" }, + "sonnet": { "model": "anthropic/claude-sonnet-5" }, "haiku": { "model": "anthropic/claude-haiku-4-5" } }, "copilot": { "opus": { "model": "claude-opus-4-8" }, - "sonnet": { "model": "claude-sonnet-4-6" }, + "sonnet": { "model": "claude-sonnet-5" }, "haiku": { "model": "claude-haiku-4-5" } }, "hermes": { "opus": { "model": "anthropic/claude-opus-4-8" }, - "sonnet": { "model": "anthropic/claude-sonnet-4-6" }, + "sonnet": { "model": "anthropic/claude-sonnet-5" }, "haiku": { "model": "anthropic/claude-haiku-4-5" } }, "kilo": { @@ -91,13 +91,13 @@ "providerPresets": { "anthropic": { "opus": { "low": { "model": "claude-opus-4-5" }, "medium": { "model": "claude-opus-4-8" }, "high": { "model": "claude-opus-4-8" } }, - "sonnet": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-sonnet-4-6" }, "high": { "model": "claude-opus-4-8" } }, - "haiku": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-haiku-4-5" }, "high": { "model": "claude-sonnet-4-6" } } + "sonnet": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-sonnet-5" }, "high": { "model": "claude-opus-4-8" } }, + "haiku": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-haiku-4-5" }, "high": { "model": "claude-sonnet-5" } } }, "anthropic-fable": { "opus": { "low": { "model": "claude-opus-4-5" }, "medium": { "model": "claude-opus-4-8" }, "high": { "model": "claude-fable-5" } }, - "sonnet": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-sonnet-4-6" }, "high": { "model": "claude-fable-5" } }, - "haiku": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-haiku-4-5" }, "high": { "model": "claude-sonnet-4-6" } } + "sonnet": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-sonnet-5" }, "high": { "model": "claude-fable-5" } }, + "haiku": { "low": { "model": "claude-haiku-4-5" }, "medium": { "model": "claude-haiku-4-5" }, "high": { "model": "claude-sonnet-5" } } }, "openai": { "opus": { "low": { "model": "gpt-5.4", "reasoning_effort": "medium" }, "medium": { "model": "gpt-5.5", "reasoning_effort": "high" }, "high": { "model": "gpt-5.5", "reasoning_effort": "xhigh" } }, diff --git a/gsd-core/workflows/settings-advanced.md b/gsd-core/workflows/settings-advanced.md index 76f452a7b..3aad8c1d5 100644 --- a/gsd-core/workflows/settings-advanced.md +++ b/gsd-core/workflows/settings-advanced.md @@ -353,13 +353,13 @@ Built-in tier defaults by runtime: | Runtime | `opus` | `sonnet` | `haiku` | |------------|-------------------------------|---------------------------------|-------------------------------| -| `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | +| `claude` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | | `codex` | `gpt-5.5` | `gpt-5.4` | `gpt-5.4-mini` | | `gemini` | `gemini-3.1-pro-preview` | `gemini-3-flash` | `gemini-2.5-flash-lite` | | `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` | -| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | -| `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` | -| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` | +| `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | +| `copilot` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` | +| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` | | Group B (`kilo`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`, `antigravity`) | (no built-in default — your runtime handles model selection) | | | Display a table to the user showing the effective configuration: @@ -623,8 +623,8 @@ AskUserQuestion([ header: "Provider", multiSelect: false, options: [ - { label: "anthropic", description: "claude-opus-4-8 / claude-sonnet-4-6 / claude-haiku-4-5 (Anthropic / Claude)" }, - { label: "anthropic-fable", description: "claude-fable-5 / claude-sonnet-4-6 / claude-haiku-4-5 (Anthropic / Claude Fable opt-in)" }, + { label: "anthropic", description: "claude-opus-4-8 / claude-sonnet-5 / claude-haiku-4-5 (Anthropic / Claude)" }, + { label: "anthropic-fable", description: "claude-fable-5 / claude-sonnet-5 / claude-haiku-4-5 (Anthropic / Claude Fable opt-in)" }, { label: "openai", description: "gpt-5.5 / gpt-5.4 / gpt-5.4-mini (OpenAI / Codex)" }, { label: "Other known provider", description: "Type google or qwen; both still use the canonical tier mapping." } ] @@ -654,11 +654,11 @@ Canonical tier mappings by provider and budget: | Provider | Budget | high | medium | low | |-----------|--------|----------------------------|----------------------------|----------------------------| -| anthropic | high | claude-opus-4-8 | claude-opus-4-8 | claude-sonnet-4-6 | -| anthropic | medium | claude-opus-4-8 | claude-sonnet-4-6 | claude-haiku-4-5 | +| anthropic | high | claude-opus-4-8 | claude-opus-4-8 | claude-sonnet-5 | +| anthropic | medium | claude-opus-4-8 | claude-sonnet-5 | claude-haiku-4-5 | | anthropic | low | claude-haiku-4-5 | claude-haiku-4-5 | claude-haiku-4-5 | -| anthropic-fable | high | claude-fable-5 | claude-fable-5 | claude-sonnet-4-6 | -| anthropic-fable | medium | claude-opus-4-8 | claude-sonnet-4-6 | claude-haiku-4-5 | +| anthropic-fable | high | claude-fable-5 | claude-fable-5 | claude-sonnet-5 | +| anthropic-fable | medium | claude-opus-4-8 | claude-sonnet-5 | claude-haiku-4-5 | | anthropic-fable | low | claude-haiku-4-5 | claude-haiku-4-5 | claude-haiku-4-5 | | openai | high | gpt-5.5 | gpt-5.5 | gpt-5.5 | | openai | medium | gpt-5.5 | gpt-5.4 | gpt-5.4-mini | diff --git a/tests/feat-49-model-policy-presets.test.cjs b/tests/feat-49-model-policy-presets.test.cjs index d660a61ab..b7e3920ac 100644 --- a/tests/feat-49-model-policy-presets.test.cjs +++ b/tests/feat-49-model-policy-presets.test.cjs @@ -142,8 +142,8 @@ describe('#49 resolveModelPolicy Sub-path B: provider presets', () => { test('known provider "anthropic-fable" + tier "haiku" + budget "high" keeps low tier on Sonnet', () => { const policy = { provider: 'anthropic-fable', budget: 'high' }; const result = resolveModelPolicy(policy, 'haiku'); - assert.strictEqual(result, 'claude-sonnet-4-6', - `expected anthropic-fable haiku/high to resolve to claude-sonnet-4-6, got: ${result}`); + assert.strictEqual(result, 'claude-sonnet-5', + `expected anthropic-fable haiku/high to resolve to claude-sonnet-5, got: ${result}`); }); test('known provider "openai" + tier "sonnet" + budget "low" returns model with reasoning_effort from preset', () => { diff --git a/tests/issue-2517-runtime-aware-profiles.test.cjs b/tests/issue-2517-runtime-aware-profiles.test.cjs index 84b3d43d4..812c0329e 100644 --- a/tests/issue-2517-runtime-aware-profiles.test.cjs +++ b/tests/issue-2517-runtime-aware-profiles.test.cjs @@ -705,9 +705,9 @@ describe('issue #2612: runtime "opencode" — OpenCode tier resolution', () => { assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'anthropic/claude-opus-4-8'); }); - test('sonnet tier -> anthropic/claude-sonnet-4-6', () => { + test('sonnet tier -> anthropic/claude-sonnet-5', () => { writeConfig(tmpDir, { runtime: 'opencode', model_profile: 'balanced' }); - assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-roadmapper'), 'anthropic/claude-sonnet-4-6'); + assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-roadmapper'), 'anthropic/claude-sonnet-5'); }); test('haiku tier -> anthropic/claude-haiku-4-5', () => { @@ -733,9 +733,9 @@ describe('issue #2612: runtime "copilot" — Copilot tier resolution', () => { assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-opus-4-8'); }); - test('sonnet tier -> claude-sonnet-4-6', () => { + test('sonnet tier -> claude-sonnet-5', () => { writeConfig(tmpDir, { runtime: 'copilot', model_profile: 'balanced' }); - assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-roadmapper'), 'claude-sonnet-4-6'); + assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-roadmapper'), 'claude-sonnet-5'); }); test('haiku tier -> claude-haiku-4-5', () => { @@ -862,6 +862,6 @@ describe('issue #2612: partial override merge for new Group A runtimes', () => { // gsd-codebase-mapper budget -> haiku -> overridden assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-codebase-mapper'), 'claude-haiku-4-6'); // gsd-planner budget -> sonnet -> built-in default - assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-sonnet-4-6'); + assert.strictEqual(resolveModelInternal(tmpDir, 'gsd-planner'), 'claude-sonnet-5'); }); }); diff --git a/tests/model-alias-map.test.cjs b/tests/model-alias-map.test.cjs index d12f07afa..c4ae2f951 100644 --- a/tests/model-alias-map.test.cjs +++ b/tests/model-alias-map.test.cjs @@ -17,8 +17,8 @@ describe('MODEL_ALIAS_MAP (#1690 regression)', () => { assert.equal(MODEL_ALIAS_MAP.opus, 'claude-opus-4-8'); }); - test('sonnet maps to claude-sonnet-4-6', () => { - assert.equal(MODEL_ALIAS_MAP.sonnet, 'claude-sonnet-4-6'); + test('sonnet maps to claude-sonnet-5', () => { + assert.equal(MODEL_ALIAS_MAP.sonnet, 'claude-sonnet-5'); }); test('haiku maps to claude-haiku-4-5', () => { diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index 6e785faa5..d3b24ea65 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -67,7 +67,7 @@ "scan.md": 7688, "secure-phase.md": 13476, "session-report.md": 4044, - "settings-advanced.md": 39666, + "settings-advanced.md": 39646, "settings-integrations.md": 15848, "settings.md": 33413, "ship.md": 24647, From 3593b8b61d9259ba54e25500babdc69296a40826 Mon Sep 17 00:00:00 2001 From: Behruz Nassre Esfahani Date: Thu, 25 Jun 2026 17:13:22 -0700 Subject: [PATCH 03/14] fix(#1580): exclude 0/999 sentinels from milestone-complete guard and roadmap analyze (#1691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(#1580): exclude 0/999 sentinels from milestone-complete guard and roadmap analyze Closed #1445 added the `^999` backlog-sentinel exclusion to the progress denominators but missed two other resolvers, leaving two user-facing failures live on a milestone whose only directory-less ROADMAP heading is a backlog sentinel: (A) `milestone complete` was blocked by the unstarted-phase guard in src/milestone.cts — it flagged `### Phase 999: Backlog` as an unstarted phase and refused to close a fully-shipped milestone without --force. (B) `roadmap analyze` (src/roadmap.cts) counted the sentinel in phase_count and routed `next_phase` straight into Phase 999. Both now skip Phase 0 (pre-milestone) and Phase 999 (backlog) sentinels, mirroring the engine-wide convention (phase-id getMilestoneFromPhaseId, roadmap-command-router SENTINELS, the #1445 progress filters). Symptom (C) (state.cts total_phases) was already fixed inline by #1445/#1514 and is out of scope here. Regression coverage folded into tests/fix-1445-*.test.cjs (scenarios C and D); updated tests/bug-978 fixture to use a real unstarted phase (Phase 2) instead of a 999 sentinel, since the sentinel is now correctly excluded from that guard. Co-Authored-By: Claude Opus 4.8 (1M context) * chore(#1580): add changeset for 0/999 sentinel exclusion fix Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) (cherry picked from commit 6414249d255a2602acaaee6d0b7cecb010c40c42) --- .../1580-999-sentinel-milestone-roadmap.md | 5 + src/milestone.cts | 7 + src/roadmap.cts | 13 +- .../bug-978-milestone-complete-force.test.cjs | 13 +- ...acklog-excluded-from-total-phases.test.cjs | 121 ++++++++++++++++++ 5 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 .changeset/1580-999-sentinel-milestone-roadmap.md diff --git a/.changeset/1580-999-sentinel-milestone-roadmap.md b/.changeset/1580-999-sentinel-milestone-roadmap.md new file mode 100644 index 000000000..2ddf49e5f --- /dev/null +++ b/.changeset/1580-999-sentinel-milestone-roadmap.md @@ -0,0 +1,5 @@ +--- +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/src/milestone.cts b/src/milestone.cts index f15c9baad..9bf81cc05 100644 --- a/src/milestone.cts +++ b/src/milestone.cts @@ -184,6 +184,13 @@ function cmdMilestoneComplete(cwd: string, version: string, options: MilestoneCo })(); while ((pm = phasePattern.exec(scopedContent)) !== null) { const phaseNum = pm[1]; + // Phase 0 (pre-milestone) and Phase 999 (backlog) are sentinels, not + // real phases — they legitimately have no directory and must not block + // milestone completion. Mirrors the engine-wide sentinel convention + // (phase-id getMilestoneFromPhaseId, roadmap-command-router SENTINELS, + // the #1445 /^999/ progress filters). (#1580) + const major = parseInt(phaseNum, 10); + if (major === 0 || major === 999) continue; const normalized = normalizePhaseName(phaseNum); // A phase has disk_status: 'no_directory' when no phase directory // with a matching token exists on disk. Use the same phaseTokenMatches diff --git a/src/roadmap.cts b/src/roadmap.cts index 1c442c502..510edf647 100644 --- a/src/roadmap.cts +++ b/src/roadmap.cts @@ -318,6 +318,16 @@ function cmdRoadmapAnalyze(cwd: string, raw: boolean): void { }> = []; let match: RegExpExecArray | null; + // Phase 0 (pre-milestone) and Phase 999 (backlog) are sentinels, not real + // phases. They legitimately have no directory and must never be surfaced as + // current/next phase or counted in phase_count. Mirrors the engine-wide + // sentinel convention (phase-id getMilestoneFromPhaseId, roadmap-command-router + // SENTINELS, the #1445 /^999/ progress filters). (#1580) + const isSentinelPhase = (num: string): boolean => { + const major = parseInt(num, 10); + return major === 0 || major === 999; + }; + // Build phase directory lookup once (O(1) readdir instead of O(N) per phase) const _phaseDirNames = (() => { try { @@ -329,6 +339,7 @@ function cmdRoadmapAnalyze(cwd: string, raw: boolean): void { while ((match = phasePattern.exec(content)) !== null) { const phaseNum = match[1]; + if (isSentinelPhase(phaseNum)) continue; const phaseName = match[2].replace(/\(INSERTED\)/i, '').trim(); // Extract goal from the section @@ -437,7 +448,7 @@ function cmdRoadmapAnalyze(cwd: string, raw: boolean): void { checklistPhases.add(checklistMatch[1]); } const detailPhases = new Set(phases.map(p => p.number)); - const missingDetails = [...checklistPhases].filter(p => !detailPhases.has(p)); + const missingDetails = [...checklistPhases].filter(p => !detailPhases.has(p) && !isSentinelPhase(p)); const result = { milestones, diff --git a/tests/bug-978-milestone-complete-force.test.cjs b/tests/bug-978-milestone-complete-force.test.cjs index 8cd74c883..0ff7d5612 100644 --- a/tests/bug-978-milestone-complete-force.test.cjs +++ b/tests/bug-978-milestone-complete-force.test.cjs @@ -19,10 +19,13 @@ const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs'); * Build a fixture where the guard will fire: * - STATE.md has `milestone: ` so the guard's version-match check is * satisfied. - * - ROADMAP.md lists a `### Phase 999.1: Backlog Work` heading for that - * milestone, but there is NO on-disk phase directory for it. + * - ROADMAP.md lists a `### Phase 2: Real Work` heading for that milestone, but + * there is NO on-disk phase directory for it. * * This guarantees "unstarted phase" detection without touching any real phases. + * NOTE: the unstarted phase must be a REAL phase number — Phase 0 and Phase 999 + * are backlog/pre-milestone sentinels that are intentionally excluded from this + * guard (#1580), so they would not fire it. */ function makeGuardFixture(tmpDir, version) { // STATE.md with frontmatter milestone field matching the version @@ -32,10 +35,10 @@ function makeGuardFixture(tmpDir, version) { ); // ROADMAP.md — the heading must include the version so getMilestonePhaseFilter - // does not return missingExplicitVersion. Phase 999.1 has no on-disk dir. + // does not return missingExplicitVersion. Phase 2 has no on-disk dir. fs.writeFileSync( path.join(tmpDir, '.planning', 'ROADMAP.md'), - `# Roadmap ${version}\n\n### Phase 999.1: Backlog Work\n**Goal:** Not started\n`, + `# Roadmap ${version}\n\n### Phase 2: Real Work\n**Goal:** Not started\n`, ); } @@ -80,7 +83,7 @@ describe('bug-978: milestone complete --force overrides unstarted-phase guard', const output = JSON.parse(result.output); assert.strictEqual(output.version, 'v1.0'); - // Milestone entry should have been created even though phase 999.1 has no dir + // Milestone entry should have been created even though phase 2 has no dir assert.ok( fs.existsSync(path.join(tmpDir, '.planning', 'MILESTONES.md')), 'MILESTONES.md should have been created', diff --git a/tests/fix-1445-999x-backlog-excluded-from-total-phases.test.cjs b/tests/fix-1445-999x-backlog-excluded-from-total-phases.test.cjs index 1490db251..00b4d169a 100644 --- a/tests/fix-1445-999x-backlog-excluded-from-total-phases.test.cjs +++ b/tests/fix-1445-999x-backlog-excluded-from-total-phases.test.cjs @@ -16,6 +16,14 @@ * Scenarios: * A. deriveProgressFromRoadmap with a progress table containing a 999.x row. * B. state json total_phases via extractCurrentMilestone / roadmapPhaseCount. + * + * Follow-up #1580: the same `^999` (and Phase 0) sentinel exclusion was missing + * in two more code paths — `milestone complete`'s unstarted-phase guard + * (src/milestone.cts) and `roadmap analyze`'s next_phase routing + phase_count + * (src/roadmap.cts). Scenarios C and D below cover those. + * + * C. milestone complete is NOT blocked by a Phase 999 backlog heading. + * D. roadmap analyze never routes next_phase to 999 / never counts it. */ const { describe, test, beforeEach, afterEach } = require('node:test'); @@ -172,3 +180,116 @@ describe('bug #1445 — state json excludes 999.x phase headings from total_phas ); }); }); + +// ─── Scenario C: milestone complete not blocked by a 999 backlog heading ───── + +describe('fix #1580 — milestone complete ignores the 999 backlog sentinel', () => { + let tmpDir; + + beforeEach(() => { + tmpDir = createTempProject('fix-1580-mc-'); + const planning = path.join(tmpDir, '.planning'); + // One real, on-disk phase + a directory-less Phase 999 backlog heading. + fs.writeFileSync( + path.join(planning, 'ROADMAP.md'), + [ + '# Roadmap v1.0', + '## v1.0 Milestone', + '## Phases', + '- [x] **Phase 1: Foundation**', + '## Phase Details', + '### Phase 1: Foundation', + '**Goal:** build it', + '### Phase 999: Backlog / Someday', + '**Goal:** deferred, never executed', + ].join('\n'), + 'utf-8', + ); + fs.writeFileSync( + path.join(planning, 'STATE.md'), + `---\nmilestone: v1.0\n---\n# State\n\n**Status:** In progress\n**Last Activity:** 2025-01-01\n**Last Activity Description:** Working\n`, + 'utf-8', + ); + const dir = path.join(planning, 'phases', '01-foundation'); + fs.mkdirSync(dir, { recursive: true }); + fs.writeFileSync(path.join(dir, 'PLAN.md'), '# Plan\n', 'utf-8'); + }); + + afterEach(() => { + cleanup(tmpDir); + }); + + test('completes WITHOUT --force despite a Phase 999 backlog heading', () => { + const result = runGsdTools( + ['milestone', 'complete', 'v1.0', '--name', 'Regression'], + tmpDir, + ); + assert.ok( + result.success, + `milestone complete must not be blocked by the 999 sentinel; got error: ${result.error}`, + ); + assert.ok( + !/Cannot mark milestone complete/.test(result.error || ''), + `the unstarted-phase guard must not fire on Phase 999. Got: ${result.error}`, + ); + }); +}); + +// ─── Scenario D: roadmap analyze never routes/ counts the 999 sentinel ──────── + +describe('fix #1580 — roadmap analyze excludes the 999 backlog sentinel', () => { + let tmpDir; + + beforeEach(() => { + tmpDir = createTempProject('fix-1580-ra-'); + const planning = path.join(tmpDir, '.planning'); + fs.writeFileSync( + path.join(planning, 'ROADMAP.md'), + [ + '# Roadmap v1.0', + '## v1.0 Milestone', + '## Phases', + '- [x] **Phase 1: Foundation**', + '## Phase Details', + '### Phase 1: Foundation', + '**Goal:** build it', + '### Phase 999: Backlog / Someday', + '**Goal:** deferred, never executed', + ].join('\n'), + 'utf-8', + ); + fs.writeFileSync( + path.join(planning, 'STATE.md'), + `---\nmilestone: v1.0\n---\n# State\n`, + 'utf-8', + ); + const dir = path.join(planning, 'phases', '01-foundation'); + fs.mkdirSync(dir, { recursive: true }); + fs.writeFileSync(path.join(dir, 'PLAN.md'), '# Plan\n', 'utf-8'); + fs.writeFileSync(path.join(dir, 'SUMMARY.md'), '# Summary\n', 'utf-8'); + }); + + afterEach(() => { + cleanup(tmpDir); + }); + + test('next_phase is never 999 and phase_count excludes the sentinel', () => { + const result = runGsdTools(['roadmap', 'analyze', '--raw'], tmpDir); + assert.ok(result.success, `roadmap analyze failed: ${result.error}`); + const analysis = JSON.parse(result.output); + assert.notEqual( + String(analysis.next_phase), + '999', + `next_phase must never route to the 999 backlog sentinel. Got ${analysis.next_phase}`, + ); + assert.equal( + analysis.phase_count, + 1, + `phase_count must exclude the 999 sentinel (expected 1). Got ${analysis.phase_count}`, + ); + assert.ok( + !(analysis.phases || []).some(p => String(p.number) === '999'), + 'the phases array must not include the 999 backlog sentinel', + ); + }); +}); From 52ac52aa549209e9f86d644c07ddf200a5a55726 Mon Sep 17 00:00:00 2001 From: Behruz Nassre Esfahani Date: Fri, 26 Jun 2026 12:19:57 -0700 Subject: [PATCH 04/14] fix(#1693): don't double-quote $CLAUDE_PROJECT_DIR-anchored hook paths on Windows (#1746) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(#1693): don't double-quote $CLAUDE_PROJECT_DIR-anchored hook paths on Windows The installer's #2979 legacy-node rewrite ran every managed node hook path through JSON.stringify on Windows. For local installs the path already carries a "$CLAUDE_PROJECT_DIR"-anchored quoted prefix, so stringifying produced "\"$CLAUDE_PROJECT_DIR\"/...". Node then received an argument starting with a literal " , treated it as relative, and failed MODULE_NOT_FOUND — breaking every node managed hook at once (a self-locking PreToolUse-guard deadlock). projectLegacySettingsHookCommand now emits an already-anchored token verbatim and only JSON.stringify-quotes bare absolute paths (which may contain spaces). Scoped to win32 so non-Windows token-shape behavior is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) * chore(#1693): add changeset Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) (cherry picked from commit dcd1d7f973ba21eceddc3ffa49c3303d17c2fc92) --- .changeset/lucky-quails-greet.md | 5 ++ src/shell-command-projection.cts | 23 ++++- ...bug-3413-shell-command-projection.test.cjs | 89 +++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 .changeset/lucky-quails-greet.md diff --git a/.changeset/lucky-quails-greet.md b/.changeset/lucky-quails-greet.md new file mode 100644 index 000000000..5ef8dc1ea --- /dev/null +++ b/.changeset/lucky-quails-greet.md @@ -0,0 +1,5 @@ +--- +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/src/shell-command-projection.cts b/src/shell-command-projection.cts index ca762b3ed..570574e1c 100644 --- a/src/shell-command-projection.cts +++ b/src/shell-command-projection.cts @@ -253,6 +253,15 @@ export function isManagedHookCommand(commandText: unknown, opts: { surface?: str return false; } +/** + * Detect a `"$VAR"/rest` anchored hook-script token — a path whose leading + * shell variable is already double-quoted with the remainder left bare (the + * shape `projectLocalHookPrefix` emits for local installs, e.g. + * `"$CLAUDE_PROJECT_DIR"/.claude/hooks/gsd-x.js`). Such a token is ALREADY a + * valid, correctly-quoted shell argument and must never be re-quoted. + */ +const ANCHORED_HOOK_SCRIPT_TOKEN = /^"\$[A-Za-z_][A-Za-z0-9_]*"\//; + /** * Projection helper for legacy settings.json hook rewrites. * @@ -275,8 +284,20 @@ export function projectLegacySettingsHookCommand({ }): string | null { if (!absoluteRunner || !scriptPath) return null; const normalizedScriptPath = platform === 'win32' ? scriptPath.replace(/\\/g, '/') : scriptPath; + // #1693: a script path already carrying a `"$CLAUDE_PROJECT_DIR"`-anchored + // quoted prefix (local installs) is already a valid shell token — only the + // variable is quoted, the rest is bare. JSON.stringify-ing it on Windows + // yields `"\"$CLAUDE_PROJECT_DIR\"/..."` (escaped quotes inside an outer + // quote); node then receives an argument that *starts* with a `"`, treats it + // as relative, and dies with MODULE_NOT_FOUND. Emit anchored tokens verbatim; + // only bare absolute paths (which may contain spaces, e.g. "Program Files") + // need the JSON.stringify quoting. Scoped to win32: the non-Windows branch + // already preserves the caller's `scriptToken` (which is the bare anchored + // token for these inputs), so it never had the double-quote bug. const commandScriptToken = platform === 'win32' - ? JSON.stringify(normalizedScriptPath) + ? (ANCHORED_HOOK_SCRIPT_TOKEN.test(normalizedScriptPath) + ? normalizedScriptPath + : JSON.stringify(normalizedScriptPath)) : (scriptToken || JSON.stringify(normalizedScriptPath)); return projectShellCommandText({ runnerToken: absoluteRunner, diff --git a/tests/bug-3413-shell-command-projection.test.cjs b/tests/bug-3413-shell-command-projection.test.cjs index bbc6a2541..8a793fb01 100644 --- a/tests/bug-3413-shell-command-projection.test.cjs +++ b/tests/bug-3413-shell-command-projection.test.cjs @@ -187,3 +187,92 @@ describe('bug #3439: shell projection module owns managed-hook policy and legacy ); }); }); + +describe('#1693 regression: Windows legacy-node rewrite must not double-quote a "$CLAUDE_PROJECT_DIR"-anchored local hook path', () => { + const winRunner = '"C:/Program Files/nodejs/node.exe"'; + + // WHY: a local-install hook path already carries a `"$CLAUDE_PROJECT_DIR"` + // anchored prefix (only the variable quoted, rest bare). On Windows the legacy + // rewrite previously JSON.stringify'd the whole token, yielding + // `"\"$CLAUDE_PROJECT_DIR\"/..."`. node then received an argument starting with + // a literal `"`, treated it as relative, and died with MODULE_NOT_FOUND — + // breaking every node managed hook at once (self-locking deadlock). + test('projectLegacySettingsHookCommand emits the anchored path verbatim, not re-quoted', () => { + const anchored = '"$CLAUDE_PROJECT_DIR"/.claude/hooks/gsd-context-monitor.js'; + const command = projectLegacySettingsHookCommand({ + absoluteRunner: winRunner, + scriptPath: anchored, + scriptToken: anchored, + platform: 'win32', + runtime: 'claude', + }); + assert.equal( + command, + '"C:/Program Files/nodejs/node.exe" "$CLAUDE_PROJECT_DIR"/.claude/hooks/gsd-context-monitor.js', + ); + assert.ok(!command.includes('\\"'), 'must not contain escaped double-quotes'); + }); + + // WHY: the fix must be surgical — a BARE absolute Windows path (no anchored + // prefix) can contain spaces ("Program Files") and still REQUIRES quoting. + test('projectLegacySettingsHookCommand still quotes a bare absolute Windows path', () => { + const abs = 'C:/Program Files App/.claude/hooks/gsd-context-monitor.js'; + const command = projectLegacySettingsHookCommand({ + absoluteRunner: winRunner, + scriptPath: abs, + scriptToken: JSON.stringify(abs), + platform: 'win32', + runtime: 'claude', + }); + assert.equal( + command, + '"C:/Program Files/nodejs/node.exe" "C:/Program Files App/.claude/hooks/gsd-context-monitor.js"', + ); + }); + + // WHY: the anchored short-circuit is scoped to win32. On POSIX the rewrite + // already preserved the caller's original `scriptToken` and never had the + // double-quote bug, so that behavior must be left byte-identical. scriptPath + // is anchored but scriptToken is a DISTINCT single-quoted value: if the + // win32 gate were removed, the anchored short-circuit would emit scriptPath + // and this assertion would fail — that is what pins the gate. + test('projectLegacySettingsHookCommand preserves the original scriptToken for anchored paths on POSIX', () => { + const command = projectLegacySettingsHookCommand({ + absoluteRunner: '"/usr/local/bin/node"', + scriptPath: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/gsd-statusline.js', + scriptToken: "'/x/hooks/gsd-statusline.js'", + platform: 'linux', + runtime: 'claude', + }); + assert.equal(command, `"/usr/local/bin/node" '/x/hooks/gsd-statusline.js'`); + }); + + // WHY: end-to-end through the installer rewrite — the actual #2979 path that + // ran during the user's 1.5.0 -> 1.6.0 local update. Managed node hooks get + // the absolute runner + clean anchored path; a non-node-prefixed managed .sh + // hook (already correct) is left untouched. + test('rewriteLegacyManagedNodeHookCommands produces clean anchored node commands on Windows', () => { + const settings = { + hooks: { + PostToolUse: [ + { + hooks: [ + { command: 'node "$CLAUDE_PROJECT_DIR"/.claude/hooks/gsd-context-monitor.js' }, + ], + }, + ], + }, + }; + const changed = rewriteLegacyManagedNodeHookCommands(settings, winRunner, { + platform: 'win32', + runtime: 'claude', + }); + assert.equal(changed, true); + const rewritten = settings.hooks.PostToolUse[0].hooks[0].command; + assert.equal( + rewritten, + '"C:/Program Files/nodejs/node.exe" "$CLAUDE_PROJECT_DIR"/.claude/hooks/gsd-context-monitor.js', + ); + assert.ok(!rewritten.includes('\\"'), 'rewritten command must not contain escaped double-quotes'); + }); +}); From 742264084bddc44c135af70ab2d31fe3c09d5f62 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sun, 28 Jun 2026 22:41:57 -0400 Subject: [PATCH 05/14] fix(#1591): phase.complete recognizes checkbox-list phases in isLastPhase fallback (#1819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(#1591): phase.complete recognizes checkbox-list phases in the isLastPhase fallback When the active milestone's phase checklist is written as `- [ ] Phase N:` checkbox items inside a
block (the @Azd325 structure) and the next phase has no directory yet, the disk-based next-phase resolver finds nothing and phase.complete falls back to the roadmap-enumeration guard at the isLastPhase site. That guard's phasePattern was heading-only (/#{2,4}\s*Phase…/), so it never matched checklist items → is_last_phase=true and next_phase=null on a mid-milestone phase, and STATE.md was wrongly marked 'Milestone complete' with total_phases decremented. Broaden the marker alternation to match BOTH heading-style (### Phase N:) and checkbox-list items (- [ ] Phase N: / - [x] Phase N:); the number/name captures are unchanged. extractCurrentMilestone already surfaces the
-wrapped checklist correctly, so no parser change is needed. The heading-only sibling patterns elsewhere in phase.cts are left untouched (scope discipline — only the reproduced isLastPhase fallback is changed). Regression: a phase complete 36 on a
-wrapped v2.0 checklist (Phases 36-38, only 36 has a dir) returns is_last_phase=false, next_phase=37, and does NOT flip STATE.md to 'Milestone complete'. * docs(#1591): add changeset fragment for phase.complete checkbox-list fix * test(#1752): add total_phases-preservation regression for the #1591 follow-up #1752 is the scoped follow-up to #1591 — same
-wrapped-checkbox defect, with the additional emphasis on the total_phases decrement cascade. The #1591 fix (is_last_phase=false) already resolves it: with all 8 phase dirs on disk, phase.complete 36 on a v2.0
checklist leaves total_phases at 8 (not decremented to 7) and does not flip STATE.md to 'Milestone complete'. Verified manually before adding the test. Add the #1752 regression case (8 phase dirs, curated total_phases: 8) to the phase complete command block in tests/phase.test.cjs, and update the changeset to reference both issues (#1591, #1752) since this is one user-facing change resolving both. (cherry picked from commit 4f6fda852e57913e2f41f92ce9ef6bf6f423bc05) --- ...hase-complete-details-wrapped-checklist.md | 6 + src/phase.cts | 11 +- tests/phase.test.cjs | 181 ++++++++++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 .changeset/1591-phase-complete-details-wrapped-checklist.md diff --git a/.changeset/1591-phase-complete-details-wrapped-checklist.md b/.changeset/1591-phase-complete-details-wrapped-checklist.md new file mode 100644 index 000000000..c6814916b --- /dev/null +++ b/.changeset/1591-phase-complete-details-wrapped-checklist.md @@ -0,0 +1,6 @@ +--- +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 both heading-style (`### Phase N:`) and checkbox-list phases (`- [ ] Phase N:` / `- [x] Phase N:`); `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/src/phase.cts b/src/phase.cts index 4e0a3ae4a..b43c49f46 100644 --- a/src/phase.cts +++ b/src/phase.cts @@ -1649,7 +1649,16 @@ function cmdPhaseComplete(cwd: string, phaseNum: string, raw: boolean): void { if (isLastPhase && roadmapContent !== null) { try { const roadmapForPhases = extractCurrentMilestone(roadmapContent, cwd); - const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi; + // #1591: match BOTH heading-style phases (`### Phase N:`) AND + // checkbox-list items (`- [ ] Phase N:` / `- [x] Phase N:`). When + // the active milestone's checklist is `- [ ]` items inside a + //
block (and the next phase has no directory yet, so the + // disk-based resolver finds nothing), this roadmap-enumeration + // fallback is the only path that can find the next phase. The prior + // heading-only pattern missed checkbox items → is_last_phase=true on + // a mid-milestone phase. The marker alternation is the only change; + // the number/name captures are unchanged. + const phasePattern = /(?:#{2,4}|-\s*\[[ xX]\])\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi; let pm: RegExpExecArray | null; while ((pm = phasePattern.exec(roadmapForPhases)) !== null) { if (comparePhaseNum(pm[1], phaseNum) > 0) { diff --git a/tests/phase.test.cjs b/tests/phase.test.cjs index fc70420fc..a8bbb398b 100644 --- a/tests/phase.test.cjs +++ b/tests/phase.test.cjs @@ -2362,6 +2362,187 @@ describe('phase complete command', () => { assert.ok(state.includes('Milestone complete'), 'status should be milestone complete'); }); + // #1591: when the active milestone's phase checklist is wrapped in a + //
block AND phases are written as `- [ ] Phase N:` checkbox list + // items (not `### Phase N:` headings), phase.complete's next-phase enumerator + // saw no further phases → is_last_phase=true, next_phase=null on a mid- + // milestone phase, and STATE.md was wrongly marked "Milestone complete" with + // total_phases decremented. extractCurrentMilestone correctly surfaces the + //
-wrapped checklist; the defect was the heading-only phasePattern + // at the isLastPhase enumerator not recognizing checkbox-list phase items. + test('#1591:
-wrapped checkbox checklist — mid-milestone phase is NOT last', () => { + fs.writeFileSync( + path.join(tmpDir, '.planning', 'ROADMAP.md'), + [ + '# ROADMAP', + '', + '## Phases', + '', + '
', + '✅ v1.0 First (Phases 1–3) — SHIPPED', + '', + '- [x] Phase 1: a', + '- [x] Phase 2: b', + '- [x] Phase 3: c', + '', + '
', + '', + '
', + '🚀 v2.0 Second (Phases 36–38) — IN PLANNING', + '', + '- [x] Phase 36: first (completed)', + '- [ ] Phase 37: second', + '- [ ] Phase 38: third', + '', + '
', + '', + '## Backlog', + '', + '### Phase 999.1: future (BACKLOG)', + '', + ].join('\n') + ); + fs.writeFileSync( + path.join(tmpDir, '.planning', 'STATE.md'), + [ + '---', + 'gsd_state_version: 1.0', + 'milestone: v2.0', + 'milestone_name: Second', + 'current_phase: "36"', + 'status: executing', + '---', + '', + '# GSD State', + '', + '**Current Phase:** 36', + '**Status:** Executing Phase 36', + '', + ].join('\n') + ); + // Only the COMPLETING phase (36) has a directory. Phases 37/38 exist only + // as `- [ ]` checklist items in the ROADMAP — they are not yet started, so + // they have no phase dirs. This is the @Azd325 scenario: the disk-based + // next-phase resolver finds nothing, and the roadmap-enumeration fallback + // (the heading-only phasePattern) is the only path that can find Phase 37. + const d36 = path.join(tmpDir, '.planning', 'phases', '36-first'); + fs.mkdirSync(d36, { recursive: true }); + fs.writeFileSync(path.join(d36, '36-PLAN.md'), '# Plan\n'); + fs.writeFileSync(path.join(d36, '36-SUMMARY.md'), '# Summary\n'); + + const result = runVerifiedPhaseComplete('phase complete 36', tmpDir); + assert.ok(result.success, `phase complete failed: ${result.error}`); + const output = JSON.parse(result.output); + + assert.strictEqual( + output.is_last_phase, + false, + 'Phase 36 of 36–38 must NOT be last — Phases 37/38 are still open `- [ ]` (#1591)', + ); + assert.strictEqual( + output.next_phase, + '37', + 'next_phase must resolve to 37 from the
-wrapped checkbox checklist (#1591)', + ); + + // Cascade check: a wrong is_last_phase=true previously wrote "Milestone + // complete" + decremented total_phases. With the fix, the milestone is + // still in progress. + const state = fs.readFileSync(path.join(tmpDir, '.planning', 'STATE.md'), 'utf-8'); + assert.ok( + !/Milestone complete/i.test(state), + 'a mid-milestone phase must not flip STATE.md to "Milestone complete" (#1591)', + ); + }); + + // #1752: the #1591 follow-up — when phase.complete wrongly returned + // is_last_phase=true on a
-wrapped mid-milestone checklist, the + // milestone-complete cascade also DECREMENTED progress.total_phases (e.g. + // 8 -> 7) and flipped status. Same root cause, distinct symptom. With the + // #1591 fix (is_last_phase=false), the decrement must not occur: with all 8 + // phase dirs on disk, total_phases stays 8 and status does not flip. + test('#1752:
-wrapped checklist — total_phases is NOT decremented on a mid-milestone phase', () => { + fs.writeFileSync( + path.join(tmpDir, '.planning', 'ROADMAP.md'), + [ + '# ROADMAP', + '', + '## Phases', + '', + '
', + '✅ v1.0 First (Phases 1–3) — SHIPPED', + '', + '- [x] Phase 1: a', + '- [x] Phase 2: b', + '- [x] Phase 3: c', + '', + '
', + '', + '
', + '🚀 v2.0 Second (Phases 36–43) — IN PLANNING', + '', + '- [x] Phase 36: first (completed)', + '- [ ] Phase 37: second', + '- [ ] Phase 38: third', + '- [ ] Phase 39: fourth', + '', + '
', + '', + ].join('\n') + ); + fs.writeFileSync( + path.join(tmpDir, '.planning', 'STATE.md'), + [ + '---', + 'gsd_state_version: 1.0', + 'milestone: v2.0', + 'milestone_name: Second', + 'current_phase: "36"', + 'status: executing', + 'progress:', + ' total_phases: 8', + ' completed_phases: 5', + ' percent: 62', + '---', + '', + '# GSD State', + '', + '**Current Phase:** 36', + '**Status:** Executing Phase 36', + '', + ].join('\n') + ); + // All 8 phase dirs on disk (Phases 36–43) so the disk count is 8 — the + // reporter's real state. Before the #1591 fix, phase.complete 36 returned + // is_last_phase=true (no Phase 37+ heading match) and the milestone-complete + // path DECREMENTED total_phases 8 -> 7. + const names = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth']; + for (let i = 0; i < 8; i++) { + const num = String(36 + i); + const d = path.join(tmpDir, '.planning', 'phases', `${num}-${names[i]}`); + fs.mkdirSync(d, { recursive: true }); + fs.writeFileSync(path.join(d, `${num}-PLAN.md`), '# Plan\n'); + } + + const result = runVerifiedPhaseComplete('phase complete 36', tmpDir); + assert.ok(result.success, `phase complete failed: ${result.error}`); + const output = JSON.parse(result.output); + assert.strictEqual(output.is_last_phase, false, 'is_last_phase must be false (#1752 cascade root)'); + + const state = fs.readFileSync(path.join(tmpDir, '.planning', 'STATE.md'), 'utf-8'); + assert.ok( + !/Milestone complete/i.test(state), + 'a mid-milestone phase must not flip STATE.md to "Milestone complete" (#1752)', + ); + const tpMatch = state.match(/total_phases:\s*(\d+)/); + assert.ok(tpMatch, 'STATE.md must carry a total_phases value after phase.complete'); + assert.notStrictEqual( + parseInt(tpMatch[1], 10), + 7, + 'total_phases must NOT be decremented to 7 — the #1752 cascade of the false is_last_phase', + ); + }); + test('updates REQUIREMENTS.md traceability when phase completes', () => { fs.writeFileSync( path.join(tmpDir, '.planning', 'ROADMAP.md'), From 36bb15ac201d0ec8ba1bb7b44ac27547b8191fc1 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 30 Jun 2026 20:56:20 -0400 Subject: [PATCH 06/14] docs(#1847): add changeset fragment for Claude Sonnet 5 standard tier Co-Authored-By: Claude Opus 4.8 --- .changeset/1847-claude-sonnet-5-standard-tier.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/1847-claude-sonnet-5-standard-tier.md diff --git a/.changeset/1847-claude-sonnet-5-standard-tier.md b/.changeset/1847-claude-sonnet-5-standard-tier.md new file mode 100644 index 000000000..b01b141e6 --- /dev/null +++ b/.changeset/1847-claude-sonnet-5-standard-tier.md @@ -0,0 +1,5 @@ +--- +type: Added +pr: 1847 +--- +**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 tiers are unchanged. (#1847) From ad94b38a69b4d91d2d4f820f288fc8f19d76b5c6 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 30 Jun 2026 21:08:02 -0400 Subject: [PATCH 07/14] fix(#1591): match bold checklist phase markers in isLastPhase fallback The #1591 checkbox broadening matched `- [ ] Phase N:` but not the canonical bold form the roadmap template emits (`- [ ] **Phase N: Name**`), so a
-wrapped bold checklist with no next-phase directory still fell through to is_last_phase=true and a false 'Milestone complete'. Allow optional **/__ emphasis after the marker and stop the name capture at emphasis so bold names slug cleanly. Surfaced by adversarial (codex) review. Co-Authored-By: Claude Opus 4.8 --- src/phase.cts | 21 +++++++------ tests/phase.test.cjs | 70 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/phase.cts b/src/phase.cts index b43c49f46..879719098 100644 --- a/src/phase.cts +++ b/src/phase.cts @@ -1650,15 +1650,18 @@ function cmdPhaseComplete(cwd: string, phaseNum: string, raw: boolean): void { try { const roadmapForPhases = extractCurrentMilestone(roadmapContent, cwd); // #1591: match BOTH heading-style phases (`### Phase N:`) AND - // checkbox-list items (`- [ ] Phase N:` / `- [x] Phase N:`). When - // the active milestone's checklist is `- [ ]` items inside a - //
block (and the next phase has no directory yet, so the - // disk-based resolver finds nothing), this roadmap-enumeration - // fallback is the only path that can find the next phase. The prior - // heading-only pattern missed checkbox items → is_last_phase=true on - // a mid-milestone phase. The marker alternation is the only change; - // the number/name captures are unchanged. - const phasePattern = /(?:#{2,4}|-\s*\[[ xX]\])\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi; + // checkbox-list items, INCLUDING the canonical bold form the roadmap + // template emits (`- [ ] **Phase N: Name**`). When the active + // milestone's checklist is `- [ ]` items inside a
block + // (and the next phase has no directory yet, so the disk-based + // resolver finds nothing), this roadmap-enumeration fallback is the + // only path that can find the next phase. The prior heading-only + // pattern missed checkbox items, and a checkbox-only broadening still + // missed the bold template rows → is_last_phase=true on a mid-milestone + // phase. Allow optional `**`/`__` emphasis after the marker and stop + // the name capture at emphasis so bold names slug cleanly; the number + // capture is unchanged. + const phasePattern = /(?:#{2,4}|-\s*\[[ xX]\])\s*(?:\*\*|__)?\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n*]+)/gi; let pm: RegExpExecArray | null; while ((pm = phasePattern.exec(roadmapForPhases)) !== null) { if (comparePhaseNum(pm[1], phaseNum) > 0) { diff --git a/tests/phase.test.cjs b/tests/phase.test.cjs index a8bbb398b..c40284bcb 100644 --- a/tests/phase.test.cjs +++ b/tests/phase.test.cjs @@ -2455,6 +2455,76 @@ describe('phase complete command', () => { ); }); + // #1591 (bold-checklist follow-up): the roadmap TEMPLATE emits checklist rows + // in the canonical BOLD form `- [ ] **Phase N: Name**`. The initial checkbox + // broadening only matched the un-bolded `- [ ] Phase N:` shape, so the exact + //
-wrapped bold template still fell through to is_last_phase=true. + // Guard the canonical bold form explicitly. + test('#1591:
-wrapped BOLD checkbox checklist — mid-milestone phase is NOT last', () => { + fs.writeFileSync( + path.join(tmpDir, '.planning', 'ROADMAP.md'), + [ + '# ROADMAP', + '', + '## Phases', + '', + '
', + '🚀 v2.0 Second (Phases 36–38) — IN PLANNING', + '', + '- [x] **Phase 36: first (completed)** - done', + '- [ ] **Phase 37: second** - one-line description', + '- [ ] **Phase 38: third** - one-line description', + '', + '
', + '', + ].join('\n') + ); + fs.writeFileSync( + path.join(tmpDir, '.planning', 'STATE.md'), + [ + '---', + 'gsd_state_version: 1.0', + 'milestone: v2.0', + 'milestone_name: Second', + 'current_phase: "36"', + 'status: executing', + '---', + '', + '# GSD State', + '', + '**Current Phase:** 36', + '**Status:** Executing Phase 36', + '', + ].join('\n') + ); + // Only Phase 36 has a directory; 37/38 are bold `- [ ]` checklist rows only. + const d36 = path.join(tmpDir, '.planning', 'phases', '36-first'); + fs.mkdirSync(d36, { recursive: true }); + fs.writeFileSync(path.join(d36, '36-PLAN.md'), '# Plan\n'); + fs.writeFileSync(path.join(d36, '36-SUMMARY.md'), '# Summary\n'); + + const result = runVerifiedPhaseComplete('phase complete 36', tmpDir); + assert.ok(result.success, `phase complete failed: ${result.error}`); + const output = JSON.parse(result.output); + + assert.strictEqual( + output.is_last_phase, + false, + 'Phase 36 of 36–38 must NOT be last with the canonical BOLD checklist (#1591)', + ); + assert.strictEqual( + output.next_phase, + '37', + 'next_phase must resolve to 37 from the BOLD `- [ ] **Phase N: ...**` checklist (#1591)', + ); + + const state = fs.readFileSync(path.join(tmpDir, '.planning', 'STATE.md'), 'utf-8'); + assert.ok( + !/Milestone complete/i.test(state), + 'a mid-milestone phase must not flip STATE.md to "Milestone complete" — bold checklist (#1591)', + ); + }); + // #1752: the #1591 follow-up — when phase.complete wrongly returned // is_last_phase=true on a
-wrapped mid-milestone checklist, the // milestone-complete cascade also DECREMENTED progress.total_phases (e.g. From 12c828c87479ae76582644c3e374a557d78ee951 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 30 Jun 2026 21:17:08 -0400 Subject: [PATCH 08/14] docs(#1847): point sonnet changeset pr at #1848 Co-Authored-By: Claude Opus 4.8 --- .changeset/1847-claude-sonnet-5-standard-tier.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/1847-claude-sonnet-5-standard-tier.md b/.changeset/1847-claude-sonnet-5-standard-tier.md index b01b141e6..f0bd85f8a 100644 --- a/.changeset/1847-claude-sonnet-5-standard-tier.md +++ b/.changeset/1847-claude-sonnet-5-standard-tier.md @@ -1,5 +1,5 @@ --- type: Added -pr: 1847 +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 tiers are unchanged. (#1847) From 1c352d1ea37b010e99b8353905eb5def4f784100 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 01:31:38 +0000 Subject: [PATCH 09/14] chore: promote CHANGELOG for v1.6.1 --- .changeset/1580-999-sentinel-milestone-roadmap.md | 5 ----- ...1591-phase-complete-details-wrapped-checklist.md | 6 ------ .changeset/1847-claude-sonnet-5-standard-tier.md | 5 ----- .changeset/lucky-quails-greet.md | 5 ----- CHANGELOG.md | 13 +++++++++++++ 5 files changed, 13 insertions(+), 21 deletions(-) delete mode 100644 .changeset/1580-999-sentinel-milestone-roadmap.md delete mode 100644 .changeset/1591-phase-complete-details-wrapped-checklist.md delete mode 100644 .changeset/1847-claude-sonnet-5-standard-tier.md delete mode 100644 .changeset/lucky-quails-greet.md 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/1591-phase-complete-details-wrapped-checklist.md b/.changeset/1591-phase-complete-details-wrapped-checklist.md deleted file mode 100644 index c6814916b..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 both heading-style (`### Phase N:`) and checkbox-list phases (`- [ ] Phase N:` / `- [x] Phase N:`); `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/1847-claude-sonnet-5-standard-tier.md b/.changeset/1847-claude-sonnet-5-standard-tier.md deleted file mode 100644 index f0bd85f8a..000000000 --- a/.changeset/1847-claude-sonnet-5-standard-tier.md +++ /dev/null @@ -1,5 +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 tiers are unchanged. (#1847) 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/CHANGELOG.md b/CHANGELOG.md index 3dbc738ca..0a64f2189 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +## [1.6.1] - 2026-07-01 + +### Added + +- **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 tiers are unchanged. (#1847) (#1848) + +### Fixed + +- `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) +- **`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 both heading-style (`### Phase N:`) and checkbox-list phases (`- [ ] Phase N:` / `- [x] Phase N:`); `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) +- 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) + ## [1.6.0] - 2026-06-24 ### Added From 72292ba1497def2b367edf6c0cc507626bb1d21a Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Tue, 14 Jul 2026 21:15:03 -0400 Subject: [PATCH 10/14] ci: raise finalize job timeout 10m->30m to match rc (suite growth) --- .github/workflows/release.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f39cf0242..19e5ec846 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -507,7 +507,10 @@ jobs: needs: [validate-version, install-smoke-finalize] if: inputs.action == 'finalize' runs-on: ubuntu-latest - timeout-minutes: 10 + # Matches the rc job's budget: `npm ci` + `npm run test:coverage:unit` now + # exceeds 10m as the unit suite grows, so a 10m cap cancels the job mid-test + # before tag/publish. 30m gives the same headroom rc already relies on. + timeout-minutes: 30 permissions: contents: write pull-requests: write From dd4c90f82f5188ba60859da1b89fa9b3ab0bf1b2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:33:01 +0000 Subject: [PATCH 11/14] chore: finalize v1.7.0 --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- capabilities/ai-integration/capability.json | 2 +- capabilities/antigravity/capability.json | 2 +- capabilities/assumption-delta/capability.json | 2 +- capabilities/audit/capability.json | 2 +- capabilities/augment/capability.json | 2 +- .../claude-orchestration/capability.json | 2 +- capabilities/claude/capability.json | 2 +- capabilities/cline/capability.json | 2 +- capabilities/code-review/capability.json | 2 +- capabilities/codebuddy/capability.json | 2 +- capabilities/codex/capability.json | 2 +- capabilities/copilot/capability.json | 2 +- capabilities/cursor/capability.json | 2 +- capabilities/drift/capability.json | 2 +- capabilities/external-job/capability.json | 2 +- capabilities/gap-analysis/capability.json | 2 +- capabilities/graphify/capability.json | 2 +- capabilities/hermes/capability.json | 2 +- capabilities/intel/capability.json | 2 +- capabilities/kilo/capability.json | 2 +- capabilities/kimi/capability.json | 2 +- capabilities/mempalace/capability.json | 2 +- capabilities/nyquist/capability.json | 2 +- capabilities/opencode/capability.json | 2 +- capabilities/pattern-mapper/capability.json | 2 +- capabilities/pi/capability.json | 2 +- capabilities/profile-pipeline/capability.json | 2 +- capabilities/qwen/capability.json | 2 +- capabilities/research/capability.json | 2 +- capabilities/schema-gate/capability.json | 2 +- capabilities/security/capability.json | 2 +- capabilities/tdd/capability.json | 2 +- capabilities/trae/capability.json | 2 +- capabilities/ui/capability.json | 2 +- capabilities/vscode/capability.json | 2 +- capabilities/windsurf/capability.json | 2 +- capabilities/zcode/capability.json | 2 +- gsd-core/bin/lib/capability-registry.cjs | 110 +++++++++--------- package-lock.json | 4 +- package.json | 2 +- vscode/package.json | 2 +- 43 files changed, 98 insertions(+), 98 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6af927e23..05bdc022d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ { "name": "gsd-core", "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.", - "version": "1.7.0-rc.6", + "version": "1.7.0", "source": "./", "author": { "name": "open-gsd", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 8fd746b7c..e208749f5 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "gsd-core", "displayName": "GSD Core", - "version": "1.7.0-rc.6", + "version": "1.7.0", "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.", "author": { "name": "open-gsd", diff --git a/capabilities/ai-integration/capability.json b/capabilities/ai-integration/capability.json index 937bb4cd8..3d33785a0 100644 --- a/capabilities/ai-integration/capability.json +++ b/capabilities/ai-integration/capability.json @@ -1,7 +1,7 @@ { "id": "ai-integration", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "AI design contract", "description": "AI-SPEC design contract workflow for phases that build AI systems; owns the AI integration command, agents, and workflow.ai_integration_phase activation key.", "tier": "full", diff --git a/capabilities/antigravity/capability.json b/capabilities/antigravity/capability.json index 996fb4191..2a3660192 100644 --- a/capabilities/antigravity/capability.json +++ b/capabilities/antigravity/capability.json @@ -1,7 +1,7 @@ { "id": "antigravity", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.", "tier": "core", diff --git a/capabilities/assumption-delta/capability.json b/capabilities/assumption-delta/capability.json index 4634ba396..2c40b5ffa 100644 --- a/capabilities/assumption-delta/capability.json +++ b/capabilities/assumption-delta/capability.json @@ -1,7 +1,7 @@ { "id": "assumption-delta", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Assumption-delta architecture checkpoint", "description": "Rarely-firing advisory checkpoint that triggers when a phase makes something plural, optional, or chosen that used to be singular, required, or derived. Surfaces one identity-model question (promote the new general representation to primary, or add it alongside?) so a silent primary-key drift does not accumulate into a later user-facing bug. Non-blocking; fires only on a detected signal.", "tier": "full", diff --git a/capabilities/audit/capability.json b/capabilities/audit/capability.json index 0dd08f936..d8fa0f66d 100644 --- a/capabilities/audit/capability.json +++ b/capabilities/audit/capability.json @@ -1,7 +1,7 @@ { "id": "audit", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Audit", "description": "Open-artifact audit and UAT-gap audit for milestone close gates; exposes `gsd-tools audit-uat` (cross-phase UAT outstanding items) and `gsd-tools audit-open` (structured open-artifact scan across debug, tasks, threads, todos, seeds, UAT, verification, context-questions).", "tier": "full", diff --git a/capabilities/augment/capability.json b/capabilities/augment/capability.json index ffa16d6a9..979d354cf 100644 --- a/capabilities/augment/capability.json +++ b/capabilities/augment/capability.json @@ -1,7 +1,7 @@ { "id": "augment", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Augment Code", "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/claude-orchestration/capability.json b/capabilities/claude-orchestration/capability.json index 6c9dd8f1b..31a9e815e 100644 --- a/capabilities/claude-orchestration/capability.json +++ b/capabilities/claude-orchestration/capability.json @@ -1,7 +1,7 @@ { "id": "claude-orchestration", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Claude orchestration (Workflow backend)", "description": "Default-off, BETA, claude-only capability that adopts Claude Code's Workflow tool (the engine behind /effort ultracode) as an optional parallel-execution backend for the GSD loop. When the runtime exposes the Workflow tool and claude_orchestration.execution_backend resolves to 'workflow', 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 token budget) that composes the SAME gsd-executor agent and worktree isolation the inline path uses, restoring the wave parallelism the #853 backgrounded-agent nesting limitation forces inline on Claude Code. (The plan-checker and verifier remain inline until separately wired — this capability delivers the parallel-execution backend, not those gates.) Also folds the ultraplan plan-offload under one runtime gate (plan:* surface). On any runtime lacking the Workflow tool, or when the capability is disabled, behaviour is byte-identical to today (inline/manual dispatch). Detection + emission live in gsd-core/bin/lib/claude-orchestration.cjs (pure, fail-closed). Mirrors the existing gsd-ultraplan-phase BETA-isolation posture.", "tier": "full", diff --git a/capabilities/claude/capability.json b/capabilities/claude/capability.json index fa1dbcfd1..e9223b595 100644 --- a/capabilities/claude/capability.json +++ b/capabilities/claude/capability.json @@ -1,7 +1,7 @@ { "id": "claude", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Claude Code", "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.", "tier": "core", diff --git a/capabilities/cline/capability.json b/capabilities/cline/capability.json index 7fb53a3a7..99766ddf0 100644 --- a/capabilities/cline/capability.json +++ b/capabilities/cline/capability.json @@ -1,7 +1,7 @@ { "id": "cline", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Cline", "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.", "tier": "core", diff --git a/capabilities/code-review/capability.json b/capabilities/code-review/capability.json index acdcfe088..d7580f9a7 100644 --- a/capabilities/code-review/capability.json +++ b/capabilities/code-review/capability.json @@ -1,7 +1,7 @@ { "id": "code-review", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Code review", "description": "Source-file code review and review-fix workflow support for completed execution work.", "tier": "full", diff --git a/capabilities/codebuddy/capability.json b/capabilities/codebuddy/capability.json index d915d5922..504b3b85a 100644 --- a/capabilities/codebuddy/capability.json +++ b/capabilities/codebuddy/capability.json @@ -1,7 +1,7 @@ { "id": "codebuddy", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/codex/capability.json b/capabilities/codex/capability.json index ab5533549..232a93ba0 100644 --- a/capabilities/codex/capability.json +++ b/capabilities/codex/capability.json @@ -1,7 +1,7 @@ { "id": "codex", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "OpenAI Codex CLI", "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.", "tier": "core", diff --git a/capabilities/copilot/capability.json b/capabilities/copilot/capability.json index 304c46c6c..9571b813d 100644 --- a/capabilities/copilot/capability.json +++ b/capabilities/copilot/capability.json @@ -1,7 +1,7 @@ { "id": "copilot", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "GitHub Copilot", "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.", "tier": "core", diff --git a/capabilities/cursor/capability.json b/capabilities/cursor/capability.json index 69d5a3050..bf8ca2eda 100644 --- a/capabilities/cursor/capability.json +++ b/capabilities/cursor/capability.json @@ -1,7 +1,7 @@ { "id": "cursor", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Cursor", "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.", "tier": "core", diff --git a/capabilities/drift/capability.json b/capabilities/drift/capability.json index 64539626c..3dd1487d4 100644 --- a/capabilities/drift/capability.json +++ b/capabilities/drift/capability.json @@ -1,7 +1,7 @@ { "id": "drift", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Drift detection gates", "description": "Drift detection gates for the planning loop. At execute:wave:post: a blocking schema drift gate (detects schema files changed without a database push) and a non-blocking codebase drift gate (detects structural additions not reflected in STRUCTURE.md). At plan:pre: a non-blocking, warn-only codebase drift gate (gated on workflow.plan_drift_precheck) that flags a stale codebase map before planning, so plans are authored against a fresh STRUCTURE.md instead of discovering drift mid-execution.", "tier": "full", diff --git a/capabilities/external-job/capability.json b/capabilities/external-job/capability.json index 5541349da..affd4da7b 100644 --- a/capabilities/external-job/capability.json +++ b/capabilities/external-job/capability.json @@ -1,7 +1,7 @@ { "id": "external-job", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Async external-job scheduler adapter", "description": "Default-off producer of the async external-job manifest (#1164). At execute:wave:post an executor can externalize long-running compute (SLURM first, scheduler-pluggable), commit a .planning/async-jobs/.json manifest, defer SUMMARY.md, and return external_job_waiting. The core loop (#1165) consumes the manifest; this capability is the only thing that writes it. NOTE on contribution point: #1164 specifies execute:wave:pre, but execute-phase.md only dispatches execute:wave:post today (wave:pre is declared in the loop host contract but not rendered); wiring wave:pre dispatch is a core-loop change #1164 explicitly puts out of scope, so this capability registers at wave:post and the executor honors the runtime_budget classification guidance before running any tagged task. The adapter (scripts/slurm-adapter.cjs) reads external_job.submit_timeout_ms / poll_timeout_ms / artifact_dir through the canonical capability-config seam (env override > config > registry default).", "tier": "full", diff --git a/capabilities/gap-analysis/capability.json b/capabilities/gap-analysis/capability.json index 05f592e4d..39a176d6c 100644 --- a/capabilities/gap-analysis/capability.json +++ b/capabilities/gap-analysis/capability.json @@ -1,7 +1,7 @@ { "id": "gap-analysis", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Post-planning gap analysis", "description": "Proactive, non-blocking post-planning coverage report. After all PLAN.md files are generated, cross-references every REQ-ID and D-ID from REQUIREMENTS.md and CONTEXT.md against plan bodies. Emits a Source | Item | Status table. Does not block phase advancement.", "tier": "standard", diff --git a/capabilities/graphify/capability.json b/capabilities/graphify/capability.json index 0b4d10610..b5c438a6f 100644 --- a/capabilities/graphify/capability.json +++ b/capabilities/graphify/capability.json @@ -1,7 +1,7 @@ { "id": "graphify", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Knowledge graph", "description": "Build, query, and inspect the project knowledge graph in `.planning/graphs/`; exposes graphify CLI subcommands (build, query, status, diff) and the /gsd-graphify skill.", "tier": "full", diff --git a/capabilities/hermes/capability.json b/capabilities/hermes/capability.json index a125f6893..46e1833d5 100644 --- a/capabilities/hermes/capability.json +++ b/capabilities/hermes/capability.json @@ -1,7 +1,7 @@ { "id": "hermes", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Hermes Agent", "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/intel/capability.json b/capabilities/intel/capability.json index f3a39a7ff..aa795f8e9 100644 --- a/capabilities/intel/capability.json +++ b/capabilities/intel/capability.json @@ -1,7 +1,7 @@ { "id": "intel", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Codebase intelligence", "description": "Code-intelligence store for codebase querying, diff, snapshot, and API-surface extraction; exposes `gsd-tools intel` subcommands (query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface) and backs `/gsd-map-codebase` and `gsd-intel-updater`.", "tier": "full", diff --git a/capabilities/kilo/capability.json b/capabilities/kilo/capability.json index fe8b82e58..8326113cc 100644 --- a/capabilities/kilo/capability.json +++ b/capabilities/kilo/capability.json @@ -1,7 +1,7 @@ { "id": "kilo", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Kilo Code", "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.", "tier": "core", diff --git a/capabilities/kimi/capability.json b/capabilities/kimi/capability.json index 23184955d..1c61df833 100644 --- a/capabilities/kimi/capability.json +++ b/capabilities/kimi/capability.json @@ -1,7 +1,7 @@ { "id": "kimi", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Kimi CLI", "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; native config.toml [[hooks]] bus at ~/.kimi/config.toml; background dispatch; tier-2 support.", "tier": "core", diff --git a/capabilities/mempalace/capability.json b/capabilities/mempalace/capability.json index 63ea31e1d..42e8a6cea 100644 --- a/capabilities/mempalace/capability.json +++ b/capabilities/mempalace/capability.json @@ -1,7 +1,7 @@ { "id": "mempalace", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "MemPalace memory", "description": "Cross-session, cross-project memory: deliberate recall before discuss/plan and verbatim capture + temporal-KG sync at phase boundaries, via the MemPalace MCP server and CLI.", "tier": "full", diff --git a/capabilities/nyquist/capability.json b/capabilities/nyquist/capability.json index c6639c4fe..e3107d5e5 100644 --- a/capabilities/nyquist/capability.json +++ b/capabilities/nyquist/capability.json @@ -1,7 +1,7 @@ { "id": "nyquist", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Nyquist validation", "description": "Validation coverage audit that maps executed work back to tests and manual-only evidence.", "tier": "full", diff --git a/capabilities/opencode/capability.json b/capabilities/opencode/capability.json index f18c39c5e..c92438326 100644 --- a/capabilities/opencode/capability.json +++ b/capabilities/opencode/capability.json @@ -1,7 +1,7 @@ { "id": "opencode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "OpenCode", "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.", "tier": "core", diff --git a/capabilities/pattern-mapper/capability.json b/capabilities/pattern-mapper/capability.json index a8086a88a..f1709e007 100644 --- a/capabilities/pattern-mapper/capability.json +++ b/capabilities/pattern-mapper/capability.json @@ -1,7 +1,7 @@ { "id": "pattern-mapper", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Pattern mapping", "description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.", "tier": "full", diff --git a/capabilities/pi/capability.json b/capabilities/pi/capability.json index caa54b1f4..a48edcfd8 100644 --- a/capabilities/pi/capability.json +++ b/capabilities/pi/capability.json @@ -1,7 +1,7 @@ { "id": "pi", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "pi", "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.cjs; no shared-settings hook surface; tier-2 support.", "tier": "core", diff --git a/capabilities/profile-pipeline/capability.json b/capabilities/profile-pipeline/capability.json index 3293d8dcf..0a45ba8aa 100644 --- a/capabilities/profile-pipeline/capability.json +++ b/capabilities/profile-pipeline/capability.json @@ -1,7 +1,7 @@ { "id": "profile-pipeline", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Developer profiling pipeline", "description": "Developer behavioral profiling from Claude Code session history; scans session JSONL files, extracts and samples user messages, and generates profile artifacts (USER-PROFILE.md, dev-preferences.md, CLAUDE.md sections). Exposes eight `gsd-tools` commands: scan-sessions, extract-messages, profile-sample (pipeline phase) and write-profile, profile-questionnaire, generate-dev-preferences, generate-claude-profile, generate-claude-md (output phase). Backs the /gsd-profile-user skill and gsd-user-profiler agent.", "tier": "full", diff --git a/capabilities/qwen/capability.json b/capabilities/qwen/capability.json index 65bc957be..33bd1e1ed 100644 --- a/capabilities/qwen/capability.json +++ b/capabilities/qwen/capability.json @@ -1,7 +1,7 @@ { "id": "qwen", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Qwen Code", "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", diff --git a/capabilities/research/capability.json b/capabilities/research/capability.json index 1715811c5..387d71165 100644 --- a/capabilities/research/capability.json +++ b/capabilities/research/capability.json @@ -1,7 +1,7 @@ { "id": "research", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Phase research", "description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.", "tier": "standard", diff --git a/capabilities/schema-gate/capability.json b/capabilities/schema-gate/capability.json index f00c9feb4..b48e1871b 100644 --- a/capabilities/schema-gate/capability.json +++ b/capabilities/schema-gate/capability.json @@ -1,7 +1,7 @@ { "id": "schema-gate", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Schema push detection gate", "description": "Detects ORM schema-relevant files in the phase scope during planning and injects a mandatory [BLOCKING] schema push task into the plan. Prevents false-positive verification where build/types pass because TypeScript types come from config, not the live database.", "tier": "full", diff --git a/capabilities/security/capability.json b/capabilities/security/capability.json index 268351cf3..de255d52a 100644 --- a/capabilities/security/capability.json +++ b/capabilities/security/capability.json @@ -1,7 +1,7 @@ { "id": "security", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Security enforcement", "description": "Threat mitigation verification and ship-time security blocking for phases with security enforcement enabled.", "tier": "full", diff --git a/capabilities/tdd/capability.json b/capabilities/tdd/capability.json index a181bc3b4..b1c8d1829 100644 --- a/capabilities/tdd/capability.json +++ b/capabilities/tdd/capability.json @@ -1,7 +1,7 @@ { "id": "tdd", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Test-driven development", "description": "Injects TDD heuristics into the planner and enforces RED/GREEN gate compliance on type:tdd plans after execution. Owns workflow.tdd_mode; the --tdd CLI flag is the ephemeral override.", "tier": "full", diff --git a/capabilities/trae/capability.json b/capabilities/trae/capability.json index 350ff2117..8dcb5a730 100644 --- a/capabilities/trae/capability.json +++ b/capabilities/trae/capability.json @@ -1,7 +1,7 @@ { "id": "trae", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", diff --git a/capabilities/ui/capability.json b/capabilities/ui/capability.json index a1539f2dd..64b9b09e4 100644 --- a/capabilities/ui/capability.json +++ b/capabilities/ui/capability.json @@ -1,7 +1,7 @@ { "id": "ui", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "UI design contracts", "description": "UI-SPEC design contract + retrospective UI audit for frontend phases.", "tier": "full", diff --git a/capabilities/vscode/capability.json b/capabilities/vscode/capability.json index bad8ac769..d0f0ec25b 100644 --- a/capabilities/vscode/capability.json +++ b/capabilities/vscode/capability.json @@ -1,7 +1,7 @@ { "id": "vscode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "VS Code", "description": "VS Code — Marketplace/VSIX extension; no file-projected config directory; IDE-profile reference host (active vscode.lm model, engine-owned hook bus, sandboxed globalState/workspaceState stateIO).", "tier": "core", diff --git a/capabilities/windsurf/capability.json b/capabilities/windsurf/capability.json index 5c99b40f4..46714bb3a 100644 --- a/capabilities/windsurf/capability.json +++ b/capabilities/windsurf/capability.json @@ -1,7 +1,7 @@ { "id": "windsurf", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Windsurf", "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; Cascade native hooks.json blocking hook bus (pre_write_code, pre_run_command); tier-2 support.", "tier": "core", diff --git a/capabilities/zcode/capability.json b/capabilities/zcode/capability.json index b86ee3abf..c864cf9ee 100644 --- a/capabilities/zcode/capability.json +++ b/capabilities/zcode/capability.json @@ -1,7 +1,7 @@ { "id": "zcode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "ZCode", "description": "ZCode (Z.ai) — desktop Agentic Development Environment for GLM-5.2; Claude-shaped nested skills at ~/.zcode/skills//SKILL.md, slash commands, named subagents, native MCP; declarative plugin surface; profile-marker install; tier-2 community support.", "tier": "core", diff --git a/gsd-core/bin/lib/capability-registry.cjs b/gsd-core/bin/lib/capability-registry.cjs index bde61caf9..e90ea3576 100644 --- a/gsd-core/bin/lib/capability-registry.cjs +++ b/gsd-core/bin/lib/capability-registry.cjs @@ -10,7 +10,7 @@ const capabilities = { "ai-integration": { "id": "ai-integration", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "AI design contract", "description": "AI-SPEC design contract workflow for phases that build AI systems; owns the AI integration command, agents, and workflow.ai_integration_phase activation key.", "tier": "full", @@ -95,7 +95,7 @@ const capabilities = { "antigravity": { "id": "antigravity", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.", "tier": "core", @@ -196,7 +196,7 @@ const capabilities = { "assumption-delta": { "id": "assumption-delta", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Assumption-delta architecture checkpoint", "description": "Rarely-firing advisory checkpoint that triggers when a phase makes something plural, optional, or chosen that used to be singular, required, or derived. Surfaces one identity-model question (promote the new general representation to primary, or add it alongside?) so a silent primary-key drift does not accumulate into a later user-facing bug. Non-blocking; fires only on a detected signal.", "tier": "full", @@ -242,7 +242,7 @@ const capabilities = { "audit": { "id": "audit", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Audit", "description": "Open-artifact audit and UAT-gap audit for milestone close gates; exposes `gsd-tools audit-uat` (cross-phase UAT outstanding items) and `gsd-tools audit-open` (structured open-artifact scan across debug, tasks, threads, todos, seeds, UAT, verification, context-questions).", "tier": "full", @@ -279,7 +279,7 @@ const capabilities = { "augment": { "id": "augment", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Augment Code", "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -386,7 +386,7 @@ const capabilities = { "claude": { "id": "claude", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Claude Code", "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.", "tier": "core", @@ -491,7 +491,7 @@ const capabilities = { "claude-orchestration": { "id": "claude-orchestration", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Claude orchestration (Workflow backend)", "description": "Default-off, BETA, claude-only capability that adopts Claude Code's Workflow tool (the engine behind /effort ultracode) as an optional parallel-execution backend for the GSD loop. When the runtime exposes the Workflow tool and claude_orchestration.execution_backend resolves to 'workflow', 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 token budget) that composes the SAME gsd-executor agent and worktree isolation the inline path uses, restoring the wave parallelism the #853 backgrounded-agent nesting limitation forces inline on Claude Code. (The plan-checker and verifier remain inline until separately wired — this capability delivers the parallel-execution backend, not those gates.) Also folds the ultraplan plan-offload under one runtime gate (plan:* surface). On any runtime lacking the Workflow tool, or when the capability is disabled, behaviour is byte-identical to today (inline/manual dispatch). Detection + emission live in gsd-core/bin/lib/claude-orchestration.cjs (pure, fail-closed). Mirrors the existing gsd-ultraplan-phase BETA-isolation posture.", "tier": "full", @@ -578,7 +578,7 @@ const capabilities = { "cline": { "id": "cline", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Cline", "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.", "tier": "core", @@ -647,7 +647,7 @@ const capabilities = { "code-review": { "id": "code-review", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Code review", "description": "Source-file code review and review-fix workflow support for completed execution work.", "tier": "full", @@ -708,7 +708,7 @@ const capabilities = { "codebuddy": { "id": "codebuddy", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -819,7 +819,7 @@ const capabilities = { "codex": { "id": "codex", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "OpenAI Codex CLI", "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.", "tier": "core", @@ -904,7 +904,7 @@ const capabilities = { "copilot": { "id": "copilot", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "GitHub Copilot", "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.", "tier": "core", @@ -997,7 +997,7 @@ const capabilities = { "cursor": { "id": "cursor", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Cursor", "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.", "tier": "core", @@ -1118,7 +1118,7 @@ const capabilities = { "drift": { "id": "drift", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Drift detection gates", "description": "Drift detection gates for the planning loop. At execute:wave:post: a blocking schema drift gate (detects schema files changed without a database push) and a non-blocking codebase drift gate (detects structural additions not reflected in STRUCTURE.md). At plan:pre: a non-blocking, warn-only codebase drift gate (gated on workflow.plan_drift_precheck) that flags a stale codebase map before planning, so plans are authored against a fresh STRUCTURE.md instead of discovering drift mid-execution.", "tier": "full", @@ -1196,7 +1196,7 @@ const capabilities = { "external-job": { "id": "external-job", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Async external-job scheduler adapter", "description": "Default-off producer of the async external-job manifest (#1164). At execute:wave:post an executor can externalize long-running compute (SLURM first, scheduler-pluggable), commit a .planning/async-jobs/.json manifest, defer SUMMARY.md, and return external_job_waiting. The core loop (#1165) consumes the manifest; this capability is the only thing that writes it. NOTE on contribution point: #1164 specifies execute:wave:pre, but execute-phase.md only dispatches execute:wave:post today (wave:pre is declared in the loop host contract but not rendered); wiring wave:pre dispatch is a core-loop change #1164 explicitly puts out of scope, so this capability registers at wave:post and the executor honors the runtime_budget classification guidance before running any tagged task. The adapter (scripts/slurm-adapter.cjs) reads external_job.submit_timeout_ms / poll_timeout_ms / artifact_dir through the canonical capability-config seam (env override > config > registry default).", "tier": "full", @@ -1279,7 +1279,7 @@ const capabilities = { "gap-analysis": { "id": "gap-analysis", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Post-planning gap analysis", "description": "Proactive, non-blocking post-planning coverage report. After all PLAN.md files are generated, cross-references every REQ-ID and D-ID from REQUIREMENTS.md and CONTEXT.md against plan bodies. Emits a Source | Item | Status table. Does not block phase advancement.", "tier": "standard", @@ -1320,7 +1320,7 @@ const capabilities = { "graphify": { "id": "graphify", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Knowledge graph", "description": "Build, query, and inspect the project knowledge graph in `.planning/graphs/`; exposes graphify CLI subcommands (build, query, status, diff) and the /gsd-graphify skill.", "tier": "full", @@ -1361,7 +1361,7 @@ const capabilities = { "hermes": { "id": "hermes", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Hermes Agent", "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -1450,7 +1450,7 @@ const capabilities = { "intel": { "id": "intel", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Codebase intelligence", "description": "Code-intelligence store for codebase querying, diff, snapshot, and API-surface extraction; exposes `gsd-tools intel` subcommands (query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface) and backs `/gsd-map-codebase` and `gsd-intel-updater`.", "tier": "full", @@ -1502,7 +1502,7 @@ const capabilities = { "kilo": { "id": "kilo", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Kilo Code", "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -1610,7 +1610,7 @@ const capabilities = { "kimi": { "id": "kimi", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Kimi CLI", "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; native config.toml [[hooks]] bus at ~/.kimi/config.toml; background dispatch; tier-2 support.", "tier": "core", @@ -1698,7 +1698,7 @@ const capabilities = { "mempalace": { "id": "mempalace", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "MemPalace memory", "description": "Cross-session, cross-project memory: deliberate recall before discuss/plan and verbatim capture + temporal-KG sync at phase boundaries, via the MemPalace MCP server and CLI.", "tier": "full", @@ -1872,7 +1872,7 @@ const capabilities = { "nyquist": { "id": "nyquist", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Nyquist validation", "description": "Validation coverage audit that maps executed work back to tests and manual-only evidence.", "tier": "full", @@ -1922,7 +1922,7 @@ const capabilities = { "opencode": { "id": "opencode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "OpenCode", "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -2028,7 +2028,7 @@ const capabilities = { "pattern-mapper": { "id": "pattern-mapper", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Pattern mapping", "description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.", "tier": "full", @@ -2082,7 +2082,7 @@ const capabilities = { "pi": { "id": "pi", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "pi", "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.cjs; no shared-settings hook surface; tier-2 support.", "tier": "core", @@ -2142,7 +2142,7 @@ const capabilities = { "profile-pipeline": { "id": "profile-pipeline", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Developer profiling pipeline", "description": "Developer behavioral profiling from Claude Code session history; scans session JSONL files, extracts and samples user messages, and generates profile artifacts (USER-PROFILE.md, dev-preferences.md, CLAUDE.md sections). Exposes eight `gsd-tools` commands: scan-sessions, extract-messages, profile-sample (pipeline phase) and write-profile, profile-questionnaire, generate-dev-preferences, generate-claude-profile, generate-claude-md (output phase). Backs the /gsd-profile-user skill and gsd-user-profiler agent.", "tier": "full", @@ -2219,7 +2219,7 @@ const capabilities = { "qwen": { "id": "qwen", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Qwen Code", "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -2324,7 +2324,7 @@ const capabilities = { "research": { "id": "research", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Phase research", "description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.", "tier": "standard", @@ -2376,7 +2376,7 @@ const capabilities = { "schema-gate": { "id": "schema-gate", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Schema push detection gate", "description": "Detects ORM schema-relevant files in the phase scope during planning and injects a mandatory [BLOCKING] schema push task into the plan. Prevents false-positive verification where build/types pass because TypeScript types come from config, not the live database.", "tier": "full", @@ -2422,7 +2422,7 @@ const capabilities = { "security": { "id": "security", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Security enforcement", "description": "Threat mitigation verification and ship-time security blocking for phases with security enforcement enabled.", "tier": "full", @@ -2521,7 +2521,7 @@ const capabilities = { "tdd": { "id": "tdd", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Test-driven development", "description": "Injects TDD heuristics into the planner and enforces RED/GREEN gate compliance on type:tdd plans after execution. Owns workflow.tdd_mode; the --tdd CLI flag is the ephemeral override.", "tier": "full", @@ -2574,7 +2574,7 @@ const capabilities = { "trae": { "id": "trae", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", @@ -2664,7 +2664,7 @@ const capabilities = { "ui": { "id": "ui", "role": "feature", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "UI design contracts", "description": "UI-SPEC design contract + retrospective UI audit for frontend phases.", "tier": "full", @@ -2759,7 +2759,7 @@ const capabilities = { "vscode": { "id": "vscode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "VS Code", "description": "VS Code — Marketplace/VSIX extension; no file-projected config directory; IDE-profile reference host (active vscode.lm model, engine-owned hook bus, sandboxed globalState/workspaceState stateIO).", "tier": "core", @@ -2810,7 +2810,7 @@ const capabilities = { "windsurf": { "id": "windsurf", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Windsurf", "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; Cascade native hooks.json blocking hook bus (pre_write_code, pre_run_command); tier-2 support.", "tier": "core", @@ -2895,7 +2895,7 @@ const capabilities = { "zcode": { "id": "zcode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "ZCode", "description": "ZCode (Z.ai) — desktop Agentic Development Environment for GLM-5.2; Claude-shaped nested skills at ~/.zcode/skills//SKILL.md, slash commands, named subagents, native MCP; declarative plugin surface; profile-marker install; tier-2 community support.", "tier": "core", @@ -3906,7 +3906,7 @@ const runtimes = { "antigravity": { "id": "antigravity", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; flat skill layout; tier-1 support.", "tier": "core", @@ -4007,7 +4007,7 @@ const runtimes = { "augment": { "id": "augment", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Augment Code", "description": "Augment Code CLI — commands + nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -4114,7 +4114,7 @@ const runtimes = { "claude": { "id": "claude", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Claude Code", "description": "Anthropic Claude Code — primary development runtime; tier-1 support with full hook surface and skills-based global install.", "tier": "core", @@ -4219,7 +4219,7 @@ const runtimes = { "cline": { "id": "cline", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Cline", "description": "Cline (VS Code extension) — global-only nested-skill layout; cline-rules hook surface (.clinerules); no hook events emitted; tier-2 support.", "tier": "core", @@ -4288,7 +4288,7 @@ const runtimes = { "codebuddy": { "id": "codebuddy", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -4399,7 +4399,7 @@ const runtimes = { "codex": { "id": "codex", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "OpenAI Codex CLI", "description": "OpenAI Codex CLI — shell-var command style; per-agent sandbox tiers; config.toml + hooks.json hook surface; tier-1 support.", "tier": "core", @@ -4484,7 +4484,7 @@ const runtimes = { "copilot": { "id": "copilot", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "GitHub Copilot", "description": "GitHub Copilot (VS Code) — markdown config format; copilot-inline hook surface; no hook events emitted; flat skill nesting (unconfirmed recursive loader); tier-2 support.", "tier": "core", @@ -4577,7 +4577,7 @@ const runtimes = { "cursor": { "id": "cursor", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Cursor", "description": "Cursor IDE — skills + converted commands artifact layout; hooks.json surface; Claude hook event dialect; recursive skill loader (flat nesting); tier-2 support.", "tier": "core", @@ -4698,7 +4698,7 @@ const runtimes = { "hermes": { "id": "hermes", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Hermes Agent", "description": "Hermes Agent (NousResearch) — skills nest under skills/gsd/ category bucket; nested skill layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -4787,7 +4787,7 @@ const runtimes = { "kilo": { "id": "kilo", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Kilo Code", "description": "Kilo Code — XDG-based config dir; global skills at ~/.kilo/skills (separate from XDG config); flat command/ + skills artifact layout; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -4895,7 +4895,7 @@ const runtimes = { "kimi": { "id": "kimi", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Kimi CLI", "description": "Kimi CLI (Moonshot AI) — generic agents root at ~/.config/agents; skills + kimi-agents artifact layout; native config.toml [[hooks]] bus at ~/.kimi/config.toml; background dispatch; tier-2 support.", "tier": "core", @@ -4983,7 +4983,7 @@ const runtimes = { "opencode": { "id": "opencode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "OpenCode", "description": "OpenCode — XDG-based config dir; flat command/ + skills artifact layout; settings-json config format; no lifecycle hook registration; tier-2 support.", "tier": "core", @@ -5089,7 +5089,7 @@ const runtimes = { "pi": { "id": "pi", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "pi", "description": "pi (pi.dev) — bun-runtime programmatic-CLI; TS ExtensionAPI (registerCommand/registerTool/registerProvider/pi.on); single native-extension file at ~/.pi/agent/extensions/gsd.cjs; no shared-settings hook surface; tier-2 support.", "tier": "core", @@ -5149,7 +5149,7 @@ const runtimes = { "qwen": { "id": "qwen", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Qwen Code", "description": "Qwen Code (Alibaba) — nested-skill artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -5254,7 +5254,7 @@ const runtimes = { "trae": { "id": "trae", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", @@ -5344,7 +5344,7 @@ const runtimes = { "vscode": { "id": "vscode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "VS Code", "description": "VS Code — Marketplace/VSIX extension; no file-projected config directory; IDE-profile reference host (active vscode.lm model, engine-owned hook bus, sandboxed globalState/workspaceState stateIO).", "tier": "core", @@ -5395,7 +5395,7 @@ const runtimes = { "windsurf": { "id": "windsurf", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "Windsurf", "description": "Windsurf (Codeium) — workspace workflow artifact layout for slash commands; Cascade native hooks.json blocking hook bus (pre_write_code, pre_run_command); tier-2 support.", "tier": "core", @@ -5480,7 +5480,7 @@ const runtimes = { "zcode": { "id": "zcode", "role": "runtime", - "version": "1.7.0-rc.6", + "version": "1.7.0", "title": "ZCode", "description": "ZCode (Z.ai) — desktop Agentic Development Environment for GLM-5.2; Claude-shaped nested skills at ~/.zcode/skills//SKILL.md, slash commands, named subagents, native MCP; declarative plugin surface; profile-marker install; tier-2 community support.", "tier": "core", diff --git a/package-lock.json b/package-lock.json index 98b85e5ea..2020a3ef2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@opengsd/gsd-core", - "version": "1.7.0-rc.6", + "version": "1.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@opengsd/gsd-core", - "version": "1.7.0-rc.6", + "version": "1.7.0", "license": "MIT", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.84", diff --git a/package.json b/package.json index 95acd9e1c..083b2d3fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@opengsd/gsd-core", - "version": "1.7.0-rc.6", + "version": "1.7.0", "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.", "main": ".opencode/plugins/gsd-core.js", "bin": { diff --git a/vscode/package.json b/vscode/package.json index 0c3991af7..1dbb05caf 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -2,7 +2,7 @@ "name": "gsd-core-vscode", "displayName": "GSD Core", "description": "GSD orchestration engine embedded in VS Code (ADR-1239 IDE profile).", - "version": "1.7.0-rc.6", + "version": "1.7.0", "publisher": "opengsd", "engines": { "vscode": "^1.105.0" From b1c9381b7abbf443f16c197118236b45cdd0486a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:43:00 +0000 Subject: [PATCH 12/14] chore: promote CHANGELOG for v1.7.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 - .../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/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-orcas-wander.md | 7 - .changeset/bold-ravens-wake.md | 7 - .changeset/bold-seals-chatter.md | 5 - .changeset/brave-hawks-fly.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-rams-march.md | 5 - .changeset/curious-koalas-gather.md | 5 - .changeset/curious-pandas-howl.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/eager-bears-wander.md | 5 - .changeset/eager-elks-frolic.md | 7 - .changeset/eager-ibex-bark.md | 5 - .changeset/eager-tunas-swim.md | 5 - .changeset/external-job-config-wiring.md | 5 - .changeset/fierce-bears-gather.md | 5 - .changeset/fierce-pumas-gather.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/graceful-badgers-click.md | 5 - .changeset/graceful-badgers-dance.md | 5 - .changeset/graceful-geese-click.md | 7 - .changeset/graceful-koalas-greet.md | 5 - .changeset/graceful-moles-gather.md | 5 - .changeset/graceful-wasps-caper.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-seals-rest.md | 5 - .changeset/humble-sloths-jump.md | 5 - .changeset/humble-tunas-munch.md | 5 - .changeset/humble-tunas-travel.md | 5 - .changeset/humble-zebras-zip.md | 5 - .changeset/jolly-jays-hop.md | 5 - .changeset/jolly-jays-march.md | 5 - .changeset/kind-lynx-munch.md | 7 - .changeset/kind-tigers-romp.md | 5 - .changeset/lively-lynx-snooze.md | 5 - .changeset/lucky-quails-greet.md | 5 - .changeset/lucky-tigers-leap.md | 6 - .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/noble-foxes-purr.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-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/quick-seals-parade.md | 5 - .changeset/rapid-orcas-sing.md | 7 - .changeset/rapid-pumas-click.md | 5 - .changeset/serene-birds-rest.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/steady-ibex-run.md | 5 - .changeset/steady-lynx-fly.md | 5 - .changeset/steady-mice-frolic.md | 5 - .changeset/sturdy-voles-dart.md | 7 - .changeset/sturdy-voles-tumble.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-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-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-dogs-hop.md | 5 - .changeset/witty-seals-snooze.md | 7 - .changeset/zcode-runtime-1925.md | 5 - .changeset/zesty-rams-march.md | 5 - CHANGELOG.md | 208 ++++++++++++++++++ 183 files changed, 208 insertions(+), 953 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/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/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-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/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-rams-march.md delete mode 100644 .changeset/curious-koalas-gather.md delete mode 100644 .changeset/curious-pandas-howl.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/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-tunas-swim.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/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/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-greet.md delete mode 100644 .changeset/graceful-moles-gather.md delete mode 100644 .changeset/graceful-wasps-caper.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-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-zebras-zip.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-romp.md delete mode 100644 .changeset/lively-lynx-snooze.md delete mode 100644 .changeset/lucky-quails-greet.md delete mode 100644 .changeset/lucky-tigers-leap.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/noble-foxes-purr.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-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/quick-seals-parade.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-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/steady-ibex-run.md delete mode 100644 .changeset/steady-lynx-fly.md delete mode 100644 .changeset/steady-mice-frolic.md delete mode 100644 .changeset/sturdy-voles-dart.md delete mode 100644 .changeset/sturdy-voles-tumble.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-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-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-dogs-hop.md delete mode 100644 .changeset/witty-seals-snooze.md delete mode 100644 .changeset/zcode-runtime-1925.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 2840e7640..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 Kilo and ZCode** — both declare `hooksSurface: 'none'` and have no plugin surface, so the staged `hooks/*.js`, `hooks/*.sh`, `hooks/lib/` and the CommonJS `package.json` marker were dead weight in `~/.kilo/` and `~/.zcode/`. The two hook-copy guards in `install.js` now exclude Kilo and 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. 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/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/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-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/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-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/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/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/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-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/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/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/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-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-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-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-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-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-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/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/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/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/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-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-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/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-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-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/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-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-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-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-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-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-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-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-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..2506e0619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,214 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +## [1.7.0] - 2026-07-15 + +### 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) +- **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) +- +**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) +- **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) + +### Changed + +- +**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) +- **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 Kilo and ZCode** — both declare `hooksSurface: 'none'` and have no plugin surface, so the staged `hooks/*.js`, `hooks/*.sh`, `hooks/lib/` and the CommonJS `package.json` marker were dead weight in `~/.kilo/` and `~/.zcode/`. The two hook-copy guards in `install.js` now exclude Kilo and 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. (#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) +- **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) +- **`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) +- **`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) +- 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) +- **`/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) +- 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) +- **`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-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) +- **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) +- **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) +- 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) +- 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) +- **`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) +- **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) +- **`/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) +- 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) +- **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) +- **`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) +- **`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-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) +- **`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) +- **`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) +- **`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) +- **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) +- **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) +- **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) +- **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) +- 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) +- **`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) +- **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) + +### 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) +- **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 `(`, `[`, ``, ` -**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 `(`, `[`, ``, `