docs(references): extend planning-config.md with complete field reference (#1786)
* docs(references): extend planning-config.md with complete field reference Add a comprehensive field table generated from CONFIG_DEFAULTS and VALID_CONFIG_KEYS covering all config.json fields with types, defaults, allowed values, and descriptions. Includes field interaction notes (auto-detection, threshold triggers) and three copy-pasteable example configurations for common setups. Closes #1741 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(docs): add missing sub_repos and model_overrides to config reference (#1741) - Add sub_repos field to planning-config.md field table - Add model_overrides field to planning-config.md field table - Fix test namespace map to cover both missing fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(docs): add thinking_partner field and plan_checker alias note (#1741) - Add features.thinking_partner to config reference documentation - Document plan_checker as flat-key alias of workflow.plan_check - Move file reads from describe scope into before() hooks - Add test coverage for thinking_partner field Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -214,4 +214,219 @@ Squash merge is recommended — keeps main branch history clean while preserving
|
||||
|
||||
</branching_strategy_behavior>
|
||||
|
||||
<complete_field_reference>
|
||||
|
||||
## Complete Field Reference
|
||||
|
||||
Generated from `CONFIG_DEFAULTS` (core.cjs) and `VALID_CONFIG_KEYS` (config.cjs).
|
||||
|
||||
### Core Fields
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `model_profile` | string | `"balanced"` | `"quality"`, `"balanced"`, `"budget"`, `"inherit"` | Model selection preset for subagents |
|
||||
| `mode` | string | (none) | `"code-first"`, `"plan-first"`, `"hybrid"` | Per-phase workflow mode controlling discuss/plan/execute flow |
|
||||
| `granularity` | string | (none) | `"coarse"`, `"standard"`, `"fine"` | Planning depth for phase plans (migrated from deprecated `depth`) |
|
||||
| `commit_docs` | boolean | `true` | `true`, `false` | Commit .planning/ artifacts to git (auto-false if .planning/ is gitignored) |
|
||||
| `search_gitignored` | boolean | `false` | `true`, `false` | Include gitignored paths in broad rg searches via `--no-ignore` |
|
||||
| `phase_naming` | string | `"sequential"` | `"sequential"`, `"custom"` | Phase numbering: auto-increment or arbitrary string IDs |
|
||||
| `project_code` | string\|null | `null` | Any short string | Prefix for phase dirs (e.g., `"CK"` produces `CK-01-foundation`) |
|
||||
| `response_language` | string\|null | `null` | Any language name | Language for user-facing prompts (e.g., `"Portuguese"`, `"Japanese"`) |
|
||||
| `context_window` | number | `200000` | `200000`, `1000000` | Context window size; set `1000000` for 1M-context models |
|
||||
| `resolve_model_ids` | boolean\|string | `false` | `false`, `true`, `"omit"` | Map model aliases to full Claude IDs; `"omit"` returns empty string |
|
||||
|
||||
### Workflow Fields
|
||||
|
||||
Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research": true }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `workflow.research` | boolean | `true` | `true`, `false` | Run research agent before planning |
|
||||
| `workflow.plan_check` | boolean | `true` | `true`, `false` | Run plan-checker agent to validate plans. _Alias:_ `plan_checker` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.plan_check` is the canonical namespaced form. |
|
||||
| `workflow.verifier` | boolean | `true` | `true`, `false` | Run verifier agent after execution |
|
||||
| `workflow.nyquist_validation` | boolean | `true` | `true`, `false` | Enable Nyquist-inspired validation gates |
|
||||
| `workflow.auto_advance` | boolean | `false` | `true`, `false` | Auto-advance to next phase after completion |
|
||||
| `workflow.node_repair` | boolean | `true` | `true`, `false` | Attempt automatic repair of failed plan nodes |
|
||||
| `workflow.node_repair_budget` | number | `2` | Any positive integer | Max repair retries per failed node |
|
||||
| `workflow.ui_phase` | boolean | `true` | `true`, `false` | Generate UI-SPEC.md for frontend phases |
|
||||
| `workflow.ui_safety_gate` | boolean | `true` | `true`, `false` | Require safety gate approval for UI changes |
|
||||
| `workflow.text_mode` | boolean | `false` | `true`, `false` | Use plain-text numbered lists instead of AskUserQuestion menus |
|
||||
| `workflow.research_before_questions` | boolean | `false` | `true`, `false` | Run research before interactive questions in discuss phase |
|
||||
| `workflow.discuss_mode` | string | `"discuss"` | `"discuss"`, `"auto"`, `"analyze"` | Default mode for discuss-phase agent |
|
||||
| `workflow.skip_discuss` | boolean | `false` | `true`, `false` | Skip discuss phase entirely |
|
||||
| `workflow.use_worktrees` | boolean | `true` | `true`, `false` | Run executor agents in isolated git worktrees |
|
||||
| `workflow.subagent_timeout` | number | `300000` | Any positive integer (ms) | Timeout for parallel subagent tasks (default: 5 minutes) |
|
||||
| `workflow._auto_chain_active` | boolean | `false` | `true`, `false` | Internal: tracks whether autonomous chaining is active |
|
||||
|
||||
### Git Fields
|
||||
|
||||
Set via `git.*` namespace (e.g., `"git": { "branching_strategy": "phase" }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `git.branching_strategy` | string | `"none"` | `"none"`, `"phase"`, `"milestone"` | Git branching approach for phase/milestone isolation |
|
||||
| `git.base_branch` | string\|null | `null` (auto-detect) | Any branch name | Target branch for PRs and merges; auto-detects from `origin/HEAD` when `null` |
|
||||
| `git.phase_branch_template` | string | `"gsd/phase-{phase}-{slug}"` | Template with `{phase}`, `{slug}` | Branch naming template for `phase` strategy |
|
||||
| `git.milestone_branch_template` | string | `"gsd/{milestone}-{slug}"` | Template with `{milestone}`, `{slug}` | Branch naming template for `milestone` strategy |
|
||||
| `git.quick_branch_template` | string\|null | `null` | Template with `{slug}` | Optional branch template for quick-task runs |
|
||||
|
||||
### Search & API Fields
|
||||
|
||||
These toggle external search integrations. Auto-detected at project creation when API keys are present.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `brave_search` | boolean | `false` | `true`, `false` | Enable Brave web search for research agent (requires `BRAVE_API_KEY`) |
|
||||
| `firecrawl` | boolean | `false` | `true`, `false` | Enable Firecrawl page scraping (requires `FIRECRAWL_API_KEY`) |
|
||||
| `exa_search` | boolean | `false` | `true`, `false` | Enable Exa semantic search (requires `EXA_API_KEY`) |
|
||||
|
||||
### Features Fields
|
||||
|
||||
Set via `features.*` namespace (e.g., `"features": { "thinking_partner": true }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `features.thinking_partner` | boolean | `false` | `true`, `false` | Enable conditional extended thinking at workflow decision points (used by discuss-phase and plan-phase for architectural tradeoff analysis) |
|
||||
|
||||
### Hook Fields
|
||||
|
||||
Set via `hooks.*` namespace (e.g., `"hooks": { "context_warnings": true }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `hooks.context_warnings` | boolean | `true` | `true`, `false` | Show warnings when context budget is exceeded |
|
||||
|
||||
### Manager Fields
|
||||
|
||||
Set via `manager.*` namespace (e.g., `"manager": { "flags": { "discuss": "--auto" } }`).
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `manager.flags.discuss` | string | `""` | Any CLI flags string | Flags passed to `/gsd-discuss-phase` from manager (e.g., `"--auto --analyze"`) |
|
||||
| `manager.flags.plan` | string | `""` | Any CLI flags string | Flags passed to plan workflow from manager |
|
||||
| `manager.flags.execute` | string | `""` | Any CLI flags string | Flags passed to execute workflow from manager |
|
||||
|
||||
### Advanced Fields
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `parallelization` | boolean\|object | `true` | `true`, `false`, `{ "enabled": true }` | Enable parallel wave execution; object form allows additional sub-keys |
|
||||
| `model_overrides` | object\|null | `null` | `{ "<agent-type>": "<model-id>" }` | Override model selection per agent type |
|
||||
| `agent_skills` | object | `{}` | `{ "<agent-type>": "<skill-set>" }` | Assign skill sets to specific agent types |
|
||||
| `sub_repos` | array | `[]` | Array of relative path strings | Child directories with independent `.git` repos (auto-detected) |
|
||||
|
||||
### Planning Fields
|
||||
|
||||
These can be set at top level or nested under `planning.*` (e.g., `"planning": { "commit_docs": false }`). Both forms are equivalent; top-level takes precedence if both exist.
|
||||
|
||||
| Key | Type | Default | Allowed Values | Description |
|
||||
|-----|------|---------|----------------|-------------|
|
||||
| `planning.commit_docs` | boolean | `true` | `true`, `false` | Alias for top-level `commit_docs` |
|
||||
| `planning.search_gitignored` | boolean | `false` | `true`, `false` | Alias for top-level `search_gitignored` |
|
||||
|
||||
---
|
||||
|
||||
## Field Interactions
|
||||
|
||||
Several config fields affect each other or trigger special behavior:
|
||||
|
||||
1. **`commit_docs` auto-detection** -- When no explicit value is set in config.json and `.planning/` is in `.gitignore`, `commit_docs` automatically resolves to `false`. An explicit `true` or `false` in config always overrides auto-detection.
|
||||
|
||||
2. **`branching_strategy` controls branch templates** -- The `phase_branch_template` and `milestone_branch_template` fields are only used when `branching_strategy` is set to `"phase"` or `"milestone"` respectively. When `branching_strategy` is `"none"`, all template fields are ignored.
|
||||
|
||||
3. **`context_window` threshold triggers** -- When `context_window >= 500000`, workflows enable adaptive context enrichment: full-body reads of prior phase SUMMARYs, cross-phase context injection in plan-phase, and deeper read depth for anti-pattern references. Below 500000, only frontmatter and summaries are read.
|
||||
|
||||
4. **`parallelization` polymorphism** -- Accepts both a simple boolean and an object with an `enabled` field. `loadConfig()` normalizes either form to a boolean. `{ "enabled": true }` is equivalent to `true`.
|
||||
|
||||
5. **Search API keys and flags** -- `brave_search`, `firecrawl`, and `exa_search` are auto-set to `true` during project creation if the corresponding API key is detected (environment variable or `~/.gsd/<name>_api_key` file). Setting them to `true` without the API key has no effect.
|
||||
|
||||
6. **`planning.*` and top-level equivalence** -- `planning.commit_docs` and `commit_docs` are equivalent; `planning.search_gitignored` and `search_gitignored` are equivalent. If both are set, the top-level value takes precedence.
|
||||
|
||||
7. **`depth` to `granularity` migration** -- The deprecated `depth` key (`quick`/`standard`/`comprehensive`) is automatically migrated to `granularity` (`coarse`/`standard`/`fine`) on config load and persisted back to disk.
|
||||
|
||||
8. **`sub_repos` auto-sync** -- On every config load, GSD scans for child directories with `.git` and updates the `sub_repos` array if the filesystem has changed. Legacy `multiRepo: true` is automatically migrated to a detected `sub_repos` array.
|
||||
|
||||
---
|
||||
|
||||
## Example Configurations
|
||||
|
||||
### Minimal -- Solo Developer
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "balanced",
|
||||
"commit_docs": true,
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"use_worktrees": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Team Project with Branching
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "quality",
|
||||
"commit_docs": true,
|
||||
"project_code": "APP",
|
||||
"git": {
|
||||
"branching_strategy": "phase",
|
||||
"base_branch": "develop",
|
||||
"phase_branch_template": "gsd/phase-{phase}-{slug}"
|
||||
},
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"nyquist_validation": true,
|
||||
"use_worktrees": true,
|
||||
"discuss_mode": "discuss"
|
||||
},
|
||||
"manager": {
|
||||
"flags": {
|
||||
"discuss": "",
|
||||
"plan": "",
|
||||
"execute": ""
|
||||
}
|
||||
},
|
||||
"response_language": "English"
|
||||
}
|
||||
```
|
||||
|
||||
### Large Codebase -- 1M Context with Extended Timeouts
|
||||
|
||||
```json
|
||||
{
|
||||
"model_profile": "quality",
|
||||
"context_window": 1000000,
|
||||
"commit_docs": true,
|
||||
"project_code": "MEGA",
|
||||
"phase_naming": "sequential",
|
||||
"git": {
|
||||
"branching_strategy": "milestone",
|
||||
"milestone_branch_template": "gsd/{milestone}-{slug}"
|
||||
},
|
||||
"workflow": {
|
||||
"research": true,
|
||||
"plan_check": true,
|
||||
"verifier": true,
|
||||
"nyquist_validation": true,
|
||||
"subagent_timeout": 600000,
|
||||
"use_worktrees": true,
|
||||
"node_repair": true,
|
||||
"node_repair_budget": 3,
|
||||
"auto_advance": true
|
||||
},
|
||||
"brave_search": true,
|
||||
"hooks": {
|
||||
"context_warnings": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</complete_field_reference>
|
||||
|
||||
</planning_config>
|
||||
|
||||
179
tests/config-field-docs.test.cjs
Normal file
179
tests/config-field-docs.test.cjs
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* Verify planning-config.md documents all config fields from source code.
|
||||
*/
|
||||
|
||||
const { describe, test, before } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const REFERENCE_PATH = path.join(__dirname, '..', 'get-shit-done', 'references', 'planning-config.md');
|
||||
const CORE_PATH = path.join(__dirname, '..', 'get-shit-done', 'bin', 'lib', 'core.cjs');
|
||||
|
||||
describe('config-field-docs', () => {
|
||||
let content;
|
||||
|
||||
before(() => {
|
||||
content = fs.readFileSync(REFERENCE_PATH, 'utf-8');
|
||||
});
|
||||
|
||||
test('contains Complete Field Reference section', () => {
|
||||
assert.ok(
|
||||
content.includes('## Complete Field Reference'),
|
||||
'planning-config.md must contain a "Complete Field Reference" heading'
|
||||
);
|
||||
});
|
||||
|
||||
test('documents at least 15 config fields in tables', () => {
|
||||
// Count table rows that start with | `<key>` (field rows, not header/separator)
|
||||
const fieldRows = content.match(/^\| `[a-z_][a-z0-9_.]*` \|/gm);
|
||||
assert.ok(fieldRows, 'Expected markdown table rows with backtick-quoted keys');
|
||||
assert.ok(
|
||||
fieldRows.length >= 15,
|
||||
`Expected at least 15 documented fields, found ${fieldRows.length}`
|
||||
);
|
||||
});
|
||||
|
||||
test('contains example configurations', () => {
|
||||
assert.ok(
|
||||
content.includes('## Example Configurations'),
|
||||
'planning-config.md must contain an "Example Configurations" section'
|
||||
);
|
||||
// Verify at least one JSON code block with a model_profile key
|
||||
assert.ok(
|
||||
content.includes('"model_profile"'),
|
||||
'Example configurations must include model_profile'
|
||||
);
|
||||
});
|
||||
|
||||
test('contains field interactions section', () => {
|
||||
assert.ok(
|
||||
content.includes('## Field Interactions'),
|
||||
'planning-config.md must contain a "Field Interactions" section'
|
||||
);
|
||||
});
|
||||
|
||||
test('every CONFIG_DEFAULTS key appears in the doc', () => {
|
||||
// Extract CONFIG_DEFAULTS keys from core.cjs source
|
||||
const coreSource = fs.readFileSync(CORE_PATH, 'utf-8');
|
||||
const defaultsMatch = coreSource.match(
|
||||
/const CONFIG_DEFAULTS\s*=\s*\{([\s\S]*?)\n\};/
|
||||
);
|
||||
assert.ok(defaultsMatch, 'Could not find CONFIG_DEFAULTS in core.cjs');
|
||||
|
||||
const body = defaultsMatch[1];
|
||||
// Match property keys (word characters before the colon)
|
||||
const keys = [...body.matchAll(/^\s*(\w+)\s*:/gm)].map(m => m[1]);
|
||||
assert.ok(keys.length > 0, 'Could not extract any keys from CONFIG_DEFAULTS');
|
||||
|
||||
// CONFIG_DEFAULTS uses flat keys; the doc may use namespaced equivalents.
|
||||
// Map flat keys to the namespace forms used in config.json and the doc.
|
||||
const NAMESPACE_MAP = {
|
||||
research: 'workflow.research',
|
||||
plan_checker: 'workflow.plan_check',
|
||||
verifier: 'workflow.verifier',
|
||||
nyquist_validation: 'workflow.nyquist_validation',
|
||||
text_mode: 'workflow.text_mode',
|
||||
subagent_timeout: 'workflow.subagent_timeout',
|
||||
branching_strategy: 'git.branching_strategy',
|
||||
phase_branch_template: 'git.phase_branch_template',
|
||||
milestone_branch_template: 'git.milestone_branch_template',
|
||||
quick_branch_template: 'git.quick_branch_template',
|
||||
};
|
||||
|
||||
const missing = keys.filter(k => {
|
||||
// Check both bare key and namespaced form
|
||||
if (content.includes(`\`${k}\``)) return false;
|
||||
const ns = NAMESPACE_MAP[k];
|
||||
if (ns && content.includes(`\`${ns}\``)) return false;
|
||||
return true;
|
||||
});
|
||||
assert.deepStrictEqual(
|
||||
missing,
|
||||
[],
|
||||
`CONFIG_DEFAULTS keys missing from planning-config.md: ${missing.join(', ')}`
|
||||
);
|
||||
});
|
||||
|
||||
test('documents workflow namespace fields', () => {
|
||||
const workflowFields = [
|
||||
'workflow.research',
|
||||
'workflow.plan_check',
|
||||
'workflow.verifier',
|
||||
'workflow.nyquist_validation',
|
||||
'workflow.use_worktrees',
|
||||
'workflow.subagent_timeout',
|
||||
'workflow.text_mode',
|
||||
];
|
||||
const missing = workflowFields.filter(f => !content.includes(`\`${f}\``));
|
||||
assert.deepStrictEqual(
|
||||
missing,
|
||||
[],
|
||||
`Workflow fields missing from planning-config.md: ${missing.join(', ')}`
|
||||
);
|
||||
});
|
||||
|
||||
test('documents git namespace fields', () => {
|
||||
const gitFields = [
|
||||
'git.branching_strategy',
|
||||
'git.base_branch',
|
||||
'git.phase_branch_template',
|
||||
'git.milestone_branch_template',
|
||||
];
|
||||
const missing = gitFields.filter(f => !content.includes(`\`${f}\``));
|
||||
assert.deepStrictEqual(
|
||||
missing,
|
||||
[],
|
||||
`Git fields missing from planning-config.md: ${missing.join(', ')}`
|
||||
);
|
||||
});
|
||||
|
||||
test('documents KNOWN_TOP_LEVEL internal fields not in CONFIG_DEFAULTS', () => {
|
||||
// These fields are in KNOWN_TOP_LEVEL (core.cjs) and read by loadConfig()
|
||||
// but not in CONFIG_DEFAULTS, so the CONFIG_DEFAULTS test doesn't cover them.
|
||||
const internalFields = [
|
||||
'model_overrides',
|
||||
'agent_skills',
|
||||
];
|
||||
const missing = internalFields.filter(f => !content.includes(`\`${f}\``));
|
||||
assert.deepStrictEqual(
|
||||
missing,
|
||||
[],
|
||||
`KNOWN_TOP_LEVEL internal fields missing from planning-config.md: ${missing.join(', ')}`
|
||||
);
|
||||
});
|
||||
|
||||
test('documents sub_repos field (CONFIG_DEFAULTS, no namespace form)', () => {
|
||||
// sub_repos is in CONFIG_DEFAULTS but has no NAMESPACE_MAP entry
|
||||
// (it uses a planning.sub_repos nested lookup but is documented as a
|
||||
// top-level field). Verify it explicitly since the NAMESPACE_MAP path
|
||||
// would silently skip it.
|
||||
assert.ok(
|
||||
content.includes('`sub_repos`'),
|
||||
'planning-config.md must document the sub_repos field'
|
||||
);
|
||||
});
|
||||
|
||||
test('documents features.thinking_partner field', () => {
|
||||
// features.thinking_partner is in VALID_CONFIG_KEYS (config.cjs) and
|
||||
// used by discuss-phase.md and plan-phase.md for conditional extended
|
||||
// thinking at workflow decision points.
|
||||
assert.ok(
|
||||
content.includes('`features.thinking_partner`'),
|
||||
'planning-config.md must document the features.thinking_partner field'
|
||||
);
|
||||
});
|
||||
|
||||
test('documents plan_checker alias for workflow.plan_check', () => {
|
||||
// plan_checker is the flat-key form in CONFIG_DEFAULTS; workflow.plan_check
|
||||
// is the canonical namespaced form. The doc should mention the alias.
|
||||
assert.ok(
|
||||
content.includes('`workflow.plan_check`'),
|
||||
'planning-config.md must document workflow.plan_check'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('plan_checker'),
|
||||
'planning-config.md must mention the plan_checker flat-key alias'
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user