# CONDUIT W2 — releases#228: a shell whose owner was not up at the boot sweep stays down forever

Branch `fix/228-owner-online-restore`, worktree `.worktrees/conduit-w2`, off main `f1395b6a`.
doyle RULED on releases#228 (comment: SaberMage): shape **(c) APPROVED with conditions**, (a) not
built if (c) lands, (b) REJECTED (ADR-0048 untouched).

## The defect (measured, not the ticket's words)

The boot sweep's owner-online conjunct is correct and its ONCE-ness is the bug: an owner endpoint
that comes online AFTER the sweep is never revisited (bringup produces no rest edge either), so its
`persistent` shells stay down until a human relinks. Whether a boot works is an ordering accident.

## Build

1. `OwnerOnlineEdge` — per-owner online state carried across reconcile passes; EDGE (offline→online
   since the last pass), never level. A failing launch under a level trigger would retry every 5s
   forever; the edge bounds it to one attempt per owner-online event.
2. The refusal arms are carried VERBATIM by construction: one shared per-owner body
   (`restore_persistent_shells_of_owner`) that BOTH triggers call — persistent-only, owner online,
   down in fact via the derived read (pair test), stamp present, launch predates boot, no boot
   oracle ⇒ restore nothing.
3. Seed the edge BEFORE the boot sweep, not after: the safe direction. Seeded-after loses an owner
   that came online between sweep and first tick (a real miss); seeded-before can at worst re-attempt
   an instance the sweep already restored, which the RESTAMPED BIRTH STAMP then refuses.
   Measured, not assumed: down-in-fact is NOT the arm -- a launch is not the online switch, so a
   just-restored instance keeps an `offline` record until its bind-shell handshake and still reads
   as down in fact; the launch moving `launched_ms` past the boot instant is what refuses it.
4. Distinct event name per trigger (`SHELL_OWNER_ONLINE_RESTORED` vs `SHELL_BOOT_RESTORED`) — the
   field evidence on this ticket came from counting those events; a shared name would blind the next
   investigation to which trigger fired.
5. Mutual exclusivity: mid-generation a watcher CAN already be armed for the casualty (the reconcile
   start side has no owner-online conjunct), so the edge path stops the watcher before launching.
   The boot sweep passes none — no watcher exists before the loop's first tick.
6. Fix the contradicting `spawn_wake_host` comment (~:898-903) in this lane: it claims the once-ness
   protects the force-kill ruling, which `reconcile_once` (~:815-823) records as having moved to the
   discriminant, and which is mechanically false (a shell killable this boot was launched this boot).
7. Sweep the doc-stage text that states the boot sweep as the ONLY trigger: `CONTEXT.md` §persistent,
   `docs/KNOWN-HAZARDS.md` 2.7 (entry + table row), `docs/MANIFEST.md` §Sleep/wake.

## Registry

Mint + activate `REQ-SHELL-OWNER-ONLINE-RESTORE` (doc/impl/unit). Test evidence also tags
`[unit->REQ-HAZARD-RESTART-STRANDS-PERSISTENT-SHELLS]` + `[unit->REQ-SHELL-PERSISTENT-BOOT-RESTORE]`
per the ruling.

## Hazard test — two arms in ONE fixture (doyle holds me to my own BAROMETER W2 warning)

Owner OFFLINE at the sweep (sweep spends, restores nothing) → owner flips online → edge pass:
- POSITIVE: the restart casualty (stamp predates boot) is RESTORED, with no rest edge anywhere.
- NEGATIVE: a sibling force-killed THIS boot is NOT restored. A single-instance fixture cannot tell a
  correct trigger from one that restores everything.

## Battery

`cargo run -p xtask -- check`, `traceable-reqs check`, targeted nextest on `spt-daemon` shellwake,
clippy on BOTH OS (Linux via `reavus@kitsubito`, `export PATH=$HOME/.cargo/bin:$PATH` first, echo the
sha in the SAME command). Read every verdict from its own `.exit` file, never a wrapper's status.
