---
name: w3-engine-room-recon
description: "W3 engine-room + empower recon (ADR-0052): two ADR clauses are false against the daemon's code, empower as specced is agent-invocable, and the plan lives in ACCESS-CONTROL-JIT.md §W3."
metadata: 
  node_type: memory
  type: project
  originSessionId: ab7de6a6-a70c-4471-b48a-b6021d187c4e
  modified: 2026-07-29T14:49:44.993Z
---

**W3 = engine room + `empower` (ADR-0052), milestone A ACCESS-CONTROL.** Recon done 2026-07-29
(todlando, zero cargo — box was doyle's). Plan + task breakdown + 12 REQ mints + seams:
`ACCESS-CONTROL-JIT.md` §W3. Base = `build/two-key-subnet`. Sent to doyle; six rulings open.

⭐⭐ **Two ADR-0052 clauses do not survive contact with the code** — same class as the W1 tier-1
finding (ADR premise vs code), and the reason recon-before-plan pays:

1. **"Online only while a controller is attached — detach drops it offline"** collides with
   KNOWN-HAZARDS §7.10 ("an `rc` detach ends ONLY the viewport; the harness must keep running")
   and with `harnesshost.rs`'s own doc-invariant (broker owns the PTY *so that* detach cannot
   terminate). Buildable reading = **access-posture offline** (refuse inbound, drop empowerments,
   de-advertise); the literal reading re-breaks a paid hazard.
2. **"Local `rc --take` forces a harness restart and revokes all empowerments"** is false:
   `Take` is a broker lease displacement (`resolve_subscribe` → `TookControl` +
   `displaced_envelope`); no restart on any path. Revocation must be an EXPLICIT drop edge on
   take AND on detach — "revoked by restart" is not an available argument.
   Amendment wording drafted (scratchpad `adr-0052-amendment-draft.md`), rides the W3 PR.
3. **`empower` as a bare CLI verb is agent-invocable** — precisely what ADR-0052's context rules
   out. Recommend it ship as an `spt api` verb gated by `api::auth::Proof` (perch capability
   token + session id vs info.json), the same gate as the ER-only `access-refresh`.
4. **Member-or-admin at the bring-up gate re-instantiates ADR-0051 §1a's 2× guess budget** — but
   against a LOCAL CLI attacker, where the pairing rate limiter is not in the path. §1a's
   "rate-limited, not count-limited" does NOT carry; W3 needs its own attempt bound.

Cheap answers already found in code: `PerchInfo` carries `home_subnet` + `adapter` (exactly what
ADR §4's reset may change) and `controlled`/`driven_by`/`viewer_count` (the controller-attached
predicate); `spool::spool_message_at(perch, from_id, body)` gives the session-start briefing with
no new mechanism and no harness catering (reserved system `from_id`, adapter drains it as ordinary
inbound) — preferred over reserved role text since posture is per-session and role is durable.

**BUILD STATE 2026-07-29:** doyle ruled (a)–(f) and DISPATCHED. Worktree `.worktrees/engine-room`,
branch `build/engine-room` off `build/two-key-subnet` @ecbf582. **Chunk 1 committed @30c3331**
(12 REQs minted, ADR-0052 §2a + §3a amendments, `spt-store::engineroom` with reserved id +
single create/reset ceremony + shared failure ledger + pure `GateOutcome` classifier, elevated
purge→RESET arm with its decision table). 10 units green, `cargo check` clean.
Throwaway target: scratchpad `w3-target`. Ruling detail lives in `ACCESS-CONTROL-JIT.md` §W3.

Rotation tail (`REQ-SUBNET-ADMIN-SEED-ROTATION`, INACTIVE) leg plan drafted in the same JIT
(§W3-tail) — **PREP-ONLY** until doyle confirms the operator's cut-to-milestone-B veto window
closed.

Related: [[w2-two-key-subnet-progress]], [[access-control-grill-2026-07]],
[[spt-core-harness-boundary-and-grounding]].
