---
name: v0200-published
description: "v0.20.0 PUBLISHED — cross-node WAN-idle delivery milestone (F-023/F-024/F-015B), counter 40"
metadata: 
  node_type: memory
  type: project
  originSessionId: d095b3e4-b4dc-4ff4-8597-17c8faaa35fc
---

v0.20.0 PUBLISHED 2026-07-02 11:25:08Z. Counter **40** (published v0.19.1=39, monotonic, rollback floor intact). Tag v0.20.0 → merge commit **3043f4e** (PR#44 f023-wan-idle-delivery→main; tree byte-identical to CI-validated @8a4e4e5, bump-in-PR; code gated by doyle FINAL-GATE @c65441c 1460/1460). **PR TITLE carried [twohost]** — twohost-a + twohost-b both RAN + GREEN (cross-node delivery legs both real hosts). deployah drove full flow end-to-end (authored bump-in-PR, merged, tagged, published). doyle token PUBLISHED-CONFIRMED-C40.

**Content (7 surfaces, F-023/F-024/F-015B wave):**
1. Cross-node delivery to IDLE spt-hosted endpoint = immediate (daemon WAN-ingress inject + ACTIVE→IDLE spool drain); deferred spooled-while-active also drains at idle edge.
2. `spt adapter update --adapter <name>:<profile>` honest swap (parent-aware matcher; success only after real swap; was silent no-op). F-015B [[f015b-adapter-apply-silent-noop]].
3. SESSION_REPIN auth self-heal: perch on dead session re-pins next activity (dead-owner only; live-owner mismatch still refused).
4. {node} manifest substitution key (advertised node label, single-token).
5. from-less `spt send` stamps cli@<node> (never blank sender; legacy empty-from renders origin node at ingress).
6. New diagnostics SPOOL_SENTINEL_CREATE_FAIL + IDLE_DRAIN loud lines; docs/STORAGE.md operator notes.
7. Docs: KNOWN-HAZARDS 7.23/7.24/7.25, ADR-0032 (boundary rotation credential), ADR-0025 amendment 2. (KH/ADR internal → EXCLUDED from CHANGELOG.)

**Publish:** bins verified vs SHA256SUMS (linux 051756164c7029f6…, win 6684fd4005bc8214…) → signed both (pubkey 54188f12…) → update-set v40 → PUBLIC+Latest. Both .release.json version=40 product 0.20.0.

**SETTLE-CHECK (doyle-mandated this cut for the v0.19.1 stale-update-set window [[release-updateset-stale-window]]):** polled served update-set.json until version==40 — SETTLED on attempt 1, NO stale window this cut. xtask upload-order fix stays a SEPARATE gated change next cycle (not folded into release).

**FLAKE:** PR#44 first CI — 1/1364 Windows fail = `spt-daemon seedmap::tests::stop_op_acks_then_serve_returns` TIMED OUT (SLOW>60/120/180→TIMEOUT 240s) = seedmap STARVATION-on-loaded-box [[seedmap-test-collides-live-daemon]], rerunnable. Zero code delta + Linux green same tree = flake. Cleared on rerun. twohost SKIPPED first pass because it `needs: test` (Windows test dep failed) — NOT a tag-detection failure; on Windows-test-pass rerun, twohost a/b auto-triggered + went green. GOTCHA: twohost jobs only appear AFTER both test legs pass (downstream) — don't premature-green before they populate.

MONITOR GOTCHA: a Monitor grepping only run-level status can emit a spurious "DONE:success" on a transient/empty API read while run still in_progress — use `status==completed AND conclusion non-empty` as the completion gate.

Roles: doyle final gate-verify + release-pings perri (F015B verify rides HIS ping, not deployah's). deployah = publisher.

**CLOSED OUT (doyle, 2026-07-02):** independent post-publish verify PASS (gh: isLatest v0.20.0 draft=false; served update-set metadata version==40 product 0.20.0, both platform shas match, rel-primary-2026). Release-ping SENT to perri: F015B verify-post-fix ask (tracker item OPEN until her on-node CLOSE w/ evidence) + {node} consumable (min_spt_core floor 0.20.0 if adopted) + heads-up that SPOOL_SENTINEL_CREATE_FAIL will name the ENLYZEAM sentinel io::Error kind on its next WAN arrival. Wave gate practice locked: detached-worktree + fresh throwaway target for EVERY gate on the shared checkout ([[gate-clean-target-not-incremental]] extended — executor WIP in the live checkout tainted one gate rerun this wave).
