# Census raw: releases#350 "shells follow active" (subagent, read-only, sha 91fe5f30)

Written by todlando from the subagent's returned report: its session was read-only, so it could not save the file. File:line citations are the subagent's, not re-read. My own direct reads are in census-raw-todlando.md.

## A. Shell→owner paths
- **A1 Sensory**: `spt api emit` → `crates/spt/src/api/reporting.rs:565` `cmd_emit`.
  - Owner = `find_shell_by_token` (`shellhost.rs:603-616`), which scans the LOCAL owlery only.
  - Type is checked against `[shell.sensory].types` (:585-602).
  - Frame: `shellchan::compose_sensory_frame` (`shellchan.rs:126-132`) → `<EVENT type="sensory" from="<shell-id>" sensory-type=...>`.
  - Transport: `is_online(owner) && deliver_tcp(owner, "", frame)` (:605-606). The wire `from` is "". There is no spool; otherwise it prints SENSORY_DROPPED, exit 0.
- **A2 Text**: an ordinary `spt send <owner> --from <shell-id>` (`shellchan.rs:15-16`, `frames.md:136-139`, `spt-proto/src/event.rs:58-59`).
  - Route: `cmd_send_verdict` (`cli.rs:13360`). `resolve_from` is at :12918. pre_route runs at :13451 → `resolve_among` (`spt-net registry.rs:1109`): active first (:1134-1143), then warm (dormant before suspended, :1146-1154). A remote answer pins the WAN leg (:13453).
  - The dormant gate is at :13468-77, and the local admission gate at :13491.
  - `admit_message_trigger(target, sender_proven.unwrap_or(from), window)` runs at :13691, only when `wan_pin.is_none()`. A shell-id sender therefore gives `RestEvent::Wake` (`resting.rs:267-276`), a STEAL.
  - Local deliver is TCP, else a spool into the owner perch (`deliver.rs:135-146`). The WAN leg is `wan_send` (:13892/:13902).
- **A3 File**: there is NO shell→owner file primitive. `shell send --file` goes owner→shell only (`cli.rs:26470-26550`). The only way up is send `--attachment` (ADR-0058 pull model, `attach.rs`).
- **A4 Other**:
  - `cmd_drive_poll` (`reporting.rs:628`, owner→shell).
  - `cmd_tunnel` (:713): shell bytes into a broker tunnel, same-node (REQ-SHELL-4; `tunnel_e2e.rs:235-239`).
  - `cmd_owner_shutdown` (:794): a rest event, not a payload.
  - `cmd_poll_shell` (`delivery.rs:697-724`): owner→shell drain.
  - The mock emitter is at `adapters/mock/src/shell.rs:10,205-222`.

## B. Owner-side receive
- Sensory arrives with wire from="". `message_trigger` returns None for an empty sender (`resting.rs:262,268`; test :1210 "shell frames"). `cmd_emit` never calls admit_message_trigger.
- Text with `--from <shell-id>` is classified Wake at local admission AND at WAN admission (`wan.rs:1363-1374`, sender = `sender_proven.unwrap_or(from)`).

## C. Cross-node primitives
- `WanMessage` (`wanmsg.rs:104-150`): target, from, body (opaque; a typed EVENT rides verbatim), op_id, sender_proven?, sender_origin?, handoff.
- `wan_send` / `wan_send_with` (`wansend.rs:644-697/700`).
- `receive_wan` (`wan.rs:1269`) runs in this order: gate :1289-1309 → perch :1335 → wan_seen :1344 → trigger :1363-74 → deliver or spool.
- `shelllink` (`spt-net shelllink.rs`): RELINK/CMD/DRIVE, all owner→shell one-shot. `wan_shell_link` (`wansend.rs:1505-1549`), where @node = the SHELL's node.
- NO cross-node shell→owner frame exists. The sensory wire form is local only (`event.rs:64-67`).
- `forward_wake` sends a REST_EVENT_WAKE via resthost (`shellwake.rs:470-513`).

## D. Spool + activation visibility
- `spt_store::spool` schema (`spool.rs:158-214`, plus `wan_seen` :220-227). TTL 0 = infinite (:26-28); `purge_expired` acts only on a finite TTL (:576-584).
- **No row or size cap exists in spool.rs.** The only cap is wire `MAX_MESSAGE_BYTES` = 16 MiB (`spt-msg wire.rs:21`). So "the existing spool bounds" = infinite TTL + a 16 MiB per-message cap.
- The shell perch spool is `perches/<owner>/shells/<adapter>-<n>/spool.db` (`STORAGE.md:40`). It is INBOUND owner→shell only:
  - `spool_shell_frame` (`shellchan.rs:337-347`, from_id "") writes it.
  - The drain is relay `cmd_poll_shell` or stdin `deliver_stdin_pending_in` (`shellchan.rs:356-450`: peek, send_effect, mark_delivered).
  - Restamp on rotation: `restamp_pending_at` :298, `restamp_for_drain` :321.
- "Outbound spool" has zero code hits.
- Existing drain triggers:
  - `inject::drain_idle_spool` (`inject.rs:128`)
  - `shellwake::reconcile_once` (~5 s tick, `shellwake.rs:906`)
  - the `request_advertise_now` marker (`registryhost.rs:1352`) → pump
- Activation-visible hooks:
  - `dispatch.rs:1407` `commit_feed_batch` → `apply_feed_batch` claims; today it only demotes outranked local Active (:1423-1446).
  - `resting::daemon_sibling_activated` (:810-844) and `daemon_rest_event` (~:790-806) both call `cascade_shells_on_edge` + `request_advertise_now`.
  - `sibling_view(_from)` (:634-659) gives active_sibling + max_activation, excluding the own node.
  - `siblings.rs:92-96` `SendHead::{Local,Pinned,Shell}`; `dormant_send_refusal` (:112) refuses Shell while dormant (:144).

## E. Wake-watcher (`shellwake.rs`)
- `WAKE_OPCODE` = 86 (:42). `watcher_run` (:265-342) gives up after 6 backoffs.
- `resolve_wake` (:364-437); its doc at :344-360 is STALE (D4 wording).
  - No local owner info.json: `remote_owner_node` (:444-464) picks by highest last_active_ms. That is a RECENCY pick, not active. Then `forward_wake`, reply "stays offline here (cross-node shell link lands at D8c)", else WAKE_NO_REACHABLE_INSTANCE.
  - Local owner: Active → nothing. `active_elsewhere` → left in place. Dormant or Suspended → Wake → active. Then the `live_launch_winner` guard, then `launch_shell`.
- Tests:
  - `resolve_wake_wakes_a_dormant_owner_unless_active_elsewhere` (:1573-1628) [unit REQ-SHELL-2, REQ-ACTIVATION-TRIGGERS]
  - `resolve_wake_revives_a_suspended_owner_without_double_launch` (:1636)
  - :1526, :1558

## F. presence::addressed_target (`presence.rs:214-229`)
- `resolve` (:106-157) is an MRA over local live perches plus routable rows carrying last_active_ms. `routable` = !Offline (`registry.rs:576-578`), so dormant and suspended are eligible. It is NOT active-first.
- Callers: `notif.rs:335` (Node scope, empty regs) and `notif.rs:339` (Subnet). Neither falls back (:324-330).

## G. REQs
- REQ-SHELLS-FOLLOW-ACTIVE (:8123) `[]`; REQ-SHELL-OUTBOUND-SPOOL (:8128) `[]`.
- REQ-SHELL-1 (:1232) impl/unit/int. Its TITLE goes STALE ("sensory REST-only never spooled + dropped-unless-owner-live").
- REQ-SHELL-2 (:1236), REQ-SHELL-3 (:1386), REQ-SHELL-4 (:1390), REQ-SHELL-5 (:1398).
- REQ-ACTIVATION-TRIGGERS (:8098; clause 5 = the watcher lands active), REQ-DORMANT-SEND-RESTRICTION (:8118), REQ-RESOLVE-ACTIVE-FIRST (:8173), REQ-SEND-RESOLVES-BEFORE-LOCAL (:8178), REQ-INSTANCE-AXIS-SPLIT (:8088), REQ-PRES-1 (:1228).

## H. Stale tests/docs after the change
- Units:
  - `cli.rs:36638` `shell_channels_relay_sensory_and_text_file` asserts sensory drops WITHOUT spooling (:36754-67).
  - `shellchan.rs:636`, `resting.rs:1210`, and the shellwake tests.
- Ints: `shell_e2e.rs` (:206-217 sensory live), `gateway_owner_shell_e2e.rs:303-307`, `tunnel_e2e.rs:235-239`, `shell_sleepwake_e2e.rs:114,130`.
- Two-host: `twohost.rs` seeds are owner→shell only (:790, :874); `twohost_axes.rs:1033` covers the dormant restriction. There is NO two-host shell→owner rung.
- Docs:
  - `frames.md:136-139, 191-202`
  - `shells/overview.md:25-27, 39-40`
  - `getting-started.md:110-113`
  - `harness-contract/api.md:654-659`
  - `manifest.md:1001, 1021`
  - `cli/reference.md:2172-73, 2705-15` (generated from `api/mod.rs:268`)
  - `docs/MANIFEST.md:842`
  - `STORAGE.md:40, 44`
  - `CONTEXT.md:206, 347, 402-409`
  - `event.rs:58-67`, `shellchan.rs:13-21, 125`, `reporting.rs:555-562`, `shellwake.rs:344-360, 383-384`
