---
name: w3e-live-update-int-keystone
description: W3e NO-MOCKS int A+B keystone for v0.13.2 live adapter update — own-copy lock-free, stop-path orphan reap, broker adapter_apply locked-binary swap; UAC binary-name gotcha bit the test names.
metadata:
  type: project
---

W3e ship-blocker keystone for v0.13.2 live adapter update (REQ-ADAPTER-LIVE-UPDATE + REQ-HAZARD-STOP-PATH-PSYCHE-ORPHAN-REAP), real-daemon NO-MOCKS, both GREEN on this Windows host.

**Files (own integration binary each → own process, avoids lib deadlock; run `-- --test-threads=1`):**
- `crates/spt/tests/live_adapt_psyche_lock_e2e.rs` — fn `live_update_own_copy_frees_install_binary_and_stop_reaps_orphan_psyche`. Tags `[int->REQ-HAZARD-STOP-PATH-PSYCHE-ORPHAN-REAP]` + `[int->REQ-ADAPTER-LIVE-UPDATE]` (own-copy/lock asserts).
- `crates/spt/tests/live_adapt_translation_swap_e2e.rs` — fn `adapter_apply_swaps_locked_translation_binary_without_restarting_endpoint`. Tag `[int->REQ-ADAPTER-LIVE-UPDATE]`.

**CRITICAL gotcha — test binary name MUST NOT contain `update`/`setup`/`install`/`patch`.** First named them `live_update_*`; the int test EXE (`live_update_*-HASH.exe`) failed to even launch with **os error 740 (requires elevation)** — the Windows UAC binary-name heuristic (see user auto-memory windows-uac-binary-name-740). Renamed to `live_adapt_*` and they run. Applies to ANY spawned/test exe under target/.

**int A mechanism proven (perri 4-step):** dummyharness fixture (from [[spt-test-conventions]] dummy_harness_e2e) → endpoint run --start --id wallX → poll `{wallX}-psyche` perch read_pid+is_process_alive. (a) own-copy EXISTS at `<perch>/.live-bin/psychebin<exe_suffix>` (perch = `resolve_perch_path(id, ParentHint::Infer)`); (b) LOCK-FREE proof = while psyche alive, append-overwrite the install-dir `srcs/dummyharness/psychebin*` SUCCEEDS (pre-W3 shared-spawn would os-5 lock it); (c) `kill_pid_single(brain_pid)` (taskkill /PID /F, NO /T) orphans psyche → still alive; (d) `endpoint stop wallX` REAPS it (poll !is_process_alive, ~25s budget), test never kills it. NOTE: after the single-pid brain kill the supervisor RESPAWNS the brain (BRAIN_EXIT exit 1 → respawn gen1 → BRAIN_RESTART_PSYCHE_REAP) — reap any current `brain.ready` pid in cleanup too.

**int B mechanism proven (broker-coordinated apply):** register adapter `cc` = `[session.self]` dummy + `[message-idle-translation-binary] path='<install_dir>/xlate<EXE_SUFFIX>'` (ABSOLUTE, stable across swap; broker `read_translation_path` re-reads `<install_dir>/manifest.toml` after swap). install_dir = `SPT_HOME/srcs/cc` (registry record source_dir = the W3a swap target). COPY `sibling_bin("translate_proof_fixture")` → `srcs/cc/xlate<suffix>`. endpoint run --start ccX spawns the resident translation child from install-dir xlate (Windows-locks it). `#[cfg(windows)]`: a DIRECT truncate-overwrite of `<install_dir>/xlate.exe` FAILS (os-5) = proves the lock. Staging tree = manifest.toml (same path) + xlate = fixture+4096 trailing zero bytes (PE/ELF tolerate trailing data → hash flips, behavior identical; per brain_survive.rs). `Brain::cold_start(&broker_socket_name(), now_ms)` then `adapter_apply(&AdapterApplyReq{adapter,staging_dir,install_dir})` → Ok. POST: sha256(install xlate) == staged != before (swap LANDED on previously-locked binary) AND harness_pid still alive AND perch still STATUS_ONLINE (brain-parity, endpoint never restarted).

**APIs used:** `spt_daemon::brain::Brain::{cold_start, adapter_apply}`, `spt_daemon::endpoint::broker_socket_name()`, `spt_daemon::msg::AdapterApplyReq{adapter,staging_dir,install_dir: String}` (all `pub`). `adapter_apply` returns `io::Result<()>`.

traceable-reqs check EXIT=0; both REQs now `+int`. Touched ONLY the two test files (the modified `docs/adr/0025-*.md` in the tree is pre-existing, not mine).
