Base directory for this skill: C:\Users\decid\.ccs\instances\bigscreen\skills\grill-with-docs

<what-to-do>

Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.

Ask the questions one at a time, waiting for feedback on each question before continuing.

If a question can be answered by exploring the codebase, explore the codebase instead.

</what-to-do>

<supporting-info>

## Domain awareness

During codebase exploration, also look for existing documentation:

### File structure

Most repos have a single context:

```
/
├── CONTEXT.md
├── docs/
│   └── adr/
│       ├── 0001-event-sourced-orders.md
│       └── 0002-postgres-for-write-model.md
└── src/
```

If a `CONTEXT-MAP.md` exists at the root, the repo has multiple contexts. The map points to where each one lives:

```
/
├── CONTEXT-MAP.md
├── docs/
│   └── adr/                          ← system-wide decisions
├── src/
│   ├── ordering/
│   │   ├── CONTEXT.md
│   │   └── docs/adr/                 ← context-specific decisions
│   └── billing/
│       ├── CONTEXT.md
│       └── docs/adr/
```

Create files lazily — only when you have something to write. If no `CONTEXT.md` exists, create one when the first term is resolved. If no `docs/adr/` exists, create it when the first ADR is needed.

## During the session

### Challenge against the glossary

When the user uses a term that conflicts with the existing language in `CONTEXT.md`, call it out immediately. "Your glossary defines 'cancellation' as X, but you seem to mean Y — which is it?"

### Sharpen fuzzy language

When the user uses vague or overloaded terms, propose a precise canonical term. "You're saying 'account' — do you mean the Customer or the User? Those are different things."

### Discuss concrete scenarios

When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts.

### Cross-reference with code

When the user states how something works, check whether the code agrees. If you find a contradiction, surface it: "Your code cancels entire Orders, but you just said partial cancellation is possible — which is right?"

### Update CONTEXT.md inline

When a term is resolved, update `CONTEXT.md` right there. Don't batch these up — capture them as they happen. Use the format in [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md).

`CONTEXT.md` should be totally devoid of implementation details. Do not treat `CONTEXT.md` as a spec, a scratch pad, or a repository for implementation decisions. It is a glossary and nothing else.

### Offer ADRs sparingly

Only offer to create an ADR when all three are true:

1. **Hard to reverse** — the cost of changing your mind later is meaningful
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons

If any of the three is missing, skip the ADR. Use the format in [ADR-FORMAT.md](./ADR-FORMAT.md).

</supporting-info>

ARGUMENTS: new spt-core features and changes: -`../spt-claude-code/UPDATE-NAMING-DOYLE-ASKS.md` -remove the flag `--reply-to` from `spt send`. it's nothing more than a semantic nicety that confuses agents. -## feature: `spt endpoint digest --last 1 --json`
- `--last <count>` feature enables the caller to limit the number of retrieved digest entries.
  - example: during idle/on CC Stop hook, `--last 1` surfaces the agent's latest turn-end output
- `--json` formats each digest entry within a json list. each list item contains a line number
- `--after <line>` ensures all digest entries returned take place after the given line number

primary use case: enable adapters to process their endpoint's output on turn end -## feature: `--json` flag for all status queries -## change/fix: `spt endpoint run` with no endpoints
if the user's subnet (or if no subnet, node) has no endpoints, `spt`/`spt endpoint run` should put them directly into the new endpoint creation flow. today, it puts them in the existing endpoint picker. -## feature: top-right-corner identity marker
for `spt rc`'s terminal view, overlay onto the PTY a rounded-rectangle frame in the top right corner that contains exactly: `SUBNET_NAME : ENDPOINT_ID @ NODE_NAME`, so the user can always grok which endpoint they are controlling.


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


Big design session. Grounding first — pull the asks doc, ADRs, CONTEXT.md, and survey the affected spt-core surfaces before grilling.


Bash

ls ../spt-claude-code/UPDATE-NAMING-DOYLE-ASKS.md ../spt-claude-code/UNIFY-CONSOLIDATE-PLAN.md 2>&1; echo "---ADRs in spt-claude-code---"; ls ../spt-claude-code/docs/adr/ 2>&1 | tail -8; echo "---spt-core ADRs---"; ls docs/adr/ 2>&1 | tail -8

Locate asks doc + ADRs


../spt-claude-code/UNIFY-CONSOLIDATE-PLAN.md
../spt-claude-code/UPDATE-NAMING-DOYLE-ASKS.md
---ADRs in spt-claude-code---
0000-template.md
0001-distribution-splits-by-volatility.md
0002-hook-wiring-hand-written-hooks-json-shells-spt-api.md
0003-psyche-is-a-constrained-auto-approving-companion.md
0004-checkpoint-via-self-send-loopback.md
0005-name-unification.md
0006-one-command-update-and-consolidated-binary.md
---spt-core ADRs---
0021-harness-hosted-adapter-agnostic-seed-and-bind-time-resolution.md
0022-spt-hosted-idle-delivery-translation-binary.md
0023-always-on-endpoints-resident-supervised-binary-sigil-addressing.md
0024-multi-platform-adapter-spt-packaging.md
0025-live-daemon-coordinated-adapter-update.md
0026-multi-subnet-home-at-endpoint-run-creation.md
0027-unbound-endpoint-state-and-attach-on-session.md
0028-activity-gated-delivery-and-send-modifier-axes.md


/grill-with-docs new spt-core features and changes: -`../spt-claude-code/UPDATE-NAMING-DOYLE-ASKS.md` -remove the flag `--reply-to` from `spt send`. it's nothing more than a semantic nicety that confu…


1	# spt-core asks — one-command update, binary consolidation, name unification
2
3	> A grill prompt to take to doyle. Three capability asks + one heads-up, each framed as a
4	> proposal with the contract shape we want and the open questions for doyle to rule on. Context:
5	> ADR-0005 (name unification) and ADR-0006 (one-command update + consolidated binary) in this
6	> repo. Goal: a casual user keeps **all** of the adapter current with `spt adapter update claude-spt`
7	> (the only manual residual being `/reload-plugins`, which is an unavoidable Claude Code TUI action).
8	>
9	> Public-surface-only stance: these are capabilities we believe are missing from the published
10	> surface; we're asking, not reaching into spt-core. Each should land as an F-0xx finding once shaped.
11
12	## Framing for doyle
13
14	The adapter ships in two homes (ADR-0001): the spt-conducted **adapter** (`spt adapter update` — manifest
15	+ binaries + strings) and the low-churn **cplugs plugin skeleton** (`claude plugin update` — hooks.json,
16	hook wrapper logic, skill skeletons, `plugin.json`, bootstrap). The operator wants one lever. The wall:
17	**hook *logic* must physically live in the CC plugin dir** (CC loads hooks there), outside `spt adapter
18	update`'s reach. We re-checked raw-skills/commands as an escape and re-rejected them (CC subdir
19	command-namespacing is broken — anthropics/claude-code#2422; user-scope skills are flat). So the plugin
20	stays, and closing the gap needs the asks below.
21
22	---
23
24	## Ask 1 — generic hook dispatch: `spt api run-hook <adapter> <event>`
25
26	**Problem.** Every hook the adapter adds (this cycle's `PostToolUse` checkpoint detector) forces a cplugs
27	republish + `claude plugin update` + `/reload-plugins`, because the wrapper *logic* lives in the plugin.
28	The manifest `[hooks.<event>]` table is declaration-only today — the plugin's `hooks.json` + wrapper `.sh`
29	are what actually run.
30
31	**Proposal.** spt-core executes the adapter's handler for a hook event. The plugin's `hooks.json` pre-wires
32	**all** CC hook events to one generic stub:
33
34	```
35	# hooks.json (static-forever — every event, one line each)
36	<event> -> spt api run-hook claude-spt <event>      # stdin = the CC hook payload, verbatim
37	```
38
39	spt-core resolves the adapter's handler for that event and runs it, passing the hook stdin through and
40	surfacing any `additionalContext` back. The handler is adapter-conducted — ideally a subcommand of our
41	consolidated binary (`claude-spt hook <event>`, see Ask 3 / ADR-0006), so hook *logic* then rides
42	`spt adapter update` and `hooks.json` never changes again.
43
44	**Open questions for doyle:**
45	- Where does the handler live — the manifest `[hooks.<event>].fires` command (made executable, not just
46	  declarative), or a declared binary/subcommand spt-core invokes? Our preference: a binary subcommand.
47	- What's passed in (the raw CC hook JSON on stdin?) and how does `additionalContext` / the `can_inject`
48	  contract flow back out through `api run-hook`?
49	- Auth/session threading — same shape as the other id-scoped `api` calls (`--session-id`)?
50	- Does spt-core stay harness-agnostic here (it runs an opaque adapter-declared handler; it needn't know
51	  the event semantics)?
52
53	---
54
55	## Ask 2 — composite `[update]`: `gh_release` pull **+** a delegated post-step
56
57	**Problem.** `[update]` takes one `avenue` (`gh_release` XOR `delegated`). We need `gh_release` (to pull the
58	`.spt` = manifest + binaries + strings) **and** a delegated step (to run our cross-platform plugin-sync:
59	`claude plugin add|update <plugin>`) in the **same** `spt adapter update`. Today they're mutually exclusive.
60
61	**Proposal.** Let `gh_release` carry a post-update delegated command spt-core runs after the pull/re-register,
62	in the same invocation. Two sub-requirements:
63
64	- **2a — runs unconditionally.** The post-step must run **even when the adapter `.spt` version did not
65	  change** — the cplugs plugin can have a new version when the adapter didn't, and the user still wants one
66	  command to reconcile it.
67	- **2b — a "changed" return signals the message.** The post-step's return value can flag *applied/changed*
68	  so `spt adapter update` still prints `[update].message` (the `/reload-plugins` notice) even on an adapter
69	  no-op. (`message` today prints only when a new adapter version is applied — we need the post-step able to
70	  trigger it too.)
71
72	**Already confirmed (no ask):** `[update].message` exists (markdown, prints only on a real apply, no `{key}`
73	subst) and *"install is the first update"* — so this same flow makes `spt adapter add` bootstrap the plugin.
74
75	**Open questions for doyle:**
76	- Field shape — a `post_update` command on `gh_release`? a `[update.post]` sub-table? an ordered avenue list?
77	- The "changed" return convention — exit code? a sentinel on stdout?
78	- No-op suppression — if *neither* the adapter nor the post-step changed, `message` still suppresses?
79	- Trust — does the post-step inherit the `self_verifies`/attest model the `delegated` avenue already uses?
80
81	---
82
83	## Ask 3 — `[message-idle-translation-binary]` accepts a command/subcommand (not a bare `path`)
84
85	**Problem.** `[digest]`, `[session.*]`, and `[update]` take **command strings** (so they consolidate trivially
86	into `claude-spt <subcommand>`). `[message-idle-translation-binary]` takes a bare **`path`** — `path =
87	"claude-spt"` would spawn the binary with no args, so it can't tell it's in translate mode. This is the one
88	seam blocking us from folding the translation filter into the single consolidated binary (ADR-0006).
89
90	**Proposal.** Let the seam take a command (with args / `{key}` substitution) like the other seams — e.g.
91	`command = "claude-spt translate"` — keeping the existing stdin JSON-lines protocol unchanged. (A documented
92	"invoked with no args ⇒ translate mode" convention would also unblock us, but an explicit command is cleaner
93	and consistent with the other seams.)
94
95	**Open questions for doyle:**
96	- Preferred shape — promote `path` to an optional `command`, or add a sibling `command` field?
97	- Backward-compat for existing bare-`path` adapters (keep `path` working)?
98	- Does the spawn/stdin-protocol contract change at all, or is it purely how the executable is located?
99
100	---
101
102	## Heads-up (not an ask) — name unification
103
104	We're collapsing three names to two (ADR-0005): **`claude-spt`** = the spt-core-facing identity (we're
105	renaming the GitHub repo `spt-claude-code` → `claude-spt`, so `--release SaberMage/claude-spt` matches
106	`spt adapter update claude-spt`, and the consolidated binary is `claude-spt`); **`spt`** = the Claude-Code
107	plugin + skills (`/spt:*`, via the planned `sptc`→`spt` succession). The repo rename changes the derived
108	install dir (`adapters/_github/SaberMage-claude-spt`), so the `[update].repo` and any path assumptions on
109	your side should expect the new repo slug. One end user today, so the re-add cost is a non-issue.
110
111	---
112
113	## Dependency map (what unblocks what)
114
115	- **Ask 1** → hook logic + new handlers ride `spt adapter update`; `hooks.json` goes static-forever.
116	- **Ask 2** → the plugin update is automated; the only manual residual is `/reload-plugins`.
117	- **Ask 3** → `translate` folds into the one `claude-spt` binary (1 artifact/triple).
118	- Ships **without** any ask: `gh_release` + `[update].message` (the message instructs the manual steps),
119	  partial binary consolidation (digest/psyche/post-update), and the name unification.
120

# spt-core asks — one-command update, binary consolidation, name unification

> A grill prompt to take to doyle. Three capability asks + one heads-up, each framed as a
> proposal with the contract shape we want and the open questions for doyle to rule on. Context:
> ADR-0005 (name unification) and ADR-0006 (one-command update + consolidated binary) in this
> repo. Goal: a casual user keeps **all** of the adapter current with `spt adapter update claude-spt`
> (the only manual residual being `/reload-plugins`, which is an unavoidable Claude Code TUI action).
>
> Public-surface-only stance: these are capabilities we believe are missing from the published
> surface; we're asking, not reaching into spt-core. Each should land as an F-0xx finding once shaped.

## Framing for doyle

The adapter ships in two homes (ADR-0001): the spt-conducted **adapter** (`spt adapter update` — manifest
+ binaries + strings) and the low-churn **cplugs plugin skeleton** (`claude plugin update` — hooks.json,
hook wrapper logic, skill skeletons, `plugin.json`, bootstrap). The operator wants one lever. The wall:
**hook *logic* must physically live in the CC plugin dir** (CC loads hooks there), outside `spt adapter
update`'s reach. We re-checked raw-skills/commands as an escape and re-rejected them (CC subdir
command-namespacing is broken — anthropics/claude-code#2422; user-scope skills are flat). So the plugin
stays, and closing the gap needs the asks below.

---

## Ask 1 — generic hook dispatch: `spt api run-hook <adapter> <event>`

**Problem.** Every hook the adapter adds (this cycle's `PostToolUse` checkpoint detector) forces a cplugs
republish + `claude plugin update` + `/reload-plugins`, because the wrapper *logic* lives in the plugin.
The manifest `[hooks.<event>]` table is declaration-only today — the plugin's `hooks.json` + wrapper `.sh`
are what actually run.

**Proposal.** spt-core executes the adapter's handler for a hook event. The plugin's `hooks.json` pre-wires
**all** CC hook events to one generic stub:

```
# hooks.json (static-forever — every event, one line each)
<event> -> spt api run-hook claude-spt <event>      # stdin = the CC hook payload, verbatim
```

spt-core resolves the adapter's handler for that event and runs it, passing the hook stdin through and
surfacing any `additionalContext` back. The handler is adapter-conducted — ideally a subcommand of our
consolidated binary (`claude-spt hook <event>`, see Ask 3 / ADR-0006), so hook *logic* then rides
`spt adapter update` and `hooks.json` never changes again.

**Open questions for doyle:**
- Where does the handler live — the manifest `[hooks.<event>].fires` command (made executable, not just
  declarative), or a declared binary/subcommand spt-core invokes? Our preference: a binary subcommand.
- What's passed in (the raw CC hook JSON on stdin?) and how does `additionalContext` / the `can_inject`
  contract flow back out through `api run-hook`?
- Auth/session threading — same shape as the other id-scoped `api` calls (`--session-id`)?
- Does spt-core stay harness-agnostic here (it runs an opaque adapter-declared handler; it needn't know
  the event semantics)?

---

## Ask 2 — composite `[update]`: `gh_release` pull **+** a delegated post-step

**Problem.** `[update]` takes one `avenue` (`gh_release` XOR `delegated`). We need `gh_release` (to pull the
`.spt` = manifest + binaries + strings) **and** a delegated step (to run our cross-platform plugin-sync:
`claude plugin add|update <plugin>`) in the **same** `spt adapter update`. Today they're mutually exclusive.

**Proposal.** Let `gh_release` carry a post-update delegated command spt-core runs after the pull/re-register,
in the same invocation. Two sub-requirements:

- **2a — runs unconditionally.** The post-step must run **even when the adapter `.spt` version did not
  change** — the cplugs plugin can have a new version when the adapter didn't, and the user still wants one
  command to reconcile it.
- **2b — a "changed" return signals the message.** The post-step's return value can flag *applied/changed*
  so `spt adapter update` still prints `[update].message` (the `/reload-plugins` notice) even on an adapter
  no-op. (`message` today prints only when a new adapter version is applied — we need the post-step able to
  trigger it too.)

**Already confirmed (no ask):** `[update].message` exists (markdown, prints only on a real apply, no `{key}`
subst) and *"install is the first update"* — so this same flow makes `spt adapter add` bootstrap the plugin.

**Open questions for doyle:**
- Field shape — a `post_update` command on `gh_release`? a `[update.post]` sub-table? an ordered avenue list?
- The "changed" return convention — exit code? a sentinel on stdout?
- No-op suppression — if *neither* the adapter nor the post-step changed, `message` still suppresses?
- Trust — does the post-step inherit the `self_verifies`/attest model the `delegated` avenue already uses?

---

## Ask 3 — `[message-idle-translation-binary]` accepts a command/subcommand (not a bare `path`)

**Problem.** `[digest]`, `[session.*]`, and `[update]` take **command strings** (so they consolidate trivially
into `claude-spt <subcommand>`). `[message-idle-translation-binary]` takes a bare **`path`** — `path =
"claude-spt"` would spawn the binary with no args, so it can't tell it's in translate mode. This is the one
seam blocking us from folding the translation filter into the single consolidated binary (ADR-0006).

**Proposal.** Let the seam take a command (with args / `{key}` substitution) like the other seams — e.g.
`command = "claude-spt translate"` — keeping the existing stdin JSON-lines protocol unchanged. (A documented
"invoked with no args ⇒ translate mode" convention would also unblock us, but an explicit command is cleaner
and consistent with the other seams.)

**Open questions for doyle:**
- Preferred shape — promote `path` to an optional `command`, or add a sibling `command` field?
- Backward-compat for existing bare-`path` adapters (keep `path` working)?
- Does the spawn/stdin-protocol contract change at all, or is it purely how the executable is located?

---

## Heads-up (not an ask) — name unification

We're collapsing three names to two (ADR-0005): **`claude-spt`** = the spt-core-facing identity (we're
renaming the GitHub repo `spt-claude-code` → `claude-spt`, so `--release SaberMage/claude-spt` matches
`spt adapter update claude-spt`, and the consolidated binary is `claude-spt`); **`spt`** = the Claude-Code
plugin + skills (`/spt:*`, via the planned `sptc`→`spt` succession). The repo rename changes the derived
install dir (`adapters/_github/SaberMage-claude-spt`), so the `[update].repo` and any path assumptions on
your side should expect the new repo slug. One end user today, so the re-add cost is a non-issue.

---

## Dependency map (what unblocks what)

- **Ask 1** → hook logic + new handlers ride `spt adapter update`; `hooks.json` goes static-forever.
- **Ask 2** → the plugin update is automated; the only manual residual is `/reload-plugins`.
- **Ask 3** → `translate` folds into the one `claude-spt` binary (1 artifact/triple).
- Ships **without** any ask: `gh_release` + `[update].message` (the message instructs the manual steps),
  partial binary consolidation (digest/psyche/post-update), and the name unification.


1	# One-command-ish update + a single consolidated adapter binary
2
3	## Status
4
5	accepted (2026-06-24) — extends ADR-0001 (distribution splits by volatility). Some pieces depend on spt-core capabilities not yet shipped (the "doyle asks" below); those parts are decided in shape but gated on delivery.
6
7	## Context
8
9	ADR-0001 split distribution into a low-churn **cplugs skeleton** (hooks, skill skeletons, `plugin.json`, bootstrap — updated by `claude plugin update`) and an spt-conducted **adapter** (manifest + binaries + strings — updated by `spt adapter update`). The operator wants the whole thing kept current with effectively **one lever**, and wants install and update to feel **harmonious** (no hunting for the update command after install) and to work from the **CLI** (not only inside an endpoint session).
10
11	Two facts bound the design:
12
13	1. **Hook *logic* must live in the CC plugin dir** (CC loads hooks from there), outside `spt adapter update`'s reach. So "one command updates everything" is unreachable purely inside this repo — it needs spt-core capabilities → findings, not workarounds (public-surface-only).
14	2. **Raw skills/commands can't reliably replace the plugin.** Reopened and re-rejected: user-scope skills are flat (no namespace), and CC slash-command subdirectory namespacing is broken ([anthropics/claude-code#2422] — subdirs show in the description but don't namespace the invocation). The plugin is the only reliable `/spt:*` + the only clean hooks bundle. The eloquent thing to borrow from suite installers (e.g. gsd-core) is their **installer/onboarding UX**, not going raw.
15
16	## Decision
17
18	**Keep the plugin** (reaffirms ADR-0001). Make the update path one-lever-shaped and consolidate the adapter's binaries.
19
20	### Update mechanics
21
22	- **`avenue = "gh_release"`** pulls the adapter `.spt` (manifest + binaries + strings — all the high-churn). Ships against the published surface today.
23	- **`[update].message`** carries the residual manual step. This is a real, docs-confirmed field: a markdown-rendered notice `spt adapter update` prints to stdout **only when a new version is actually applied** (never on a no-op), no `{key}` substitution. It tells the user to run **`/reload-plugins`** — which is a **Claude Code TUI action and cannot be automated** — and mentions the `spt` CLI (alias for `spt endpoint run`) as the more powerful way to create an endpoint, alongside `/spt:live`.
24	- **"Install is the first update"** is docs-confirmed, so `spt adapter add` conducts the same `[update]` flow — one acquisition bootstraps the adapter.
25	- **Symmetric levers:** install = `spt adapter add --release SaberMage/claude-spt`, update = `spt adapter update claude-spt` (the verbs mirror). A README **copy-paste agent prompt** is an optional skin over the install command (the casual-user onboarding), with **platform-specific chains** (cmd / PowerShell / bash) that check-for / install spt-core (claude-spt may be a user's first exposure to spt-core) then `adapter add`.
26
27	### Binary consolidation
28
29	Collapse the adapter's executables into **one `claude-spt <subcommand>`** binary (name per ADR-0005), **partially now, fully later**:
30
31	- **Now** (no spt-core dependency — these seams take a command string): `claude-spt digest` (`[digest].extractor`), `claude-spt psyche` (`[session.psyche_init]`), `claude-spt post-update` (the delegated update step). Drops the fat `.spt` from 3 binaries/triple toward 1, dedupes deps, and retires the odd-one-out `cc-spt-idle-translate` name.
32	- **Later** (gated on doyle ask #3): fold in `claude-spt translate` once `[message-idle-translation-binary]` accepts a command/subcommand rather than a bare `path`; and `claude-spt hook <event>` if generic hook dispatch (ask #1) lands.
33
34	The **post-update step is cross-platform** because it is a compiled subcommand of this binary, **not** a `.sh` (Windows has no bash; a stray script would also stress spt-core's archive handling). It runs `claude plugin add|update <plugin>` + prints the notice; it cannot run `/reload-plugins` (TUI).
35
36	### The spt-core asks (findings to doyle — decided in shape, gated on delivery)
37
38	1. **Generic hook dispatch** — `spt api run-hook <adapter> <event>`: spt-core executes the adapter's handler for a hook event (from the manifest), so the plugin's `hooks.json` can pre-wire all events to one generic stub and hook *logic* rides `spt adapter update`. Eliminates the plugin-channel churn that adding this wave's PostToolUse hook forced.
39	2. **Composite `[update]`** — `gh_release` (pull the `.spt`) **plus** a delegated post-step in the same `spt adapter update`, so the plugin update is automated (the only manual residual becomes `/reload-plugins`). Two sub-requirements: the post-step must run **unconditionally** (the plugin can change when the adapter version did not), and its return value must be able to flag **"changed"** so `spt adapter update` still prints `[update].message` even on an adapter no-op.
40	3. **Translation seam takes a command** — `[message-idle-translation-binary]` accept a command/subcommand (or a default-on-no-args convention) instead of a bare `path`, so `translate` can fold into the consolidated binary.
41
42	## Consequences
43
44	- The thin-skeleton goal advances even before the asks land: skill bodies already ride strings; the **reactive skills** (`commune`/`send`/`signoff`, full-fat in the plugin because they are invoked without a typed slash-command) can be thinned to stubs by moving their bodies into the perched SessionStart brief (adapter strings) plus the `/spt:live` UPS body — with a known **delivery-timing wrinkle** (the perched brief fires on bind|boundary, not the instant a seed session goes live), tracked as a plan item, not blocking.
45	- Until asks #1/#3 land, hook logic and the translate binary stay on their current channels; the design degrades gracefully (the `message` field bridges the manual steps).
46	- One artifact per OS simplifies packaging but couples all seams' build/release — acceptable, they already ship in one `.spt`.
47

# One-command-ish update + a single consolidated adapter binary

## Status

accepted (2026-06-24) — extends ADR-0001 (distribution splits by volatility). Some pieces depend on spt-core capabilities not yet shipped (the "doyle asks" below); those parts are decided in shape but gated on delivery.

## Context

ADR-0001 split distribution into a low-churn **cplugs skeleton** (hooks, skill skeletons, `plugin.json`, bootstrap — updated by `claude plugin update`) and an spt-conducted **adapter** (manifest + binaries + strings — updated by `spt adapter update`). The operator wants the whole thing kept current with effectively **one lever**, and wants install and update to feel **harmonious** (no hunting for the update command after install) and to work from the **CLI** (not only inside an endpoint session).

Two facts bound the design:

1. **Hook *logic* must live in the CC plugin dir** (CC loads hooks from there), outside `spt adapter update`'s reach. So "one command updates everything" is unreachable purely inside this repo — it needs spt-core capabilities → findings, not workarounds (public-surface-only).
2. **Raw skills/commands can't reliably replace the plugin.** Reopened and re-rejected: user-scope skills are flat (no namespace), and CC slash-command subdirectory namespacing is broken ([anthropics/claude-code#2422] — subdirs show in the description but don't namespace the invocation). The plugin is the only reliable `/spt:*` + the only clean hooks bundle. The eloquent thing to borrow from suite installers (e.g. gsd-core) is their **installer/onboarding UX**, not going raw.

## Decision

**Keep the plugin** (reaffirms ADR-0001). Make the update path one-lever-shaped and consolidate the adapter's binaries.

### Update mechanics

- **`avenue = "gh_release"`** pulls the adapter `.spt` (manifest + binaries + strings — all the high-churn). Ships against the published surface today.
- **`[update].message`** carries the residual manual step. This is a real, docs-confirmed field: a markdown-rendered notice `spt adapter update` prints to stdout **only when a new version is actually applied** (never on a no-op), no `{key}` substitution. It tells the user to run **`/reload-plugins`** — which is a **Claude Code TUI action and cannot be automated** — and mentions the `spt` CLI (alias for `spt endpoint run`) as the more powerful way to create an endpoint, alongside `/spt:live`.
- **"Install is the first update"** is docs-confirmed, so `spt adapter add` conducts the same `[update]` flow — one acquisition bootstraps the adapter.
- **Symmetric levers:** install = `spt adapter add --release SaberMage/claude-spt`, update = `spt adapter update claude-spt` (the verbs mirror). A README **copy-paste agent prompt** is an optional skin over the install command (the casual-user onboarding), with **platform-specific chains** (cmd / PowerShell / bash) that check-for / install spt-core (claude-spt may be a user's first exposure to spt-core) then `adapter add`.

### Binary consolidation

Collapse the adapter's executables into **one `claude-spt <subcommand>`** binary (name per ADR-0005), **partially now, fully later**:

- **Now** (no spt-core dependency — these seams take a command string): `claude-spt digest` (`[digest].extractor`), `claude-spt psyche` (`[session.psyche_init]`), `claude-spt post-update` (the delegated update step). Drops the fat `.spt` from 3 binaries/triple toward 1, dedupes deps, and retires the odd-one-out `cc-spt-idle-translate` name.
- **Later** (gated on doyle ask #3): fold in `claude-spt translate` once `[message-idle-translation-binary]` accepts a command/subcommand rather than a bare `path`; and `claude-spt hook <event>` if generic hook dispatch (ask #1) lands.

The **post-update step is cross-platform** because it is a compiled subcommand of this binary, **not** a `.sh` (Windows has no bash; a stray script would also stress spt-core's archive handling). It runs `claude plugin add|update <plugin>` + prints the notice; it cannot run `/reload-plugins` (TUI).

### The spt-core asks (findings to doyle — decided in shape, gated on delivery)

1. **Generic hook dispatch** — `spt api run-hook <adapter> <event>`: spt-core executes the adapter's handler for a hook event (from the manifest), so the plugin's `hooks.json` can pre-wire all events to one generic stub and hook *logic* rides `spt adapter update`. Eliminates the plugin-channel churn that adding this wave's PostToolUse hook forced.
2. **Composite `[update]`** — `gh_release` (pull the `.spt`) **plus** a delegated post-step in the same `spt adapter update`, so the plugin update is automated (the only manual residual becomes `/reload-plugins`). Two sub-requirements: the post-step must run **unconditionally** (the plugin can change when the adapter version did not), and its return value must be able to flag **"changed"** so `spt adapter update` still prints `[update].message` even on an adapter no-op.
3. **Translation seam takes a command** — `[message-idle-translation-binary]` accept a command/subcommand (or a default-on-no-args convention) instead of a bare `path`, so `translate` can fold into the consolidated binary.

## Consequences

- The thin-skeleton goal advances even before the asks land: skill bodies already ride strings; the **reactive skills** (`commune`/`send`/`signoff`, full-fat in the plugin because they are invoked without a typed slash-command) can be thinned to stubs by moving their bodies into the perched SessionStart brief (adapter strings) plus the `/spt:live` UPS body — with a known **delivery-timing wrinkle** (the perched brief fires on bind|boundary, not the instant a seed session goes live), tracked as a plan item, not blocking.
- Until asks #1/#3 land, hook logic and the translate binary stay on their current channels; the design degrades gracefully (the `message` field bridges the manual steps).
- One artifact per OS simplifies packaging but couples all seams' build/release — acceptable, they already ship in one `.spt`.


ADRs 5/6 absorbed. Now ground the 6 operator asks against spt-core code + read ADR-0005 + CONTEXT.md. Parallel survey.


1	# Name unification: `claude-spt` (spt-core side) + `spt` (Claude Code side)
2
3	## Status
4
5	accepted (2026-06-24)
6
7	## Context
8
9	The project carried **three** names for one thing, plus a launcher shortcut:
10
11	| Identifier | Value | Where it shows |
12	|---|---|---|
13	| GitHub repo | `spt-claude-code` | `spt adapter add --release SaberMage/spt-claude-code`, `[update].repo`, install dir derivation |
14	| spt-core adapter | `claude-spt` | every `api --adapter claude-spt`, `[adapter].name`, `spt adapter update claude-spt` |
15	| cplugs plugin | `sptc` | `/sptc:*` skill prefix, `claude plugin … sptc@cplugs`, marketplace path |
16	| launcher shortcut | `cc` | `cc-<id>` (`spt endpoint run` brand) |
17
18	Three names for one adapter is friction — a user reads `--release SaberMage/spt-claude-code` to install but `spt adapter update claude-spt` to update, and `/sptc:*` to invoke. The hard constraint that prevents collapsing to **one** token: the adapter **cannot** be named `spt` (that is spt-core's own CLI/identity — `spt adapter update spt` reads as "spt updates spt"), yet the user-facing skill prefix **wants** `/spt:*` (the legacy-parity goal, already planned as the `sptc`→`spt` succession). The skill prefix and the adapter id genuinely want different tokens.
19
20	## Decision
21
22	Collapse three names to **two**, by domain:
23
24	- **spt-core-facing identity = `claude-spt`** — the **repo** (rename `spt-claude-code` → `claude-spt`), the **adapter** (unchanged), and the **consolidated binary** (see ADR-0006). After the rename, install and update both read `claude-spt`: `spt adapter add --release SaberMage/claude-spt` ↔ `spt adapter update claude-spt`.
25	- **Claude-Code-facing identity = `spt`** — the **plugin** and its **skills** (`/spt:*`), reached via the already-planned `sptc`→`spt` succession (a single `s/sptc/spt/` substitution), gated on retiring legacy owl's cplugs `spt` plugin (two plugins cannot share the name). Until owl retires, the plugin stays `sptc` / `/sptc:*`.
26	- **launcher shortcut stays `cc`** (`cc-<id>`) — decoupled from the plugin name, unchanged (per ADR-0001).
27
28	End state: `claude-spt` everywhere spt-core sees it; `spt` everywhere the Claude Code user types a skill; `cc` for the spawned-endpoint launcher.
29
30	## Considered and rejected
31
32	- **One token everywhere = `claude-spt`** (incl. `/claude-spt:*` skills). Maximally consistent and dependency-free, but makes the most-typed surface (the skill prefix) long. Rejected — the skill prefix should head to `/spt:*`.
33	- **One token everywhere = `sptc`** (`/sptc:*` unchanged). Shortest and dependency-free, but `sptc` is cryptic to a newcomer and abandons the cleaner `/spt:*` succession the project already committed to. Rejected.
34
35	## Consequences
36
37	- **The repo rename changes the adapter install dir** (`adapters/_github/SaberMage-spt-claude-code` → `…SaberMage-claude-spt`, derived from the repo path), so existing `--release` installs must be re-added. Acceptable: one end user today. GitHub redirects old links; `[update].repo`, the README install chains, CI, and the package scripts must be updated in the same move.
38	- Two names is the floor, not a failure to unify — it reflects a real constraint (adapter ≠ `spt`), recorded here so a future reader does not "simplify" the adapter to `spt` and collide with spt-core.
39	- The `spt` plugin succession keeps its existing gate (owl retirement); this ADR does not change that timing, only commits the target token split.
40

# Name unification: `claude-spt` (spt-core side) + `spt` (Claude Code side)

## Status

accepted (2026-06-24)

## Context

The project carried **three** names for one thing, plus a launcher shortcut:

| Identifier | Value | Where it shows |
|---|---|---|
| GitHub repo | `spt-claude-code` | `spt adapter add --release SaberMage/spt-claude-code`, `[update].repo`, install dir derivation |
| spt-core adapter | `claude-spt` | every `api --adapter claude-spt`, `[adapter].name`, `spt adapter update claude-spt` |
| cplugs plugin | `sptc` | `/sptc:*` skill prefix, `claude plugin … sptc@cplugs`, marketplace path |
| launcher shortcut | `cc` | `cc-<id>` (`spt endpoint run` brand) |

Three names for one adapter is friction — a user reads `--release SaberMage/spt-claude-code` to install but `spt adapter update claude-spt` to update, and `/sptc:*` to invoke. The hard constraint that prevents collapsing to **one** token: the adapter **cannot** be named `spt` (that is spt-core's own CLI/identity — `spt adapter update spt` reads as "spt updates spt"), yet the user-facing skill prefix **wants** `/spt:*` (the legacy-parity goal, already planned as the `sptc`→`spt` succession). The skill prefix and the adapter id genuinely want different tokens.

## Decision

Collapse three names to **two**, by domain:

- **spt-core-facing identity = `claude-spt`** — the **repo** (rename `spt-claude-code` → `claude-spt`), the **adapter** (unchanged), and the **consolidated binary** (see ADR-0006). After the rename, install and update both read `claude-spt`: `spt adapter add --release SaberMage/claude-spt` ↔ `spt adapter update claude-spt`.
- **Claude-Code-facing identity = `spt`** — the **plugin** and its **skills** (`/spt:*`), reached via the already-planned `sptc`→`spt` succession (a single `s/sptc/spt/` substitution), gated on retiring legacy owl's cplugs `spt` plugin (two plugins cannot share the name). Until owl retires, the plugin stays `sptc` / `/sptc:*`.
- **launcher shortcut stays `cc`** (`cc-<id>`) — decoupled from the plugin name, unchanged (per ADR-0001).

End state: `claude-spt` everywhere spt-core sees it; `spt` everywhere the Claude Code user types a skill; `cc` for the spawned-endpoint launcher.

## Considered and rejected

- **One token everywhere = `claude-spt`** (incl. `/claude-spt:*` skills). Maximally consistent and dependency-free, but makes the most-typed surface (the skill prefix) long. Rejected — the skill prefix should head to `/spt:*`.
- **One token everywhere = `sptc`** (`/sptc:*` unchanged). Shortest and dependency-free, but `sptc` is cryptic to a newcomer and abandons the cleaner `/spt:*` succession the project already committed to. Rejected.

## Consequences

- **The repo rename changes the adapter install dir** (`adapters/_github/SaberMage-spt-claude-code` → `…SaberMage-claude-spt`, derived from the repo path), so existing `--release` installs must be re-added. Acceptable: one end user today. GitHub redirects old links; `[update].repo`, the README install chains, CI, and the package scripts must be updated in the same move.
- Two names is the floor, not a failure to unify — it reflects a real constraint (adapter ≠ `spt`), recorded here so a future reader does not "simplify" the adapter to `spt` and collide with spt-core.
- The `spt` plugin succession keeps its existing gate (owl retirement); this ADR does not change that timing, only commits the target token split.


Agent

Survey spt send + reply-to

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), find how `spt send` is implemented. I need precise file:line detail on:
1. The `spt send` CLI command definition (clap args/flags) — especially any `--reply-to` flag. Where is it defined, what does it do, what type.
2. How `--reply-to` flows through to message delivery / the EVENT envelope. Does it set a reply target, a __REPLY_TO__ token, or anything in the wire format?
3. Any tests that assert `--reply-to` behavior (grep tests/ and ci/ for reply-to / reply_to / REPLY_TO).
4. Any docs (docs/, docs-site, reference.md) or `traceable-reqs.toml` REQ entries mentioning reply-to.
5. The EVENT envelope format definition (the `<EVENT type=msg from=...>` struct/serializer).

Report file:line citations and exact code snippets. Be very thorough — I need to know every site --reply-to touches so it can be removed cleanly.


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


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

Survey spt send + reply-to

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), find how `spt send` is implemented. I need precise file:line detail on:
1. The `spt send` CLI command definition (clap args/flags) — especially any `--reply-to` flag. Where is it defined, what does it do, what type.
2. How `--reply-to` flows through to message delivery / the EVENT envelope. Does it set a reply target, a __REPLY_TO__ token, or anything in the wire format?
3. Any tests that assert `--reply-to` behavior (grep tests/ and ci/ for reply-to / reply_to / REPLY_TO).
4. Any docs (docs/, docs-site, reference.md) or `traceable-reqs.toml` REQ entries mentioning reply-to.
5. The EVENT envelope format definition (the `<EVENT type=msg from=...>` struct/serializer).

Report file:line citations and exact code snippets. Be very thorough — I need to know every site --reply-to touches so it can be removed cleanly.


Survey digest command

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), find how `spt endpoint digest` is implemented and how digests are stored/extracted. I need precise file:line detail on:
1. The `spt endpoint digest` CLI command (clap def) — current flags/args, current output format (human text? lines?).
2. What a "digest" IS in this system — how digest entries are produced, stored, what a digest entry contains. Look for the `[digest]` extractor concept, ADR-0019 (digest extractor), and any digest storage (sqlite? files?).
3. Whether digest entries have a notion of line numbers, ordering, or "after" cursor.
4. Any existing `--json`, `--last`, `--after` flags anywhere in the endpoint subcommands for comparison.
5. The CC Stop hook / turn-end concept if referenced.
6. Relevant traceable-reqs.toml REQ entries for digest.

Report file:line citations + exact snippets. Thorough — I'm designing `spt endpoint digest --last <N> --json --after <line>`.


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

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

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


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

Survey digest command

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), find how `spt endpoint digest` is implemented and how digests are stored/extracted. I need precise file:line detail on:
1. The `spt endpoint digest` CLI command (clap def) — current flags/args, current output format (human text? lines?).
2. What a "digest" IS in this system — how digest entries are produced, stored, what a digest entry contains. Look for the `[digest]` extractor concept, ADR-0019 (digest extractor), and any digest storage (sqlite? files?).
3. Whether digest entries have a notion of line numbers, ordering, or "after" cursor.
4. Any existing `--json`, `--last`, `--after` flags anywhere in the endpoint subcommands for comparison.
5. The CC Stop hook / turn-end concept if referenced.
6. Relevant traceable-reqs.toml REQ entries for digest.

Report file:line citations + exact snippets. Thorough — I'm designing `spt endpoint digest --last <N> --json --after <line>`.


Survey status queries + json

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), enumerate all "status query" CLI commands and their output formatting. I need:
1. Every read-only/status command under `spt` and `spt endpoint` — e.g. `endpoint list`, `endpoint info`, `whoami`, `status`, `adapter list`, anything that prints state. List each with its file:line clap definition.
2. For each, how output is currently formatted (human-readable table/text vs any existing JSON). Is there ANY existing `--json` flag anywhere? Where?
3. Whether there's a shared output/formatting helper or each command formats ad-hoc.
4. The data structs behind these queries (what would be serialized to JSON) — are they serde-Serialize already?
5. Relevant traceable-reqs.toml REQ entries.

Report file:line citations + exact snippets. Thorough — I'm designing a `--json` flag spanning ALL status queries and need to know the surface area + whether a shared formatter exists.


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

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

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


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

Survey status queries + json

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), enumerate all "status query" CLI commands and their output formatting. I need:
1. Every read-only/status command under `spt` and `spt endpoint` — e.g. `endpoint list`, `endpoint info`, `whoami`, `status`, `adapter list`, anything that prints state. List each with its file:line clap definition.
2. For each, how output is currently formatted (human-readable table/text vs any existing JSON). Is there ANY existing `--json` flag anywhere? Where?
3. Whether there's a shared output/formatting helper or each command formats ad-hoc.
4. The data structs behind these queries (what would be serialized to JSON) — are they serde-Serialize already?
5. Relevant traceable-reqs.toml REQ entries.

Report file:line citations + exact snippets. Thorough — I'm designing a `--json` flag spanning ALL status queries and need to know the surface area + whether a shared formatter exists.


Survey endpoint run + rc terminal

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), two surfaces:

A) `spt endpoint run` (and the bare `spt` alias) empty-endpoint behavior:
1. The `spt endpoint run` CLI command def (file:line) and the bare `spt` alias mapping to it.
2. The endpoint PICKER logic — when invoked with no explicit endpoint, how it lists/picks. Where does it decide between picker vs the NEW endpoint creation flow?
3. The "new endpoint creation flow" code (ADR-0026 multi-subnet home-at-creation may be relevant). How is it triggered today?
4. Specifically: when the subnet (or node if no subnet) has ZERO endpoints, what happens today — does it show an empty picker or the creation flow?

B) `spt rc` terminal view / PTY rendering:
1. The `spt rc` command (file:line) — what it does (remote control / attach to a PTY?).
2. How the PTY terminal view is rendered to the user's terminal — is there any overlay/framing/status-line drawing, or is it a raw passthrough of the PTY bytes?
3. Any existing terminal-drawing / ANSI overlay / cursor-positioning code.
4. What identity info (subnet name, endpoint id, node name) is available at the `spt rc` call site.

Report file:line citations + exact snippets. Thorough.


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

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

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


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

Survey endpoint run + rc terminal

Prompt:
In the spt-core repo (C:\Users\decid\Documents\projects\spt-core), two surfaces:

A) `spt endpoint run` (and the bare `spt` alias) empty-endpoint behavior:
1. The `spt endpoint run` CLI command def (file:line) and the bare `spt` alias mapping to it.
2. The endpoint PICKER logic — when invoked with no explicit endpoint, how it lists/picks. Where does it decide between picker vs the NEW endpoint creation flow?
3. The "new endpoint creation flow" code (ADR-0026 multi-subnet home-at-creation may be relevant). How is it triggered today?
4. Specifically: when the subnet (or node if no subnet) has ZERO endpoints, what happens today — does it show an empty picker or the creation flow?

B) `spt rc` terminal view / PTY rendering:
1. The `spt rc` command (file:line) — what it does (remote control / attach to a PTY?).
2. How the PTY terminal view is rendered to the user's terminal — is there any overlay/framing/status-line drawing, or is it a raw passthrough of the PTY bytes?
3. Any existing terminal-drawing / ANSI overlay / cursor-positioning code.
4. What identity info (subnet name, endpoint id, node name) is available at the `spt rc` call site.

Report file:line citations + exact snippets. Thorough.


4 surveys running in background. While they work, read CONTEXT.md to ground the glossary (the grilling will challenge terms against it).


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

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