feat(config): add execution context profiles for mode-specific agent output (#1827)
* feat(config): add execution context profiles for mode-specific agent output * fix(config): add enum validation for context config key Validate context values against allowed enum (dev, research, review) in cmdConfigSet before writing to config.json, matching the pattern used for model_profile validation. Add rejection test for invalid context values.
This commit is contained in:
@@ -6,6 +6,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- **Execution context profiles** — Three context profiles (`dev`, `research`, `review`) for mode-specific agent output guidance (#1807)
|
||||
|
||||
## [1.33.0] - 2026-04-05
|
||||
|
||||
### Added
|
||||
|
||||
@@ -28,6 +28,7 @@ const VALID_CONFIG_KEYS = new Set([
|
||||
'workflow.subagent_timeout',
|
||||
'hooks.context_warnings',
|
||||
'features.thinking_partner',
|
||||
'context',
|
||||
'project_code', 'phase_naming',
|
||||
'manager.flags.discuss', 'manager.flags.plan', 'manager.flags.execute',
|
||||
'response_language',
|
||||
@@ -337,6 +338,11 @@ function cmdConfigSet(cwd, keyPath, value, raw) {
|
||||
try { parsedValue = JSON.parse(value); } catch { /* keep as string */ }
|
||||
}
|
||||
|
||||
const VALID_CONTEXT_VALUES = ['dev', 'research', 'review'];
|
||||
if (keyPath === 'context' && !VALID_CONTEXT_VALUES.includes(String(parsedValue))) {
|
||||
error(`Invalid context value '${value}'. Valid values: ${VALID_CONTEXT_VALUES.join(', ')}`);
|
||||
}
|
||||
|
||||
const setConfigValueResult = setConfigValue(cwd, keyPath, parsedValue);
|
||||
output(setConfigValueResult, raw, `${keyPath}=${parsedValue}`);
|
||||
}
|
||||
|
||||
21
get-shit-done/contexts/dev.md
Normal file
21
get-shit-done/contexts/dev.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Dev Context Profile
|
||||
|
||||
Agent output guidance for dev mode. Loaded when `context: dev` is set in config.json.
|
||||
|
||||
## Output Style
|
||||
|
||||
- Concise, action-oriented responses
|
||||
- Lead with the code change or command, follow with brief rationale
|
||||
- Skip preamble — assume the developer has full context
|
||||
- Use inline code references (`file:line`) over prose descriptions
|
||||
|
||||
## Focus Areas
|
||||
|
||||
- Working code that compiles and passes tests
|
||||
- Minimal diff — change only what is necessary
|
||||
- Flag side effects or breaking changes immediately
|
||||
- Surface the next actionable step at the end of every response
|
||||
|
||||
## Verbosity
|
||||
|
||||
Low. One-liner explanations unless the change is non-obvious. Omit background theory, alternative approaches, and caveats that do not affect the current task.
|
||||
22
get-shit-done/contexts/research.md
Normal file
22
get-shit-done/contexts/research.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Research Context Profile
|
||||
|
||||
Agent output guidance for research mode. Loaded when `context: research` is set in config.json.
|
||||
|
||||
## Output Style
|
||||
|
||||
- Verbose, exploratory responses that surface trade-offs and alternatives
|
||||
- Present multiple approaches with pros and cons before recommending one
|
||||
- Include links, references, and citations where available
|
||||
- Use structured headings and bullet lists for scan-ability
|
||||
|
||||
## Focus Areas
|
||||
|
||||
- Breadth of options — enumerate before narrowing
|
||||
- Prior art and ecosystem conventions
|
||||
- Risks, edge cases, and failure modes
|
||||
- Dependencies and compatibility implications
|
||||
- Long-term maintainability of each approach
|
||||
|
||||
## Verbosity
|
||||
|
||||
High. Explain reasoning, show evidence, and document assumptions. Include background context even if the developer likely knows it — research artifacts are read by future contributors who may not.
|
||||
22
get-shit-done/contexts/review.md
Normal file
22
get-shit-done/contexts/review.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Review Context Profile
|
||||
|
||||
Agent output guidance for review mode. Loaded when `context: review` is set in config.json.
|
||||
|
||||
## Output Style
|
||||
|
||||
- Critical, detail-focused responses that prioritize correctness
|
||||
- Organize findings by severity: blocking, important, nit
|
||||
- Reference specific lines and files for every finding
|
||||
- State what is correct as well as what needs change — confirm the good parts
|
||||
|
||||
## Focus Areas
|
||||
|
||||
- Correctness — logic errors, off-by-ones, missing edge cases
|
||||
- Security — input validation, injection vectors, secret exposure
|
||||
- Performance — unnecessary allocations, O(n^2) patterns, missing caching
|
||||
- Style and consistency — naming, formatting, import order
|
||||
- Test coverage — untested branches, missing assertions, flaky patterns
|
||||
|
||||
## Verbosity
|
||||
|
||||
Medium. Be thorough on findings but terse in explanation. Each issue should be one to three sentences: what is wrong, why it matters, and how to fix it.
|
||||
@@ -861,3 +861,67 @@ describe('config-set/config-get workflow.use_worktrees', () => {
|
||||
assert.strictEqual(output, true);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── config-set/config-get context ─────────────────────────────────────────
|
||||
|
||||
describe('config-set/config-get context', () => {
|
||||
let tmpDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = createTempProject();
|
||||
runGsdTools('config-ensure-section', tmpDir, { HOME: tmpDir, USERPROFILE: tmpDir });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup(tmpDir);
|
||||
});
|
||||
|
||||
test('config set context dev succeeds', () => {
|
||||
const result = runGsdTools('config-set context dev', tmpDir);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const config = readConfig(tmpDir);
|
||||
assert.strictEqual(config.context, 'dev');
|
||||
});
|
||||
|
||||
test('config set context research succeeds', () => {
|
||||
const result = runGsdTools('config-set context research', tmpDir);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const config = readConfig(tmpDir);
|
||||
assert.strictEqual(config.context, 'research');
|
||||
});
|
||||
|
||||
test('config set context review succeeds', () => {
|
||||
const result = runGsdTools('config-set context review', tmpDir);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const config = readConfig(tmpDir);
|
||||
assert.strictEqual(config.context, 'review');
|
||||
});
|
||||
|
||||
test('config get context returns the set value', () => {
|
||||
runGsdTools('config-set context dev', tmpDir);
|
||||
const result = runGsdTools('config-get context', tmpDir);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output, 'dev');
|
||||
});
|
||||
|
||||
test('config set context rejects invalid values', () => {
|
||||
const result = runGsdTools('config-set context foobar', tmpDir);
|
||||
assert.strictEqual(result.success, false);
|
||||
assert.ok(
|
||||
result.error.includes('Invalid context value'),
|
||||
`Expected "Invalid context value" in error: ${result.error}`
|
||||
);
|
||||
});
|
||||
|
||||
test('all three context profile files exist', () => {
|
||||
const contextsDir = path.join(__dirname, '..', 'get-shit-done', 'contexts');
|
||||
assert.ok(fs.existsSync(path.join(contextsDir, 'dev.md')), 'dev.md should exist');
|
||||
assert.ok(fs.existsSync(path.join(contextsDir, 'research.md')), 'research.md should exist');
|
||||
assert.ok(fs.existsSync(path.join(contextsDir, 'review.md')), 'review.md should exist');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user