# Boundary body-integrity plan (Athenaeum regression)

## Scope

Reported by Athenaeum ops (Philip): after adapter 0.3.19→0.3.20 + daemon restart on Oh My Pi
≥16.3.15, inbound `spt send` bodies arrive EMPTY to the live session — the agent sees
self-closing `<msg from="peer"/>` frames with no text; the full body lands only in the raw
`owl_message`/digest. Confirmed reproduced locally.

## Root cause (confirmed, repro'd)

Native delivery is two-part: submit a self-closing **stub** `<msg from="peer"/>` to wake the
turn, then at the context boundary `injectEnvelope()` splices the real body in by an
**exact-string match** — `messageText(message) === item.stub` (`omp-spt.mjs`, since native
cutover `94f4d02`). When newer OMP echoes the submitted user-message text non-verbatim
(leading whitespace, wrapping, or tag re-serialization), the match misses, `index<0`, and
`injectEnvelope` returns the messages unchanged with **no fallback** — the body is silently
dropped from the turn.

- NOT a 0.3.20 code regression: the fragile match predates it. 0.3.20's required OMP
  ≥16.3.15 bump merely exposed a latent exact-match fragility.
- The 0.3.20 delivery watchdog correctly does not fire: the stub still triggers a turn, so
  the session is not "deaf" — this is a body-drop, a distinct failure.

## Decision

Match the stub by its **identity signature** (`from` + `delivery` attributes), not by byte
identity. The signature is exactly what already makes stubs unique per pending item, so
signature matching preserves the newest-occurrence correlation guarantee
(`testListenerEnvelopeTargetsNewestMatchingStub`, same-peer `delivery="2"`, orphan-stub
rejection) while tolerating whitespace, surrounding text, and `<msg .. />` / `<msg></msg>`
re-serialization. Preserve the return-identity-on-miss contract the context loop depends on.

## Tasks

1. `REQ-HAZARD-DELIVERY-BODY-INTEGRITY` in `traceable-reqs.toml` (doc/impl/unit) +
   KNOWN-HAZARDS entry.
2. `parseStubSignature()` helper; rewrite `injectEnvelope` match to compare signatures.
3. Regression tests: echo drift (leading newline, wrapping, self-closing↔paired tag) still
   injects body; distinct same-peer deliveries stay correlated; genuine miss still returns
   messages unchanged.
4. Version bump 0.3.21 across manifest/package/Cargo/docs; CHANGELOG; finding note.
5. Gates: `node --test tests/omp-extension.mjs`, `sh ci/run-gates.sh`, `traceable-reqs check`.

## Gate

All existing tests still green (correlation unbroken); new echo-drift tests fail before the
fix and pass after; deterministic gates + traceability green.
