fix(config): prevent workflow.research reset during milestone transitions

Two bugs caused workflow.research to silently reset to false:

1. new-milestone.md unconditionally overwrote workflow.research via
   config-set after asking about research — coupling a per-milestone
   decision to a persistent user preference. Now the research question
   is per-invocation only; persistent config changes via /gsd:settings.

2. verify.cjs health repair (createConfig/resetConfig) used flat keys
   (research, plan_checker, verifier) instead of the canonical nested
   workflow object from config.cjs, also missing branch templates,
   nyquist_validation, and brave_search fields.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Maxim Brashenko
2026-03-15 21:08:59 +05:00
committed by GitHub
parent 63823c2e8a
commit eba9423ce0
4 changed files with 36 additions and 13 deletions

View File

@@ -527,6 +527,15 @@ describe('validate health --repair command', () => {
assert.ok(fs.existsSync(configPath), 'config.json should now exist on disk');
const diskConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
assert.strictEqual(diskConfig.model_profile, 'balanced', 'default model_profile should be balanced');
// Verify nested workflow structure matches config.cjs canonical format
assert.ok(diskConfig.workflow, 'config should have nested workflow object');
assert.strictEqual(diskConfig.workflow.research, true, 'workflow.research should default to true');
assert.strictEqual(diskConfig.workflow.plan_check, true, 'workflow.plan_check should default to true');
assert.strictEqual(diskConfig.workflow.verifier, true, 'workflow.verifier should default to true');
assert.strictEqual(diskConfig.workflow.nyquist_validation, true, 'workflow.nyquist_validation should default to true');
// Verify branch templates are present
assert.strictEqual(diskConfig.phase_branch_template, 'gsd/phase-{phase}-{slug}');
assert.strictEqual(diskConfig.milestone_branch_template, 'gsd/{milestone}-{slug}');
});
test('resets config.json when JSON is invalid', () => {
@@ -545,9 +554,11 @@ describe('validate health --repair command', () => {
const resetAction = output.repairs_performed.find(r => r.action === 'resetConfig');
assert.ok(resetAction, `Expected resetConfig action: ${JSON.stringify(output.repairs_performed)}`);
// Verify config.json is now valid JSON
// Verify config.json is now valid JSON with correct nested structure
const diskConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
assert.ok(typeof diskConfig === 'object', 'config.json should be valid JSON after repair');
assert.ok(diskConfig.workflow, 'reset config should have nested workflow object');
assert.strictEqual(diskConfig.workflow.research, true, 'workflow.research should be true after reset');
});
test('regenerates STATE.md when missing', () => {