# W21 — the scanner's body fidelity, and the records that drifted

Follows W20 (Project registry + the node-owned daemon, `3455c60`). Small, four-item
slice: one live bug, one tripwire filed but not built, and two records that no longer
describe reality. Opened 2026-07-26 after the ResidentService design wave.

## Scope

1. **#25 — tag bodies lose their code spans (the live bug).** A `#< … #>` tag whose
   opener is bare fires with any backticked or fenced span in its **body** blanked to
   spaces. The tag executes and the author's content is silently gone. Only defect here
   that is live on a path agents use today.
2. **The announce tripwire — file only, do not build.** Cursor advance past an
   input-bearing seq-less turn. Ruled `announce-and-advance` (doyle, 2026-07-26);
   barrier rejected. Mint its REQ **inactive** per rule 5.
3. **ADR-0012 — record the Operator's deliberate revision.** `start='boot'`, core is
   the single start authority, ensure-at-bind retires **at adoption**.
4. **Request #22 — correct a body that is stale in three ways.**

## Open design questions

- **Resolved before planning:** extend `REQ-TAG-SCANNER` rather than mint a sibling for
  body fidelity. It is the same contract (how a tag body is obtained from a digest), its
  stages are already active, and a sibling would fragment tag extraction across two ids.
  The tripwire *does* get its own id, because it is a distinct property on a distinct
  trigger and it must stay inactive while body fidelity ships.
- **Deliberately not in scope:** `CONTEXT.md` §Hub Daemon still describes the relay-hop
  spawn, and that is correct — the glossary records what *is*. It changes at ResidentService
  **adoption**, not at ratification. Same for retiring the relay hop itself.

## Tasks

- **T1** — extend `REQ-TAG-SCANNER`'s title with body fidelity; document the property in
  `CONTEXT.md` beside the existing quotation rule, which today states only the opener half.
- **T2** — fix `extract_tags`: keep finding delimiters on the blanked copy (that *is* the
  quotation rule, and it correctly stops a span-protected `#>` from closing the tag), but
  slice the body from the **original** string at the same offsets.
  - **T2a** — `blank_inline_code` is **not** byte-offset preserving: it maps `Vec<char>`
    and replaces each char with one space, so a multi-byte char inside a span shrinks the
    string and desynchronises the two buffers. Byte offsets must be preserved before any
    slice-from-original is sound. `blank_code_fences` is already byte-preserving.
  - **T2b** — correct the false comment at `src/tags.rs:141-143`. Scoped, per liam: the
    flag/missing-seq equivalence holds for **input-bearing** turns and breaks on exactly
    one shape, `input: null` preamble rows.
- **T3** — red-first regression tests from the probe cases: bare opener + inline span,
  bare opener + fenced block, span carrying a `#>` lookalike, a non-ASCII span (T2a), and
  both negative controls so the quotation rule is not weakened by the fix.
- **T4** — file the announce tripwire as a Request; mint its REQ with
  `required_stages = []`.
- **T5** — ADR-0012 revision record + Request #22 body correction.

## Gate

`cargo build` clean, `cargo test` green, `traceable-reqs check` exit 0.
