---
name: m11-w4-progress
description: "M11-W4 Gateway-owner shell capstone (REQ-SHELL-5) — built, merged, awaiting CI green + doyle gate"
metadata: 
  node_type: memory
  type: project
  originSessionId: 5b0a69e3-d6a3-47f7-8152-ee14e5b4ff5c
---

M11-W4 = REQ-SHELL-5 (shell ownership owner-type-agnostic), the LAST build wave
before W5 (rig + docs). PROOF-NOT-CHANGE: T0 audit found no type-gate on any
ownership path; W4 proves it E2E + activates unit/int. ZERO production diff — held.

**Built (2026-06-15/16):**
- int: `crates/spt/tests/gateway_owner_shell_e2e.rs` — a `state="gateway"` owner
  succeeds on EVERY path same-node (spawn→bind+SHELL_TUNNEL_OPEN→cmd(durable)→
  drive(latest-wins)→tunnel(opaque bytes both dirs)→act-gate(REQ-CONSENT-3 grant
  keyed on the gateway endpoint-id)→relink). NEGATIVE (doyle gate-blocking
  refinement): gateway-B SAME type="gateway" DIFFERENT id refused on cmd/drive/
  tunnel (NO_SHELL/NO_TUNNEL) → exclusivity keys on owner endpoint_id, not type.
  Harness = union of tunnel_e2e + drive_e2e start_inproc_daemon (seed + broker-
  with-net + tunnel ctrl + drive ctrl). relink needs offline → close_shell first.
- unit: `linkhost::gateway_typed_owner_resolves_and_drives_keyed_on_id_not_type`
  (resolve_link_target/run_action resolve+drive gateway owner opaquely; same-type
  different-id → NoShell at resolution layer). NOTE: a pre-existing
  `shellhost::gateway_typed_owner_spawns_and_owns_a_shell` is tagged [unit->REQ-EP-6].
- REQ-SHELL-5 activated [doc,impl,unit,int], traceable EXIT=0.

**doyle GATE: code-read PASS + tree-identity confirmed — W4 PRE-CLEARED.** Only
remaining input = CI green. No further code review needed (he said so).

**CI saga:** branch had fallen 15 behind main (doyle's v0.7.2/v0.7.3 release churn)
→ UNMERGEABLE → GitHub created ZERO pull_request runs (NOT a webhook drop — see
[[unmergeable-pr-blocks-ci]]). FIXED by merging origin/main (1 real conflict:
FLAKE-LEDGER union; rest auto-merged; regen reference.md). Merge HEAD = 63a5d3e
(gate HEAD now). Branch at v0.7.3. PR #16. CI run 27599789430 queued.

**NEXT:** on CI green → ping doyle → he stamps W4 GATE PASS. If attach_survives
times out on kitsubito = FLAKE-LEDGER #7, `gh run rerun <id> --failed`. Then W5
(M11-PLAN T5.x): drive/tunnel [twohost] rungs + how-to subnet (REQ-DOCS-6) +
ADR-0020 tunnel EVENT-exemption enumeration + on-LAN posture docs. Supersedes [[m11-w3-progress]].

---
**doyle GATE VERDICT (2026-06-16): W4 PASS — STAMPED.** Independently confirmed CI run 27599789430: conclusion=success, headSha=63a5d3e (gate HEAD), all 5 jobs green both runners (test+n1-gate x2, traceability; twohost skip expected), attach_survives clean (no flake, no rerun). Delta-rechecked the merge: W4 code (gateway_owner_shell_e2e.rs + linkhost.rs) byte-UNCHANGED across 63a5d3e → my code-read PASS held verbatim. PROOF-NOT-CHANGE confirmed (zero production diff; the gateway-B same-type-different-id refusal is the load-bearing negative). **M11-W4 CLOSED.** todlando CLEARED to W5 (the last M11 wave). PR #16 stays unmerged until the M11 milestone release (after W5). LESSON: an UNMERGEABLE PR silently gets ZERO CI runs — check mergeable state before blaming a webhook ([[unmergeable-pr-blocks-ci]]).
