* fix(#4186): anchored status vocabulary, record-session arg guard, recount pin
Three defects from #4186:
1. normalizeStateStatus ran a first-match-wins SUBSTRING chain over the
free-prose body Status field, so prose merely mentioning a status word
was silently rewritten to a credible wrong token (a .planning/ path in
Italian prose -> status: planning; verifica -> verifying; completezza ->
completed). Recognition is now an ANCHORED whole-field match against a
declared vocabulary (STATUS_EXACT_TOKENS + STATUS_ANCHORED_PATTERNS,
state-document.cts) — case/whitespace-tolerant, branch-order artifacts
preserved (Planning complete -> planning; Phase complete — ready for
verification -> verifying). The recorded lenient fallback (#3873 row 26)
stands: unrecognized prose passes through verbatim. Read-side consumers
(W011, statusline) ride the same function.
2. The progress recount skew (stray *-SUMMARY.md inflating
completed_plans) is already dead on next via #1988/PR #2016
(countMatchedSummaries pairs summaries to plans) — verified live and
pinned with regression rows composed against the #4129/#4359 ratchet.
3. state record-session with no args executed and wrote STATE.md; it now
errors like state update (stopped-at or resume-file required), handler-
side so SDK callers are covered too. Four tests pinning the bare-call
write are updated to the new contract.
* fix(#4186): update status pins to the anchored vocabulary contract
Bench round 1 follow-ups:
- Legacy bare 'Milestone complete' kept as reader-side vocabulary
(ADR-2207 removed the writers, not recognition of legacy files).
- state.test pins updated: 'Paused at Plan 3' and round-trip
'Executing Plan 5' were pins of the substring guessing itself —
the round-trip now uses the real handler form 'Executing Phase 5'.
- record-session no-op/no-fields tests repurposed to the usage-error
contract (CLI + SDK-level ExitError), byte-unchanged assertions kept.
- statusline tests repinned: vocabulary values collapse to keywords;
narratives render the documented first-word fallback instead of a
guessed token. Hook doc comment updated to match.
- docs-guard exempt baseline: state.test.cjs now cites docs/CLI-TOOLS.md.
- docs/CLI-TOOLS.md: record-session signature notes the required flag.
* fix(#4186): repair a dangling sentence in the schema docstring
* test(#4186): bound the completed_plans scan regex (#2128 class)
* chore(#4186): backfill changeset PR number
---------
Co-authored-by: sim <sim@local>