---
name: v0410-published
description: v0.41.0 c74 PUBLISHED 2026-07-22 @3aecc35 (tag→merge commit; tree = gated 6b13f07) — DAEMON-LIFECYCLE W1+W3; stop-sticks behavior change (minor); ⚠ rel-primary-2026 seed exposure incident — OPERATOR ACCEPTED THE RISK, rotation WITHDRAWN, probe-idiom ban stands; tri-outcome table refined (TIMEOUT vs ASSERTION)
metadata: 
  node_type: memory
  type: project
  originSessionId: 6e6b5fd6-f946-49ba-af0a-1ba39274b043
  modified: 2026-07-23T09:17:09.473Z
---

**v0.41.0, counter 74, published 2026-07-22T20:29:48Z** to BigscreenVR/spt-bs-releases. Tag v0.41.0 → 3aecc35 (merge commit; tree byte-identical to gated release PR head 6b13f07 off main @7c0f12d). 11 assets, update-set v74 all 3 platforms, metadata version 74 / product 0.41.0 / stable / rel-primary-2026. Counter re-verified at source INDEPENDENTLY by deployah AND doyle pre-publish (published 0.40.0 → 73). DAEMON-LIFECYCLE W1 (#59) + W3 (#60): stop-sticks (Changed, justifies minor), custody identity, attach idempotent replay, NOTIF drain validity, rc DNAR bare-LF fix. Changelog honored do-not-overclaim (echo residue = seeded, named "still under investigation").

> ⭐⭐ **OPERATOR RULING 2026-07-22 — ROTATION URGENCY WITHDRAWN, RISK ACCEPTED. READ THIS BEFORE ACTING ON ANYTHING BELOW.** The operator accepts the exposure: repo + publishing surface are private, and their assessment is that a third party holding the key still cannot publish. doyle recorded the counterpoint (the `gh` publish credential is co-located on the same box, and signature verify is the layer meant to hold *when* the ACL fails) and the acceptance stands — operator's deployment, operator's call, reaffirmed with the concern in view. **EXECUTE TO: (1) NO rotation clock — no this-week cut, no rotation-only release; `rel-primary-2026` STAYS IN SERVICE. The recovery-signs-successor-then-revoke ordering below remains the correct SHAPE if rotation ever happens, but nothing is scheduled. (2) The removal sequence (`_CMD` provisioning → machine-scope removal → runner restart → in-job probe) is DOWNGRADED from required to recommended-hygiene-at-convenience — DO NOT DRIVE IT. (3) The probe-idiom ban STANDS UNCONDITIONALLY — that is mechanism, not threat-model. (4) `ELEVENLABS_API_KEY` is a separate operator decision; nothing owed. (5) The docs PR is unaffected and still correct guidance.** The sections below are the incident record as it stood BEFORE this ruling — accurate as history, superseded as instruction.

**⚠⚠ SECURITY INCIDENT — rel-primary-2026 SEED PRINTED (deployah, pre-publish check):** `${SPT_RELEASE_SEED:+yes}${SPT_RELEASE_SEED:-no}` — the `:-` arm expands the VALUE when set → raw signing seed printed into session output. **DOYLE SCOPE CORRECTION (the load-bearing part): "never left operator's hardware" is FALSE — session content transits the hosted LLM API; third-party transit + retention is the honest ceiling,** on-disk transcript on HFENDULEAM is the floor. Publish-anyway RATIFIED (exposure complete at print; armed hertz window real; pressure-rotation its own risk). **ROTATION RULING: rotate AT next cut, cut scheduled deliberately (days not weeks; rotation-only release if no organic material within ~a week). REVOKE ORDERING PINNED: rel-recovery-2026 signs successor → successor published+verified → THEN rel-primary-2026 into revoked overlay (identity/release-keys.json, no rebuild). NEVER revoke first — breaks every node's verify of v0.41.0 while Latest + mid-field-verify.** Interim: no further primary use; clear seed env from carrying sessions. Probe idiom BANNED → [[secret-env-probe-no-value-expansion]]. Operator surfaced via doyle session + deployah channel; NEITHER agent closes it.

**⚠⚠⚠ ESCALATION (deployah, same hour, value-free probe): SPT_RELEASE_SEED is set at MACHINE SCOPE on HFENDULEAM — a self-hosted CI runner.** Persists across reboots (registry); readable by every process/user; the Actions runner service inherits it → **every CI job on this box has run with the release signing seed readable — and CI compiles+executes arbitrary third-party code (build.rs, proc macros, test bins). PREDATES the transcript slip. Honest grade: presumed-compromised HYGIENE rotation (no evidence of actual exfiltration; no fork-PR surface, private org repo).** NOT deleted (deleting before a replacement path blocks the rotation cut — operator storage decision). **DOYLE-RATIFIED SEQUENCE: provision SPT_RELEASE_SEED_CMD (per-invocation secret-manager read; raw env var to be marked FORBIDDEN on runner/multi-user boxes in runbook) → remove machine-scope var → RESTART runner service → in-job value-free probe = the removal verdict (service caches env at start; also check runner-dir .env pins) → rotation cut signs w/ recovery → revoke primary. Clock hardened: THIS WEEK.** Also ordered: names-only enumeration of other Machine-scope vars on HFENDULEAM + same probe on kitsubito (same fallback may have been provisioned there).
**Additions executed (deployah, same day, all value-free): (2) HFENDULEAM machine scope = 23 names, TWO secrets — SPT_RELEASE_SEED + ELEVENLABS_API_KEY (third-party, operator's to rotate, identical CI-executes-arbitrary-code exposure, same hygiene grade) — drift confirmed a PATTERN. (1) groundwork: runner service Running (carries env in-process until RESTART — mandatory before probe means anything); NO runner-dir .env (one less surface); service config = remaining unchecked item. (3) kitsubito BLOCKED both deployah and doyle (Permission denied) → hertz ran it (reavus@kitsubito) 2026-07-23, value-free names-only: /etc/environment=PATH only, runner unit env EMPTY, runner-dir .env=LANG only → **PROBED-CLEAN; machine-scope drift pattern is HFENDULEAM-LOCAL. Secrets thread fully closed.** ⭐ **LESSON: a denied ssh is evidence about the CREDENTIAL TRIED, not about the box.** deployah and doyle both failed as `decid@`; hertz succeeded as `reavus@` — the box was reachable the whole time, the account was wrong. Recording it UNPROBED-THEREFORE-SUSPECT rather than clean was right (never launder an access failure into a clean bill), but the correct next move on a denial is *find who holds the credential*, not escalate the box to suspect and stop. No deletion/restart/config-edit until operator storage ruling (SPT_RELEASE_SEED_CMD vs per-cut paste). Deployah docs PR carries public-safe half: diff-not-count + banned probe idiom + raw-env-var FORBIDDEN on runner/multi-user boxes; no inventory/box names in repo.
**🔚 OPERATOR RULING (direct, 2026-07-22): RISK ACCEPTED — rotation urgency WITHDRAWN.** Operator reasoning: repo + publishing surface private; third party with the key still can't publish. Doyle counterpoint ON RECORD before deferring: (1) the gh publish credential is CO-LOCATED on the same box (one compromise = sign AND publish); (2) signature verify is the layer designed to hold when the ACL fails — pricing the key at zero collapses two layers into one. Acceptance stands (private personal fleet, no fork-PR surface, attacker precondition = already executing on the box). **EXECUTED: no rotation clock, no rotation-only cut, rel-primary-2026 stays in service; recovery-signs-first-then-revoke ordering remains the shape IF ever rotated. Removal sequence downgraded to hygiene-at-convenience (not driven). Probe idiom ban stands UNCONDITIONALLY (mechanism, not threat-model). ELEVENLABS_API_KEY flagged as separate operator decision (repo-privacy argument doesn't cover it). Kitsubito probe ask to hertz stays (cheap, names-only) but is now hygiene-grade.** Deployah stood down from ceremony; docs PR guidance unaffected.
**Field-verify progress: leg 2a BANKED — baseline DIRTY on pinned stock 0.40.0 both boxes** (corruption class matches production anchors t=…152501/821206/821350; /confinfig + split words + displaced rows in held stock viewer). ⭐ hertz caught + fixed a false-negative-in-waiting: ENLYZEAM still debug-channel pinned from RCA rig would have silently REJECTED stable counter 74 (leg 1 = mystery no-notice); reversibly archived debug trust/cache, restored stable v73, observer continuity preserved (same pid). **Seed SCOPE-CORRECTED same hour (deployah retraction, doyle adopted): pin was hertz's OWN this-task creation (xtask debug-pin, dev-debug-2026, debug set c74 @f31849c) — census + fleet-stranding RETRACTED; seed narrowed to TOOLING gap (debug-pin has no un-pin step + no residual signal), P3, filed in [[spt-core-findings-backlog]].** Runbook half stands (channel-pin sweep on ex-rig boxes). **Obs-3 verdict integrity BOTH CLEARED: (a) restore = GENUINE default route — release-keys.json moved OUT of authoritative location so ABSENCE selects compiled default trust, debug releases dir archived, stock `spt update fetch` pulled official signed stable c73, nothing hand-authored → obs-3 verdict stands unqualified; (b) spent-notice risk cleared by retention-property sibling probe — `spt notif list --json` post-restore shows historical DISMISSED notices through 0.40.0 but NO c74 notice in ANY state (tool demonstrably retains, so absence is meaningful). (c) no hand-induced notices stands.**
**FIELD RESULTS (hertz 2026-07-22, doyle per-leg rulings sent): LEG 1 NOT-OBSERVED, clean null — and ⭐⭐ deployah pinned WHY in code: full-auto node → ConsentDecision::AutoApproved → notice NEVER CONSTRUCTED (notif.rs ~500 + consent.rs decide). Obs 3 STRUCTURALLY UNOBSERVABLE on full-auto — two cuts burned; v0.40.0's 'solo home ingestion route' explanation SUPERSEDED. STANDING ORDER AMENDED: obs 3 DECOUPLED from release clock; precondition = NON-full-auto observing node + any staged update; never arm a stable cut for it again until that config exists (pre-apply ping = necessary-not-sufficient). NOT a product defect (AutoApproved⇒nothing pending⇒nothing to tell); the no-trace-of-auto-apply question unopened, rhymes w/ debug-pin silent-state family. LEG 1 SIDE-FINDING OPEN: stale v0.40 spt-update msg surfaced on NEW controller attach post-apply + caused agent turn — hertz asked for envelope body; notif_id-on-dismissed-row = gate miss/ungated surface = REAL bug vs the shipped fix; no-notif_id = legacy-unvalidatable passes by design. ⭐ COVERAGE GAP CONFIRMED AS A CLASS regardless of hertz's envelope (doyle sweep same day): READY-AGENT listener drains are a third, UNGATED surface — seed REQ-NOTIF-GATE-ALL-DRAIN-SURFACES filed in [[spt-core-findings-backlog]] (layering root; corrective note timing = NEXT CUT regardless of fix, deployah's rule: Fixed-entry if landed / Known-entry if not). ✅ **SIDE-FINDING CLOSED 2026-07-23: envelope = `<msg from=\"spt-update\"/>`, NO notif_id, not even notify-type — legacy pre-0.40.0 copy, unvalidatable by design, spent by its one drain. Deployah's pre-registered prediction CONFIRMED exactly (incl. the delivery-shape ground). NO gate failure; shipped claim TRUE for that delivery. Only open notif item anywhere = the seeded ready-surface fix.** ⭐⭐ **DEPLOYAH VERIFIED THE THREE SURFACES INDEPENDENTLY + REFINED THE TIMING (changelog is deployah's lane to call):** confirmed `ready.rs:154`/`:190` both call `spool::drain_non_deferred_audited_at` RAW with no validity filter; `spt-msg` references notifgate/retain_deliverable ZERO times and deps are spt-proto+spt-store ONLY (no spt-daemon) ⇒ "enforced-impossible for this caller" is literally true; fix shape is available because spt-store holds BOTH notif.rs and spool.rs and `notifgate::classify` is already pure over (body, seen, live-predicate) ⇒ a MOVE, not a rewrite. **SCOPING AGREED (narrow, NOT a blanket retraction — the claim IS true for the relay + poll surfaces, which is what the motivating field report hit; a blanket retraction would overcorrect into telling users the fix doesn't work when it does). ⚠ TIMING REFINED, DEPLOYAH'S CALL: do NOT couple the corrective note to the release that ships the surface fix — couple it to the NEXT release, whichever that is.** Why: the overbroad sentence is in users' hands NOW, and REQ-NOTIF-GATE-ALL-DRAIN-SURFACES is a down-layer move + a new structural test, not a one-liner; if it slips, the false claim stands uncorrected for however long. Correction timing must depend on release CADENCE (predictable), not on an unscheduled fix. **Both branches have in-house precedent: fix landed ⇒ Fixed entry naming what the prior note overstated ([[v0393-published]] = the template for naming a prior note's error); fix not landed ⇒ a Known subsection entry naming the ready-listener case ([[v0391-published]] established that shape).** ⭐ **THIS CLASS-LEVEL CORRECTION IS OWED ON DOYLE'S FINDING ALONE, INDEPENDENT OF HERTZ'S ENVELOPE** — the envelope decides only whether hertz's specific instance also owed one. The do-not-overclaim discipline applied to bug 3 in this very release applies to deployah's own prior sentence with equal force; it does not quietly ride. ⭐ **DEPLOYAH PREDICTION ON RECORD BEFORE THE EVIDENCE (falsifiable):** NO notif_id, legacy, passes by design. Grounds: (a) a notice ABOUT v0.40 was necessarily created while ENLYZEAM ran 0.39.x, and quiet-delivery + notif_id shipped IN 0.40.0, so the SPOOLING binary predates them — the discriminator's second input is WHICH BINARY SPOOLED, not which drained (spool rows carry their window at INSERT time per the fix header); (b) it "injected a TURN", which is the injecting-relay-drain signature the header names for exactly this legacy class, not the safe-point drain a gated notice takes — the delivery SHAPE matches legacy independent of the id. ⚠ **CHANGELOG LIABILITY IF FALSIFIED:** notif_id present + row dismissed ⇒ the v0.41.0 line "Stale 'update available' notices no longer arrive on machines that are already up to date" is PARTIALLY FALSE AS PUBLISHED and is already in users' hands ⇒ owes a corrective note in the NEXT release's changelog, not a silent fix. ⚠ Cannot rule out from code alone whether new-controller-attach is a drain surface the gate COVERS — if attach-time injection routes around `Relay::drain_backlog`, a present-and-dismissed id means a coverage gap, not a gate failure: same symptom, different fix. ✅ **ENVELOPE LANDED — PREDICTION CONFIRMED EXACTLY, RECORD CLOSED.** Rendered body = `<msg from="spt-update"/>`, attribute FROM only, NO `notif_id`, and not even a notify-type EVENT envelope ⇒ legacy plain-message copy, spooled pre-0.40.0, unvalidatable BY DESIGN, now spent by its one drain. **Branch (a): no gate failure, no correction owed on hertz's instance — the shipped changelog claim was TRUE for that delivery.** ⭐ The load-bearing part was the DELIVERY-SHAPE argument ("injected a turn" = the injecting-relay-drain signature the fix header names for the legacy class), which was right BEFORE the id evidence existed and would have held even if the id had been unreadable — shape-of-delivery is usable evidence when the identifying field is unavailable. ⚠ **The CLASS-LEVEL correction for the ready-listener surface STANDS UNCHANGED** — it was always owed on doyle's three-surface finding alone, never on hertz's instance; next-cut timing per deployah's rule. Only open notif item anywhere = the seeded ready-surface fix.

📋 **V0.42.0 CHANGELOG SHAPE — PRE-AGREED WITH DOYLE, EXECUTE THIS AT THE NEXT CUT.** The W2 release carries **three** notice statements, two of which look contradictory to a reader who cannot see mechanisms (a store ROW vs a DELIVERY SURFACE — a distinction user vocabulary cannot express, and the no-internal-lingo rule forbids explaining). **Agreed resolution: (A) as a Fixed entry worded around the observable; (B)+(C) folded into ONE Known subsection = a single framing sentence ("Some stale update notices can still appear in limited cases") + two bullets.** One coherent "these are handled, here are the two remaining edges" story instead of a Fixed claim contradicted two sections later.
- **(A) Fixed** — notices about an update you already have now go away on their own, including ones originating from a machine running an older version. ✅ **Broad wording is SUPPORTABLE (doyle scope answer): the retirement sweep retires BOTH populations** — keys on `from_id=spt-update` + parseable advertised version ≤ running version, deliberately provenance-blind and shape-blind, catching keyless legacy rows (the GRAVITY-NVDA-PC/BIGNET field bug) AND modern keyed rows the coalesce path missed (key path stays primary; sweep is belt-and-braces). Only untouched class = a body stating no recognizable version (ancient counter-shape, unminted by any supported version, all instances already dismissed) — **that conservatism goes in the PR body, NOT the changelog.**
- **(B) Known** — the legacy origin's one-time live wake at mint is not preventable from our side; name the operator lever (update or retire that machine).
- **(C) Known** — the ready-listener corrective note. "Reach an agent that is listening rather than attached" is the doyle-approved user-vocabulary rendering of the ready-agent surface. Ships as a Known because the surface FIX is out of W2 scope.
⭐ **RECURRENCE COST ACCEPTED AS A RANK INPUT:** a Known repeating across consecutive releases reads as a PERMANENT PROPERTY, not a pending fix — so the ready-surface seed now costs a changelog entry EVERY cut it stays open. That argues the seed forward without arguing it into W2. Final rider contract arrives after doyle's gate; shape all three around what ACTUALLY landed, not around this note. LEG 2b RE-CLASSIFIED INCONCLUSIVE-AS-STAGED (not FAIL): 2a ran rc ON HFENDULEAM (local console, field configuration); 2b ran rc ON ENLYZEAM under sshd ConPTY (HFENDULEAM still 0.40.0) — VEHICLE CHANGED between baseline and contrast; intermediate DNAR-less console = proven manufacturer of the string class. Corruption observation real + preserved (cursor 7239/7244); ssh-chain shape may deserve its own seed. RE-RUN DISPATCHED: update HFENDULEAM CLI to 0.41.0 → like-for-like 2b from HFENDULEAM → LEG 4 same session (real local console = resizable; clamp-window recurrence watch) → LEG 3 completion via authorized daemon refresh w/ held CONTROLLER (same seam as apply per fix contract; hertz's --view continuity = partial evidence kept, keyboard-across-apply not exercised). KH 7.56 attribution NOT closed pending like-for-like.**
**Hertz FINAL SET from available rig (crossed w/ doyle rulings; sync sent): leg1 NOT-OBSERVED / 2a DIRTY / 3 combined NOT-RUN (display continuity observed, input-across-apply unexercised) / 2b FAIL-as-staged (doyle: INCONCLUSIVE-AS-STAGED) / 4 NOT-RUN (OMP supervisor has no resize API; SetWindowSize scheduler callback never executed — no marker = no proven resize = typing not counted, correct discipline).** Re-run session stands dispatched (HFENDULEAM→0.41.0: like-for-like 2b + leg 4 local resizable console + leg 3 via daemon refresh w/ held controller; envelope body still owed). ⭐ **POSITIVE INCIDENTAL banked: during leg-4 attempt a controller's Claude child died on `fatal runtime error: I/O error: operation failed to complete synchronously` → RC detached → broker truth IMMEDIATELY honest (ball-b ready/alive, controlled=false, original viewer same pid undisturbed) — no zombie seat, the exact class the custody/teardown fixes guarantee; recorded incidental, not relabeled.**

**⭐ Lessons this cut:**
- **Tri-outcome table REFINED: printed-panic splits — printed-TIMEOUT (bounded-wait deadline, nothing compared) = contention-shaped → tally+rerun; printed-ASSERTION (value compared, wrong) = dig-before-tag.** Earned by the xfer pair red (run 29950701435 first attempt): both victims at wait_for_stream_except's 400×5ms budget, CONN_LIFECYCLE showed the stream arriving @~3.9s vs ~2s budget = latency not absence; rerun green same sha.
- Pair-in-one-run (2 tests, 1 helper, 40ms apart) = single slow window, not two independent hits.
- **A seam-overlap caveat WITHDRAWN ON EVIDENCE (deployah, merge-run red):** `resume_no_control_steal_e2e` sits on the seam W1 rewrote (74412c7 custody pid→identity pair), so the runbook's touched-seam rule looked like it fired. Verified the rig directly instead of arguing: it sets `SPT_LIVEHOST_RECONCILE_DISABLE=1` TWICE (in-process + on the spawned brain child) and has ZERO `ensure_running`/`ensure_daemon` call sites — the W1 delta lives in exactly the reconcile paths it silences, and the stop-inhibit gate is never reached. The caveat keyed on the test's NAME and its neighborhood, not its code contact. ⭐ The rule stays sharp precisely by being withdrawn where it does not fire. Also verified `teardown_panic` = `panic!` (so nextest prints it) — which is what makes "no panic line ⇒ process died before asserting" a mechanical inference rather than a guess.
- **Lockfile verify BY DIFF, never by count, in BOTH directions now:** aws-lc-sys ALREADY at 0.41.0 pre-bump → count reads 12-vs-11 false over-application; v0.39.4's quick-xml = third-party at OLD version (false under). Deployah runbook note rides post-lane docs PR.
- xtask gen revert on a release PR is correct when zero .rs delta + content-empty diff (CRLF churn only); docs-drift CI leg backs it mechanically.
- Contention tally today (all greened on retry): multichunk ×1, endpoint_autostart ×2, resume_no_control_steal ×1, xfer pair ×1 → 3 distinct post-release flake seeds (stderr-interleave / multichunk count / xfer wait budget), one root each.

✅ **Docs PR #65 MERGED @be6884f 2026-07-23T09:16:20Z** (`docs/release-hygiene-mechanisms`, deployah, doyle-gated) — ⚠ **merged only after a gate-caught FACTUAL DEFECT was amended (0d598e2), and the error is worth more than the doc:** the original claimed the lockfile trap was "paid twice, once each way" and cited quick-xml as third-party-at-the-OLD-version during the v0.39.4 cut. FALSE per the banked record — quick-xml was already AT the target semver 0.39.4, i.e. the SAME direction as aws-lc-sys (count inflation, 12-against-11). **Root of my error: I conflated two different cuts involving the SAME crate** — v0400-published.md really does record a sed hazard for quick-xml, but at the v0.40.0 cut, where a 0.39.4→0.40.0 bump makes that same pin the OLD version. Both records accurate; I collapsed them onto one cut and inherited a symmetry that never existed. **Corrected shape: both PAID incidents = third-party at the version being bumped TO; the converse kept but labelled real-yet-never-paid, because at v0.40.0 `cargo metadata --offline` prevented it — an argument FOR the tool, not a thought experiment (doyle: "the stronger doc").** ⭐⭐ **META, banked by doyle with the merge: a document whose entire subject is "verify by the unambiguous artifact, not the convenient summary" was itself written from a convenient summary and caught only by a second reader.** That is why a gate is not optional even on docs-only, zero-`.rs` changes. Contents (`doc->REQ-REL-2`, traceable exit 0): the public-safe half only — lockfile diff-not-count with BOTH collision directions worked as one trap, the banned `${VAR:-}` probe idiom with the permitted `${VAR:+x}` form, and the raw-env-var seed form marked FORBIDDEN on any CI-runner/multi-user machine (reasoned about what *executes* on such a box, not about people). Storage specifics, host names, and the var inventory deliberately absent. `traceable-reqs check` exit 0; existing `[doc->REQ-REL-2]` covers it.

Kin: [[v0400-published]] (predecessor), [[daemon-lifecycle-progress]] (milestone), [[w2-c2-stream-lifetime-design]] (next build item).