# doyle pre-gate review, #345 W2 @37e8900c (read-only diff vs da5b3415), 2026-09-26

The lane matches the WIP I read at da4676ec, plus the condition-4 test edit.

## F1: FIX REQUIRED. The R4-9 self-send guard keys ONLY on the session-proven id
cli.rs passes `session_proven.as_deref()` as `sender`. When `roster::detect_self_id()`
returns None (no OWL_SESSION_ID perch match and no SPT_AGENT_ID, e.g. a send spawned
from a hook or adapter subprocess outside the session env), a bare send to the
sender's own id enters the resolver. It can then cross to an active sibling. That is
exactly the unwoken-recharge failure R4-9 forbids.
Fix: when the proven id is absent, use the resolved `from` label for the self-id
EQUALITY check only. This is safe although admission keys on the proven id: this
branch can only KEEP the send local (today's leg), so an unproven label gains nothing.
Unit: sender unproven + from == bare target + an active far sibling => Local.
ALSO MEASURE, do not assume: name the process that sends the recharge wake (claude-spt
wake fire) and whether detect_self_id resolves inside it. Record both in the lane notes.

## F2: RELEASE NOTE. The Ambiguous arm now refuses where the local leg used to spool
A local instance that is suspended or offline, plus >=2 far dormant instances, now
exits AMBIGUOUS (code 1) before the local leg. Before, the send spooled locally. This
is S6 as ruled (suspended ranks below dormant). Name it in the same release-note line
as condition 1.

## Checked, OK
- Fail-open: daemon down => empty regs => bare target Unresolved => today's leg.
  Qualified-own-node still routes Local.
- Activation trigger skipped for a wan-pinned send (a dormant local must not take
  active for a sibling's message). Correct.
- rc attach pins both the dial and the reconnect to the resolved node. Correct.
- with_local_view never borrows the sibling's uid for a synthesized own row. Correct.
- Liveness: effective_rest_of folds is_perch_alive, so a dead local perch does not
  rank as Active.
