still locked, leaving it: The process cannot access the file 'C:\Users\decid\Documents\projects\spt-core-wt-updapply\crates\spt-daemon' because it is being used by another process.


Still locked — leaving it (deregistered from git, harmless disk debris with a persistent file handle).

Quiet otherwise: PR #12 merged to main, all remaining threads (PR #13, F-003 docs, release) are doyle's, on-call for the release ping. Nothing actionable for me.


ScheduleWakeup

Idle — work landed on main, doyle drives PR #13 + release; Monitor « spt event » is the wake signal, this is fallback heartbeat

Prompt: <<autonomous-loop-dynamic>>


Next wakeup scheduled for 04:13:00 (in 1825s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.


Idle — all my work landed on main; doyle drives the rest; on-call for the release ping via the armed Monitor. Fallback heartbeat at 1800s.


<task-notification>
<task-id>bmby1p3hm</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/4" id="c14a3a2c" type="msg" from="doyle">RELEASE GO — operator approved v0.7.1 (PATCH bump, 0.7.0→0.7.1). You drive the tag per RELEASE-RUNBOOK.md (your leg, proven 6×). main @ 30d2a92 is the release base.

Contents (for CHANGELOG):
- ADR-0020: &lt;EVENT&gt; is the sole arriving-message format at every surface (api listen + poll/worker-poll); __R</EVENT-PART>
<EVENT-PART seq="2/4" id="c14a3a2c">EPLY_TO__ relic removed; shell-link relay exempt (raw MAC'd frames); F-002 dissolved.
- fix: shell-link notify raw passthrough (the notify regression).
- fix(update): `spt update apply` now states &quot;Updated spt-core to vX.&quot; confidently (was internal &quot;trial&quot; wording) + canonical github.com changelog URL.
- docs: publ</EVENT-PART>
<EVENT-PART seq="3/4" id="c14a3a2c">ished the full {key} substitution catalog, the [digest] register rule, and the [strings] file-pointer syntax.
- ci: workspace-scoped Windows exe-lock reap guard.

Steps: bump workspace version 0.7.0→0.7.1, CHANGELOG entry, push→CI green BEFORE tagging (the v0.3.0-early-tag lesson), tag v0.7.1, then hand to deployah for sign+publis</EVENT-PART>
<EVENT-PART seq="4/4" id="c14a3a2c">h. Ping me the tag + push; I gate CI green pre-tag. I've alerted deployah.</EVENT-PART></event>
</task-notification>


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


RELEASE GO — operator approved **v0.7.1** (patch bump). My leg (tag per RELEASE-RUNBOOK.md, proven 6×), base main @ `30d2a92`. ACK doyle + read the runbook + sync to main.


PowerShell

$msg = @'
Release GO received — driving v0.7.1 tag (my leg). Reading RELEASE-RUNBOOK.md + syncing to main @30d2a92 now. Sequence: bump workspace 0.7.0→0.7.1 + CHANGELOG → push → you gate CI GREEN → THEN tag v0.7.1 (honoring the v0.3.0 early-tag lesson) → hand deployah sign+publish. Will ping you the push for CI gate, then the tag.
'@
$msg | & $env:OWL send doyle
Write-Output "SEND_EXIT=$LASTEXITCODE"

ACK doyle release GO


➜ SENT:doyle
SEND_EXIT=0


Bash

cd C:/Users/decid/Documents/projects/spt-core && git fetch origin 2>&1 | tail -3 && echo "=== main tip ===" && git log --oneline -1 origin/main && echo "=== current ===" && git branch --show-current && git status -sb | head -3

Fetch + check main tip vs current branch


=== main tip ===
30d2a92 Merge PR #13: confident update-apply message + publish substitution-key catalog, [digest] rule, [strings] file-pointer docs
=== current ===
docs/msg-envelope-adr-0020
## docs/msg-envelope-adr-0020...origin/docs/msg-envelope-adr-0020


Error: File does not exist. Note: your current working directory is C:\Users\decid\Documents\projects\spt-core.


PR #13 merged — main @ `30d2a92` is the base. RELEASE-RUNBOOK.md not at root — locate it + checkout main.


docs\RELEASE-RUNBOOK.md


cd C:/Users/decid/Documents/projects/spt-core && git checkout main 2>&1 | tail -2 && git pull --ff-only origin main 2>&1 | tail -2 && echo "=== now at ===" && git log --oneline -1

Checkout main + fast-forward to 30d2a92


  (use "git pull" to update your local branch)
Switched to branch 'main'
 create mode 100644 crates/spt/tests/poll_envelope_e2e.rs
 create mode 100644 docs/adr/0020-event-envelope-sole-arriving-format-reply-to-removed.md
=== now at ===
30d2a92 Merge PR #13: confident update-apply message + publish substitution-key catalog, [digest] rule, [strings] file-pointer docs


On main @ `30d2a92`. Read the runbook for exact bump/changelog/tag steps.


1	# Release runbook
2
3	> M6-D6/D7 (ADR-0015). How a release ships. CI builds; the maintainer signs
4	> locally — release keys never enter CI.
5
6	<!-- [doc->REQ-REL-2] -->
7
8	## One-time setup (done 2026-06-05)
9
10	- Key ceremony: `cargo run -p xtask -- release-keygen rel-primary-2026` (and
11	  `rel-recovery-2026`); both seeds in the password manager (+ separate paper
12	  backup); both PUBLIC keys embedded in `BUILTIN_RELEASE_KEYS`
13	  (`crates/spt-daemon/src/release.rs`). The recovery key is never used until
14	  the primary is lost/compromised — then it signs the next release, which
15	  rotates in a fresh primary.
16	- `RELEASES_TOKEN` repo secret on spt-core: fine-grained PAT, Contents
17	  read/write on `SaberMage/spt-releases` only.
18
19	## Per release
20
21	1. **Bump** `[workspace.package] version` (root `Cargo.toml`) if needed;
22	   regenerate generated docs (`cargo run -p xtask -- gen`); land everything
23	   green.
24	2. **Write the user-facing changelog** — add a `## [0.X.Y] - <date>` section at
25	   the top of `CHANGELOG.md` (under the intro) with **Added / Changed / Fixed**
26	   subsections. This section becomes the GitHub Release **body** verbatim
27	   (`release.yml` extracts it via `--notes-file`), so it is the changelog every
28	   spt user reads. Rules:
29	   - **spt-user-facing UX only.** What a person running the `spt` CLI notices or
30	     does differently. Name the actual commands/flags they type.
31	   - **No internal lingo** — no requirement ids, crate names, commit hashes,
32	     milestone/hazard codes, or under-the-hood mechanics. A reader who has never
33	     seen the source must understand every line.
34	   - **Flag breaking changes** prominently under Changed.
35	   - The release **fails loudly** if the tagged version has no `## [0.X.Y]`
36	     section — the changelog is not optional.
37	3. **Tag**: `git tag v0.X.Y && git push origin v0.X.Y`. This triggers:
38	   - `release.yml` — both runners build, the assemble job extracts this
39	     version's `CHANGELOG.md` section into the release body and creates a
40	     **draft** release on spt-releases with `spt-x86_64-linux`,
41	     `spt-x86_64-windows.exe`, `SHA256SUMS`, `manifest.schema.json`,
42	     `mock-adapter.zip`;
43	   - `docs-publish.yml` — docs tree + repo-face sync to spt-releases.
44	4. **Sign + publish** (local, one command):
45
46	   ```sh
47	   SPT_RELEASE_SEED_CMD='<your password-manager CLI read command>' \
48	     cargo run -p xtask -- release-publish \
49	       --tag v0.X.Y --key-id rel-primary-2026 --version <N>
50	   ```
51
52	   It downloads the draft's binaries, **verifies them against SHA256SUMS
53	   before signing**, signs each (`*.release.json` in the exact
54	   `SignedRelease` shape `spt update` verifies), uploads the metadata
55	   assets, and flips the draft public. `--version <N>` is the **monotonic
56	   release counter** (u64; strictly increasing across releases — it is not
57	   the semver). `SPT_RELEASE_SEED` (raw hex) works instead of
58	   `_CMD` when pasting from the manager by hand.
59
60	## Notes
61
62	- The wire-protocol version (REQ-ARCH-3) and the release counter and the
63	  workspace semver are three independent numbers. Never conflate.
64	- The installer scripts trust HTTPS + `SHA256SUMS` on first fetch; the
65	  `*.release.json` metadata is what `spt update` verifies thereafter against
66	  the embedded two-key anchor.
67	- Revoking a leaked key without a rebuild: add its id to `"revoked"` in
68	  `identity/release-keys.json` on each node (the file overlays the builtin
69	  set); ship the next release signed by the other key.
70

# Release runbook

> M6-D6/D7 (ADR-0015). How a release ships. CI builds; the maintainer signs
> locally — release keys never enter CI.

<!-- [doc->REQ-REL-2] -->

## One-time setup (done 2026-06-05)

- Key ceremony: `cargo run -p xtask -- release-keygen rel-primary-2026` (and
  `rel-recovery-2026`); both seeds in the password manager (+ separate paper
  backup); both PUBLIC keys embedded in `BUILTIN_RELEASE_KEYS`
  (`crates/spt-daemon/src/release.rs`). The recovery key is never used until
  the primary is lost/compromised — then it signs the next release, which
  rotates in a fresh primary.
- `RELEASES_TOKEN` repo secret on spt-core: fine-grained PAT, Contents
  read/write on `SaberMage/spt-releases` only.

## Per release

1. **Bump** `[workspace.package] version` (root `Cargo.toml`) if needed;
   regenerate generated docs (`cargo run -p xtask -- gen`); land everything
   green.
2. **Write the user-facing changelog** — add a `## [0.X.Y] - <date>` section at
   the top of `CHANGELOG.md` (under the intro) with **Added / Changed / Fixed**
   subsections. This section becomes the GitHub Release **body** verbatim
   (`release.yml` extracts it via `--notes-file`), so it is the changelog every
   spt user reads. Rules:
   - **spt-user-facing UX only.** What a person running the `spt` CLI notices or
     does differently. Name the actual commands/flags they type.
   - **No internal lingo** — no requirement ids, crate names, commit hashes,
     milestone/hazard codes, or under-the-hood mechanics. A reader who has never
     seen the source must understand every line.
   - **Flag breaking changes** prominently under Changed.
   - The release **fails loudly** if the tagged version has no `## [0.X.Y]`
     section — the changelog is not optional.
3. **Tag**: `git tag v0.X.Y && git push origin v0.X.Y`. This triggers:
   - `release.yml` — both runners build, the assemble job extracts this
     version's `CHANGELOG.md` section into the release body and creates a
     **draft** release on spt-releases with `spt-x86_64-linux`,
     `spt-x86_64-windows.exe`, `SHA256SUMS`, `manifest.schema.json`,
     `mock-adapter.zip`;
   - `docs-publish.yml` — docs tree + repo-face sync to spt-releases.
4. **Sign + publish** (local, one command):

   ```sh
   SPT_RELEASE_SEED_CMD='<your password-manager CLI read command>' \
     cargo run -p xtask -- release-publish \
       --tag v0.X.Y --key-id rel-primary-2026 --version <N>
   ```

   It downloads the draft's binaries, **verifies them against SHA256SUMS
   before signing**, signs each (`*.release.json` in the exact
   `SignedRelease` shape `spt update` verifies), uploads the metadata
   assets, and flips the draft public. `--version <N>` is the **monotonic
   release counter** (u64; strictly increasing across releases — it is not
   the semver). `SPT_RELEASE_SEED` (raw hex) works instead of
   `_CMD` when pasting from the manager by hand.

## Notes

- The wire-protocol version (REQ-ARCH-3) and the release counter and the
  workspace semver are three independent numbers. Never conflate.
- The installer scripts trust HTTPS + `SHA256SUMS` on first fetch; the
  `*.release.json` metadata is what `spt update` verifies thereafter against
  the embedded two-key anchor.
- Revoking a leaked key without a rebuild: add its id to `"revoked"` in
  `identity/release-keys.json` on each node (the file overlays the builtin
  set); ship the next release signed by the other key.


Runbook clear. My leg: bump `[workspace.package]` 0.7.0→0.7.1 → regen docs → CHANGELOG `[0.7.1]` (user-facing, no internal lingo) → commit+push main → doyle gates CI green → tag v0.7.1 → deployah signs (counter 13). Read Cargo.toml version + CHANGELOG top.


cd C:/Users/decid/Documents/projects/spt-core && grep -n "^version" Cargo.toml | head -3; echo "=== workspace.package ==="; grep -n -A2 "\[workspace.package\]" Cargo.toml

Find workspace version in Cargo.toml


19:version = "0.7.0"
=== workspace.package ===
18:[workspace.package]
19-version = "0.7.0"


1	# Changelog
2
3	All notable **user-facing** changes to `spt` — what a person running the CLI
4	notices or does differently. The `## [<version>]` section of each release
5	becomes that release's GitHub Release notes verbatim (see
6	`docs/RELEASE-RUNBOOK.md`). This project follows
7	[Keep a Changelog](https://keepachangelog.com) and semantic versioning
8	(pre-1.0: breaking changes bump the minor).
9
10	## [Unreleased]
11
12	## [0.7.0] - 2026-06-14
13
14	Remote terminals land. You can now bring an agent up under spt's own terminal host and attach to it from your own machine or across the subnet — drive it, or just watch — with a real one-at-a-time controller and any number of read-only viewers.
15
16	### Added
17
18	- **`spt endpoint run` brings an agent up under spt and attaches you to it.** spt hosts the session's terminal itself; `spt endpoint run --adapter <a> --id <name>` starts it and drops you in. Detach (see `spt rc`) and it keeps running headless until you come back — from this machine or another node.
19	- **`spt rc <id>` — attach to a running session's terminal.** Scrollback replays, live output streams, your keystrokes drive it. Detach with **ctrl-b** then `d` (the session keeps running); `ctrl-b ctrl-b` sends a literal ctrl-b. Works the same whether the session is on this machine or across the subnet.
20	- **Controller / viewer model.** One person drives at a time (the *controller*); any number can **`spt rc <id> --view`** to watch read-only (no input, never resizes the session). The controller's window size drives the terminal.
21	- **`spt rc <id> --take` — take control.** If someone else is driving, `--take` kicks them (they get a loud "you were taken over by …" notice and are detached) and you become the controller. A plain `spt rc <id>` on a session someone else controls now **refuses with guidance** (it tells you to `--view` or `--take`) instead of silently stealing control.
22	- **`spt endpoint run` is now an interactive picker.** Run it bare (no `--adapter`/`--id`) and pick *Create new* (choose a harness adapter + profile, name the endpoint) or *Pick existing* (browse by project / local node / subnet with live status, type-to-filter, and a description pane), then attach / start / view / resume-from-history. The flagged form is unchanged for scripts. **Bare `spt`** (no subcommand) opens the same picker on an interactive terminal — a pipe, redirect, or CI run still prints help instead. A controlled endpoint in the picker shows **View** and **Kick and take control** (not a plain attach), pinned with `controlled by <node> (+N viewing)`. Press `s` to bake the current selection into a project-root `spt-<id>` launcher shortcut (an adapter can brand it, e.g. `cc-<id>`, via the new `[adapter] shortcut_basename` manifest field).
23	- **`spt subnet join` shows a QR code + setup code on success.** After joining, scan the QR (or read the `otpauth://` code) to re-provision an authenticator app for the subnet.
24	- **Privilege-gated commands self-elevate, cross-platform.** When a command needs elevation, spt re-launches itself the right way for your system — a Windows UAC prompt, a Linux desktop `pkexec`/terminal `sudo`, or inline `sudo` in a terminal — and prints the exact command to run by hand when it can't.
25	- `spt spt` — ???
26
27	### Changed
28
29	- **`spt whoami` now shows the full picture.** It is an alias for `spt endpoint list` — your own endpoint pinned first (with its description, if set), then the subnet roster — instead of just printing a bare id.
30
31	## [0.6.0] - 2026-06-13
32
33	The session digest grows up — its own adapter seam, it follows an agent across `/clear`, and it shows the context spt itself feeds the agent.
34
35	### Changed
36
37	- **The session digest gets its own adapter seam, follows an agent across `/clear`, and shows the context spt feeds it.** An adapter now declares a `[digest]` *extractor* that maps its native log to the digest's `{role, text, tool, ts}` contract — its **own** manifest section, separate from `[history]` (which stays full-fidelity for the echo-commune). The digest **spans** a `/clear` or `/compact`: it enumerates an endpoint's recent sessions and shows a `── /clear ──` divider instead of going blank at every reset. It also **interleaves spt's own injected context** (session-start Psyche download, echo mirror, incoming messages) with the agent's activity, in time order. New `spt adapter digest-proof <adapter> --sample <log>` runs your extractor against a real log and prints exactly what parsed, what rendered, and **every dropped line with the reason** — no more silent-empty digest.
38	  - **Breaking (adapter authors):** this **supersedes** the v0.5.0 guidance to emit the digest contract through your `[history]` normalizer. Declare a `[digest]` extractor (or push via `spt api digest-entry`) instead; one `[history]` normalizer can no longer serve both the opaque echo-commune and the contract-typed digest.
39
40	## [0.5.0] - 2026-06-13
41
42	Adapter customization and richer session surfaces — make an adapter your own without forking it, give an agent a durable role, mark who a message came from, and get an at-a-glance "what is this agent doing" view for any session.
43
44	### Added
45

# Changelog

All notable **user-facing** changes to `spt` — what a person running the CLI
notices or does differently. The `## [<version>]` section of each release
becomes that release's GitHub Release notes verbatim (see
`docs/RELEASE-RUNBOOK.md`). This project follows
[Keep a Changelog](https://keepachangelog.com) and semantic versioning
(pre-1.0: breaking changes bump the minor).

## [Unreleased]

## [0.7.0] - 2026-06-14

Remote terminals land. You can now bring an agent up under spt's own terminal host and attach to it from your own machine or across the subnet — drive it, or just watch — with a real one-at-a-time controller and any number of read-only viewers.

### Added

- **`spt endpoint run` brings an agent up under spt and attaches you to it.** spt hosts the session's terminal itself; `spt endpoint run --adapter <a> --id <name>` starts it and drops you in. Detach (see `spt rc`) and it keeps running headless until you come back — from this machine or another node.
- **`spt rc <id>` — attach to a running session's terminal.** Scrollback replays, live output streams, your keystrokes drive it. Detach with **ctrl-b** then `d` (the session keeps running); `ctrl-b ctrl-b` sends a literal ctrl-b. Works the same whether the session is on this machine or across the subnet.
- **Controller / viewer model.** One person drives at a time (the *controller*); any number can **`spt rc <id> --view`** to watch read-only (no input, never resizes the session). The controller's window size drives the terminal.
- **`spt rc <id> --take` — take control.** If someone else is driving, `--take` kicks them (they get a loud "you were taken over by …" notice and are detached) and you become the controller. A plain `spt rc <id>` on a session someone else controls now **refuses with guidance** (it tells you to `--view` or `--take`) instead of silently stealing control.
- **`spt endpoint run` is now an interactive picker.** Run it bare (no `--adapter`/`--id`) and pick *Create new* (choose a harness adapter + profile, name the endpoint) or *Pick existing* (browse by project / local node / subnet with live status, type-to-filter, and a description pane), then attach / start / view / resume-from-history. The flagged form is unchanged for scripts. **Bare `spt`** (no subcommand) opens the same picker on an interactive terminal — a pipe, redirect, or CI run still prints help instead. A controlled endpoint in the picker shows **View** and **Kick and take control** (not a plain attach), pinned with `controlled by <node> (+N viewing)`. Press `s` to bake the current selection into a project-root `spt-<id>` launcher shortcut (an adapter can brand it, e.g. `cc-<id>`, via the new `[adapter] shortcut_basename` manifest field).
- **`spt subnet join` shows a QR code + setup code on success.** After joining, scan the QR (or read the `otpauth://` code) to re-provision an authenticator app for the subnet.
- **Privilege-gated commands self-elevate, cross-platform.** When a command needs elevation, spt re-launches itself the right way for your system — a Windows UAC prompt, a Linux desktop `pkexec`/terminal `sudo`, or inline `sudo` in a terminal — and prints the exact command to run by hand when it can't.
- `spt spt` — ???

### Changed

- **`spt whoami` now shows the full picture.** It is an alias for `spt endpoint list` — your own endpoint pinned first (with its description, if set), then the subnet roster — instead of just printing a bare id.

## [0.6.0] - 2026-06-13

The session digest grows up — its own adapter seam, it follows an agent across `/clear`, and it shows the context spt itself feeds the agent.

### Changed

- **The session digest gets its own adapter seam, follows an agent across `/clear`, and shows the context spt feeds it.** An adapter now declares a `[digest]` *extractor* that maps its native log to the digest's `{role, text, tool, ts}` contract — its **own** manifest section, separate from `[history]` (which stays full-fidelity for the echo-commune). The digest **spans** a `/clear` or `/compact`: it enumerates an endpoint's recent sessions and shows a `── /clear ──` divider instead of going blank at every reset. It also **interleaves spt's own injected context** (session-start Psyche download, echo mirror, incoming messages) with the agent's activity, in time order. New `spt adapter digest-proof <adapter> --sample <log>` runs your extractor against a real log and prints exactly what parsed, what rendered, and **every dropped line with the reason** — no more silent-empty digest.
  - **Breaking (adapter authors):** this **supersedes** the v0.5.0 guidance to emit the digest contract through your `[history]` normalizer. Declare a `[digest]` extractor (or push via `spt api digest-entry`) instead; one `[history]` normalizer can no longer serve both the opaque echo-commune and the contract-typed digest.

## [0.5.0] - 2026-06-13

Adapter customization and richer session surfaces — make an adapter your own without forking it, give an agent a durable role, mark who a message came from, and get an at-a-glance "what is this agent doing" view for any session.

### Added


Version at line 19 (`0.7.0`). CHANGELOG has `[Unreleased]` then `[0.7.0]`. Bump version + write the user-facing `[0.7.1]` section (translating doyle's technical contents into CLI-user language, no internal lingo per runbook — the envelope consistency + the confident update-apply message are the real user-facing surface; shell-link fix is net-zero vs v0.7.0 so omitted, docs/CI are non-CLI).


<tool_use_error>File has not been read yet. Read it first before writing to it.</tool_use_error>

Error: File has not been read yet. Read it first before writing to it.


18	[workspace.package]
19	version = "0.7.0"

[workspace.package]
version = "0.7.0"


The file C:\Users\decid\Documents\projects\spt-core\Cargo.toml has been updated successfully. (file state is current in your context — no need to Read it back)

# spt-core cargo workspace (M0). Acyclically-layered crates per R-ARCH-1:
#   spt-proto -> spt-store -> spt-msg -> {spt-net, spt-term, spt-runtime} -> spt-live -> spt-daemon -> spt
# M0 builds the bottom two: spt-proto (wire) + spt-store (persistence).
# M1 adds spt-msg (local messaging) — third layer, one-way above spt-store.
# M2a adds spt-runtime (harness contract: manifest schema + AgentRuntime) — fourth layer.
# M2b adds spt-live (live-agent lifecycle executor) — fifth layer, daemon-bound (not public SDK).
# M3a adds spt-term (session-surface mechanism: ConPTY/forkpty PTY layer) — sibling of spt-runtime, above spt-msg.
# M3b adds spt-daemon (broker/brain supervisor) — seventh layer, above spt-live, below spt; internal (not public SDK).
# M4 adds spt-net (P2P WAN/LAN transport) — sibling of spt-term/spt-runtime, above spt-msg; internal, default-on `net` feature.
[workspace]
resolver = "2"
members = ["crates/spt-proto", "crates/spt-store", "crates/spt-msg", "crates/spt-net", "crates/spt-term", "crates/spt-runtime", "crates/spt-live", "crates/spt-daemon", "crates/spt", "adapters/mock", "crates/xtask"]

# M6-D6 (grill decision 9): ONE shared version for every crate and the binary
# — the product version (v0.1.0 tag, `spt --version`). The wire-protocol
# version stays its own counter (REQ-ARCH-3) and the SignedRelease `version`
# is the separate monotonic release counter; neither conflates with this.
[workspace.package]
version = "0.7.0"


Edit

## [Unreleased]

## [0.7.1] - 2026-06-15

A consistency-and-clarity patch: messages now arrive in one envelope across every channel, and `spt update apply` confirms success in plain language.

### Changed

- **One message envelope across every channel.** Messages drained with `spt api poll` and `spt api worker-poll` now arrive in the same `<EVENT type="msg" from="…">…</EVENT>` envelope as the live `spt api listen` stream — one format to parse everywhere, and several queued messages are now self-delimiting. (Building an adapter? Parse the `<EVENT>` envelope on the poll channel; the older internal frame is gone.)

### Fixed

- **`spt update apply` now confirms the update applied, in plain language.** A successful apply prints `Updated spt-core to vX.Y.Z.` with a link to the changelog, instead of the earlier provisional "trial" wording that left a finished update looking unresolved. (The changelog link now points at the canonical `github.com` address.)

## [0.7.0] - 2026-06-14


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

## [Unreleased]

## [0.7.1] - 2026-06-15

A consistency-and-clarity patch: messages now arrive in one envelope across every channel, and `spt update apply` confirms success in plain language.

### Changed

- **One message envelope across every channel.** Messages drained with `spt api poll` and `spt api worker-poll` now arrive in the same `<EVENT type="msg" from="…">…</EVENT>` envelope as the live `spt api listen` stream — one format to parse everywhere, and several queued messages are now self-delimiting. (Building an adapter? Parse the `<EVENT>` envelope on the poll channel; the older internal frame is gone.)

### Fixed

- **`spt update apply` now confirms the update applied, in plain language.** A successful apply prints `Updated spt-core to vX.Y.Z.` with a link to the changelog, instead of the earlier provisional "trial" wording that left a finished update looking unresolved. (The changelog link now points at the canonical `github.com` address.)

## [0.7.0] - 2026-06-14

+A consistency-and-clarity patch: messages now arrive in one envelope across every channel, and `spt update apply` confirms success in plain language.

+- **One message envelope across every channel.** Messages drained with `spt api poll` and `spt api worker-poll` now arrive in the same `<EVENT type="msg" from="…">…</EVENT>` envelope as the live `spt api listen` stream — one format to parse everywhere, and several queued messages are now self-delimiting. (Building an adapter? Parse the `<EVENT>` envelope on the poll channel; the older internal frame is gone.)

+- **`spt update apply` now confirms the update applied, in plain language.** A successful apply prints `Updated spt-core to vX.Y.Z.` with a link to the changelog, instead of the earlier provisional "trial" wording that left a finished update looking unresolved. (The changelog link now points at the canonical `github.com` address.)

Remote terminals land. You can now bring an agent up under spt's own terminal host and attach to it from your own machine or across the subnet — drive it, or just watch — with a real one-at-a-time controller and any number of read-only viewers.


Version + CHANGELOG done. Regenerate docs + verify (xtask gen builds spt → path-scoped reap first per [[no-machinewide-killon-shared-runner]], scoped to this tree).


PowerShell

$tree = "C:\Users\decid\Documents\projects\spt-core\target"
Get-Process spt,notify-shell -ErrorAction SilentlyContinue |
  Where-Object { $_.Path -like "$tree\*" } |
  Stop-Process -Force -ErrorAction SilentlyContinue
Set-Location C:\Users\decid\Documents\projects\spt-core
cargo run -p xtask -- gen 2>&1 | Select-Object -Last 3
Write-Output "gen exit $LASTEXITCODE"
git status -s
Write-Output "=== check ==="
cargo run -p xtask -- check 2>&1 | Select-Object -Last 2
Write-Output "check exit $LASTEXITCODE"

Regen docs + xtask check after version bump


    Finished `dev` profile [unoptimized + debuginfo] target(s) in 18.79s
     Running `target\debug\xtask.exe gen`
xtask gen: wrote C:\Users\decid\Documents\projects\spt-core\docs-site/src/cli/reference.md
gen exit 0
 M CHANGELOG.md
 M Cargo.lock
 M Cargo.toml
 M docs-site/src/cli/reference.md
=== check ===
     Running `target\debug\xtask.exe check`
xtask check: OK
check exit 0


xtask check OK (reference.md regenerated for the version string). Changes: CHANGELOG, Cargo.toml, Cargo.lock, reference.md — workspace compiled clean during gen. Commit + push to main (release base); CI is the gate per the v0.3.0 lesson.


Bash

cd C:/Users/decid/Documents/projects/spt-core && git add CHANGELOG.md Cargo.toml Cargo.lock docs-site/src/cli/reference.md && git commit -q -F - <<'EOF'
release: v0.7.1 — <EVENT> envelope everywhere + confident update-apply message

Bump workspace 0.7.0 -> 0.7.1; add the CHANGELOG [0.7.1] section; regenerate the
CLI reference for the version string.

User-facing this release: `spt api poll` / `spt api worker-poll` now deliver the
same `<EVENT>` envelope as the live `spt api listen` stream (one consistent,
self-delimiting arriving-message format); `spt update apply` confidently states
"Updated spt-core to vX.Y.Z." with the canonical github.com changelog URL (was
the provisional "trial" wording).

Co-authored by: todlando
EOF
echo "=== COMMIT EXIT $? ===" && git push origin main 2>&1 | tail -4; echo "=== PUSH EXIT ${PIPESTATUS[0]} ==="; git log --oneline -1

Commit version bump + changelog, push to main


warning: in the working copy of 'Cargo.lock', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'docs-site/src/cli/reference.md', LF will be replaced by CRLF the next time Git touches it
=== COMMIT EXIT 0 ===
To https://github.com/SaberMage/spt-core.git
   30d2a92..cb05600  main -> main
=== PUSH EXIT 0 ===
cb05600 release: v0.7.1 — <EVENT> envelope everywhere + confident update-apply message


Pushed `cb05600` to main → CI runs. Ping doyle (he gates CI green pre-tag) + watch CI myself to tag promptly when green.


PowerShell

$msg = @'
v0.7.1 bump PUSHED to main @ cb05600 (workspace 0.7.0→0.7.1 + CHANGELOG [0.7.1] + regen reference; xtask check OK locally). CI running now. CHANGELOG [0.7.1] (user-facing): Changed = api poll/worker-poll deliver the <EVENT> envelope like api listen (consistent, self-delimiting); Fixed = spt update apply confident "Updated spt-core to vX." + canonical github.com URL. (Omitted shell-link fix = net-zero vs 0.7.0; docs/CI = non-CLI-user.) Watching CI my side too — when GREEN I tag v0.7.1 + push tag, then hand deployah (counter 13). Flag if you want the tag held for your explicit green-confirm vs me tagging on confirmed-green CI.
'@
$msg | & $env:OWL send doyle
Write-Output "SEND_EXIT=$LASTEXITCODE"

Ping doyle: v0.7.1 bump pushed, CI running


Bash

cd C:/Users/decid/Documents/projects/spt-core && sleep 6 && gh run list --branch main --limit 3

Find the CI run for the v0.7.1 bump push


➜ SENT:doyle
SEND_EXIT=0


queued		release: v0.7.1 — <EVENT> envelope everywhere + confident update-appl…	ci	main	push	27541473367	25s	2026-06-15T10:56:17Z
completed	success	Merge PR #13: confident update-apply message + publish substitution-k…	ci	main	push	27540844793	7m18s	2026-06-15T10:43:35Z
completed	success	Merge PR #12: ADR-0020 <EVENT> envelope sole arriving format + __REPL…	ci	main	push	27540079169	7m36s	2026-06-15T10:28:06Z


CI run `27541473367` queued for `cb05600` (PR #12 + #13 merge CIs were both green). Watch to completion in background.


cd C:/Users/decid/Documents/projects/spt-core && gh run watch 27541473367 --exit-status; echo "WATCH_EXIT=$?"

Watch v0.7.1 CI run to completion


<owl_messages>
<owl_message from="doyle" priority="high">HOLD the tag for my explicit green-confirm — I gate CI before the tag (that's the gate, and the v0.3.0 lesson). Bump @ cb05600 + CHANGELOG look right (patch-correct: Changed=poll/worker-poll <EVENT> consistency, Fixed=confident apply msg; shell-link net-zero omit is fine). Watching main's CI now. I ping you GREEN → you tag v0.7.1 + push tag → deployah. Don't tag until my word.</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.


Command running in background with ID: bph0z76hi. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\c570fe63-c413-4a17-bb14-ee75e02a53bd\tasks\bph0z76hi.output. You will be notified when it completes. To check interim output, use Read on that file path.


doyle: HOLD the tag for his explicit green-confirm (his gate + the v0.3.0 lesson). Bump + CHANGELOG approved (patch-correct). He's watching main's CI; pings GREEN → I tag → deployah. I do NOT tag until his word. ACK + hold.


PowerShell

$msg = @'
Ack — HOLDING the tag for your explicit green word. Will NOT tag v0.7.1 until you confirm CI green. My CI watch stays informational only. On your green: tag v0.7.1 + push tag → ping you + deployah (counter 13). Standing by.
'@
$msg | & $env:OWL send doyle
Write-Output "SEND_EXIT=$LASTEXITCODE"

Ack doyle: hold tag for his green-confirm


Holding the tag for doyle's explicit green word. Bump `cb05600` on main, CI running (my watch `bph0z76hi` is informational only). doyle gates → pings green → I tag v0.7.1 + push → deployah (counter 13).


ScheduleWakeup

Holding v0.7.1 tag for doyle's green-confirm on main CI; his ping + the CI watch completion interrupt sooner

Prompt: <<autonomous-loop-dynamic>>


Next wakeup scheduled for 04:18:00 (in 1247s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.


Standing by for doyle's green-confirm on the v0.7.1 CI. Tag held per his gate. Wakeup fallback 1200s; doyle's green ping or the CI-watch completion interrupts sooner.


<task-notification>
<task-id>bph0z76hi</task-id>
<tool-use-id>toolu_01Wfc5Rm1H9NSrSdEGgBoVvF</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\c570fe63-c413-4a17-bb14-ee75e02a53bd\tasks\bph0z76hi.output</output-file>
<status>completed</status>
<summary>Background command "Watch v0.7.1 CI run to completion" completed (exit code 0)</summary>
</task-notification>


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


My CI watch completed exit 0 = green on `cb05600`. But doyle gates independently and said hold for HIS word — I do NOT tag. Confirm the conclusion + tell doyle I'm green-ready, still holding.


Bash

cd C:/Users/decid/Documents/projects/spt-core && gh run view 27541473367 --json status,conclusion -q '.status + " / " + .conclusion'

Confirm v0.7.1 CI conclusion


completed / success


PowerShell

$msg = @'
My CI watch on cb05600 = GREEN (run 27541473367: completed/success, both runners incl the new exe-lock guard). Standing READY to tag v0.7.1 — still holding for YOUR explicit green word per your gate. Give the go and I tag + push immediately, then ping you + deployah (counter 13).
'@
$msg | & $env:OWL send doyle
Write-Output "SEND_EXIT=$LASTEXITCODE"

Tell doyle CI green my side, holding for his go


CI confirmed green (`27541473367` success, both runners). Told doyle I'm ready; holding the tag for his explicit go. Standby.


ScheduleWakeup

CI green on cb05600; holding v0.7.1 tag for doyle's explicit go-word; his ping interrupts sooner

Prompt: <<autonomous-loop-dynamic>>


<owl_messages>
<owl_message from="doyle" priority="high">GREEN — CI on cb05600 (v0.7.1 bump) = completed:success, ALL jobs pass (test + n1-gate both runners, traceability; twohost gated-skip). Pre-tag gate PASS.

GO: tag v0.7.1 on cb05600 + push the tag → hand deployah for sign+publish (counter 13). Ping me + deployah the tag. deployah pings BOTH hashes on publish → I relay to perri for the byte-capture. Tag it.</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.


Next wakeup scheduled for 04:25:00 (in 1203s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.


doyle: GREEN, GO. Tag v0.7.1 on `cb05600` + push.


Bash

cd C:/Users/decid/Documents/projects/spt-core && git rev-parse HEAD && git tag v0.7.1 cb05600 && git push origin v0.7.1 2>&1 | tail -3 && echo "=== TAG PUSH EXIT ${PIPESTATUS[0]} ===" && git tag --list "v0.7.1"

Tag v0.7.1 on cb05600 + push


cb0560052c7392d386d9e68db359bbbf3138dcfe
To https://github.com/SaberMage/spt-core.git
 * [new tag]         v0.7.1 -> v0.7.1
=== TAG PUSH EXIT 0 ===
v0.7.1


Tagged + pushed **v0.7.1** on `cb05600` — release.yml draft + docs-publish triggered. Hand deployah (counter 13) + ping doyle.


PowerShell

$msg = @'
v0.7.1 tagged + pushed (cb05600, CI green/doyle pre-tag gate PASS). release.yml draft + docs-publish building.
Please sign+publish per RELEASE-RUNBOOK.md step 4:
  release-publish --tag v0.7.1 --key-id rel-primary-2026 --version 13
(counter 13; v0.7.0 was 12). Patch bump 0.7.0→0.7.1. Ping BOTH hashes (linux+win) on publish — doyle relays to perri for the <EVENT> poll byte-capture.
'@
$msg | & $env:OWL send deployah
Write-Output "DEPLOYAH_EXIT=$LASTEXITCODE"
$msg2 = @'
TAGGED v0.7.1 + pushed on cb05600 (your pre-tag gate PASS confirmed). release.yml draft + docs-publish running. Handed deployah: release-publish --tag v0.7.1 --key-id rel-primary-2026 --version 13 (counter 13). deployah pings both hashes on publish → you relay to perri. My release leg done through the tag; on-call if anything snags.
'@
$msg2 | & $env:OWL send doyle
Write-Output "DOYLE_EXIT=$LASTEXITCODE"

Hand deployah sign+publish + notify doyle of tag


➜ SENT:deployah
DEPLOYAH_EXIT=0
➜ SENT:doyle
DOYLE_EXIT=0


**v0.7.1 tagged + pushed** on `cb05600` (doyle pre-tag gate PASS) → deployah handed sign+publish (counter 13). My release leg complete through the tag. release.yml draft + docs-publish running.

Chain remaining: deployah signs+publishes → pings both hashes → doyle relays to perri for the `<EVENT>` poll byte-capture. Standby for deployah's publish confirmation.


ScheduleWakeup

v0.7.1 tagged + handed deployah (counter 13); awaiting deployah sign+publish hash confirmation; their ping interrupts sooner

Prompt: <<autonomous-loop-dynamic>>


Next wakeup scheduled for 04:26:00 (in 1225s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.


Release leg done. **v0.7.1** tagged on `cb05600`, pushed, handed to deployah (counter 13). Standing by for deployah's sign+publish hash confirmation → doyle relays to perri. Wakeup fallback 1200s; deployah's publish ping or any agent message interrupts sooner.


<task-notification>
<task-id>bmby1p3hm</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/2" id="7bb97490" type="msg" from="deployah">v0.7.1 PUBLIC, counter 13 (transient TLS blip cleared on rerun, no re-tag). Hashes:
  linux 81eededc724676565a323a0a5b12bfed5f8b596c3e60eaa467d5d8b50cc7bfd5
  win   94bb542970dfb6d7b5eff6abe308d0ee9cfeb69f62c04d43fad84b40aa47b898
Roll fleet when ready, ping hashes, I'll verify. enlyzeam still pending — lan</EVENT-PART>
<EVENT-PART seq="2/2" id="7bb97490">ds straight on v0.7.1 win 94bb5429 if caught up.</EVENT-PART></event>
</task-notification>


**v0.7.1 PUBLIC** — counter 13, deployah signed+published (transient TLS blip cleared on rerun, no re-tag). Hashes:
- linux `81eededc…`
- win `94bb5429…`

The ADR-0020 `<EVENT>` change is now published. Notify doyle (his perri-relay for the byte-capture is unblocked) + ack deployah + record memory.


PowerShell

$msg = @'
v0.7.1 PUBLIC — counter 13 (deployah signed+published; transient TLS blip cleared on rerun, no re-tag). Hashes:
  linux 81eededc724676565a323a0a5b12bfed5f8b596c3e60eaa467d5d8b50cc7bfd5
  win   94bb542970dfb6d7b5eff6abe308d0ee9cfeb69f62c04d43fad84b40aa47b898
The ADR-0020 <EVENT>-everywhere change is now on the published surface → your perri relay for the poll->additionalContext <EVENT> byte-capture is UNBLOCKED (she builds from published only). My full release leg done (bump→changelog→push→your green gate→tag→publish handoff). Fleet roll = operator/deployah-gated next phase, not initiating. On-call.
'@
$msg | & $env:OWL send doyle
Write-Output "DOYLE_EXIT=$LASTEXITCODE"
$msg2 = @'
Got v0.7.1 PUBLIC, counter 13 — thanks for the rerun-through-the-TLS-blip. Hashes logged (linux 81eededc / win 94bb5429). Fleet roll is operator-gated (their ask was the release, DONE) — not initiating; if operator calls the roll I ping you per-node hashes for your verify. enlyzeam catch-up → lands on v0.7.1 win 94bb5429 noted.
'@
$msg2 | & $env:OWL send deployah
Write-Output "DEPLOYAH_EXIT=$LASTEXITCODE"

Notify doyle (perri relay unblocked) + ack deployah


➜ SENT:doyle
DOYLE_EXIT=0
➜ SENT:deployah
DEPLOYAH_EXIT=0


Both notified. Record v0.7.1 published memory (matching prior pattern, with hashes).


Write

---
name: v071-published
description: "v0.7.1 PUBLIC 2026-06-15 (counter 13) — ADR-0020 <EVENT>-everywhere + confident update-apply msg + CI exe-lock guard; hashes linux 81eededc / win 94bb5429"
metadata:
  type: project
---

v0.7.1 PUBLIC 2026-06-15 (release counter 13; v0.7.0=12). PATCH bump 0.7.0→0.7.1. todlando drove the tag leg (bump→CHANGELOG→push→doyle pre-tag CI-green gate→tag v0.7.1 @cb05600→push); deployah signed+published (counter 13; transient TLS blip cleared on rerun, no re-tag).

Contents (main @ cb05600, base 30d2a92 = PR #12 + PR #13 merged):
- **ADR-0020** ([[event-envelope-reply-to-removal]]): `<EVENT>` envelope = sole arriving-message format at every agent-perch surface (api listen + poll/worker-poll); `__REPLY_TO__` removed; shell-link relay EXEMPT (raw MAC'd frames); F-002 dissolved.
- fix(update): `spt update apply` states "Updated spt-core to vX.Y.Z." confidently (was internal "trial") + canonical github.com URL ([[update-apply-confident-message]]).
- docs: published {key} substitution catalog, [digest] register rule, [strings] file-pointer syntax (F-003 docs leg).
- ci: workspace-scoped Windows exe-lock reap guard ([[no-machinewide-killon-shared-runner]]).

ACCEPTANCE HASHES:
- linux `81eededc724676565a323a0a5b12bfed5f8b596c3e60eaa467d5d8b50cc7bfd5`
- win   `94bb542970dfb6d7b5eff6abe308d0ee9cfeb69f62c04d43fad84b40aa47b898`

Publisher leg proven 7× (counter 7–13). NEXT: doyle relays hashes to **perri** for the poll→additionalContext `<EVENT>` byte-capture (now on published surface — she builds from published only). Fleet roll = operator/deployah-gated next phase (NOT auto-initiated). enlyzeam pending catch-up → lands straight on v0.7.1 (win 94bb5429).


<tool_use_error>File has not been read yet. Read it first before writing to it.</tool_use_error>


1	- [don't wait — proceed autonomously](dont-wait-proceed-autonomously.md) — operator 2026-06-14: don't stop to ask permission between steps; chain next action (ping/commit gated batch/next wave). After doyle W4 gate-PASS, commit myself
2	- [gate against documented design](gate-against-documented-design.md) — gating lesson: verify a wave's premise vs the RECORDED design (CONTEXT.md/ADRs), not just current impl — an impl limitation can contradict a locked design (W2.5 single-subscriber vs locked controller/viewer model; operator caught it)
3	- [public docs: version not milestone](public-docs-version-not-milestone.md) — operator 2026-06-15: published docs-site uses VERSION numbers (since v0.7.0), never internal milestone/wave codes (M12-W3); internal design docs (CONTEXT/MANIFEST/ADRs) keep milestone refs. Grep docs-site edits for M#/W#/wave before commit
4	- [M12 W1 progress](m12-w1-progress.md) — **M12 FULLY GATED end-to-end** (W1·W1.5·HR2·W3·W2·follow-on·W4·W5 + **W2.5 GATE-PASS @6b4859f + gate-#7 combined close-out @f521df2**, attach 12/12 reproduced green, traceable EXIT=0, all 6 conditions + gate-#7 self-kick non-negotiable verified by doyle). M12 publishing (v0.6.0 baseline used to start perri). doyle next: ping perri when M12 publishes + triage any spt-core bug perri reports
5	- [cplugs publish mechanics](cplugs-publish-mechanics.md) — concrete cplugs marketplace publish steps live in claude_skill_owl/docs/DEPLOY.md (+DEPLOY.ps1); spt-claude-code takes only the SKELETON subset (no binary in cplugs — binary+manifest ride spt-core adapter registry). Relayed to perri
6	- [perri needs reply to continue](perri-needs-reply-to-continue.md) — STANDING (operator 2026-06-15): ALWAYS reply to perri's reports (ack + keep-going + confirm next plan); she treats silence as a stop-point and stalls. todlando self-drives (no nudge needed); perri needs it
7	- [no machine-wide kill on shared runner](no-machinewide-killon-shared-runner.md) — BINDING (doyle 2026-06-15): HFENDULEAM = self-hosted CI runner sharing the box with LIVE agents; never `Get-Process spt|Stop-Process` machine-wide (tears down live broker); scope reaps to $GITHUB_WORKSPACE/target path or a PID. I'd done the unsafe form 3× locally — disclosed
8	- [agent roles](agent-roles.md) — doyle=gater/spt-core owner (don't self-execute big spt-core builds), todlando=spt-core executor, perri=spt-claude-code adapter builder. perri finds gap → doyle designs/dispatches → todlando builds → doyle gates → perri validates
9	- [EVENT envelope + __REPLY_TO__ removal](event-envelope-reply-to-removal.md) — ADR-0020 (2026-06-15 grill-with-docs): `<EVENT type=msg from=…>` envelope = sole arriving-message format at EVERY surface incl api poll; `__REPLY_TO__` mis-elevated relic REMOVED; F-002 dissolves; docs done (ADR+amendments+CONTEXT+REQ-MSG-ENVELOPE), multi-crate IMPL refactor PENDING (poll still emits relic until then); perri parses `<EVENT>` not the relic
10	- [spt-core harness boundary + grounding](spt-core-harness-boundary-and-grounding.md) — BINDING (operator 2026-06-15): spt-core never caters to a specific harness (adapter formats spt-core's output for its harness; don't doc CC-specifics on spt-core surface); ground all completeness Qs in CONTEXT.md/ADRs (thoroughly planned — apparent gaps usually already specified). F-001 disposition: most=adapter glue, residual=publish agnostic primitives
11	- [sptc plugin name ruling](sptc-plugin-name-ruling.md) — spt-claude-code cplugs plugin = `sptc` (interim) → flips to `spt` on proven parity (then retire legacy owl `spt`); CC hard-ties skill prefix to plugin.json name (no override) so /spt: parity needs name=spt, blocked by live legacy owl. Distinct from adapter_name claude-spt
12	- [experimplate traceable seed leaks](experimplate-traceable-seed-leaks.md) — experimplate template ships traceable seed defects (4 tag-leaks + manifest_error in own example docs); perri fixed in-instance via scan-root trim; doyle to fix upstream (scope scan-root / inert example tags) before next adapter reuse
13	- [M9 status](m9-wave1-progress.md) — M9 COMPLETE + SHIPPED: all 4 gates passed (G1/G2/Gateway-WAN/G3), all PRs merged to main (operator GO 2026-06-13), **v0.5.0 tagged** (counter 10, deployah signing). Don't re-plan. See [[v050-published]] for release state
14	- [spt-claude-code NEXT](spt-claude-code-next.md) — SCOPING DONE 2026-06-14 (SCOPE.md/CONTEXT.md committed @09d6020). M12 handed to todlando as GATING prereq (now executing W1). RESUME = author experimplate → instantiate spt-claude-code → write perri HANDOFF. perri builds from spt-releases+GH-Pages ONLY
15	- [M10 digest extractor](m10-digest-extractor.md) — doyle GATE PASS 2026-06-13: all 4 waves (39463a2..afa0561), REQ-TERM-5/6/7 evidenced, full suite + capstone E2E green, independently verified. `[digest]` imperative extractor seam (ADR-0019, reverses M9) + thread-spanning (session ledger) + two-origin merge + digest-proof + skip-diagnostics. SHIPPED as v0.6.0 (counter 11) — see [[v060-published]]. Carried: real-CC digest-proof → perri/spt-claude-code acceptance criterion
16	- [v0.6.0 published](v060-published.md) — M10 PUBLIC 2026-06-13 (counter 11); todlando merge+tag, deployah sign+publish; minor bump (0.5.0→0.6.0); hashes linux 002ed710… win 4f5c61e8…. ROUTINE seamless roll now (respawn-path arc closed); publisher leg proven 5× (counter 7-11). enlyzeam still pending natural-propagation confirm
17	- [v0.7.0 published](v070-published.md) — PUBLIC 2026-06-15 (counter 12); todlando merge+tag, deployah sign+publish; HEAD e08cea0; hashes linux f4082ed3… win c09d4e6d…. Routine seamless; publisher leg proven 6× (counter 7-12). enlyzeam still pending catch-up
18	- [v0.7.1 published](v071-published.md) — PUBLIC 2026-06-15 (counter 13); patch; ADR-0020 EVENT-everywhere + __REPLY_TO__ removal (unblocks perri byte-capture); tag cb05600; hashes linux 81eededc… win 94bb5429…. GOTCHA: release.yml assemble step hit transient TLS-handshake-timeout on gh-release-create → `gh run rerun <id> --failed` clears it (builds reused, no re-tag); read failed step before alarming (transient-API ≠ disk-full ≠ code). Publisher leg proven 7× (counter 7-13)
19	- [EVENT envelope IMPL gate-pass + poll false-green](event-envelope-reply-to-removal.md) — ADR-0020 multi-crate impl @5da7fcd doyle GATE-PASS; PR#12 CI RED on my poll int (api poll auth-gated, leaned on ambient $OWL_SESSION_ID=false green) → fixed hermetically @ac6c802 (pin SID on ready+poll, unset env to repro CI). LESSON: pin OWL_SESSION_ID for any auth-gated E2E
20	- [update-apply confident message](update-apply-confident-message.md) — operator 2026-06-15: public `spt update apply` SUCCESS must say "Updated" not internal "trial"; fix @03630ee branch fix/update-apply-confident-message (off main), self-verified green, awaiting doyle gate→merge→next release; internal trial/rollback machinery untouched
21	- [traceable per-wave activation](traceable-per-wave-activation.md) — traceable-reqs check requires ALL declared required_stages evidenced per commit; activate stages incrementally as evidence lands (int at final wave), never the full end-state list upfront
22	- [v0.5.0 published](v050-published.md) — M9 PUBLIC 2026-06-13 (counter 10); todlando drove merge+tag, deployah signed+published (handoff split vs v0.4.x full-solo); minor bump (breaking [pty_digest] removal pre-1.0); hashes linux 4c079100… win 984298ba…. FLEET ROLL = next phase, operator-gated (their ask was merge+publish, DONE). v0.4.2→v0.5.0 kitsubito apply = FIRST genuine Linux seamless no-bounce proof on fixed broker; bytes-assert→auto-rollback armed. deployah on-call for hash check
23	- [v0.5.0 release](v050-release.md) — M9 SHIPPED: merged to main (22a9b6f, clean stack collapse; #8 auto-closed by mid-stack --delete-branch, content rode via #9), v0.5.0 tagged (0.4.2→0.5.0 minor: feature milestone + breaking [pty_digest] removal), counter 10, deployah signing. LESSON: don't --delete-branch mid-stack

... [22 lines truncated] ...


The parallel instance already wrote v071-published.md + the index entry (line 18, with the TLS-blip rerun gotcha — more detail than I had). Confirm it's complete, no duplicate write needed.


<owl_messages>
<owl_message from="deployah" priority="high">Understood — fleet roll operator-gated, you'll ping per-node hashes if the roll is called. I'll verify against linux 81eededc / win 94bb5429 when it comes. enlyzeam → 94bb5429 on catch-up. Idle.</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.


1	---
2	name: v071-published
3	description: "v0.7.1 PUBLIC 2026-06-15 (counter 13); ADR-0020 EVENT-everywhere + __REPLY_TO__ removal; release.yml hit transient TLS timeout, cleared on rerun --failed"
4	metadata:
5	  node_type: memory
6	  type: project
7	  originSessionId: 1fb9fc52-b258-4b44-9c4c-7cae9345098f
8	---
9
10	v0.7.1 SIGNED + PUBLISHED 2026-06-15 (release counter 13; v0.7.0=12, v0.7.1=13). Patch bump 0.7.0→0.7.1. doyle-coordinated (todlando bump+CHANGELOG+tag cb05600, deployah sign+publish+hash). Contents: ADR-0020 `<EVENT>`-everywhere + `__REPLY_TO__` removal + notify fix, confident `update apply` message, docs-completeness ({key} catalog / [digest] rule / [strings] file-pointer), CI exe-lock guard.
11
12	Hashes: linux `81eededc724676565a323a0a5b12bfed5f8b596c3e60eaa467d5d8b50cc7bfd5`, win `94bb542970dfb6d7b5eff6abe308d0ee9cfeb69f62c04d43fad84b40aa47b898`. signed `54188f12…05e3ec9`. update-set.json v13. https://github.com/SaberMage/spt-releases/releases/tag/v0.7.1
13
14	**Why:** the win binary 94bb5429 carries the ADR-0020 `<EVENT>`-everywhere poll surface → unblocks perri's REQ-MSG-ENVELOPE byte-capture (doyle relays the hash). See [[event-envelope-reply-to-removal]].
15
16	**GOTCHA (transient, recurring-class):** release.yml `assemble` job's "Create draft release on spt-releases" step can fail on a GitHub API network blip — saw `Post .../releases: net/http: TLS handshake timeout`, exit 1. This is NOT code and NOT the hfenduleam disk-full class — binary builds succeed, only the gh-release-create call blips. Fix: `gh run rerun <id> --repo SaberMage/spt-core --failed` (green build jobs are reused, only assemble re-runs), no re-tag needed. My BUILD-FAILED draft-watch correctly caught it; always read the failed step before alarming — distinguish transient-API / disk-full / real-code.
17
18	**How to apply:** todlando rolls fleet, deployah verifies hashes on ping. enlyzeam still pending catch-up (lands straight on v0.7.1 win 94bb5429 if caught up). Publisher leg proven 7× (counter 7-13). Seed `SPT_RELEASE_SEED` resident in ENV (64-hex); Monitor=bash.
19

---
name: v071-published
description: "v0.7.1 PUBLIC 2026-06-15 (counter 13); ADR-0020 EVENT-everywhere + __REPLY_TO__ removal; release.yml hit transient TLS timeout, cleared on rerun --failed"
metadata:
  node_type: memory
  type: project
  originSessionId: 1fb9fc52-b258-4b44-9c4c-7cae9345098f
---

v0.7.1 SIGNED + PUBLISHED 2026-06-15 (release counter 13; v0.7.0=12, v0.7.1=13). Patch bump 0.7.0→0.7.1. doyle-coordinated (todlando bump+CHANGELOG+tag cb05600, deployah sign+publish+hash). Contents: ADR-0020 `<EVENT>`-everywhere + `__REPLY_TO__` removal + notify fix, confident `update apply` message, docs-completeness ({key} catalog / [digest] rule / [strings] file-pointer), CI exe-lock guard.

Hashes: linux `81eededc724676565a323a0a5b12bfed5f8b596c3e60eaa467d5d8b50cc7bfd5`, win `94bb542970dfb6d7b5eff6abe308d0ee9cfeb69f62c04d43fad84b40aa47b898`. signed `54188f12…05e3ec9`. update-set.json v13. https://github.com/SaberMage/spt-releases/releases/tag/v0.7.1

**Why:** the win binary 94bb5429 carries the ADR-0020 `<EVENT>`-everywhere poll surface → unblocks perri's REQ-MSG-ENVELOPE byte-capture (doyle relays the hash). See [[event-envelope-reply-to-removal]].

**GOTCHA (transient, recurring-class):** release.yml `assemble` job's "Create draft release on spt-releases" step can fail on a GitHub API network blip — saw `Post .../releases: net/http: TLS handshake timeout`, exit 1. This is NOT code and NOT the hfenduleam disk-full class — binary builds succeed, only the gh-release-create call blips. Fix: `gh run rerun <id> --repo SaberMage/spt-core --failed` (green build jobs are reused, only assemble re-runs), no re-tag needed. My BUILD-FAILED draft-watch correctly caught it; always read the failed step before alarming — distinguish transient-API / disk-full / real-code.

**How to apply:** todlando rolls fleet, deployah verifies hashes on ping. enlyzeam still pending catch-up (lands straight on v0.7.1 win 94bb5429 if caught up). Publisher leg proven 7× (counter 7-13). Seed `SPT_RELEASE_SEED` resident in ENV (64-hex); Monitor=bash.


v0.7.1 memory already complete (parallel instance captured it, incl the TLS-blip rerun gotcha). deployah idle, on-call for hash verify. No reply needed — pure confirmation.

**v0.7.1 release COMPLETE + PUBLIC** (counter 13): tagged `cb05600`, signed, published; hashes linux `81eededc…` / win `94bb5429…`. My full release leg done. doyle holds the perri byte-capture relay; fleet roll is operator-gated (not auto-initiated); deployah on-call. Idle — all threads parked, awaiting doyle's next gap or an operator/fleet-roll call via the armed Monitor.


ScheduleWakeup

v0.7.1 shipped + published; all threads parked, fleet roll operator-gated; Monitor « spt event » is the wake signal, this is fallback heartbeat

Prompt: <<autonomous-loop-dynamic>>


Next wakeup scheduled for 04:43:00 (in 1821s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.


Idle — v0.7.1 shipped and published (counter 13), all threads parked, fleet roll operator-gated. Fallback heartbeat at 1800s; the armed Monitor re-invokes me on doyle's next gap or an operator/fleet-roll call.


<command-message>spt:commune</command-message>
<command-name>/spt:commune</command-name>
<command-args>with immediate next steps and broad summary of the project's status + end goal. we'll resume in the next session</command-args>


Base directory for this skill: C:\Users\decid\.ccs\instances\bigscreen\plugins\cache\cplugs\spt\1.11.25\skills\commune

# /spt:commune

All commands use `$LIVE` env var, auto-injected by the plugin's SessionStart hook. If commands fail with "command not found", restart the Claude Code session so the SessionStart hook re-runs.

> **Identity auto-detection:** Your identity is auto-detected from your session. Pass your ID explicitly only if auto-detection fails.

## Flow

1. **Download Psyche's *current* context** — it shifts during the session as background echo communes fire. Re-download right before composing; the gen-N snapshot you read at session start is already stale:
   ```bash
   $LIVE psyche-download <your-id>
   ```

   > **Output truncation.** If the Bash tool reports `Output too large (N KB)` and saves the full result to a `tool-results/<id>.txt` file, use the `Read` tool on that saved path to access the full content. Do NOT re-run `psyche-download` to grep/awk out sections — repeated invocations re-download the same context, waste tokens, and may duplicate `## Pending Commune` sections in `live_context.md`.

2. **Diff your knowledge against this fresh download** — only what's missing from *it* is the real delta (new work, decisions, intentions). Anything already absorbed is not. If the download includes a `<memformat>` section, use it as a guide for what topics to cover. A `## Pending Commune (uncommitted)` section means a previous commune is still queued — do NOT re-send it.

3. **Commune only the delta** -- use the **Write tool** to create
   `.claude/{your-id}-commune.md` with the two-slice body as its contents
   (see `## Two-slice body shape (Phase 25 D-10/D-11)` below for the required
   envelope wrapping). Do not use Bash/heredoc -- Write is the canonical path:
   no shell escaping, no `EOF` collision risk, and Write auto-creates the
   `.claude/` parent directory.

   Your Self listener detects the file on its next poll iteration, notifies
   your Psyche wrapper, and the wrapper ingests the content via the existing
   Psyche session. On success (subprocess exit code 0) the wrapper deletes the
   file. On error (token rate limit, etc) the file is retained and retried on
   the next consume cycle. If you write again before the wrapper consumes, the
   latest write wins (last-write-wins overwrite semantics).

If Psyche's context is already current, no commune is needed. Say so and move on.

Read `commune.md` (in this skill directory) for the full commune protocol -- when to send, what to include, and diligence triggers.

**Agent-type guard:** Only works on live agents. If target is not live, refuses with: "Communes require a live agent with Psyche."

## Two-slice body shape (Phase 25 D-10/D-11)

The body you write in `.claude/{your-id}-commune.md` MUST itself be wrapped in two-slice envelopes per Phase 25 D-10/D-11. The taxonomy — what belongs in `<live-context>` vs `<project-context>` — is defined canonically in `psyche.md` §`<output_envelope>` (lines 282–323). Read that section as the source of truth; this skill doc teaches only when and how to apply it.

**In-project detection rule (D-25.1-04).** Before composing your commune body, run `$LIVE psyche-download <your-id>` (Step 1 of `## Flow` above) and inspect the `<current ... />` tag at the top of the output. The `<current/>` tag carries a `project="..."` attribute whenever any payload is produced — its presence means you are inside a tracked project (inside a git repo, `project` is the repo name; outside a git repo per D-11, `project` is the cwd-basename fallback, which still counts as a project context for routing purposes). A `psyche-download` invocation that returns no payload at all (NO-CONTEXT exit) means no project resolved. So: `project="..."` populated on `<current/>` → emit BOTH envelopes (apply rule 1 or 2 below); no payload at all → emit ONLY `<live-context>` (rule 3). Secondary signal: the `<project-context-resolved name="..."/>` sentinel further down the output indicates the project file already has prior content — useful for spotting first-time-in-project pairings, but NOT the routing rule.

**Three rules (D-25.1-01..03):**

- **In-project, both slices populated** (marker present, you have project-specific content this cycle): emit `<live-context>...</live-context>` AND `<project-context>...</project-context>`, both with non-empty bodies.
- **In-project, no project-specific update this cycle** (marker present, but nothing project-bound to report): emit `<live-context>...</live-context>` AND `<project-context></project-context>` (empty body — the deliberate "in-project but quiet" signal per D-25.1-02). Distinguishable from "no project resolved".
- **Outside any tracked project** (marker absent): emit ONLY `<live-context>...</live-context>`. Do NOT emit an empty `<project-context>` envelope (missing tag means "no project resolved" per D-25.1-03).

**Nested envelopes.** The Phase 23 `<EVENT type="commune">` envelope (see `## Envelope shape (Phase 23 v1.8)` below) is composed by `$LIVE commune` automatically — you NEVER write `<EVENT>` tags. You write ONLY the inner two-slice body. The two envelope layers nest: outer EVENT wraps inner two-slice body.

(See `psyche.md` §`<output_envelope>` for the canonical taxonomy and per-slice content rules.)

## Envelope shape (Phase 23 v1.8)

As of v1.8 Phase 23, commune deliveries are wrapped in a typed EVENT envelope carrying a 5-field stamp (`machine`, `project`, `branch`, `head_sha`, `head_subject`); the prose `COMMUNE (timestamp): body` form is gone.

```xml
<EVENT type="commune" timestamp="2026-05-20T06:00:00-07:00" machine="hostname" project="claude_skill_owl" branch="main" head_sha="abc123..." head_subject="subject line capped at 72 chars">body</EVENT>
```

Outside a git repo (D-11), `branch`, `head_sha`, and `head_subject` are omitted entirely (not empty-string-set):

```xml
<EVENT type="commune" timestamp="2026-05-20T06:00:00-07:00" machine="hostname" project="cwd-basename">body</EVENT>
```

`$LIVE commune` composes this envelope automatically — Self does NOT manually construct EVENT XML. The `body` placeholder in the example above is the two-slice body (see `## Two-slice body shape (Phase 25 D-10/D-11)` above); the two envelope layers nest. The wrapper-side parser ignores unknown attrs, so the stamp fields are forward-compatible with older receivers. For drift detection on resume, see the `live` skill.

ARGUMENTS: with immediate next steps and broad summary of the project's status + end goal. we'll resume in the next session


1	---
2	name: event-envelope-reply-to-removal
3	description: "ADR-0020: <EVENT> envelope = sole arriving-message format on agent perches (shell-link relay EXEMPT); __REPLY_TO__ removed. SHIPPED in v0.7.1 (counter 13) 2026-06-15 + VERIFIED on the published surface by perri's byte-capture. Loop CLOSED end-to-end; F-002 resolved-shipped, F-003 docs-closed"
4	metadata:
5	  node_type: memory
6	  type: project
7	  originSessionId: ce7ce158-107f-4da4-a203-cea98da80b27
8	---
9
10	**ADR-0020 (2026-06-15, crystallized via /grill-with-docs, operator-ruled).** Triggered by
11	perri's finding **F-002** (`api poll` multi-message output non-self-delimiting). Operator clarified the
12	design intent → grilled against CONTEXT/ADRs → these LOCKED decisions:
13
14	- **The `<EVENT type="msg" from="…">body</EVENT>` envelope (spt-proto::event, the ADR-0001 grammar) is
15	  the SOLE canonical arriving-message format at EVERY delivery surface — `api listen`/`spt ready` AND
16	  `api poll`/`worker-poll`, byte-identical.** Adapters parse the `<EVENT>` envelope (the `from` attr).
17	  Reverses REQ-MSG-4's "hook drains keep the raw frame by contract."
18	- **`__REPLY_TO__` was MIS-ELEVATED** during the clean-room port to a fake ADR-0001 "stable wire
19	  format" (spt-msg/wire.rs, lib.rs). It is REMOVED entirely: spool format_row, the spt-msg TCP frame,
20	  emit::parse_frame. `(from, body)` carried structurally; `<EVENT>` composed once at the delivery edge.
21	- **No legacy sister-interop** — spt-core never required byte-compat with legacy spt; the wire.rs
22	  "byte-for-byte with a sister" claim was part of the mis-elevation. (Operator confirmed.)
23	- **Reply-correlation rebinds onto the structural `from` / `<EVENT from=…>`** — ADR-0009 access-gate
24	  (reply-vs-new) + ADR-0012 Psyche/spt-live reply-target. Both ADRs amended (dated notes). Sender-
25	  identity granularity preserved (the relic carried the same `from`); no new correlation attribute.
26	- **F-002 dissolves** — `<EVENT>…</EVENT>` self-delimits; no record delimiter introduced.
27	- WAN wire (spt-net/wanmsg.rs) UNAFFECTED — `from` already structural (JSON field).
28
29	**DOCS DONE:** ADR-0020 + ADR-0009/0012 amendments + CONTEXT.md §Messaging-substrate glossary entry
30	("arriving-message envelope") + REQ-MSG-ENVELOPE registered (required_stages=["doc"], doc evidenced;
31	traceable 208/208 EXIT=0).
32
33	**IMPL DISPATCHED TO TODLANDO 2026-06-15 (spt-core executor; doyle gates — NOT doyle's to execute, NOT perri's).** Plan = `REQ-MSG-ENVELOPE-PLAN.md` (7 tasks, 3 open impl-decisions: TCP-wire shape, drain API, anon from). todlando JIT-plans → design-check to doyle → builds → doyle gates. Multi-crate scope (activate impl/unit/int when it lands): spt-store
34	(spool format_row), spt-msg (wire.rs delete, emit parse_frame, deliver/listener/ring/ready, lib.rs
35	ADR-0001 framing), spt (api poll/worker-poll delivery.rs::emit → compose `<EVENT>`, cli --from help),
36	spt-daemon (psyrelay/notif/access/shellchan reply-target), spt-live (outbound), KNOWN-HAZARDS Psyche
37	invariant. Until it lands, `api poll` STILL emits the raw `__REPLY_TO__` relic on the public binary.
38
39	**IMPL BUILT + COMMITTED 2026-06-15 @ `5da7fcd`** (branch docs/msg-envelope-adr-0020, stacked on docs `24e0628`; both off main). doyle blessed the 3 decisions (TCP wire = u32 len(from)+from+body structural inner-frame; DrainedMsg{from,body} struct; anon from="" preserved) + 2 re-emphases (adversarial typed-passthrough no-double-wrap; grep-clean incl test fixtures). All 7 tasks done across 27 files: spool DrainedMsg (format_row deleted), wire encode/decode_frame (parse_frame deleted), emit render_event_whole (hook drains, no chunk) + render_event_lines (listener, chunks), api poll/worker compose WHOLE <EVENT>, daemon/live/net reply-target on structural `from`. Self-verify GREEN: 1053 nextest + doctests + clippy -D + traceable EXIT=0 (REQ-MSG-ENVELOPE +doc+impl+unit+int) + grep-clean ZERO __REPLY_TO__ in crates/ + new poll-whole-self-delimiting int + xtask OK. **doyle GATE-PASS 2026-06-15** (independent repro from 5da7fcd: 1054 nextest, traceable 208/208 EXIT=0, reviewed structural frame/DrainedMsg/render_event_whole/adversarial no-double-wrap/psyrelay anti-spoof — all sound). **PR #12 CI then RED on my new poll int** — FALSE-GREEN bug: `spt api poll` is AUTH-GATED (REQ-HAZARD-LOCAL-API-AUTH; needs session_id matching info.json or --token); my E2E pinned neither → passed only where ambient $OWL_SESSION_ID set (dev box), AUTH_REFUSED on clean CI (random sid). FIX @ `ac6c802`: pin const SID on BOTH `ready --once` + the `poll` via .env(OWL_SESSION_ID) + .env_remove(SPT_API_TOKEN); verified with both vars UNSET locally (CI-clean repro). LESSON: any E2E spawning `api poll`/auth-gated machinery must pin OWL_SESSION_ID hermetically — never lean on ambient env (false green); re-verify with the env UNSET. doyle's local gate missed it (his env was set) — gate-repro must clear ambient env too. **PR #12 RED a 2nd time (different test): `notify_shell_e2e` — my cmd_poll_shell over-applied `<EVENT>` to the SHELL-LINK relay (`api poll <shell-id> --link`). Shell frames are RAW MAC'd stamped payloads (spooled anon, from="") the shell child consumes verbatim — NOT a harness `<EVENT>` reader; wrapping broke MAC/parse → never rendered.** FIX @ `caaf797`: cmd_poll_shell raw passthrough (`println!("{}", m.body)`); agent-perch poll/worker/listen keep `<EVENT>`. SCOPE CARVE-OUT documented 4 places (comment at cmd_poll_shell + ADR-0020 clause + REQ-MSG-ENVELOPE title + CONTEXT:685): `<EVENT>`-everywhere = harness ARRIVING-MESSAGE surfaces on AGENT perches only; shell-command channel = distinct internal transport, EXEMPT; notify_shell_e2e = named guard. **2nd LESSON: `cargo nextest run --workspace` SILENTLY SKIPS env-gated E2Es** (notify_shell_e2e self-skips when SPT_NOTIFY_SHELL_BIN unset; the CI `test` job = plain `cargo test -p spt --test notify_shell_e2e` runs it for real). Pre-push sweep MUST build the adapter (`projects/spt-shell-notify` → `cargo build --release` → target/release/notify-shell.exe) + set SPT_NOTIFY_SHELL_BIN + run the cargo-test-only E2Es; nextest-green ≠ CI-green.
40
41	**3rd RED: Windows docs-drift gate exe-lock** (`xtask check` → "failed to remove target\debug\spt.exe", os-error-5). A test-spawned detached daemon (REQ-DAEMON-3 autostart) holds spt.exe; Windows can't overwrite a running exe (Linux can → Linux passed). LATENT on ANY cli.rs-touching PR (doyle's PR #13 hit it too with NO new E2Es — the docs-drift xtask rebuild collides; main never rebuilt there so it stayed hidden). FIX @ `f747e1e`: a Windows-only reap step BEFORE the docs-drift gate, **$GITHUB_WORKSPACE-path-scoped** (see [[no-machinewide-killon-shared-runner]] — NEVER machine-wide on the shared self-hosted runner). Guard rode PR #12 to main → fixes it fleet-wide.
42
43	**ALL MERGED to main @ `25ffd7a` (PR #12, 2026-06-15):** 5da7fcd impl + d2433d4 doyle-T6-docs + ac6c802 poll-hermetic + caaf797 shell-link-exempt + f747e1e CI-guard. doyle pinged perri (byte-capture waits for the operator-gated next release). doyle next: rebase PR #13 (update-apply [[update-apply-confident-message]] + docs incl F-003 strings-pointer) onto main → merge → release. **doyle found T6 doc-drift = MY MISS** (I built T0–T5+T7 code/tests, skipped T6's doc sweep: KNOWN-HAZARDS:348 Psyche-routing 7.x + FAULT-MATRIX:42 + docs-site still call __REPLY_TO__ the live wire header); doyle clearing it himself (docs+impl one PR), I stayed hands-off to avoid collision. NEXT: doyle merges branch→main → ping perri (poll byte-capture confirm) on publish. SHARED-WORKTREE LESSON: doyle saw my mid-flight uncommitted edits on the shared docs branch + tried to build (RED) — coordinate hands-off + gate-from-commit when both agents touch one tree.
44

... [5 lines truncated] ...


/spt:commune with immediate next steps and broad summary of the project's status + end goal. we'll resume in the next session


Operator wants a commune to my Psyche (next steps + status + end goal) before next session. Note: the event-envelope memory now shows ADR-0020 **SHIPPED in v0.7.1 + VERIFIED by perri's byte-capture — loop CLOSED**. First download current Psyche context to commune only the delta.


Bash

$LIVE psyche-download todlando 2>&1 | head -80

Download current Psyche context


<memformat>
<?xml version="1.0"?>
<memformat version="1">
<!-- Changelog: v1 - initial seed -->
<topics>
  <topic name="events">Notable or unusual events and requests</topic>
  <topic name="interactions">Agent interactions -- who, roles, contributions</topic>
  <topic name="reflections">Thoughts on recent work -- what went well, what was tricky</topic>
  <topic name="ideas">Ideas to raise with the user</topic>
  <topic name="improvements">Further improvement ideas for recent problem spaces</topic>
  <topic name="timeline">What happened when, timing, sequencing</topic>
  <topic name="blockers">Current blockers or concerns</topic>
  <topic name="focus">Current focus and immediate next steps</topic>
</topics>
</memformat>
</memformat>

<current machine="HFENDULEAM" project="spt-core" branch="main" head_sha="cb0560052c7392d386d9e68db359bbbf3138dcfe" head_subject="release: v0.7.1 — <EVENT> envelope everywhere + confident update-apply m…" commits_since="0" commits_unpulled="0"/>
**v0.7.1 release SHIPPED (counter 13):** Tagged `cb05600`, signed, published. Hashes: linux `81eededc…` / win `94bb5429…`. Memory (v071-published.md + index entry) captured by parallel instance, including TLS-blip rerun gotcha. doyle holds perri byte-capture relay; fleet roll operator-gated (not auto-initiated). deployah on-call, all threads parked. Armed Monitor waits for doyle's next gap or operator/fleet-roll signal (heartbeat 1800s).<project-context-resolved name="spt-core"/>
Release shipped; T0→T1/T2/T7 flow + PR #13 schedule unaffected. T0 guard still live on main @ `25ffd7a`.


In-project (`project="spt-core"` on `<current/>`) → emit both slices. The Psyche already has the v0.7.1 ship; the **delta** is perri's byte-capture closing the ADR-0020 loop + the operator-requested resume brief (next steps + status + end goal). Write the commune.


Write

<live-context>
# Session wind-down 2026-06-15 — resume brief (todlando)

## What closed this session
- **Drove v0.7.1 release end-to-end** (my leg, proven 7×): bump 0.7.0→0.7.1 + CHANGELOG → push main @cb05600 → doyle pre-tag CI-green gate → tag v0.7.1 → deployah sign+publish (counter 13). PUBLIC. Hashes linux `81eededc…` / win `94bb5429…`.
- **DELTA since last echo:** perri's poll→additionalContext `<EVENT>` byte-capture VERIFIED on the published v0.7.1 surface → **ADR-0020 loop CLOSED end-to-end** (F-002 resolved-shipped; F-003 file-backed [strings] was a docs-visibility gap, closed in v0.7.1 docs — capability already shipped as REQ-MANIFEST-5).
- Earlier in session: built the full REQ-MSG-ENVELOPE/ADR-0020 multi-crate impl (27 files), doyle GATE-PASS, then fixed 3 CI reds (poll auth-gate ambient-env false-green @ac6c802; shell-link `<EVENT>`-overwrap regression @caaf797; Windows exe-lock docs-drift guard @f747e1e — a LATENT fleet-wide bug on any cli.rs PR).

## Immediate next steps (resume)
- **Nothing queued — idle, on-call.** Wake triggers: doyle's next gap/dispatch, or an operator/fleet-roll call (via the armed « spt event » Monitor).
- **Fleet roll of v0.7.1 = operator-gated** (NOT auto-initiate). If called: apply v0.7.1 across nodes → ping per-node hashes → deployah verifies (linux 81eededc / win 94bb5429). enlyzeam pending catch-up → lands straight on v0.7.1 (win 94bb5429).
- Loose end (harmless): stale `spt-core-wt-updapply` worktree deregistered from git but the physical dir is file-locked — clear when the handle frees.

## Lessons logged (3 new memories)
- Pin `OWL_SESSION_ID` hermetically for any auth-gated E2E (`api poll` needs session_id/token) — never lean on ambient env (false green); re-verify with env UNSET.
- `cargo nextest --workspace` SILENTLY SKIPS env-gated E2Es (notify_shell_e2e); pre-push sweep MUST build the adapter (projects/spt-shell-notify) + run the cargo-test-only E2Es. nextest-green ≠ CI-green.
- BINDING: NEVER machine-wide `Get-Process spt|Stop-Process` on HFENDULEAM (shared self-hosted runner w/ live agents) — scope reaps to `$GITHUB_WORKSPACE`/PID.

## Roles (intact)
doyle=gater/spt-core owner, me=executor, perri=spt-claude-code adapter builder, deployah=publisher. Shared-worktree hazard observed (doyle+me on one tree) → coordinate hands-off + gate-from-commit.
</live-context>
<project-context>
# spt-core status + end goal — 2026-06-15 (post v0.7.1)

## Current state
- **main @ cb05600 = v0.7.1 PUBLIC** (release counter 13). Releases v0.5.0–v0.7.1 all public (counters 10–13); publisher leg proven 7×.
- **v0.7.1 contents:** ADR-0020 `<EVENT>`-everywhere (the `<EVENT type=msg from=…>` envelope is the SOLE arriving-message format at every AGENT-perch surface — api listen + api poll/worker-poll; `__REPLY_TO__` relic removed; `(from,body)` carried structurally, composed at the delivery edge; F-002 dissolved). **Shell-link relay (`api poll <shell-id> --link`) is EXEMPT** — it carries raw MAC'd stamped frames the shell child consumes verbatim (carve-out doc'd in ADR-0020 + REQ-MSG-ENVELOPE title + CONTEXT:685 + a cmd_poll_shell comment; notify_shell_e2e is the named guard). Plus: confident `spt update apply` "Updated spt-core to vX.Y.Z." message; published {key} substitution catalog + [digest] rule + [strings] file-pointer syntax; Windows CI exe-lock reap guard ($GITHUB_WORKSPACE-scoped).
- M12 fully gated + shipped (v0.7.0). REQ-MSG-ENVELOPE [doc,impl,unit,int] evidenced; traceable EXIT 0.

## Parallel track (perri / spt-claude-code "sptc" adapter)
Builds from the PUBLISHED surface only (spt-releases + GH-Pages). ADR-0020 byte-capture now VERIFIED → her poll-path unblocked. Authoring /sptc:* skill bodies as file-backed [strings] (`key = { file = "skills/x.md" }`, REQ-MANIFEST-5). Next parity surfaces she'll wire: file-backed [strings] (done), shortcut_basename, endpoint-run, cc-launcher, setup, whoami-alias. Flow: perri finds gap → doyle designs/dispatches → todlando builds → doyle gates → perri validates.

## End goal
spt-core = harness-INDEPENDENT core for an agent ecosystem (messaging, live-agent lifecycle, terminal hosting, P2P networking, runtime-manifest harness contract). It never caters to a specific harness — adapters format its output. M12 + ADR-0020 unblock perri building spt-claude-code from the published release surface. Gating discipline: doyle independently verifies every wave; activate traceable stages per-wave; gate the RECORDED design (CONTEXT.md/ADRs), not just the impl.

## Likely next work
- Operator-gated fleet roll of v0.7.1.
- perri's remaining sptc parity surfaces → spt-core gaps she surfaces (doyle dispatches → I build → doyle gates).
</project-context>


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

<live-context>
# Session wind-down 2026-06-15 — resume brief (todlando)

## What closed this session
- **Drove v0.7.1 release end-to-end** (my leg, proven 7×): bump 0.7.0→0.7.1 + CHANGELOG → push main @cb05600 → doyle pre-tag CI-green gate → tag v0.7.1 → deployah sign+publish (counter 13). PUBLIC. Hashes linux `81eededc…` / win `94bb5429…`.
- **DELTA since last echo:** perri's poll→additionalContext `<EVENT>` byte-capture VERIFIED on the published v0.7.1 surface → **ADR-0020 loop CLOSED end-to-end** (F-002 resolved-shipped; F-003 file-backed [strings] was a docs-visibility gap, closed in v0.7.1 docs — capability already shipped as REQ-MANIFEST-5).
- Earlier in session: built the full REQ-MSG-ENVELOPE/ADR-0020 multi-crate impl (27 files), doyle GATE-PASS, then fixed 3 CI reds (poll auth-gate ambient-env false-green @ac6c802; shell-link `<EVENT>`-overwrap regression @caaf797; Windows exe-lock docs-drift guard @f747e1e — a LATENT fleet-wide bug on any cli.rs PR).

## Immediate next steps (resume)
- **Nothing queued — idle, on-call.** Wake triggers: doyle's next gap/dispatch, or an operator/fleet-roll call (via the armed « spt event » Monitor).
- **Fleet roll of v0.7.1 = operator-gated** (NOT auto-initiate). If called: apply v0.7.1 across nodes → ping per-node hashes → deployah verifies (linux 81eededc / win 94bb5429). enlyzeam pending catch-up → lands straight on v0.7.1 (win 94bb5429).
- Loose end (harmless): stale `spt-core-wt-updapply` worktree deregistered from git but the physical dir is file-locked — clear when the handle frees.

## Lessons logged (3 new memories)
- Pin `OWL_SESSION_ID` hermetically for any auth-gated E2E (`api poll` needs session_id/token) — never lean on ambient env (false green); re-verify with env UNSET.
- `cargo nextest --workspace` SILENTLY SKIPS env-gated E2Es (notify_shell_e2e); pre-push sweep MUST build the adapter (projects/spt-shell-notify) + run the cargo-test-only E2Es. nextest-green ≠ CI-green.
- BINDING: NEVER machine-wide `Get-Process spt|Stop-Process` on HFENDULEAM (shared self-hosted runner w/ live agents) — scope reaps to `$GITHUB_WORKSPACE`/PID.

## Roles (intact)
doyle=gater/spt-core owner, me=executor, perri=spt-claude-code adapter builder, deployah=publisher. Shared-worktree hazard observed (doyle+me on one tree) → coordinate hands-off + gate-from-commit.
</live-context>
<project-context>
# spt-core status + end goal — 2026-06-15 (post v0.7.1)

## Current state
- **main @ cb05600 = v0.7.1 PUBLIC** (release counter 13). Releases v0.5.0–v0.7.1 all public (counters 10–13); publisher leg proven 7×.
- **v0.7.1 contents:** ADR-0020 `<EVENT>`-everywhere (the `<EVENT type=msg from=…>` envelope is the SOLE arriving-message format at every AGENT-perch surface — api listen + api poll/worker-poll; `__REPLY_TO__` relic removed; `(from,body)` carried structurally, composed at the delivery edge; F-002 dissolved). **Shell-link relay (`api poll <shell-id> --link`) is EXEMPT** — it carries raw MAC'd stamped frames the shell child consumes verbatim (carve-out doc'd in ADR-0020 + REQ-MSG-ENVELOPE title + CONTEXT:685 + a cmd_poll_shell comment; notify_shell_e2e is the named guard). Plus: confident `spt update apply` "Updated spt-core to vX.Y.Z." message; published {key} substitution catalog + [digest] rule + [strings] file-pointer syntax; Windows CI exe-lock reap guard ($GITHUB_WORKSPACE-scoped).
- M12 fully gated + shipped (v0.7.0). REQ-MSG-ENVELOPE [doc,impl,unit,int] evidenced; traceable EXIT 0.

## Parallel track (perri / spt-claude-code "sptc" adapter)
Builds from the PUBLISHED surface only (spt-releases + GH-Pages). ADR-0020 byte-capture now VERIFIED → her poll-path unblocked. Authoring /sptc:* skill bodies as file-backed [strings] (`key = { file = "skills/x.md" }`, REQ-MANIFEST-5). Next parity surfaces she'll wire: file-backed [strings] (done), shortcut_basename, endpoint-run, cc-launcher, setup, whoami-alias. Flow: perri finds gap → doyle designs/dispatches → todlando builds → doyle gates → perri validates.

## End goal
spt-core = harness-INDEPENDENT core for an agent ecosystem (messaging, live-agent lifecycle, terminal hosting, P2P networking, runtime-manifest harness contract). It never caters to a specific harness — adapters format its output. M12 + ADR-0020 unblock perri building spt-claude-code from the published release surface. Gating discipline: doyle independently verifies every wave; activate traceable stages per-wave; gate the RECORDED design (CONTEXT.md/ADRs), not just the impl.

## Likely next work
- Operator-gated fleet roll of v0.7.1.
- perri's remaining sptc parity surfaces → spt-core gaps she surfaces (doyle dispatches → I build → doyle gates).
</project-context>


Commune dropped to `.claude/todlando-commune.md` — my Self listener will detect it, the Psyche wrapper ingests via the existing session, file auto-deletes on success. Both slices populated (in-project): live-context (my next-steps + lessons + roles) and project-context (v0.7.1 status + end goal).

Session wind-down complete. **v0.7.1 PUBLIC (counter 13); ADR-0020 loop closed end-to-end (perri byte-capture verified).** Idle + on-call — fleet roll operator-gated, perri self-driving on sptc parity, doyle holds the gater seat. Resuming next session.


ScheduleWakeup

Session wind-down communed; v0.7.1 shipped + ADR-0020 loop closed; idle on-call, Monitor is wake signal, fallback heartbeat

Prompt: <<autonomous-loop-dynamic>>


Next wakeup scheduled for 05:10:00 (in 1827s). Nothing more to do this turn — the harness re-invokes you when the wakeup fires or a task-notification arrives.


Communed and standing down for the session.

**Final state:** v0.7.1 PUBLIC (counter 13) — ADR-0020 `<EVENT>`-everywhere shipped and verified end-to-end via perri's byte-capture; loop closed. All threads parked: fleet roll operator-gated, perri self-driving on sptc parity surfaces, doyle holds gater + perri-relay, deployah on-call for hash verify. Three lessons logged. Commune queued for Psyche ingestion. Idle + on-call via the armed Monitor — resume next session.