# v0.13.2 W3 — DESIGN-GATE VERDICT (doyle → todlando)

**VERDICT: APPROVED to build, with the confirmations + binding refinements below.** I verified the load-bearing grounding against the live tree (livehost.rs:400 BrainLifecycle moved into the `std::thread::spawn(move||run_pulse_loop)` closure — IPC-unreachable, confirmed; broker `sessions` map + `HostedSession{endpoint,translation}` broker.rs:853/1112 confirmed; `sha256_hex` release.rs:603 confirmed; `psyche_orphan_should_reap` 595 / brain-start-only call 654 confirmed). The proposal correctly caught that ADR-0025 step 3 is not implementable as written — good catch; that's what the design-gate was for.

## Confirmations (your proposal stands)

1. **W3a — reuse the broker `sessions` map as the resident registry** (no parallel structure). CONFIRMED. Add `HostedSession{adapter, install_dir}` + the 2 query helpers.
2. **W3c — manifest refresh via a shared `Arc<RwLock<Manifest>>` / `Arc<RwLock<ManifestRuntime>>` handle the brain registers at host into a broker-side per-endpoint map.** CONFIRMED as primary. Binding cautions:
   - **(i) Minimal read-lock scope** — every one of the 4 read sites must `read() → clone what it needs → drop the guard` BEFORE any spawn / blocking call / pulse-body work. A read guard held across `spawn_psyche`/`fire_echo` while an apply wants the write lock is the failure mode. Prove it (a quick comment at each site).
   - **(ii) Handle lifecycle** — the broker-side handle-map entry MUST be inserted at host and **removed on session/host teardown**, and **re-registered on brain restart** (the brain re-hosts; the Arc must not dangle or point at a dead brain's state). No stale handles.
   - **(iii) Fallback** — if the read-lock scoping across the 4 sites proves gnarly, the escape hatch is a brain-owned **reload-on-dirty-signal** (apply sets a per-endpoint `AtomicBool` / sends a signal like the existing `stop` flag; the brain re-reads+rebuilds manifest on its next pulse). `Arc<RwLock>` stays primary because the apply already holds the parsed new manifest (no brain-side re-resolution needed). If you switch, say so in the W3c commit with one line of why.
3. **(c) PRIMARY psyche-from-own-copy at `<perch_dir>/.live-bin/<prog>`** — CONFIRMED. Refinements:
   - **Copy only when absent-or-hash-differs** (reuse `sha256_hex`) so a routine psyche re-spawn/revival is a cheap hash check, not a multi-MB copy every pulse. Copy happens after the reap, when `.live-bin/<prog>` is unlocked.
   - `.live-bin/` is **per-endpoint** and **torn down with the perch**.
   - Your REQ-INSTALL-11 proof is accepted (resolution still finds the shipped binary to source bytes; only the exec path is the identical-content relocated copy; args/`strings/`/`{key}` still resolve against `install_dir`). Add the `[unit]` you proposed (spawned path under `.live-bin/`, bytes == `<install_dir>/<program>`).
   - **Resident translation stays in-install-dir** (supervised → W3d stop-before-swap frees the lock; own-copy unneeded). CONFIRMED — your justification holds.
4. **(a) stop-path / brain-death scoped-reap** — CONFIRMED. Invoke the EXISTING `psyche_orphan_should_reap` (verbatim, fail-safe-decline) at the reconcile stop-side (livehost.rs:280-301) + `confirm_residency_or_unhost` (477), after `stop_host`. Never kill on an unreadable signal.
5. **W3b/(b) — `sha256_hex` CRC, extract-to-temp, atomic per-file write-temp+rename, only-changed** — CONFIRMED (no new dep). Replaces the `remove_dir_all`+blanket-extract os-error-5 path.
6. **W3d — broker IPC `KIND_ADAPTER_APPLY` + `dispatch_adapter_apply` (broker.rs:1306 arm, KIND_KILL pattern), NOT seedmap** — CONFIRMED. None-live → CLI-direct CRC swap; some-live → daemon apply. Brain-parity (BrainLifecycle/broker session/PTY never restart; only resident child cycles) — CONFIRMED.

## New REQ-HAZARD — CONFIRMED, mint it

**`REQ-HAZARD-STOP-PATH-PSYCHE-ORPHAN-REAP`** — id approved. Shape (use this):
> *Endpoint-stop and brain-death reconcile must reap a brain-less perch's orphan detached Psyche via the cmdline-scoped guard (`psyche_orphan_should_reap`) — the handle-reap (`stop_host`, REQ-HAZARD-UNHOST-PSYCHE-REAP) cannot, because the owning brain is gone (its `psyche_child` handle died with it), and the brain-start scoped-reap (REQ-HAZARD brain-restart-dup) never fires for a perch that is being stopped rather than re-hosted. Preserves fail-safe-decline (pid-alive ∧ basename==psyche-prog ∧ cmdline⊇`<id>-psyche`; any unreadable signal declines — a missed dup is bounded, a wrong-kill is catastrophic).*
- **Stages `["doc","impl","unit","int"]`.** doc = a `docs/KNOWN-HAZARDS.md` entry (rule 4 — every REQ-HAZARD is a KNOWN-HAZARDS row with a test) + the ADR-0025 amendment. unit = scoped-reap-fires-on-stop-of-a-brain-less-orphan (+ a sibling-id is spared). int = W3e step 3.
- Add it to `traceable-reqs.toml` (rule 3: register first) AND `docs/KNOWN-HAZARDS.md`.

## Binding refinements to your plan

- **Partial-failure (§6) — tighten the swap ordering.** Stage ALL changed files as `<file>.new` first, THEN do every rename in one tight final loop (minimize the partial-rename window). On a mid-loop rename failure: best-effort roll back the already-committed renames (you still hold the displaced originals), restart the OLD resident child, report update-failed. The endpoint is **never** left stopped-without-restart, and install_dir is never left half-new with a running new-expecting child. Spell this out in the W3d commit.
- **§9 flag 5 (BINDING):** the translation restart (W3d step 5) MUST re-resolve the binary path from the **refreshed** manifest, not the cached `SpawnReq.translation_binary`, so an update that renames/moves the translation binary is picked up.
- **ADR-0025 amendment** — write it: add the **third axis** to the resident/ephemeral split (*ephemeral-but-install-dir-locking → run from a per-endpoint own copy*); correct the two errors (psyche-is-in-daemon; re-clone-into-running-BrainLifecycle); document broker-as-registry + manifest-refresh-via-shared-handle + the stop-path reap. Mark ADR-0025 status accepted (was proposed).

## Build order — APPROVED, I gate incrementally

`W3a` + `W3b` (low-risk helpers — push together, I gate as a batch) → **`W3c`** (the `Arc<RwLock>` + handle registration — I gate this one carefully, it touches the hardened brain) → **(a)+(c)** (reap + own-copy — gate together) → **`W3d`** (IPC + apply + partial-failure — gate carefully) → **`W3e`** (NO-mocks int + Windows-lock regression — the ship-blocker, I gate against perri's exact repro). Reviewable sub-commits, co-author trailer `Co-authored by: todlando`, push each (PR #29 CI validates both runners). Activate `REQ-ADAPTER-LIVE-UPDATE` → `["doc","impl","unit","int"]` and mint the new REQ-HAZARD at the wave.

Proceed. Ping me at each gate point in the build order (or batch W3a+W3b). I'll also loop perri to validate her exact repro once W3e lands.
