diff --git a/.changeset/curious-eagles-purr.md b/.changeset/curious-eagles-purr.md new file mode 100644 index 000000000..d0bb8852c --- /dev/null +++ b/.changeset/curious-eagles-purr.md @@ -0,0 +1,5 @@ +--- +type: Fixed +pr: 1500 +--- +**`workflow.mvp_mode` now accepted by `config-set`; three undocumented workflow keys added to references** — `workflow.mvp_mode`, `workflow.code_review_command`, and `workflow.plan_chunked` were consumed by planning-pipeline code but could not be set via `config-set` (they were missing from `VALID_CONFIG_KEYS`) or discovered via reference docs. All three are now in the schema and documented in `references/planning-config.md`. (#1500) diff --git a/.changeset/lively-orcas-roam.md b/.changeset/lively-orcas-roam.md new file mode 100644 index 000000000..0cd9159a7 --- /dev/null +++ b/.changeset/lively-orcas-roam.md @@ -0,0 +1,5 @@ +--- +type: Fixed +pr: 1504 +--- +`verify codebase-drift` now reads `workflow.drift_action` and `workflow.drift_threshold` from the correct nested config shape — previously both keys silently no-oped because `loadConfig()` returns a flattened object and `config?.workflow` was always `undefined`. diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 03b85863d..2ca16dae6 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "gsd-core", "displayName": "GSD Core", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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/.github/workflows/release.yml b/.github/workflows/release.yml index bf3af0b70..927ab0c58 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -107,7 +107,7 @@ jobs: needs: validate-version if: inputs.action == 'create' runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 permissions: contents: write steps: @@ -118,6 +118,10 @@ jobs: - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies and build + run: npm ci --silent && npm run build:lib - name: Check branch doesn't already exist env: @@ -358,6 +362,9 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + - name: Install dependencies and build + run: npm ci --silent && npm run build:lib + - name: Bump to pre-release version env: PRE_VERSION: ${{ steps.prerelease.outputs.pre_version }} @@ -523,6 +530,9 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + - name: Install dependencies and build + run: npm ci --silent && npm run build:lib + - name: Set final version env: VERSION: ${{ inputs.version }} diff --git a/capabilities/ai-integration/capability.json b/capabilities/ai-integration/capability.json index d029fad81..7c56d4ede 100644 --- a/capabilities/ai-integration/capability.json +++ b/capabilities/ai-integration/capability.json @@ -1,7 +1,7 @@ { "id": "ai-integration", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 a6065c3b4..36586138b 100644 --- a/capabilities/antigravity/capability.json +++ b/capabilities/antigravity/capability.json @@ -1,7 +1,7 @@ { "id": "antigravity", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; nested skill layout; tier-1 support.", "tier": "core", diff --git a/capabilities/audit/capability.json b/capabilities/audit/capability.json index 7a19ee8cf..1e5c27d98 100644 --- a/capabilities/audit/capability.json +++ b/capabilities/audit/capability.json @@ -1,7 +1,7 @@ { "id": "audit", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 116f2f8c1..28f0095c3 100644 --- a/capabilities/augment/capability.json +++ b/capabilities/augment/capability.json @@ -1,7 +1,7 @@ { "id": "augment", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 30f47f2c3..1416265f7 100644 --- a/capabilities/claude/capability.json +++ b/capabilities/claude/capability.json @@ -1,7 +1,7 @@ { "id": "claude", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 8116f7d59..1fe0247be 100644 --- a/capabilities/cline/capability.json +++ b/capabilities/cline/capability.json @@ -1,7 +1,7 @@ { "id": "cline", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 5a558f01c..24109e6b8 100644 --- a/capabilities/code-review/capability.json +++ b/capabilities/code-review/capability.json @@ -1,7 +1,7 @@ { "id": "code-review", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 930786fe9..987f10305 100644 --- a/capabilities/codebuddy/capability.json +++ b/capabilities/codebuddy/capability.json @@ -1,7 +1,7 @@ { "id": "codebuddy", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 46fe4ebbb..d8b092899 100644 --- a/capabilities/codex/capability.json +++ b/capabilities/codex/capability.json @@ -1,7 +1,7 @@ { "id": "codex", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 5b42a3464..b28307ac4 100644 --- a/capabilities/copilot/capability.json +++ b/capabilities/copilot/capability.json @@ -1,7 +1,7 @@ { "id": "copilot", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 b08d547df..044c46674 100644 --- a/capabilities/cursor/capability.json +++ b/capabilities/cursor/capability.json @@ -1,7 +1,7 @@ { "id": "cursor", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 01b31bc88..23af8acc8 100644 --- a/capabilities/drift/capability.json +++ b/capabilities/drift/capability.json @@ -1,7 +1,7 @@ { "id": "drift", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Drift detection gates", "description": "Post-execution drift detection gates that run after each wave completes. Provides two gates 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).", "tier": "full", diff --git a/capabilities/gap-analysis/capability.json b/capabilities/gap-analysis/capability.json index 6534113c8..63bbaf3f6 100644 --- a/capabilities/gap-analysis/capability.json +++ b/capabilities/gap-analysis/capability.json @@ -1,7 +1,7 @@ { "id": "gap-analysis", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 4aa3a9af6..699e23404 100644 --- a/capabilities/gemini/capability.json +++ b/capabilities/gemini/capability.json @@ -1,7 +1,7 @@ { "id": "gemini", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 1b3830c48..41a7c65d4 100644 --- a/capabilities/graphify/capability.json +++ b/capabilities/graphify/capability.json @@ -1,7 +1,7 @@ { "id": "graphify", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 cd195cdac..6e705fc5e 100644 --- a/capabilities/hermes/capability.json +++ b/capabilities/hermes/capability.json @@ -1,7 +1,7 @@ { "id": "hermes", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 0a5b9d3fc..cc7362dce 100644 --- a/capabilities/intel/capability.json +++ b/capabilities/intel/capability.json @@ -1,7 +1,7 @@ { "id": "intel", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 3c3f0020a..9fa90243d 100644 --- a/capabilities/kilo/capability.json +++ b/capabilities/kilo/capability.json @@ -1,7 +1,7 @@ { "id": "kilo", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 705c6bc5a..84447404c 100644 --- a/capabilities/kimi/capability.json +++ b/capabilities/kimi/capability.json @@ -1,7 +1,7 @@ { "id": "kimi", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 8e434a5f7..7bbf50e79 100644 --- a/capabilities/mempalace/capability.json +++ b/capabilities/mempalace/capability.json @@ -1,7 +1,7 @@ { "id": "mempalace", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 f04f51176..0d1b9f609 100644 --- a/capabilities/nyquist/capability.json +++ b/capabilities/nyquist/capability.json @@ -1,7 +1,7 @@ { "id": "nyquist", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 0ccfebaeb..12468558b 100644 --- a/capabilities/opencode/capability.json +++ b/capabilities/opencode/capability.json @@ -1,7 +1,7 @@ { "id": "opencode", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 ce3fda24e..4311f5c2a 100644 --- a/capabilities/pattern-mapper/capability.json +++ b/capabilities/pattern-mapper/capability.json @@ -1,7 +1,7 @@ { "id": "pattern-mapper", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 7861e6e4b..4bd45b0ca 100644 --- a/capabilities/profile-pipeline/capability.json +++ b/capabilities/profile-pipeline/capability.json @@ -1,7 +1,7 @@ { "id": "profile-pipeline", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 dd0fbaabb..9727ffb89 100644 --- a/capabilities/qwen/capability.json +++ b/capabilities/qwen/capability.json @@ -1,7 +1,7 @@ { "id": "qwen", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 f1c3909da..17a168295 100644 --- a/capabilities/research/capability.json +++ b/capabilities/research/capability.json @@ -1,7 +1,7 @@ { "id": "research", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 0a3a638b8..650edc568 100644 --- a/capabilities/schema-gate/capability.json +++ b/capabilities/schema-gate/capability.json @@ -1,7 +1,7 @@ { "id": "schema-gate", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 2d17a5a06..7a100f506 100644 --- a/capabilities/security/capability.json +++ b/capabilities/security/capability.json @@ -1,7 +1,7 @@ { "id": "security", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 4e6c15b22..645f31300 100644 --- a/capabilities/tdd/capability.json +++ b/capabilities/tdd/capability.json @@ -1,7 +1,7 @@ { "id": "tdd", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 4015c7d5f..3cd9f043d 100644 --- a/capabilities/trae/capability.json +++ b/capabilities/trae/capability.json @@ -1,7 +1,7 @@ { "id": "trae", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 75dc81922..bf90dd8c3 100644 --- a/capabilities/ui/capability.json +++ b/capabilities/ui/capability.json @@ -1,7 +1,7 @@ { "id": "ui", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 1c95f874c..3b8d0e86a 100644 --- a/capabilities/windsurf/capability.json +++ b/capabilities/windsurf/capability.json @@ -1,7 +1,7 @@ { "id": "windsurf", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Windsurf", "description": "Windsurf (Codeium) — nested under ~/.codeium/windsurf; skills-only artifact layout; no hook surface; no hook events; tier-2 support.", "tier": "core", diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 550dceff3..a21244574 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -260,6 +260,7 @@ All workflow toggles follow the **absent = enabled** pattern. If a key is missin | `workflow.plan_chunked` | boolean | `false` | Enable chunked planning mode. When `true` (or when `--chunked` flag is passed to `/gsd-plan-phase`), the orchestrator splits the single long-lived planner Task into a short outline Task followed by N short per-plan Tasks (~3-5 min each). Each plan is committed individually for crash resilience. If a Task hangs and the terminal is force-killed, rerunning with `--chunked` resumes from the last completed plan. Particularly useful on Windows where long-lived Tasks may hang on stdio. Added in v1.38 | | `workflow.code_review_command` | string | (none) | Shell command for external code review integration in `/gsd-ship`. Receives changed file paths via stdin. Non-zero exit blocks the ship workflow. Added in v1.36 | | `workflow.tdd_mode` | boolean | `false` | Enable TDD pipeline as a first-class execution mode. When `true`, the planner aggressively applies `type: tdd` to eligible tasks (business logic, APIs, validations, algorithms) and the executor enforces RED/GREEN/REFACTOR gate sequence. An end-of-phase collaborative review checkpoint verifies gate compliance. Added in v1.36 | +| `workflow.mvp_mode` | boolean | `false` | Persist the MVP-mode flag in config so every phase defaults to MVP framing without requiring `--mvp` on the CLI. Resolved via the precedence chain: `--mvp` CLI flag → ROADMAP.md `**Mode:** mvp` field → this config value → `false`. When `true`, the planner, executor, verifier, and discovery surfaces treat the phase as an MVP vertical slice (UI → API → DB) of one user-visible capability instead of a horizontal layer. | | `workflow.human_verify_mode` | string | `'end-of-phase'` | Controls human verification checkpoints. `'end-of-phase'` (default since #3309) suppresses `checkpoint:human-verify` tasks and embeds checks into `` blocks for end-of-phase review. `'mid-flight'` restores blocking checkpoint tasks. `checkpoint:decision` and `checkpoint:human-action` are unaffected. See [Checkpoints Reference](../gsd-core/references/checkpoints.md#checkpoint_types). | | `workflow.cross_ai_execution` | boolean | `false` | Delegate phase execution to an external AI CLI instead of spawning local executor agents. Useful for leveraging a different model's strengths for specific phases. Added in v1.36 | | `workflow.cross_ai_command` | string | (none) | Shell command template for cross-AI execution. Receives the phase prompt via stdin. Must produce SUMMARY.md-compatible output. Required when `cross_ai_execution` is `true`. Added in v1.36 | diff --git a/gemini-extension.json b/gemini-extension.json index e6fe4c760..fc904a07e 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "gsd-core", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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 e17c237b0..249397540 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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; nested skill layout; tier-1 support.", "tier": "core", @@ -123,7 +123,7 @@ const capabilities = { "audit": { "id": "audit", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.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.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Drift detection gates", "description": "Post-execution drift detection gates that run after each wave completes. Provides two gates 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).", "tier": "full", @@ -707,7 +707,7 @@ const capabilities = { "gap-analysis": { "id": "gap-analysis", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -748,7 +748,7 @@ const capabilities = { "gemini": { "id": "gemini", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -805,7 +805,7 @@ const capabilities = { "graphify": { "id": "graphify", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -846,7 +846,7 @@ const capabilities = { "hermes": { "id": "hermes", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -899,7 +899,7 @@ const capabilities = { "intel": { "id": "intel", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -951,7 +951,7 @@ const capabilities = { "kilo": { "id": "kilo", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1026,7 +1026,7 @@ const capabilities = { "kimi": { "id": "kimi", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1082,7 +1082,7 @@ const capabilities = { "mempalace": { "id": "mempalace", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1256,7 +1256,7 @@ const capabilities = { "nyquist": { "id": "nyquist", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Nyquist validation", "description": "Validation coverage audit that maps executed work back to tests and manual-only evidence.", "tier": "full", @@ -1306,7 +1306,7 @@ const capabilities = { "opencode": { "id": "opencode", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1376,7 +1376,7 @@ const capabilities = { "pattern-mapper": { "id": "pattern-mapper", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Pattern mapping", "description": "Optional codebase-pattern mapping before planning; owns the pattern mapper agent and workflow.pattern_mapper activation key.", "tier": "full", @@ -1430,7 +1430,7 @@ const capabilities = { "profile-pipeline": { "id": "profile-pipeline", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1507,7 +1507,7 @@ const capabilities = { "qwen": { "id": "qwen", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1564,7 +1564,7 @@ const capabilities = { "research": { "id": "research", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Phase research", "description": "Optional phase research before planning; owns the phase researcher agent and workflow.research activation key.", "tier": "standard", @@ -1616,7 +1616,7 @@ const capabilities = { "schema-gate": { "id": "schema-gate", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1662,7 +1662,7 @@ const capabilities = { "security": { "id": "security", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Security enforcement", "description": "Threat mitigation verification and ship-time security blocking for phases with security enforcement enabled.", "tier": "full", @@ -1761,7 +1761,7 @@ const capabilities = { "tdd": { "id": "tdd", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -1814,7 +1814,7 @@ const capabilities = { "trae": { "id": "trae", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", @@ -1866,7 +1866,7 @@ const capabilities = { "ui": { "id": "ui", "role": "feature", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "UI design contracts", "description": "UI-SPEC design contract + retrospective UI audit for frontend phases.", "tier": "full", @@ -1961,7 +1961,7 @@ const capabilities = { "windsurf": { "id": "windsurf", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Windsurf", "description": "Windsurf (Codeium) — nested under ~/.codeium/windsurf; skills-only artifact layout; no hook surface; no hook events; tier-2 support.", "tier": "core", @@ -2721,7 +2721,7 @@ const runtimes = { "antigravity": { "id": "antigravity", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Antigravity", "description": "Google Antigravity IDE — nested under ~/.gemini/antigravity; probed across 1.x and 2.x layouts; Gemini hook event dialect; nested skill layout; tier-1 support.", "tier": "core", @@ -2781,7 +2781,7 @@ const runtimes = { "augment": { "id": "augment", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -2850,7 +2850,7 @@ const runtimes = { "claude": { "id": "claude", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -2916,7 +2916,7 @@ const runtimes = { "cline": { "id": "cline", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -2959,7 +2959,7 @@ const runtimes = { "codebuddy": { "id": "codebuddy", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "CodeBuddy", "description": "CodeBuddy (Tencent) — converted commands + skills artifact layout; settings-json hook surface; Claude hook event dialect; tier-2 support.", "tier": "core", @@ -3028,7 +3028,7 @@ const runtimes = { "codex": { "id": "codex", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3081,7 +3081,7 @@ const runtimes = { "copilot": { "id": "copilot", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3134,7 +3134,7 @@ const runtimes = { "cursor": { "id": "cursor", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3203,7 +3203,7 @@ const runtimes = { "gemini": { "id": "gemini", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3260,7 +3260,7 @@ const runtimes = { "hermes": { "id": "hermes", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3313,7 +3313,7 @@ const runtimes = { "kilo": { "id": "kilo", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3388,7 +3388,7 @@ const runtimes = { "kimi": { "id": "kimi", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3444,7 +3444,7 @@ const runtimes = { "opencode": { "id": "opencode", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3514,7 +3514,7 @@ const runtimes = { "qwen": { "id": "qwen", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", @@ -3571,7 +3571,7 @@ const runtimes = { "trae": { "id": "trae", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Trae IDE", "description": "Trae IDE — nested-skill artifact layout; no hook surface (profile-marker-only config); tier-2 support.", "tier": "core", @@ -3623,7 +3623,7 @@ const runtimes = { "windsurf": { "id": "windsurf", "role": "runtime", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "title": "Windsurf", "description": "Windsurf (Codeium) — nested under ~/.codeium/windsurf; skills-only artifact layout; no hook surface; no hook events; tier-2 support.", "tier": "core", diff --git a/gsd-core/bin/shared/config-schema.manifest.json b/gsd-core/bin/shared/config-schema.manifest.json index a768fa069..fdd268892 100644 --- a/gsd-core/bin/shared/config-schema.manifest.json +++ b/gsd-core/bin/shared/config-schema.manifest.json @@ -55,6 +55,7 @@ "workflow.subagent_timeout", "workflow.test_command", "workflow.build_command", + "workflow.mvp_mode", "executor.stall_detect_interval_minutes", "executor.stall_threshold_minutes", "workflow.inline_plan_threshold", diff --git a/gsd-core/references/planning-config.md b/gsd-core/references/planning-config.md index 997855b3a..6b35fc763 100644 --- a/gsd-core/references/planning-config.md +++ b/gsd-core/references/planning-config.md @@ -266,6 +266,9 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research": | `workflow.subagent_timeout` | number | `300000` | Any positive integer (ms) | Timeout for parallel subagent tasks (default: 5 minutes) | | `workflow.test_command` | string\|null | `null` | Any shell command | Regression/test gate command run by verify-phase, execute-phase, audit-fix, and post-merge-gate. Unset → GSD auto-detects (Makefile / package.json / Cargo.toml / go.mod / pyproject.toml). | | `workflow.build_command` | string\|null | `null` | Any shell command | Build gate command run by the post-merge gate. Unset → build step auto-detected/skipped. | +| `workflow.mvp_mode` | boolean | `false` | `true`, `false` | Persist the MVP-mode flag in config so every phase defaults to MVP framing without requiring `--mvp` on the CLI. Resolved via the chain: `--mvp` CLI flag → ROADMAP.md `**Mode:** mvp` field → this config value → `false`. When `true`, the planner, executor, verifier, and discovery surfaces (progress, stats, graphify) all treat the phase as an MVP vertical slice (UI → API → DB) of one user-visible capability. | +| `workflow.plan_chunked` | boolean | `false` | `true`, `false` | Enable chunked planning mode. When `true`, the plan-phase orchestrator splits the single long-lived planner Task into a short outline Task followed by N short per-plan Tasks (~3–5 min each). Each plan is committed individually for crash resilience. Particularly useful on Windows where long-lived Tasks may hang on stdio. Also activated by the `--chunked` flag. | +| `workflow.code_review_command` | string\|null | `null` | Any shell command | External code-review command integrated into `/gsd:ship`. The diff is piped to the command via stdin; the command must output JSON with a `verdict` field (`"APPROVED"` or `"REVISE"`). Non-zero exit or `"REVISE"` verdict blocks the ship workflow. When unset, the built-in review flow runs. Example: `my-review-tool --review`. | | `workflow.inline_plan_threshold` | number | `2` | `0`–`10` | Plans with ≤N tasks execute inline instead of spawning a subagent | | `workflow.code_review` | boolean | `true` | `true`, `false` | Enable built-in code review step in the ship workflow | | `workflow.code_review_depth` | string | `"standard"` | `"light"`, `"standard"`, `"deep"` | Depth level for code review analysis in the ship workflow | diff --git a/package-lock.json b/package-lock.json index 368dc982e..5a88720d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@opengsd/gsd-core", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@opengsd/gsd-core", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.1", "license": "MIT", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.84", diff --git a/package.json b/package.json index 59be7afb6..27614385a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@opengsd/gsd-core", - "version": "1.5.1-dev.0", + "version": "1.6.0-rc.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", diff --git a/src/verify.cts b/src/verify.cts index fa222088e..c5e2c4bb3 100644 --- a/src/verify.cts +++ b/src/verify.cts @@ -2210,8 +2210,18 @@ function cmdVerifyCodebaseDrift(cwd: string, raw: boolean): void { else if (status === 'D') deleted.push(file); } - const config = loadConfig(cwd); - const wf = config?.workflow as Record | undefined; + // loadConfig() returns a flattened object — there is no nested `workflow` + // key. Read the raw config.json directly to access workflow-scoped keys, + // matching the pattern used in check-command-router.cts:readWorkflowConfig. + let wf: Record | undefined; + try { + const rawCfg = JSON.parse( + fs.readFileSync(path.join(planningDir(cwd), 'config.json'), 'utf-8'), + ) as Record; + wf = rawCfg['workflow'] as Record | undefined; + } catch { + wf = undefined; + } const threshold = Number.isInteger(wf?.drift_threshold) && (wf?.drift_threshold as number) >= 1 ? (wf?.drift_threshold as number) diff --git a/tests/drift-detection.test.cjs b/tests/drift-detection.test.cjs index ebdfc52b4..ebb59615d 100644 --- a/tests/drift-detection.test.cjs +++ b/tests/drift-detection.test.cjs @@ -720,3 +720,77 @@ describe('verify codebase-drift CLI', () => { } }); }); + +// ─── Regression #1493 — workflow.drift_action / drift_threshold read from nested config shape ─── +// +// loadConfig() returns a flattened object; config?.workflow was always undefined, +// making drift_action permanently 'warn' and drift_threshold always 3 regardless +// of .planning/config.json contents. Fix reads the raw nested JSON directly. + +describe('verify codebase-drift — workflow config read from nested shape (#1493)', () => { + let tmp; + beforeEach(() => { + tmp = createTempGitProject('gsd-drift-1493-'); + fs.mkdirSync(path.join(tmp, '.planning', 'codebase'), { recursive: true }); + }); + afterEach(() => cleanup(tmp)); + + test('workflow.drift_action=auto-remap in config.json is honored (not always warn) (#1493)', () => { + // Write config with nested workflow shape — the flat loadConfig() path would + // have silently dropped this, leaving action === 'warn'. + fs.writeFileSync( + path.join(tmp, '.planning', 'config.json'), + JSON.stringify({ workflow: { drift_action: 'auto-remap', drift_threshold: 1 } }, null, 2), + ); + + // Map codebase to current HEAD so anything committed next is "new" drift. + const structure = path.join(tmp, '.planning', 'codebase', 'STRUCTURE.md'); + fs.writeFileSync(structure, '# Codebase Structure\n\n- `src/`\n'); + writeMappedCommit(structure, git(tmp, 'rev-parse', 'HEAD'), '2026-04-22'); + git(tmp, 'add', '-A'); + git(tmp, 'commit', '-m', 'map codebase'); + + // Add one structural barrel file — enough to exceed drift_threshold of 1. + const dir = path.join(tmp, 'packages', 'ui', 'src'); + fs.mkdirSync(dir, { recursive: true }); + fs.writeFileSync(path.join(dir, 'index.ts'), 'export {};\n'); + git(tmp, 'add', '-A'); + git(tmp, 'commit', '-m', 'add package barrel'); + + const r = runGsdTools(['verify', 'codebase-drift'], tmp); + assert.strictEqual(r.success, true, r.error); + const data = JSON.parse(r.output); + assert.strictEqual( + data.action, 'auto-remap', + 'workflow.drift_action=auto-remap must flow through from nested config; "warn" means the flat-shape bug is still active', + ); + }); + + test('workflow.drift_threshold in config.json gates triggering (#1493)', () => { + // Threshold of 100 — 1 structural file should not trigger action_required. + fs.writeFileSync( + path.join(tmp, '.planning', 'config.json'), + JSON.stringify({ workflow: { drift_action: 'auto-remap', drift_threshold: 100 } }, null, 2), + ); + + const structure = path.join(tmp, '.planning', 'codebase', 'STRUCTURE.md'); + fs.writeFileSync(structure, '# Codebase Structure\n\n- `src/`\n'); + writeMappedCommit(structure, git(tmp, 'rev-parse', 'HEAD'), '2026-04-22'); + git(tmp, 'add', '-A'); + git(tmp, 'commit', '-m', 'map codebase'); + + const dir = path.join(tmp, 'packages', 'ui', 'src'); + fs.mkdirSync(dir, { recursive: true }); + fs.writeFileSync(path.join(dir, 'index.ts'), 'export {};\n'); + git(tmp, 'add', '-A'); + git(tmp, 'commit', '-m', 'add one package barrel'); + + const r = runGsdTools(['verify', 'codebase-drift'], tmp); + assert.strictEqual(r.success, true, r.error); + const data = JSON.parse(r.output); + assert.strictEqual(data.threshold, 100, + 'workflow.drift_threshold=100 must be read from nested config; 3 means the flat-shape bug is still active'); + assert.strictEqual(data.action_required, false, + '1 structural file must not exceed threshold of 100'); + }); +}); diff --git a/tests/enh-1494-workflow-config-key-docs.test.cjs b/tests/enh-1494-workflow-config-key-docs.test.cjs new file mode 100644 index 000000000..bd782533d --- /dev/null +++ b/tests/enh-1494-workflow-config-key-docs.test.cjs @@ -0,0 +1,118 @@ +'use strict'; + +/** + * Parity assertions for #1494: workflow config keys that are consumed by + * planning-pipeline code must be (a) accepted by VALID_CONFIG_KEYS and + * (b) documented in references/planning-config.md. + * + * Per DEFECT.GENERATIVE-FIX: a shared constant / key-list that spans two + * surfaces requires a parity assertion that fails when the surfaces diverge. + */ + +const { describe, test, before, afterEach } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); + +const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs'); + +const CONFIG_SCHEMA_PATH = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'config-schema.cjs'); +const PLANNING_CONFIG_PATH = path.join(__dirname, '..', 'gsd-core', 'references', 'planning-config.md'); + +describe('VALID_CONFIG_KEYS parity — #1494 orphan-undocumented keys', () => { + const { VALID_CONFIG_KEYS } = require(CONFIG_SCHEMA_PATH); + + test('workflow.mvp_mode is in VALID_CONFIG_KEYS', () => { + assert.ok( + VALID_CONFIG_KEYS.has('workflow.mvp_mode'), + 'workflow.mvp_mode is read by config-loader.cts and plan-phase.md but was missing from VALID_CONFIG_KEYS (#1494)' + ); + }); + + test('workflow.code_review_command is in VALID_CONFIG_KEYS', () => { + assert.ok( + VALID_CONFIG_KEYS.has('workflow.code_review_command'), + 'workflow.code_review_command must be in VALID_CONFIG_KEYS' + ); + }); + + test('workflow.plan_chunked is in VALID_CONFIG_KEYS', () => { + assert.ok( + VALID_CONFIG_KEYS.has('workflow.plan_chunked'), + 'workflow.plan_chunked must be in VALID_CONFIG_KEYS' + ); + }); + + test('workflow.test_command is in VALID_CONFIG_KEYS', () => { + assert.ok( + VALID_CONFIG_KEYS.has('workflow.test_command'), + 'workflow.test_command must be in VALID_CONFIG_KEYS' + ); + }); + + test('workflow.build_command is in VALID_CONFIG_KEYS', () => { + assert.ok( + VALID_CONFIG_KEYS.has('workflow.build_command'), + 'workflow.build_command must be in VALID_CONFIG_KEYS' + ); + }); +}); + +describe('config-set accepts workflow.mvp_mode (#1494)', () => { + let tmpDir; + afterEach(() => { if (tmpDir) cleanup(tmpDir); }); + + test('config-set workflow.mvp_mode true succeeds and stores the value', () => { + tmpDir = createTempProject(); + const result = runGsdTools(['config-set', 'workflow.mvp_mode', 'true'], tmpDir); + assert.ok( + result.success, + `config-set workflow.mvp_mode must succeed; got:\nstdout: ${result.output}\nstderr: ${result.error}` + ); + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.updated, true, 'response must have updated:true'); + assert.strictEqual(parsed.key, 'workflow.mvp_mode', 'response must echo the key'); + }); + + test('config-set workflow.mvp_mode false succeeds', () => { + tmpDir = createTempProject(); + const result = runGsdTools(['config-set', 'workflow.mvp_mode', 'false'], tmpDir); + assert.ok( + result.success, + `config-set workflow.mvp_mode false must succeed; got:\nstdout: ${result.output}\nstderr: ${result.error}` + ); + const parsed = JSON.parse(result.output); + assert.strictEqual(parsed.updated, true); + }); +}); + +// allow-test-rule: source-text-is-the-product — planning-config.md is the deployed reference contract (#1494) +describe('planning-config.md documents #1494 keys', () => { + let content; + before(() => { content = fs.readFileSync(PLANNING_CONFIG_PATH, 'utf-8'); }); + + const KEYS = [ + 'workflow.mvp_mode', + 'workflow.code_review_command', + 'workflow.plan_chunked', + 'workflow.test_command', + 'workflow.build_command', + ]; + + for (const key of KEYS) { + test(`planning-config.md documents \`${key}\``, () => { + assert.ok( + content.includes(`\`${key}\``), + `planning-config.md must document \`${key}\` (#1494)` + ); + }); + + test(`\`${key}\` appears in the Complete Field Reference section`, () => { + const refSection = content.slice(content.indexOf('## Complete Field Reference')); + assert.ok( + refSection.includes(`\`${key}\``), + `planning-config.md Complete Field Reference must include \`${key}\` (#1494)` + ); + }); + } +});