Files
msd-core/get-shit-done/workflows/settings-advanced.md
Tom Boucher b1a670e662 fix(#2697): replace retired /gsd: prefix with /gsd- in all user-facing text (#2699)
All workflow, command, reference, template, and tool-output files that
surfaced /gsd:<cmd> as a user-typed slash command have been updated to
use /gsd-<cmd>, matching the Claude Code skill directory name.

Closes #2697

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 10:59:33 -04:00

436 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<purpose>
Interactive configuration of GSD power-user knobs — plan bounce, node repair, subagent timeouts,
inline plan threshold, cross-AI execution, base branch, branch templates, response language,
context window, gitignored search, and graphify build timeout.
This is a companion to `/gsd-settings` — the common-case prompt there covers model profile,
research/plan_check/verifier toggles, branching strategy, UI/AI phase gates, and worktree
isolation. This advanced command covers everything else that is user-settable, grouped into
six sections so each prompt batch stays cognitively scoped. Every answer pre-selects the
current value; numeric-input answers that are non-numeric are rejected and re-prompted.
</purpose>
<required_reading>
Read all files referenced by the invoking prompt's execution_context before starting.
</required_reading>
<process>
<step name="ensure_and_load_config">
Ensure config exists and resolve the workstream-aware config path (mirrors `settings.md`):
```bash
gsd-sdk query config-ensure-section
if [[ -z "${GSD_CONFIG_PATH:-}" ]]; then
if [[ -f .planning/active-workstream ]]; then
WS=$(tr -d '\n\r' < .planning/active-workstream)
GSD_CONFIG_PATH=".planning/workstreams/${WS}/config.json"
else
GSD_CONFIG_PATH=".planning/config.json"
fi
fi
```
All subsequent reads and writes go through `$GSD_CONFIG_PATH`. Never hardcode
`.planning/config.json` — workstream installs must route to their own config file.
</step>
<step name="read_current">
```bash
cat "$GSD_CONFIG_PATH"
```
Parse the following current values. If a key is absent, fall back to the documented default
shown in parentheses:
Planning Tuning:
- `workflow.plan_bounce` (default: `false`)
- `workflow.plan_bounce_passes` (default: `2`)
- `workflow.plan_bounce_script` (default: `null`)
- `workflow.subagent_timeout` (default: `600`)
- `workflow.inline_plan_threshold` (default: `3`)
Execution Tuning:
- `workflow.node_repair` (default: `true`)
- `workflow.node_repair_budget` (default: `2`)
- `workflow.auto_prune_state` (default: `false`)
Discussion Tuning:
- `workflow.max_discuss_passes` (default: `3`)
Cross-AI Execution:
- `workflow.cross_ai_execution` (default: `false`)
- `workflow.cross_ai_command` (default: `null`)
- `workflow.cross_ai_timeout` (default: `300`)
Git Customization:
- `git.base_branch` (default: `main`)
- `git.phase_branch_template` (default: `gsd/phase-{phase}-{slug}`)
- `git.milestone_branch_template` (default: `gsd/{milestone}-{slug}`)
Runtime / Output:
- `response_language` (default: `null`)
- `context_window` (default: `200000`)
- `search_gitignored` (default: `false`)
- `graphify.build_timeout` (default: `300`)
Each field's **current value is pre-selected** in the prompt rendering below. When the
current value is absent from the config, render the documented default as the pre-selected
option so the user sees what the effective value is.
</step>
<step name="present_settings">
**Text mode (`workflow.text_mode: true` or `--text` flag):** Set `TEXT_MODE=true` if `--text` is
in `$ARGUMENTS` OR `text_mode` is true in config. When `TEXT_MODE=true`, replace every
`AskUserQuestion` call below with a plain-text numbered list and ask the user to type the
choice number or free-text value.
**Numeric-input validation.** For any numeric field (`*_passes`, `*_budget`, `*_timeout`,
`*_threshold`, `context_window`, `graphify.build_timeout`), if the user types a value that
is not a non-negative integer, the workflow MUST reject it, state which value was invalid,
and re-prompt that single field. The minimum accepted value is field-specific and is stated
in each field's prompt below — `workflow.plan_bounce_passes` and `workflow.max_discuss_passes`
require `>= 1`; all other numeric fields accept `>= 0`. An empty input means "keep current"
— the existing value is retained. Non-numeric input is never silently coerced.
**Free-text validation.** For branch template fields (`git.phase_branch_template`,
`git.milestone_branch_template`), if the user supplies a non-default value, it MUST be
non-empty and SHOULD contain at least one `{placeholder}`. A template missing placeholders
is rejected with a message explaining the available variables (`{phase}`, `{slug}`,
`{milestone}`) and re-prompted. An empty input means "keep current."
**Null-allowed fields.** For `response_language`, `workflow.plan_bounce_script`,
`workflow.cross_ai_command`: an empty input clears the field (`null`). A non-empty input is
stored verbatim as a string.
---
### Section 1 — Planning Tuning
```text
AskUserQuestion([
{
question: "Run external plan-bounce validator against generated PLAN.md? (current: <value or false>)",
header: "Plan Bounce",
multiSelect: false,
options: [
{ label: "No (default: false)", description: "Skip external plan validation." },
{ label: "Yes", description: "Pipe each PLAN.md through `plan_bounce_script` and block on non-zero exit." }
]
},
{
question: "How many plan-bounce passes? (current: <value or 2>)",
header: "Bounce Passes",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave the existing value unchanged." },
{ label: "Enter number", description: "Type an integer >= 1. Non-numeric input is rejected and re-prompted. Default: 2" }
]
},
{
question: "Path to plan-bounce validation script? (current: <value or null>)",
header: "Bounce Script",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave existing path unchanged." },
{ label: "Clear (null)", description: "Unset the script path." },
{ label: "Enter path", description: "Type an absolute or repo-relative path. Receives PLAN.md path as first argument." }
]
},
{
question: "Subagent timeout (seconds)? (current: <value or 600>)",
header: "Subagent Timeout",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave timeout unchanged." },
{ label: "Enter seconds", description: "Integer number of seconds. Non-numeric rejected. Default: 600" }
]
},
{
question: "Inline plan threshold — tasks allowed inline before splitting to PLAN.md? (current: <value or 3>)",
header: "Inline Plan Threshold",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave threshold unchanged." },
{ label: "Enter number", description: "Integer count. Non-numeric rejected. Default: 3" }
]
}
])
```
### Section 2 — Execution Tuning
```text
AskUserQuestion([
{
question: "Enable autonomous node repair on verification failure? (current: <value or true>)",
header: "Node Repair",
multiSelect: false,
options: [
{ label: "Yes (default: true)", description: "Executor retries failed tasks up to the repair budget." },
{ label: "No", description: "Stop on first verification failure." }
]
},
{
question: "Maximum node-repair attempts per failed task? (current: <value or 2>)",
header: "Repair Budget",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave existing budget unchanged." },
{ label: "Enter number", description: "Integer >= 0. Non-numeric rejected. Default: 2" }
]
},
{
question: "Auto-prune stale STATE.md entries at phase boundaries? (current: <value or false>)",
header: "Auto Prune",
multiSelect: false,
options: [
{ label: "No (default: false)", description: "Prompt before pruning." },
{ label: "Yes", description: "Prune stale entries without prompting." }
]
}
])
```
### Section 3 — Discussion Tuning
```text
AskUserQuestion([
{
question: "Maximum discuss-phase question rounds? (current: <value or 3>)",
header: "Max Discuss Passes",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave existing value unchanged." },
{ label: "Enter number", description: "Integer >= 1. Non-numeric rejected. Default: 3. Prevents infinite discussion loops in headless mode." }
]
}
])
```
### Section 4 — Cross-AI Execution
```text
AskUserQuestion([
{
question: "Delegate phase execution to an external AI CLI? (current: <value or false>)",
header: "Cross-AI",
multiSelect: false,
options: [
{ label: "No (default: false)", description: "Use local executor agents." },
{ label: "Yes", description: "Pipe phase prompt to `cross_ai_command` via stdin. Requires command to be set." }
]
},
{
question: "Cross-AI command template? (current: <value or null>)",
header: "Cross-AI Command",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave command unchanged." },
{ label: "Clear (null)", description: "Unset the command." },
{ label: "Enter command", description: "Shell command receiving phase prompt via stdin. Must produce SUMMARY.md-compatible output." }
]
},
{
question: "Cross-AI timeout (seconds)? (current: <value or 300>)",
header: "Cross-AI Timeout",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave timeout unchanged." },
{ label: "Enter seconds", description: "Integer seconds. Non-numeric rejected. Default: 300" }
]
}
])
```
### Section 5 — Git Customization
```text
AskUserQuestion([
{
question: "Git base branch? (current: <value or main>)",
header: "Base Branch",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave base branch unchanged." },
{ label: "Enter branch name", description: "e.g., main, master, develop. Integration branch for phase/milestone branches." }
]
},
{
question: "Phase branch template? (current: <value or gsd/phase-{phase}-{slug}>)",
header: "Phase Template",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave template unchanged." },
{ label: "Enter template", description: "Non-empty string with at least one placeholder. Available: {phase}, {slug}. Non-default values missing placeholders are rejected." }
]
},
{
question: "Milestone branch template? (current: <value or gsd/{milestone}-{slug}>)",
header: "Milestone Template",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave template unchanged." },
{ label: "Enter template", description: "Non-empty string. Available placeholders: {milestone}, {slug}. Non-default values missing placeholders are rejected." }
]
}
])
```
### Section 6 — Runtime / Output
```text
AskUserQuestion([
{
question: "Response language for agent output? (current: <value or null>)",
header: "Language",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave unchanged." },
{ label: "Clear (null)", description: "Use Claude default (English)." },
{ label: "Enter language", description: "Free-text language name or code (e.g., Japanese, pt, ko). Propagates to spawned agents." }
]
},
{
question: "Context window size (tokens)? (current: <value or 200000>)",
header: "Context Window",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave unchanged." },
{ label: "Enter number", description: "Integer. Non-numeric rejected. Default: 200000. Use 1000000 for 1M-context models. Values >= 500000 enable adaptive enrichment." }
]
},
{
question: "Include gitignored files in broad searches? (current: <value or false>)",
header: "Search Gitignored",
multiSelect: false,
options: [
{ label: "No (default: false)", description: "Respect .gitignore during searches." },
{ label: "Yes", description: "Add --no-ignore to broad searches (includes .planning/)." }
]
},
{
question: "Graphify build timeout (seconds)? (current: <value or 300>)",
header: "Graphify Timeout",
multiSelect: false,
options: [
{ label: "Keep current", description: "Leave timeout unchanged." },
{ label: "Enter seconds", description: "Integer seconds. Non-numeric rejected. Default: 300" }
]
}
])
```
</step>
<step name="update_config">
Merge the new settings into the existing config at `$GSD_CONFIG_PATH`. This merge is the
core correctness invariant: **preserve every unrelated key** — do not clobber siblings.
Apply each selected value via `gsd-sdk query config-set <key> <value>` so the central
validator (`isValidConfigKey`) accepts the write and the deep-merge preserves unrelated
keys and sibling sub-objects.
```bash
# Example — only write keys the user changed. "Keep current" selections are skipped.
gsd-sdk query config-set workflow.plan_bounce_passes 5
gsd-sdk query config-set workflow.subagent_timeout 900
gsd-sdk query config-set git.base_branch main
gsd-sdk query config-set context_window 1000000
```
Conceptual shape after merge (unchanged top-level keys like `model_profile`,
`granularity`, `mode`, `brave_search`, `agent_skills.*`, `hooks.context_warnings`, and
anything not listed in Sections 1–6 MUST survive the update):
```json
{
...existing_config,
"workflow": {
...existing_workflow,
"plan_bounce": <new|existing>,
"plan_bounce_passes": <new|existing>,
"plan_bounce_script": <new|existing|null>,
"subagent_timeout": <new|existing>,
"inline_plan_threshold": <new|existing>,
"node_repair": <new|existing>,
"node_repair_budget": <new|existing>,
"auto_prune_state": <new|existing>,
"max_discuss_passes": <new|existing>,
"cross_ai_execution": <new|existing>,
"cross_ai_command": <new|existing|null>,
"cross_ai_timeout": <new|existing>
},
"git": {
...existing_git,
"base_branch": <new|existing>,
"phase_branch_template": <new|existing>,
"milestone_branch_template": <new|existing>
},
"response_language": <new|existing|null>,
"context_window": <new|existing>,
"search_gitignored": <new|existing>,
"graphify": {
...existing_graphify,
"build_timeout": <new|existing>
}
}
```
Never emit a full overwrite of the file that omits keys the user did not touch. Always
route each write through `gsd-sdk query config-set` so sibling preservation is handled by
the central setter.
</step>
<step name="confirm">
Display:
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► ADVANCED SETTINGS UPDATED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| Setting | Value |
|--------------------------------|-------|
| workflow.plan_bounce | {on/off} |
| workflow.plan_bounce_passes | {n} |
| workflow.plan_bounce_script | {path/null} |
| workflow.subagent_timeout | {seconds} |
| workflow.inline_plan_threshold | {n} |
| workflow.node_repair | {on/off} |
| workflow.node_repair_budget | {n} |
| workflow.auto_prune_state | {on/off} |
| workflow.max_discuss_passes | {n} |
| workflow.cross_ai_execution | {on/off} |
| workflow.cross_ai_command | {cmd/null} |
| workflow.cross_ai_timeout | {seconds} |
| git.base_branch | {branch} |
| git.phase_branch_template | {template} |
| git.milestone_branch_template | {template} |
| response_language | {lang/null} |
| context_window | {tokens} |
| search_gitignored | {on/off} |
| graphify.build_timeout | {seconds} |
These settings apply to future /gsd-plan-phase, /gsd-execute-phase, /gsd-discuss-phase,
and /gsd-ship runs.
For common-case toggles (model profile, research/plan_check/verifier, branching strategy,
UI/AI phase gates), use /gsd-settings.
```
</step>
</process>
<success_criteria>
- [ ] Current config read from resolved `$GSD_CONFIG_PATH`
- [ ] Six sections rendered (Planning, Execution, Discussion, Cross-AI, Git, Runtime)
- [ ] Every field pre-selected to its current value (or documented default if absent)
- [ ] Numeric inputs validated — non-numeric rejected and re-prompted
- [ ] Branch-template inputs validated — non-default must contain a placeholder
- [ ] Null-allowed fields accept an empty input as a clear
- [ ] Writes routed through `gsd-sdk query config-set` so unrelated keys are preserved
- [ ] Confirmation table rendered listing all 19 fields
</success_criteria>