fix(milestone): deduplicate phase filter and handle empty MILESTONES.md

Two hardening changes to cmdMilestoneComplete:

1. Replace 27 lines of inline isDirInMilestone logic (roadmap parsing,
   normalization, and matching) with a single call to the shared
   getMilestonePhaseFilter(cwd) from core.cjs. The inline copy was
   identical to the core version — deduplicating prevents future drift.

2. Handle empty MILESTONES.md files. Previously, an existing but empty
   file would fall into the headerMatch branch and produce malformed
   output. Now an empty file is treated the same as a missing one,
   writing the standard "# Milestones" header before the entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Tibsfox
2026-03-03 01:48:47 -08:00
committed by Lex Christopherson
parent 15226feb18
commit 8b8d1074b8
3 changed files with 121 additions and 48 deletions

View File

@@ -638,9 +638,31 @@ function mergeCodexConfig(configPath, gsdBlock) {
// Case 2: Has GSD marker — truncate and re-append
if (markerIndex !== -1) {
const before = existing.substring(0, markerIndex).trimEnd();
const newContent = before ? before + '\n\n' + gsdBlock + '\n' : gsdBlock + '\n';
fs.writeFileSync(configPath, newContent);
let before = existing.substring(0, markerIndex).trimEnd();
if (before) {
// Strip any GSD-managed sections that leaked above the marker from previous installs
before = before.replace(/^\[agents\.gsd-[^\]]+\]\n(?:(?!\[)[^\n]*\n?)*/gm, '');
before = before.replace(/^\[agents\]\n(?:(?!\[)[^\n]*\n?)*/m, '');
before = before.replace(/\n{3,}/g, '\n\n').trimEnd();
// Re-inject feature keys if user has [features] above the marker
const hasFeatures = /^\[features\]\s*$/m.test(before);
if (hasFeatures) {
if (!before.includes('multi_agent')) {
before = before.replace(/^\[features\]\s*$/m, '[features]\nmulti_agent = true');
}
if (!before.includes('default_mode_request_user_input')) {
before = before.replace(/^\[features\].*$/m, '$&\ndefault_mode_request_user_input = true');
}
}
// Skip [features] from gsdBlock if user already has it
const block = hasFeatures
? GSD_CODEX_MARKER + '\n' + gsdBlock.substring(gsdBlock.indexOf('[agents]'))
: gsdBlock;
fs.writeFileSync(configPath, before + '\n\n' + block + '\n');
} else {
fs.writeFileSync(configPath, gsdBlock + '\n');
}
return;
}