* fix(#2400): warn on planned-phase no-op + sync progress.total_plans Bug A: When STATE.md Current Position has no recognized labels (narrative prose), emit a warning field so the workflow detects the no-op instead of continuing with stale state. Bug B: Sync progress.total_plans in the YAML frontmatter when a plan count is provided, preventing contradictory state between frontmatter (0) and body (actual count). This writes the explicitly-provided count, not a re-derivation from disk (#500 safe). Closes #2400 * docs(#2400): backfill changeset PR number (2552)
This commit is contained in:
5
.changeset/2400-planned-phase-empty-transition.md
Normal file
5
.changeset/2400-planned-phase-empty-transition.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
type: Fixed
|
||||||
|
pr: 2552
|
||||||
|
---
|
||||||
|
**`state.planned-phase` now warns on no-op transitions and syncs `progress.total_plans`** — when STATE.md's Current Position has no recognized labels (narrative prose), the command emits a `warning` field so the workflow can detect the no-op instead of continuing with stale state. When a plan count is provided, `progress.total_plans` in the YAML frontmatter is updated alongside the body `Total Plans in Phase` field, preventing contradictory state between the two representations. Previously, the command silently returned success with an empty `updated` array and zero bytes written, and left `progress.total_plans` at 0 while the body reported the actual count. (#2400)
|
||||||
@@ -1117,6 +1117,19 @@ function plannedPhaseCore(
|
|||||||
);
|
);
|
||||||
if (body !== beforePos) updated.push('Current Position');
|
if (body !== beforePos) updated.push('Current Position');
|
||||||
|
|
||||||
|
// #2400 Bug B: sync progress.total_plans to the frontmatter when a plan count
|
||||||
|
// is given. This writes the explicitly-provided count — it is NOT a re-derivation
|
||||||
|
// from disk (#500 RC1 is about deriving from a half-planned snapshot, not about
|
||||||
|
// refusing to write an explicitly-passed argument).
|
||||||
|
if (intent.planCount !== null && intent.planCount !== undefined && hasFrontmatter) {
|
||||||
|
const fmProgress = (existingFm['progress'] as Record<string, unknown> | undefined) || {};
|
||||||
|
if (fmProgress['total_plans'] !== intent.planCount) {
|
||||||
|
fmProgress['total_plans'] = intent.planCount;
|
||||||
|
existingFm['progress'] = fmProgress;
|
||||||
|
updated.push('progress.total_plans');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { content: reassemble(body), updated };
|
return { content: reassemble(body), updated };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2529,7 +2529,10 @@ function cmdStatePlannedPhase(cwd: string, phaseNumber: string | number, planCou
|
|||||||
return result.content;
|
return result.content;
|
||||||
}, cwd, { resync: false, deriveProgressKeys: true });
|
}, cwd, { resync: false, deriveProgressKeys: true });
|
||||||
|
|
||||||
output({ updated, phase: phaseNumber, plan_count: planCount }, raw, updated.length > 0 ? 'true' : 'false');
|
const result = updated.length === 0
|
||||||
|
? { updated, phase: phaseNumber, plan_count: planCount, warning: 'STATE.md Current Position has no recognized labels — transition was a no-op. Verify STATE.md uses the canonical labeled format (Status:, Total Plans in Phase:, etc.).' }
|
||||||
|
: { updated, phase: phaseNumber, plan_count: planCount };
|
||||||
|
output(result, raw, updated.length > 0 ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user