* fix(#2427): ground smart-entry completion in ROADMAP-derived counts + tighten status regex
Two coupled defects in isComplete (src/smart-entry.cts):
1. Two-scale comparison: isComplete compared global current_phase (from
STATE.md body 'Phase: N') against milestone-scoped total_phases (from
STATE.md frontmatter progress.total_phases, written once at milestone-
switch time and going stale as soon as new phases are appended to the
roadmap). When current_phase >= stale total_phases (e.g. 7 >= 4),
isComplete tripped true even though later phases were still unchecked
in ROADMAP.md.
2. Over-broad status regex: /\bcomplete(d)?|done|shipped\b/i matched any
'shipped' or 'done' substring — including per-phase status like
'Phase X shipped — PR #N' — and falsely satisfied the status side of
the completion check.
Fix:
- Added two new SmartEntrySignals fields: roadmap_total_phases and
roadmap_completed_phases, populated by calling the existing
deriveProgressFromRoadmap helper (from phase-lifecycle.cts:60) when
ROADMAP.md exists. These are global, authoritative counts from the
Progress table — never stale.
- isComplete now prefers the roadmap-derived counts when available
(completed >= total) and falls back to the legacy STATE.md comparison
only when the roadmap has no parseable Progress table (backward compat
for fresh or non-standard projects).
- Tightened the status regex to /\b(milestone\s+complete|all\s+phases\s+complete|complete(d)?)\b/i.
Drops 'done' and 'shipped' (per-phase language). Keeps milestone-level
signals per ADR-2207 (milestone complete, all phases complete) plus the
legacy short form 'complete'/'completed'.
Tests (tests/smart-entry.unit.test.cjs gains a #2427 describe block):
- Mid-milestone with stale total_phases=4, current_phase=7, per-phase
'shipped' status, and 3 unchecked roadmap phases → NOT complete (the
core bug scenario).
- All roadmap phases complete classifies as complete even with stale
cached total_phases (roadmap wins).
- Per-phase 'shipped' or 'done' status alone does NOT satisfy completion
when roadmap phases are unchecked.
- Legacy fallback: empty roadmap (no Progress table) still classifies via
STATE.md comparison (backward compat).
The makeProject test helper now accepts a string for the 'roadmap'
parameter (written verbatim) in addition to the boolean shorthand, so
tests can supply a real Progress table.
References: #2427; ADR-2207 (milestone status lifecycle); ADR-2143
(column-name-driven Progress table parsing via deriveProgressFromRoadmap);
triage note that this is a read-side fix only (the milestone-switch write
path in state.cjs is out of scope).
* chore(#2427): backfill pr:2466 in .changeset/curious-rams-run.md