
## Gate fixups rounds 2+3 @ 3037b2c9 (2026-09-27, todlando)

Subject: `feat/351-w4-shells` = **3037b2c9f67161fffda9251ae163942ed2d66620**, tree **a2bc100a477f1f53e43f0ef4cc3c90721bf2a70c**. Chain: 8cea2af4 → 71a676a1 (round 1) → cc81fd2c (round 2) → 3037b2c9 (round 3). **cc81fd2c did not compile its tests**: two `OutboundRow` test literals were missing `met_vacancy`. Fixed in 3037b2c9. No run was taken at cc81fd2c.

### What changed
- **D1 / R3-1 / R3-2: the fate of a row is keyed on `met_vacancy`**, a new spool column (`INTEGER NOT NULL DEFAULT 0`, additive).
  - **How a row gets the mark:** it is set at APPEND when `submit`'s resolve finds no active owner. A drain pass that finds no active owner also sets it on every pending row.
  - **A row that met a vacancy:** kept for audit once delivered. A live-only one HOLDS when the owner is not live.
  - **Any other row:** deleted once delivered.
  - **On a not-live answer:** every pending sensory row that never met a vacancy is dropped unshipped (`drop_not_live`, order-neutral). Vacancy rows and text rows wait.
  - **Condition-4 growth claim, restated:** the queue keeps rows ONLY for vacancy traffic, and contended or active-not-live traffic leaves zero rows (unit: 50 contended emits → 0 pending; with a held vacancy head → exactly 1 pending).
- **D2:** `receive_wan`'s live-only branch requires STAMPED traffic (`shell` marker AND `sender_proven == target`) and publishes MSG_IN (peer = shell id). Unstamped marked traffic takes the ordinary path, warning included.
- **R3-3:** `fate` never claims what it did not see. A row another drain took reads `Submitted::Handed`, printed as `SENSORY_HANDED:` / `HANDED:<owner>` with exit 0, and documented in api.md.
- **R3-4:** a shell text send whose body is a sensory EVENT (bare, or as the committed msg envelope's body) is refused with `SHELL_SAY_REFUSED:`. **D3:** both nodes key live-only on the BODY (`shellout::is_sensory_frame`), with a unit that goes red if `ship_local` reverts to `row.kind`.
- **F3-gap:** the pure `ship_for_reply` seam, now with its redial arms asserted.
- **G3:** `SendTriggerFacts` named fields.
- **D5:** local sensory is named at-least-once.

### Battery (all at 3037b2c9, dirty=0)
- `cargo clippy -j 8 -p spt-store -p spt-daemon -p spt --all-targets -- -D warnings`: rc 0. The run was taken on the working tree just before the commit, and the commit's tree is identical to it.
- `cargo build -q -j 8 -p spt --bin translate_proof_fixture`: rc 0. Then `cargo nextest run -j 8 -p spt-store -p spt-daemon -p spt --lib --bins --test shell_outbound_local --test twohost_axes --no-fail-fast`: **2658 run, 2658 passed**, 1 slow, 1 leaky (`broker::tests::windows_session_is_zombie_sees_a_handle_held_corpse_as_dead`, LEAK, passed), 1 skipped. rc 0, wall 633 s. Log `%TEMP%\w4r3-nextest.raw`.
- `cargo run -q -j 8 -p xtask -- check`: see below. `traceable-reqs check` on `git archive HEAD`: see below.
- **Two-host cell 7 at 3037b2c9: rc 0 on BOTH hosts.**
  - A = HFENDULEAM, exe `twohost_axes-e1074e95806ab0cf.exe` (built 00:37:17, after the commit), `rc=0 wall_ms=63491`. Log `<scratchpad 7c736928>\351w4-w4r3-a.raw`.
  - B = kitsubito, HEAD read back as 3037b2c9 (from bundle `~/w4r3.bundle`), exe `twohost_axes-06ae70918887d2cb` rebuilt 00:35:33, `rc=0 wall=68.88`. Log `kitsubito:~/351w3-w4r3-b.raw`.
  - Per-cell: 7a B `(102 ms)`; 7b on both; 7c A `(533 ms)`, B `in order (409 ms)`. The 7a not-live drop leg and 7d are assert-only, and both roles reached `ok`.
