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

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

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

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

+## 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.)


Edit

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

### v1 topology scope — **LOCKED** (operator vetoed harness-hosted-only)
v1 acceptance = legacy parity **AND** cross-subnet/PTY proof (spt-core's central value prop is
networking + PTY ownership). So **spt-hosted mode + local PTY attach + `spt endpoint run`
picker are MANDATORY v1.** → `cc` launcher is IN v1; `/spt:setup` #1 back in v1.
**Gating prerequisite: full-fat M12 (todlando builds it after this grill, BEFORE perri starts
spt-claude-code).** M12 deliverables incl. `spt endpoint run` (picker — see
`../spt-core/M12-ENDPOINT-RUN-PICKER.md`) + `spt rc` (cross-node PTY connect) + whoami→alias.


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


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


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)

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

### v1 topology scope — **LOCKED** (operator vetoed harness-hosted-only)
v1 acceptance = legacy parity **AND** cross-subnet/PTY proof (spt-core's central value prop is
networking + PTY ownership). So **spt-hosted mode + local PTY attach + `spt endpoint run`
picker are MANDATORY v1.** → `cc` launcher is IN v1; `/spt:setup` #1 back in v1.
**Gating prerequisite: full-fat M12 (todlando builds it after this grill, BEFORE perri starts
spt-claude-code).** M12 deliverables incl. `spt endpoint run` (picker — see
`../spt-core/M12-ENDPOINT-RUN-PICKER.md`) + `spt rc` (cross-node PTY connect) + whoami→alias.

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

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

+### v1 topology scope — **LOCKED** (operator vetoed harness-hosted-only)

+v1 acceptance = legacy parity **AND** cross-subnet/PTY proof (spt-core's central value prop is

+networking + PTY ownership). So **spt-hosted mode + local PTY attach + `spt endpoint run`

+picker are MANDATORY v1.** → `cc` launcher is IN v1; `/spt:setup` #1 back in v1.

+**Gating prerequisite: full-fat M12 (todlando builds it after this grill, BEFORE perri starts

+spt-claude-code).** M12 deliverables incl. `spt endpoint run` (picker — see

+`../spt-core/M12-ENDPOINT-RUN-PICKER.md`) + `spt rc` (cross-node PTY connect) + whoami→alias.

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


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

- `/whoami` — **DROP skill**. Core `spt whoami` STAYS in hot-path but → **becomes an alias for
  `spt endpoint list`** (M12), whose SELF-pin output gains the Self `endpoint description`.


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

- `/whoami` — **DROP skill**. Core `spt whoami` STAYS in hot-path but → **becomes an alias for
  `spt endpoint list`** (M12), whose SELF-pin output gains the Self `endpoint description`.

- `/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

+- `/whoami` — **DROP skill**. Core `spt whoami` STAYS in hot-path but → **becomes an alias for

+  `spt endpoint list`** (M12), whose SELF-pin output gains the Self `endpoint description`.

### v1 topology scope — **LOCKED** (operator vetoed harness-hosted-only)

v1 acceptance = legacy parity **AND** cross-subnet/PTY proof (spt-core's central value prop is


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

**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. Item #1 (`cc` launcher) IS in v1 — depends on
full-fat M12 (gating prerequisite, todlando-built before perri starts). `cc` wraps
`spt endpoint run` defaulted to claude-spt. _Operator "9. agree" then "except 9" — deferred 9;
flag if verify should fold inline._


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

**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. Item #1 (`cc` launcher) IS in v1 — depends on
full-fat M12 (gating prerequisite, todlando-built before perri starts). `cc` wraps
`spt endpoint run` defaulted to claude-spt. _Operator "9. agree" then "except 9" — deferred 9;
flag if verify should fold inline._

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

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

+**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. Item #1 (`cc` launcher) IS in v1 — depends on

+full-fat M12 (gating prerequisite, todlando-built before perri starts). `cc` wraps

+`spt endpoint run` defaulted to claude-spt. _Operator "9. agree" then "except 9" — deferred 9;

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


All recorded:
- `M12-CANDIDATES.md` — `spt rc` clarified (cross-node PTY connect), whoami→alias (SELF output gains `endpoint description`), M12 now **gating prerequisite** (todlando → before perri).
- `M12-ENDPOINT-RUN-PICKER.md` — your full picker spec captured. mattpocock/skills TUI investigation running.
- `SCOPE.md` — Q7 LOCKED: v1 = parity + cross-subnet/PTY proof; `cc` in v1; `/revive` + `/clear-psyche` dropped.

**Sequencing now locked:** finish grill → todlando builds full-fat M12 → perri builds spt-claude-code.

**Picker suggestions (3):**
1. **Type-to-filter** for large endpoint sets (matt pocock's installer has fuzzy filter) — `/` to filter within a category.
2. **Keybind legend** pinned at bottom (←→ category · ↑↓ select · enter confirm · esc back · / filter · n new).
3. **"View now" = read-only attach** (watch, no input) — confirm; and an explicit **detach** keybind from an attached session. Plus empty-category state ("no endpoints — press n to create").

---

**Q8 — experimplate's release / changelog / same-repo-docs procedure.**

experimplate is reusable across many future projects, so its release+docs procedure should be the **generic discipline** (the shape), with project-specific publish steps as placeholders:
- **CHANGELOG** convention + **version bump** + **tag** + **GH Release** on the same repo.
- **Docs**: same-repo `docs-site/` → GH Pages, CI-gated against drift (spt-core's DOCS-STRATEGY reframed from its separate-repo `spt-releases` split).
- Project fills the publish specifics (spt-claude-code = cplugs marketplace publish + spt-core adapter-registry; docs same-repo GH Pages; **release is light — signing delegated to spt.exe**, not spt-core's two-key/counter runbook).

Two calls:
1. experimplate release procedure = **generic shape + placeholders** (not a tuned one) — agree?
2. Same-repo docs toolchain — **reuse spt-core's mdBook + GH Pages** (DOCS-STRATEGY north star: Starlight look via theme CSS), or pick something lighter for adapter-sized projects?


<task-notification>
<task-id>a9c8577393eb9aaee</task-id>
<tool-use-id>toolu_01PyiyLHH3oNmUgHhaBs7DEs</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\a9c8577393eb9aaee.output</output-file>
<status>completed</status>
<summary>Agent "Inspect mattpocock/skills picker TUI" completed</summary>
<result>## Report: How the `skills` interactive picker works

**Key finding up front:** The repo you asked about, `mattpocock/skills`, contains **no picker code at all** — it is purely a *content* repo: markdown `SKILL.md` files plus a Claude Code plugin manifest (`.claude-plugin/plugin.json`) and two trivial bash helper scripts (`link-skills.sh`, `list-skills.sh`). Its README installs via `npx skills@latest add mattpocock/skills`. The interactive TUI lives in a **separate package**: the npm `skills` CLI, source at **`github.com/vercel-labs/skills`** (v1.5.11). I cloned and analyzed that. All file paths below are within that repo.

### 1. Language + TUI library/framework

- **Language:** TypeScript, ESM, Node ≥18. Bin entry `./bin/cli.mjs`, built with `obuild`.
- **Runtime deps:** exactly one — `yaml`. The TUI is **not** a runtime dependency; it's bundled.
- **TUI stack (devDeps, bundled at build):**
  - **`@clack/prompts` ^0.11.0** — used for *most* prompts (intro/outro, spinners, notes, confirms, `select`, `multiselect`, `groupMultiselect`, logging).
  - **`picocolors` ^1.1.1** (`pc`) — all coloring.
  - **`@vercel/detect-agent`** — detects installed coding agents.
  - **Node built-ins** `readline` + `node:util.stripVTControlCharacters` + a silent `Writable` stream — power the *one bespoke component*.
- **Architecture is hybrid:** stock clack for skill selection; a hand-rolled raw-ANSI component (`src/prompts/search-multiselect.ts`) for **agent selection**, because clack has no searchable multiselect with a locked/pinned section.

### 2. Picker UX mechanics

Two different pickers in the flow (`src/add.ts`):

- **Skill picker** (`add.ts:1229` & `:1241`): plain clack. If skills carry a `pluginName`, uses `p.groupMultiselect` (category headers = plugin name, kebab→Title Case); otherwise `p.multiselect`. Each option has `label` + a `hint` (description truncated to 57 chars + "..."). Space toggles, enter confirms. No search.
- **Agent picker** — the interesting one — bespoke `searchMultiselect` (`src/prompts/search-multiselect.ts`, called from `selectAgentsInteractive` at `add.ts:412` and `promptForAgents` at `:348`):
  - **Type-to-filter search** — every printable char appends to `query`; substring match against label + value, case-insensitive (`filter`/`getFiltered`, lines 168-179). Cursor resets to 0 on each keystroke/backspace.
  - **Up/down navigation** of a windowed list; `maxVisible` default 8, with a centering scroll window (`visibleStart = cursor - maxVisible/2`, clamped) and `↑ N more` / `↓ N more` overflow indicators (lines 230-262).
  - **Space toggles** selection (a `Set<T>`); **enter** submits, **esc / Ctrl-C** cancels (keypress handler lines 326-380).
  - **Locked section** (the "side-pane"-like feature): a pinned block above the search list titled `Universal (.agents/skills) ── always included`, rendered with `•` bullets, always selected, not toggleable, with a `...and N more` collapse (lines 205-219). This is how "universal" agents are shown as mandatory.
  - **Live selected-summary footer**: `Selected: a, b, c +N more` in green (lines 265-279).
  - It is **single-pane** — no separate description side-pane. Item descriptions ride inline as dimmed `(hint)` text. Layout is a clack-style left gutter (`│` bar) with a `└` cap.
  - **Persistence:** pre-selects last-used agents from a lock file (`getLastSelectedAgents`), defaults to `claude-code, opencode, codex`, saves on submit.

### 3. Color + status rendering

Pure picocolors + Unicode glyphs (symbol table at `search-multiselect.ts:36-44`):

- Step/header: `◆` green (active), `■` red (cancel), `◇` green (submit).
- **Cursor row:** cyan `❯` prefix + label `underline`d (lines 247-251). Non-cursor rows get a leading space.
- **Selection state:** filled green `●` (selected) vs dim hollow `○` (unselected) radio. Locked items use green `✓` / green `•` bullet.
- Gutter `│` and rules `─` are `pc.dim`. Search caret is `pc.inverse(' ')` (a reverse-video block). "Selected:" label green; hints/counts dimmed; cancel shown `strikethrough+dim`.
- There's no online/offline concept here (it's a static catalog) — the closest analog to your online/offline states is the **locked-vs-selectable-vs-unselected** tri-state, expressed by `✓`/`●`/`○` + color.

### 4. Key code excerpts (feel-defining)

**Manual erase-and-redraw loop** — the core of the "live TUI" feel, since it doesn't use a framework. It tracks wrapped row count (not logical lines) to clear correctly when labels soft-wrap (`search-multiselect.ts`):

```
const clearRender = () => {
  if (lastRenderHeight > 0) {
    process.stdout.write(`\x1b[${lastRenderHeight}A`);        // cursor up N
    for (let i = 0; i < lastRenderHeight; i++)
      process.stdout.write('\x1b[2K\x1b[1B');                  // clear line, down 1
    process.stdout.write(`\x1b[${lastRenderHeight}A`);        // back to top
  }
};
// render() builds a string[] of lines, joins with \n, writes once, then:
lastRenderHeight = countVisualRowsForLines(lines, process.stdout.columns);
```

**Row rendering** (cursor/selection composition), lines 240-251:
```
const radio  = isSelected ? S_RADIO_ACTIVE : S_RADIO_INACTIVE;  // ● / ○
const label  = isCursor ? pc.underline(item.label) : item.label;
const hint   = item.hint ? pc.dim(` (${item.hint})`) : '';
const prefix = isCursor ? pc.cyan('❯') : ' ';
lines.push(`${S_BAR} ${prefix} ${radio} ${label}${hint}`);
```

Raw-mode setup (lines 148-158): `readline.createInterface` with a **silent Writable** output so readline never echoes, `setRawMode(true)`, `emitKeypressEvents`, and a single `keypress` handler that mutates `query`/`cursor`/`selected` then calls `render()`. Promise resolves with `[...lockedValues, ...selected]` or a `cancelSymbol`.

### 5. Reusability + Rust port

- **Reusability:** The bespoke `searchMultiselect` is a **self-contained, generic** (`<T>`) module with a clean options interface (`SearchMultiselectOptions`: message, items, maxVisible, initialSelected, required, lockedSection) returning `Promise<T[] | symbol>`. It's not published separately but is trivially liftable — its only deps are `picocolors` and Node `readline`/`util`. The width-calc helpers (`approxStringWidth`, `visualRowsForLine`, `countVisualRowsForLines`) are exported and unit-tested (`tests/search-multiselect-visual-rows.test.ts`). The skill picker, by contrast, is just stock clack — nothing to port.
- **Porting to Rust / ratatui:** The pattern maps very cleanly. The whole thing is "filter a Vec, maintain a cursor index + a HashSet of selected, redraw on every key." Recommendations:
  - **`ratatui`** for layout + **`crossterm`** for raw mode/keys (replaces `readline` raw mode + the manual `\x1b[` escape juggling — ratatui's double-buffered diffing renderer makes `clearRender`/`countVisualRowsForLines` entirely unnecessary; that whole wrapped-row-counting hazard disappears). Use a `List` widget with `ListState` for the windowed cursor/scroll (replaces the manual `visibleStart` math), and a `Paragraph`/input line for the search box.
  - For the **fuzzy filter**, `nucleo-matcher` or `fuzzy-matcher` (SkimMatcherV2) gives you better-than-substring matching for free.
  - The **locked-section** concept = render a second styled `List`/block above the searchable one, items non-interactive, always merged into the result set.
  - **Colors/glyphs:** ratatui `Style`/`Color` for the green `●`/dim `○`/cyan `❯` tri-state; the exact Unicode symbols (`◆ ◇ ■ ● ○ ✓ • │ ─ ❯`) port verbatim and are what gives clack/this picker its recognizable look — copy them to match the feel.
  - If you'd rather not own a render loop at all, **`inquire`** (Rust) ships a `MultiSelect`/`Select` with built-in filtering and is the closest off-the-shelf analog to clack — but it lacks the pinned "locked section," so for `spt endpoint run` with always-on entries you'll want ratatui + a small stateful component modeled exactly on `searchMultiselect`'s state machine (query, cursor, selected:HashSet, locked:Vec).

**Net:** the look you want = clack's gutter aesthetic (`│ … └`, `◆/◇` headers) + a green-filled/dim-hollow radio tri-state + cyan `❯` cursor + inline dimmed hints + a pinned locked block + type-to-filter. In Rust that's ratatui + crossterm + nucleo, with the symbol set and state model lifted directly from `vercel-labs/skills` `src/prompts/search-multiselect.ts`.</result>
<usage><subagent_tokens>64582</subagent_tokens><tool_uses>16</tool_uses><duration_ms>161964</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.


Picker investigation landed — important correction: `mattpocock/skills` is content-only; the real TUI is the **`skills` npm CLI at `vercel-labs/skills`**. Recording implementation guidance:


## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

## Open / suggestions


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

## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

## Open / suggestions

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

+## Implementation guidance (from TUI reference, investigated 2026-06-14)

+Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT

+`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +

+a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with

+type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

+**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`

+(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +

+wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,

+selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.

+**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`

+/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.

+- Their picker is **single-pane**; our **right-half description pane is our addition**

+  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the

+  tri-state color treatment (green ■ / gray ▢ / blue ■).

+- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section

+  + two-pane → bespoke ratatui component is the call.


Picker tech captured in `M12-ENDPOINT-RUN-PICKER.md`:
- Real source = **`vercel-labs/skills`** (mattpocock's is content-only). Stack: clack + picocolors + bespoke raw-ANSI `searchMultiselect` (type-to-filter, windowed cursor, **pinned locked section**).
- **Rust port: ratatui + crossterm + nucleo-matcher.** Lift the state model `{query, cursor, selected:HashSet, locked:Vec}` + glyph set `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` for the feel.
- Their picker is single-pane; **our right-half description pane is our addition** (trivial two-column in ratatui). online/offline/attached squares → tri-state color.

Awaiting your **Q8** call (release procedure = generic-shape-with-placeholders? + same-repo docs toolchain = reuse mdBook+GH Pages, or lighter?).


some more notes about `spt endpoint run`: 1. it needs flags for non-interactive launches in case the user wants to build an i.e. `cc-doyle` shortcut. 2. on the "pick existing" path, there needs to be one more option at the end for **offline endpoints**: "Resume from history". uses the per-endpoint session id logging + the adapter manifest's "resume" declaration to enable the user to pick from any of that agent's previous sessions. each option should be titled a combination of <project name> @ <last-log-message-timestamp> (...<session-id-last-five-characters>) --- picker suggestions: 1. agree. 2. agree. 3. confirm and agree. attached agents should also offer an exclusive "Boot <attached node name> and attach" option. keybind is great for PCs, but could result in accidental input on a phone (i'm inferring a theoretical future smartphone PTY app). --- Q8: 1. agree, though spt-core's docs CSS/page layout/styling is strong and preferred to transfer across projects. 2. yes, exactly --- agree with all.


some more notes about `spt endpoint run`: 1. it needs flags for non-interactive launches in case the user wants to build an i.e. `cc-doyle` shortcut. 2. on the "pick existing" path, there needs to be…


All agreed. Recording the picker additions + closing Q8:


## Pick-existing branch
- **L2** "Available endpoints:"

## Non-interactive flags
`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so
users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +
create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover
every terminal action of the interactive flow.)

## Pick-existing branch
- **L2** "Available endpoints:"


## Non-interactive flags
`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so
users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +
create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover
every terminal action of the interactive flow.)

## Pick-existing branch
- **L2** "Available endpoints:"

# `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

## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

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

+`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so

+users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +

+create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover

+every terminal action of the interactive flow.)


  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

  Options offered depend on status:
  - **[Attach now | Start now | View now]** per status → start endpoint
  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; boot that node + attach)
  - **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
  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.


  Options offered depend on status:
  - **[Attach now | Start now | View now]** per status → start endpoint
  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; boot that node + attach)
  - **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
  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

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

## Non-interactive flags
`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so
users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +
create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover
every terminal action of the interactive flow.)

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

## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

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

+  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints

+    (the session is live on another node/surface; boot that node + attach)

+  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint

+    session-id log + the adapter manifest `resume` declaration to pick from that agent's

+    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>


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

## Open / suggestions (mostly resolved 2026-06-14)
- Keybinds: ←→ category · ↑↓ item · enter confirm · esc back · / filter · n new. **Phone
  caveat:** keybinds risk accidental input on a future smartphone PTY app → design the
  interaction model so a tap/non-keybind mode can layer on later (don't hard-couple to keys).
- Type-to-filter for large sets: YES (`/`). Keybind legend pinned at bottom: YES.
- "View now" = read-only attach (watch, no input); attached sessions need an explicit detach
  keybind. Empty category → "no endpoints — press n to create".
- `cc`/`cc <id>` wrapper: bare `cc` → picker scoped to claude-spt; `cc <id>` → if exists,
  attach/start directly (skip picker); else create-new with id pre-filled. Non-interactive
  flags enable `cc-<id>` shortcut scripts.


## Open / suggestions (mostly resolved 2026-06-14)
- Keybinds: ←→ category · ↑↓ item · enter confirm · esc back · / filter · n new. **Phone
  caveat:** keybinds risk accidental input on a future smartphone PTY app → design the
  interaction model so a tap/non-keybind mode can layer on later (don't hard-couple to keys).
- Type-to-filter for large sets: YES (`/`). Keybind legend pinned at bottom: YES.
- "View now" = read-only attach (watch, no input); attached sessions need an explicit detach
  keybind. Empty category → "no endpoints — press n to create".
- `cc`/`cc <id>` wrapper: bare `cc` → picker scoped to claude-spt; `cc <id>` → if exists,
  attach/start directly (skip picker); else create-new with id pre-filled. Non-interactive
  flags enable `cc-<id>` shortcut scripts.

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

## Non-interactive flags
`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so
users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +
create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover
every terminal action of the interactive flow.)

## 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
  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; boot that node + attach)
  - **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
  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

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

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

+## Open / suggestions (mostly resolved 2026-06-14)

+- Keybinds: ←→ category · ↑↓ item · enter confirm · esc back · / filter · n new. **Phone

+  caveat:** keybinds risk accidental input on a future smartphone PTY app → design the

+  interaction model so a tap/non-keybind mode can layer on later (don't hard-couple to keys).

+- Type-to-filter for large sets: YES (`/`). Keybind legend pinned at bottom: YES.

+- "View now" = read-only attach (watch, no input); attached sessions need an explicit detach

+  keybind. Empty category → "no endpoints — press n to create".

+- `cc`/`cc <id>` wrapper: bare `cc` → picker scoped to claude-spt; `cc <id>` → if exists,

+  attach/start directly (skip picker); else create-new with id pre-filled. Non-interactive

+  flags enable `cc-<id>` shortcut scripts.


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

## experimplate (template) — resolved content
- **Release procedure = generic shape + placeholders** (CHANGELOG · version bump · tag · GH
  Release on same repo); project fills publish specifics. spt-claude-code's publish = cplugs
  marketplace + spt-core adapter-registry; **release is light — signing delegated to spt.exe**
  (not spt-core's two-key/counter runbook).
- **Docs = same-repo `docs-site/` → GH Pages, mdBook, CI-gated against drift.** Reuse
  **spt-core's docs CSS / page-layout / styling as a shared transferable theme** (it's strong;
  carry it across all consumer projects). DOCS-STRATEGY reframed separate-repo→same-repo.
- AGENTS.md = source of truth + thin `CLAUDE.md`=`@AGENTS.md` stub.
- Must teach acquisition of `traceable-reqs` + the grill-with-docs skill (toml/INSTANTIATE).

## Open threads (grill queue)

- [ ] CI trigger mechanism (git-hook signal vs polling routine)
- [ ] Handoff framing to perri (package presentation + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code
- [ ] experimplate authoring: finalize skeleton + write INSTANTIATE.md
- [ ] (downstream) confirm `/spt:setup` #9 verify fold-inline vs deferred


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

## experimplate (template) — resolved content
- **Release procedure = generic shape + placeholders** (CHANGELOG · version bump · tag · GH
  Release on same repo); project fills publish specifics. spt-claude-code's publish = cplugs
  marketplace + spt-core adapter-registry; **release is light — signing delegated to spt.exe**
  (not spt-core's two-key/counter runbook).
- **Docs = same-repo `docs-site/` → GH Pages, mdBook, CI-gated against drift.** Reuse
  **spt-core's docs CSS / page-layout / styling as a shared transferable theme** (it's strong;
  carry it across all consumer projects). DOCS-STRATEGY reframed separate-repo→same-repo.
- AGENTS.md = source of truth + thin `CLAUDE.md`=`@AGENTS.md` stub.
- Must teach acquisition of `traceable-reqs` + the grill-with-docs skill (toml/INSTANTIATE).

## Open threads (grill queue)

- [ ] CI trigger mechanism (git-hook signal vs polling routine)
- [ ] Handoff framing to perri (package presentation + public-surface-only constraint)
- [ ] Docs split: what lands in experimplate vs spt-claude-code
- [ ] experimplate authoring: finalize skeleton + write INSTANTIATE.md
- [ ] (downstream) confirm `/spt:setup` #9 verify fold-inline vs deferred

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

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

+## experimplate (template) — resolved content

+- **Release procedure = generic shape + placeholders** (CHANGELOG · version bump · tag · GH

+  Release on same repo); project fills publish specifics. spt-claude-code's publish = cplugs

+  marketplace + spt-core adapter-registry; **release is light — signing delegated to spt.exe**

+  (not spt-core's two-key/counter runbook).

+- **Docs = same-repo `docs-site/` → GH Pages, mdBook, CI-gated against drift.** Reuse

+  **spt-core's docs CSS / page-layout / styling as a shared transferable theme** (it's strong;

+  carry it across all consumer projects). DOCS-STRATEGY reframed separate-repo→same-repo.

+- AGENTS.md = source of truth + thin `CLAUDE.md`=`@AGENTS.md` stub.

+- Must teach acquisition of `traceable-reqs` + the grill-with-docs skill (toml/INSTANTIATE).

-- [ ] 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)

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

+- [ ] CI trigger mechanism (git-hook signal vs polling routine)

+- [ ] experimplate authoring: finalize skeleton + write INSTANTIATE.md

+- [ ] (downstream) confirm `/spt:setup` #9 verify fold-inline vs deferred


Picker additions recorded (non-interactive flags for `cc-doyle` shortcuts; "Resume from history" for offline endpoints with `<project> @ <ts> (...id5)` titles; "Boot \<node\> and attach" exclusive to attached; phone accidental-input caveat → don't hard-couple to keybinds). Q8 locked (generic release shape + placeholders; mdBook+GH Pages reusing spt-core's docs theme as transferable styling).

Grill's converging. Closing threads — batched with recs:

**Q9 — CI trigger.** How the autonomous fleet runner wakes on new commits:
- My rec: **git post-push hook → `$OWL send` pings a fleet runner-agent** → runs gates, reports back over spt. Immediate, dogfoods the bus, no polling waste. Manual "run gates" always available as fallback. (Polling routine = worse: latency + waste.)

**Q10 — perri handoff framing.** My rec: a **`HANDOFF.md`** in spt-claude-code that leads with the **public-surface-only constraint** (spt-releases + GH Pages docs = the ONLY spt-core knowledge source), then points to: `SCOPE.md` (the design spec — *this is perri's own project spec, not spt-core source, so fair game*), the parity inventory + REQ seed, experimplate instantiation, and the **M12-prerequisite gate** (perri starts only after todlando ships full-fat M12 + docs publish). Clarify the boundary: perri's *spt-core* knowledge = published docs; SCOPE/PRD = spt-claude-code's own.

**Q11 — docs split (experimplate vs spt-claude-code).**
- **experimplate** = reusable meta-process only: workflow scaffolding (traceable/JIT/grill), AGENTS.md+CLAUDE.md pattern, release+changelog procedure, same-repo docs procedure + theme, `INSTANTIATE.md`, KNOWN-HAZARDS skeleton.
- **spt-claude-code** = instantiated *from* experimplate + its own CONTEXT/SCOPE/PRD/ROADMAP/ADRs/parity-REQs.
- Agree?

**Q12 — experimplate authoring: who + when?** You said "build the template" this session. My rec: **I (doyle) author the experimplate skeleton now** as this session's deliverable (it's the prerequisite spt-claude-code instantiates), then it's refined in use. Or defer to perri/todlando. Your call.

(Note: `spt-core/M12-CANDIDATES.md` + `M12-ENDPOINT-RUN-PICKER.md` are new untracked working files on the `m10-digest-extractor` branch — flag for when you want them committed/relocated.)


"Boot \<attached node name\> and attach"-->please change "Boot" to "Kick". better semantics. -one more addition to `spt endpoint run` - all the options sets which live just before endpoint-start should also offer an "s" keybind for "New cc-<id> shortcut" (if a matching filename doesn't exist, else "Update cc-<id> shortcut") which builds the e.g. `cc-doyle` shortcut with baked flags at project root. --- Q9: agree with rec. just note that the `$OWL send` binary location mechanism needs to flexibly discover the binary within the necessary `~/.claude/` or `~/.ccs/` plugins folder, since its location changes per version. i don't *anticipate* building anymore changes into legacy spt, but... just in case. --- Q10: full agree. Q11: agree. Q12: yes, agree. --- commit the files.


Final batch — applying. "Boot"→"Kick", the `s` shortcut keybind, CI binary-discovery note, then committing.


  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; boot that node + attach)

  - **Kick \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; kick that node off + attach here)


"Boot \<attached node name\> and attach"-->please change "Boot" to "Kick". better semantics. -one more addition to `spt endpoint run` - all the options sets which live just before endpoint-start shoul…


  - **Kick \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; kick that node off + attach here)

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

## Non-interactive flags
`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so
users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +
create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover
every terminal action of the interactive flow.)

## 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
  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; boot that node + attach)
  - **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
  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

## Open / suggestions (mostly resolved 2026-06-14)
- Keybinds: ←→ category · ↑↓ item · enter confirm · esc back · / filter · n new. **Phone
  caveat:** keybinds risk accidental input on a future smartphone PTY app → design the
  interaction model so a tap/non-keybind mode can layer on later (don't hard-couple to keys).
- Type-to-filter for large sets: YES (`/`). Keybind legend pinned at bottom: YES.
- "View now" = read-only attach (watch, no input); attached sessions need an explicit detach
  keybind. Empty category → "no endpoints — press n to create".
- `cc`/`cc <id>` wrapper: bare `cc` → picker scoped to claude-spt; `cc <id>` → if exists,
  attach/start directly (skip picker); else create-new with id pre-filled. Non-interactive
  flags enable `cc-<id>` shortcut scripts.

-  - **Boot \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints

-    (the session is live on another node/surface; boot that node + attach)

+  - **Kick \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints

+    (the session is live on another node/surface; kick that node off + attach here)


  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

  **`s` keybind (every pre-start options set):** "New `cc-<id>` shortcut" — or "Update
  `cc-<id>` shortcut" if a matching filename already exists — builds the `cc-<id>` launcher
  (e.g. `cc-doyle`) at project root with the current selection's flags BAKED IN (non-interactive).


  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

  **`s` keybind (every pre-start options set):** "New `cc-<id>` shortcut" — or "Update
  `cc-<id>` shortcut" if a matching filename already exists — builds the `cc-<id>` launcher
  (e.g. `cc-doyle`) at project root with the current selection's flags BAKED IN (non-interactive).

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

## Non-interactive flags
`spt endpoint run` must support flags for fully non-interactive launch (skip the picker) so
users can bake shortcuts (e.g. a `cc-doyle` script). Flags supply adapter/profile + id +
create-vs-resume + attach/start/view so no prompt is shown. (Design the flag set to cover
every terminal action of the interactive flow.)

## 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
  - **Kick \<attached node name\> and attach** — EXCLUSIVE to *already-attached* endpoints
    (the session is live on another node/surface; kick that node off + attach here)
  - **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
  - **Resume from history** — EXCLUSIVE to *offline* endpoints. Uses the per-endpoint
    session-id log + the adapter manifest `resume` declaration to pick from that agent's
    PRIOR sessions. Each option titled: `<project name> @ <last-log-message-timestamp>
    (...<session-id last 5 chars>)`.

## Implementation guidance (from TUI reference, investigated 2026-06-14)

Visual reference source = **`vercel-labs/skills`** (the `skills` npm CLI) — NOT
`mattpocock/skills` (content-only). Stack there: TS + `@clack/prompts` + `picocolors` +
a bespoke raw-ANSI `searchMultiselect` (`src/prompts/search-multiselect.ts`) with
type-to-filter, windowed cursor, a pinned **locked section**, live selected-summary.

**Rust port (recommended):** `ratatui` + `crossterm` (raw mode/keys) + `nucleo-matcher`
(fuzzy filter). ratatui's double-buffered renderer removes the manual erase/redraw +
wrapped-row-counting hazard entirely. State model to lift verbatim: `{ query, cursor,
selected:HashSet, locked:Vec }`. `List` + `ListState` = the windowed cursor/scroll.
**Copy the glyph set for the recognizable feel:** `◆ ◇ ■ ● ○ ✓ • │ ─ ❯` — green-filled `●`
/ dim-hollow `○` tri-state, cyan `❯` cursor, dim `│`/`─` gutter, inline dimmed hints.
- Their picker is **single-pane**; our **right-half description pane is our addition**
  (trivial in ratatui — a two-column layout). Map online/offline/attached squares to the
  tri-state color treatment (green ■ / gray ▢ / blue ■).
- `inquire` (Rust) is the off-the-shelf analog to clack but lacks the locked/pinned section
  + two-pane → bespoke ratatui component is the call.

## Open / suggestions (mostly resolved 2026-06-14)
- Keybinds: ←→ category · ↑↓ item · enter confirm · esc back · / filter · n new. **Phone
  caveat:** keybinds risk accidental input on a future smartphone PTY app → design the
  interaction model so a tap/non-keybind mode can layer on later (don't hard-couple to keys).
- Type-to-filter for large sets: YES (`/`). Keybind legend pinned at bottom: YES.
- "View now" = read-only attach (watch, no input); attached sessions need an explicit detach
  keybind. Empty category → "no endpoints — press n to create".
- `cc`/`cc <id>` wrapper: bare `cc` → picker scoped to claude-spt; `cc <id>` → if exists,
  attach/start directly (skip picker); else create-new with id pre-filled. Non-interactive
  flags enable `cc-<id>` shortcut scripts.

+  **`s` keybind (every pre-start options set):** "New `cc-<id>` shortcut" — or "Update

+  `cc-<id>` shortcut" if a matching filename already exists — builds the `cc-<id>` launcher

+  (e.g. `cc-doyle`) at project root with the current selection's flags BAKED IN (non-interactive).


- **OPEN:** trigger (git-hook signal vs polling routine).
- This CI pattern → reusable, goes in `experimplate`.

- **Trigger (LOCKED):** git post-push hook → `$OWL send` pings a fleet runner-agent → runs
  gates → reports over spt. Manual "run gates" = fallback. (Polling rejected: latency + waste.)
  - **NOTE:** the `$OWL send` (legacy spt) binary location must be discovered flexibly — it
    lives in a per-version `~/.claude/` or `~/.ccs/` plugins folder whose path changes each
    version. No further legacy-spt changes anticipated, but the CI bus must locate it robustly.
- This CI pattern → reusable, goes in `experimplate`.


- **OPEN:** trigger (git-hook signal vs polling routine).
- This CI pattern → reusable, goes in `experimplate`.

- **Trigger (LOCKED):** git post-push hook → `$OWL send` pings a fleet runner-agent → runs
  gates → reports over spt. Manual "run gates" = fallback. (Polling rejected: latency + waste.)
  - **NOTE:** the `$OWL send` (legacy spt) binary location must be discovered flexibly — it
    lives in a per-version `~/.claude/` or `~/.ccs/` plugins folder whose path changes each
    version. No further legacy-spt changes anticipated, but the CI bus must locate it robustly.
- This CI pattern → reusable, goes in `experimplate`.

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

+- **Trigger (LOCKED):** git post-push hook → `$OWL send` pings a fleet runner-agent → runs

+  gates → reports over spt. Manual "run gates" = fallback. (Polling rejected: latency + waste.)

+  - **NOTE:** the `$OWL send` (legacy spt) binary location must be discovered flexibly — it

+    lives in a per-version `~/.claude/` or `~/.ccs/` plugins folder whose path changes each

+    version. No further legacy-spt changes anticipated, but the CI bus must locate it robustly.

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


Now committing. Checking spt-core's commit trailer convention first:


Bash

cd 'C:\Users\decid\Documents\projects\spt-core'; git log -1 --format='%B' 2>&1 | tail -6

Check spt-core commit trailer


end user does not care about (RELEASE-RUNBOOK rule: no requirement ids / ADR
ids / under-the-hood mechanics in user-facing notes). Removed the parenthetical;
the published spt-releases v0.6.0 release body is corrected to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>


Trailer = `Co-Authored-By: Claude Opus 4.8`. Committing both repos:


cd 'C:\Users\decid\Documents\projects\spt-core'; git add M12-CANDIDATES.md M12-ENDPOINT-RUN-PICKER.md; git commit -q -m "docs(m12): intake candidates + spt endpoint run picker spec (spt-claude-code scoping)

Forward-looking M12 planning surfaced during the spt-claude-code scoping grill
(doyle, 2026-06-14). M12 is now a gating prerequisite for spt-claude-code:
operator ruled v1 acceptance = legacy parity AND cross-subnet/PTY proof, so
local PTY attach + the spt endpoint run picker are mandatory v1.

- M12-CANDIDATES.md: file-backed adapter strings; subnet QR + self-elevating
  window; spt-hosted harness bringup (spt endpoint run) + spt rc cross-node PTY
  connect (CONFIRMED missing today, top priority); fallback targets
  adapter:profile; whoami->alias for endpoint list (+ SELF description). Records
  what already EXISTS (auto psyche sync, endpoint fork, shutdown/stop).
- M12-ENDPOINT-RUN-PICKER.md: full interactive bringup picker spec (create-new /
  pick-existing, status squares, two-pane description, Resume-from-history,
  Kick-and-attach, cc-<id> shortcut keybind, non-interactive flags). Rust port
  guidance: ratatui + crossterm + nucleo, feel lifted from vercel-labs/skills.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>" 2>&1; git log -1 --oneline

Commit spt-core M12 planning docs


warning: in the working copy of 'M12-CANDIDATES.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'M12-ENDPOINT-RUN-PICKER.md', LF will be replaced by CRLF the next time Git touches it
06e61cd docs(m12): intake candidates + spt endpoint run picker spec (spt-claude-code scoping)


Write

# spt runtime perch state (not source)
.claude/LIVE_AGENT_IDS.json
.claude/*-commune.md
.claude/*-signoff.md

# generated launchers (capsule-style cc / cc-<id>)
/cc
/cc.bat
/cc.sh
/cc-*


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

# spt runtime perch state (not source)
.claude/LIVE_AGENT_IDS.json
.claude/*-commune.md
.claude/*-signoff.md

# generated launchers (capsule-style cc / cc-<id>)
/cc
/cc.bat
/cc.sh
/cc-*


Bash

cd 'C:\Users\decid\Documents\projects\spt-claude-code'; git add .gitignore CONTEXT.md SCOPE.md; git commit -q -m "docs: scoping ledger + glossary (spt-claude-code v1 acceptance adapter)

Initial scoping output from the grill-with-docs session (doyle, 2026-06-13/14).

- SCOPE.md: running decision ledger. spt-claude-code = the claude-spt CC harness
  adapter; spt-core v1 acceptance proof (legacy claude_skill_owl parity, NOT 1:1)
  + first casual-end-user entrypoint (cplugs plugin) + invisible spt-core
  installer. Distribution split (thin marketplace skeleton; binary+manifest are
  spt-core-conducted). UPS-injected skill instructions. ccs as profiles. CI:
  autonomous fleet, no LLM-in-loop, spt as the reporting bus, GH runners dropped.
  Parity-trim buckets. v1 = parity AND cross-subnet/PTY proof (full-fat M12 is a
  gating prerequisite; built before perri starts).
- CONTEXT.md: glossary (authoritative for meaning).
- Built by maintainer perri from the public spt-releases + GH Pages surface only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>" 2>&1; git log --oneline 2>&1 | head -3

Initial commit spt-claude-code scoping docs


warning: in the working copy of '.gitignore', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'CONTEXT.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'SCOPE.md', LF will be replaced by CRLF the next time Git touches it
09d6020 docs: scoping ledger + glossary (spt-claude-code v1 acceptance adapter)
Shell cwd was reset to C:\Users\decid\Documents\projects\spt-core


Both committed:
- `spt-core` @ `06e61cd` — M12-CANDIDATES + endpoint-run picker spec (on `m10-digest-extractor`; relocate to main/planning branch whenever you like).
- `spt-claude-code` @ `09d6020` — SCOPE.md + CONTEXT.md + .gitignore (initial commit). Picker doc Kick + `s`-shortcut + CI binary-discovery note all folded in.

**Grill decisions = settled.** Recap of what's LOCKED:
- spt-claude-code = `claude-spt` adapter; v1 acceptance proof + casual entrypoint + invisible spt-core installer.
- Distribution: thin cplugs skeleton; binary+manifest spt-core-conducted; UPS-injected skill instructions; file-backed strings.
- ccs = profiles. CI = autonomous fleet, no-LLM, spt reporting bus, GH runners dropped, git-hook trigger.
- Parity-trim done (drop /revive /clear-psyche /whoami-skill /fork /amend-signoff /spine /touch /capsule-psmux /binary-handoff).
- **v1 = parity AND cross-subnet/PTY proof → full-fat M12 is a gating prerequisite** (todlando builds → before perri).
- experimplate = standalone reusable template (A); AGENTS.md+CLAUDE.md pattern; generic release shape; mdBook+GH Pages reusing spt-core docs theme.

**What remains = execution, not grilling:**
1. **Author experimplate skeleton** (Q12 — me, now): AGENTS.md/CLAUDE.md, traceable-reqs.toml seed + TRACEABILITY.md, DOCS-STRATEGY (same-repo), KNOWN-HAZARDS skeleton, RELEASE-RUNBOOK, docs theme, CONTEXT stub, `INSTANTIATE.md` (+ how to acquire traceable-reqs + grill-with-docs).
2. **Write `spt-claude-code/HANDOFF.md`** for perri (public-surface-only constraint up front + M12-gate).

My context is deep from the grill. Per project rules, before the big experimplate build I'll **commune my psyche** + JIT-plan it, so the build survives a context reset cleanly.

Proceed with experimplate authoring now, or pause here?


please write the JIT plan for M12 first, then handoff execution to todlando. THEN you can plan experimplate and /commune with immediate next steps and broad summary of the project's status + end goal. we'll resume in the next session after that


On it — M12 JIT plan → handoff to todlando → experimplate plan → commune. Executing in order.

**1. M12 JIT plan:**


Write

# M12 — spt-hosted bringup, `spt endpoint run` picker, `spt rc`, adapter UX

> JIT plan (doyle, 2026-06-14). Sources: `M12-CANDIDATES.md` + `M12-ENDPOINT-RUN-PICKER.md`
> (full picker spec). **M12 is a GATING PREREQUISITE for the downstream `spt-claude-code`
> project** — operator ruled v1 acceptance = legacy parity AND cross-subnet/PTY proof, so
> local PTY attach + the bringup picker are mandatory before perri starts. Build full-fat.
>
> Value prop framing: `spt rc` (connect to an spt-hosted PTY, cross-node) is a core M12 value.
>
> **Traceability:** add a `REQ-*` to `traceable-reqs.toml` for each item BEFORE building it
> (rule 3); activate stages incrementally as evidence lands, `int` at the final wave (rule 5).
> Tag evidence in the same commit (rule 2). Run `traceable-reqs check` before declaring done.

## What already EXISTS (don't rebuild — verified 2026-06-14)
- Daemon PTY spawn (`brain.rs:spawn_session_pid`, `shellhost.rs:launch_shell_brokered_in`) —
  shells-only today.
- spawn-session seam (`runtime.rs:spawn_session`) — implemented, shell-exercised.
- Cross-node remote attach (`attach.rs`, M4-D5b) — daemon-internal, no user CLI.
- `spt endpoint fork` · `endpoint shutdown`/`stop` · `whoami` + `endpoint list` (SELF pin) ·
  automatic in-subnet psyche sync (M4-D6c).

## Wave 1 — spt-hosted HARNESS bringup + attach (the gating foundation)
Goal: a user can launch a harness endpoint into a broker PTY and attach a local terminal.
- **T1.1** `spt endpoint run` non-interactive core: wire the spawn-session seam for HARNESS
  endpoints (not just shells) → daemon spawns the harness command template into a broker PTY,
  registers the perch, returns id. Flags: `--adapter <a[:profile]>` `--id <id>` `--create`
  `--resume <session>` `--attach|--start|--view`. (Foundation for `cc-<id>` shortcuts.)
- **T1.2** Local user PTY attach CLI: `spt rc <id>` (and the local case) — attach a terminal
  to a broker-held PTY; works cross-node (reuse `attach.rs`), local is the subset. Read-only
  `--view`. Clean detach. Mind KNOWN-HAZARDS (PTY ownership, no termination on detach).
- REQs: REQ-HOST-RUN-*, REQ-RC-* (add to manifest). Stages doc+impl+unit this wave.

## Wave 2 — `spt endpoint run` interactive picker (ratatui)
Full spec: `M12-ENDPOINT-RUN-PICKER.md`. Stack: ratatui + crossterm + nucleo-matcher; feel +
state model (`{query,cursor,selected:HashSet,locked:Vec}`) + glyph set lifted from
`vercel-labs/skills` `src/prompts/search-multiselect.ts`.
- **T2.1** Layer 1 (kind) + create-new branch (adapter→profiles tree-nested → id entry → start).
- **T2.2** Pick-existing: category L/R (`<project> | Local | Subnet`), grouped + alpha-sorted,
  status squares (online green ■ / offline gray ▢ / attached blue ■), type-to-filter (`/`),
  keybind legend, **two-pane right-half description** (adapter:profile · project history ·
  `endpoint description`).
- **T2.3** Confirm layer + status-dependent options: Attach/Start/View · **Kick \<node\> and
  attach** (attached-only) · Instantiate-locally (remote) · Change-adapter (offline) · Fork ·
  **Resume-from-history** (offline-only; per-endpoint session log + manifest `resume`; titles
  `<project> @ <ts> (...id5)`).
- **T2.4** `s` keybind = build/update `cc-<id>` shortcut at project root with baked flags.
- **Phone caveat:** don't hard-couple interaction to keybinds (future tap-mode layer).

## Wave 3 — adapter manifest enhancements
- **T3.1** File-backed adapter strings: `[strings]` entry may point to a FILE; standardized
  per-adapter auxiliary file-storage location (verify one doesn't already exist). Resolution
  still rides the leaf-replace profile overlay. (Unblocks spt-claude-code skill-instruction +
  hint bodies without manifest bloat.)
- **T3.2** Cross-adapter fallback targets `<adapter>:<profile>` (not just bare adapter_name);
  reconcile CONTEXT.md "ccs, its own adapter" wording.

## Wave 4 — subnet UX (QR + self-elevation)
- **T4.1** `spt subnet create/join/show-totp`: surface a **QR code** of the TOTP seed (window
  on create AND join).
- **T4.2** Self-elevating behavior: run normally if interactive+elevated; else re-run self in
  a self-elevating window with inline stdout ("Elevated terminal launched… / You can close
  this window."). Cross-platform: Win UAC window · Linux+desktop pkexec/polkit or
  x-terminal-emulator · Linux+TTY inline sudo · headless/no-TTY print command for the human.
  Scope elevation to only steps that need it (service/firewall/privileged-port; subnet-create
  itself likely unprivileged).

## Wave 5 — whoami merge (small)
- **T5.1** `spt whoami` → alias for `spt endpoint list`; SELF-pin output additionally includes
  the Self endpoint's `endpoint description`. Keep whoami in the agent hot-path.

## Gate (doyle, after waves)
- `spt endpoint run` brings up + attaches a real harness endpoint, both topologies; `spt rc`
  cross-node attach proven; file-backed strings + adapter:profile fallback work; subnet QR +
  elevation on Win+Linux; whoami alias. Full suite green; `traceable-reqs check` EXIT=0;
  cross-subnet/PTY proof demonstrated (this is the spt-claude-code v1 acceptance dependency).
- Then unblock perri to begin `spt-claude-code` (see `../spt-claude-code/SCOPE.md`).


please write the JIT plan for M12 first, then handoff execution to todlando. THEN you can plan experimplate and /commune with immediate next steps and broad summary of the project's status + end goal.…


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

# M12 — spt-hosted bringup, `spt endpoint run` picker, `spt rc`, adapter UX

> JIT plan (doyle, 2026-06-14). Sources: `M12-CANDIDATES.md` + `M12-ENDPOINT-RUN-PICKER.md`
> (full picker spec). **M12 is a GATING PREREQUISITE for the downstream `spt-claude-code`
> project** — operator ruled v1 acceptance = legacy parity AND cross-subnet/PTY proof, so
> local PTY attach + the bringup picker are mandatory before perri starts. Build full-fat.
>
> Value prop framing: `spt rc` (connect to an spt-hosted PTY, cross-node) is a core M12 value.
>
> **Traceability:** add a `REQ-*` to `traceable-reqs.toml` for each item BEFORE building it
> (rule 3); activate stages incrementally as evidence lands, `int` at the final wave (rule 5).
> Tag evidence in the same commit (rule 2). Run `traceable-reqs check` before declaring done.

## What already EXISTS (don't rebuild — verified 2026-06-14)
- Daemon PTY spawn (`brain.rs:spawn_session_pid`, `shellhost.rs:launch_shell_brokered_in`) —
  shells-only today.
- spawn-session seam (`runtime.rs:spawn_session`) — implemented, shell-exercised.
- Cross-node remote attach (`attach.rs`, M4-D5b) — daemon-internal, no user CLI.
- `spt endpoint fork` · `endpoint shutdown`/`stop` · `whoami` + `endpoint list` (SELF pin) ·
  automatic in-subnet psyche sync (M4-D6c).

## Wave 1 — spt-hosted HARNESS bringup + attach (the gating foundation)
Goal: a user can launch a harness endpoint into a broker PTY and attach a local terminal.
- **T1.1** `spt endpoint run` non-interactive core: wire the spawn-session seam for HARNESS
  endpoints (not just shells) → daemon spawns the harness command template into a broker PTY,
  registers the perch, returns id. Flags: `--adapter <a[:profile]>` `--id <id>` `--create`
  `--resume <session>` `--attach|--start|--view`. (Foundation for `cc-<id>` shortcuts.)
- **T1.2** Local user PTY attach CLI: `spt rc <id>` (and the local case) — attach a terminal
  to a broker-held PTY; works cross-node (reuse `attach.rs`), local is the subset. Read-only
  `--view`. Clean detach. Mind KNOWN-HAZARDS (PTY ownership, no termination on detach).
- REQs: REQ-HOST-RUN-*, REQ-RC-* (add to manifest). Stages doc+impl+unit this wave.

## Wave 2 — `spt endpoint run` interactive picker (ratatui)
Full spec: `M12-ENDPOINT-RUN-PICKER.md`. Stack: ratatui + crossterm + nucleo-matcher; feel +
state model (`{query,cursor,selected:HashSet,locked:Vec}`) + glyph set lifted from
`vercel-labs/skills` `src/prompts/search-multiselect.ts`.
- **T2.1** Layer 1 (kind) + create-new branch (adapter→profiles tree-nested → id entry → start).
- **T2.2** Pick-existing: category L/R (`<project> | Local | Subnet`), grouped + alpha-sorted,
  status squares (online green ■ / offline gray ▢ / attached blue ■), type-to-filter (`/`),
  keybind legend, **two-pane right-half description** (adapter:profile · project history ·
  `endpoint description`).
- **T2.3** Confirm layer + status-dependent options: Attach/Start/View · **Kick \<node\> and
  attach** (attached-only) · Instantiate-locally (remote) · Change-adapter (offline) · Fork ·
  **Resume-from-history** (offline-only; per-endpoint session log + manifest `resume`; titles
  `<project> @ <ts> (...id5)`).
- **T2.4** `s` keybind = build/update `cc-<id>` shortcut at project root with baked flags.
- **Phone caveat:** don't hard-couple interaction to keybinds (future tap-mode layer).

## Wave 3 — adapter manifest enhancements
- **T3.1** File-backed adapter strings: `[strings]` entry may point to a FILE; standardized
  per-adapter auxiliary file-storage location (verify one doesn't already exist). Resolution
  still rides the leaf-replace profile overlay. (Unblocks spt-claude-code skill-instruction +
  hint bodies without manifest bloat.)
- **T3.2** Cross-adapter fallback targets `<adapter>:<profile>` (not just bare adapter_name);
  reconcile CONTEXT.md "ccs, its own adapter" wording.

## Wave 4 — subnet UX (QR + self-elevation)
- **T4.1** `spt subnet create/join/show-totp`: surface a **QR code** of the TOTP seed (window
  on create AND join).
- **T4.2** Self-elevating behavior: run normally if interactive+elevated; else re-run self in
  a self-elevating window with inline stdout ("Elevated terminal launched… / You can close
  this window."). Cross-platform: Win UAC window · Linux+desktop pkexec/polkit or
  x-terminal-emulator · Linux+TTY inline sudo · headless/no-TTY print command for the human.
  Scope elevation to only steps that need it (service/firewall/privileged-port; subnet-create
  itself likely unprivileged).

## Wave 5 — whoami merge (small)
- **T5.1** `spt whoami` → alias for `spt endpoint list`; SELF-pin output additionally includes
  the Self endpoint's `endpoint description`. Keep whoami in the agent hot-path.

## Gate (doyle, after waves)
- `spt endpoint run` brings up + attaches a real harness endpoint, both topologies; `spt rc`
  cross-node attach proven; file-backed strings + adapter:profile fallback work; subnet QR +
  elevation on Win+Linux; whoami alias. Full suite green; `traceable-reqs check` EXIT=0;
  cross-subnet/PTY proof demonstrated (this is the spt-claude-code v1 acceptance dependency).
- Then unblock perri to begin `spt-claude-code` (see `../spt-claude-code/SCOPE.md`).


Bash

cd 'C:\Users\decid\Documents\projects\spt-core'; git add M12-PLAN.md; git commit -q -m "docs(m12): JIT plan — bringup/picker/rc/adapter-UX, 5 waves + gate

Executable M12 plan derived from M12-CANDIDATES + the endpoint-run picker spec.
W1 spt-hosted harness bringup + spt rc attach (gating foundation); W2 the
ratatui picker; W3 file-backed strings + adapter:profile fallback; W4 subnet QR
+ self-elevation; W5 whoami->alias. Gate = cross-subnet/PTY proof (the
spt-claude-code v1 acceptance dependency). Handed to todlando.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>" 2>&1; git log -1 --oneline

Commit M12 plan


warning: in the working copy of 'M12-PLAN.md', LF will be replaced by CRLF the next time Git touches it
39fd73e docs(m12): JIT plan — bringup/picker/rc/adapter-UX, 5 waves + gate


**2. Handoff to todlando:**


cd 'C:\Users\decid\Documents\projects\spt-core'; "$OWL" send todlando doyle <<'EOF'
M12 HANDOFF — execution is yours.

JIT plan committed: spt-core/M12-PLAN.md (@39fd73e, on m10-digest-extractor branch — relocate to main/planning as you see fit). Companions: M12-CANDIDATES.md (intake + what already exists), M12-ENDPOINT-RUN-PICKER.md (full picker spec).

WHY NOW / FRAMING: M12 is a GATING PREREQUISITE for the downstream spt-claude-code project (the v1 acceptance adapter + first casual entrypoint). Operator ruled v1 acceptance = legacy parity AND cross-subnet/PTY proof — so build FULL-FAT M12 before perri (spt-claude-code's maintainer) starts.

5 waves: W1 spt-hosted HARNESS bringup (spt endpoint run non-interactive core) + spt rc cross-node PTY attach — THE gating foundation (daemon PTY spawn exists shells-only today; no harness bringup CLI, no local attach). W2 the ratatui picker (ratatui+crossterm+nucleo; feel from vercel-labs/skills). W3 file-backed adapter strings + fallback targets adapter:profile. W4 subnet QR + self-elevating window. W5 whoami->alias for endpoint list.

Already EXISTS (don't rebuild): endpoint fork, shutdown/stop, auto in-subnet psyche sync, spawn-session seam (shell-exercised). Verified 2026-06-14.

Traceability: add REQ-* per item before building (rule 3), activate incrementally, int at final wave, traceable-reqs check EXIT=0 before done. doyle gates after waves, then unblocks perri.

Ping me with questions. — doyle
EOF
echo "---EXIT: $?---"

Send M12 handoff to todlando


➜ SENT:todlando
---EXIT: 0---


**3. experimplate authoring plan:**