# IDLE-EDGE W1 — JIT plan (doyle, 2026-07-24)

Contract authority: **ADR-0048** (docs/adr/0048-idle-edge-contract.md) + CONTEXT.md
entries stamped 2026-07-24 (activity observation · digest turn sealing · cross-node
instance resolution · digest cross-node pull-first). REQ set (all ACTIVATED at mint,
registry tail): `REQ-ACTIVITY-{LINK-PUSH,INFO-PULL,LIST-JSON}` +
`REQ-DIGEST-{SEAL-ON-IDLE,CROSS-NODE-PULL}`.

**Binding external contract:** perri (spt-rebound-tool) holds the locked activity
contract (lock message SENT 2026-07-24, perri building against it — sole blocker on
their critical path). ADR-0048 decisions 1–3 are not renegotiable during build; any
forced deviation goes back through the operator BEFORE code.

## Build order (dependency-driven)

1. **Leg A — activity push (REQ-ACTIVITY-LINK-PUSH).** Highest priority: perri
   hard-blocked. Daemon observes idle-sentinel flips (bounded observation — the
   contract does NOT require report-path plumbing; ship the simplest observer that
   meets sub-second class) and emits the activity frame on the owner's shell links:
   drive-class, current-state + transition timestamp (sentinel flip time), re-emit
   current state on every (re-)link. Extend the published shell frame vocabulary doc
   (REQ-SHELL-FRAME-VOCAB lineage — doc stage evidence lands there; docs are
   drift-gated). **Notify perri with frame name/attrs the moment the vocab doc
   settles** — they fill in their decoder + E2E from published docs, not from us.
2. **Leg B — pull surfaces (REQ-ACTIVITY-INFO-PULL, REQ-ACTIVITY-LIST-JSON).**
   Small, additive keys; both read the same sentinel truth Leg A observes. Public
   docs: additive-evolution note; NO internal codes in clap help (xtask gate).
3. **Leg C — digest seal-on-idle (REQ-DIGEST-SEAL-ON-IDLE).** Rides the same
   idle-edge observation Leg A builds — one observed flip, two effects (frame emit +
   trailing-turn seal). Idempotent, seq-stable, straggler-tolerant; next-input seal
   demoted to no-op fallback. Int rig = the liam field shape RED-first
   (finish-turn → idle → no further prompt → scanner sees sealed seq).
4. **Leg D — cross-node digest pull (REQ-DIGEST-CROSS-NODE-PULL).** Lift the
   CROSS_NODE_M4 refusal for the digest snapshot verb (+ `--after`) under the
   existing address gate; delta stream untouched (stays node-local). Two-node int
   rig. Independent of A–C except that seal-stability makes remote `--after`
   trustworthy — land after C so the int rig can assert against sealed seqs.

## Gates (every leg, before "done")

- Tests authored via the **spt-test-engineer** subagent (standing rule); timebox
  every background test run with hard timeouts + proactive log checks (no alarm
  mechanism on this host; silent wedges). Kill stale `spt_daemon-*` orphans before
  `spt-daemon --lib` suites; CI is authority for that suite on this box.
- Workspace clippy in CI form; rebuild the real `spt` binary (not just cargo test);
  `traceable-reqs check` exit 0 (all five REQs evidenced) before PR.
- Evidence tags in the SAME commit as the evidence, on/above it — never file-top.
- Docs regen (reference.md + docs-site) drift-gate green; public help stays free of
  REQ-*/ADR-#### codes.

## Ship + verify loop

- PR off this branch (`build/idle-edge-w1`, based on fetched origin/main) → CI
  two-leg green → merge → **dedicated release PR only** (RELEASE-RUNBOOK; the
  lockfile bullet — both paid incidents same direction) → deployah publish next
  counter → `spt update apply` on HFENDULEAM.
- **Field verify, three consumers:** perri — live idle-edge→ping loop E2E against
  the real seam (their M1 rig is ready and mock-swappable); liam — scanner-sees-
  latest-turn re-verify, then retire their drive-one-more-command workaround note;
  flynn/spt-mobile — informational: cross-node digest pull unblocks the
  SPT-CORE-NEEDS cross-node digest ask (pull leg only — say so plainly).
- Close the backlog seed (spt-core-findings-backlog.md perri section) with the ship
  counter + field-verify verdicts.

### Field-verify verdicts (v0.42.0, closed 2026-07-25)

- **perri — PASS.** Live idle-edge→ping loop E2E against the real seam.
- **flynn/spt-mobile — PASS** (informational leg: cross-node digest pull).
- **liam — RECUSED, not failed** (doyle canon, W1 closed at counter 76; supersedes my
  earlier "no-count / invalid instrument" wording). liam's endpoint has not sealed a turn
  since ~05:20 2026-07-24 (`--last 1` = one open turn, `input_seq=null`, 37 entries
  accreting); scanner skip-partial then correctly skips it, so no tag ever reaches
  the scanner. Predates 0.42.0 (same failure under old next-input sealing, W16), so
  it is NOT a seal-on-idle regression. Measured on a stale shell (old `target/debug`,
  since swapped to released 0.2.0) and with daemon version/restart state unconfirmed
  — two discriminators were owed. **Discriminator (a) daemon-version/restart: RULED
  OUT 2026-07-25.** Same daemon (pid 54156, broker image 0.42.0), two co-located local
  endpoints read back-to-back: flynn `input_seq=201863463073` with real per-entry seqs
  (seals every turn), liam `input_seq=null` / 39 entries (never seals). Core seal path
  + daemon proven healthy on that node by the co-located PASS → **spt-core exonerated
  for this fault**; owner is adapter-side (extraction / session-identity-or-digest-
  source binding for liam's session). Seq-scheme detail: flynn's is epoch-ish, liam's
  last good seal was the small counter `8` — i.e. pre-swap scheme, consistent with the
  extraction path chasing a pre-rotation source while entry-append survives.
  **Discriminator (b) fresh session = remaining live hypothesis and likely fix**
  (liam's running CC session loaded the pre-setup adapter/hook binding and cannot
  rebind live); requires an OPERATOR action to restart liam's live session. Still
  `input_seq=null` after a fresh session → escalate back to core. Tracked as doyle's
  `SEAL-DUAL-TRIGGER-ABSENCE` (P2, RCA-first) — single authoritative record; no
  separate Request. liam's relay-lag observation RETRACTED as a contaminant.
- **My RCA input (sent to doyle):** the "dual absence" is probably NOT dual — seal-on-
  idle stamps a trailing turn whose identity comes from the extracted Input record, so
  "no Input extraction since the boundary" fully explains "idle seal not firing" and
  the seal correctly no-ops. One cause, two symptoms; RCA extraction FIRST, not the
  seal effect.
- **If a fresh session fixes it, the fault is NOT closed:** it would mean `/sptc setup`
  mid-session leaves the session's extraction permanently broken, silently, with no
  warning (2 days undetected here). The adapter owes either a live rebind or a loud
  RESTART-REQUIRED-class notice at setup completion.
- **drive-one-more-command workaround note: RETIRED** (todlando ruling 2026-07-25) on
  the two PASS legs; replaced by a fault-shaped line — `input_seq=null` on the newest
  turn means the endpoint is not sealing at all (endpoint-level fault, check daemon
  version + restart first), not a scanner problem.
- **RCA CONFIRMED adapter-side; mechanism found (perri probe, 2026-07-26).** A
  mid-flight-activated session binds its perch to a SYNTHETIC sid: core takes the
  session id from the BRINGUP process's `OWL_SESSION_ID`, and that env cannot be
  written mid-session (`CLAUDE_ENV_FILE` is SessionStart-only) — so `/reload-plugins`
  (restores hooks+skills but never re-registers the session) and `/clear` both leave
  the binding dark FOR GOOD, and re-seeding does NOT heal it. Hypothesis (b) was the
  right live one; core exoneration stands. The "adapter owes a live rebind or a loud
  notice" obligation is being paid: fix item 1 landed adapter-side @ecc6e10
  (built + probe-verified, NOT yet released) = seed + a once notice + an explicit
  bringup command injected on every ready/live turn (both forms probe-verified —
  necessary because a live rebind is impossible by the SessionStart-only mechanism
  above). `SEAL-DUAL-TRIGGER-ABSENCE` stays OPEN until liam's endpoint seals under
  the fixed adapter in the field; that same fresh-session return also closes the
  held STALE-ONLINE relink specimen (REQ-HAZARD-SHELL-STALE-ONLINE field verdict) —
  one return, two threads.
- **CLOSED 2026-07-26 (doyle ruling; the double harvest fired).** Adapter v0.25.12
  (ecc6e10 + cf6267c) released; liam's endpoint started fresh under it
  (operator-authorized, `endpoint run --create --start`, session fd91c6b04b0adc58).
  Field-close gate met by the designated authority: perri's `digest liam --last 3`
  read every input-bearing complete turn SEALED (input_seq 4294967499 and 8589934592,
  non-null), with the in-flight turn showing the correct partial=true signature and
  the input_seq=None non-partial rows correctly discriminated as Boundary/Context
  pseudo-turns (no Input record exists to seal from — honest no-seal, not the fault).
  liam corroborates: first sealed turn of the fresh session on record. liam is
  mint-capable again; the hard dependency lifted with the same return that harvested
  the relink specimen. RESIDUE, filed separately (liam's find, their lane): the old
  dark session's unsealable turns leave permanently-unfirable rows in a live window —
  a scanner jumps them without any possible missed-rows notice because a generation
  bump is not a window slide (floor test correctly false). Ruled 2026-07-26:
  scanner-side announce for knowingly-jumped INPUT-BEARING null-seq turns is the fix
  shape (alchemy lane); pseudo-turns (input=None) are tagless by construction and
  jumping them silently is CORRECT. DISCRIMINATION DONE same day (liam, raw rows +
  full-window census): class real, concrete rows discriminated to sub-shape (i) and
  DISMISSED — both are the session seam itself (boot Boundary + psyche_download
  Context, input=null, stamped at the fresh session's boot instant), not dark-session
  survivors; sub-shape (ii) count over the whole retained window = ZERO, and every
  input-bearing gen-1 turn carries a non-null seq — the prior session's typed turns
  are sealed on record, so the feared dark residue did not survive into the live
  window (a further corroboration of this closure). Tagless-by-construction proven
  two independent ways (no input text exists to carry a tag; the scanner extracts
  from Agent entries only — Boundary/Context are never read). (ii) STRENGTHENED at
  close from unwitnessed to UNREACHABLE BY CONSTRUCTION (liam, line-evidenced, both
  assignment sites grep-confirmed): under `project_timeline` as it stands, an
  input-bearing turn is BORN with its seq (projection.rs:343-350, no omitting branch)
  and the only clearing site blanks seq ATOMICALLY with partial=true on the trailing
  turn of a non-idle endpoint (439-441; the idle path returns first, so sealed turns
  keep Some(seq)) — so non-partial + input-bearing + null-seq cannot be produced,
  and liam's own earlier existence-proof (dark-session turns as (ii) specimens) is
  WITHDRAWN by its author: those were partial turns, the ordinary open-turn case.
  The scanner announce is therefore a TRIPWIRE against a future projection
  regression (another digest producer, or a refactor that blanks seq without setting
  partial), not a plug for a live hole — file and prioritize it as such. This also
  independently re-justifies the no-live-manufacturing ruling: the shape cannot be
  produced on a live node at all, so the hand-authored rig fixture is the ONLY
  red-first path, not merely the preferred one. Core provides sufficient discrimination data
  already (input + input_seq + partial per turn) — no core REQ minted for the
  residue. liam's stated error pattern (read one field, infer the record — same shape
  as their derived-view misread) recorded with their correction; it is the
  REQ-SHELL-LIST-DERIVED-PROVENANCE class from the consumer side.
- **Carried forward (next wave candidate, not scoped here):** a silently never-sealing
  endpoint is undetectable without manually reading `--last 1`. Warn surface for
  "newest turn open beyond N" — real gap liam surfaced. Banked by doyle as
  `NEVER-SEALING-OBSERVABILITY` with a binding guard: open-beyond-N is a **DIAGNOSTIC
  only** — heuristics stay banned from driving sealing itself (ADR-0048 line holds).

## Explicitly NOT in this wave (ruled 2026-07-24 — do not scope-creep)

- #70 leg (b) cross-node shell drive — queued immediately AFTER this wave (rulings
  banked in backlog + CONTEXT.md: local-first resolution, refuse-ambiguous only
  multi-remote-no-local, `ref@node` exact, node-qualified `persistent` co-bringup).
  Leg (a) spawn-on-named-node deferred until a remote-instantiation consumer exists.
- Planning-direct items (no grill owed): #61 loud-refusal + `--`, #62 stdin shell
  send body, #63 teaching arity refusal, stale listener registry row prune,
  subnet.json crash safety (RCA-first), echo provenance tiering, daemon-at-boot
  bootstrap rider.
- Backlog: EVENT-PART conformance probe + `--disable-chunking` listener opt-out;
  digest delta-stream cross-node.
