Per-phase prose backfill (Plan 142 prose-preservation Phase 2, GATE2 step 1).
Purpose
-------
P1.7 seeded the roadmap ITEM SET into the registry but dropped the per-phase
PROSE — every ``# PHASE Mx`` section in the legacy
``oc_chat/roadmap/ROADMAP-v3.38.md`` (phase metadata + the full ``### Deliverables``
table with each item's *rich description + status provenance* + ``### Acceptance``)
was lost: the seeded ``phases/<code>.md`` records carry an EMPTY body and a few
``sub_phases`` descriptions degraded to bare-id stubs (e.g. ``M0.2``).
This tool restores them, byte-faithfully, mirroring the Phase-1 pattern (verbatim
section -> record body): for each ``# PHASE`` section it writes the verbatim
section body into the matching ``phases/<code>.md`` record BODY (which the P1.4
build already carries into ``roadmap_items_v3.prose`` via ``prose=body or None``,
so the EXTENDED render can emit it). It also replaces each ``description == id``
sub-phase stub with the real Item-column text from that phase's deliverables
table (single-lined, capped to the ``Line240`` contract).
No contract change: the Phase model is unchanged; only record BODIES (and the
handful of stub descriptions) are rewritten. Idempotent — re-running yields
identical bytes.
Responsibilities
----------------
- ``parse_phase_sections`` (split the legacy file on ``# PHASE`` headers),
``deliverable_items`` (id -> Item-column text), ``backfill`` (re-emit records),
``coverage`` (the per-phase / per-item map for the audit artifact).
Diagnostics
-----------
Domain: OC_CHAT.MAIN
Levels:
L2 - backfill lifecycle
L3 - per-phase section extraction
L4 - per-record emission
Contracts
---------
- Deterministic; writes only ``source/phases/<code>.md`` records; never touches
the live legacy roadmap; every rewritten record re-validates + re-canonicalises.
Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- oc_chat.registry.regenerate (imported for the contracts bootstrap it runs)
- oc_chat.registry.source.canonical (load_record and format_record_text - reads each phase record and re-emits it with the restored body)
- oc_chat.registry.source.scanner (scan_source_tree - finds the phase records)