* fix(#2997): include phase_id_convention in resolved config _baseConfig in config-loader.cts is an explicit allowlist of keys copied from parsed into the resolved config. phase_id_convention was in VALID_CONFIG_KEYS (manifest line 83) and survived the unknown-key filter, but was never copied into _baseConfig — silently dropped on a clean read. The milestone-prefix validation check could only be activated via the ROADMAP frontmatter fallback, not the documented project-config surface. Added phase_id_convention: get('phase_id_convention') ?? null to _baseConfig. 3 tests: survives resolution, null round-trips, absent resolves to null. * chore(#2997): backfill changeset PR number 3098 --------- Co-authored-by: sim <sim@local>
This commit is contained in:
5
.changeset/wise-jays-romp.md
Normal file
5
.changeset/wise-jays-romp.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 3098
|
||||
---
|
||||
**`phase_id_convention` set in `.planning/config.json` is no longer silently dropped** — the config loader's resolved-config constructor omitted the key despite it being in the valid-keys manifest, so the milestone-prefix validation check could only be activated via the ROADMAP frontmatter fallback. The key now survives resolution. (#2997)
|
||||
@@ -812,6 +812,7 @@ function loadConfigResolved(cwd: string, options: Record<string, unknown> = {}):
|
||||
response_language: get('response_language') || null,
|
||||
claude_md_path: get('claude_md_path') || null,
|
||||
claude_md_assembly: (parsed['claude_md_assembly']) || null,
|
||||
phase_id_convention: get('phase_id_convention') ?? null,
|
||||
};
|
||||
|
||||
// ADR-857 phase 3b: federated config overlay
|
||||
|
||||
@@ -1255,3 +1255,44 @@ describe("loadConfigResolved — corrupt config is distinguishable from absent",
|
||||
assert.equal(res.degraded, false, "an empty file is not corruption");
|
||||
});
|
||||
});
|
||||
|
||||
// ─── #2997: phase_id_convention survives config resolution ─────────────────
|
||||
|
||||
describe('#2997: phase_id_convention is not silently dropped on a clean read', () => {
|
||||
const { createTempDir } = require('./helpers.cjs');
|
||||
const cfgPath = (dir) => path.join(dir, '.planning', 'config.json');
|
||||
|
||||
test('setting phase_id_convention in config.json survives into the resolved config', () => {
|
||||
const tmpDir = createTempDir('gsd-2997-');
|
||||
try {
|
||||
fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true });
|
||||
fs.writeFileSync(cfgPath(tmpDir), JSON.stringify({ phase_id_convention: 'milestone-prefixed' }), 'utf-8');
|
||||
const res = loadConfigResolved(tmpDir);
|
||||
assert.equal(res.degraded, false, 'read must report as non-degraded');
|
||||
assert.equal(res.config.phase_id_convention, 'milestone-prefixed',
|
||||
`phase_id_convention must survive resolution; got: ${JSON.stringify(res.config.phase_id_convention)}`);
|
||||
} finally { cleanup(tmpDir); }
|
||||
});
|
||||
|
||||
test('phase_id_convention set to null round-trips correctly', () => {
|
||||
const tmpDir = createTempDir('gsd-2997-null-');
|
||||
try {
|
||||
fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true });
|
||||
fs.writeFileSync(cfgPath(tmpDir), JSON.stringify({ phase_id_convention: null }), 'utf-8');
|
||||
const res = loadConfigResolved(tmpDir);
|
||||
assert.equal(res.config.phase_id_convention, null,
|
||||
'null phase_id_convention must round-trip as null');
|
||||
} finally { cleanup(tmpDir); }
|
||||
});
|
||||
|
||||
test('phase_id_convention absent → null in resolved config (no false default)', () => {
|
||||
const tmpDir = createTempDir('gsd-2997-absent-');
|
||||
try {
|
||||
fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true });
|
||||
fs.writeFileSync(cfgPath(tmpDir), JSON.stringify({ commit_docs: true }), 'utf-8');
|
||||
const res = loadConfigResolved(tmpDir);
|
||||
assert.equal(res.config.phase_id_convention, null,
|
||||
'absent phase_id_convention must resolve to null, not undefined');
|
||||
} finally { cleanup(tmpDir); }
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user