* fix(#1761): skip conflated progress in state json read-path when milestone unbounded ADR-1769 Phase 7 (#1794) closed the state sync WRITE path — when a milestone version is asserted in frontmatter but the ROADMAP has no versioned heading for it, sync leaves Progress untouched. But the state json READ path rebuilds progress via buildStateFrontmatter, whose roadmapPhaseCount loop counts phase headings across the WHOLE document when extractCurrentMilestone can't bound the milestone. state json therefore reported a conflated total_phases (sum of sibling milestones) + a derived percent — exactly the value the sync guard was added to prevent. (Repro from the issue: total_phases 8 = 4+4, percent 13.) Mirror the cmdStateSync guard inside buildStateFrontmatter: when the asserted milestone cannot be bounded to a versioned ROADMAP heading (the same versionedHeading test the sync path uses), fall back to the on-disk phase-dir count for total_phases and skip percent. Bounded milestones (versioned ROADMAP, or no milestone asserted) are unchanged. The signal rides on the existing _diskScanCache (new milestoneBounded field) so neither extractCurrentMilestone's return contract nor its other callers change. Regression: extend tests/bug-1761-state-sync-wrong-progress.test.cjs with the read-path case (unbounded → no percent, no conflated total_phases) and a bounded control (versioned ROADMAP → unchanged percent + total_phases). * docs(#1761): add changeset fragment for state json read-path fix
1.0 KiB
type, pr
| type | pr |
|---|---|
| Fixed | 1818 |
gsd-tools state json no longer reports conflated progress for an unversioned milestone (#1761) — the ADR-1769 Phase 7 fix (#1794) taught state sync to leave Progress untouched when a milestone version is asserted but the ROADMAP has no versioned heading for it, but the state json read path still rebuilt progress via buildStateFrontmatter, whose phase-heading count fell back to the whole document and summed sibling milestones. state json therefore reported a conflated total_phases (e.g. 8 = 4+4 across two milestones) plus a derived percent, contradicting the sync guard on the very same project. The read path now mirrors the sync guard: when the asserted milestone cannot be bounded to a versioned ROADMAP heading, total_phases falls back to the on-disk phase-dir count and percent is omitted. Bounded milestones (versioned ROADMAP, or no milestone asserted) are unchanged; the signal rides on the existing _diskScanCache so extractCurrentMilestone's return contract and its other callers are untouched.