Split out of #502 review (codex P1 on the canonical half, which #502 fixed).
parse_ledger now skips fenced matches when deciding entry identity and extent, so a worked example quoted inside a fence no longer becomes a canonical DW- entry (src/bmad_loop/deferredwork.py:140 _example / _unfenced). parse_legacy did not get the same treatment and is still fence-blind: its only masking is the canonical spans it subtracts up front (src/bmad_loop/deferredwork.py:1022-1028), and its line loop (:1056-1140) never consults fence state.
Consequence, with a fenced complete example sitting in the preamble (before any real entry, so no canonical span covers it):
# Deferred Work
The format, for reference:
```markdown
### DW-1: wire the blob-storage credentials
status: open
gate: 3-2, 3-3
- source_spec: `example.md`
summary: quoted
evidence: e
DW-07: a real entry
status: open
- `main` (`65e5844`): `open_ids` = `{DW-1, DW-07}` — a phantom **canonical** entry — plus legacy `["quoted"]`.
- With #502: `open_ids` = `{DW-07}` (correct), but legacy is `["wire the blob-storage credentials"]` — `_ENTRY_HEADING_RE` reads the fenced heading as a legacy heading entry.
So #502 removes the dangerous half (a phantom canonical entry carries a live `gate:` and can pause a run) and leaves a gate-free phantom on the legacy side. The gate path only ever iterates `parse_ledger` (`src/bmad_loop/engine.py:917-932`) and `gates()` takes a `DWEntry`, so a legacy entry can never gate a story — this cannot wedge a dispatch. It shows up as a spurious item for the sweep to triage.
Both shapes are pre-existing on `main`; only the title of the phantom changed. Deliberately not fixed in #502 to keep that PR off the surrounding legacy scanner.
Fix shape: make the `parse_legacy` line loop skip fenced lines, most likely by folding fence state into the `masked` string it already builds rather than adding a second walk — `src/bmad_loop/fences.py` is the shared reader.
Split out of #502 review (codex P1 on the canonical half, which #502 fixed).
parse_ledgernow skips fenced matches when deciding entry identity and extent, so a worked example quoted inside a fence no longer becomes a canonicalDW-entry (src/bmad_loop/deferredwork.py:140_example/_unfenced).parse_legacydid not get the same treatment and is still fence-blind: its only masking is the canonical spans it subtracts up front (src/bmad_loop/deferredwork.py:1022-1028), and its line loop (:1056-1140) never consults fence state.Consequence, with a fenced complete example sitting in the preamble (before any real entry, so no canonical span covers it):
DW-07: a real entry
status: open