# RESIDENT-SERVICE W1 — JIT plan (doyle, 2026-07-26; builder: todlando)

Contract authority: **ADR-0049** (docs/adr/0049-resident-service-substrate.md) +
CONTEXT.md entries **ResidentService** / **AlwaysOnEndpoint** (re-based) +
`REQ-RESIDENT-SERVICE` (registry — the full int gate is specced IN the req title;
treat it as the acceptance list, not advice). Design grilled with the operator
2026-07-26 (grill-with-docs); flynn reviewed as first consumer and the record is
drift-free from alchemy's facts — do NOT re-litigate ratified decisions; a forced
deviation goes back through doyle/operator BEFORE code.

**Step 0 (todlando, first commit): ACTIVATE** `REQ-RESIDENT-SERVICE`
(`required_stages = ["doc","impl","unit","int"]`) — rule 5, activation belongs to
the milestone start. Evidence tags land with their evidence, same commit, never
file-top.

## Build order (dependency-driven)

1. **Leg A — manifest + registry.** `[service]` section parsing in the adapter
   manifest (binary spawn spec, `start = "boot" | "bind"`, `stop_grace_ms`
   default ~30s), per-adapter-option service identity model. Doc stage rides
   docs/MANIFEST.md (drift-gated). No internal codes in any public help (xtask
   gate).
2. **Leg B — supervisor substrate.** Daemon-side: job-neutral spawn
   (`detached_no_inherit` + the existing cold-start ladder posture), child-handle
   liveness (derived, NEVER a running-record — the v0.43.0 lesson is structural),
   wake-watcher scaffolding reuse (backoff, give-up latch, one-per-instance lock,
   orphan-kill, brain-side reconcile) minus the offline flip. **Boot =
   desired-state-running**: reconcile toward running at daemon boot, at adapter
   REGISTRATION against a live daemon (no spt restart ever required to bring a
   fresh adapter's service up — operator addition), at hold release, and at first
   shell bind (defensive ensure). `bind` = lazy first-bind start. **Per-option
   identity threaded into the spawn env** (option name + per-option runtime dir) —
   flynn's gap; without it two options sharing one adapter config dir flap
   silently forever.
3. **Leg C — hold + update integration.** HOLD is a first-class supervisor state:
   held ⇒ stopped and never relaunched. Adapter update-apply performs the ordered
   op: quiesce → hold → bits swap → start new bits → release. Crash-relaunch
   (backoff) ONLY when not held. If anything must sequence, the hold ships FIRST
   (flynn's forcing case: eager relaunch mid-swap re-pins the old exe — the
   stale-online ruling one layer down).
4. **Leg D — quiesce + fault classification.** Stop-request marker file in the
   service's core-owned runtime dir; cooperative exit-when-safe IS the ack; grace
   deadline then force-kill; delay possible, veto never. **Fast-exit = STARTUP
   FAULT**: N consecutive immediate exits trip the give-up latch EARLY with a
   distinct loud `STARTUP_FAULT` diagnostic + captured early stderr (a lock
   conflict reads as config fault, never a backoff flap). Optional advisory
   status line surfaces in the status view — display-only, never consulted.
5. **Leg E — env capability + the int rig.** Supervisor threads env so the
   service can invoke the spt CLI (`spt send`, identityless `cli@<node>`,
   durable spooling) — consumer-blocking: a Hub that cannot shell out kills
   node-wide Watch delivery silently. Int rig = a MOCK service adapter driving
   every gate leg in the req (boot rise, registration-start on a live daemon,
   shell-teardown survival, held update with a concurrent crash, quiesce within
   grace, force-kill on a wedged mock, STARTUP_FAULT on instant-exit loop,
   spt send from the supervised env). The gate NEVER depends on alchemy being
   the specimen.

## Gates (every leg, before "done")

- Tests via the **spt-test-engineer** subagent; timebox background runs (hard
  timeouts + proactive log checks — silent wedges on this host); kill stale
  `spt_daemon-*` orphans before daemon `--lib` suites (CI is authority there).
- Mock conformance is a property of the RIG (todlando's A4 lesson): the mock
  service must honor the real quiesce/exit contract — a credulous mock is a
  broken rig.
- **Mock binary naming**: unique across the WORKSPACE ([[bin]] clobber class,
  PR#28) and free of update/setup/install/patch substrings (Windows UAC 740).
- Workspace clippy CI form; rebuild the real `spt` binary; `traceable-reqs
  check` exit 0; docs drift gate green.
- Branch: fresh off FETCHED origin/main (after PR #84 merges — the design is
  its base). Shared tree discipline: build in a `.worktrees/` worktree.

## Ship + verify loop

- PR → two-leg CI green → merge → dedicated release PR (RELEASE-RUNBOOK;
  lockfile bullet) → deployah publish next counter → `spt update apply`.
- **Field verify, first consumer: flynn/alchemy.** Adoption = alchemy declares
  `start = "boot"` (operator-ruled; alchemy ADR-0012 revised deliberately,
  ensure-at-bind retires, relay hop retires — flynn records both in their repo),
  Hub supervised by core, then: a real alchemy release exercises the held
  update end-to-end on this node (the deploy pain that motivated the design).
- Explicitly NOT in scope: the endpoint layer (REQ-EP-8 remainder), `#` sigil
  (REQ-EP-9), any addressability. The substrate is faceless by design.
