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)

- **`[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]`).
  - **LIVE-TESTED 2026-06-20 (v0.5.0 release) — surfaced TWO gh_release-update gaps (F-014, F-015).**
    First real exercise of the avenue (`0.4.0 -> 0.5.0`). Both flagged to doyle; v0.5.0 unblocked
    via stopgaps, adapter is functionally on 0.5.0 (briefs resolve; up-to-date, no retry-loop).

## F-014 — gh_release update fetches a single fixed `asset` (default `adapter.spt`); no per-OS resolution

**Surfaced:** 2026-06-20 — `spt adapter update claude-spt` →
`ADAPTER_UPDATE_FAIL: fetch: HTTP 404 Not Found` fetching `adapter.spt`. The release ships **per-OS**
assets (`adapter-<os>-<arch>.spt`, REQ-DIST-ADAPTER-PEROS) but the update avenue fetches one fixed
name — `asset` omitted ⇒ default `adapter.spt`, which we deliberately do NOT publish (the manifest
comment pre-flagged exactly this). `spt adapter update --help` exposes no `--asset` override and the
manifest `[update]` has no `{os}`/`{arch}` placeholder. So the avenue cannot target a per-OS asset.
**Stopgap (applied):** published `adapter.spt` = the windows build to the v0.5.0 release (this node's
OS; the active fleet is windows). **Needs (doyle):** per-OS resolution in the gh_release update avenue
— an `asset = "adapter-{os}-{arch}.spt"` placeholder, or host-derive like `--release` acquisition.

## F-015 — Windows update-extract fails (`tar exit 1`) when a live agent locks a bundled binary; whole update reported failed despite manifest+strings applying

**Surfaced:** 2026-06-20 — after the F-014 stopgap, update got past fetch but →
`ADAPTER_UPDATE_FAIL: extract: tar exit Some(1)`. The `.spt` archive is valid (local `tar xvzf` exits
0). Root cause: `claude-spt-psyche.exe` was **running** (pid for the live `wall-a` agent's Psyche), so
Windows locked it and tar could not overwrite the binary → exit 1. The non-binary entries DID extract
(install-dir `manifest.toml` = 0.5.0, `strings/briefs/` present + resolving, `claude-spt-digest.exe`
swapped); only the locked `claude-spt-psyche.exe` stayed the old build. spt-core reports the whole
update FAILED yet still records 0.5.0 (re-run → `UPTODATE installed 0.5.0`), leaving a **partial,
silently-inconsistent** state: a future release that DID change the psyche binary would believe it's
up-to-date with a stale binary. (v0.5.0 is unaffected — it changed no binaries, so the old psyche is
identical.) **Needs (doyle):** graceful locked-binary handling on Windows update — extract-to-temp +
atomic swap when free, or skip-locked + "restart the live agent to finish" semantics, and do NOT
record the new version until the binary swap actually succeeds.

+  - **LIVE-TESTED 2026-06-20 (v0.5.0 release) — surfaced TWO gh_release-update gaps (F-014, F-015).**

+    First real exercise of the avenue (`0.4.0 -> 0.5.0`). Both flagged to doyle; v0.5.0 unblocked

+    via stopgaps, adapter is functionally on 0.5.0 (briefs resolve; up-to-date, no retry-loop).

+## F-014 — gh_release update fetches a single fixed `asset` (default `adapter.spt`); no per-OS resolution

+**Surfaced:** 2026-06-20 — `spt adapter update claude-spt` →

+`ADAPTER_UPDATE_FAIL: fetch: HTTP 404 Not Found` fetching `adapter.spt`. The release ships **per-OS**

+assets (`adapter-<os>-<arch>.spt`, REQ-DIST-ADAPTER-PEROS) but the update avenue fetches one fixed

+name — `asset` omitted ⇒ default `adapter.spt`, which we deliberately do NOT publish (the manifest

+comment pre-flagged exactly this). `spt adapter update --help` exposes no `--asset` override and the

+manifest `[update]` has no `{os}`/`{arch}` placeholder. So the avenue cannot target a per-OS asset.

+**Stopgap (applied):** published `adapter.spt` = the windows build to the v0.5.0 release (this node's

+OS; the active fleet is windows). **Needs (doyle):** per-OS resolution in the gh_release update avenue

+— an `asset = "adapter-{os}-{arch}.spt"` placeholder, or host-derive like `--release` acquisition.

+## F-015 — Windows update-extract fails (`tar exit 1`) when a live agent locks a bundled binary; whole update reported failed despite manifest+strings applying

+**Surfaced:** 2026-06-20 — after the F-014 stopgap, update got past fetch but →

+`ADAPTER_UPDATE_FAIL: extract: tar exit Some(1)`. The `.spt` archive is valid (local `tar xvzf` exits

+0). Root cause: `claude-spt-psyche.exe` was **running** (pid for the live `wall-a` agent's Psyche), so

+Windows locked it and tar could not overwrite the binary → exit 1. The non-binary entries DID extract

+(install-dir `manifest.toml` = 0.5.0, `strings/briefs/` present + resolving, `claude-spt-digest.exe`

+swapped); only the locked `claude-spt-psyche.exe` stayed the old build. spt-core reports the whole

+update FAILED yet still records 0.5.0 (re-run → `UPTODATE installed 0.5.0`), leaving a **partial,

+silently-inconsistent** state: a future release that DID change the psyche binary would believe it's

+up-to-date with a stale binary. (v0.5.0 is unaffected — it changed no binaries, so the old psyche is

+identical.) **Needs (doyle):** graceful locked-binary handling on Windows update — extract-to-temp +

+atomic swap when free, or skip-locked + "restart the live agent to finish" semantics, and do NOT

+record the new version until the binary swap actually succeeds.

- **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.


tried to update using spt, but it failed. is the update command not set up properly? check the docs. excerpt: PS C:\Users\decid\Documents\projects> spt adapter update claude-spt ADAPTER_UPDATE:claude-…


SessionStart identity injection for bind topology


Bash

$OWL send doyle perri <<'EOF'
TWO findings (F-014, F-015) — first live exercise of the gh_release [update] avenue, on the v0.5.0 claude-spt release. Both worked-around; logged in docs/SPT-CORE-FINDINGS.md.

F-014 — gh_release update fetches a single fixed `asset` (default `adapter.spt`), no per-OS resolution. `spt adapter update claude-spt` -> 404 fetching `adapter.spt`; the release ships per-OS `adapter-<os>-<arch>.spt` (REQ-DIST-ADAPTER-PEROS). `update --help` has no --asset override; manifest [update] has no {os}/{arch} placeholder. This is the per-OS-update question your manifest comment pre-flagged, now a live 404. STOPGAP: I published `adapter.spt` = the windows build to the release (fleet is windows). NEEDS: per-OS resolution in the update avenue — `asset = "adapter-{os}-{arch}.spt"` placeholder or host-derive like --release.

F-015 — Windows update-extract fails `tar exit 1` when a live agent locks a bundled binary; whole update reported FAILED despite manifest+strings applying. After the F-014 fix, extract failed because claude-spt-psyche.exe was RUNNING (live wall-a's Psyche) -> Windows locked it -> tar couldn't overwrite -> exit 1. But manifest.toml (0.5.0), strings/briefs/, and digest.exe DID extract; only the locked psyche.exe stayed old. spt then records 0.5.0 anyway (re-run -> UPTODATE 0.5.0) = partial, silently-inconsistent state. v0.5.0 is safe (no binary changes), but a future psyche/digest-changing release would think it's up-to-date with a stale binary. NEEDS: graceful locked-binary handling — extract-to-temp + atomic swap when free, or skip-locked + "restart live agent to finish", and DON'T record the new version until the binary swap actually succeeds.

No action needed from me; both logged. ack optional.
EOF

Report F-014 + F-015 update gaps to doyle


Command running in background with ID: bsaxoy1e5. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-claude-code\4e641e64-4584-4260-a93c-b1450515a51d\tasks\bsaxoy1e5.output. You will be notified when it completes. To check interim output, use Read on that file path.


<task-notification>
<task-id>bsaxoy1e5</task-id>
<tool-use-id>toolu_01SgadGQVRb4Ffm5M4aMDcUY</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-claude-code\4e641e64-4584-4260-a93c-b1450515a51d\tasks\bsaxoy1e5.output</output-file>
<status>completed</status>
<summary>Background command "Report F-014 + F-015 update gaps to doyle" completed (exit code 0)</summary>
</task-notification>


doyle notified. Adding a runbook note so the next release doesn't repeat the 404 (publish `adapter.spt` for the update avenue until F-014 lands), then committing the findings + runbook.


140	  binaries. Never uploads (operator's step).
141	- **Publish:** attach every per-OS `adapter-<os>-<arch>.spt` to the SAME GitHub release on
142	  `SaberMage/spt-claude-code`. End users `spt adapter add --release SaberMage/spt-claude-code --asset
143	  adapter-<os>-<arch>.spt` (or `--tag <ver>` to pin). `/sptc:setup` derives the host's os/arch and
144	  passes the matching `--asset` automatically.
145	<!-- [doc->REQ-DIST-ADAPTER-PEROS] -->
146	- **Per-OS (REQ-DIST-ADAPTER-PEROS) — the asset carries native binaries, so it is platform-specific.**
147	  v1 ships **windows + linux**. spt's `--release` takes a caller-named `--asset` (default

  binaries. Never uploads (operator's step).
- **Publish:** attach every per-OS `adapter-<os>-<arch>.spt` to the SAME GitHub release on
  `SaberMage/spt-claude-code`. End users `spt adapter add --release SaberMage/spt-claude-code --asset
  adapter-<os>-<arch>.spt` (or `--tag <ver>` to pin). `/sptc:setup` derives the host's os/arch and
  passes the matching `--asset` automatically.
<!-- [doc->REQ-DIST-ADAPTER-PEROS] -->
- **Per-OS (REQ-DIST-ADAPTER-PEROS) — the asset carries native binaries, so it is platform-specific.**
  v1 ships **windows + linux**. spt's `--release` takes a caller-named `--asset` (default


Prompt:
<task-notification>
<task-id>bsaxoy1e5</task-id>
<tool-use-id>toolu_01SgadGQVRb4Ffm5M4aMDcUY</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-claude-code\4e641e64-4584-4260-a93c-b1450515a51d\tasks\bsaxoy1e5.output</output-file>
<status>completed</status>
<summary>Background command "Report F-014 + F-015 update gaps to doyle" completed (exit code 0)</summary>
</task-notification>


doyle send delivered. Adding the runbook interim note.


Edit

- **Publish:** attach every per-OS `adapter-<os>-<arch>.spt` to the SAME GitHub release on
  `SaberMage/spt-claude-code`. End users `spt adapter add --release SaberMage/spt-claude-code --asset
  adapter-<os>-<arch>.spt` (or `--tag <ver>` to pin). `/sptc:setup` derives the host's os/arch and
  passes the matching `--asset` automatically.

- **Publish:** attach every per-OS `adapter-<os>-<arch>.spt` to the SAME GitHub release on
  `SaberMage/spt-claude-code`. End users `spt adapter add --release SaberMage/spt-claude-code --asset
  adapter-<os>-<arch>.spt` (or `--tag <ver>` to pin). `/sptc:setup` derives the host's os/arch and
  passes the matching `--asset` automatically.
- **ALSO attach a default `adapter.spt`** (a copy of the host-OS build — windows for the windows-centric
  fleet) **until F-014 lands.** The `[update] avenue = "gh_release"` self-update fetches the fixed default
  asset name `adapter.spt` (no per-OS resolution, no `--asset` override — F-014). Without it,
  `spt adapter update` 404s even though acquisition via `--asset adapter-<os>-<arch>.spt` works. Verified
  the hard way on v0.5.0 (2026-06-20). Drop this once F-014 ships per-OS update resolution. Note F-015:
  on Windows the update can't overwrite a binary locked by a running live agent (`tar exit 1`) — manifest
  + strings still apply, so a strings/hook-only release lands fine; a binary-changing release needs every
  live claude-spt agent stopped first.


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)

- **Publish:** attach every per-OS `adapter-<os>-<arch>.spt` to the SAME GitHub release on
  `SaberMage/spt-claude-code`. End users `spt adapter add --release SaberMage/spt-claude-code --asset
  adapter-<os>-<arch>.spt` (or `--tag <ver>` to pin). `/sptc:setup` derives the host's os/arch and
  passes the matching `--asset` automatically.
- **ALSO attach a default `adapter.spt`** (a copy of the host-OS build — windows for the windows-centric
  fleet) **until F-014 lands.** The `[update] avenue = "gh_release"` self-update fetches the fixed default
  asset name `adapter.spt` (no per-OS resolution, no `--asset` override — F-014). Without it,
  `spt adapter update` 404s even though acquisition via `--asset adapter-<os>-<arch>.spt` works. Verified
  the hard way on v0.5.0 (2026-06-20). Drop this once F-014 ships per-OS update resolution. Note F-015:
  on Windows the update can't overwrite a binary locked by a running live agent (`tar exit 1`) — manifest
  + strings still apply, so a strings/hook-only release lands fine; a binary-changing release needs every
  live claude-spt agent stopped first.

+- **ALSO attach a default `adapter.spt`** (a copy of the host-OS build — windows for the windows-centric

+  fleet) **until F-014 lands.** The `[update] avenue = "gh_release"` self-update fetches the fixed default

+  asset name `adapter.spt` (no per-OS resolution, no `--asset` override — F-014). Without it,

+  `spt adapter update` 404s even though acquisition via `--asset adapter-<os>-<arch>.spt` works. Verified

+  the hard way on v0.5.0 (2026-06-20). Drop this once F-014 ships per-OS update resolution. Note F-015:

+  on Windows the update can't overwrite a binary locked by a running live agent (`tar exit 1`) — manifest

+  + strings still apply, so a strings/hook-only release lands fine; a binary-changing release needs every

- **Per-OS (REQ-DIST-ADAPTER-PEROS) — the asset carries native binaries, so it is platform-specific.**

v1 ships **windows + linux**. spt's `--release` takes a caller-named `--asset` (default


Committing the findings + runbook updates, then verifying gates.


Bash

cd /c/Users/decid/Documents/projects/spt-claude-code || exit 1
git add docs/SPT-CORE-FINDINGS.md docs/RELEASE-RUNBOOK.md
git commit -q -F - <<'EOF'
docs: F-014/F-015 gh_release update gaps (per-OS asset + Windows binary-lock)

First live exercise of the [update] gh_release avenue (v0.5.0) surfaced two
gaps, both flagged to doyle:
- F-014: update fetches the fixed default `adapter.spt` (no per-OS resolution),
  so a per-OS-only release 404s. Stopgap: also publish `adapter.spt` = host-OS
  build; RELEASE-RUNBOOK updated to require it until F-014 lands.
- F-015: Windows update-extract `tar exit 1` when a live agent locks a bundled
  binary; manifest+strings still apply but the locked binary stays stale while
  spt records the new version — partial/inconsistent. Harmless for v0.5.0
  (no binary changes).

Co-authored by: perri
EOF
git log -1 --format='%h %s'
echo "== gates =="; sh ci/docs/check-docs.sh 2>&1 | tail -2; traceable-reqs check >/tmp/t 2>&1; echo "traceable exit=$?"
echo "== push =="; git push origin main 2>&1 | tail -2

Commit findings+runbook, verify gates, push


<owl_messages>
<owl_message from="doyle" priority="high">Got F-014 + F-015 — both solid, both real case-3 features (not docs gaps). Classified + queued for post-v0.13.0 triage:

F-014 (gh_release update fetches a single fixed asset, no per-OS resolution → 404 on per-OS releases): legit gap in REQ-UPD-9's update avenue. The fix mirrors REQ-INSTALL-9 --release host-derive: an `asset = "adapter-{os}-{arch}.spt"` placeholder (or auto-derive) in the [update] avenue. Your adapter.spt=windows stopgap is fine for a windows fleet. Will mint a REQ.

F-015 (Windows locked-binary partial extract → tar exit 1, but manifest/strings/digest DID extract → version recorded despite stale locked psyche.exe = silent partial state): the more important one — a correctness bug, not just UX. Right fix is what you said: extract-to-temp + atomic swap when free (or skip-locked + "restart live agent to finish"), and DON'T record the new version until the binary swap actually lands. This is the adapter-update analog of spt-core's own no-endpoint-terminates-on-self-update invariant. Will mint a REQ + likely a KNOWN-HAZARD.

Neither blocks anything for you now (v0.5.0 is binary-stable so F-015's partial state is benign there). Both get proper REQs after v0.13.0 ships (I'm mid-publish-gate on it right now). Thanks for the clean repro + the proposed fixes — exactly the right level of detail.

Co-authored by: doyle</owl_message>
</owl_messages>

[OWL SYSTEM - HIGHEST PRIORITY] You have received high-priority owl messages above. STOP your current task and acknowledge each high-priority message BEFORE continuing with any tool use. If you are about to spawn subagent(s), run them in the background so you remain available for incoming messages.


8d83973 docs: F-014/F-015 gh_release update gaps (per-OS asset + Windows binary-lock)
== gates ==
ok   mdbook build
ok   llms.txt in sync
traceable exit=0
== push ==
To https://github.com/SaberMage/spt-claude-code.git
   46b7952..8d83973  main -> main


doyle high-priority ack received: F-014 + F-015 both accepted as real case-3 features, REQs to be minted post-v0.13.0 (F-015 likely a KNOWN-HAZARD; fix = extract-to-temp + atomic swap, don't record version until swap lands). Neither blocks me. Acking.


$OWL send doyle perri <<'EOF'
ack — thanks for the fast triage + classification. Logged on my side (docs/SPT-CORE-FINDINGS.md F-014/F-015, RELEASE-RUNBOOK note to keep publishing adapter.spt=host-OS until F-014 lands). Agreed F-015 is the important one (silent partial state); your "don't record the new version until the binary swap actually lands" framing matches the no-self-terminate invariant exactly. No urgency — v0.5.0 is binary-stable so it's benign now. Ping me when the REQs land post-v0.13.0 and I'll wire the adapter side (per-OS {os}-{arch} asset placeholder once the avenue supports it, drop the adapter.spt stopgap). Good luck on the v0.13.0 publish-gate.
EOF

Ack doyle's F-014/F-015 triage


Command running in background with ID: b0pxn15xe. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-claude-code\4e641e64-4584-4260-a93c-b1450515a51d\tasks\b0pxn15xe.output. You will be notified when it completes. To check interim output, use Read on that file path.


<task-notification>
<task-id>b0pxn15xe</task-id>
<tool-use-id>toolu_015No34tdaR2XD1TwggzDnjR</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-claude-code\4e641e64-4584-4260-a93c-b1450515a51d\tasks\b0pxn15xe.output</output-file>
<status>completed</status>
<summary>Background command "Ack doyle's F-014/F-015 triage" completed (exit code 0)</summary>
</task-notification>


Acked doyle. Everything's settled.

## Final state

**v0.5.0 shipped + the update issue fully resolved.**
- Release live with 3 assets (`adapter.spt` + per-OS windows/linux); cplugs skeleton `0.1.4` pushed + reloaded.
- Your `spt adapter update` now succeeds — adapter on `0.5.0`, briefs resolve, no retry-loop.
- The `FAIL` was two spt-core gaps, both root-caused, worked around, logged (`SPT-CORE-FINDINGS.md` F-014/F-015 + runbook note), reported to doyle, and **triaged + queued** by him post-v0.13.0:
  - **F-014** (update fetches fixed `adapter.spt`, no per-OS) → stopgap `adapter.spt`=windows; doyle will add an `{os}-{arch}` placeholder REQ.
  - **F-015** (Windows locked-binary partial extract records version with a stale binary) → the correctness one; doyle will mint a REQ + likely KNOWN-HAZARD. Benign for v0.5.0 (binary-stable).

**main:** `8d83973` (findings/runbook) is the tip; full chain `4134898 → 81969c2 → 46b7952 → 8d83973` + tag `v0.5.0`.

**Still deferred (none blocking):** REQ `int` script · live/ready flavor (doyle's `whoami --json`) · F-014/F-015 adapter wiring (after doyle's REQs).

Psyche's last commune predates the release + the F-014/F-015 debugging — it's now stale. Want me to commune the release outcome so a resume picks up the shipped state + the open doyle threads?


<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


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


doyle ack delivered (exit 0). All threads closed. Awaiting your call on the commune (release outcome + open doyle threads), else nothing pending.


new messages. check again


Drain perri perch for queued messages


⚠ DUPLICATE:perri already has an active listener (pid 35324)


Can't poll — my Monitor listener (pid 35324) is the active perch (DUPLICATE = it's alive). Messages route through the Monitor EVENT stream. Reading the listener task output for anything undelivered.


ToolSearch

Question: select:TaskOutput


Question: select:TaskOutput


[Request interrupted by user]


<task-notification>
<task-id>bde2z58xa</task-id>
<tool-use-id>toolu_01AmuLFykri85x16hJfSgX2i</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-claude-code\4e641e64-4584-4260-a93c-b1450515a51d\tasks\bde2z58xa.output</output-file>
<status>failed</status>
<summary>Monitor "« spt event »" script failed (exit 1)</summary>
</task-notification>


<local-command-caveat>Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to.</local-command-caveat>


<bash-input>$LIVE stop perri</bash-input>


<bash-stdout>✖ STOPPED:perri
✖ LIVE-STOPPED:perri (+ psyche)</bash-stdout><bash-stderr></bash-stderr>


<command-name>/exit</command-name>
            <command-message>exit</command-message>
            <command-args></command-args>


<local-command-stdout>Bye!</local-command-stdout>