1	# spt-core public-surface findings
2
3	> Per the public-surface-only constraint (`AGENTS.md`, `HANDOFF.md` §1): if a capability needed
4	> to build the adapter is missing/ambiguous in spt-core's **published** surface (`spt-releases`
5	> releases + GH Pages docs), that is a **finding** — `spt-core`'s published contract has a gap.
6	> We report it to the spt-core owner (**doyle**) and do **not** reverse-engineer from legacy
7	> `claude_skill_owl` or reach into spt-core source. This file is the in-repo log of those findings.
8
9	| # | Date | Status | Summary |
10	|---|------|--------|---------|
11	| F-001 | 2026-06-14 | **re-scoped 2026-06-15** — most = adapter-authoring (closed); 1 residual spt-core docs item open | Hook-wiring for a CC adapter — boundary clarified |
12	| F-002 | 2026-06-15 | **RESOLVED-SHIPPED (v0.7.1)** — `<EVENT>` verified on the published `api poll` surface; F-002 dissolved; int flipped | `api poll` agent path has no inter-frame delimiter → multi-message drains are unsplittable |
13	| F-003 | 2026-06-15 | **RESOLVED + docs CLOSED (v0.7.1)** — capability shipped; the file-pointer syntax is now on the published surface | File-backed `[strings]` IS shipped (value-position table pointer `key = { file = "rel" }`) but was **undocumented** on the published surface |
14	| F-004 | 2026-06-15 | **CONFIRMED-IMPL-BUG (doyle); fix in progress** — `digest-proof` will fill `{id}`+`{session_id}` matching runtime; int deferred until the carrying release | `spt adapter digest-proof --sample` passes an empty substitution-key map → false-fails any extractor whose command uses `{session_id}` (incl. the published example) |
15	| F-005 | 2026-06-15 | **TRIAGED (doyle) — (a)+(b) mix, nothing unbuildable** — 2 of 3 sub-claims were docs-read misses; residuals = author Ed25519 key-provisioning doc + zero-touch auto-activation roadmap (REQ-UPD-1/M4). **Bridge that works today: `spt adapter add --release <repo>`** | End-user adapter activation step (`adapter add [--github/--release]`) was undocumented in install-on-demand/checklist; binary-present ≠ adapter-active |
16	| F-006 | 2026-06-15 | **Feature B SHIPPED in v0.8.0 (REQ-INSTALL-11); interim STILL IN PLACE** — install-dir resolution can't be dogfood-proven until the daemon-hosted psyche actually spawns (blocked by the v0.8.0 psyche-spawn-via-acceptance-harness gap; keep the interim until then) | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |
17	| F-007 | 2026-06-16 | **RESOLVED-SHIPPED (v0.8.0)** — `spt how-to live` topic is live; /sptc:live re-pointed at it; the int's relay leg is green on 0.8.0 (psyche-spawn moved to daemon-host = real-session, see v0.8.0 dogfood note) | `spt how-to live` was `NO_SUCH_TOPIC`; the non-interactive live-bringup was `--manifest` + persistent-child `api listen` (Monitor surrogate) |
18	| F-008 | 2026-06-16 | **OPEN — reported to doyle** — blocks SCOPE LOCKED v1 setup #5 (legacy migration); /sptc:setup can't author the step against the public surface | No published legacy-migration command (`spt` has no migrate/import/adopt/legacy/owl verb in any subcommand, no how-to) though spt-core CONTEXT.md commits to claude_skill_owl→spt migration as first-class |
19
20	---
21
22	## F-001 — Harness hook-wiring contract incomplete for a Claude Code adapter
23
24	**Reported:** 2026-06-14 to doyle (owl). **Status:** awaiting ruling / docs fix.
25
26	**What IS published (sufficient):**
27	- `harness-contract/api.md` — the full `spt api` primitive surface: `seed`, `listen`, `bind`,
28	  `boundary`, `session-end`, `shutdown`, `state`, `echo-gate`, `presence`, `driven-by`, `poll`,
29	  `history-log`, `worker-start/poll/stop`, `bind-shell`, `emit`, `owner-shutdown`, `capability`.
30	- `harness-contract/install-on-demand.md` — install-on-demand bootstrap, exact `sh` + `ps1`

# spt-core public-surface findings

> Per the public-surface-only constraint (`AGENTS.md`, `HANDOFF.md` §1): if a capability needed
> to build the adapter is missing/ambiguous in spt-core's **published** surface (`spt-releases`
> releases + GH Pages docs), that is a **finding** — `spt-core`'s published contract has a gap.
> We report it to the spt-core owner (**doyle**) and do **not** reverse-engineer from legacy
> `claude_skill_owl` or reach into spt-core source. This file is the in-repo log of those findings.

| # | Date | Status | Summary |
|---|------|--------|---------|
| F-001 | 2026-06-14 | **re-scoped 2026-06-15** — most = adapter-authoring (closed); 1 residual spt-core docs item open | Hook-wiring for a CC adapter — boundary clarified |
| F-002 | 2026-06-15 | **RESOLVED-SHIPPED (v0.7.1)** — `<EVENT>` verified on the published `api poll` surface; F-002 dissolved; int flipped | `api poll` agent path has no inter-frame delimiter → multi-message drains are unsplittable |
| F-003 | 2026-06-15 | **RESOLVED + docs CLOSED (v0.7.1)** — capability shipped; the file-pointer syntax is now on the published surface | File-backed `[strings]` IS shipped (value-position table pointer `key = { file = "rel" }`) but was **undocumented** on the published surface |
| F-004 | 2026-06-15 | **CONFIRMED-IMPL-BUG (doyle); fix in progress** — `digest-proof` will fill `{id}`+`{session_id}` matching runtime; int deferred until the carrying release | `spt adapter digest-proof --sample` passes an empty substitution-key map → false-fails any extractor whose command uses `{session_id}` (incl. the published example) |
| F-005 | 2026-06-15 | **TRIAGED (doyle) — (a)+(b) mix, nothing unbuildable** — 2 of 3 sub-claims were docs-read misses; residuals = author Ed25519 key-provisioning doc + zero-touch auto-activation roadmap (REQ-UPD-1/M4). **Bridge that works today: `spt adapter add --release <repo>`** | End-user adapter activation step (`adapter add [--github/--release]`) was undocumented in install-on-demand/checklist; binary-present ≠ adapter-active |
| F-006 | 2026-06-15 | **Feature B SHIPPED in v0.8.0 (REQ-INSTALL-11); interim STILL IN PLACE** — install-dir resolution can't be dogfood-proven until the daemon-hosted psyche actually spawns (blocked by the v0.8.0 psyche-spawn-via-acceptance-harness gap; keep the interim until then) | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |
| F-007 | 2026-06-16 | **RESOLVED-SHIPPED (v0.8.0)** — `spt how-to live` topic is live; /sptc:live re-pointed at it; the int's relay leg is green on 0.8.0 (psyche-spawn moved to daemon-host = real-session, see v0.8.0 dogfood note) | `spt how-to live` was `NO_SUCH_TOPIC`; the non-interactive live-bringup was `--manifest` + persistent-child `api listen` (Monitor surrogate) |
| F-008 | 2026-06-16 | **OPEN — reported to doyle** — blocks SCOPE LOCKED v1 setup #5 (legacy migration); /sptc:setup can't author the step against the public surface | No published legacy-migration command (`spt` has no migrate/import/adopt/legacy/owl verb in any subcommand, no how-to) though spt-core CONTEXT.md commits to claude_skill_owl→spt migration as first-class |

---

## F-001 — Harness hook-wiring contract incomplete for a Claude Code adapter

**Reported:** 2026-06-14 to doyle (owl). **Status:** awaiting ruling / docs fix.

**What IS published (sufficient):**
- `harness-contract/api.md` — the full `spt api` primitive surface: `seed`, `listen`, `bind`,
  `boundary`, `session-end`, `shutdown`, `state`, `echo-gate`, `presence`, `driven-by`, `poll`,
  `history-log`, `worker-start/poll/stop`, `bind-shell`, `emit`, `owner-shutdown`, `capability`.
- `harness-contract/install-on-demand.md` — install-on-demand bootstrap, exact `sh` + `ps1`


Edit

| F-006 | 2026-06-15 | **Feature B SHIPPED in v0.8.0 (REQ-INSTALL-11); interim STILL IN PLACE** — install-dir resolution can't be dogfood-proven until the daemon-hosted psyche actually spawns (blocked by the v0.8.0 psyche-spawn-via-acceptance-harness gap; keep the interim until then) | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |
| F-007 | 2026-06-16 | **RESOLVED-SHIPPED (v0.8.0)** — `spt how-to live` topic is live; /sptc:live re-pointed at it; the int's relay leg is green on 0.8.0 (psyche-spawn moved to daemon-host = real-session, see v0.8.0 dogfood note) | `spt how-to live` was `NO_SUCH_TOPIC`; the non-interactive live-bringup was `--manifest` + persistent-child `api listen` (Monitor surrogate) |
| F-008 | 2026-06-16 | **OPEN — reported to doyle** — blocks SCOPE LOCKED v1 setup #5 (legacy migration); /sptc:setup can't author the step against the public surface | No published legacy-migration command (`spt` has no migrate/import/adopt/legacy/owl verb in any subcommand, no how-to) though spt-core CONTEXT.md commits to claude_skill_owl→spt migration as first-class |

| F-006 | 2026-06-15 | **RESOLVED + interim RETIRED (v0.8.1 dogfood 2026-06-16)** — install-dir resolution (REQ-INSTALL-11) dogfood-proven for BOTH binaries: digest-proof + daemon-hosted Psyche resolve straight from `…/adapters/_github/<safe>/` with nothing on PATH. Interim PATH-copy step dropped from both /sptc:setup bodies; interim copies deleted | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |
| F-007 | 2026-06-16 | **RESOLVED-SHIPPED (v0.8.0)** — `spt how-to live` topic is live; /sptc:live re-pointed at it; the int's relay leg is green on 0.8.0 (psyche-spawn moved to daemon-host = real-session, see v0.8.0 dogfood note) | `spt how-to live` was `NO_SUCH_TOPIC`; the non-interactive live-bringup was `--manifest` + persistent-child `api listen` (Monitor surrogate) |
| F-008 | 2026-06-16 | **OPEN — reported to doyle** — blocks SCOPE LOCKED v1 setup #5 (legacy migration); /sptc:setup can't author the step against the public surface | No published legacy-migration command (`spt` has no migrate/import/adopt/legacy/owl verb in any subcommand, no how-to) though spt-core CONTEXT.md commits to claude_skill_owl→spt migration as first-class |
| F-009 | 2026-06-16 | **OPEN — PENDING DELIVERY to doyle (he's offline; report in commit ddf1965 + below)**. Adapter worked around it (greedy `--prompt`); recommend spt-core fix so it doesn't bite every adapter | `[session.psyche_init]`/extractor command templating substitutes a `{key}` into the command STRING then WHITESPACE-SPLITS → ANY multi-word fill (e.g. `{psyche_prompt}`) explodes into stray argv tokens. Survived only by single-token fills |
| F-010 | 2026-06-16 | **OPEN — PENDING DELIVERY to doyle**. Hardening request on top of the v0.8.1 `psyche_host_error` surface | Silent-exit still maskable: `psyche_host_error` stays clear when the detached spawn() succeeds but the child exits IMMEDIATELY (e.g. arg-parse exit 2). A crash-on-startup host looks identical to a healthy one |


The file C:\Users\decid\Documents\projects\spt-claude-code\docs\SPT-CORE-FINDINGS.md has been updated successfully. (file state is current in your context — no need to Read it back)

| F-006 | 2026-06-15 | **Feature B SHIPPED in v0.8.0 (REQ-INSTALL-11); interim STILL IN PLACE** — install-dir resolution can't be dogfood-proven until the daemon-hosted psyche actually spawns (blocked by the v0.8.0 psyche-spawn-via-acceptance-harness gap; keep the interim until then) | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |
| F-007 | 2026-06-16 | **RESOLVED-SHIPPED (v0.8.0)** — `spt how-to live` topic is live; /sptc:live re-pointed at it; the int's relay leg is green on 0.8.0 (psyche-spawn moved to daemon-host = real-session, see v0.8.0 dogfood note) | `spt how-to live` was `NO_SUCH_TOPIC`; the non-interactive live-bringup was `--manifest` + persistent-child `api listen` (Monitor surrogate) |
| F-008 | 2026-06-16 | **OPEN — reported to doyle** — blocks SCOPE LOCKED v1 setup #5 (legacy migration); /sptc:setup can't author the step against the public surface | No published legacy-migration command (`spt` has no migrate/import/adopt/legacy/owl verb in any subcommand, no how-to) though spt-core CONTEXT.md commits to claude_skill_owl→spt migration as first-class |

| F-006 | 2026-06-15 | **RESOLVED + interim RETIRED (v0.8.1 dogfood 2026-06-16)** — install-dir resolution (REQ-INSTALL-11) dogfood-proven for BOTH binaries: digest-proof + daemon-hosted Psyche resolve straight from `…/adapters/_github/<safe>/` with nothing on PATH. Interim PATH-copy step dropped from both /sptc:setup bodies; interim copies deleted | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |
| F-007 | 2026-06-16 | **RESOLVED-SHIPPED (v0.8.0)** — `spt how-to live` topic is live; /sptc:live re-pointed at it; the int's relay leg is green on 0.8.0 (psyche-spawn moved to daemon-host = real-session, see v0.8.0 dogfood note) | `spt how-to live` was `NO_SUCH_TOPIC`; the non-interactive live-bringup was `--manifest` + persistent-child `api listen` (Monitor surrogate) |
| F-008 | 2026-06-16 | **OPEN — reported to doyle** — blocks SCOPE LOCKED v1 setup #5 (legacy migration); /sptc:setup can't author the step against the public surface | No published legacy-migration command (`spt` has no migrate/import/adopt/legacy/owl verb in any subcommand, no how-to) though spt-core CONTEXT.md commits to claude_skill_owl→spt migration as first-class |
| F-009 | 2026-06-16 | **OPEN — PENDING DELIVERY to doyle (he's offline; report in commit ddf1965 + below)**. Adapter worked around it (greedy `--prompt`); recommend spt-core fix so it doesn't bite every adapter | `[session.psyche_init]`/extractor command templating substitutes a `{key}` into the command STRING then WHITESPACE-SPLITS → ANY multi-word fill (e.g. `{psyche_prompt}`) explodes into stray argv tokens. Survived only by single-token fills |
| F-010 | 2026-06-16 | **OPEN — PENDING DELIVERY to doyle**. Hardening request on top of the v0.8.1 `psyche_host_error` surface | Silent-exit still maskable: `psyche_host_error` stays clear when the detached spawn() succeeds but the child exits IMMEDIATELY (e.g. arg-parse exit 2). A crash-on-startup host looks identical to a healthy one |

| F-003 | 2026-06-15 | **RESOLVED + docs CLOSED (v0.7.1)** — capability shipped; the file-pointer syntax is now on the published surface | File-backed `[strings]` IS shipped (value-position table pointer `key = { file = "rel" }`) but was **undocumented** on the published surface |

| F-004 | 2026-06-15 | **CONFIRMED-IMPL-BUG (doyle); fix in progress** — `digest-proof` will fill `{id}`+`{session_id}` matching runtime; int deferred until the carrying release | `spt adapter digest-proof --sample` passes an empty substitution-key map → false-fails any extractor whose command uses `{session_id}` (incl. the published example) |

| F-005 | 2026-06-15 | **TRIAGED (doyle) — (a)+(b) mix, nothing unbuildable** — 2 of 3 sub-claims were docs-read misses; residuals = author Ed25519 key-provisioning doc + zero-touch auto-activation roadmap (REQ-UPD-1/M4). **Bridge that works today: `spt adapter add --release <repo>`** | End-user adapter activation step (`adapter add [--github/--release]`) was undocumented in install-on-demand/checklist; binary-present ≠ adapter-active |

-| F-006 | 2026-06-15 | **Feature B SHIPPED in v0.8.0 (REQ-INSTALL-11); interim STILL IN PLACE** — install-dir resolution can't be dogfood-proven until the daemon-hosted psyche actually spawns (blocked by the v0.8.0 psyche-spawn-via-acceptance-harness gap; keep the interim until then) | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |

+| F-006 | 2026-06-15 | **RESOLVED + interim RETIRED (v0.8.1 dogfood 2026-06-16)** — install-dir resolution (REQ-INSTALL-11) dogfood-proven for BOTH binaries: digest-proof + daemon-hosted Psyche resolve straight from `…/adapters/_github/<safe>/` with nothing on PATH. Interim PATH-copy step dropped from both /sptc:setup bodies; interim copies deleted | `--release` bundles + extracts the adapter binaries beside the manifest, but bare-name `[digest]`/`[session]` templates resolve from PATH only → bundled binaries don't resolve (copy-mode) |

+| F-009 | 2026-06-16 | **OPEN — PENDING DELIVERY to doyle (he's offline; report in commit ddf1965 + below)**. Adapter worked around it (greedy `--prompt`); recommend spt-core fix so it doesn't bite every adapter | `[session.psyche_init]`/extractor command templating substitutes a `{key}` into the command STRING then WHITESPACE-SPLITS → ANY multi-word fill (e.g. `{psyche_prompt}`) explodes into stray argv tokens. Survived only by single-token fills |

+| F-010 | 2026-06-16 | **OPEN — PENDING DELIVERY to doyle**. Hardening request on top of the v0.8.1 `psyche_host_error` surface | Silent-exit still maskable: `psyche_host_error` stays clear when the detached spawn() succeeds but the child exits IMMEDIATELY (e.g. arg-parse exit 2). A crash-on-startup host looks identical to a healthy one |


Now update the F-006 detail section + line 647, and append F-009/F-010 detail sections. Read those regions.


451	---
452
453	## F-006 — `--release` bundles adapter binaries but bare-name templates don't resolve them (copy-mode)
454
455	**Surfaced:** 2026-06-15, the first real end-to-end `--release` dogfood (spt v0.7.3, counter 15).
456
457	**Chain proven first (all green on the win node):** `spt update fetch` → `apply` (0.7.2→0.7.3, exe
458	hash flipped to the signed `d867…0794`, seamless no-bounce) → `spt adapter add --release
459	SaberMage/spt-claude-code --tag v0.1.0` → fetched `adapter.spt` from the release →
460	`ADAPTER_ADD:claude-spt:Harness:Copy (registered)` + `ADAPTER_INSTALL_SKIP: no [update] avenue
461	(manifest-only adapter)` → `claude-spt` **ACTIVE**. The end-user activation path works.
462
463	**The gap (doyle predicted it; dogfood confirmed).** `--release` extracts the bundled binaries to the
464	adapter install dir —
465	`C:\Users\decid\AppData\Local\spt-core\adapters\_github\SaberMage-spt-claude-code\claude-spt-digest.exe`
466	+ `…\claude-spt-psyche.exe` (note: the `_github/<safe>` dir even for `--release`). But the registered
467	manifest's command templates invoke them **by bare name**:
468
469	```
470	extractor = "claude-spt-digest --session {session_id} --in {source}"
471	command   = "claude-spt-psyche --id {id} --session-id {session_id} --prompt {psyche_prompt}"
472	```
473
474	Bare names resolve from **PATH** only, and the extract dir is **not** on PATH → `command -v
475	claude-spt-digest` / `-psyche` both **MISS**. Registration/activation succeed, but runtime
476	session-digest + LiveAgent Psyche can't find the bundled binaries. Copy-mode copies `manifest.toml` +
477	`strings/` only — the binaries extract but aren't placed on PATH.
478
479	**Interim (shipped, adapter-side).** `/sptc:setup` now, after an `--release` activation, copies the
480	two binaries from the extract dir (the `from …` path in `spt adapter list`) onto a PATH dir (the

---

## F-006 — `--release` bundles adapter binaries but bare-name templates don't resolve them (copy-mode)

**Surfaced:** 2026-06-15, the first real end-to-end `--release` dogfood (spt v0.7.3, counter 15).

**Chain proven first (all green on the win node):** `spt update fetch` → `apply` (0.7.2→0.7.3, exe
hash flipped to the signed `d867…0794`, seamless no-bounce) → `spt adapter add --release
SaberMage/spt-claude-code --tag v0.1.0` → fetched `adapter.spt` from the release →
`ADAPTER_ADD:claude-spt:Harness:Copy (registered)` + `ADAPTER_INSTALL_SKIP: no [update] avenue
(manifest-only adapter)` → `claude-spt` **ACTIVE**. The end-user activation path works.

**The gap (doyle predicted it; dogfood confirmed).** `--release` extracts the bundled binaries to the
adapter install dir —
`C:\Users\decid\AppData\Local\spt-core\adapters\_github\SaberMage-spt-claude-code\claude-spt-digest.exe`
+ `…\claude-spt-psyche.exe` (note: the `_github/<safe>` dir even for `--release`). But the registered
manifest's command templates invoke them **by bare name**:

```
extractor = "claude-spt-digest --session {session_id} --in {source}"
command   = "claude-spt-psyche --id {id} --session-id {session_id} --prompt {psyche_prompt}"
```

Bare names resolve from **PATH** only, and the extract dir is **not** on PATH → `command -v
claude-spt-digest` / `-psyche` both **MISS**. Registration/activation succeed, but runtime
session-digest + LiveAgent Psyche can't find the bundled binaries. Copy-mode copies `manifest.toml` +
`strings/` only — the binaries extract but aren't placed on PATH.

**Interim (shipped, adapter-side).** `/sptc:setup` now, after an `--release` activation, copies the
two binaries from the extract dir (the `from …` path in `spt adapter list`) onto a PATH dir (the


480	two binaries from the extract dir (the `from …` path in `spt adapter list`) onto a PATH dir (the
481	`spt` bin dir — already on PATH). Verified: copying them there makes `command -v` resolve both and
482	`claude-spt-digest --help` run. Unblocks runtime today.
483
484	**Proper (doyle, REQ-INSTALL-9).** spt-core resolves `[digest]`/`[session]` program paths against the
485	adapter's own install dir (the `_github/<safe>` extract home / `adapters/<name>/`) **before** PATH —
486	so a bundled `.spt` binary resolves with zero PATH placement (truly self-contained `--release`
487	delivery). Rides **v0.8.0 / counter 16** (deployah's leg). The interim retires when it lands.
488
489	**Status:** **CONFIRMED + interim shipped; proper fix scoped by doyle (REQ-INSTALL-9, v0.8.0).**
490	Reported to doyle + deployah 2026-06-15 with the concrete paths + templates above.
491
492	---
493
494	## F-007 — no `spt how-to live` topic, though live-agent lifecycle is a first-class advertised concern
495
496	**Surfaced:** 2026-06-16, building the REQ-SKILL-LIVE relay int (spt v0.7.3, counter 15).
497
498	**The gap.** `spt --help` lists "live-agent lifecycle" among the core concerns, and the task-oriented
499	`spt how-to <topic>` surface is the contract's canonical, always-current agent guidance. But only two
500	topics exist:
501
502	```
503	$ spt how-to
504	Topics (`spt how-to <topic>`):
505	  ready  receive messages: listener guidance + the --once fallback loop
506	  send   deliver messages: send vs ring, replies, SENT vs QUEUED
507
508	$ spt how-to live
509	NO_SUCH_TOPIC:live — topics:
510	  ready  ...
511	  send   ...
512	```
513
514	`ready` (becoming reachable) has a how-to; `live` (becoming a LiveAgent — a strictly larger, more
515	hazard-laden lifecycle: `[session.psyche_init]`, daemon-spawned Psyche, the `:live` composite, the
516	Monitor relay-vs-poll reconcile) does **not**. There is no published, canonical bringup recipe for a
517	live agent to defer to.
518
519	**Why it matters for the adapter.** Our `/sptc:live` body (`adapter/strings/skills/live.md`) was

two binaries from the extract dir (the `from …` path in `spt adapter list`) onto a PATH dir (the
`spt` bin dir — already on PATH). Verified: copying them there makes `command -v` resolve both and
`claude-spt-digest --help` run. Unblocks runtime today.

**Proper (doyle, REQ-INSTALL-9).** spt-core resolves `[digest]`/`[session]` program paths against the
adapter's own install dir (the `_github/<safe>` extract home / `adapters/<name>/`) **before** PATH —
so a bundled `.spt` binary resolves with zero PATH placement (truly self-contained `--release`
delivery). Rides **v0.8.0 / counter 16** (deployah's leg). The interim retires when it lands.

**Status:** **CONFIRMED + interim shipped; proper fix scoped by doyle (REQ-INSTALL-9, v0.8.0).**
Reported to doyle + deployah 2026-06-15 with the concrete paths + templates above.

---

## F-007 — no `spt how-to live` topic, though live-agent lifecycle is a first-class advertised concern

**Surfaced:** 2026-06-16, building the REQ-SKILL-LIVE relay int (spt v0.7.3, counter 15).

**The gap.** `spt --help` lists "live-agent lifecycle" among the core concerns, and the task-oriented
`spt how-to <topic>` surface is the contract's canonical, always-current agent guidance. But only two
topics exist:

```
$ spt how-to
Topics (`spt how-to <topic>`):
  ready  receive messages: listener guidance + the --once fallback loop
  send   deliver messages: send vs ring, replies, SENT vs QUEUED

$ spt how-to live
NO_SUCH_TOPIC:live — topics:
  ready  ...
  send   ...
```

`ready` (becoming reachable) has a how-to; `live` (becoming a LiveAgent — a strictly larger, more
hazard-laden lifecycle: `[session.psyche_init]`, daemon-spawned Psyche, the `:live` composite, the
Monitor relay-vs-poll reconcile) does **not**. There is no published, canonical bringup recipe for a
live agent to defer to.

**Why it matters for the adapter.** Our `/sptc:live` body (`adapter/strings/skills/live.md`) was


Re-run psyche proof on v0.8.1 + read psyche-host line

SPTC_ACCEPTANCE=1 sh ci/psyche/live-relay-int.sh on 0.8.1 → psyche leg flips skip→assert. Check spt endpoint list/whoami for psyche-host: line (FAILED reason or clean).

REQ-INSTALL-11 proof: drop F-006 PATH interim

Remove ~/AppData/Local/spt-core/bin/claude-spt-{psyche,digest}.exe → confirm psyche still spawns from install-dir. Drop interim PATH-copy step from setup.md step 4 + plugin SKILL.md step 3.

Per-OS re-release (windows + linux .spt)

Pack adapter-windows-x86_64.spt + adapter-linux-x86_64.spt (zigbuild cross), attach BOTH to new GitHub release with updated manifest ([update] block + dropped interim).

Live gh_release auto-update test

With new release, spt adapter update pulls it. Re-acquire new [update]-bearing manifest first.

cplugs republish v0.1.2

AFTER per-OS release. Ships os-detecting setup floor + ccs (#7) + subnet (#3/#4) + dropped interim.


**Proper (doyle, REQ-INSTALL-9).** spt-core resolves `[digest]`/`[session]` program paths against the
adapter's own install dir (the `_github/<safe>` extract home / `adapters/<name>/`) **before** PATH —
so a bundled `.spt` binary resolves with zero PATH placement (truly self-contained `--release`
delivery). Rides **v0.8.0 / counter 16** (deployah's leg). The interim retires when it lands.

**Status:** **CONFIRMED + interim shipped; proper fix scoped by doyle (REQ-INSTALL-9, v0.8.0).**
Reported to doyle + deployah 2026-06-15 with the concrete paths + templates above.

**Proper (doyle, REQ-INSTALL-11).** spt-core resolves `[digest]`/`[session]` program paths against the
adapter's own install dir (the `_github/<safe>` extract home / `adapters/<name>/`) **before** PATH —
so a bundled `.spt` binary resolves with zero PATH placement (truly self-contained `--release`
delivery). Shipped in **v0.8.0 / counter 16** (Feature B).

**Status:** **RESOLVED + interim RETIRED (v0.8.1 dogfood, 2026-06-16).** Install-dir resolution is now
dogfood-proven for BOTH binaries with nothing on PATH:
- **digest** — `spt adapter digest-proof claude-spt --sample …` ran the extractor from the install dir
  (`parsed 5 record(s), dropped 0`) after the interim PATH copies were moved aside and `RELDIR` was
  off PATH.
- **psyche** — the daemon-hosted Psyche resolved + spawned `claude-spt-psyche` from the install dir
  (resident runner, `procs=1`), again with the interim off PATH. (This only became provable once the
  Psyche actually stayed resident — see **F-009**, the prompt-split bug that was masking it.)
The interim PATH-copy step is **dropped** from both `/sptc:setup` bodies and the interim copies under
`…/spt-core/bin/` are deleted. Reported to doyle + deployah 2026-06-15; resolution dogfood-confirmed.


**Proper (doyle, REQ-INSTALL-9).** spt-core resolves `[digest]`/`[session]` program paths against the
adapter's own install dir (the `_github/<safe>` extract home / `adapters/<name>/`) **before** PATH —
so a bundled `.spt` binary resolves with zero PATH placement (truly self-contained `--release`
delivery). Rides **v0.8.0 / counter 16** (deployah's leg). The interim retires when it lands.

**Status:** **CONFIRMED + interim shipped; proper fix scoped by doyle (REQ-INSTALL-9, v0.8.0).**
Reported to doyle + deployah 2026-06-15 with the concrete paths + templates above.

**Proper (doyle, REQ-INSTALL-11).** spt-core resolves `[digest]`/`[session]` program paths against the
adapter's own install dir (the `_github/<safe>` extract home / `adapters/<name>/`) **before** PATH —
so a bundled `.spt` binary resolves with zero PATH placement (truly self-contained `--release`
delivery). Shipped in **v0.8.0 / counter 16** (Feature B).

**Status:** **RESOLVED + interim RETIRED (v0.8.1 dogfood, 2026-06-16).** Install-dir resolution is now
dogfood-proven for BOTH binaries with nothing on PATH:
- **digest** — `spt adapter digest-proof claude-spt --sample …` ran the extractor from the install dir
  (`parsed 5 record(s), dropped 0`) after the interim PATH copies were moved aside and `RELDIR` was
  off PATH.
- **psyche** — the daemon-hosted Psyche resolved + spawned `claude-spt-psyche` from the install dir
  (resident runner, `procs=1`), again with the interim off PATH. (This only became provable once the
  Psyche actually stayed resident — see **F-009**, the prompt-split bug that was masking it.)
The interim PATH-copy step is **dropped** from both `/sptc:setup` bodies and the interim copies under
`…/spt-core/bin/` are deleted. Reported to doyle + deployah 2026-06-15; resolution dogfood-confirmed.

`spt` bin dir — already on PATH). Verified: copying them there makes `command -v` resolve both and

`claude-spt-digest --help` run. Unblocks runtime today.

-**Proper (doyle, REQ-INSTALL-9).** spt-core resolves `[digest]`/`[session]` program paths against the

+**Proper (doyle, REQ-INSTALL-11).** spt-core resolves `[digest]`/`[session]` program paths against the

-delivery). Rides **v0.8.0 / counter 16** (deployah's leg). The interim retires when it lands.

+delivery). Shipped in **v0.8.0 / counter 16** (Feature B).

-**Status:** **CONFIRMED + interim shipped; proper fix scoped by doyle (REQ-INSTALL-9, v0.8.0).**

-Reported to doyle + deployah 2026-06-15 with the concrete paths + templates above.

+**Status:** **RESOLVED + interim RETIRED (v0.8.1 dogfood, 2026-06-16).** Install-dir resolution is now

+dogfood-proven for BOTH binaries with nothing on PATH:

+- **digest** — `spt adapter digest-proof claude-spt --sample …` ran the extractor from the install dir

+  (`parsed 5 record(s), dropped 0`) after the interim PATH copies were moved aside and `RELDIR` was

+- **psyche** — the daemon-hosted Psyche resolved + spawned `claude-spt-psyche` from the install dir

+  (resident runner, `procs=1`), again with the interim off PATH. (This only became provable once the

+  Psyche actually stayed resident — see **F-009**, the prompt-split bug that was masking it.)

+The interim PATH-copy step is **dropped** from both `/sptc:setup` bodies and the interim copies under

+`…/spt-core/bin/` are deleted. Reported to doyle + deployah 2026-06-15; resolution dogfood-confirmed.


Now the v0.8.0-dogfood note (~647) + append F-009/F-010 detail sections. Read the tail.


636	- **`[update]` gh_release ✓ (declared)** — `adapter/claude-spt.toml` now declares `[update] avenue =
637	  "gh_release", repo = "SaberMage/spt-claude-code"`; validates against the re-vendored v0.8.0
638	  `manifest.schema.json`. Live `spt adapter update` test rides the per-OS re-release (the registered
639	  adapter is still the published v0.1.0 sans `[update]`).
640	- **Relay leg ✓** — `ci/psyche/live-relay-int.sh` green on 0.8.0: BOUND/READY + a probe relayed as the
641	  escaped `<EVENT>` off the listen child + live_agent kind. No `--manifest` needed.
642
643	- **OPEN — daemon-hosted psyche-spawn: a reconcile/brain gap (spt v0.8.1 fix).** how-to live says
644	  "the daemon hosts the Psyche off the perch's online status." DIAGNOSED with doyle (startup.rs:283
645	  live_capable guard + livehost.rs reconcile): bringing up a live id via `api seed` + `api listen
646	  --manifest <local>` stamps the perch **`status="online"`** (confirmed in its info.json:
647	  `{"state":"live_agent","status":"online","adapter":"claude-spt:live"}`) — so `live_capable` fired
648	  and the `:live` manifest's `[session.psyche_init]` DID surface at the guard (same manifest spawned
649	  the psyche in-process on 0.7.3). The manifest/profile is correct. **Yet** the daemon reconcile does
650	  not host the Psyche: no `{id}-psyche` perch in `spt endpoint list`, no `claude-spt-psyche` proc,
651	  nothing in `daemon-effects.log` (only `net-send`). Per doyle's branch, status=online + no
652	  `LIVEHOST_PSYCHE` = `reconcile_once` not hosting → **a reconcile/brain-not-running gap on spt's side,
653	  fixed in v0.8.1.** Possible correlate: `spt daemon status` reports "peer pump STALLED" right after
654	  every restart (the brain/reconcile loop may share that lifecycle). **Consequence:** (1) the int's
655	  ≥0.8.0 psyche leg is skip-with-note (auto-flips to assert once v0.8.1 hosts); (2) **REQ-INSTALL-11
656	  install-dir binary resolution rides the same fix** (the psyche must spawn to exercise it) — the
657	  F-006 PATH interim STAYS until v0.8.1. doyle pings on v0.8.1 → re-run the proof.
658

- **`[update]` gh_release ✓ (declared)** — `adapter/claude-spt.toml` now declares `[update] avenue =
  "gh_release", repo = "SaberMage/spt-claude-code"`; validates against the re-vendored v0.8.0
  `manifest.schema.json`. Live `spt adapter update` test rides the per-OS re-release (the registered
  adapter is still the published v0.1.0 sans `[update]`).
- **Relay leg ✓** — `ci/psyche/live-relay-int.sh` green on 0.8.0: BOUND/READY + a probe relayed as the
  escaped `<EVENT>` off the listen child + live_agent kind. No `--manifest` needed.

- **OPEN — daemon-hosted psyche-spawn: a reconcile/brain gap (spt v0.8.1 fix).** how-to live says
  "the daemon hosts the Psyche off the perch's online status." DIAGNOSED with doyle (startup.rs:283
  live_capable guard + livehost.rs reconcile): bringing up a live id via `api seed` + `api listen
  --manifest <local>` stamps the perch **`status="online"`** (confirmed in its info.json:
  `{"state":"live_agent","status":"online","adapter":"claude-spt:live"}`) — so `live_capable` fired
  and the `:live` manifest's `[session.psyche_init]` DID surface at the guard (same manifest spawned
  the psyche in-process on 0.7.3). The manifest/profile is correct. **Yet** the daemon reconcile does
  not host the Psyche: no `{id}-psyche` perch in `spt endpoint list`, no `claude-spt-psyche` proc,
  nothing in `daemon-effects.log` (only `net-send`). Per doyle's branch, status=online + no
  `LIVEHOST_PSYCHE` = `reconcile_once` not hosting → **a reconcile/brain-not-running gap on spt's side,
  fixed in v0.8.1.** Possible correlate: `spt daemon status` reports "peer pump STALLED" right after
  every restart (the brain/reconcile loop may share that lifecycle). **Consequence:** (1) the int's
  ≥0.8.0 psyche leg is skip-with-note (auto-flips to assert once v0.8.1 hosts); (2) **REQ-INSTALL-11
  install-dir binary resolution rides the same fix** (the psyche must spawn to exercise it) — the
  F-006 PATH interim STAYS until v0.8.1. doyle pings on v0.8.1 → re-run the proof.


- **OPEN — daemon-hosted psyche-spawn: a reconcile/brain gap (spt v0.8.1 fix).** how-to live says
  "the daemon hosts the Psyche off the perch's online status." DIAGNOSED with doyle (startup.rs:283
  live_capable guard + livehost.rs reconcile): bringing up a live id via `api seed` + `api listen
  --manifest <local>` stamps the perch **`status="online"`** (confirmed in its info.json:
  `{"state":"live_agent","status":"online","adapter":"claude-spt:live"}`) — so `live_capable` fired
  and the `:live` manifest's `[session.psyche_init]` DID surface at the guard (same manifest spawned
  the psyche in-process on 0.7.3). The manifest/profile is correct. **Yet** the daemon reconcile does
  not host the Psyche: no `{id}-psyche` perch in `spt endpoint list`, no `claude-spt-psyche` proc,
  nothing in `daemon-effects.log` (only `net-send`). Per doyle's branch, status=online + no
  `LIVEHOST_PSYCHE` = `reconcile_once` not hosting → **a reconcile/brain-not-running gap on spt's side,
  fixed in v0.8.1.** Possible correlate: `spt daemon status` reports "peer pump STALLED" right after
  every restart (the brain/reconcile loop may share that lifecycle). **Consequence:** (1) the int's
  ≥0.8.0 psyche leg is skip-with-note (auto-flips to assert once v0.8.1 hosts); (2) **REQ-INSTALL-11
  install-dir binary resolution rides the same fix** (the psyche must spawn to exercise it) — the
  F-006 PATH interim STAYS until v0.8.1. doyle pings on v0.8.1 → re-run the proof.

- **RESOLVED (v0.8.1 dogfood, 2026-06-16) — daemon-hosted psyche-spawn.** Two layered bugs, not the
  net-race we first suspected. (1) spt-core v0.8.0 livehost did not reconcile/host at all (doyle's
  v0.8.1 fix addressed this — the daemon now reaches the spawn). (2) The spawn then SILENTLY failed:
  the daemon spawned `claude-spt-psyche` but it exited instantly (phantom pid, `status=online`, no
  `psyche_host_error`). Root cause = **F-009** (spt-core whitespace-splits the substituted
  `{psyche_prompt}`, so the runner's non-greedy `--prompt` rejected the 2nd word and exited 2).
  **Confirmed via argv-capture instrumentation:** the daemon passed `--prompt PSYCHE REVIVAL time:
  epoch-ms:… incoming event: (none)` as 7 separate argv tokens. Fixed adapter-side (greedy `--prompt`,
  commit ddf1965); the Psyche now stays resident, `ci/psyche/live-relay-int.sh` psyche leg flips
  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.


- **OPEN — daemon-hosted psyche-spawn: a reconcile/brain gap (spt v0.8.1 fix).** how-to live says
  "the daemon hosts the Psyche off the perch's online status." DIAGNOSED with doyle (startup.rs:283
  live_capable guard + livehost.rs reconcile): bringing up a live id via `api seed` + `api listen
  --manifest <local>` stamps the perch **`status="online"`** (confirmed in its info.json:
  `{"state":"live_agent","status":"online","adapter":"claude-spt:live"}`) — so `live_capable` fired
  and the `:live` manifest's `[session.psyche_init]` DID surface at the guard (same manifest spawned
  the psyche in-process on 0.7.3). The manifest/profile is correct. **Yet** the daemon reconcile does
  not host the Psyche: no `{id}-psyche` perch in `spt endpoint list`, no `claude-spt-psyche` proc,
  nothing in `daemon-effects.log` (only `net-send`). Per doyle's branch, status=online + no
  `LIVEHOST_PSYCHE` = `reconcile_once` not hosting → **a reconcile/brain-not-running gap on spt's side,
  fixed in v0.8.1.** Possible correlate: `spt daemon status` reports "peer pump STALLED" right after
  every restart (the brain/reconcile loop may share that lifecycle). **Consequence:** (1) the int's
  ≥0.8.0 psyche leg is skip-with-note (auto-flips to assert once v0.8.1 hosts); (2) **REQ-INSTALL-11
  install-dir binary resolution rides the same fix** (the psyche must spawn to exercise it) — the
  F-006 PATH interim STAYS until v0.8.1. doyle pings on v0.8.1 → re-run the proof.

- **RESOLVED (v0.8.1 dogfood, 2026-06-16) — daemon-hosted psyche-spawn.** Two layered bugs, not the
  net-race we first suspected. (1) spt-core v0.8.0 livehost did not reconcile/host at all (doyle's
  v0.8.1 fix addressed this — the daemon now reaches the spawn). (2) The spawn then SILENTLY failed:
  the daemon spawned `claude-spt-psyche` but it exited instantly (phantom pid, `status=online`, no
  `psyche_host_error`). Root cause = **F-009** (spt-core whitespace-splits the substituted
  `{psyche_prompt}`, so the runner's non-greedy `--prompt` rejected the 2nd word and exited 2).
  **Confirmed via argv-capture instrumentation:** the daemon passed `--prompt PSYCHE REVIVAL time:
  epoch-ms:… incoming event: (none)` as 7 separate argv tokens. Fixed adapter-side (greedy `--prompt`,
  commit ddf1965); the Psyche now stays resident, `ci/psyche/live-relay-int.sh` psyche leg flips
  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.

- **Relay leg ✓** — `ci/psyche/live-relay-int.sh` green on 0.8.0: BOUND/READY + a probe relayed as the

escaped `<EVENT>` off the listen child + live_agent kind. No `--manifest` needed.

-- **OPEN — daemon-hosted psyche-spawn: a reconcile/brain gap (spt v0.8.1 fix).** how-to live says

-  "the daemon hosts the Psyche off the perch's online status." DIAGNOSED with doyle (startup.rs:283

-  live_capable guard + livehost.rs reconcile): bringing up a live id via `api seed` + `api listen

-  --manifest <local>` stamps the perch **`status="online"`** (confirmed in its info.json:

-  `{"state":"live_agent","status":"online","adapter":"claude-spt:live"}`) — so `live_capable` fired

-  and the `:live` manifest's `[session.psyche_init]` DID surface at the guard (same manifest spawned

-  the psyche in-process on 0.7.3). The manifest/profile is correct. **Yet** the daemon reconcile does

-  not host the Psyche: no `{id}-psyche` perch in `spt endpoint list`, no `claude-spt-psyche` proc,

-  nothing in `daemon-effects.log` (only `net-send`). Per doyle's branch, status=online + no

-  `LIVEHOST_PSYCHE` = `reconcile_once` not hosting → **a reconcile/brain-not-running gap on spt's side,

-  fixed in v0.8.1.** Possible correlate: `spt daemon status` reports "peer pump STALLED" right after

-  every restart (the brain/reconcile loop may share that lifecycle). **Consequence:** (1) the int's

-  ≥0.8.0 psyche leg is skip-with-note (auto-flips to assert once v0.8.1 hosts); (2) **REQ-INSTALL-11

-  install-dir binary resolution rides the same fix** (the psyche must spawn to exercise it) — the

-  F-006 PATH interim STAYS until v0.8.1. doyle pings on v0.8.1 → re-run the proof.

+- **RESOLVED (v0.8.1 dogfood, 2026-06-16) — daemon-hosted psyche-spawn.** Two layered bugs, not the

+  net-race we first suspected. (1) spt-core v0.8.0 livehost did not reconcile/host at all (doyle's

+  v0.8.1 fix addressed this — the daemon now reaches the spawn). (2) The spawn then SILENTLY failed:

+  the daemon spawned `claude-spt-psyche` but it exited instantly (phantom pid, `status=online`, no

+  `psyche_host_error`). Root cause = **F-009** (spt-core whitespace-splits the substituted

+  `{psyche_prompt}`, so the runner's non-greedy `--prompt` rejected the 2nd word and exited 2).

+  **Confirmed via argv-capture instrumentation:** the daemon passed `--prompt PSYCHE REVIVAL time:

+  epoch-ms:… incoming event: (none)` as 7 separate argv tokens. Fixed adapter-side (greedy `--prompt`,

+  commit ddf1965); the Psyche now stays resident, `ci/psyche/live-relay-int.sh` psyche leg flips

+  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"

+  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine

+  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.


Now append the F-009 / F-010 detail sections at the end of the file.


<system-reminder>Warning: the file exists but is shorter than the provided offset (655). The file has 655 lines.</system-reminder>


648	  `{psyche_prompt}`, so the runner's non-greedy `--prompt` rejected the 2nd word and exited 2).
649	  **Confirmed via argv-capture instrumentation:** the daemon passed `--prompt PSYCHE REVIVAL time:
650	  epoch-ms:… incoming event: (none)` as 7 separate argv tokens. Fixed adapter-side (greedy `--prompt`,
651	  commit ddf1965); the Psyche now stays resident, `ci/psyche/live-relay-int.sh` psyche leg flips
652	  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
653	  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
654	  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.

  `{psyche_prompt}`, so the runner's non-greedy `--prompt` rejected the 2nd word and exited 2).
  **Confirmed via argv-capture instrumentation:** the daemon passed `--prompt PSYCHE REVIVAL time:
  epoch-ms:… incoming event: (none)` as 7 separate argv tokens. Fixed adapter-side (greedy `--prompt`,
  commit ddf1965); the Psyche now stays resident, `ci/psyche/live-relay-int.sh` psyche leg flips
  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.


  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.

  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.

---

## F-009 — command templating substitutes a `{key}` into the command STRING then whitespace-splits

**Surfaced:** 2026-06-16, v0.8.1 dogfood of the daemon-hosted Psyche (the F-006/REQ-INSTALL-11 proof).

**The gap.** The `[session.psyche_init]` (and `[digest]`) command is authored as a single template
string with `{key}` placeholders:

```
command = "claude-spt-psyche --id {id} --session-id {session_id} --prompt {psyche_prompt}"
```

spt-core substitutes the daemon-filled values **into the string** and then **splits the result on
whitespace** to build argv. So a multi-word fill does not arrive as one argument — it explodes.
`{psyche_prompt}` is always a sentence; argv-capture (instrumented `claude-spt-psyche` dumping its raw
argv to a file when daemon-spawned) showed exactly this:

```
--id  sptc-argv-cap-psyche
--session-id  sptc-argv-cap-sess
--prompt  PSYCHE  REVIVAL  time:  epoch-ms:1781652607426  incoming  event:  (none)   <- 7 tokens
```

**Consequence.** Any adapter whose command has a multi-word fill is broken unless its receiving binary
slurps the stray tokens. The published `[digest]` extractor survives only by accident — its fills
(`{session_id}`, `{source}`) are single-token. The Psyche runner's strict `--prompt` parser took
`PSYCHE`, rejected `REVIVAL` as "unknown arg", and exited 2 — which the detached host masked (F-010).

**Adapter workaround (shipped, ddf1965).** `claude-spt-psyche` parses `--prompt` **greedily/terminally**
— it consumes every remaining token and rejoins with spaces (the manifest keeps `--prompt` last).
Robust whether spt-core splits or passes one arg.

**Recommended spt-core fix.** Split the command template into argv **first**, then fill each
placeholder slot as exactly **one** argv element (no post-substitution whitespace split). This makes
multi-word fills usable without every adapter hand-rolling a slurp. Alternatively, document the
constraint loudly (fills must be single-token) — but that effectively forbids prompt-like keys.

**Status:** **OPEN — PENDING DELIVERY to doyle** (offline at fix time; full report in commit ddf1965
and queued to retry `spt send doyle`). Adapter unblocked via the greedy workaround.

---

## F-010 — `psyche_host_error` still masks a host that spawns then exits immediately

**Surfaced:** 2026-06-16, same v0.8.1 dogfood. **Builds on** doyle's v0.8.1 `psyche_host_error`
surface (the additive `info.json` field + `spt endpoint list`/`whoami` rendering).

**The gap.** v0.8.1 makes a *spawn* failure harness-reachable, but the failure mode we actually hit
was a spawn *success* followed by an immediate child exit. Because the daemon's detached `spawn()`
returned `Ok`, `psyche_host_error` stayed **clear** while the hosted process was already gone — nested
`{id}-psyche` `info.json` read `status=online` with a real-looking (already-dead) pid, and `spt
endpoint list`/`whoami` showed no error line. A crash-on-startup host is indistinguishable from a
healthy one. (Here the child exited 2 from F-009; arg-parse is just one way a host can die fast.)

**Recommended spt-core fix.** Treat a non-resident host as a host failure: e.g. confirm the child is
still alive a short interval after spawn (or that the `{id}-psyche` perch actually re-registers /
comes online) before clearing/omitting `psyche_host_error`, and record `{reason: "host exited <code>
within <n>s"}` otherwise. This closes the last masking gap so "online + no Psyche + no cause" cannot
recur.

**Status:** **OPEN — PENDING DELIVERY to doyle** (offline; report in commit ddf1965 + queued send).
Lower urgency than F-009 (the adapter fix removes our trigger), but it would have surfaced the bug
directly instead of via argv instrumentation.


  skip→ASSERT green, and **REQ-INSTALL-11 / F-006** is proven in the same run. The "peer pump STALLED"
  correlate recurs ~7-8 min after every daemon start but did NOT block hosting (a Psyche hosted fine
  with the pump stalled) — flagged to doyle as **F-010**-adjacent, separate from the host path.

---

## F-009 — command templating substitutes a `{key}` into the command STRING then whitespace-splits

**Surfaced:** 2026-06-16, v0.8.1 dogfood of the daemon-hosted Psyche (the F-006/REQ-INSTALL-11 proof).

**The gap.** The `[session.psyche_init]` (and `[digest]`) command is authored as a single template
string with `{key}` placeholders:

```
command = "claude-spt-psyche --id {id} --session-id {session_id} --prompt {psyche_prompt}"
```

spt-core substitutes the daemon-filled values **into the string** and then **splits the result on
whitespace** to build argv. So a multi-word fill does not arrive as one argument — it explodes.
`{psyche_prompt}` is always a sentence; argv-capture (instrumented `claude-spt-psyche` dumping its raw
argv to a file when daemon-spawned) showed exactly this:

```
--id  sptc-argv-cap-psyche
--session-id  sptc-argv-cap-sess
--prompt  PSYCHE  REVIVAL  time:  epoch-ms:1781652607426  incoming  event:  (none)   <- 7 tokens
```

**Consequence.** Any adapter whose command has a multi-word fill is broken unless its receiving binary
slurps the stray tokens. The published `[digest]` extractor survives only by accident — its fills
(`{session_id}`, `{source}`) are single-token. The Psyche runner's strict `--prompt` parser took
`PSYCHE`, rejected `REVIVAL` as "unknown arg", and exited 2 — which the detached host masked (F-010).

**Adapter workaround (shipped, ddf1965).** `claude-spt-psyche` parses `--prompt` **greedily/terminally**
— it consumes every remaining token and rejoins with spaces (the manifest keeps `--prompt` last).
Robust whether spt-core splits or passes one arg.

**Recommended spt-core fix.** Split the command template into argv **first**, then fill each
placeholder slot as exactly **one** argv element (no post-substitution whitespace split). This makes
multi-word fills usable without every adapter hand-rolling a slurp. Alternatively, document the
constraint loudly (fills must be single-token) — but that effectively forbids prompt-like keys.

**Status:** **OPEN — PENDING DELIVERY to doyle** (offline at fix time; full report in commit ddf1965
and queued to retry `spt send doyle`). Adapter unblocked via the greedy workaround.

---

## F-010 — `psyche_host_error` still masks a host that spawns then exits immediately

**Surfaced:** 2026-06-16, same v0.8.1 dogfood. **Builds on** doyle's v0.8.1 `psyche_host_error`
surface (the additive `info.json` field + `spt endpoint list`/`whoami` rendering).

**The gap.** v0.8.1 makes a *spawn* failure harness-reachable, but the failure mode we actually hit
was a spawn *success* followed by an immediate child exit. Because the daemon's detached `spawn()`
returned `Ok`, `psyche_host_error` stayed **clear** while the hosted process was already gone — nested
`{id}-psyche` `info.json` read `status=online` with a real-looking (already-dead) pid, and `spt
endpoint list`/`whoami` showed no error line. A crash-on-startup host is indistinguishable from a
healthy one. (Here the child exited 2 from F-009; arg-parse is just one way a host can die fast.)

**Recommended spt-core fix.** Treat a non-resident host as a host failure: e.g. confirm the child is
still alive a short interval after spawn (or that the `{id}-psyche` perch actually re-registers /
comes online) before clearing/omitting `psyche_host_error`, and record `{reason: "host exited <code>
within <n>s"}` otherwise. This closes the last masking gap so "online + no Psyche + no cause" cannot
recur.

**Status:** **OPEN — PENDING DELIVERY to doyle** (offline; report in commit ddf1965 + queued send).
Lower urgency than F-009 (the adapter fix removes our trigger), but it would have surfaced the bug
directly instead of via argv instrumentation.

+## F-009 — command templating substitutes a `{key}` into the command STRING then whitespace-splits

+**Surfaced:** 2026-06-16, v0.8.1 dogfood of the daemon-hosted Psyche (the F-006/REQ-INSTALL-11 proof).

+**The gap.** The `[session.psyche_init]` (and `[digest]`) command is authored as a single template

+command = "claude-spt-psyche --id {id} --session-id {session_id} --prompt {psyche_prompt}"

+spt-core substitutes the daemon-filled values **into the string** and then **splits the result on

+whitespace** to build argv. So a multi-word fill does not arrive as one argument — it explodes.

+`{psyche_prompt}` is always a sentence; argv-capture (instrumented `claude-spt-psyche` dumping its raw

+argv to a file when daemon-spawned) showed exactly this:

+--prompt  PSYCHE  REVIVAL  time:  epoch-ms:1781652607426  incoming  event:  (none)   <- 7 tokens

+**Consequence.** Any adapter whose command has a multi-word fill is broken unless its receiving binary

+slurps the stray tokens. The published `[digest]` extractor survives only by accident — its fills

+(`{session_id}`, `{source}`) are single-token. The Psyche runner's strict `--prompt` parser took

+`PSYCHE`, rejected `REVIVAL` as "unknown arg", and exited 2 — which the detached host masked (F-010).

+**Adapter workaround (shipped, ddf1965).** `claude-spt-psyche` parses `--prompt` **greedily/terminally**

+— it consumes every remaining token and rejoins with spaces (the manifest keeps `--prompt` last).

+Robust whether spt-core splits or passes one arg.

+**Recommended spt-core fix.** Split the command template into argv **first**, then fill each

+placeholder slot as exactly **one** argv element (no post-substitution whitespace split). This makes

+multi-word fills usable without every adapter hand-rolling a slurp. Alternatively, document the

+constraint loudly (fills must be single-token) — but that effectively forbids prompt-like keys.

+**Status:** **OPEN — PENDING DELIVERY to doyle** (offline at fix time; full report in commit ddf1965

+and queued to retry `spt send doyle`). Adapter unblocked via the greedy workaround.

+## F-010 — `psyche_host_error` still masks a host that spawns then exits immediately

+**Surfaced:** 2026-06-16, same v0.8.1 dogfood. **Builds on** doyle's v0.8.1 `psyche_host_error`

+surface (the additive `info.json` field + `spt endpoint list`/`whoami` rendering).

+**The gap.** v0.8.1 makes a *spawn* failure harness-reachable, but the failure mode we actually hit

+was a spawn *success* followed by an immediate child exit. Because the daemon's detached `spawn()`

+returned `Ok`, `psyche_host_error` stayed **clear** while the hosted process was already gone — nested

+`{id}-psyche` `info.json` read `status=online` with a real-looking (already-dead) pid, and `spt

+endpoint list`/`whoami` showed no error line. A crash-on-startup host is indistinguishable from a

+healthy one. (Here the child exited 2 from F-009; arg-parse is just one way a host can die fast.)

+**Recommended spt-core fix.** Treat a non-resident host as a host failure: e.g. confirm the child is

+still alive a short interval after spawn (or that the `{id}-psyche` perch actually re-registers /

+comes online) before clearing/omitting `psyche_host_error`, and record `{reason: "host exited <code>

+within <n>s"}` otherwise. This closes the last masking gap so "online + no Psyche + no cause" cannot

+**Status:** **OPEN — PENDING DELIVERY to doyle** (offline; report in commit ddf1965 + queued send).

+Lower urgency than F-009 (the adapter fix removes our trigger), but it would have surfaced the bug

+directly instead of via argv instrumentation.


Update the RELEASE-RUNBOOK binaries caveat + SETUP-SLICE-PLAN reference for consistency.


- **Binaries (copy-mode caveat):** registration copies `manifest.toml` + `strings/` only — **not**
  the binaries. The command templates use **bare names** (`claude-spt-digest`, `claude-spt-psyche`)
  ⇒ resolved from **PATH** (the `/sptc:setup` interim copies them onto PATH) until **v0.8.0 Feature B
  / REQ-INSTALL-11** resolves them from the adapter install dir (F-006). The archive carries them so
  the installer/Feature-B has a source.

- **Binaries (install-dir resolution — REQ-INSTALL-11).** A `--release`/`--github` acquisition extracts
  the `.spt` archive's `manifest.toml` + `strings/` **+ both tool binaries** into the adapter install
  dir (`…/adapters/_github/<safe>/`). The command templates use **bare names** (`claude-spt-digest`,
  `claude-spt-psyche`), which spt-core resolves **from that install dir** (v0.8.0 Feature B /
  REQ-INSTALL-11) — **no PATH placement needed** (dogfood-proven on v0.8.1 for both binaries; F-006
  RESOLVED, interim retired). The pack therefore MUST carry both binaries (the resolution source). Note:
  a plain local-dev `spt adapter add <manifest.toml>` copies manifest + strings only (no binaries in the
  install dir), so local-dev runtime still relies on the built binary being on PATH (e.g. the CI ints
  prepend `target/release`); the install-dir path is the end-user `--release` story.


The file C:\Users\decid\Documents\projects\spt-claude-code\docs\RELEASE-RUNBOOK.md has been updated successfully. (file state is current in your context — no need to Read it back)

- **Binaries (copy-mode caveat):** registration copies `manifest.toml` + `strings/` only — **not**
  the binaries. The command templates use **bare names** (`claude-spt-digest`, `claude-spt-psyche`)
  ⇒ resolved from **PATH** (the `/sptc:setup` interim copies them onto PATH) until **v0.8.0 Feature B
  / REQ-INSTALL-11** resolves them from the adapter install dir (F-006). The archive carries them so
  the installer/Feature-B has a source.

- **Binaries (install-dir resolution — REQ-INSTALL-11).** A `--release`/`--github` acquisition extracts
  the `.spt` archive's `manifest.toml` + `strings/` **+ both tool binaries** into the adapter install
  dir (`…/adapters/_github/<safe>/`). The command templates use **bare names** (`claude-spt-digest`,
  `claude-spt-psyche`), which spt-core resolves **from that install dir** (v0.8.0 Feature B /
  REQ-INSTALL-11) — **no PATH placement needed** (dogfood-proven on v0.8.1 for both binaries; F-006
  RESOLVED, interim retired). The pack therefore MUST carry both binaries (the resolution source). Note:
  a plain local-dev `spt adapter add <manifest.toml>` copies manifest + strings only (no binaries in the
  install dir), so local-dev runtime still relies on the built binary being on PATH (e.g. the CI ints
  prepend `target/release`); the install-dir path is the end-user `--release` story.

carries those per-OS assets — never before. Sequence: cut the per-OS-asset release FIRST, then

republish the cplugs skeleton (next `plugin.json` bump) that points at it. A skeleton bump ahead

-- **Binaries (copy-mode caveat):** registration copies `manifest.toml` + `strings/` only — **not**

-  the binaries. The command templates use **bare names** (`claude-spt-digest`, `claude-spt-psyche`)

-  ⇒ resolved from **PATH** (the `/sptc:setup` interim copies them onto PATH) until **v0.8.0 Feature B

-  / REQ-INSTALL-11** resolves them from the adapter install dir (F-006). The archive carries them so

-  the installer/Feature-B has a source.

+- **Binaries (install-dir resolution — REQ-INSTALL-11).** A `--release`/`--github` acquisition extracts

+  the `.spt` archive's `manifest.toml` + `strings/` **+ both tool binaries** into the adapter install

+  dir (`…/adapters/_github/<safe>/`). The command templates use **bare names** (`claude-spt-digest`,

+  `claude-spt-psyche`), which spt-core resolves **from that install dir** (v0.8.0 Feature B /

+  REQ-INSTALL-11) — **no PATH placement needed** (dogfood-proven on v0.8.1 for both binaries; F-006

+  RESOLVED, interim retired). The pack therefore MUST carry both binaries (the resolution source). Note:

+  a plain local-dev `spt adapter add <manifest.toml>` copies manifest + strings only (no binaries in the

+  install dir), so local-dev runtime still relies on the built binary being on PATH (e.g. the CI ints

+  prepend `target/release`); the install-dir path is the end-user `--release` story.

- **Acquisition only:** `--release` does **not** establish an `[update]` self-update route (our

manifest declares no `[update]` → COPY-mode registration). Re-acquire a newer version by re-running

`--release --tag <newer>`. The signed `file_pull` self-update channel is a separate, later concern.


Live gh_release auto-update test

cplugs republish v0.1.2


143	  `spt update fetch`→`apply` (0.7.2→0.7.3, exe hash = signed `d867…0794`, seamless) →
144	  `adapter add --release SaberMage/spt-claude-code --tag v0.1.0` → fetched `adapter.spt` → registered
145	  → **`claude-spt` ACTIVE** (Harness Copy, from `…/adapters/_github/SaberMage-spt-claude-code`).
146	  One gap found + interim-fixed + logged: bundled binaries extract beside the manifest but bare-name
147	  templates resolve from PATH only (**F-006**); interim = `/sptc:setup` copies them onto a PATH dir
148	  (now wired into both setup bodies); proper fix = doyle's **REQ-INSTALL-9** (v0.8.0/counter-16).
149	- **DONE (2026-06-16):** int scripts flipped REQ-SETUP-ACTIVATE + REQ-DIST-ADAPTER-RELEASE int
150	  stages green. `ci/setup/activate-int.sh` = the deregistered→active RE-ACTIVATE assertion (local
151	  file-form, F-005 bridge); `ci/publish/release-acquire-int.sh` = real `adapter add --release` acquire
152	  (active + `_github` source + .spt-shipped profiles/strings resolve). Both slow-lane

  `spt update fetch`→`apply` (0.7.2→0.7.3, exe hash = signed `d867…0794`, seamless) →
  `adapter add --release SaberMage/spt-claude-code --tag v0.1.0` → fetched `adapter.spt` → registered
  → **`claude-spt` ACTIVE** (Harness Copy, from `…/adapters/_github/SaberMage-spt-claude-code`).
  One gap found + interim-fixed + logged: bundled binaries extract beside the manifest but bare-name
  templates resolve from PATH only (**F-006**); interim = `/sptc:setup` copies them onto a PATH dir
  (now wired into both setup bodies); proper fix = doyle's **REQ-INSTALL-9** (v0.8.0/counter-16).
- **DONE (2026-06-16):** int scripts flipped REQ-SETUP-ACTIVATE + REQ-DIST-ADAPTER-RELEASE int
  stages green. `ci/setup/activate-int.sh` = the deregistered→active RE-ACTIVATE assertion (local
  file-form, F-005 bridge); `ci/publish/release-acquire-int.sh` = real `adapter add --release` acquire
  (active + `_github` source + .spt-shipped profiles/strings resolve). Both slow-lane


  One gap found + interim-fixed + logged: bundled binaries extract beside the manifest but bare-name
  templates resolve from PATH only (**F-006**); interim = `/sptc:setup` copies them onto a PATH dir
  (now wired into both setup bodies); proper fix = doyle's **REQ-INSTALL-9** (v0.8.0/counter-16).

  One gap found + logged: bundled binaries extract beside the manifest but bare-name templates once
  resolved from PATH only (**F-006**). **RESOLVED (v0.8.1 dogfood 2026-06-16):** spt-core's install-dir
  resolution (**REQ-INSTALL-11**, v0.8.0 Feature B) is dogfood-proven for both binaries; the interim
  PATH-copy step is dropped from both setup bodies and the interim copies deleted.


The file C:\Users\decid\Documents\projects\spt-claude-code\SETUP-SLICE-PLAN.md has been updated successfully. (file state is current in your context — no need to Read it back)

  One gap found + interim-fixed + logged: bundled binaries extract beside the manifest but bare-name
  templates resolve from PATH only (**F-006**); interim = `/sptc:setup` copies them onto a PATH dir
  (now wired into both setup bodies); proper fix = doyle's **REQ-INSTALL-9** (v0.8.0/counter-16).

  One gap found + logged: bundled binaries extract beside the manifest but bare-name templates once
  resolved from PATH only (**F-006**). **RESOLVED (v0.8.1 dogfood 2026-06-16):** spt-core's install-dir
  resolution (**REQ-INSTALL-11**, v0.8.0 Feature B) is dogfood-proven for both binaries; the interim
  PATH-copy step is dropped from both setup bodies and the interim copies deleted.

`spt update fetch`→`apply` (0.7.2→0.7.3, exe hash = signed `d867…0794`, seamless) →

`adapter add --release SaberMage/spt-claude-code --tag v0.1.0` → fetched `adapter.spt` → registered

→ **`claude-spt` ACTIVE** (Harness Copy, from `…/adapters/_github/SaberMage-spt-claude-code`).

-  One gap found + interim-fixed + logged: bundled binaries extract beside the manifest but bare-name

-  templates resolve from PATH only (**F-006**); interim = `/sptc:setup` copies them onto a PATH dir

-  (now wired into both setup bodies); proper fix = doyle's **REQ-INSTALL-9** (v0.8.0/counter-16).

+  One gap found + logged: bundled binaries extract beside the manifest but bare-name templates once

+  resolved from PATH only (**F-006**). **RESOLVED (v0.8.1 dogfood 2026-06-16):** spt-core's install-dir

+  resolution (**REQ-INSTALL-11**, v0.8.0 Feature B) is dogfood-proven for both binaries; the interim

+  PATH-copy step is dropped from both setup bodies and the interim copies deleted.

- **DONE (2026-06-16):** int scripts flipped REQ-SETUP-ACTIVATE + REQ-DIST-ADAPTER-RELEASE int

stages green. `ci/setup/activate-int.sh` = the deregistered→active RE-ACTIVATE assertion (local

file-form, F-005 bridge); `ci/publish/release-acquire-int.sh` = real `adapter add --release` acquire


Docs swept consistent. Run the traceability gate, then commit task 2.


Bash

cd "C:\Users\decid\Documents\projects\spt-claude-code"
echo "=== traceable-reqs check ==="; traceable-reqs check 2>&1 | grep -iE "FAIL|MISSING|error|\[OK\] REQ-SETUP-ACTIVATE|all .* ok|coverage" | head
echo "=== exit code ==="; traceable-reqs check >/dev/null 2>&1; echo $?
echo "=== git status ==="; git status -s

Traceability gate + git status


=== traceable-reqs check ===
       Deterministic gates (shell-syntax + unit tests + traceable-reqs check + manifest-schema + docs-drift), each a binary pass/fail, runnable as one command
  [OK] REQ-SETUP-ACTIVATE  required: [doc, int]  stages: +doc -impl -unit +int
=== exit code ===
0
=== git status ===
 M SETUP-SLICE-PLAN.md
 M adapter/strings/skills/setup.md
 M docs/RELEASE-RUNBOOK.md
 M docs/SPT-CORE-FINDINGS.md
 M plugin/sptc/skills/setup/SKILL.md


`traceable-reqs check` exit 0. Commit task 2 (F-006 retirement + findings log).


cd "C:\Users\decid\Documents\projects\spt-claude-code"
git add adapter/strings/skills/setup.md plugin/sptc/skills/setup/SKILL.md docs/SPT-CORE-FINDINGS.md docs/RELEASE-RUNBOOK.md SETUP-SLICE-PLAN.md
git commit -F - <<'EOF'
docs(setup): retire F-006 PATH interim — REQ-INSTALL-11 install-dir resolution proven

v0.8.1 dogfood proved spt-core resolves both adapter binaries by bare name FROM
the install dir (…/adapters/_github/<safe>/) with nothing on PATH:
- digest: `spt adapter digest-proof claude-spt --sample` ran the extractor from
  the install dir (parsed 5, dropped 0) with the interim copies moved aside.
- psyche: the daemon-hosted Psyche spawned claude-spt-psyche from the install dir
  (resident, procs=1), interim off PATH.

Drops the interim PATH-copy step from both /sptc:setup bodies (adapter strings +
plugin skeleton); deletes the interim copies under ~/spt-core/bin/. F-006 RESOLVED.

Also logs two new spt-core findings (PENDING delivery to doyle — offline):
- F-009: command templating substitutes {key} into the command STRING then
  whitespace-splits → multi-word fills explode into stray argv (the prompt-split
  root cause; adapter worked around via greedy --prompt). Recommend split-then-fill.
- F-010: psyche_host_error still masks a host that spawns then exits immediately
  (detached spawn() returns Ok). Recommend treating a non-resident host as failure.

Corrects the stale REQ-INSTALL-9 references to REQ-INSTALL-11 (doyle's current id).

Co-authored by: perri
EOF
echo "=== committed ==="; git log --oneline -3

Commit F-006 retirement + findings


[main 717efd2] docs(setup): retire F-006 PATH interim — REQ-INSTALL-11 install-dir resolution proven
 5 files changed, 125 insertions(+), 53 deletions(-)
=== committed ===
717efd2 docs(setup): retire F-006 PATH interim — REQ-INSTALL-11 install-dir resolution proven
ddf1965 fix(psyche): greedy --prompt — survive spt-core's whitespace-split of {psyche_prompt}
25feaeb dogfood(v0.8.0): REQ-API-4 + how-to-live + gh_release [update]; psyche-spawn = v0.8.1 (reconcile gap)


Task 2 committed (717efd2). Before checkpointing, I edited `docs/` files — let me make sure I'm not leaving a red docs-drift gate, then finalize the checkpoint.


cd "C:\Users\decid\Documents\projects\spt-claude-code"
ls ci/ 2>&1; echo "=== gates ==="; ls ci/*.sh 2>&1 | head
echo "=== docs-drift gate? ==="; grep -rln "docs-drift\|docs-site\|mdbook" ci/ 2>/dev/null | head

Find docs-drift gate


acceptance
digest
docs
git-hooks
hooks
install-hooks.sh
lib
manifest
psyche
publish
run-gates.sh
setup
=== gates ===
ci/install-hooks.sh
ci/run-gates.sh
=== docs-drift gate? ===
ci/docs/check-docs.sh
ci/docs/gen-llms.sh
ci/run-gates.sh


cd "C:\Users\decid\Documents\projects\spt-claude-code"
timeout 90 sh ci/docs/check-docs.sh 2>&1 | tail -20; echo "exit=$?"

Run docs-drift check


ok   mdbook build
ok   llms.txt in sync
exit=0


Docs-drift gate green. Both committed units are clean. Mark task 2 done and write the JIT plan for the remaining release-engineering (tasks 3-5), which I'm deliberately pausing before — a GitHub release is outward-facing.


Updated task #2 status


Write

# Per-OS re-release + cplugs v0.1.2 — JIT plan

> **Status: NOT STARTED.** Gated on operator go-ahead (outward-facing GitHub release).
> Prereqs DONE: v0.8.1 psyche fix (ddf1965) + F-006 retired (717efd2), both committed, proof green.

## Why this release
The registered/published adapter is **v0.1.0** — it predates: the greedy-`--prompt` psyche fix
(ddf1965), the `[update] gh_release` block, the dropped F-006 interim, per-OS assets, ccs (#7) +
subnet (#3/#4) setup waves. End users on v0.1.0 still have the broken psyche + the interim step.
This release ships all of it.

## Scope / tasks

1. **Rebuild the tool binaries from source** (the psyche fix is in source; the install-dir exe was
   hand-deployed during diagnosis — NOT a packaged artifact):
   - `sh ci/digest/build.sh && sh ci/psyche/build.sh` (cargo test + release build, Windows native).
2. **Pack `adapter-windows-x86_64.spt`**: `sh ci/publish/package-adapter.sh --apply` → `dist/`.
3. **Cross-build + pack `adapter-linux-x86_64.spt`** (recipe in `docs/RELEASE-RUNBOOK.md` §Per-OS):
   - zig @ `~/.sptc-zig/...` on PATH; `cargo zigbuild --release --target x86_64-unknown-linux-gnu`
     for BOTH tool crates; then
     `SPTC_OS=linux SPTC_ARCH=x86_64 SPTC_TARGET=x86_64-unknown-linux-gnu sh ci/publish/package-adapter.sh --apply`.
   - Verify both .spt carry the RIGHT binaries (win=PE, linux=ELF) and validate the manifest.
4. **Bump + changelog**: decide version (adapter manifest version — distinct from plugin version).
   Add a `## [<ver>] - 2026-06-16` CHANGELOG section (user-facing: psyche live-agent now works; no
   more manual PATH-copy in setup; per-OS assets; ccs + subnet setup). Regenerate gated docs
   (`sh ci/docs/gen-llms.sh` if needed; `ci/docs/check-docs.sh` must stay green).
5. **[OUTWARD-FACING] Cut the GitHub release** on `SaberMage/spt-claude-code`, attach BOTH per-OS
   `.spt` assets. Tag triggers docs-publish. **← confirm with operator before this step.**
6. **Live gh_release auto-update test (TASK 4)**: the currently-registered adapter is v0.1.0 (no
   `[update]`), so first **re-acquire** the new one: `spt adapter add --release SaberMage/spt-claude-code
   --tag <newver> --asset adapter-windows-x86_64.spt`. Then confirm `spt adapter update` pulls a
   subsequent bump via the declared `[update] gh_release` avenue.
7. **cplugs republish v0.1.2 (TASK 5)** — coupled, AFTER the per-OS release (RELEASE-RUNBOOK ordering:
   assets first, skeleton bump second, else end-user setup 404s). Bump `plugin.json` version; copy the
   skeleton subset (skills/hooks/plugin.json) into the cplugs marketplace clone; `claude plugin install
   sptc@cplugs`. Ships the os-detecting setup floor + ccs + subnet + dropped interim.

## Gate
`sh ci/run-gates.sh` green + `traceable-reqs check` green + both .spt validate + (post-publish)
`spt adapter add --release …` re-acquires active with the fix.

## Known context
- doyle is OFFLINE — the F-009/F-010 findings (in `docs/SPT-CORE-FINDINGS.md` + commit ddf1965) are
  PENDING delivery; retry `spt send doyle --from perri`. The auto-update test (task 4) does NOT need
  doyle, but coordinating the spt-core findings does.
- The psyche runner calls `claude` by bare name; `claude` (`~/.local/bin`) is NOT on the persistent
  logon PATH, so a fresh-logon daemon's psyche seed/pulse turns will no-op (the runner stays resident
  but its claude turns fail). Separate from F-006; verify on a real fresh-logon live session — may need
  a setup step to put `claude` on the persistent PATH, or the psyche to resolve claude robustly.


File created successfully at: C:\Users\decid\Documents\projects\spt-claude-code\PEROS-RERELEASE-PLAN.md (file state is current in your context — no need to Read it back)

# Per-OS re-release + cplugs v0.1.2 — JIT plan

> **Status: NOT STARTED.** Gated on operator go-ahead (outward-facing GitHub release).
> Prereqs DONE: v0.8.1 psyche fix (ddf1965) + F-006 retired (717efd2), both committed, proof green.

## Why this release
The registered/published adapter is **v0.1.0** — it predates: the greedy-`--prompt` psyche fix
(ddf1965), the `[update] gh_release` block, the dropped F-006 interim, per-OS assets, ccs (#7) +
subnet (#3/#4) setup waves. End users on v0.1.0 still have the broken psyche + the interim step.
This release ships all of it.

## Scope / tasks

1. **Rebuild the tool binaries from source** (the psyche fix is in source; the install-dir exe was
   hand-deployed during diagnosis — NOT a packaged artifact):
   - `sh ci/digest/build.sh && sh ci/psyche/build.sh` (cargo test + release build, Windows native).
2. **Pack `adapter-windows-x86_64.spt`**: `sh ci/publish/package-adapter.sh --apply` → `dist/`.
3. **Cross-build + pack `adapter-linux-x86_64.spt`** (recipe in `docs/RELEASE-RUNBOOK.md` §Per-OS):
   - zig @ `~/.sptc-zig/...` on PATH; `cargo zigbuild --release --target x86_64-unknown-linux-gnu`
     for BOTH tool crates; then
     `SPTC_OS=linux SPTC_ARCH=x86_64 SPTC_TARGET=x86_64-unknown-linux-gnu sh ci/publish/package-adapter.sh --apply`.
   - Verify both .spt carry the RIGHT binaries (win=PE, linux=ELF) and validate the manifest.
4. **Bump + changelog**: decide version (adapter manifest version — distinct from plugin version).
   Add a `## [<ver>] - 2026-06-16` CHANGELOG section (user-facing: psyche live-agent now works; no
   more manual PATH-copy in setup; per-OS assets; ccs + subnet setup). Regenerate gated docs
   (`sh ci/docs/gen-llms.sh` if needed; `ci/docs/check-docs.sh` must stay green).
5. **[OUTWARD-FACING] Cut the GitHub release** on `SaberMage/spt-claude-code`, attach BOTH per-OS
   `.spt` assets. Tag triggers docs-publish. **← confirm with operator before this step.**
6. **Live gh_release auto-update test (TASK 4)**: the currently-registered adapter is v0.1.0 (no
   `[update]`), so first **re-acquire** the new one: `spt adapter add --release SaberMage/spt-claude-code
   --tag <newver> --asset adapter-windows-x86_64.spt`. Then confirm `spt adapter update` pulls a
   subsequent bump via the declared `[update] gh_release` avenue.
7. **cplugs republish v0.1.2 (TASK 5)** — coupled, AFTER the per-OS release (RELEASE-RUNBOOK ordering:
   assets first, skeleton bump second, else end-user setup 404s). Bump `plugin.json` version; copy the
   skeleton subset (skills/hooks/plugin.json) into the cplugs marketplace clone; `claude plugin install
   sptc@cplugs`. Ships the os-detecting setup floor + ccs + subnet + dropped interim.

## Gate
`sh ci/run-gates.sh` green + `traceable-reqs check` green + both .spt validate + (post-publish)
`spt adapter add --release …` re-acquires active with the fix.

## Known context
- doyle is OFFLINE — the F-009/F-010 findings (in `docs/SPT-CORE-FINDINGS.md` + commit ddf1965) are
  PENDING delivery; retry `spt send doyle --from perri`. The auto-update test (task 4) does NOT need
  doyle, but coordinating the spt-core findings does.
- The psyche runner calls `claude` by bare name; `claude` (`~/.local/bin`) is NOT on the persistent
  logon PATH, so a fresh-logon daemon's psyche seed/pulse turns will no-op (the runner stays resident
  but its claude turns fail). Separate from F-006; verify on a real fresh-logon live session — may need
  a setup step to put `claude` on the persistent PATH, or the psyche to resolve claude robustly.


Update memory to reflect tasks 1+2 done + point at the JIT plan.


Edit

## REMAINING (v0.8.1 unblocked everything)
1. **Drop F-006 PATH interim** (TASK 2, next): verify claude-spt-digest ALSO resolves from install-dir
   (same REQ-INSTALL-11), then remove the interim PATH-copy step from BOTH setup bodies
   (`adapter/strings/skills/setup.md` step ~4 + `plugin/sptc/skills/setup/SKILL.md` step 3). Interim
   copies live at `~/AppData/Local/spt-core/bin/claude-spt-{psyche,digest}.exe`.
   CAVEAT: the psyche runner internally calls `claude` by bare name — `claude` is at `~/.local/bin`
   which is NOT on the persistent (logon) PATH, so a fresh-logon daemon won't resolve it (the seed/pulse
   claude turns no-op). Separate from the digest/psyche interim; flag if it bites the live psyche LLM.
2. **Per-OS re-release**: pack adapter-windows + adapter-linux .spt (zigbuild cross; zig @ ~/.sptc-zig;
   recipe in docs/RELEASE-RUNBOOK.md), attach BOTH to a NEW release w/ updated manifest ([update] +
   dropped interim). REBUILD the psyche .exe first (the fix is in source; install-dir exe was hand-deployed).
3. **Live gh_release auto-update test** with the new release.
4. **cplugs republish v0.1.2** (coupled AFTER per-OS release): os-detecting setup floor + ccs (#7) +
   subnet (#3/#4) + dropped interim.

## DONE THIS SESSION (committed)
- TASK 1 ✓ psyche fix + proof green (ddf1965).
- TASK 2 ✓ F-006 RETIRED: digest + psyche BOTH proven from install-dir (interim moved aside, RELDIR off
  PATH); interim PATH-copy step dropped from both setup bodies; interim copies deleted; F-009/F-010
  findings logged in docs/SPT-CORE-FINDINGS.md (717efd2). docs-drift + traceable-reqs green.

## REMAINING → see `PEROS-RERELEASE-PLAN.md` (JIT plan, committed)
3. **Per-OS re-release** [OUTWARD-FACING — confirm w/ operator]: REBUILD binaries first (psyche fix is
   in source; install-dir exe was hand-deployed, NOT packaged), pack adapter-windows + adapter-linux
   .spt (zigbuild cross; zig @ ~/.sptc-zig), cut GitHub release w/ BOTH assets + updated manifest +
   CHANGELOG. Registered/published adapter is still v0.1.0 (broken psyche + interim).
4. **Live gh_release auto-update test** (re-acquire new [update]-bearing manifest first). No doyle needed.
5. **cplugs republish v0.1.2** (coupled AFTER per-OS release per RELEASE-RUNBOOK ordering).
   CAVEAT (flag if it bites): psyche runner calls `claude` by bare name; `claude` @ ~/.local/bin is NOT
   on the persistent logon PATH → fresh-logon daemon's psyche seed/pulse turns no-op (runner stays
   resident, claude turns fail). Separate from F-006. Verify on a real fresh-logon live session.

## doyle report STILL PENDING (offline). Retry `spt send doyle --from perri` when reachable.


The file C:\Users\decid\.ccs\instances\bigscreen\projects\C--Users-decid-Documents-projects-spt-claude-code\memory\v074-follow-ups.md has been updated successfully. (file state is current in your context — no need to Read it back)

## DONE THIS SESSION (committed)
- TASK 1 ✓ psyche fix + proof green (ddf1965).
- TASK 2 ✓ F-006 RETIRED: digest + psyche BOTH proven from install-dir (interim moved aside, RELDIR off
  PATH); interim PATH-copy step dropped from both setup bodies; interim copies deleted; F-009/F-010
  findings logged in docs/SPT-CORE-FINDINGS.md (717efd2). docs-drift + traceable-reqs green.

## REMAINING → see `PEROS-RERELEASE-PLAN.md` (JIT plan, committed)
3. **Per-OS re-release** [OUTWARD-FACING — confirm w/ operator]: REBUILD binaries first (psyche fix is
   in source; install-dir exe was hand-deployed, NOT packaged), pack adapter-windows + adapter-linux
   .spt (zigbuild cross; zig @ ~/.sptc-zig), cut GitHub release w/ BOTH assets + updated manifest +
   CHANGELOG. Registered/published adapter is still v0.1.0 (broken psyche + interim).
4. **Live gh_release auto-update test** (re-acquire new [update]-bearing manifest first). No doyle needed.
5. **cplugs republish v0.1.2** (coupled AFTER per-OS release per RELEASE-RUNBOOK ordering).
   CAVEAT (flag if it bites): psyche runner calls `claude` by bare name; `claude` @ ~/.local/bin is NOT
   on the persistent logon PATH → fresh-logon daemon's psyche seed/pulse turns no-op (runner stays
   resident, claude turns fail). Separate from F-006. Verify on a real fresh-logon live session.

## doyle report STILL PENDING (offline). Retry `spt send doyle --from perri` when reachable.

---
name: v074-follow-ups
description: "spt v0.8.1 dogfood — daemon-hosted Psyche BLOCKER RESOLVED (commit ddf1965, greedy --prompt fix). REQ-INSTALL-11 proven. REMAINING: drop F-006 interim from setup docs, per-OS re-release + cplugs v0.1.2, live auto-update. doyle report PENDING (he's offline)."
metadata:
  node_type: project
  type: project
  originSessionId: 6f3dfa64-ae2e-4144-85ce-993c366887f4
---

**spt v0.8.1 dogfooded 2026-06-16** (updated 0.8.0→0.8.1 via `spt update fetch && spt update apply`;
RESTARTED the daemon — old daemon was `peer pump: STALLED`, possibly stale-code/env).

## BLOCKER RESOLVED — daemon-hosted Psyche now hosts (commit ddf1965)
Root cause of v0.8.0/v0.8.1 "Psyche online + no process + no cause": **spt-core substitutes
`{psyche_prompt}` into the `[session.psyche_init]` command STRING then WHITESPACE-SPLITS** → the
multi-word prompt arrived as 7 stray argv tokens (`--prompt PSYCHE REVIVAL time: epoch-ms:… incoming
event: (none)`). The runner's non-greedy `--prompt` took "PSYCHE", rejected "REVIVAL" as unknown-arg,
**exited 2 instantly**. The daemon's detached spawn() returned Ok → phantom hosted perch (nested
info.json status=online, real-looking pid) with NO live process and NO psyche_host_error.
- **Diagnosed** via argv-capture instrumentation (temporarily dumped argv to a file from a deployed
  instrumented exe; reverted). doyle's v0.8.1 reconcile fix DID work (v0.8.0 never reached the spawn).
- **Fixed adapter-side**: `--prompt` is now TERMINAL + GREEDY (slurps trailing tokens; manifest keeps
  `--prompt` last). Verified: claude-spt-psyche stays RESIDENT full window (was 0 procs every prior run).
- **REQ-INSTALL-11 PROVEN**: the daemon resolved claude-spt-psyche by bare name FROM the install dir
  (`adapters/_github/SaberMage-spt-claude-code/`) — binaries DO registration-copy there (manifest +
  strings + BOTH .exe). No PATH interim needed for runner resolution.
- **live-relay-int.sh**: psyche-spawn leg flips skip→ASSERT GREEN; detection = resident
  claude-spt-psyche proc + nested `{id}-psyche` perch dir (endpoint list NEVER surfaces the nested
  perch); id/session now **per-run-unique** (`$$` suffix) — daemon hosts a Psyche once per session_id,
  so a fixed id can't re-host. `SPTC_ACCEPTANCE=1 sh ci/psyche/live-relay-int.sh` = LIVE-RELAY-INT OK.

## doyle report PENDING DELIVERY (he's offline — NO_PERCH, even --deferred local-only)
Full content in commit ddf1965 msg. Retry `spt send doyle --from perri` when reachable. Two spt-core
findings for him: (1) command-templating whitespace-splits substituted multi-word keys → ANY prompt-
like fill unusable as one arg (digest survives only b/c single-token fills); recommend split-then-fill.
(2) silent-exit still maskable — psyche_host_error stays clear when spawn() ok but child exits instantly;
treat non-resident host as failure. MINOR: peer pump STALLS ~7-8min after every daemon start (didn't
block hosting).

## REMAINING (v0.8.1 unblocked everything)
1. **Drop F-006 PATH interim** (TASK 2, next): verify claude-spt-digest ALSO resolves from install-dir
   (same REQ-INSTALL-11), then remove the interim PATH-copy step from BOTH setup bodies
   (`adapter/strings/skills/setup.md` step ~4 + `plugin/sptc/skills/setup/SKILL.md` step 3). Interim
   copies live at `~/AppData/Local/spt-core/bin/claude-spt-{psyche,digest}.exe`.
   CAVEAT: the psyche runner internally calls `claude` by bare name — `claude` is at `~/.local/bin`
   which is NOT on the persistent (logon) PATH, so a fresh-logon daemon won't resolve it (the seed/pulse
   claude turns no-op). Separate from the digest/psyche interim; flag if it bites the live psyche LLM.
2. **Per-OS re-release**: pack adapter-windows + adapter-linux .spt (zigbuild cross; zig @ ~/.sptc-zig;
   recipe in docs/RELEASE-RUNBOOK.md), attach BOTH to a NEW release w/ updated manifest ([update] +
   dropped interim). REBUILD the psyche .exe first (the fix is in source; install-dir exe was hand-deployed).
3. **Live gh_release auto-update test** with the new release.
4. **cplugs republish v0.1.2** (coupled AFTER per-OS release): os-detecting setup floor + ccs (#7) +
   subnet (#3/#4) + dropped interim.

F-008 (#5 legacy migration) = deferred-by-design. See [[live-int-gated-m11-counter15]],
[[per-os-and-setup-waves]], [[succession-flip-gated]].

-## REMAINING (v0.8.1 unblocked everything)

-1. **Drop F-006 PATH interim** (TASK 2, next): verify claude-spt-digest ALSO resolves from install-dir

-   (same REQ-INSTALL-11), then remove the interim PATH-copy step from BOTH setup bodies

-   (`adapter/strings/skills/setup.md` step ~4 + `plugin/sptc/skills/setup/SKILL.md` step 3). Interim

-   copies live at `~/AppData/Local/spt-core/bin/claude-spt-{psyche,digest}.exe`.

-   CAVEAT: the psyche runner internally calls `claude` by bare name — `claude` is at `~/.local/bin`

-   which is NOT on the persistent (logon) PATH, so a fresh-logon daemon won't resolve it (the seed/pulse

-   claude turns no-op). Separate from the digest/psyche interim; flag if it bites the live psyche LLM.

-2. **Per-OS re-release**: pack adapter-windows + adapter-linux .spt (zigbuild cross; zig @ ~/.sptc-zig;

-   recipe in docs/RELEASE-RUNBOOK.md), attach BOTH to a NEW release w/ updated manifest ([update] +

-   dropped interim). REBUILD the psyche .exe first (the fix is in source; install-dir exe was hand-deployed).

-3. **Live gh_release auto-update test** with the new release.

-4. **cplugs republish v0.1.2** (coupled AFTER per-OS release): os-detecting setup floor + ccs (#7) +

+- TASK 1 ✓ psyche fix + proof green (ddf1965).

+- TASK 2 ✓ F-006 RETIRED: digest + psyche BOTH proven from install-dir (interim moved aside, RELDIR off

+  PATH); interim PATH-copy step dropped from both setup bodies; interim copies deleted; F-009/F-010

+  findings logged in docs/SPT-CORE-FINDINGS.md (717efd2). docs-drift + traceable-reqs green.

+## REMAINING → see `PEROS-RERELEASE-PLAN.md` (JIT plan, committed)

+3. **Per-OS re-release** [OUTWARD-FACING — confirm w/ operator]: REBUILD binaries first (psyche fix is

+   in source; install-dir exe was hand-deployed, NOT packaged), pack adapter-windows + adapter-linux

+   .spt (zigbuild cross; zig @ ~/.sptc-zig), cut GitHub release w/ BOTH assets + updated manifest +

+4. **Live gh_release auto-update test** (re-acquire new [update]-bearing manifest first). No doyle needed.

+5. **cplugs republish v0.1.2** (coupled AFTER per-OS release per RELEASE-RUNBOOK ordering).

+   CAVEAT (flag if it bites): psyche runner calls `claude` by bare name; `claude` @ ~/.local/bin is NOT

+   on the persistent logon PATH → fresh-logon daemon's psyche seed/pulse turns no-op (runner stays

+   resident, claude turns fail). Separate from F-006. Verify on a real fresh-logon live session.

+## doyle report STILL PENDING (offline). Retry `spt send doyle --from perri` when reachable.


Commit the JIT plan and retry the doyle send (in case he's back).


Bash

cd "C:\Users\decid\Documents\projects\spt-claude-code"
git add PEROS-RERELEASE-PLAN.md
git commit -q -F - <<'EOF'
plan(release): JIT plan for per-OS re-release + cplugs v0.1.2

Captures the remaining v0.8.1 follow-through (rebuild binaries, pack win+linux
.spt, cut GitHub release, gh_release auto-update test, cplugs republish). The
GitHub release is outward-facing — gated on operator go-ahead. Prereqs (psyche
fix ddf1965 + F-006 retirement 717efd2) are done and green.

Co-authored by: perri
EOF
echo "committed JIT plan: $(git log --oneline -1)"
echo "=== retry doyle send ==="
unset SPT_AGENT_ID OWL_SESSION_ID SPTC_CI_ID
echo "v0.8.1 psyche FIXED (greedy --prompt, commit ddf1965). Root cause F-009: spt-core whitespace-splits substituted {psyche_prompt} -> runner exited 2 on stray argv -> phantom host (no psyche_host_error). REQ-INSTALL-11/F-006 proven+retired. Two findings for you in docs/SPT-CORE-FINDINGS.md (F-009 command-templating split; F-010 silent-exit masking). Full report in ddf1965 + retry-queued. -- perri" | spt send doyle --from perri 2>&1
echo "send rc=$?"

Commit JIT plan + retry doyle send


committed JIT plan: 0a5e9e1 plan(release): JIT plan for per-OS re-release + cplugs v0.1.2
=== retry doyle send ===
NO_PERCH:doyle is not listening
send rc=1


doyle still offline — report is durably captured (commit ddf1965, `docs/SPT-CORE-FINDINGS.md` F-009/F-010, memory; send queued for retry). Final cleanup of diagnosis-run perches, then status.


cd "C:\Users\decid\Documents\projects\spt-claude-code"
for p in $(tasklist 2>/dev/null | grep -i claude-spt-psyche | awk '{print $2}'); do taskkill //PID "$p" //T //F >/dev/null 2>&1; done
# shutdown leftover diagnosis perches
spt daemon status 2>&1 | sed -n '/local endpoints/,$p' | grep -oE "sptc-(diag|fresh|argv|fix|uniq|nointerim|psy)[a-z0-9-]*" | sort -u | while read id; do
  spt endpoint shutdown "$id" >/dev/null 2>&1; spt endpoint stop "$id" >/dev/null 2>&1
done
echo "cleaned. remaining claude-spt-psyche procs: $(tasklist 2>/dev/null | grep -ci claude-spt-psyche)"
echo "=== final state ==="
echo "git: $(git log --oneline -3 | tr '\n' ' | ')"
echo "tree: $(git status -s | wc -l) uncommitted files"
spt --version

Final cleanup + state summary


cleaned. remaining claude-spt-psyche procs: 0
=== final state ===
git: 0a5e9e1 plan(release): JIT plan for per-OS re-release + cplugs v0.1.2 717efd2 docs(setup): retire F-006 PATH interim — REQ-INSTALL-11 install-dir resolution proven ddf1965 fix(psyche): greedy --prompt — survive spt-core's whitespace-split of {psyche_prompt}
tree: 0 uncommitted files
spt 0.8.1


Done with this body of work. Checkpoint clean: tree committed, no stray processes, spt on 0.8.1.

## What happened

**v0.8.1 ping → psyche blocker RESOLVED.** Root cause was NOT the suspected net-race/reconcile gap.

**Real bug (F-009):** spt-core substitutes `{psyche_prompt}` into the `[session.psyche_init]` command **string** then **whitespace-splits**. Multi-word prompt exploded into 7 stray argv tokens:
```
--prompt PSYCHE REVIVAL time: epoch-ms:… incoming event: (none)
```
Runner's non-greedy `--prompt` took `PSYCHE`, rejected `REVIVAL` → exit 2 instantly. Daemon's detached `spawn()` returned Ok → phantom host (info.json `online`, dead pid, no `psyche_host_error`). Exactly your symptom.

**Found it** via argv-capture instrumentation (deployed instrumented exe, dumped raw argv, reverted).

## Shipped (committed, all gates green)

- **ddf1965** — runner `--prompt` now terminal+greedy (slurps trailing tokens). Psyche stays **resident** full window (was 0 procs every prior run). `live-relay-int.sh` psyche leg flips skip→**ASSERT green**. +2 unit tests.
- **717efd2** — **F-006 RETIRED**: digest + psyche BOTH proven resolving from install-dir (REQ-INSTALL-11) with interim off PATH. Dropped interim PATH-copy from both `/sptc:setup` bodies, deleted interim copies. Logged **F-009** (command-templating split) + **F-010** (silent-exit masking) for doyle.
- **0a5e9e1** — JIT plan for the remaining re-release.

## Flags

- **doyle OFFLINE** — F-009/F-010 report can't deliver (NO_PERCH). Durably captured in commit ddf1965 + `docs/SPT-CORE-FINDINGS.md`; send queued for retry.
- **Owl reachability dropped** — daemon restart (old daemon was `peer pump: STALLED`) killed the event monitor. Not re-established.
- **Peer pump re-STALLS ~7-8min after every daemon start** — recurring spt-core correlate, but did NOT block hosting.
- **Latent:** psyche runner calls `claude` by bare name; `claude` (`~/.local/bin`) not on persistent logon PATH → fresh-logon daemon's psyche claude-turns will no-op (runner stays alive, turns fail). Flagged in the plan.

## Decision point

Tasks 3-5 (per-OS re-release → gh_release auto-update test → cplugs v0.1.2) are next, but **cutting a GitHub release is outward-facing** — published v0.1.0 still has the broken psyche + interim. Plan ready in `PEROS-RERELEASE-PLAN.md`.

Want me to proceed with the re-release now (rebuild → cross-build linux → pack both `.spt` → publish), or hold? I'd recommend doing the local build+pack regardless and pausing only at the actual GitHub publish.


doyle isn't offline, you are. /revive perri


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


You right — daemon restart killed MY perch, not doyle's. NO_PERCH was me being unreachable to send. Reviving.


Launching skill: spt:revive