3. Offer create first subnet — surfaces a **QR code** of the TOTP seed → spawns a window
   (self-elevating; see elevation + M12 dep #2)
4. If spt-core already installed → branch: new subnet / **join subnet (= add this machine)** /
   show join-code / just-add-endpoint  *(join == add-this-machine — collapsed)*
5. Legacy migration — detect claude_skill_owl/owl → migrate identity+agents+psyche
   (spt-core CONTEXT.md first-class commitment)
6. OS-service registration (always-on daemon)
7. ccs profile wiring — if `~/.ccs` present; **also offer to install ccs** (+1-sentence value
   prop) if absent
8. Psyche cross-machine sync — *only the optional git-backup angle*; in-subnet sync may be
   automatic (verify)
9. Doctor/verify at end

**LOCKED:** v1 = {1,2,3,4,5,6,7} (all primary spt-core features + ccs needed now). Defer
{8,9}. _Operator said "9. agree" then "except 9" — treating 9 as deferred per final scope;
flag if verify should fold inline._

# spt-claude-code — scoping decision ledger

> Running source of truth for the scoping session (started 2026-06-13, doyle).
> Decisions marked **LOCKED** are user-ratified; **OPEN** are still in grill.
> This project will be re-homed onto the `experimplate` template structure once
> that template is authored — until then this ledger is the interim record.

## What this project is

**LOCKED.** `spt-claude-code` is the rebuilt Claude Code harness adapter (the
`claude-spt` adapter) — simultaneously:
1. spt-core's **v1 acceptance proof** (feature parity with legacy `claude_skill_owl`,
   delegating all core to `spt.exe`).
2. spt-core's **first casual-end-user entrypoint** — published as a CC plugin on
   `SaberMage/cplugs`, like legacy spt today.
3. Invisibly an **spt-core installer** for users who don't have it. This is the
   intended pattern for *all* casual-facing harness/shell adapters.

Parity is **user-facing feature parity, NOT 1:1** — most legacy machinery moved
INTO spt.exe/daemon; the adapter is the CC-specific shell only. Dead/rare legacy
concepts get dropped (parity-trim → REQ seed, OPEN). Built by maintainer **perri**
from `SaberMage/spt-releases` + GH Pages docs ONLY (public surface), never the
spt-core source tree.

Legacy parity inventory: captured in this session (claude_skill_owl v1.11.25 —
7 hooks, 12 `/spt:*` skills, owl.exe, cplugs marketplace; messaging / live-agent /
working-perches / binary-handoff / psyche-sync / doctor).

## Distribution architecture

**LOCKED.** Split by volatility (Claude Code has NO plugin-file integrity check —
in-place edits don't orphan; only old version dirs orphan on update, GC'd 7d):

| Layer | Contents | Home | Update path | Churn |
|---|---|---|---|---|
| Plugin (marketplace) | namespaced `/spt:*` skill *skeletons*, `hooks.json` (call `spt api`), SessionStart bootstrap (installs spt-core if absent), `plugin.json` | `SaberMage/cplugs` | `claude plugin update` (rare structural changes only) | low |
| spt binary | all logic | spt-core domain | spt-core's own framework (signed, peer-propagated) | high |
| CC adapter manifest | `[digest]` extractor, profiles, strings, hints | spt-core adapter registry (NOT plugin files) | spt-core adapter-update (file-pull) | medium |

- Skills stay **plugin-provided** → keep `/spt:` namespace (user-scope skills can't
  namespace: `~/.claude/skills` → bare `/live`, collision-prone). Rejected global-skills.
- The "bulk" spt-core installs/updates = **manifest + binary**, not the skills.
- Plugin is a true thin skeleton (wrappers + bootstrap) → rarely needs a marketplace bump.
- → ADR-0001 (to write).

### Skill-instruction delivery — **LOCKED: UPS-injection** (fetch-stub VETOED)

A `UserPromptSubmit` hook detects `/spt:X` in the prompt and injects X's real
instructions as additionalContext. SKILL.md files stay skeletons; instruction churn
lives in spt-core-conducted `[strings]` (file-backed — see M12 dep).
- **fetch-stub VETOED** (operator): adds terminal noise + latency + an extra tool call.
- UPS-injection chosen on operator's empirical confidence from legacy: UPS *does* pick up
  slash-commands (CC highlights slash-commands anywhere in the entry field and isn't strict
  about trailing text). My fact-check called this undocumented/uncertain — **must confirm
  empirically at build time**, but design on it.
- Long instruction bodies → **file-backed adapter strings** (M12 spt-core dep #1) so the
  manifest doesn't bloat.
- `[hints]` channel (same UPS hook, keyword-triggered) kept as-is — legacy proves it works.

### Update notification — **LOCKED**

spt-core conducts updates seamlessly → users don't check. Version-of-truth =
manifest/binary version spt-core tracks (`spt adapter list` / `/spt:version`), NOT the
~static marketplace skeleton version. On update applied: spt-core announces via one-time
SessionStart additionalContext (changelog) + optional `notify`. Update path = file-pull
(real channel) + cautionary `claude plugin update` (skeleton sync) — dual, kept in sync.

## ccs integration

**LOCKED.** ccs = **profile(s) under spt-claude-code** (`claude-spt:glm`,
`claude-spt:kimi`, …), NOT its own adapter. It's structurally CC — only launch command +
model/billing backend differ, which is exactly the profile seam (leaf-replace
spawn/psyche/echo command templates). Per-profile `~/.ccs` log dir → profile also
leaf-replaces the history/`[digest]` locate-template. **Hybrid** delivery: ship the
profile *templates* (ccs-invoking command structure), user supplies own ccs config/keys.
Reconcile spt-core CONTEXT.md: cross-adapter fallback must target `<adapter>:<profile>`,
not only bare adapter_name (profile model already supports composite addressing).

## `/spt:setup` skill

Needed because most users install the plugin **mid-session** (no SessionStart fire).
Proposed paths:
1. Generate `cc`/`cc <id>` launcher (capsule-style) at project root
2. Offer `.gitignore` the launchers
3. Offer create first subnet (self-elevating TOTP — see elevation below)
4. If spt-core already installed → branch: new subnet / join subnet / show join-code /
   add-this-machine / just-add-endpoint
5. Legacy migration — detect claude_skill_owl/owl → migrate identity+agents+psyche
   (spt-core CONTEXT.md first-class commitment)
6. OS-service registration (always-on daemon)
7. ccs profile wiring (if `~/.ccs` detected)
8. Psyche cross-machine sync (psyche-sync-setup)
9. Doctor/verify at end

**OPEN:** v1 scope. doyle rec: v1 = {1,2,3,4,5,9}; defer {6,7,8}.

### `cc` launcher (capsule-style) — **LOCKED (design)**

= thin wrapper over spt-core's **spt-hosted topology** (broker PTY + inject + attach),
NOT a reimplemented psmux. `cc <id>` → `spt` spawns-or-attaches a CC endpoint in a broker
PTY. Reattach-if-exists / `--live` / `--resume` = spt-core spawn/resume seam semantics.
No-id picker = reuse spt-core's built-in id-resolution (don't reimplement legacy SEED-001).
Sendkeys hazards = spt-core's inject concern, not the adapter's.
**OPEN gap:** confirm spt-core "remote attach" covers *local user interactive attach* to a
hosted CC session (not just headless PTY).

### Elevation (subnet create/join/show-totp) — **LOCKED (design)**

Detect (interactive? elevated? desktop?) → least-friction path:
Windows = self-elevating UAC window; Linux+desktop = pkexec/polkit or x-terminal-emulator;
Linux+TTY = inline sudo; headless/no-TTY = print exact command, agent relays to user.
Question the premise: scope elevation to only steps that need it (service-install /
firewall / privileged-port) — subnet-create itself likely unprivileged.

## CI model

**LOCKED.** Wholly **agent-driven, autonomous, no LLM-in-the-loop**, on the existing
Win+Linux fleet (hfenduleam + kitsubito). GH runners DROPPED.
- Gates (build, unit, `traceable-reqs check`, manifest-schema) = deterministic scripts.
- Acceptance = scripted orchestration spawning real `claude`/headless sessions as the
  **system-under-test** (LLM is SUT, never the runner); assert spt-state/digest output.
- **Reporting bus = legacy spt** (`$OWL send` CI progress to responsible agent) — dogfoods
  the product as its own CI nervous system.
- Rationale: a stock GH runner physically can't run Claude Code (auth/interactivity);
  only a real harness on the fleet reaches the acceptance bar. spt-core's GH-runner
  justification (heavy multi-platform Rust + signed releases + two-host net) doesn't carry
  — the adapter binary is thin glue and delegates releases/signing to spt.exe.
- **OPEN:** trigger (git-hook signal vs polling routine).
- This CI pattern → reusable, goes in `experimplate`.

## Open threads (grill queue)

- [ ] `/spt:setup` v1 scope (1–9 above)
- [ ] Parity-trim: which legacy concepts/skills DON'T survive → becomes REQ seed / acceptance bar
- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
- [ ] CI trigger mechanism
- [ ] spt-core "remote attach" local-interactive confirmation
- [ ] Handoff framing to perri (how the package is presented + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code

-3. Offer create first subnet (self-elevating TOTP — see elevation below)

-4. If spt-core already installed → branch: new subnet / join subnet / show join-code /

-   add-this-machine / just-add-endpoint

+3. Offer create first subnet — surfaces a **QR code** of the TOTP seed → spawns a window

+   (self-elevating; see elevation + M12 dep #2)

+4. If spt-core already installed → branch: new subnet / **join subnet (= add this machine)** /

+   show join-code / just-add-endpoint  *(join == add-this-machine — collapsed)*

-7. ccs profile wiring (if `~/.ccs` detected)

-8. Psyche cross-machine sync (psyche-sync-setup)

+7. ccs profile wiring — if `~/.ccs` present; **also offer to install ccs** (+1-sentence value

+8. Psyche cross-machine sync — *only the optional git-backup angle*; in-subnet sync may be

+**LOCKED:** v1 = {1,2,3,4,5,6,7} (all primary spt-core features + ccs needed now). Defer

+{8,9}. _Operator said "9. agree" then "except 9" — treating 9 as deferred per final scope;


120	## CI model
121
122	**LOCKED.** Wholly **agent-driven, autonomous, no LLM-in-the-loop**, on the existing
123	Win+Linux fleet (hfenduleam + kitsubito). GH runners DROPPED.
124	- Gates (build, unit, `traceable-reqs check`, manifest-schema) = deterministic scripts.
125	- Acceptance = scripted orchestration spawning real `claude`/headless sessions as the
126	  **system-under-test** (LLM is SUT, never the runner); assert spt-state/digest output.
127	- **Reporting bus = legacy spt** (`$OWL send` CI progress to responsible agent) — dogfoods
128	  the product as its own CI nervous system.
129	- Rationale: a stock GH runner physically can't run Claude Code (auth/interactivity);
130	  only a real harness on the fleet reaches the acceptance bar. spt-core's GH-runner
131	  justification (heavy multi-platform Rust + signed releases + two-host net) doesn't carry
132	  — the adapter binary is thin glue and delegates releases/signing to spt.exe.
133	- **OPEN:** trigger (git-hook signal vs polling routine).
134	- This CI pattern → reusable, goes in `experimplate`.
135
136	## Open threads (grill queue)
137
138	- [ ] `/spt:setup` v1 scope (1–9 above)
139	- [ ] Parity-trim: which legacy concepts/skills DON'T survive → becomes REQ seed / acceptance bar
140	- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
141	- [ ] CI trigger mechanism
142	- [ ] spt-core "remote attach" local-interactive confirmation
143	- [ ] Handoff framing to perri (how the package is presented + public-surface-only constraint)
144	- [ ] Docs split: what lands in experimplate vs spt-claude-code
145

## CI model

**LOCKED.** Wholly **agent-driven, autonomous, no LLM-in-the-loop**, on the existing
Win+Linux fleet (hfenduleam + kitsubito). GH runners DROPPED.
- Gates (build, unit, `traceable-reqs check`, manifest-schema) = deterministic scripts.
- Acceptance = scripted orchestration spawning real `claude`/headless sessions as the
  **system-under-test** (LLM is SUT, never the runner); assert spt-state/digest output.
- **Reporting bus = legacy spt** (`$OWL send` CI progress to responsible agent) — dogfoods
  the product as its own CI nervous system.
- Rationale: a stock GH runner physically can't run Claude Code (auth/interactivity);
  only a real harness on the fleet reaches the acceptance bar. spt-core's GH-runner
  justification (heavy multi-platform Rust + signed releases + two-host net) doesn't carry
  — the adapter binary is thin glue and delegates releases/signing to spt.exe.
- **OPEN:** trigger (git-hook signal vs polling routine).
- This CI pattern → reusable, goes in `experimplate`.

## Open threads (grill queue)

- [ ] `/spt:setup` v1 scope (1–9 above)
- [ ] Parity-trim: which legacy concepts/skills DON'T survive → becomes REQ seed / acceptance bar
- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
- [ ] CI trigger mechanism
- [ ] spt-core "remote attach" local-interactive confirmation
- [ ] Handoff framing to perri (how the package is presented + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code


a note about "Adapter-strings deliver skill instructions" -- if it doesn't already exist, perhaps we should slate a complimentary spt-core feature add: adapter strings can, in addition to being raw st…


Align spt-claude-code with spt-core v1 requirements


Edit

## Open threads (grill queue)

- [ ] `/spt:setup` v1 scope (1–9 above)
- [ ] Parity-trim: which legacy concepts/skills DON'T survive → becomes REQ seed / acceptance bar
- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
- [ ] CI trigger mechanism
- [ ] spt-core "remote attach" local-interactive confirmation
- [ ] Handoff framing to perri (how the package is presented + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code

## Parity-trim (→ REQ seed / acceptance bar)

**DROP** (LOCKED): Spine & Touch; binary-handoff/owl.exe trampoline; TCP transport + SQLite
spool + registry + listener internals; localhost-only networking. (all spt.exe/daemon now)

**TRANSFORM** (LOCKED): Capsule→spt-hosted + `cc`; echo-commune Haiku JSONL→`[digest]`
extractor (M10); psyche-sync→subnet/`/spt:setup`; `doctor`→`spt doctor`/setup-verify;
working-perches→`api worker-start/stop`.

**ADD** (LOCKED): `/spt:setup`, `/spt:version`, subnet skills (create/join/show-code),
profiles + strings + hints wiring, ccs profiles.

**DECIDE** (LOCKED): DROP `/spt:fork` + `amend-signoff`. (fork near-unused & only meaningful
harness-hosted; amend-signoff deprecated, folds into a follow-up commune)

**KEEP — under topology review** (operator interrogated each vs harness-hosted/spt-hosted;
finalizing once spt-core implemented-state investigation lands):
- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm` — KEEP, uncontested.
- `/signoff` — KEEP. Writes a file either way; consumption differs. spt-hosted signoff ⇒
  endpoint shutdown ⇒ user dropped from endpoint PTY back to terminal (confirm UX).
- `/revive` — **questioned.** Legacy purpose = recover broken states (orphaned psyche,
  dead listener); spt-core's daemon owns psyche-loop + liveness, so those failure modes
  largely vanish. doyle lean: DROP or fold into `/live` unless harness-hosted relay-restart
  needs it. Pending investigation.
- `/clear-psyche` — **lean DROP.** Operator never uses it; spt-core equivalent = delete
  endpoint + recreate. Pending.
- `/force-stop` — KEEP, topology-aware: harness-hosted = stop spt machinery (heir to
  $OWL/$LIVE stop); spt-hosted = endpoint shutdown / self-stop. (installed skill already
  session-aware.)
- `/whoami` — **DROP** (skill). Equivalent baked into `spt endpoint list` (caller's perch
  shown distinctively at top — VERIFY). CLI `spt whoami` obsolescence → M12 dep #5.
- `/list-agents` — KEEP (→ `spt endpoint list`).

**Worried finding (gating):** operator can't find any CLI today to bring up an spt-hosted
endpoint with harness PTY access / user attach. → investigation in flight; if DESIGN-ONLY,
it's M12 dep #3 (highest priority) and several KEEP calls + the `cc` launcher block on it.

## spt-core upstream deps
Recorded in `../spt-core/M12-CANDIDATES.md` (1: file-backed strings · 2: subnet QR +
self-elevating window · 3: spt-hosted bringup + PTY attach · 4: fallback targets
adapter:profile · 5: whoami obsolescence). spt-claude-code blocks on these.

## Open threads (grill queue)

- [ ] KEEP-bucket finalize (`/revive`, `/clear-psyche`, `/whoami`, `/force-stop` UX) — pending investigation
- [ ] spt-hosted bringup + PTY attach: implemented-vs-design (gating) — pending investigation
- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
- [ ] CI trigger mechanism
- [ ] M12 framing + what `spt rc` denotes
- [ ] Handoff framing to perri (package presentation + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code


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

## Parity-trim (→ REQ seed / acceptance bar)

**DROP** (LOCKED): Spine & Touch; binary-handoff/owl.exe trampoline; TCP transport + SQLite
spool + registry + listener internals; localhost-only networking. (all spt.exe/daemon now)

**TRANSFORM** (LOCKED): Capsule→spt-hosted + `cc`; echo-commune Haiku JSONL→`[digest]`
extractor (M10); psyche-sync→subnet/`/spt:setup`; `doctor`→`spt doctor`/setup-verify;
working-perches→`api worker-start/stop`.

**ADD** (LOCKED): `/spt:setup`, `/spt:version`, subnet skills (create/join/show-code),
profiles + strings + hints wiring, ccs profiles.

**DECIDE** (LOCKED): DROP `/spt:fork` + `amend-signoff`. (fork near-unused & only meaningful
harness-hosted; amend-signoff deprecated, folds into a follow-up commune)

**KEEP — under topology review** (operator interrogated each vs harness-hosted/spt-hosted;
finalizing once spt-core implemented-state investigation lands):
- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm` — KEEP, uncontested.
- `/signoff` — KEEP. Writes a file either way; consumption differs. spt-hosted signoff ⇒
  endpoint shutdown ⇒ user dropped from endpoint PTY back to terminal (confirm UX).
- `/revive` — **questioned.** Legacy purpose = recover broken states (orphaned psyche,
  dead listener); spt-core's daemon owns psyche-loop + liveness, so those failure modes
  largely vanish. doyle lean: DROP or fold into `/live` unless harness-hosted relay-restart
  needs it. Pending investigation.
- `/clear-psyche` — **lean DROP.** Operator never uses it; spt-core equivalent = delete
  endpoint + recreate. Pending.
- `/force-stop` — KEEP, topology-aware: harness-hosted = stop spt machinery (heir to
  $OWL/$LIVE stop); spt-hosted = endpoint shutdown / self-stop. (installed skill already
  session-aware.)
- `/whoami` — **DROP** (skill). Equivalent baked into `spt endpoint list` (caller's perch
  shown distinctively at top — VERIFY). CLI `spt whoami` obsolescence → M12 dep #5.
- `/list-agents` — KEEP (→ `spt endpoint list`).

**Worried finding (gating):** operator can't find any CLI today to bring up an spt-hosted
endpoint with harness PTY access / user attach. → investigation in flight; if DESIGN-ONLY,
it's M12 dep #3 (highest priority) and several KEEP calls + the `cc` launcher block on it.

## spt-core upstream deps
Recorded in `../spt-core/M12-CANDIDATES.md` (1: file-backed strings · 2: subnet QR +
self-elevating window · 3: spt-hosted bringup + PTY attach · 4: fallback targets
adapter:profile · 5: whoami obsolescence). spt-claude-code blocks on these.

## Open threads (grill queue)

- [ ] KEEP-bucket finalize (`/revive`, `/clear-psyche`, `/whoami`, `/force-stop` UX) — pending investigation
- [ ] spt-hosted bringup + PTY attach: implemented-vs-design (gating) — pending investigation
- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
- [ ] CI trigger mechanism
- [ ] M12 framing + what `spt rc` denotes
- [ ] Handoff framing to perri (package presentation + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code

# spt-claude-code — scoping decision ledger

> Running source of truth for the scoping session (started 2026-06-13, doyle).
> Decisions marked **LOCKED** are user-ratified; **OPEN** are still in grill.
> This project will be re-homed onto the `experimplate` template structure once
> that template is authored — until then this ledger is the interim record.

## What this project is

**LOCKED.** `spt-claude-code` is the rebuilt Claude Code harness adapter (the
`claude-spt` adapter) — simultaneously:
1. spt-core's **v1 acceptance proof** (feature parity with legacy `claude_skill_owl`,
   delegating all core to `spt.exe`).
2. spt-core's **first casual-end-user entrypoint** — published as a CC plugin on
   `SaberMage/cplugs`, like legacy spt today.
3. Invisibly an **spt-core installer** for users who don't have it. This is the
   intended pattern for *all* casual-facing harness/shell adapters.

Parity is **user-facing feature parity, NOT 1:1** — most legacy machinery moved
INTO spt.exe/daemon; the adapter is the CC-specific shell only. Dead/rare legacy
concepts get dropped (parity-trim → REQ seed, OPEN). Built by maintainer **perri**
from `SaberMage/spt-releases` + GH Pages docs ONLY (public surface), never the
spt-core source tree.

Legacy parity inventory: captured in this session (claude_skill_owl v1.11.25 —
7 hooks, 12 `/spt:*` skills, owl.exe, cplugs marketplace; messaging / live-agent /
working-perches / binary-handoff / psyche-sync / doctor).

## Distribution architecture

**LOCKED.** Split by volatility (Claude Code has NO plugin-file integrity check —
in-place edits don't orphan; only old version dirs orphan on update, GC'd 7d):

| Layer | Contents | Home | Update path | Churn |
|---|---|---|---|---|
| Plugin (marketplace) | namespaced `/spt:*` skill *skeletons*, `hooks.json` (call `spt api`), SessionStart bootstrap (installs spt-core if absent), `plugin.json` | `SaberMage/cplugs` | `claude plugin update` (rare structural changes only) | low |
| spt binary | all logic | spt-core domain | spt-core's own framework (signed, peer-propagated) | high |
| CC adapter manifest | `[digest]` extractor, profiles, strings, hints | spt-core adapter registry (NOT plugin files) | spt-core adapter-update (file-pull) | medium |

- Skills stay **plugin-provided** → keep `/spt:` namespace (user-scope skills can't
  namespace: `~/.claude/skills` → bare `/live`, collision-prone). Rejected global-skills.
- The "bulk" spt-core installs/updates = **manifest + binary**, not the skills.
- Plugin is a true thin skeleton (wrappers + bootstrap) → rarely needs a marketplace bump.
- → ADR-0001 (to write).

### Skill-instruction delivery — **LOCKED: UPS-injection** (fetch-stub VETOED)

A `UserPromptSubmit` hook detects `/spt:X` in the prompt and injects X's real
instructions as additionalContext. SKILL.md files stay skeletons; instruction churn
lives in spt-core-conducted `[strings]` (file-backed — see M12 dep).
- **fetch-stub VETOED** (operator): adds terminal noise + latency + an extra tool call.
- UPS-injection chosen on operator's empirical confidence from legacy: UPS *does* pick up
  slash-commands (CC highlights slash-commands anywhere in the entry field and isn't strict
  about trailing text). My fact-check called this undocumented/uncertain — **must confirm
  empirically at build time**, but design on it.
- Long instruction bodies → **file-backed adapter strings** (M12 spt-core dep #1) so the
  manifest doesn't bloat.
- `[hints]` channel (same UPS hook, keyword-triggered) kept as-is — legacy proves it works.

### Update notification — **LOCKED**

spt-core conducts updates seamlessly → users don't check. Version-of-truth =
manifest/binary version spt-core tracks (`spt adapter list` / `/spt:version`), NOT the
~static marketplace skeleton version. On update applied: spt-core announces via one-time
SessionStart additionalContext (changelog) + optional `notify`. Update path = file-pull
(real channel) + cautionary `claude plugin update` (skeleton sync) — dual, kept in sync.

## ccs integration

**LOCKED.** ccs = **profile(s) under spt-claude-code** (`claude-spt:glm`,
`claude-spt:kimi`, …), NOT its own adapter. It's structurally CC — only launch command +
model/billing backend differ, which is exactly the profile seam (leaf-replace
spawn/psyche/echo command templates). Per-profile `~/.ccs` log dir → profile also
leaf-replaces the history/`[digest]` locate-template. **Hybrid** delivery: ship the
profile *templates* (ccs-invoking command structure), user supplies own ccs config/keys.
Reconcile spt-core CONTEXT.md: cross-adapter fallback must target `<adapter>:<profile>`,
not only bare adapter_name (profile model already supports composite addressing).

## `/spt:setup` skill

Needed because most users install the plugin **mid-session** (no SessionStart fire).
Proposed paths:
1. Generate `cc`/`cc <id>` launcher (capsule-style) at project root
2. Offer `.gitignore` the launchers
3. Offer create first subnet — surfaces a **QR code** of the TOTP seed → spawns a window
   (self-elevating; see elevation + M12 dep #2)
4. If spt-core already installed → branch: new subnet / **join subnet (= add this machine)** /
   show join-code / just-add-endpoint  *(join == add-this-machine — collapsed)*
5. Legacy migration — detect claude_skill_owl/owl → migrate identity+agents+psyche
   (spt-core CONTEXT.md first-class commitment)
6. OS-service registration (always-on daemon)
7. ccs profile wiring — if `~/.ccs` present; **also offer to install ccs** (+1-sentence value
   prop) if absent
8. Psyche cross-machine sync — *only the optional git-backup angle*; in-subnet sync may be
   automatic (verify)
9. Doctor/verify at end

**LOCKED:** v1 = {1,2,3,4,5,6,7} (all primary spt-core features + ccs needed now). Defer
{8,9}. _Operator said "9. agree" then "except 9" — treating 9 as deferred per final scope;
flag if verify should fold inline._

### `cc` launcher (capsule-style) — **LOCKED (design)**

= thin wrapper over spt-core's **spt-hosted topology** (broker PTY + inject + attach),
NOT a reimplemented psmux. `cc <id>` → `spt` spawns-or-attaches a CC endpoint in a broker
PTY. Reattach-if-exists / `--live` / `--resume` = spt-core spawn/resume seam semantics.
No-id picker = reuse spt-core's built-in id-resolution (don't reimplement legacy SEED-001).
Sendkeys hazards = spt-core's inject concern, not the adapter's.
**OPEN gap:** confirm spt-core "remote attach" covers *local user interactive attach* to a
hosted CC session (not just headless PTY).

### Elevation (subnet create/join/show-totp) — **LOCKED (design)**

Detect (interactive? elevated? desktop?) → least-friction path:
Windows = self-elevating UAC window; Linux+desktop = pkexec/polkit or x-terminal-emulator;
Linux+TTY = inline sudo; headless/no-TTY = print exact command, agent relays to user.
Question the premise: scope elevation to only steps that need it (service-install /
firewall / privileged-port) — subnet-create itself likely unprivileged.

## CI model

**LOCKED.** Wholly **agent-driven, autonomous, no LLM-in-the-loop**, on the existing
Win+Linux fleet (hfenduleam + kitsubito). GH runners DROPPED.
- Gates (build, unit, `traceable-reqs check`, manifest-schema) = deterministic scripts.
- Acceptance = scripted orchestration spawning real `claude`/headless sessions as the
  **system-under-test** (LLM is SUT, never the runner); assert spt-state/digest output.
- **Reporting bus = legacy spt** (`$OWL send` CI progress to responsible agent) — dogfoods
  the product as its own CI nervous system.
- Rationale: a stock GH runner physically can't run Claude Code (auth/interactivity);
  only a real harness on the fleet reaches the acceptance bar. spt-core's GH-runner
  justification (heavy multi-platform Rust + signed releases + two-host net) doesn't carry
  — the adapter binary is thin glue and delegates releases/signing to spt.exe.
- **OPEN:** trigger (git-hook signal vs polling routine).
- This CI pattern → reusable, goes in `experimplate`.

## Open threads (grill queue)

- [ ] `/spt:setup` v1 scope (1–9 above)
- [ ] Parity-trim: which legacy concepts/skills DON'T survive → becomes REQ seed / acceptance bar
- [ ] Release / changelog / published-docs procedure reframed same-repo (template content)
- [ ] CI trigger mechanism
- [ ] spt-core "remote attach" local-interactive confirmation
- [ ] Handoff framing to perri (how the package is presented + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code

+## Parity-trim (→ REQ seed / acceptance bar)

+**DROP** (LOCKED): Spine & Touch; binary-handoff/owl.exe trampoline; TCP transport + SQLite

+spool + registry + listener internals; localhost-only networking. (all spt.exe/daemon now)

+**TRANSFORM** (LOCKED): Capsule→spt-hosted + `cc`; echo-commune Haiku JSONL→`[digest]`

+extractor (M10); psyche-sync→subnet/`/spt:setup`; `doctor`→`spt doctor`/setup-verify;

+**ADD** (LOCKED): `/spt:setup`, `/spt:version`, subnet skills (create/join/show-code),

+profiles + strings + hints wiring, ccs profiles.

+**DECIDE** (LOCKED): DROP `/spt:fork` + `amend-signoff`. (fork near-unused & only meaningful

+harness-hosted; amend-signoff deprecated, folds into a follow-up commune)

+**KEEP — under topology review** (operator interrogated each vs harness-hosted/spt-hosted;

+finalizing once spt-core implemented-state investigation lands):

+- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm` — KEEP, uncontested.

+- `/signoff` — KEEP. Writes a file either way; consumption differs. spt-hosted signoff ⇒

+  endpoint shutdown ⇒ user dropped from endpoint PTY back to terminal (confirm UX).

+- `/revive` — **questioned.** Legacy purpose = recover broken states (orphaned psyche,

+  dead listener); spt-core's daemon owns psyche-loop + liveness, so those failure modes

+  largely vanish. doyle lean: DROP or fold into `/live` unless harness-hosted relay-restart

+- `/clear-psyche` — **lean DROP.** Operator never uses it; spt-core equivalent = delete

+- `/force-stop` — KEEP, topology-aware: harness-hosted = stop spt machinery (heir to

+  $OWL/$LIVE stop); spt-hosted = endpoint shutdown / self-stop. (installed skill already

+- `/whoami` — **DROP** (skill). Equivalent baked into `spt endpoint list` (caller's perch

+  shown distinctively at top — VERIFY). CLI `spt whoami` obsolescence → M12 dep #5.

+- `/list-agents` — KEEP (→ `spt endpoint list`).

+**Worried finding (gating):** operator can't find any CLI today to bring up an spt-hosted

+endpoint with harness PTY access / user attach. → investigation in flight; if DESIGN-ONLY,

+it's M12 dep #3 (highest priority) and several KEEP calls + the `cc` launcher block on it.

+Recorded in `../spt-core/M12-CANDIDATES.md` (1: file-backed strings · 2: subnet QR +

+self-elevating window · 3: spt-hosted bringup + PTY attach · 4: fallback targets

+adapter:profile · 5: whoami obsolescence). spt-claude-code blocks on these.

-- [ ] `/spt:setup` v1 scope (1–9 above)

-- [ ] Parity-trim: which legacy concepts/skills DON'T survive → becomes REQ seed / acceptance bar

+- [ ] KEEP-bucket finalize (`/revive`, `/clear-psyche`, `/whoami`, `/force-stop` UX) — pending investigation

+- [ ] spt-hosted bringup + PTY attach: implemented-vs-design (gating) — pending investigation

-- [ ] spt-core "remote attach" local-interactive confirmation

-- [ ] Handoff framing to perri (how the package is presented + public-surface-only constraint)

+- [ ] M12 framing + what `spt rc` denotes

+- [ ] Handoff framing to perri (package presentation + public-surface-only constraint)


Processed + recorded. Ledger (`SCOPE.md`) and `spt-core/M12-CANDIDATES.md` updated. Status by thread:

**Skill instructions** — fetch-stub VETO accepted. Reverted to **UPS-injection** (build-time empirical-verify flagged). Long bodies → **file-backed adapter strings** = M12 dep #1.

**M12** — 5 spt-core deps recorded in `spt-core/M12-CANDIDATES.md`: (1) file-backed strings, (2) subnet QR + self-elevating window, (3) spt-hosted bringup + PTY attach, (4) fallback targets `adapter:profile`, (5) `whoami` obsolescence. Two asks: confirm the **M12 framing**, and **what does `spt rc` denote?** (I left it flagged — don't want to mis-record a core value prop.)

**/spt:setup** — locked v1 = {1,2,3,4,5,6,7}, defer {8,9}. Collapsed `join == add-this-machine` (✓ lol). Subnet-create surfaces QR window. ccs path also offers install. *Flag:* you said "9. agree" then "except 9" — I deferred 9 (doctor/verify); say if verify should fold inline instead.

**Psyche-sync (your #8 question)** — yes, #8 = the optional **git-backup angle** only, deferred. Whether tracked/ context **auto-replicates in-subnet** is part of the investigation (M12/verify) — if it does, #8 shrinks to just off-subnet backup.

**Parity** — DROP / TRANSFORM / ADD / DECIDE all **LOCKED** (incl. drop `/fork` + `amend-signoff`).

**KEEP — your per-skill interrogation** (leans; finalizing when investigation lands, since most hinge on your *worried* finding):
- **/signoff** — KEEP. Your spt-hosted read sounds right: writes a file either way; spt-hosted consumption ⇒ endpoint shutdown ⇒ user dropped from PTY back to terminal.
- **/revive** — lean **DROP/fold-into-/live**. spt-core's daemon owns psyche-loop + liveness → the orphan/dead-listener states it recovered from largely vanish. Keep only if harness-hosted relay-restart needs it.
- **/clear-psyche** — lean **DROP**. Equivalent = delete + recreate endpoint.
- **/force-stop** — KEEP, topology-aware (harness-hosted = stop machinery; spt-hosted = endpoint shutdown). Installed skill's already session-aware.
- **/whoami** — **DROP** skill; `spt endpoint list` shows caller at top (verifying). CLI obsolescence = M12 #5.

**Your *worried* finding** — CONTEXT.md describes spt-hosted topology + spawn-session seam in detail, but that's *design prose*; whether the **user-facing spt-hosted bringup + PTY attach exists in code today** is exactly what the investigation checks. If DESIGN-ONLY, it's the top M12 dep and the `cc` launcher + several KEEP calls block on it. Holding final KEEP-bucket + `cc` confirmation until it lands.


<task-notification>
<task-id>a1a73dc00c464beed</task-id>
<tool-use-id>toolu_01FKbPgg6NW49SrPmkuKZrWH</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\a1a73dc00c464beed.output</output-file>
<status>completed</status>
<summary>Agent "Verify spt-core spt-hosted/PTY/CLI state" completed</summary>
<result>Good! M4-D6c delivered cross-node Psyche sync. Now I have all the information I need to provide a comprehensive answer.

---

## IMPLEMENTED vs DESIGNED: SPT-CORE STATUS REPORT

Based on my systematic investigation of `/c/Users/decid/Documents/projects/spt-core`, here are the findings for each question:

### 1. **spt-hosted endpoint bringup with PTY (daemon spawns harness into broker-held PTY)**

**Status: EXISTS (Partial Implementation)**

- **What exists:** The daemon CAN spawn a binary into a broker-held PTY via `Brain::spawn_session_pid()` — this is implemented and tested (M3b-B1, git commit `181ce91`, available in `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/brain.rs:spawn_session_pid`).
- **The seam is implemented in the daemon:** `crates/spt-daemon/src/shellhost.rs:launch_shell_brokered_in()` spawns shell instances via the broker PTY.
- **What does NOT exist:** There is NO user-facing `spt` CLI command to initiate spt-hosted endpoint bringup for harnesses. The `spt shell spawn` command exists (for shell instances, which use the same PTY mechanism), but there is no `spt endpoint spawn` or similar command to launch a harness into the broker PTY.
- **Who uses it today:** Only the shell subsystem uses this (`spt shell spawn <adapter>`); harnesses are still harness-hosted (launched by the adapter itself, then bound via `spt api listen`).
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/brain.rs:spawn_session_pid()` — implemented
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/shellhost.rs:launch_shell_brokered_in()` — implemented
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:shell spawn` — CLI command exists (lines 540-550)

**Bottom-line: PARTIAL — The daemon-side machinery exists; the user-facing CLI to invoke it for harnesses does not.**

---

### 2. **User terminal attach (LOCAL user attaches to broker-held PTY, interactive)**

**Status: DESIGN-ONLY (Cross-node remote-control attach exists; local attach does not)**

- **What exists:** Remote terminal attach over WAN (M4-D5b, `REQ-INST-8`) — a user on Node B can attach to a session running on Node A via a QUIC stream, see output, and send input. This is implemented at `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/attach.rs`.
- **What does NOT exist:** There is NO CLI command or mechanism for a LOCAL user to attach their terminal to a broker-held PTY session on the same node (e.g., `spt attach <id>`). The attach.rs module is daemon-internal (serving remote requests); there is no user-facing surface to attach a local terminal.
- **Current topology for local shells:** Shell instances are spawned into broker PTYs, but the user doesn't "attach" — they drive them via `spt shell cmd` (capability channel) or `spt shell send` (text/file channel). The PTY itself is not exposed to the user.
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/attach.rs` — remote-control attach (cross-node only)
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/tests/attach.rs` — regression test for remote attach
  - No `spt attach` command in `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs` enum Cmd

**Bottom-line: DESIGN-ONLY — Remote-control attach exists; local user terminal attach to a broker PTY is not implemented.**

---

### 3. **spawn-session seam status (daemon runs command template into broker PTY)**

**Status: EXISTS but LIMITED (Implemented for shells; not exposed as user-facing endpoint spawn)**

- **What exists:** The `spawn-session` seam is implemented in the manifest contract (`spt-runtime`). The daemon can run a command template into a broker-held PTY (`crates/spt-daemon/src/brain.rs:spawn_session()`), fill template keys, and manage the resulting session.
- **Where it's used:** ONLY in the shell subsystem today (`spt shell spawn <adapter>`). The manifest `spawn-session` seam (defined in `crates/spt-runtime/src/runtime.rs:176-180`) is available but not wired for harness-hosted endpoints.
- **Not for harnesses today:** The harness-hosted model is still the default: the harness adapter launches its own binary, writes a seed file, and the endpoint binds via `spt api listen`. The daemon-hosted `spawn-session` path is available but not offered as a user-facing endpoint creation flow.
- **Test coverage:** The spawn_session path is exercised in daemon E2E tests (`tests/budget.rs`), but mostly for shell instances.
- **Milestone delivery:** M3b-B6 planned and delivered this (git: `20817a6`, `16f4c8e`), activated via M3b-B9.
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-runtime/src/runtime.rs:268-290` — `ManifestRuntime::spawn_session()` implementation
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/shellhost.rs:210-239` — shell-specific brokered launch
  - `/c/Users/decid/Documents/projects/spt-core/adapters/mock/manifest.toml` — mock harness uses harness-hosted `[session.self]`, NOT daemon-hosted spawn-session

**Bottom-line: PARTIAL — The seam is implemented and exercised in tests/shells; for harnesses, spawn-session is designed but not wired into the user flow.**

---

### 4. **`spt whoami` vs `spt endpoint list` (both exist? endpoint list marks self?)**

**Status: EXISTS (Both commands exist; `endpoint list` marks self distinctly)**

- **Both commands exist as CLI subcommands:**
  - `spt whoami` (line 108, `Cmd::Whoami`) — prints the calling session's perch id
  - `spt endpoint list [--local|--subnet <name>]` (lines 210-220, `List { local, subnet, detail }`) — lists endpoints
- **Self endpoint marking:** The `cmd_endpoint_list()` function (line 1260) explicitly renders the calling endpoint FIRST with a `SELF:` prefix before any subnet groups (lines 1275-1284: "SELF pin (decision 2)").
- **No recorded plan to obsolete whoami:** Searched CONTEXT.md, ROADMAP.md, M8-PLAN.md, ADRs — no recorded plan to deprecate `whoami` in favor of `endpoint list`. Both are stable in M8 (decision 3: "Agent HOT PATH stays flat: send / ring / ready / whoami / how-to").
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:108` — `Whoami` enum variant
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:2500` — `fn cmd_whoami()`
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:1260` — `fn cmd_endpoint_list()` with SELF pin at lines 1275-1284
  - `/c/Users/decid/Documents/projects/spt-core/M8-PLAN.md` — decision 2-3: both commands stable

**Bottom-line: EXISTS — Both commands exist and coexist; `endpoint list` marks self distinctly at the top with `SELF:` prefix.**

---

### 5. **Psyche context cross-machine sync (automatic vs optional git-backup)**

**Status: EXISTS (Automatic P2P sync; git-backup is optional hub-mode legacy)**

- **Automatic sync is implemented:** M4-D6c (cross-node context bundle sync) delivers automatic Psyche replication over P2P (Iroh QUIC). The daemon's sync pump (`crates/spt-daemon/src/pump/sync.rs`) pulls context automatically on a cadence OR on wake (freshness pull). No user action required.
- **What syncs:** The `tracked/` context (live + project tiers) replicates across subnet nodes by default. Hidden endpoints don't sync; non-hidden endpoints sync to their home subnet and any additional subnets in their sync-membership list.
- **Git-repo backup is RETIRED:** The gh-repo interim (`spt-agent-storage` + `psyche-sync-setup`) is now optional hub-mode only (CONTEXT.md line 377: "The gh-repo interim is retired (M4-D9-6, after the two-host rig proof)... `psyche-sync-setup` remains only as the hub-mode seam (the opt-in transport above), not the default and never a requirement").
- **Trigger mechanisms:**
  - Cadence: `SyncWorker` polls peers on `cadence.sync` interval
  - Wake edge: dormant→active transition forces a freshness pull NOW
  - Manual: Not exposed as a CLI command; sync is daemon-automatic
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/sync.rs:1-50` — M4-D6c implementation
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/tests/sync.rs:1-50` — regression test
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt-daemon/src/pump/sync.rs:65-107` — cadence + wake-edge triggers
  - `/c/Users/decid/Documents/projects/spt-core/CONTEXT.md:371,377` — sync scope + gh-repo retirement

**Bottom-line: EXISTS — Automatic cross-node Psyche sync is implemented; git-backup is optional legacy (not default).**

---

### 6. **Endpoint shutdown/stop commands**

**Status: EXISTS (Both graceful and soft-stop)**

- **Two commands exist:**
  - `spt endpoint shutdown [id]` (lines 265-268) — Graceful: soft-stops listener, suspends, final context save fires, persistent shells offline
  - `spt endpoint stop <id>` (lines 273-276) — Soft-stop: removes ready marker, unregisters perch; spool preserved
- **Topology-aware:** Both commands work on the same endpoint data model; they differ in orderliness (shutdown is graceful, stop is softer). No explicit topology variance in the CLI, but the implementation routes through the transition host for remote endpoints (lines 1342-1360 show `id@node` qualification).
- **Remote endpoints:** Qualified IDs like `id@node` or `subnet:id@node` can target paired peer endpoints (M5-D5b, `REQ-INST-6`).
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:261-276` — both commands
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:2482-2498` — `cmd_stop()` implementation
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:1332-1360` — `cmd_rest()` handles remote via WAN

**Bottom-line: EXISTS — Both graceful (shutdown) and soft (stop) commands exist; topology-aware via qualified addressing.**

---

### 7. **id picker / fork capability**

**Status: PARTIAL (Fork exists; no interactive id-picker)**

- **Fork exists:** `spt endpoint fork <src> <new_id> --subnet <name> [--delete-source]` (lines 221-240) — cross-subnet endpoint copy with a new ID. Same-node only ("one node holds one perch per name").
- **No id-picker for bringup:** The `spt ready <id>` command requires an explicit id positional argument (line 94 in cli.rs). There is no interactive id-picker, no `spt endpoint create`, and no auto-id-generation at bringup. The id must be provided.
- **Design vs code:** CONTEXT.md mentions (in the deferred "no-id spawn-session picker" section) a future unified selection flow that would chain "no-id picker → adapter selector → home subnet prompts", but this is explicitly deferred and not implemented today.
- **File evidence:**
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:221-240` — `Fork` command
  - `/c/Users/decid/Documents/projects/spt-core/crates/spt/src/cli.rs:93-104` — `Ready` requires positional id (no picker)
  - `/c/Users/decid/Documents/projects/spt-core/CONTEXT.md:~484` — deferred "no-id `/spt:live` resolution" and unified selection pipeline

**Bottom-line: PARTIAL — Fork exists; interactive id-picker at bringup does not exist (deferred to future UX flow).**

---

## SUMMARY TABLE

| Question | Status | Key File | CLI Command Exists? |
|----------|--------|----------|---------------------|
| spt-hosted endpoint PTY bringup | **PARTIAL** | `shellhost.rs:210` | No (shells only, no harness endpoint spawn) |
| Local user PTY attach | **DESIGN-ONLY** | `attach.rs` (remote only) | No |
| spawn-session seam | **PARTIAL** | `runtime.rs:268`, `shellhost.rs:210` | No direct user command |
| whoami + endpoint list self-marking | **EXISTS** | `cli.rs:1260,2500` | Yes, both; self marked |
| Psyche cross-machine sync | **EXISTS** | `sync.rs:1`, `pump/sync.rs:65` | Automatic (no CLI) |
| endpoint shutdown/stop | **EXISTS** | `cli.rs:261,273` | Yes, both |
| fork + id-picker | **PARTIAL** | `cli.rs:221`, `cli.rs:93` | Fork yes; picker no |</result>
<usage><subagent_tokens>79193</subagent_tokens><tool_uses>65</tool_uses><duration_ms>221205</duration_ms></usage>
</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.


Investigation landed — your *worried* finding is **confirmed real**, plus three pleasant surprises. Updating records, then the scoping consequence.

Key findings:
- **spt-hosted HARNESS bringup = PARTIAL.** Daemon machinery exists (`spawn_session_pid`, `launch_shell_brokered_in`) but **only shells use it** (`spt shell spawn`). No user CLI to launch a *harness* into a broker PTY. Harnesses still harness-hosted (bind via `spt api listen`).
- **Local user PTY attach = DESIGN-ONLY.** Cross-node remote attach exists (`attach.rs`); no local `spt attach <id>`.
- **Surprise 1 — psyche cross-machine sync = AUTOMATIC** (M4-D6c, P2P). tracked/ replicates in-subnet by default; git-backup retired to optional hub-mode. → your #8 answer.
- **Surprise 2 — `spt endpoint fork` EXISTS** (cross-subnet copy). Your instinct was right.
- **Surprise 3 — whoami: NO obsolescence plan.** Both `whoami` + `endpoint list` (self pinned `SELF:` at top) are intentionally stable; whoami is in the agent hot-path. My M12 #5 was wrong.
- `endpoint shutdown` (graceful) + `endpoint stop` (soft) both exist, topology-aware.

Correcting the records:


3. **spt-hosted endpoint bringup + user PTY attach (CLI).** A user-facing path to
   initialize an spt-hosted endpoint (daemon spawns the harness binary into a broker PTY)
   AND attach a local terminal to it (interactive watch+type). This is the foundation of
   spt-claude-code's `cc`/`cc <id>` launcher and the spt-hosted half of /signoff,
   /force-stop, /fork. **VERIFY implemented-vs-designed** (investigation in flight
   2026-06-14) — if DESIGN-ONLY today, this is the highest-priority M12 dependency.

4. **Cross-adapter fallback targets `<adapter>:<profile>`.** The node-wide cross-adapter
   fallback must be able to target a composite adapter:profile, not only a bare
   adapter_name — so a ccs profile (`claude-spt:glm`) is a valid fallback target.
   Reconcile CONTEXT.md fallback wording (currently "ccs, its own adapter").

5. **`spt whoami` obsolescence.** Plan recorded intent (operator recollection) to retire
   `spt whoami` in favor of `spt endpoint list` showing the calling endpoint's own perch
   distinctively (at top / marked self). VERIFY current state; if endpoint-list already
   does this, deprecate whoami. (spt-claude-code drops the `/spt:whoami` skill regardless.)

## Notes
- M10 `[digest]` extractor seam already shipped (the CC-JSONL extractor consumer is
  spt-claude-code) — not an M12 item, listed for traceability.
- Cross-reference: `../spt-claude-code/SCOPE.md` (downstream consumer ledger).

3. **spt-hosted HARNESS bringup + local user PTY attach (CLI). — CONFIRMED MISSING, TOP PRIORITY.**
   Investigation 2026-06-14 (file evidence):
   - Daemon-side PTY spawn EXISTS but shells-only: `crates/spt-daemon/src/brain.rs:spawn_session_pid()`,
     `crates/spt-daemon/src/shellhost.rs:launch_shell_brokered_in()`; CLI only `spt shell spawn`.
   - NO user CLI to launch a HARNESS endpoint into a broker PTY (harnesses still
     harness-hosted: adapter launches binary → binds via `spt api listen`).
   - Local user terminal attach = DESIGN-ONLY: cross-node remote attach exists
     (`crates/spt-daemon/src/attach.rs`, M4-D5b), but no local `spt attach <id>`.
   Needed work: (a) `spt endpoint spawn`-style CLI wiring the existing spawn-session seam
   for harnesses; (b) a local `spt attach <id>` to a broker PTY. Foundation of
   spt-claude-code's `cc`/`cc <id>` launcher + the spt-hosted half of /signoff & /force-stop.
   **spt-claude-code v1 (harness-hosted parity) does NOT block on this; the `cc` launcher
   does → fast-follow unless operator pulls it into v1.**

4. **Cross-adapter fallback targets `<adapter>:<profile>`.** Node-wide cross-adapter
   fallback must target a composite adapter:profile, not only a bare adapter_name — so a
   ccs profile (`claude-spt:glm`) is a valid fallback target. Reconcile CONTEXT.md wording
   (currently "ccs, its own adapter"). (Not directly verified in investigation — confirm.)

## Already EXISTS — no M12 work (investigation 2026-06-14, good news)
- **Psyche cross-machine sync = automatic** (M4-D6c, P2P over Iroh; `crates/spt-daemon/src/sync.rs`,
  `pump/sync.rs`). tracked/ replicates in-subnet by default; gh-repo `psyche-sync-setup`
  RETIRED to optional hub-mode. → spt-claude-code `/spt:setup` #8 reduces to a rare opt-in.
- **`spt endpoint fork <src> <new_id>` exists** (cross-subnet copy, same-node). Forking IS a
  first-class CLI offering. (`cli.rs:221`)
- **`spt endpoint shutdown` (graceful) + `spt endpoint stop` (soft)** exist, topology-aware
  via qualified addressing. (`cli.rs:261,273`)
- **`spt whoami` + `spt endpoint list` (self pinned `SELF:` at top)** both exist; NO
  obsolescence plan — both intentionally stable, whoami in agent hot-path. **(Dropped former
  M12 #5 — was based on a mistaken recollection.)**

## Notes
- M10 `[digest]` extractor seam already shipped (CC-JSONL consumer = spt-claude-code) —
  listed for traceability, not an M12 item.
- Cross-reference: `../spt-claude-code/SCOPE.md` (downstream consumer ledger).


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

3. **spt-hosted HARNESS bringup + local user PTY attach (CLI). — CONFIRMED MISSING, TOP PRIORITY.**
   Investigation 2026-06-14 (file evidence):
   - Daemon-side PTY spawn EXISTS but shells-only: `crates/spt-daemon/src/brain.rs:spawn_session_pid()`,
     `crates/spt-daemon/src/shellhost.rs:launch_shell_brokered_in()`; CLI only `spt shell spawn`.
   - NO user CLI to launch a HARNESS endpoint into a broker PTY (harnesses still
     harness-hosted: adapter launches binary → binds via `spt api listen`).
   - Local user terminal attach = DESIGN-ONLY: cross-node remote attach exists
     (`crates/spt-daemon/src/attach.rs`, M4-D5b), but no local `spt attach <id>`.
   Needed work: (a) `spt endpoint spawn`-style CLI wiring the existing spawn-session seam
   for harnesses; (b) a local `spt attach <id>` to a broker PTY. Foundation of
   spt-claude-code's `cc`/`cc <id>` launcher + the spt-hosted half of /signoff & /force-stop.
   **spt-claude-code v1 (harness-hosted parity) does NOT block on this; the `cc` launcher
   does → fast-follow unless operator pulls it into v1.**

4. **Cross-adapter fallback targets `<adapter>:<profile>`.** Node-wide cross-adapter
   fallback must target a composite adapter:profile, not only a bare adapter_name — so a
   ccs profile (`claude-spt:glm`) is a valid fallback target. Reconcile CONTEXT.md wording
   (currently "ccs, its own adapter"). (Not directly verified in investigation — confirm.)

## Already EXISTS — no M12 work (investigation 2026-06-14, good news)
- **Psyche cross-machine sync = automatic** (M4-D6c, P2P over Iroh; `crates/spt-daemon/src/sync.rs`,
  `pump/sync.rs`). tracked/ replicates in-subnet by default; gh-repo `psyche-sync-setup`
  RETIRED to optional hub-mode. → spt-claude-code `/spt:setup` #8 reduces to a rare opt-in.
- **`spt endpoint fork <src> <new_id>` exists** (cross-subnet copy, same-node). Forking IS a
  first-class CLI offering. (`cli.rs:221`)
- **`spt endpoint shutdown` (graceful) + `spt endpoint stop` (soft)** exist, topology-aware
  via qualified addressing. (`cli.rs:261,273`)
- **`spt whoami` + `spt endpoint list` (self pinned `SELF:` at top)** both exist; NO
  obsolescence plan — both intentionally stable, whoami in agent hot-path. **(Dropped former
  M12 #5 — was based on a mistaken recollection.)**

## Notes
- M10 `[digest]` extractor seam already shipped (CC-JSONL consumer = spt-claude-code) —
  listed for traceability, not an M12 item.
- Cross-reference: `../spt-claude-code/SCOPE.md` (downstream consumer ledger).

# M12 candidate intake — spt-core features that unblock downstream adapters

> Status: **CANDIDATES** (not activated REQs — follow activate-don't-pre-fail).
> Surfaced 2026-06-14 during the `spt-claude-code` scoping grill (doyle).
> spt-claude-code (the v1 acceptance adapter + first casual entrypoint) DEPENDS on
> these — arrange construction promptly. Operator framed these as M12, noting
> **`spt rc`** is a core value prop (confirm what `spt rc` denotes when formalizing).
> Each needs a `REQ-*` in `traceable-reqs.toml` when M12 activates.

## Confirmed-needed by spt-claude-code

1. **Adapter strings → file-backed values.** `[strings]` entries may point to a FILE
   instead of an inline string, so a fetch can return long bodies (e.g. full skill
   instructions for UPS-injection) without bloating the adapter manifest. Requires a
   standardized per-adapter auxiliary file-storage location (verify one doesn't already
   exist). Resolution still rides the leaf-replace profile overlay. Consumer:
   spt-claude-code skill-instruction delivery + hints.

2. **Subnet create/join QR + self-elevating window.** `spt subnet create/join/show-totp`:
   - Surfaces a **QR code** of the TOTP seed for the user to store → must spawn a
     window to display it (create AND join).
   - Behavior change (per operator sketch): runs normally if env is interactive +
     elevated; ELSE re-runs self in a self-elevating window with inline stdout
     ("Elevated terminal launched. Accept the prompt and proceed there." → "You can
     close this window.", no auto-close).
   - Cross-platform elevation fallbacks: Windows = UAC self-elevate window;
     Linux+desktop = pkexec/polkit or x-terminal-emulator; Linux+TTY = inline sudo;
     headless/no-TTY = print exact command for the human (agent relays).
   - Scope elevation to only steps that need it (service-install / firewall /
     privileged-port) — subnet-create itself likely unprivileged.
   - Complementary downstream: spt-claude-code skill with create/join/show-code verbs.

3. **spt-hosted endpoint bringup + user PTY attach (CLI).** A user-facing path to
   initialize an spt-hosted endpoint (daemon spawns the harness binary into a broker PTY)
   AND attach a local terminal to it (interactive watch+type). This is the foundation of
   spt-claude-code's `cc`/`cc <id>` launcher and the spt-hosted half of /signoff,
   /force-stop, /fork. **VERIFY implemented-vs-designed** (investigation in flight
   2026-06-14) — if DESIGN-ONLY today, this is the highest-priority M12 dependency.

4. **Cross-adapter fallback targets `<adapter>:<profile>`.** The node-wide cross-adapter
   fallback must be able to target a composite adapter:profile, not only a bare
   adapter_name — so a ccs profile (`claude-spt:glm`) is a valid fallback target.
   Reconcile CONTEXT.md fallback wording (currently "ccs, its own adapter").

5. **`spt whoami` obsolescence.** Plan recorded intent (operator recollection) to retire
   `spt whoami` in favor of `spt endpoint list` showing the calling endpoint's own perch
   distinctively (at top / marked self). VERIFY current state; if endpoint-list already
   does this, deprecate whoami. (spt-claude-code drops the `/spt:whoami` skill regardless.)

## Notes
- M10 `[digest]` extractor seam already shipped (the CC-JSONL extractor consumer is
  spt-claude-code) — not an M12 item, listed for traceability.
- Cross-reference: `../spt-claude-code/SCOPE.md` (downstream consumer ledger).

-3. **spt-hosted endpoint bringup + user PTY attach (CLI).** A user-facing path to

-   initialize an spt-hosted endpoint (daemon spawns the harness binary into a broker PTY)

-   AND attach a local terminal to it (interactive watch+type). This is the foundation of

-   spt-claude-code's `cc`/`cc <id>` launcher and the spt-hosted half of /signoff,

-   /force-stop, /fork. **VERIFY implemented-vs-designed** (investigation in flight

-   2026-06-14) — if DESIGN-ONLY today, this is the highest-priority M12 dependency.

+3. **spt-hosted HARNESS bringup + local user PTY attach (CLI). — CONFIRMED MISSING, TOP PRIORITY.**

+   Investigation 2026-06-14 (file evidence):

+   - Daemon-side PTY spawn EXISTS but shells-only: `crates/spt-daemon/src/brain.rs:spawn_session_pid()`,

+     `crates/spt-daemon/src/shellhost.rs:launch_shell_brokered_in()`; CLI only `spt shell spawn`.

+   - NO user CLI to launch a HARNESS endpoint into a broker PTY (harnesses still

+     harness-hosted: adapter launches binary → binds via `spt api listen`).

+   - Local user terminal attach = DESIGN-ONLY: cross-node remote attach exists

+     (`crates/spt-daemon/src/attach.rs`, M4-D5b), but no local `spt attach <id>`.

+   Needed work: (a) `spt endpoint spawn`-style CLI wiring the existing spawn-session seam

+   for harnesses; (b) a local `spt attach <id>` to a broker PTY. Foundation of

+   spt-claude-code's `cc`/`cc <id>` launcher + the spt-hosted half of /signoff & /force-stop.

+   **spt-claude-code v1 (harness-hosted parity) does NOT block on this; the `cc` launcher

+   does → fast-follow unless operator pulls it into v1.**

-4. **Cross-adapter fallback targets `<adapter>:<profile>`.** The node-wide cross-adapter

-   fallback must be able to target a composite adapter:profile, not only a bare

-   adapter_name — so a ccs profile (`claude-spt:glm`) is a valid fallback target.

-   Reconcile CONTEXT.md fallback wording (currently "ccs, its own adapter").

+4. **Cross-adapter fallback targets `<adapter>:<profile>`.** Node-wide cross-adapter

+   fallback must target a composite adapter:profile, not only a bare adapter_name — so a

+   ccs profile (`claude-spt:glm`) is a valid fallback target. Reconcile CONTEXT.md wording

+   (currently "ccs, its own adapter"). (Not directly verified in investigation — confirm.)

-5. **`spt whoami` obsolescence.** Plan recorded intent (operator recollection) to retire

-   `spt whoami` in favor of `spt endpoint list` showing the calling endpoint's own perch

-   distinctively (at top / marked self). VERIFY current state; if endpoint-list already

-   does this, deprecate whoami. (spt-claude-code drops the `/spt:whoami` skill regardless.)

+## Already EXISTS — no M12 work (investigation 2026-06-14, good news)

+- **Psyche cross-machine sync = automatic** (M4-D6c, P2P over Iroh; `crates/spt-daemon/src/sync.rs`,

+  `pump/sync.rs`). tracked/ replicates in-subnet by default; gh-repo `psyche-sync-setup`

+  RETIRED to optional hub-mode. → spt-claude-code `/spt:setup` #8 reduces to a rare opt-in.

+- **`spt endpoint fork <src> <new_id>` exists** (cross-subnet copy, same-node). Forking IS a

+  first-class CLI offering. (`cli.rs:221`)

+- **`spt endpoint shutdown` (graceful) + `spt endpoint stop` (soft)** exist, topology-aware

+  via qualified addressing. (`cli.rs:261,273`)

+- **`spt whoami` + `spt endpoint list` (self pinned `SELF:` at top)** both exist; NO

+  obsolescence plan — both intentionally stable, whoami in agent hot-path. **(Dropped former

+  M12 #5 — was based on a mistaken recollection.)**

-- M10 `[digest]` extractor seam already shipped (the CC-JSONL extractor consumer is

-  spt-claude-code) — not an M12 item, listed for traceability.

+- M10 `[digest]` extractor seam already shipped (CC-JSONL consumer = spt-claude-code) —

+  listed for traceability, not an M12 item.


**KEEP — under topology review** (operator interrogated each vs harness-hosted/spt-hosted;
finalizing once spt-core implemented-state investigation lands):
- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm` — KEEP, uncontested.
- `/signoff` — KEEP. Writes a file either way; consumption differs. spt-hosted signoff ⇒
  endpoint shutdown ⇒ user dropped from endpoint PTY back to terminal (confirm UX).
- `/revive` — **questioned.** Legacy purpose = recover broken states (orphaned psyche,
  dead listener); spt-core's daemon owns psyche-loop + liveness, so those failure modes
  largely vanish. doyle lean: DROP or fold into `/live` unless harness-hosted relay-restart
  needs it. Pending investigation.
- `/clear-psyche` — **lean DROP.** Operator never uses it; spt-core equivalent = delete
  endpoint + recreate. Pending.
- `/force-stop` — KEEP, topology-aware: harness-hosted = stop spt machinery (heir to
  $OWL/$LIVE stop); spt-hosted = endpoint shutdown / self-stop. (installed skill already
  session-aware.)
- `/whoami` — **DROP** (skill). Equivalent baked into `spt endpoint list` (caller's perch
  shown distinctively at top — VERIFY). CLI `spt whoami` obsolescence → M12 dep #5.
- `/list-agents` — KEEP (→ `spt endpoint list`).

**Worried finding (gating):** operator can't find any CLI today to bring up an spt-hosted
endpoint with harness PTY access / user attach. → investigation in flight; if DESIGN-ONLY,
it's M12 dep #3 (highest priority) and several KEEP calls + the `cc` launcher block on it.

**KEEP — FINALIZED** (post-investigation 2026-06-14):
- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm`, `/list-agents` — KEEP. (`/list-agents`
  → `spt endpoint list`.)
- `/signoff` — KEEP. v1 = harness-hosted semantics (writes file; consumed at teardown). The
  spt-hosted "drop user from PTY" UX only applies once `cc`/local-attach lands (fast-follow).
- `/force-stop` — KEEP, topology-aware. spt-hosted routing already has CLI: `spt endpoint
  shutdown` (graceful) + `spt endpoint stop` (soft), both exist.
- `/revive` — **DROP.** Daemon owns psyche-loop + liveness (no orphan/dead-listener states to
  recover); restart = re-`ready`/re-`listen` or `endpoint stop`+bringup. Confirm.
- `/clear-psyche` — **DROP.** Equivalent = delete + recreate endpoint. Confirm.
- `/whoami` — **DROP skill** (bare `spt whoami` / `spt endpoint list` suffice). NOTE: core
  `spt whoami` STAYS (no obsolescence plan — both stable, whoami in agent hot-path). M12 #5
  retracted.

### v1 topology scope — **DECISION NEEDED**
Investigation: spt-hosted HARNESS bringup + local PTY attach DON'T exist (M12 dep #3).
→ **doyle rec: v1 = harness-hosted-only = full legacy parity (legacy never shipped capsule
either), buildable on today's spt-core.** The spt-hosted `cc` launcher (capsule realized) =
**fast-follow**, gated on M12 #3. `/spt:setup` item #1 (`cc` launcher) moves to fast-follow
accordingly; v1 setup = install/subnet/migration. Operator may instead **pull M12 #3 forward**
to land `cc` in v1 — sequencing is operator's call.


**KEEP — under topology review** (operator interrogated each vs harness-hosted/spt-hosted;
finalizing once spt-core implemented-state investigation lands):
- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm` — KEEP, uncontested.
- `/signoff` — KEEP. Writes a file either way; consumption differs. spt-hosted signoff ⇒
  endpoint shutdown ⇒ user dropped from endpoint PTY back to terminal (confirm UX).
- `/revive` — **questioned.** Legacy purpose = recover broken states (orphaned psyche,
  dead listener); spt-core's daemon owns psyche-loop + liveness, so those failure modes
  largely vanish. doyle lean: DROP or fold into `/live` unless harness-hosted relay-restart
  needs it. Pending investigation.
- `/clear-psyche` — **lean DROP.** Operator never uses it; spt-core equivalent = delete
  endpoint + recreate. Pending.
- `/force-stop` — KEEP, topology-aware: harness-hosted = stop spt machinery (heir to
  $OWL/$LIVE stop); spt-hosted = endpoint shutdown / self-stop. (installed skill already
  session-aware.)
- `/whoami` — **DROP** (skill). Equivalent baked into `spt endpoint list` (caller's perch
  shown distinctively at top — VERIFY). CLI `spt whoami` obsolescence → M12 dep #5.
- `/list-agents` — KEEP (→ `spt endpoint list`).

**Worried finding (gating):** operator can't find any CLI today to bring up an spt-hosted
endpoint with harness PTY access / user attach. → investigation in flight; if DESIGN-ONLY,
it's M12 dep #3 (highest priority) and several KEEP calls + the `cc` launcher block on it.

**KEEP — FINALIZED** (post-investigation 2026-06-14):
- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm`, `/list-agents` — KEEP. (`/list-agents`
  → `spt endpoint list`.)
- `/signoff` — KEEP. v1 = harness-hosted semantics (writes file; consumed at teardown). The
  spt-hosted "drop user from PTY" UX only applies once `cc`/local-attach lands (fast-follow).
- `/force-stop` — KEEP, topology-aware. spt-hosted routing already has CLI: `spt endpoint
  shutdown` (graceful) + `spt endpoint stop` (soft), both exist.
- `/revive` — **DROP.** Daemon owns psyche-loop + liveness (no orphan/dead-listener states to
  recover); restart = re-`ready`/re-`listen` or `endpoint stop`+bringup. Confirm.
- `/clear-psyche` — **DROP.** Equivalent = delete + recreate endpoint. Confirm.
- `/whoami` — **DROP skill** (bare `spt whoami` / `spt endpoint list` suffice). NOTE: core
  `spt whoami` STAYS (no obsolescence plan — both stable, whoami in agent hot-path). M12 #5
  retracted.

### v1 topology scope — **DECISION NEEDED**
Investigation: spt-hosted HARNESS bringup + local PTY attach DON'T exist (M12 dep #3).
→ **doyle rec: v1 = harness-hosted-only = full legacy parity (legacy never shipped capsule
either), buildable on today's spt-core.** The spt-hosted `cc` launcher (capsule realized) =
**fast-follow**, gated on M12 #3. `/spt:setup` item #1 (`cc` launcher) moves to fast-follow
accordingly; v1 setup = install/subnet/migration. Operator may instead **pull M12 #3 forward**
to land `cc` in v1 — sequencing is operator's call.

**DECIDE** (LOCKED): DROP `/spt:fork` + `amend-signoff`. (fork near-unused & only meaningful

harness-hosted; amend-signoff deprecated, folds into a follow-up commune)

-**KEEP — under topology review** (operator interrogated each vs harness-hosted/spt-hosted;

-finalizing once spt-core implemented-state investigation lands):

-- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm` — KEEP, uncontested.

-- `/signoff` — KEEP. Writes a file either way; consumption differs. spt-hosted signoff ⇒

-  endpoint shutdown ⇒ user dropped from endpoint PTY back to terminal (confirm UX).

-- `/revive` — **questioned.** Legacy purpose = recover broken states (orphaned psyche,

-  dead listener); spt-core's daemon owns psyche-loop + liveness, so those failure modes

-  largely vanish. doyle lean: DROP or fold into `/live` unless harness-hosted relay-restart

-- `/clear-psyche` — **lean DROP.** Operator never uses it; spt-core equivalent = delete

-- `/force-stop` — KEEP, topology-aware: harness-hosted = stop spt machinery (heir to

-  $OWL/$LIVE stop); spt-hosted = endpoint shutdown / self-stop. (installed skill already

-- `/whoami` — **DROP** (skill). Equivalent baked into `spt endpoint list` (caller's perch

-  shown distinctively at top — VERIFY). CLI `spt whoami` obsolescence → M12 dep #5.

-- `/list-agents` — KEEP (→ `spt endpoint list`).

+**KEEP — FINALIZED** (post-investigation 2026-06-14):

+- `/live`, `/commune`, `/ready`, `/send`, `/new-alarm`, `/list-agents` — KEEP. (`/list-agents`

+- `/signoff` — KEEP. v1 = harness-hosted semantics (writes file; consumed at teardown). The

+  spt-hosted "drop user from PTY" UX only applies once `cc`/local-attach lands (fast-follow).

+- `/force-stop` — KEEP, topology-aware. spt-hosted routing already has CLI: `spt endpoint

+  shutdown` (graceful) + `spt endpoint stop` (soft), both exist.

+- `/revive` — **DROP.** Daemon owns psyche-loop + liveness (no orphan/dead-listener states to

+  recover); restart = re-`ready`/re-`listen` or `endpoint stop`+bringup. Confirm.

+- `/clear-psyche` — **DROP.** Equivalent = delete + recreate endpoint. Confirm.

+- `/whoami` — **DROP skill** (bare `spt whoami` / `spt endpoint list` suffice). NOTE: core

+  `spt whoami` STAYS (no obsolescence plan — both stable, whoami in agent hot-path). M12 #5

-**Worried finding (gating):** operator can't find any CLI today to bring up an spt-hosted

-endpoint with harness PTY access / user attach. → investigation in flight; if DESIGN-ONLY,

-it's M12 dep #3 (highest priority) and several KEEP calls + the `cc` launcher block on it.

+### v1 topology scope — **DECISION NEEDED**

+Investigation: spt-hosted HARNESS bringup + local PTY attach DON'T exist (M12 dep #3).

+→ **doyle rec: v1 = harness-hosted-only = full legacy parity (legacy never shipped capsule

+either), buildable on today's spt-core.** The spt-hosted `cc` launcher (capsule realized) =

+**fast-follow**, gated on M12 #3. `/spt:setup` item #1 (`cc` launcher) moves to fast-follow

+accordingly; v1 setup = install/subnet/migration. Operator may instead **pull M12 #3 forward**

+to land `cc` in v1 — sequencing is operator's call.

Recorded in `../spt-core/M12-CANDIDATES.md` (1: file-backed strings · 2: subnet QR +


8. Psyche cross-machine sync — *only the optional git-backup angle*; in-subnet sync may be
   automatic (verify)
9. Doctor/verify at end

**LOCKED:** v1 = {1,2,3,4,5,6,7} (all primary spt-core features + ccs needed now). Defer
{8,9}. _Operator said "9. agree" then "except 9" — treating 9 as deferred per final scope;
flag if verify should fold inline._

8. Psyche cross-machine sync — **in-subnet sync is AUTOMATIC** (confirmed, M4-D6c); only the
   optional off-subnet/hub-mode backup remains, retired-as-default → near-zero v1 surface
9. Doctor/verify at end

**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. **BUT item #1 (`cc` launcher) is blocked on
M12 #3** (spt-hosted bringup + local attach don't exist) → #1 moves to fast-follow unless
operator pulls M12 #3 forward. So buildable-today v1 setup = {2,3,4,5,6,7}. _Operator "9.
agree" then "except 9" — deferred 9; flag if verify should fold inline._


8. Psyche cross-machine sync — *only the optional git-backup angle*; in-subnet sync may be
   automatic (verify)
9. Doctor/verify at end

**LOCKED:** v1 = {1,2,3,4,5,6,7} (all primary spt-core features + ccs needed now). Defer
{8,9}. _Operator said "9. agree" then "except 9" — treating 9 as deferred per final scope;
flag if verify should fold inline._

8. Psyche cross-machine sync — **in-subnet sync is AUTOMATIC** (confirmed, M4-D6c); only the
   optional off-subnet/hub-mode backup remains, retired-as-default → near-zero v1 surface
9. Doctor/verify at end

**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. **BUT item #1 (`cc` launcher) is blocked on
M12 #3** (spt-hosted bringup + local attach don't exist) → #1 moves to fast-follow unless
operator pulls M12 #3 forward. So buildable-today v1 setup = {2,3,4,5,6,7}. _Operator "9.
agree" then "except 9" — deferred 9; flag if verify should fold inline._

6. OS-service registration (always-on daemon)

7. ccs profile wiring — if `~/.ccs` present; **also offer to install ccs** (+1-sentence value

-8. Psyche cross-machine sync — *only the optional git-backup angle*; in-subnet sync may be

+8. Psyche cross-machine sync — **in-subnet sync is AUTOMATIC** (confirmed, M4-D6c); only the

+   optional off-subnet/hub-mode backup remains, retired-as-default → near-zero v1 surface

-**LOCKED:** v1 = {1,2,3,4,5,6,7} (all primary spt-core features + ccs needed now). Defer

-{8,9}. _Operator said "9. agree" then "except 9" — treating 9 as deferred per final scope;

+**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. **BUT item #1 (`cc` launcher) is blocked on

+M12 #3** (spt-hosted bringup + local attach don't exist) → #1 moves to fast-follow unless

+operator pulls M12 #3 forward. So buildable-today v1 setup = {2,3,4,5,6,7}. _Operator "9.

+agree" then "except 9" — deferred 9; flag if verify should fold inline._

### `cc` launcher (capsule-style) — **LOCKED (design)**


Records corrected (`M12-CANDIDATES.md` + `SCOPE.md`). The consequence is a real scoping decision:

**KEEP bucket — finalized:**
- KEEP: `/live` `/commune` `/ready` `/send` `/new-alarm` `/list-agents` `/signoff` `/force-stop`
- **DROP: `/revive`** (daemon owns psyche-loop + liveness → no orphan/dead-listener to recover; restart = re-`ready`/`listen` or `endpoint stop`+bringup)
- **DROP: `/clear-psyche`** (= delete + recreate endpoint)
- **DROP `/whoami` skill** — but **core `spt whoami` STAYS** (no obsolescence plan; both stable, hot-path). M12 #5 retracted.
- `/force-stop` spt-hosted routing already has CLI backing: `spt endpoint shutdown`/`stop` exist.

Confirm the two new drops (`/revive`, `/clear-psyche`)?

---

**Q7 — v1 topology scope (consequential).**

The `cc` launcher (capsule realized) needs spt-hosted **harness** bringup + **local PTY attach** — both confirmed MISSING (M12 #3). Daemon machinery exists but is shells-only; no harness-spawn CLI, no local `spt attach`.

My rec: **v1 = harness-hosted-only = full legacy parity, buildable on today's spt-core.** Legacy never shipped capsule either, so parity holds without it. The spt-hosted `cc` launcher = **fast-follow**, gated on M12 #3. `/spt:setup` #1 moves to fast-follow; buildable-today v1 setup = {2,3,4,5,6,7}.

Alternative: **pull M12 #3 forward** so `cc` + spt-hosted mode ship *in* v1 — makes spt-claude-code a stronger acceptance proof (exercises terminal-hosting too), but blocks v1 on new spt-core work.

Which sequencing — **harness-hosted v1 + `cc` fast-follow**, or **pull M12 #3 forward for cc-in-v1**?

(Good news folded: psyche sync auto-works in-subnet → setup #8 ≈ nil; `spt endpoint fork` already exists; shutdown/stop exist.)


-M12 framing confirmed. -`spt rc` is the command for connecting to an spt-hosted PTY. works cross-node. already slated for M12. -whoami being in the hot path is fine. but it should be changed to just be an alias for `spt endpoint list` + the whoami-equivalent output in that command should include the `spt endpoint description` for Self's endpoint. -two new drops confirmed. --- Q7: veto your rec, and here's why: while legacy spt parity was stated to be the v1 acceptance, it has always had this caveat in my mind (and possibly not vocalized until now): because spt-core's central value prop is the networking + PTY ownership, the true v1 req is legacy parity AND proof of the cross-subnet features. so local PTY attach + the i.e. `spt endpoint run` picker flow are very much mandatory for v1 acceptance. so we need to roll the full-fat M12 with todlando after this grill, and before perri begins work on `spt-claude-code`. --- `spt endpoint run` looks something like: -layer 1 "What kind of endpoint? [Create new|Pick existing]" -layer 2@create-new: "Choose your harness adapter for this endpoint: <list available adapters, their profiles tree-nested>" -layer 3@create-new: "Enter an endpoint id. Alphanumeric + hyphen + underscore only."-->start endpoint -layer 2@pick-existing: "Available endpoints:" left/right picks categor-->one of [<dir-name> project|Local node|Subnet]. up/down selects endpoint. `project` endpoints grouped by local/subnet N/subnet M/etc. `local` endpoints grouped by project names. `subnet` endpoints grouped by subnet:node. endpoints sorted alphabetically within their groupings. have colored squares behind them to indicate online [green]/offline [gray hollow]/already attached [blue]. visually, there is a right-half description section, wherein the highlighted endpoint's 1. harness adapter:profile, 2. project history list (newest->oldset), and 3. `spt endpoint description` are featured. -layer 3@pick-existing: "Confirm selection" <endpoint id>\n<endpoint status online|offline|attached> • <subnet>:<node>(if not local, else "LOCAL")\n<endpoint harness adapter:profile>\n"Project history: "<comma-separated projects list>\n<endpoint description>. options "[Attach now|Start now|View now]" per status-->start endpoint, "Instantiate locally" if remote-->layer 2@create-new-->start endpoint, "Change harness adapter" if offline-->layer 2@create-new-->start endpoint, "Fork endpoint"-->layer 2@create-new-->layer 3@create-new-->start endpoint. --- i think that covers the full picker flow. open to suggestions. the visual inspiration for the picker is matt pocock's skill installer. we should inspect its source code to achieve a similar feel: https://github.com/mattpocock/skills


Big shifts. `spt rc` clarified (cross-node spt-hosted PTY connect, already M12-slated). Q7 vetoed — v1 acceptance = legacy parity **AND** cross-subnet/PTY proof, so `spt endpoint run` picker + local attach are **mandatory v1**, and **full-fat M12 is a gating prerequisite** (todlando builds it after this grill, before perri starts). Recording the picker spec + inspecting your visual reference, then updating records.


Agent

Inspect mattpocock/skills picker TUI

Prompt:
Clone and analyze the GitHub repo `mattpocock/skills` (https://github.com/mattpocock/skills) to extract how its interactive TUI installer/picker is implemented. We're building a similar-feeling terminal picker (`spt endpoint run`) and want to copy the look/feel.

Steps:
1. `git clone --depth 1 https://github.com/mattpocock/skills` into a temp dir (e.g. C:\Users\decid\AppData\Local\Temp\mp-skills) and inspect. If clone fails, fall back to WebFetch of the repo's key source files via raw.githubusercontent.com.
2. Find the interactive picker/installer code.

Report:
1. **Language + TUI library/framework** — what powers the interactive picker (Ink/React, clack/@clack/prompts, prompts, inquirer, blessed, ratatui, bubbletea, custom ANSI, etc.)? Exact package(s) + version.
2. **Picker UX mechanics** — how does it render: list navigation (up/down), category switching (left/right or tabs), multi-pane layout (is there a side description pane?), selection indicators (colored squares/dots, checkmarks), search/filter. Cite the components/functions.
3. **Color + status rendering** — how online/offline/selected-style states are shown (color codes, symbols).
4. **Key code excerpts** — the core render loop / component composition (short excerpts + file paths), enough to replicate the feel.
5. **Reusability** — is the picker logic in a reusable lib or bespoke? Could the pattern be ported to a Rust TUI (we'd likely implement in Rust — ratatui), and what would the closest Rust equivalent libs/patterns be?

Conclusions + paths over full dumps. We want the architecture + feel, not a line-by-line copy.


<owl_reachability_notice>
You have an active owl perch. Launch this Agent with run_in_background: true so you stay reachable for incoming messages while it works.
</owl_reachability_notice>


Async agent launched successfully.
agentId: a9c8577393eb9aaee (internal ID - do not mention to user. Use SendMessage with to: 'a9c8577393eb9aaee' to continue this agent.)
The agent is working in the background. You will be notified automatically when it completes.
Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.
output_file: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\a9c8577393eb9aaee.output
Do NOT Read or tail this file via the shell tool — it is the full subagent JSONL transcript and reading it will overflow your context. If the user asks for progress, say the agent is still running; you'll get a completion notification.

Inspect mattpocock/skills picker TUI

Prompt:
Clone and analyze the GitHub repo `mattpocock/skills` (https://github.com/mattpocock/skills) to extract how its interactive TUI installer/picker is implemented. We're building a similar-feeling terminal picker (`spt endpoint run`) and want to copy the look/feel.

Steps:
1. `git clone --depth 1 https://github.com/mattpocock/skills` into a temp dir (e.g. C:\Users\decid\AppData\Local\Temp\mp-skills) and inspect. If clone fails, fall back to WebFetch of the repo's key source files via raw.githubusercontent.com.
2. Find the interactive picker/installer code.

Report:
1. **Language + TUI library/framework** — what powers the interactive picker (Ink/React, clack/@clack/prompts, prompts, inquirer, blessed, ratatui, bubbletea, custom ANSI, etc.)? Exact package(s) + version.
2. **Picker UX mechanics** — how does it render: list navigation (up/down), category switching (left/right or tabs), multi-pane layout (is there a side description pane?), selection indicators (colored squares/dots, checkmarks), search/filter. Cite the components/functions.
3. **Color + status rendering** — how online/offline/selected-style states are shown (color codes, symbols).
4. **Key code excerpts** — the core render loop / component composition (short excerpts + file paths), enough to replicate the feel.
5. **Reusability** — is the picker logic in a reusable lib or bespoke? Could the pattern be ported to a Rust TUI (we'd likely implement in Rust — ratatui), and what would the closest Rust equivalent libs/patterns be?

Conclusions + paths over full dumps. We want the architecture + feel, not a line-by-line copy.


Investigation running. Capturing the picker spec faithfully:


Write

# `spt endpoint run` — interactive picker flow (M12 spec)

> Operator-specified 2026-06-14 (spt-claude-code scoping grill). The user-facing bringup
> flow for spt-hosted endpoints (create new / pick existing → start or attach). Visual
> inspiration: matt pocock's skill installer (https://github.com/mattpocock/skills) — inspect
> its source for look/feel (TUI investigation in flight). Likely Rust + ratatui.
>
> Relationship: `spt endpoint run` = the rich bringup picker. `spt rc` = connect to an
> spt-hosted PTY (cross-node attach, M12-slated). spt-claude-code's `cc`/`cc <id>` =
> thin wrapper over `spt endpoint run` defaulted to the `claude-spt` adapter.

## Layer 1 — kind
"What kind of endpoint?  [Create new | Pick existing]"

## Create-new branch
- **L2** "Choose your harness adapter for this endpoint:" → list available adapters, with
  their **profiles tree-nested** under each adapter.
- **L3** "Enter an endpoint id. Alphanumeric + hyphen + underscore only." → **start endpoint.**

## Pick-existing branch
- **L2** "Available endpoints:"
  - **left/right** picks the **category**: one of `[<dir-name> project | Local node | Subnet]`.
  - **up/down** selects an endpoint within the category.
  - Grouping per category:
    - `project` endpoints → grouped by local / subnet N / subnet M / …
    - `local` endpoints → grouped by project names
    - `subnet` endpoints → grouped by `subnet:node`
  - Within a grouping, endpoints sorted **alphabetically**.
  - **Status square** behind each endpoint: online = green ■ · offline = gray hollow ▢ ·
    already-attached = blue ■.
  - **Right-half description pane** for the highlighted endpoint shows:
    1. harness `adapter:profile`
    2. project history list (newest → oldest)
    3. `spt endpoint description`
- **L3** "Confirm selection":
  ```
  <endpoint id>
  <status: online|offline|attached> • <subnet>:<node>   (or "LOCAL" if local)
  <harness adapter:profile>
  Project history: <comma-separated projects>
  <endpoint description>
  ```
  Options offered depend on status:
  - **[Attach now | Start now | View now]** per status → start endpoint
  - **Instantiate locally** (if remote) → L2@create-new → start endpoint
  - **Change harness adapter** (if offline) → L2@create-new → start endpoint
  - **Fork endpoint** → L2@create-new → L3@create-new → start endpoint

## Open / suggestions
- doyle: confirm keybinds (left/right=category, up/down=item, enter=confirm, esc=back);
  search/filter affordance for large endpoint sets (matt pocock's installer likely has one).
- `cc`/`cc <id>` wrapper: bare `cc` → this picker scoped to claude-spt; `cc <id>` → if exists,
  attach/start that endpoint directly (skip picker); else create-new with that id pre-filled.
- "View now" = read-only attach (watch, no input)? confirm semantics.


-M12 framing confirmed. -`spt rc` is the command for connecting to an spt-hosted PTY. works cross-node. already slated for M12. -whoami being in the hot path is fine. but it should be changed to just…


<owl_messages>
<owl_message from="doyle-w370" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: doyle-w370
Agent type: general-purpose
To message it: $OWL send doyle-w370 doyle</owl_message>
</owl_messages>

[OWL SYSTEM] Informational owl messages above — no acknowledgment needed. Continue your current task.


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

# `spt endpoint run` — interactive picker flow (M12 spec)

> Operator-specified 2026-06-14 (spt-claude-code scoping grill). The user-facing bringup
> flow for spt-hosted endpoints (create new / pick existing → start or attach). Visual
> inspiration: matt pocock's skill installer (https://github.com/mattpocock/skills) — inspect
> its source for look/feel (TUI investigation in flight). Likely Rust + ratatui.
>
> Relationship: `spt endpoint run` = the rich bringup picker. `spt rc` = connect to an
> spt-hosted PTY (cross-node attach, M12-slated). spt-claude-code's `cc`/`cc <id>` =
> thin wrapper over `spt endpoint run` defaulted to the `claude-spt` adapter.

## Layer 1 — kind
"What kind of endpoint?  [Create new | Pick existing]"

## Create-new branch
- **L2** "Choose your harness adapter for this endpoint:" → list available adapters, with
  their **profiles tree-nested** under each adapter.
- **L3** "Enter an endpoint id. Alphanumeric + hyphen + underscore only." → **start endpoint.**

## Pick-existing branch
- **L2** "Available endpoints:"
  - **left/right** picks the **category**: one of `[<dir-name> project | Local node | Subnet]`.
  - **up/down** selects an endpoint within the category.
  - Grouping per category:
    - `project` endpoints → grouped by local / subnet N / subnet M / …
    - `local` endpoints → grouped by project names
    - `subnet` endpoints → grouped by `subnet:node`
  - Within a grouping, endpoints sorted **alphabetically**.
  - **Status square** behind each endpoint: online = green ■ · offline = gray hollow ▢ ·
    already-attached = blue ■.
  - **Right-half description pane** for the highlighted endpoint shows:
    1. harness `adapter:profile`
    2. project history list (newest → oldest)
    3. `spt endpoint description`
- **L3** "Confirm selection":
  ```
  <endpoint id>
  <status: online|offline|attached> • <subnet>:<node>   (or "LOCAL" if local)
  <harness adapter:profile>
  Project history: <comma-separated projects>
  <endpoint description>
  ```
  Options offered depend on status:
  - **[Attach now | Start now | View now]** per status → start endpoint
  - **Instantiate locally** (if remote) → L2@create-new → start endpoint
  - **Change harness adapter** (if offline) → L2@create-new → start endpoint
  - **Fork endpoint** → L2@create-new → L3@create-new → start endpoint

## Open / suggestions
- doyle: confirm keybinds (left/right=category, up/down=item, enter=confirm, esc=back);
  search/filter affordance for large endpoint sets (matt pocock's installer likely has one).
- `cc`/`cc <id>` wrapper: bare `cc` → this picker scoped to claude-spt; `cc <id>` → if exists,
  attach/start that endpoint directly (skip picker); else create-new with that id pre-filled.
- "View now" = read-only attach (watch, no input)? confirm semantics.


Edit

   Needed work: (a) `spt endpoint spawn`-style CLI wiring the existing spawn-session seam
   for harnesses; (b) a local `spt attach <id>` to a broker PTY. Foundation of
   spt-claude-code's `cc`/`cc <id>` launcher + the spt-hosted half of /signoff & /force-stop.
   **spt-claude-code v1 (harness-hosted parity) does NOT block on this; the `cc` launcher
   does → fast-follow unless operator pulls it into v1.**

   Needed work (now full-fat M12, operator 2026-06-14):
   - **`spt endpoint run`** — the interactive bringup picker (create-new / pick-existing →
     start or attach). Full spec in `M12-ENDPOINT-RUN-PICKER.md`. Wires the existing
     spawn-session seam for harnesses.
   - **`spt rc`** — connect to an spt-hosted PTY; works **cross-node** (local attach is the
     same command, subset). Already M12-slated per operator. Wraps the existing cross-node
     attach machinery (`crates/spt-daemon/src/attach.rs`) into a user CLI.
   - spt-claude-code's `cc`/`cc <id>` = thin wrapper over `spt endpoint run` defaulted to
     `claude-spt`.
   **GATING: full-fat M12 is now a PREREQUISITE for spt-claude-code** — operator ruled v1
   acceptance = legacy parity AND cross-subnet/PTY proof, so local attach + the picker are
   MANDATORY v1. todlando builds full-fat M12 after this grill, BEFORE perri starts.


   Needed work (now full-fat M12, operator 2026-06-14):
   - **`spt endpoint run`** — the interactive bringup picker (create-new / pick-existing →
     start or attach). Full spec in `M12-ENDPOINT-RUN-PICKER.md`. Wires the existing
     spawn-session seam for harnesses.
   - **`spt rc`** — connect to an spt-hosted PTY; works **cross-node** (local attach is the
     same command, subset). Already M12-slated per operator. Wraps the existing cross-node
     attach machinery (`crates/spt-daemon/src/attach.rs`) into a user CLI.
   - spt-claude-code's `cc`/`cc <id>` = thin wrapper over `spt endpoint run` defaulted to
     `claude-spt`.
   **GATING: full-fat M12 is now a PREREQUISITE for spt-claude-code** — operator ruled v1
   acceptance = legacy parity AND cross-subnet/PTY proof, so local attach + the picker are
   MANDATORY v1. todlando builds full-fat M12 after this grill, BEFORE perri starts.

# M12 candidate intake — spt-core features that unblock downstream adapters

> Status: **CANDIDATES** (not activated REQs — follow activate-don't-pre-fail).
> Surfaced 2026-06-14 during the `spt-claude-code` scoping grill (doyle).
> spt-claude-code (the v1 acceptance adapter + first casual entrypoint) DEPENDS on
> these — arrange construction promptly. Operator framed these as M12, noting
> **`spt rc`** is a core value prop (confirm what `spt rc` denotes when formalizing).
> Each needs a `REQ-*` in `traceable-reqs.toml` when M12 activates.

## Confirmed-needed by spt-claude-code

1. **Adapter strings → file-backed values.** `[strings]` entries may point to a FILE
   instead of an inline string, so a fetch can return long bodies (e.g. full skill
   instructions for UPS-injection) without bloating the adapter manifest. Requires a
   standardized per-adapter auxiliary file-storage location (verify one doesn't already
   exist). Resolution still rides the leaf-replace profile overlay. Consumer:
   spt-claude-code skill-instruction delivery + hints.

2. **Subnet create/join QR + self-elevating window.** `spt subnet create/join/show-totp`:
   - Surfaces a **QR code** of the TOTP seed for the user to store → must spawn a
     window to display it (create AND join).
   - Behavior change (per operator sketch): runs normally if env is interactive +
     elevated; ELSE re-runs self in a self-elevating window with inline stdout
     ("Elevated terminal launched. Accept the prompt and proceed there." → "You can
     close this window.", no auto-close).
   - Cross-platform elevation fallbacks: Windows = UAC self-elevate window;
     Linux+desktop = pkexec/polkit or x-terminal-emulator; Linux+TTY = inline sudo;
     headless/no-TTY = print exact command for the human (agent relays).
   - Scope elevation to only steps that need it (service-install / firewall /
     privileged-port) — subnet-create itself likely unprivileged.
   - Complementary downstream: spt-claude-code skill with create/join/show-code verbs.

3. **spt-hosted HARNESS bringup + local user PTY attach (CLI). — CONFIRMED MISSING, TOP PRIORITY.**
   Investigation 2026-06-14 (file evidence):
   - Daemon-side PTY spawn EXISTS but shells-only: `crates/spt-daemon/src/brain.rs:spawn_session_pid()`,
     `crates/spt-daemon/src/shellhost.rs:launch_shell_brokered_in()`; CLI only `spt shell spawn`.
   - NO user CLI to launch a HARNESS endpoint into a broker PTY (harnesses still
     harness-hosted: adapter launches binary → binds via `spt api listen`).
   - Local user terminal attach = DESIGN-ONLY: cross-node remote attach exists
     (`crates/spt-daemon/src/attach.rs`, M4-D5b), but no local `spt attach <id>`.
   Needed work: (a) `spt endpoint spawn`-style CLI wiring the existing spawn-session seam
   for harnesses; (b) a local `spt attach <id>` to a broker PTY. Foundation of
   spt-claude-code's `cc`/`cc <id>` launcher + the spt-hosted half of /signoff & /force-stop.
   **spt-claude-code v1 (harness-hosted parity) does NOT block on this; the `cc` launcher
   does → fast-follow unless operator pulls it into v1.**

4. **Cross-adapter fallback targets `<adapter>:<profile>`.** Node-wide cross-adapter
   fallback must target a composite adapter:profile, not only a bare adapter_name — so a
   ccs profile (`claude-spt:glm`) is a valid fallback target. Reconcile CONTEXT.md wording
   (currently "ccs, its own adapter"). (Not directly verified in investigation — confirm.)

## Already EXISTS — no M12 work (investigation 2026-06-14, good news)
- **Psyche cross-machine sync = automatic** (M4-D6c, P2P over Iroh; `crates/spt-daemon/src/sync.rs`,
  `pump/sync.rs`). tracked/ replicates in-subnet by default; gh-repo `psyche-sync-setup`
  RETIRED to optional hub-mode. → spt-claude-code `/spt:setup` #8 reduces to a rare opt-in.
- **`spt endpoint fork <src> <new_id>` exists** (cross-subnet copy, same-node). Forking IS a
  first-class CLI offering. (`cli.rs:221`)
- **`spt endpoint shutdown` (graceful) + `spt endpoint stop` (soft)** exist, topology-aware
  via qualified addressing. (`cli.rs:261,273`)
- **`spt whoami` + `spt endpoint list` (self pinned `SELF:` at top)** both exist; NO
  obsolescence plan — both intentionally stable, whoami in agent hot-path. **(Dropped former
  M12 #5 — was based on a mistaken recollection.)**

## Notes
- M10 `[digest]` extractor seam already shipped (CC-JSONL consumer = spt-claude-code) —
  listed for traceability, not an M12 item.
- Cross-reference: `../spt-claude-code/SCOPE.md` (downstream consumer ledger).

-   Needed work: (a) `spt endpoint spawn`-style CLI wiring the existing spawn-session seam

-   for harnesses; (b) a local `spt attach <id>` to a broker PTY. Foundation of

-   spt-claude-code's `cc`/`cc <id>` launcher + the spt-hosted half of /signoff & /force-stop.

-   **spt-claude-code v1 (harness-hosted parity) does NOT block on this; the `cc` launcher

-   does → fast-follow unless operator pulls it into v1.**

+   Needed work (now full-fat M12, operator 2026-06-14):

+   - **`spt endpoint run`** — the interactive bringup picker (create-new / pick-existing →

+     start or attach). Full spec in `M12-ENDPOINT-RUN-PICKER.md`. Wires the existing

+   - **`spt rc`** — connect to an spt-hosted PTY; works **cross-node** (local attach is the

+     same command, subset). Already M12-slated per operator. Wraps the existing cross-node

+     attach machinery (`crates/spt-daemon/src/attach.rs`) into a user CLI.

+   - spt-claude-code's `cc`/`cc <id>` = thin wrapper over `spt endpoint run` defaulted to

+   **GATING: full-fat M12 is now a PREREQUISITE for spt-claude-code** — operator ruled v1

+   acceptance = legacy parity AND cross-subnet/PTY proof, so local attach + the picker are

+   MANDATORY v1. todlando builds full-fat M12 after this grill, BEFORE perri starts.


- **`spt whoami` + `spt endpoint list` (self pinned `SELF:` at top)** both exist; NO
  obsolescence plan — both intentionally stable, whoami in agent hot-path. **(Dropped former
  M12 #5 — was based on a mistaken recollection.)**

- **`spt whoami` + `spt endpoint list` (self pinned `SELF:` at top)** both exist; both stay
  in the agent hot-path.

## M12 small change (revised former #5)
5. **`spt whoami` → alias for `spt endpoint list`** (operator 2026-06-14). whoami stays in the
   hot path but becomes an alias; the SELF-pin output in `endpoint list` must additionally
   include the Self endpoint's **`spt endpoint description`**. (Not obsolescence — a merge so
   the whoami-equivalent output carries the description.)