feat(#1494): add workflow.mvp_mode to VALID_CONFIG_KEYS; document code_review_command and plan_chunked in planning-config.md (#1500)

* feat(#1494): add workflow.mvp_mode to VALID_CONFIG_KEYS; document code_review_command, plan_chunked, mvp_mode in planning-config.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: backfill PR number 1500 in changeset

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-20 15:32:07 -04:00
committed by GitHub
parent d7da068dd7
commit c330f70f65
5 changed files with 128 additions and 0 deletions

View File

@@ -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)

View File

@@ -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 `<verify><human-check>` 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 |

View File

@@ -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",

View File

@@ -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 |

View File

@@ -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)`
);
});
}
});