# W2 feat/335-adapter-leg — JIT (todlando, 2026-09-24 ~09:10Z)
Issues read in full: releases#335 #278 #62 #329 #2 (+ all comments). Base: branch off CURRENT main (W1 PR #250 may land first; ff-only main).

## #335 parallel adapters leg (cli.rs cmd_adapter_update ~22229, update_one_adapter ~22313-22537)
- Serial loop today. Fan out one std::thread per selected adapter AFTER core leg; parent prints each adapter's buffered block when that adapter finishes (no interleave), then unchanged ADAPTER_UPDATE_SUMMARY lines (selection order) + exit via adapter_update_exit (0/3/1). Post-step runs inside the thread.
- Print sites: update_one_adapter 16 eprintln/println; callees that print: run_update_post_step (~22012, println notices + eprintln POST_FAIL), nudge_adapter_service (~21711, eprintln), nudge_serving_registry (~21758). Child processes (gh, post-step) go through run_bounded_command(_in) = CAPTURED stdout/stderr, not inherited -> safe.
- spt_runtime registry::register_with_core emits via spt_proto::emit_line_err! (manifest unknown key / deprecation) -> capture must live in spt_proto::emit (thread-local sink checked by emit_line_err!/emit_block_err!; add emit_line_out! for stdout), then convert the update-path eprintln!/println! to those macros. Macro used at 533 sites: TLS check only, behavior unchanged when no capture active.
- HAZARD: register_with_core is an RMW on the registry with NO lock -> concurrent threads lose updates (REQ-HAZARD-INFO-RMW-LOST-UPDATE class). Serialize register (+ nudges if needed) with a process-wide Mutex inside the fan-out.
- Int: 3 mock adapters with sleeps finish ~max not ~sum (gate on measured wall vs sum, state not product budget); summary/exit same as serial. Unit: per-adapter output isolation.
## #278 strings PRUNE (spt-daemon crc_swap.rs plan_crc_swap; callers cli.rs apply_release_crc_swap ~21457 and broker.rs ~10212 daemon adapter_apply)
- Add PRUNE row class: files under dest/strings/ absent from staging/strings/ removed AFTER swap commits. Nothing outside strings/ ever pruned; .old/.new litter untouched. Rewrite doc comment above apply_release_crc_swap (states falsified 'stale file harmless' premise) BY REPLACEMENT. MANIFEST.md / docs-site harness-contract update section: strings/ mirrors archive; binaries additive. REQ-ADAPTER-UPDATE-PRUNES-STRINGS (doc,impl,unit,int). Unit: dest with stale strings/skills/old.md + stale dest/foo.exe -> exactly ONE prune row. Int: real adapter update v1 (skills/a.md) -> v2 (skills/a/SKILL.md) leaves no a.md; mutation: remove prune arm -> red.
## #62 exec bit (ruled (b) 2026-09-24): force exec bit on manifest-DECLARED entry binary only, loud `ADAPTER_ENTRY_EXEC_FORCED:<adapter>: <path> extracted <mode> — packaging defect upstream`. Also 2026-08-01 constraints: crc_swap compares CONTENT only -> mode-only diff never swaps (Athenaeum 644 brick); fix arm = mode-only heal in place on Unix via set_permissions, operator-visible, never silent. Precedent applyhost.rs:445 forces 0755 on core exe. F-028 BINDING: public docs (harness-contract/manifest) must state exec-bit contract (packaging must carry exec on declared entry; core preserves modes + heals mode-only diffs on declared surface) in the same wave. cfg(unix) -> prove on kitsubito. Find what "declared entry binary" is in the manifest (translation binary command / [update.post] command program / service command?) — read MANIFEST.md first.
## #329 no code: cite v0.60.0 unit (REQ-ADAPTER-FLOOR-VS-STAGED-CORE, cli.rs floor_basis ~9656) in PR body; closure rides #336 int.
## #2 arm 1 MEASUREMENT (Windows, this box): does `spt adapter update` of a LIVE shell/service exe (PACER running; alchemy ResidentService) converge without stand-down today? Report mechanism. Build ruled rename-then-replace step-aside ONLY if red; STOP-AND-REFER to doyle if red. Coordinate with doyle before touching live PACER/alchemy (they are fleet infra).

## STATUS 2026-09-24 ~09:40Z (todlando)
- Branch feat/335-adapter-leg in .worktrees/335-adapter-leg, base 5744839f, local WIP commit 80b2a00e (UNCOMPILED, unpushed). Rebase onto main after W1 (#250, b25a037d) lands.
- #335 DONE-code: spt_proto::emit Capture/deliver/replay + cap_eprintln!/cap_println! (emit_line_err! honours capture); cli fan_out_adapter_updates(_to) std::thread::scope + mpsc, per-adapter block replay on finish, panic->Failed; ADAPTER_COMMIT_LOCK around swap+register+nudges; per-adapter fetch scratch `_github/.fetch-<name>` + staged `<safe>.<name>.update.spt`. Units: emit.rs (5) + cli.rs (3, deterministic). Int crates/spt/tests/adapter_fanout_e2e.rs (post_step_fixture `hold` rendezvous mode).
- #278 DONE-code: crc_swap SwapAction::{Place,Prune}, MIRRORED_SUBTREE="strings", collect_prunes, is_swap_litter, apply_then_prune/apply_prunes (after commit; emptied dirs removed). Units 3. Int adapter_swap_e2e.rs (fake gh channel).
- #62 DONE-code: spt_runtime::entry_exec (declared_command_templates / declared_entry_binaries / exec_heal_mode / force_entry_exec). Wired: update applied (after register, before nudges), update up-to-date branch, adapter add, broker adapter_apply before restart. Unit 3 (1 cfg unix). Int adapter_swap_e2e.rs cfg(unix) -> run on kitsubito.
- REQs minted: REQ-ADAPTER-UPDATE-PARALLEL / -PRUNES-STRINGS / REQ-ADAPTER-ENTRY-EXEC-BIT; treqs exit 0.
- NEXT: (box free from doyle) cargo check/clippy/nextest targeted; mutation proofs (#278 remove prune arm -> int red; #335 serial loop -> int red); kitsubito for unix tests; #2 arm-1 hermetic measurement (running exe in install dir + real `adapter update` via fake gh: exit 0? new bytes? old proc alive? .old litter?) — no fleet PACER touched; PR body cites #329 unit REQ-ADAPTER-FLOOR-VS-STAGED-CORE.

## HANDED OFF 2026-09-24 ~10:45Z
PR #252 head 6c95d691 (on main d3582138). Verified tree at 14a7346a/ecd19186 (db3612bf). All evidence in this dir. Lane close after land: pool-release (prebuilt main xtask.exe) .worktrees/335-adapter-leg/target + reap + worktree remove; kitsubito ~/spt-w1 pool label w2-335-kitsubito (release when done). NEXT = W3 #322+#264 (use peer_rig from H3; request_asset has NO digest gate — wrap own verify vs signed/roster entry).
