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