feat(manager): add per-step passthrough flags via config
Adds `manager.flags.{discuss,plan,execute}` config keys so users can
configure flags that /gsd:manager passes to each step when dispatching.
For example, `manager.flags.discuss: "--auto --analyze"` makes every
discuss dispatched from the manager include those flags.
Closes #1400
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ const VALID_CONFIG_KEYS = new Set([
|
||||
'workflow.subagent_timeout',
|
||||
'hooks.context_warnings',
|
||||
'project_code', 'phase_naming',
|
||||
'manager.flags.discuss', 'manager.flags.plan', 'manager.flags.execute',
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
@@ -314,6 +314,7 @@ function loadConfig(cwd) {
|
||||
subagent_timeout: get('subagent_timeout', { section: 'workflow', field: 'subagent_timeout' }) ?? defaults.subagent_timeout,
|
||||
model_overrides: parsed.model_overrides || null,
|
||||
agent_skills: parsed.agent_skills || {},
|
||||
manager: parsed.manager || {},
|
||||
};
|
||||
} catch {
|
||||
return defaults;
|
||||
|
||||
@@ -1026,6 +1026,14 @@ function cmdInitManager(cwd, raw) {
|
||||
});
|
||||
|
||||
const completedCount = phases.filter(p => p.disk_status === 'complete').length;
|
||||
|
||||
// Read manager flags from config (passthrough flags for each step)
|
||||
const managerFlags = {
|
||||
discuss: (config.manager && config.manager.flags && config.manager.flags.discuss) || '',
|
||||
plan: (config.manager && config.manager.flags && config.manager.flags.plan) || '',
|
||||
execute: (config.manager && config.manager.flags && config.manager.flags.execute) || '',
|
||||
};
|
||||
|
||||
const result = {
|
||||
milestone_version: milestone.version,
|
||||
milestone_name: milestone.name,
|
||||
@@ -1039,6 +1047,7 @@ function cmdInitManager(cwd, raw) {
|
||||
project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
|
||||
roadmap_exists: true,
|
||||
state_exists: true,
|
||||
manager_flags: managerFlags,
|
||||
};
|
||||
|
||||
output(withProjectRoot(cwd, result), raw);
|
||||
|
||||
@@ -14,6 +14,13 @@ Configuration options for `.planning/` directory behavior.
|
||||
"phase_branch_template": "gsd/phase-{phase}-{slug}",
|
||||
"milestone_branch_template": "gsd/{milestone}-{slug}",
|
||||
"quick_branch_template": null
|
||||
},
|
||||
"manager": {
|
||||
"flags": {
|
||||
"discuss": "",
|
||||
"plan": "",
|
||||
"execute": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -28,6 +35,9 @@ Configuration options for `.planning/` directory behavior.
|
||||
| `git.quick_branch_template` | `null` | Optional branch template for quick-task runs |
|
||||
| `workflow.use_worktrees` | `true` | Whether executor agents run in isolated git worktrees. Set to `false` to disable worktrees — agents execute sequentially on the main working tree instead. Recommended for solo developers or when worktree merges cause issues. |
|
||||
| `workflow.subagent_timeout` | `300000` | Timeout in milliseconds for parallel subagent tasks (e.g. codebase mapping). Increase for large codebases or slower models. Default: 300000 (5 minutes). |
|
||||
| `manager.flags.discuss` | `""` | Flags passed to `/gsd:discuss-phase` when dispatched from manager (e.g. `"--auto --analyze"`) |
|
||||
| `manager.flags.plan` | `""` | Flags passed to plan workflow when dispatched from manager |
|
||||
| `manager.flags.execute` | `""` | Flags passed to execute workflow when dispatched from manager |
|
||||
</config_schema>
|
||||
|
||||
<commit_docs_behavior>
|
||||
|
||||
@@ -23,7 +23,14 @@ INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init manager)
|
||||
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
||||
```
|
||||
|
||||
Parse JSON for: `milestone_version`, `milestone_name`, `phase_count`, `completed_count`, `in_progress_count`, `phases`, `recommended_actions`, `all_complete`, `waiting_signal`.
|
||||
Parse JSON for: `milestone_version`, `milestone_name`, `phase_count`, `completed_count`, `in_progress_count`, `phases`, `recommended_actions`, `all_complete`, `waiting_signal`, `manager_flags`.
|
||||
|
||||
`manager_flags` contains per-step passthrough flags from config:
|
||||
- `manager_flags.discuss` — appended to `/gsd:discuss-phase` args (e.g. `"--auto --analyze"`)
|
||||
- `manager_flags.plan` — appended to plan agent init command
|
||||
- `manager_flags.execute` — appended to execute agent init command
|
||||
|
||||
These are empty strings by default. Set via: `gsd-tools config-set manager.flags.discuss "--auto --analyze"`
|
||||
|
||||
**If error:** Display the error message and exit.
|
||||
|
||||
@@ -193,24 +200,24 @@ When the user selects a compound option:
|
||||
2. **Then run the inline discuss:**
|
||||
|
||||
```
|
||||
Skill(skill="gsd:discuss-phase", args="{PHASE_NUM}")
|
||||
Skill(skill="gsd:discuss-phase", args="{PHASE_NUM} {manager_flags.discuss}")
|
||||
```
|
||||
|
||||
After discuss completes, loop back to dashboard step (background agents continue running).
|
||||
|
||||
### Discuss Phase N
|
||||
|
||||
Discussion is interactive — needs user input. Run inline:
|
||||
Discussion is interactive — needs user input. Run inline with any configured flags:
|
||||
|
||||
```
|
||||
Skill(skill="gsd:discuss-phase", args="{PHASE_NUM}")
|
||||
Skill(skill="gsd:discuss-phase", args="{PHASE_NUM} {manager_flags.discuss}")
|
||||
```
|
||||
|
||||
After discuss completes, loop back to dashboard step.
|
||||
|
||||
### Plan Phase N
|
||||
|
||||
Planning runs autonomously. Spawn a background agent that delegates to the Skill pipeline:
|
||||
Planning runs autonomously. Spawn a background agent that delegates to the Skill pipeline with any configured flags:
|
||||
|
||||
```
|
||||
Task(
|
||||
@@ -221,9 +228,10 @@ Task(
|
||||
Working directory: {cwd}
|
||||
Phase: {N} — {phase_name}
|
||||
Goal: {goal}
|
||||
Manager flags: {manager_flags.plan}
|
||||
|
||||
Run the plan-phase Skill:
|
||||
Skill(skill=\"gsd:plan-phase\", args=\"{N} --auto\")
|
||||
Run the plan-phase Skill with any configured manager flags:
|
||||
Skill(skill=\"gsd:plan-phase\", args=\"{N} --auto {manager_flags.plan}\")
|
||||
|
||||
This delegates to the full plan-phase pipeline including local patches, research, plan-checker, and all quality gates.
|
||||
|
||||
@@ -241,7 +249,7 @@ Loop back to dashboard step.
|
||||
|
||||
### Execute Phase N
|
||||
|
||||
Execution runs autonomously. Spawn a background agent that delegates to the Skill pipeline:
|
||||
Execution runs autonomously. Spawn a background agent that delegates to the Skill pipeline with any configured flags:
|
||||
|
||||
```
|
||||
Task(
|
||||
@@ -252,9 +260,10 @@ Task(
|
||||
Working directory: {cwd}
|
||||
Phase: {N} — {phase_name}
|
||||
Goal: {goal}
|
||||
Manager flags: {manager_flags.execute}
|
||||
|
||||
Run the execute-phase Skill:
|
||||
Skill(skill=\"gsd:execute-phase\", args=\"{N}\")
|
||||
Run the execute-phase Skill with any configured manager flags:
|
||||
Skill(skill=\"gsd:execute-phase\", args=\"{N} {manager_flags.execute}\")
|
||||
|
||||
This delegates to the full execute-phase pipeline including local patches, branching, wave-based execution, verification, and all quality gates.
|
||||
|
||||
|
||||
@@ -413,4 +413,44 @@ describe('init manager', () => {
|
||||
// macOS resolves /var → /private/var; normalize both sides
|
||||
assert.strictEqual(fs.realpathSync(output.project_root), fs.realpathSync(tmpDir));
|
||||
});
|
||||
|
||||
test('output includes manager_flags defaults when not configured', () => {
|
||||
writeState(tmpDir);
|
||||
writeRoadmap(tmpDir, [{ number: '1', name: 'Test' }]);
|
||||
|
||||
const result = runGsdTools('init manager', tmpDir);
|
||||
const output = JSON.parse(result.output);
|
||||
|
||||
assert.ok(output.manager_flags, 'should include manager_flags');
|
||||
assert.strictEqual(output.manager_flags.discuss, '');
|
||||
assert.strictEqual(output.manager_flags.plan, '');
|
||||
assert.strictEqual(output.manager_flags.execute, '');
|
||||
});
|
||||
|
||||
test('output includes manager_flags from config when set', () => {
|
||||
writeState(tmpDir);
|
||||
writeRoadmap(tmpDir, [{ number: '1', name: 'Test' }]);
|
||||
|
||||
// Write config with manager flags
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'config.json'),
|
||||
JSON.stringify({
|
||||
manager: {
|
||||
flags: {
|
||||
discuss: '--auto --analyze',
|
||||
plan: '--skip-research',
|
||||
execute: '--interactive',
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const result = runGsdTools('init manager', tmpDir);
|
||||
const output = JSON.parse(result.output);
|
||||
|
||||
assert.ok(output.manager_flags, 'should include manager_flags');
|
||||
assert.strictEqual(output.manager_flags.discuss, '--auto --analyze');
|
||||
assert.strictEqual(output.manager_flags.plan, '--skip-research');
|
||||
assert.strictEqual(output.manager_flags.execute, '--interactive');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user