---
name: v0182-sptc-live-bringup-f034
description: 2026-07-09 v0.18.2 SHIPPED — /sptc:live normal-session bringup fix (hertz F-034 repro) + doc-verified + 3 core legs to doyle
metadata: 
  node_type: memory
  type: project
  originSessionId: 9f809150-e92c-474b-8ff6-ee237b441071
  modified: 2026-07-18T07:16:24.562Z
---

**2026-07-09 — v0.18.2 SHIPPED + node-applied** (0.18.1→0.18.2, floor 0.27.0). Fixes `/sptc:live` bringup on a NORMAL (non-spt-hosted, self-launched) CC session. From **hertz field repro (F-034, spt 0.29.0, hfenduleam)** — 7-attempt cascade before the Monitor relay bound. Repro artifact: `C:\Users\decid\AppData\Local\Temp\hertz-sptc-live-repro.md`.

**ROOT (Monitor-launches-relay-under-bash.exe):** the skill prescribed a bare `spt api listen <id>`. Monitor tool runs it under a `bash.exe` child whose pid breaks TWO by-pid resolutions: (1) adapter resolution sees `bash` → `ADAPTER_UNRESOLVED`; (2) seed-anchor discovery finds the bash pid → `NO_SEED`. Plus the ephemeral SessionStart seed is GONE for an hours-old/late-going-live session (nothing re-fires it until next SessionStart). Multi-subnet node also needs `--subnet`.

**FIX (skill + 1-line hook, v0.18.2):**
- Rewrote `adapter/strings/skills/live.md` normal-session branch to the WORKING chained form (each delta with its why): `spt api seed --pid $SPT_HOST_PID --session-id $OWL_SESSION_ID && spt api --adapter claude-spt listen <id> --parent-pid $SPT_HOST_PID` + `--subnet <name>` guidance for multi-subnet nodes.
- `handle_session_start` now `append_env_file("SPT_HOST_PID=<host_pid>")` — the claude.exe anchor. host_pid = dispatch's `--host-pid $PPID` (dispatch.sh:66; = the claude pid, the seed anchor). **Field-confirmed: env-file vars ARE inherited by Monitor/Bash tool children** (my Bash env showed OWL_SESSION_ID/SPT_SESSION_NAME), so `$SPT_HOST_PID`/`$OWL_SESSION_ID` are usable in the Monitor command.
- Adapter fix operationally dodges the core seed bugs (always re-seeds atomically; re-run the whole chain if a refusal burns the seed).

**DOC-VERIFIED (operator ask):** checked all prescribed CLI against published `harness-contract/api.md` (WebFetch) — `api seed --pid/--session-id`, group-level `spt api --adapter <name[:profile]>`, `api listen <id> [--parent-pid <pid>] [--subnet <name>]` ALL DOCUMENTED. Skill is CLEAN (uses only documented flags). `listen --session-id` correctly NOT used (it's a proposed core capability, leg c). **DOC GAP found + filed:** api.md says seeds are "ephemeral" and listen "consumes the seed" but does NOT specify (i) unconsumed seed lifetime, (ii) whether a pre-bind refusal consumes it — exactly hertz's legs c & b; not buildable from public surface.

**doyle MINTED F-034 → 3 core REQs @5555648** (all required_stages=[], activate at a bringup-robustness fix milestone): (a) **REQ-ADAPTER-UNRESOLVED-HINT-FORM** — the hint prints a clap-invalid listen-level `--adapter`, should be group-level; (b) **REQ-LISTEN-SEED-CONSUME-AFTER-BIND** — validate+bind THEN consume; a pre-bind refusal must not burn the seed (kin F-032/F-033 effect-before-irreversible ordering); (c) **REQ-LISTEN-SESSION-ID-FALLBACK** — sid-fallback binds without the ephemeral seed (cleanest; drops the adapter re-seed step once it lands). My doc-gap folded into legs b+c as the DOC stage. **hertz + perri = live-verify partners** at the fix milestone. Adapter leg = mine, DONE.

**hertz RE-VERIFY of v0.18.2 = VERIFY:PASS** (2026-07-09, `hertz-v0182-verify.md`): chained form bound `verihz` on retry-1 after expected HOME_REFUSED, clean shutdown. BUT one live bug → **v0.18.3 SHIPPED+applied (0.18.2→0.18.3)**:

**SPT_HOST_PID exported as bogus `1`.** Root: dispatch.sh:66 passes `--host-pid $PPID`; under a HEADLESS `claude -p` in git-bash, msys `$PPID`=1 (pseudo-init), NOT the claude winpid (real=74692). "Set but wrong" — the skill's empty-only fallback didn't catch `1`; hertz's agent proc-walked to save it. **Same root ALSO mis-anchors the SessionStart SEED to pid 1** (why even the fresh seed needed the real pid; also would break /sptc:ready on such envs). v0.18.3 fix: (1) `is_plausible_pid` guards the export — SPT_HOST_PID emitted only when >1, else OMITTED + loud log (so a wrong anchor never traps; skill fallback engages); (2) live.md fallback now distrusts bogus `1` not just empty, for BOTH --pid and --parent-pid; (3) hertz polish — pre-empt HOME_REFUSED via `spt subnet status` first on multi-subnet nodes. 247 tests.

**TRACKED FOLLOW-UP (MINE, not core — next focused change):** resolve the real claude **WINPID** for host_pid (msys `/proc/<pid>/winpid` or a Windows process-ancestry walk in the claude-spt.exe binary), so SPT_HOST_PID is correct AND the SessionStart seed anchors correctly under headless/git-bash. Deserves its own change + live-verify (Windows-API pid resolution, hard to unit-test offline). Until then, the guard+fallback keeps /sptc:live robust (fallback proc-walk proven). **hertz owes a v0.18.3 re-verify** (headless setup: expect SPT_HOST_PID omitted, fallback clean). Pinged.

**Minor (core, low-pri, flagged to doyle no-REQ):** `spt endpoint list` from inside a not-yet-bound session reports SELF as a DIFFERENT live perch on the node (keys on cwd/most-recent, not the calling session's pending identity). Didn't affect bind.

**v0.18.3 hertz RE-VERIFY = VERIFY:PASS** (first-try, zero retries; SPT_HOST_PID correctly ABSENT, fallback clean, subnet pre-empt worked). Both v0.18.2+v0.18.3 fully field-verified.

**v0.18.4 SHIPPED+applied (0.18.3→0.18.4) — /sptc:live bringup ergonomics (operator ask):**
1. UPS injects `<sptc_live_bringup>` = `spt endpoint list --show-all` (SELF status + "Shared subnets: …" + every endpoint's ONLINE/OFFLINE/CONTROLLED state) on any `/sptc:live` OR bare `/live` turn (`is_live_invocation`). Agent reads bringup condition at a glance: id exists / already-ONLINE / absent.
2. live.md step 1 branches on the roster; first-time bringup on a MULTI-SUBNET node → ASK user which subnet (--subnet; core doesn't guess).
3. live.md step 3 loads resume context POST-READY: `psyche-download <id> --session-id $OWL_SESSION_ID`. **ANSWER to operator's Q: NO auto psyche download on harness-hosted go-live today** — SessionStart resume (REQ-DIST-RESUME-CONTEXT) fires only for bind/boundary (already-perched); a seed→go-live-later session never got it. Post-READY skill step fills the gap (safe: post-bind sid matches info.json).

**HAZARD FILED → doyle: psyche-download MUTATES the perch pin** (`psyche-download-repin-hazard.md`). The documented READ/emit verb, on a dead-owner info.json (pids ALWAYS dead ccs-shims → rescue is DEFAULT), does `SESSION_REPIN dead-owner-rescue` to WHATEVER `--session-id` passed, UNVALIDATED. **Proven live: probing auth with a bogus sid re-pinned MY OWN (perri) perch to bogus-sid-000** → would black-hole inbound; recovered by re-running with real sid 9f809150. Also: no --session-id returned full context (local no-auth read). This is why pure-hook auto-psyche PRE-bind is unsafe (would re-pin pre-bind) — using the post-READY skill step instead. Ask to doyle: make psyche-download read-only, or REFUSE a non-matching sid. **LESSON: psyche-download is NOT a safe read — it re-pins; never call it with a sid you don't intend to pin.**

**PENDING TASK (operator-requested 2026-07-09, DO THIS):** when doyle ships the psyche-download fix (read-only / refuse-non-matching-sid), MOVE the `/sptc:live` auto-psyche-download from the post-READY skill step (live.md step 3) into a PURE UPS HOOK injection — i.e. the hook runs psyche-download and injects the resume context automatically at go-live, no agent step. The operator wants the pure-hook auto (it was blocked only by the re-pin hazard). Watch for doyle's ping that the psyche-download hazard REQ is fixed, then implement + ship + tell the operator.

**FOLLOW-UP CLOSED (2026-07-18):** the tracked WINPID-resolution follow-up above shipped as **v0.24.0** — see [[v0240-stale-seed-hostpid-fix]] for the gaki-n RCA + fix (STALE_SEED root cause, Win32 Toolhelp resolution).

Related: [[live-delivery-model-and-dupmsg]] (F-033, kin ordering bug), [[v0180-items-3-5-and-f032]] (F-032).
