# `spt adapter add --github` Behavior

Based on the documentation provided, here's what I can determine:

## 1. Manifest Location

The docs don't specify whether `--github` searches subdirectories or expects the manifest at the repo root. The only reference states:

> "The registry target, distinct from any plugin/marketplace skeleton (the registry carries the manifest)."

This suggests a single canonical manifest location, but the exact path resolution strategy isn't documented in the provided content.

## 2. Extractor/Runner Binaries

The documentation indicates binaries are **resolved at runtime from PATH**, not shipped in the repo:

> "Command templates are opaque strings — spt-core fills `{key}` placeholders and runs them."

Your adapter directory is **copied into the registry** (`adapters/<adapter>/`), but whether extracted/runner binaries must be pre-built or available on PATH at invocation time isn't explicitly stated.

## 3. Exact CLI Usage

The only reference to `--github` syntax is:

> "`spt` adapter add --github <your-org>/<your-adapter-repo>`"

No subdir/path qualifier options are documented. A direct path form exists: `spt adapter add ./adapter` (local directory), but `--github` variant flags aren't specified.

## 4. Idempotency / Overwrite Behavior

The docs don't explicitly address re-registering an existing adapter. The general principle stated is:

> "spt-core validates it... nothing half-registers."

This suggests validation gates the operation, but whether re-add overwrites cleanly (idempotent) or rejects duplicates isn't documented in the provided content.


Critical facts surfaced: extractor=`claude-spt-digest`, runner=`claude-spt-psyche` (both in `tools/`, command templates resolve from **PATH** at runtime — not committed binaries). And `adapter add --github` manifest-location is **undocumented** (root vs subdir) — load-bearing since our manifest sits at `adapter/claude-spt.toml`. Probing the live binary's `adapter add` help to ground the plan.


Bash

export PATH="$HOME/AppData/Local/spt-core/bin:$PATH"; echo "=== adapter add --help ==="; spt adapter add --help 2>&1; echo; echo "=== current registry view ==="; spt adapter list 2>&1

Probe adapter add flags + registry state


=== adapter add --help ===
Register an adapter from a local path (a dir holding `manifest.toml`, or the manifest file itself)
or from GitHub (`--github user/repo`, cloned under `adapters/_github/`). Manifest-first: an invalid
manifest registers nothing. Install is the first update — the declared `[update]` avenue is
conducted once after recording

Usage: spt.exe adapter add [OPTIONS] [PATH]

Arguments:
  [PATH]  Local manifest source (omit when using --github)

Options:
      --github <GITHUB>  GitHub source `user/repo` — manifest-first, then install via the declared
                         `[update]` avenue
  -h, --help             Print help

=== current registry view ===
claude-spt: Harness Copy deregistered (from C:/Users/decid/Documents/projects/spt-claude-code/adapter)
  claude-spt:ccs (shipped)
  claude-spt:deep (shipped)
  claude-spt:live (shipped)
sptc-probe-f003: Harness Copy deregistered (from C:/Users/decid/AppData/Local/Temp/sptc-probe-f003)


Big one surfaced: `adapter add` expects a dir holding **`manifest.toml`** (or the manifest file pointed directly). Our manifest is `adapter/claude-spt.toml` — wrong name + in a subdir. And `--github` has **no subpath flag** (clones repo, looks at root). So `adapter add --github SaberMage/spt-claude-code` won't find it — the `--github` target needs the manifest at repo root. That's a load-bearing design fork for the plan. Confirming file names + existing REQs.


cd "C:/Users/decid/Documents/projects/spt-claude-code" && echo "=== adapter/ contents ==="; ls -la adapter/ 2>&1; echo "=== any manifest.toml in repo? ==="; find . -maxdepth 2 -name "manifest.toml" 2>/dev/null; echo "=== tools/ (extractor+runner source) ==="; ls tools/ 2>&1; echo "=== traceable-reqs.toml — setup/activate REQs ==="; grep -n -i -E "REQ-SETUP|REQ-.*ACTIV|REQ-DIST-BOOTSTRAP|id = \"REQ" traceable-reqs.toml | head -40

Check manifest filenames, tools, existing REQs


=== adapter/ contents ===
total 60
drwxr-xr-x 1 decid 197609     0 Jun 15 20:05 .
drwxr-xr-x 1 decid 197609     0 Jun 15 21:17 ..
-rw-r--r-- 1 decid 197609 18655 Jun 15 20:05 claude-spt.toml
-rw-r--r-- 1 decid 197609 25415 Jun 15 02:08 manifest.schema.json
drwxr-xr-x 1 decid 197609     0 Jun 15 03:13 strings
=== any manifest.toml in repo? ===
=== tools/ (extractor+runner source) ===
claude-spt-digest
claude-spt-psyche
=== traceable-reqs.toml — setup/activate REQs ===
44:# id = "REQ-EXAMPLE-1"
52:# id = "REQ-HAZARD-EXAMPLE"
62:id = "REQ-DIST-PLUGIN-SKELETON"
67:id = "REQ-DIST-BOOTSTRAP-INSTALL"
72:id = "REQ-DIST-HOOKS-API"
77:id = "REQ-DIST-MANIFEST-SCHEMA"
82:id = "REQ-DIST-SHORTCUT-BASENAME"
87:id = "REQ-DIST-DIGEST-EXTRACTOR"
92:id = "REQ-SKILL-LIVE"
97:id = "REQ-UPS-INJECTION"
106:id = "REQ-CI-GATES"
111:id = "REQ-CI-MANUAL"
116:id = "REQ-CI-TRIGGER"
121:id = "REQ-CI-BUS"
126:id = "REQ-CI-OWL-DISCOVERY"
131:id = "REQ-CI-ACCEPTANCE"
136:id = "REQ-HAZARD-PERCH-COLLISION"
141:id = "REQ-HAZARD-MSYS-PATHCONV"
149:id = "REQ-DOCS-SITE"
154:id = "REQ-DOCS-DRIFT"
159:id = "REQ-PARITY-AUDIT"
164:id = "REQ-SKILL-SUBNET"
169:id = "REQ-CCS-PROFILES"
184:id = "REQ-SKILL-VERSION"


proceed with B, which will be used to fulfill A thru dogfooding the plugin (i'll do it). this repo is published at https://github.com/SaberMage/spt-claude-code


Confirmed the blocker precisely:
- `adapter/` holds `claude-spt.toml` (not `manifest.toml`); no `manifest.toml` anywhere.
- `tools/` = `claude-spt-digest` + `claude-spt-psyche` (source; must be on PATH at runtime).
- No existing setup/activate REQ.

`--github` clones repo + looks for `manifest.toml` at **root**, no subpath flag → `SaberMage/spt-claude-code` (monorepo, manifest in `adapter/` subdir) **can't be the direct target as-is**. This is the load-bearing fork. Asking doyle the precise topology question (30-sec confirm — determines whether we need a dedicated adapter repo) while I draft the plan.


"$OWL" send doyle perri <<'EOF'
Quick one re: the F-005 activation bridge, grounded in `spt adapter add --help`:

Help says PATH = "a dir holding `manifest.toml`, or the manifest file itself"; `--github user/repo` clones under adapters/_github/ — no subpath flag shown.

Our dev repo (SaberMage/spt-claude-code) is a MONOREPO: manifest lives at `adapter/claude-spt.toml` (+ adapter/strings/), NOT at repo root, and not named manifest.toml. So `adapter add --github SaberMage/spt-claude-code` would look for manifest.toml at clone ROOT and miss.

Q1: does `--github user/repo` support pointing at a manifest in a SUBDIR (monorepo), or must manifest.toml be at the clone root? (No subpath option in --help — confirming it's root-only, not just undocumented.)
Q2: if root-only, what's the intended pattern for a dev monorepo whose adapter is a subdir — a DEDICATED adapter repo (root = manifest.toml + strings/), or a published orphan-branch/release-artifact whose root is the manifest? (This decides our repo topology for the end-user --github target.)
Q3: the copied "dir holding manifest.toml" — is it JUST the manifest's own dir, or the whole clone? (i.e. does a dedicated adapter-repo root get copied wholesale into adapters/<name>/?)

Local dev path is clear (`adapter add ./adapter/claude-spt.toml`, the file-itself form). This is only about the end-user --github distribution target. No rush.
EOF
echo "exit=$?"

Ask doyle the --github topology question


➜ SENT:doyle
exit=0


Now reading traceable-reqs format + the live-skill REQ as a template before minting `REQ-SETUP-ACTIVATE`.


56	# ── Milestone: SKELETON (thin cplugs plugin) — minted at kickoff, per-milestone (not
57	# the whole registry up front). All inactive (required_stages = []) so `check` stays
58	# green until body #2 lands evidence and flips each to ["doc"] / ["doc","impl"] etc.
59	# Seeded from SCOPE.md "Parity-trim" (Distribution + ADD buckets).
60
61	[[requirements]]
62	id = "REQ-DIST-PLUGIN-SKELETON"
63	title = "Marketplace artifact on cplugs is a thin skeleton: namespaced /sptc:* skill stubs + hooks.json + plugin.json, no embedded logic"
64	required_stages = ["doc", "impl", "unit"]  # doc: ADR-0001 + RELEASE-RUNBOOK. impl: ci/publish/{validate,package}-skeleton.sh (installability gate + publish mechanic). unit: tests/skeleton-validate.sh (pass real + fail tampered).
65
66	[[requirements]]
67	id = "REQ-DIST-BOOTSTRAP-INSTALL"
68	title = "SessionStart bootstrap installs spt-core when absent (invisible-installer pattern)"
69	required_stages = ["doc", "impl"]  # doc: ADR-0001. impl: plugin/sptc/bootstrap.{sh,ps1}.
70
71	[[requirements]]
72	id = "REQ-DIST-HOOKS-API"
73	title = "hooks.json delegates to `spt api` rather than carrying adapter logic"
74	required_stages = ["doc", "impl", "unit", "int"]  # doc: ADR-0001/0002. impl: hooks.json + wrappers. unit: tests/hooks-parse.sh. int: ci/hooks/poll-int.sh — `spt api poll` on live v0.7.1 emits the canonical <EVENT> envelope (ADR-0020), confirm-matched through render_frames; __REPLY_TO__ relic gone, multi-drain splits on </EVENT>. 5/5 green 2026-06-15 (throwaway perch, torn down).
75
76	[[requirements]]
77	id = "REQ-DIST-MANIFEST-SCHEMA"
78	title = "CC adapter manifest validates against spt-core's published manifest.schema.json (from spt-releases)"
79	required_stages = ["doc", "impl", "unit", "int"]  # doc: ADR-0001 (manifest layer + version-of-truth). impl: adapter/claude-spt.toml + vendored adapter/manifest.schema.json + ci/manifest/{validate_manifest.py,check-manifest.sh} (gate). unit: tests/manifest-schema.sh (pass real + fail tampered). int: ci/manifest/registration-int.sh — real `spt adapter add` (v0.7.0) cross-field registration-validation accepted the manifest, shipped profile resolved, [strings] read + overlay observable; 6/6 green 2026-06-15 (registry left clean via soft-remove). Cross-field discovery: [digest] requires source-or-[history].locate_template (not in JSON schema) — fixed with source="{home}/.claude/projects".
80
81	[[requirements]]
82	id = "REQ-DIST-SHORTCUT-BASENAME"
83	title = "The adapter manifest brands the `spt endpoint run` launcher shortcut as `cc-<id>` via adapter.shortcut_basename = \"cc\" (the M12 cc launcher; decoupled from the sptc plugin name, ADR-0001)"
84	required_stages = ["doc", "impl", "unit"]  # doc: ADR-0001 (cc launcher brand, decoupled from the s/sptc/spt/ plugin-name succession). impl: the cc-launcher BRINGUP machinery — adapter [session.self] (spawns `claude`) + [env.SPT_ENDPOINT_ID] (broker injects the endpoint id) + the SessionStart bind branch (sptc_register_verb -> `api bind`, the spt-hosted self-register path). unit: tests/manifest-shortcut.sh (brand-value guard) + tests/hooks-parse.sh sptc_register_verb (bind/seed/boundary branch). int (real `spt endpoint run` picker emits cc-<id> + real-claude bringup-bind) deferred — the shortcut-emitting picker "lands in a later spt-core wave" (per `endpoint run --help`); the bringup-bind is now contract-unblocked (doyle confirmed 2026-06-15: bind is establishing/intrinsic-auth, --set-session-id only, no token) but still needs a real-claude acceptance spawn (heavier tier). adapter add accepting the [session.self]/[env] blocks is covered by registration-int.sh step 4d (REQ-DIST-MANIFEST-SCHEMA int).
85
86	[[requirements]]
87	id = "REQ-DIST-DIGEST-EXTRACTOR"
88	title = "The claude-spt [digest] extractor (claude-spt-digest) maps Claude Code's JSONL transcript to the published digest-record NDJSON contract (role∈{input,agent,tool}; text/tool/ts), emitting RAW records for spt-core's renderer (ADR-0019)"
89	required_stages = ["impl", "unit", "int"]  # impl: tools/claude-spt-digest (Rust — CC JSONL -> digest NDJSON; per-session locate of <slug>/<session_id>.jsonl under the projects root via the {session_id} the command receives; native UTF-8 stdout; defensive ~ expansion) + ci/digest/build.sh gate. unit: the crate's cargo tests (9: input/agent/tool mapping, arg-key preference, thinking+tool_result+noise+bad-json drops, UTF-8 round-trip, contract invariants, tilde expansion) run by ci/digest/build.sh. int: ci/digest/digest-proof-int.sh — `spt adapter digest-proof claude-spt --sample` on live v0.7.2 ran the published-shape extractor command (`--session {session_id} --in {source}`) and rendered DIGEST_PROOF_OK (5 parsed / 0 dropped). GREEN 2026-06-15 (registry left clean via soft-remove). Was F-004-blocked (digest-proof --sample passed an empty substitution-key map, cli.rs:5135) — doyle's spt-core PR#14 fix (v0.7.2, release counter 14) now fills {id}+{session_id} + an optional --session, matching runtime. doc deferred (the mapping is documented in the module + manifest [digest] comment; a docs-site section lands with the doc slice).
90
91	[[requirements]]
92	id = "REQ-SKILL-LIVE"
93	title = "/sptc:live upgrades THIS CC session to a LiveAgent: the claude-spt:live profile overlays [session.psyche_init] (daemon spawns the Psyche), the claude-spt-psyche runner keeps the Psyche claude alive (one --continue turn per pulse, NOT one-shot `claude -p`), and the live body activates the :live composite + a resident Monitor relay as the single delivery pipe"
94	required_stages = ["doc", "impl", "unit"]  # doc: adapter/strings/skills/live.md (activation + poll/relay reconcile + Psyche-is-daemon-managed). impl: [profiles.live.session.psyche_init] in adapter/claude-spt.toml (the LiveAgent seam, 4 daemon keys) + tools/claude-spt-psyche (the resident runner). unit: claude-spt-psyche cargo tests (arg parse, seed/pulse/poll command construction, blank-pulse guard) run by ci/psyche/build.sh. int deferred: the daemon Psyche loop (lifecycle.rs run_pulse_loop) is STAGED behind the live-agent-adapter landing (brainproc.rs no-op today, REQ-DAEMON-1/M11-W0) and the Monitor relay needs a real live CC session — both are real-session acceptance, a heavier tier. The :live profile RESOLVING on the live binary is already covered by registration-int.sh (REQ-DIST-MANIFEST-SCHEMA int).
95
96	[[requirements]]
97	id = "REQ-UPS-INJECTION"
98	title = "UserPromptSubmit hook detects /sptc:X and injects X's real instructions as additionalContext (SKILL.md files stay skeletons); must be empirically confirmed UPS fires on slash-commands"
99	required_stages = ["doc", "impl", "unit", "int"]  # doc: ADR-0002. impl: user-prompt-submit.sh (skill-injection + drain) + _common.sh. unit: render_frames + sptc_skill_key tests. int: ci/hooks/poll-int.sh — the poll->additionalContext drain round-trip vs live v0.7.1 (<EVENT> envelope, render_frames confirm-match, multi-message). UPS-fires-on-slash empirical = ADR-0002 validation (CC 2.1.177); skill-injection resolve = registration-int 4c.
100
101	# ── Milestone: CI (autonomous fleet) — minted on-start. Deterministic gates + git push-trigger +
102	# spt reporting bus. Seeded from SCOPE.md "CI model" + docs/CI.md. Real-claude acceptance is a
103	# later slice (doc-only now). All harness-agnostic shell; runs on the Win+Linux fleet.
104
105	[[requirements]]
106	id = "REQ-CI-GATES"
107	title = "Deterministic gates (shell-syntax + unit tests + traceable-reqs check + manifest-schema + docs-drift), each a binary pass/fail, runnable as one command"
108	required_stages = ["doc", "impl", "unit"]
109
110	[[requirements]]
111	id = "REQ-CI-MANUAL"
112	title = "A manual 'run gates' command always exists — the same gate scripts runnable by hand on any fleet host"
113	required_stages = ["doc", "impl"]
114
115	[[requirements]]
116	id = "REQ-CI-TRIGGER"
117	title = "A git push hook fires the gates: pings a fleet runner-agent over spt rather than polling"
118	required_stages = ["doc", "impl"]
119
120	[[requirements]]
121	id = "REQ-CI-BUS"
122	title = "CI progress/results report over spt messaging (dogfood the product as its own CI nervous system)"
123	required_stages = ["doc", "impl"]
124
125	[[requirements]]
126	id = "REQ-CI-OWL-DISCOVERY"
127	title = "The spt messaging (bus) binary is located robustly at run time (per-version plugins path / PATH / configured) — never a hard-coded versioned path"
128	required_stages = ["doc", "impl", "unit"]
129
130	[[requirements]]
131	id = "REQ-CI-ACCEPTANCE"
132	title = "Acceptance = scripted orchestration spawning real claude/headless sessions as the system-under-test, asserting spt-state/digest output (LLM is SUT, never the runner)"
133	required_stages = ["doc", "impl", "int"]  # doc: docs/CI.md. impl: ci/acceptance/{lib,run-acceptance}.sh + harness unit. int: real `claude -p` spawn asserted UPS-hook-fires green 2026-06-15 under disposable id sptc-ci-40322 (operator perch perri survived — guard proven e2e).
134
135	[[requirements]]
136	id = "REQ-HAZARD-PERCH-COLLISION"
137	title = "The acceptance harness spawns every nested claude SUT under a DISPOSABLE identity (SPT_AGENT_ID=sptc-ci-<n>), never a live agent's perch id — a colliding id tears down the live agent's perch + poll stream (name-keyed, last-establish-wins)"
138	required_stages = ["unit"]  # unit: tests/acceptance-harness.sh. Diagnosed 2026-06-15 (operator): nested claude loading the spt plugin established a perch under "perri" and displaced the live poll stream.
139
140	[[requirements]]
141	id = "REQ-HAZARD-MSYS-PATHCONV"
142	title = "Hook wrappers read the CC payload from stdin, never from a /-leading positional argv (Git-Bash/MSYS path-mangles those on Windows)"
143	required_stages = ["unit"]  # unit: tests/msys-hazard.sh. Confirmed live 2026-06-15 (UPS validation run A).
144
145	# ── Milestone: DOCS-SITE (mdBook, drift-gated) — minted on-start. Dual-audience product docs
146	# in docs-site/, built with mdBook, gated against drift. Seeded from docs/DOCS-STRATEGY.md.
147
148	[[requirements]]
149	id = "REQ-DOCS-SITE"
150	title = "docs-site/ builds with mdBook from src/ (themed, Diátaxis-shaped, all-real-content — no placeholders)"
151	required_stages = ["doc", "impl"]  # doc: DOCS-STRATEGY. impl: docs-site/book.toml + src/ pages.
152
153	[[requirements]]
154	id = "REQ-DOCS-DRIFT"
155	title = "Generated docs (llms.txt) are CI-gated against drift: a deterministic generator's output must match what's checked in, and the book must build"
156	required_stages = ["doc", "impl", "unit"]  # doc: DOCS-STRATEGY #10. impl: ci/docs/{gen-llms,check-docs}.sh + run-gates wiring. unit: tests/docs-gen.sh.
157
158	[[requirements]]
159	id = "REQ-PARITY-AUDIT"
160	title = "The adapter's operative skill/profile surface is reconciled against the SCOPE.md LOCKED parity-trim (KEEP/ADD/DROP/TRANSFORM): every divergence is either resolved or logged as an accepted gap in docs/PARITY.md — the 'proven parity' record the sptc->spt succession flip gates on"

# ── Milestone: SKELETON (thin cplugs plugin) — minted at kickoff, per-milestone (not
# the whole registry up front). All inactive (required_stages = []) so `check` stays
# green until body #2 lands evidence and flips each to ["doc"] / ["doc","impl"] etc.
# Seeded from SCOPE.md "Parity-trim" (Distribution + ADD buckets).

[[requirements]]
id = "REQ-DIST-PLUGIN-SKELETON"
title = "Marketplace artifact on cplugs is a thin skeleton: namespaced /sptc:* skill stubs + hooks.json + plugin.json, no embedded logic"
required_stages = ["doc", "impl", "unit"]  # doc: ADR-0001 + RELEASE-RUNBOOK. impl: ci/publish/{validate,package}-skeleton.sh (installability gate + publish mechanic). unit: tests/skeleton-validate.sh (pass real + fail tampered).

[[requirements]]
id = "REQ-DIST-BOOTSTRAP-INSTALL"
title = "SessionStart bootstrap installs spt-core when absent (invisible-installer pattern)"
required_stages = ["doc", "impl"]  # doc: ADR-0001. impl: plugin/sptc/bootstrap.{sh,ps1}.

[[requirements]]
id = "REQ-DIST-HOOKS-API"
title = "hooks.json delegates to `spt api` rather than carrying adapter logic"
required_stages = ["doc", "impl", "unit", "int"]  # doc: ADR-0001/0002. impl: hooks.json + wrappers. unit: tests/hooks-parse.sh. int: ci/hooks/poll-int.sh — `spt api poll` on live v0.7.1 emits the canonical <EVENT> envelope (ADR-0020), confirm-matched through render_frames; __REPLY_TO__ relic gone, multi-drain splits on </EVENT>. 5/5 green 2026-06-15 (throwaway perch, torn down).

[[requirements]]
id = "REQ-DIST-MANIFEST-SCHEMA"
title = "CC adapter manifest validates against spt-core's published manifest.schema.json (from spt-releases)"
required_stages = ["doc", "impl", "unit", "int"]  # doc: ADR-0001 (manifest layer + version-of-truth). impl: adapter/claude-spt.toml + vendored adapter/manifest.schema.json + ci/manifest/{validate_manifest.py,check-manifest.sh} (gate). unit: tests/manifest-schema.sh (pass real + fail tampered). int: ci/manifest/registration-int.sh — real `spt adapter add` (v0.7.0) cross-field registration-validation accepted the manifest, shipped profile resolved, [strings] read + overlay observable; 6/6 green 2026-06-15 (registry left clean via soft-remove). Cross-field discovery: [digest] requires source-or-[history].locate_template (not in JSON schema) — fixed with source="{home}/.claude/projects".

[[requirements]]
id = "REQ-DIST-SHORTCUT-BASENAME"
title = "The adapter manifest brands the `spt endpoint run` launcher shortcut as `cc-<id>` via adapter.shortcut_basename = \"cc\" (the M12 cc launcher; decoupled from the sptc plugin name, ADR-0001)"
required_stages = ["doc", "impl", "unit"]  # doc: ADR-0001 (cc launcher brand, decoupled from the s/sptc/spt/ plugin-name succession). impl: the cc-launcher BRINGUP machinery — adapter [session.self] (spawns `claude`) + [env.SPT_ENDPOINT_ID] (broker injects the endpoint id) + the SessionStart bind branch (sptc_register_verb -> `api bind`, the spt-hosted self-register path). unit: tests/manifest-shortcut.sh (brand-value guard) + tests/hooks-parse.sh sptc_register_verb (bind/seed/boundary branch). int (real `spt endpoint run` picker emits cc-<id> + real-claude bringup-bind) deferred — the shortcut-emitting picker "lands in a later spt-core wave" (per `endpoint run --help`); the bringup-bind is now contract-unblocked (doyle confirmed 2026-06-15: bind is establishing/intrinsic-auth, --set-session-id only, no token) but still needs a real-claude acceptance spawn (heavier tier). adapter add accepting the [session.self]/[env] blocks is covered by registration-int.sh step 4d (REQ-DIST-MANIFEST-SCHEMA int).

[[requirements]]
id = "REQ-DIST-DIGEST-EXTRACTOR"
title = "The claude-spt [digest] extractor (claude-spt-digest) maps Claude Code's JSONL transcript to the published digest-record NDJSON contract (role∈{input,agent,tool}; text/tool/ts), emitting RAW records for spt-core's renderer (ADR-0019)"
required_stages = ["impl", "unit", "int"]  # impl: tools/claude-spt-digest (Rust — CC JSONL -> digest NDJSON; per-session locate of <slug>/<session_id>.jsonl under the projects root via the {session_id} the command receives; native UTF-8 stdout; defensive ~ expansion) + ci/digest/build.sh gate. unit: the crate's cargo tests (9: input/agent/tool mapping, arg-key preference, thinking+tool_result+noise+bad-json drops, UTF-8 round-trip, contract invariants, tilde expansion) run by ci/digest/build.sh. int: ci/digest/digest-proof-int.sh — `spt adapter digest-proof claude-spt --sample` on live v0.7.2 ran the published-shape extractor command (`--session {session_id} --in {source}`) and rendered DIGEST_PROOF_OK (5 parsed / 0 dropped). GREEN 2026-06-15 (registry left clean via soft-remove). Was F-004-blocked (digest-proof --sample passed an empty substitution-key map, cli.rs:5135) — doyle's spt-core PR#14 fix (v0.7.2, release counter 14) now fills {id}+{session_id} + an optional --session, matching runtime. doc deferred (the mapping is documented in the module + manifest [digest] comment; a docs-site section lands with the doc slice).

[[requirements]]
id = "REQ-SKILL-LIVE"
title = "/sptc:live upgrades THIS CC session to a LiveAgent: the claude-spt:live profile overlays [session.psyche_init] (daemon spawns the Psyche), the claude-spt-psyche runner keeps the Psyche claude alive (one --continue turn per pulse, NOT one-shot `claude -p`), and the live body activates the :live composite + a resident Monitor relay as the single delivery pipe"
required_stages = ["doc", "impl", "unit"]  # doc: adapter/strings/skills/live.md (activation + poll/relay reconcile + Psyche-is-daemon-managed). impl: [profiles.live.session.psyche_init] in adapter/claude-spt.toml (the LiveAgent seam, 4 daemon keys) + tools/claude-spt-psyche (the resident runner). unit: claude-spt-psyche cargo tests (arg parse, seed/pulse/poll command construction, blank-pulse guard) run by ci/psyche/build.sh. int deferred: the daemon Psyche loop (lifecycle.rs run_pulse_loop) is STAGED behind the live-agent-adapter landing (brainproc.rs no-op today, REQ-DAEMON-1/M11-W0) and the Monitor relay needs a real live CC session — both are real-session acceptance, a heavier tier. The :live profile RESOLVING on the live binary is already covered by registration-int.sh (REQ-DIST-MANIFEST-SCHEMA int).

[[requirements]]
id = "REQ-UPS-INJECTION"
title = "UserPromptSubmit hook detects /sptc:X and injects X's real instructions as additionalContext (SKILL.md files stay skeletons); must be empirically confirmed UPS fires on slash-commands"
required_stages = ["doc", "impl", "unit", "int"]  # doc: ADR-0002. impl: user-prompt-submit.sh (skill-injection + drain) + _common.sh. unit: render_frames + sptc_skill_key tests. int: ci/hooks/poll-int.sh — the poll->additionalContext drain round-trip vs live v0.7.1 (<EVENT> envelope, render_frames confirm-match, multi-message). UPS-fires-on-slash empirical = ADR-0002 validation (CC 2.1.177); skill-injection resolve = registration-int 4c.

# ── Milestone: CI (autonomous fleet) — minted on-start. Deterministic gates + git push-trigger +
# spt reporting bus. Seeded from SCOPE.md "CI model" + docs/CI.md. Real-claude acceptance is a
# later slice (doc-only now). All harness-agnostic shell; runs on the Win+Linux fleet.

[[requirements]]
id = "REQ-CI-GATES"
title = "Deterministic gates (shell-syntax + unit tests + traceable-reqs check + manifest-schema + docs-drift), each a binary pass/fail, runnable as one command"
required_stages = ["doc", "impl", "unit"]

[[requirements]]
id = "REQ-CI-MANUAL"
title = "A manual 'run gates' command always exists — the same gate scripts runnable by hand on any fleet host"
required_stages = ["doc", "impl"]

[[requirements]]
id = "REQ-CI-TRIGGER"
title = "A git push hook fires the gates: pings a fleet runner-agent over spt rather than polling"
required_stages = ["doc", "impl"]

[[requirements]]
id = "REQ-CI-BUS"
title = "CI progress/results report over spt messaging (dogfood the product as its own CI nervous system)"
required_stages = ["doc", "impl"]

[[requirements]]
id = "REQ-CI-OWL-DISCOVERY"
title = "The spt messaging (bus) binary is located robustly at run time (per-version plugins path / PATH / configured) — never a hard-coded versioned path"
required_stages = ["doc", "impl", "unit"]

[[requirements]]
id = "REQ-CI-ACCEPTANCE"
title = "Acceptance = scripted orchestration spawning real claude/headless sessions as the system-under-test, asserting spt-state/digest output (LLM is SUT, never the runner)"
required_stages = ["doc", "impl", "int"]  # doc: docs/CI.md. impl: ci/acceptance/{lib,run-acceptance}.sh + harness unit. int: real `claude -p` spawn asserted UPS-hook-fires green 2026-06-15 under disposable id sptc-ci-40322 (operator perch perri survived — guard proven e2e).

[[requirements]]
id = "REQ-HAZARD-PERCH-COLLISION"
title = "The acceptance harness spawns every nested claude SUT under a DISPOSABLE identity (SPT_AGENT_ID=sptc-ci-<n>), never a live agent's perch id — a colliding id tears down the live agent's perch + poll stream (name-keyed, last-establish-wins)"
required_stages = ["unit"]  # unit: tests/acceptance-harness.sh. Diagnosed 2026-06-15 (operator): nested claude loading the spt plugin established a perch under "perri" and displaced the live poll stream.

[[requirements]]
id = "REQ-HAZARD-MSYS-PATHCONV"
title = "Hook wrappers read the CC payload from stdin, never from a /-leading positional argv (Git-Bash/MSYS path-mangles those on Windows)"
required_stages = ["unit"]  # unit: tests/msys-hazard.sh. Confirmed live 2026-06-15 (UPS validation run A).

# ── Milestone: DOCS-SITE (mdBook, drift-gated) — minted on-start. Dual-audience product docs
# in docs-site/, built with mdBook, gated against drift. Seeded from docs/DOCS-STRATEGY.md.

[[requirements]]
id = "REQ-DOCS-SITE"
title = "docs-site/ builds with mdBook from src/ (themed, Diátaxis-shaped, all-real-content — no placeholders)"
required_stages = ["doc", "impl"]  # doc: DOCS-STRATEGY. impl: docs-site/book.toml + src/ pages.

[[requirements]]
id = "REQ-DOCS-DRIFT"
title = "Generated docs (llms.txt) are CI-gated against drift: a deterministic generator's output must match what's checked in, and the book must build"
required_stages = ["doc", "impl", "unit"]  # doc: DOCS-STRATEGY #10. impl: ci/docs/{gen-llms,check-docs}.sh + run-gates wiring. unit: tests/docs-gen.sh.

[[requirements]]
id = "REQ-PARITY-AUDIT"
title = "The adapter's operative skill/profile surface is reconciled against the SCOPE.md LOCKED parity-trim (KEEP/ADD/DROP/TRANSFORM): every divergence is either resolved or logged as an accepted gap in docs/PARITY.md — the 'proven parity' record the sptc->spt succession flip gates on"


Have the format + all facts. Writing the JIT plan now (build waits on doyle's topology answer — won't hardcode a guessed `--github` target). Adding the REQ first per traceability rule 3.


158	[[requirements]]
159	id = "REQ-PARITY-AUDIT"
160	title = "The adapter's operative skill/profile surface is reconciled against the SCOPE.md LOCKED parity-trim (KEEP/ADD/DROP/TRANSFORM): every divergence is either resolved or logged as an accepted gap in docs/PARITY.md — the 'proven parity' record the sptc->spt succession flip gates on"
161	required_stages = ["doc"]  # doc: docs/PARITY.md (the parity matrix + per-row evidence/finding). Pure reconciliation record (no code of its own); the per-surface impl/unit evidence lives on the surface's own REQ (REQ-SKILL-SUBNET, REQ-CCS-PROFILES, REQ-SKILL-LIVE, etc.).
162
163	[[requirements]]
164	id = "REQ-SKILL-SUBNET"
165	title = "The adapter ships subnet membership skill(s) (create/join/show-code) wrapping the published `spt subnet <verb>` surface — the LOCKED-ADD cross-subnet entrypoint (v1 topology is mandatory, SCOPE)"
166	required_stages = ["doc", "int"]  # doc: adapter/strings/skills/subnet.md (one /sptc:subnet skill covering status/create/show-code/join — mirrors the single `spt subnet` verb-family CLI). int: ci/manifest/registration-int.sh file-backed-resolve assertion (skills.subnet -> body) on live spt — the wiring proof. No separate `impl`/`unit` stage: a file-backed skill has no unit-testable code of its own (the manifest [strings.skills].subnet pointer + plugin stub are config, and the int proves they resolve end-to-end through the live registry — same model as the commune/force-stop skills, which carry no per-skill impl). (No `spt how-to subnet` topic exists — minor published-guidance gap noted in docs/SPT-CORE-FINDINGS.md; the skill wraps `spt subnet --help` as canonical.)
167
168	[[requirements]]
169	id = "REQ-CCS-PROFILES"
170	title = "The adapter ships a ccs profile template (claude-spt:ccs) — LOCKED-ADD overlay that retargets the spawn command template through `ccs` (a drop-in for the `claude` binary) and honors ccs's relocated CLAUDE_CONFIG_DIR transcript root in the digest extractor; templates only (user supplies their own ccs config/keys)"
171	# Scoped to the default-profile shape the operator actually runs: `ccs` (bare), the account set via
172	# `ccs auth default <name>`, NOT glm/kimi (those were SCOPE *examples*; this profile IS the example +
173	# the operator's own SPT use). Validated against the known-good sister project claude_skill_owl:
174	# (1) ccs is a drop-in for the `claude` binary, same argv (live/wrapper/claude.rs Tier-2 latch);
175	# (2) ccs relocates Claude Code's state tree via CLAUDE_CONFIG_DIR, resolved IN-BINARY by
176	# owlery::claude_projects_root ($CLAUDE_CONFIG_DIR/projects || $HOME/.claude/projects).
177	# impl/unit = the CLAUDE_CONFIG_DIR-aware projects-root resolver in claude-spt-digest (a .toml
178	# profile leaf does NOT register as impl evidence; the real impl is the env-aware extractor).
179	# doc = manifest [profiles.ccs] overlay + docs/PARITY.md. int = registration-int profile-resolves
180	# assertion (claude-spt:ccs resolves + adapter_label overlay observable; mirrors :deep/:live).
181	required_stages = ["doc", "impl", "unit", "int"]
182
183	[[requirements]]
184	id = "REQ-SKILL-VERSION"
185	title = "/spt:version reports the spt-core-tracked manifest/binary version (the version-of-truth, not the marketplace skeleton version)"
186	required_stages = []
187

[[requirements]]
id = "REQ-PARITY-AUDIT"
title = "The adapter's operative skill/profile surface is reconciled against the SCOPE.md LOCKED parity-trim (KEEP/ADD/DROP/TRANSFORM): every divergence is either resolved or logged as an accepted gap in docs/PARITY.md — the 'proven parity' record the sptc->spt succession flip gates on"
required_stages = ["doc"]  # doc: docs/PARITY.md (the parity matrix + per-row evidence/finding). Pure reconciliation record (no code of its own); the per-surface impl/unit evidence lives on the surface's own REQ (REQ-SKILL-SUBNET, REQ-CCS-PROFILES, REQ-SKILL-LIVE, etc.).

[[requirements]]
id = "REQ-SKILL-SUBNET"
title = "The adapter ships subnet membership skill(s) (create/join/show-code) wrapping the published `spt subnet <verb>` surface — the LOCKED-ADD cross-subnet entrypoint (v1 topology is mandatory, SCOPE)"
required_stages = ["doc", "int"]  # doc: adapter/strings/skills/subnet.md (one /sptc:subnet skill covering status/create/show-code/join — mirrors the single `spt subnet` verb-family CLI). int: ci/manifest/registration-int.sh file-backed-resolve assertion (skills.subnet -> body) on live spt — the wiring proof. No separate `impl`/`unit` stage: a file-backed skill has no unit-testable code of its own (the manifest [strings.skills].subnet pointer + plugin stub are config, and the int proves they resolve end-to-end through the live registry — same model as the commune/force-stop skills, which carry no per-skill impl). (No `spt how-to subnet` topic exists — minor published-guidance gap noted in docs/SPT-CORE-FINDINGS.md; the skill wraps `spt subnet --help` as canonical.)

[[requirements]]
id = "REQ-CCS-PROFILES"
title = "The adapter ships a ccs profile template (claude-spt:ccs) — LOCKED-ADD overlay that retargets the spawn command template through `ccs` (a drop-in for the `claude` binary) and honors ccs's relocated CLAUDE_CONFIG_DIR transcript root in the digest extractor; templates only (user supplies their own ccs config/keys)"
# Scoped to the default-profile shape the operator actually runs: `ccs` (bare), the account set via
# `ccs auth default <name>`, NOT glm/kimi (those were SCOPE *examples*; this profile IS the example +
# the operator's own SPT use). Validated against the known-good sister project claude_skill_owl:
# (1) ccs is a drop-in for the `claude` binary, same argv (live/wrapper/claude.rs Tier-2 latch);
# (2) ccs relocates Claude Code's state tree via CLAUDE_CONFIG_DIR, resolved IN-BINARY by
# owlery::claude_projects_root ($CLAUDE_CONFIG_DIR/projects || $HOME/.claude/projects).
# impl/unit = the CLAUDE_CONFIG_DIR-aware projects-root resolver in claude-spt-digest (a .toml
# profile leaf does NOT register as impl evidence; the real impl is the env-aware extractor).
# doc = manifest [profiles.ccs] overlay + docs/PARITY.md. int = registration-int profile-resolves
# assertion (claude-spt:ccs resolves + adapter_label overlay observable; mirrors :deep/:live).
required_stages = ["doc", "impl", "unit", "int"]

[[requirements]]
id = "REQ-SKILL-VERSION"
title = "/spt:version reports the spt-core-tracked manifest/binary version (the version-of-truth, not the marketplace skeleton version)"
required_stages = []


<system-reminder>Warning: the file exists but is shorter than the provided offset (187). The file has 187 lines.</system-reminder>


Edit

[[requirements]]
id = "REQ-SKILL-VERSION"
title = "/spt:version reports the spt-core-tracked manifest/binary version (the version-of-truth, not the marketplace skeleton version)"
required_stages = []

[[requirements]]
id = "REQ-SKILL-VERSION"
title = "/spt:version reports the spt-core-tracked manifest/binary version (the version-of-truth, not the marketplace skeleton version)"
required_stages = []

# ── Milestone: SETUP-SLICE (the /sptc:setup activation bridge + LOCKED v1 setup paths) — minted
# 2026-06-15, seeded from SCOPE.md §"/spt:setup" (LOCKED v1 = {1..7}) + finding F-005 (the
# post-install adapter ACTIVATION step). Inactive (required_stages = []) until the slice executes —
# REQ-SETUP-ACTIVATE activates to ["doc","impl","int"] (Wave 1); the {1..7} feature paths get their
# own REQs as each later wave starts. The end-user --github activation target is blocked on doyle's
# topology ruling (Q1-Q3, owl 2026-06-15) — see SETUP-SLICE-PLAN.md.

[[requirements]]
id = "REQ-SETUP-ACTIVATE"
title = "/sptc:setup, after confirming the spt binary is present, ACTIVATES the claude-spt adapter (`spt adapter add` — the manifest file in local dev; `--github <published-adapter-repo>` for end-users) so profiles/strings/hints/[digest] go live, then verifies (adapter no longer `deregistered`). Binary-present is NOT a no-op — this is the F-005 post-install activation bridge."
required_stages = []  # SEEDED inactive (activate-don't-pre-fail). Activates ["doc","impl","int"] when the setup-slice Wave 1 executes: doc = adapter/strings/skills/setup.md + plugin SKILL.md (the activation branch); impl = the `spt adapter add` activation step + verify; int = a registration re-activate assertion (deregistered -> active, profiles resolve). Blocked-open: the end-user `--github` target repo topology (doyle Q1-Q3 pending) — local-dir activation is unblocked.


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

[[requirements]]
id = "REQ-SKILL-VERSION"
title = "/spt:version reports the spt-core-tracked manifest/binary version (the version-of-truth, not the marketplace skeleton version)"
required_stages = []

# ── Milestone: SETUP-SLICE (the /sptc:setup activation bridge + LOCKED v1 setup paths) — minted
# 2026-06-15, seeded from SCOPE.md §"/spt:setup" (LOCKED v1 = {1..7}) + finding F-005 (the
# post-install adapter ACTIVATION step). Inactive (required_stages = []) until the slice executes —
# REQ-SETUP-ACTIVATE activates to ["doc","impl","int"] (Wave 1); the {1..7} feature paths get their
# own REQs as each later wave starts. The end-user --github activation target is blocked on doyle's
# topology ruling (Q1-Q3, owl 2026-06-15) — see SETUP-SLICE-PLAN.md.

[[requirements]]
id = "REQ-SETUP-ACTIVATE"
title = "/sptc:setup, after confirming the spt binary is present, ACTIVATES the claude-spt adapter (`spt adapter add` — the manifest file in local dev; `--github <published-adapter-repo>` for end-users) so profiles/strings/hints/[digest] go live, then verifies (adapter no longer `deregistered`). Binary-present is NOT a no-op — this is the F-005 post-install activation bridge."
required_stages = []  # SEEDED inactive (activate-don't-pre-fail). Activates ["doc","impl","int"] when the setup-slice Wave 1 executes: doc = adapter/strings/skills/setup.md + plugin SKILL.md (the activation branch); impl = the `spt adapter add` activation step + verify; int = a registration re-activate assertion (deregistered -> active, profiles resolve). Blocked-open: the end-user `--github` target repo topology (doyle Q1-Q3 pending) — local-dir activation is unblocked.

+# ── Milestone: SETUP-SLICE (the /sptc:setup activation bridge + LOCKED v1 setup paths) — minted

+# 2026-06-15, seeded from SCOPE.md §"/spt:setup" (LOCKED v1 = {1..7}) + finding F-005 (the

+# post-install adapter ACTIVATION step). Inactive (required_stages = []) until the slice executes —

+# REQ-SETUP-ACTIVATE activates to ["doc","impl","int"] (Wave 1); the {1..7} feature paths get their

+# own REQs as each later wave starts. The end-user --github activation target is blocked on doyle's

+# topology ruling (Q1-Q3, owl 2026-06-15) — see SETUP-SLICE-PLAN.md.

+title = "/sptc:setup, after confirming the spt binary is present, ACTIVATES the claude-spt adapter (`spt adapter add` — the manifest file in local dev; `--github <published-adapter-repo>` for end-users) so profiles/strings/hints/[digest] go live, then verifies (adapter no longer `deregistered`). Binary-present is NOT a no-op — this is the F-005 post-install activation bridge."

+required_stages = []  # SEEDED inactive (activate-don't-pre-fail). Activates ["doc","impl","int"] when the setup-slice Wave 1 executes: doc = adapter/strings/skills/setup.md + plugin SKILL.md (the activation branch); impl = the `spt adapter add` activation step + verify; int = a registration re-activate assertion (deregistered -> active, profiles resolve). Blocked-open: the end-user `--github` target repo topology (doyle Q1-Q3 pending) — local-dir activation is unblocked.


Now the JIT plan.


Write

# JIT plan — `/sptc:setup` activation bridge (F-005) → grow toward LOCKED v1 setup {1–7}

> Next slice after the cplugs first-publish (b1e2895). Goal: make `/sptc:setup` actually
> **activate** the claude-spt adapter after the binary check (the F-005 post-install bridge), so a
> freshly-installed plugin yields a *registered & active* adapter — not a `deregistered` one. Then
> stage the richer LOCKED v1 setup paths (`SCOPE.md` §"/spt:setup" = {1..7}) as later waves.
> Public-surface-only still binds (AGENTS.md).

## Why (the dogfooding finding, 2026-06-15)

An agent ran `/sptc:setup` on a fresh install: `spt 0.7.2` present → skill reported "No install
needed" and **stopped**. But `spt adapter list` showed **`claude-spt: … deregistered`** — the
adapter surface (profiles/strings/hints/`[digest]`) was inert, `/sptc:*` UPS-injection had nothing
to source. **Binary present ≠ adapter active.** doyle triaged F-005 (docs/SPT-CORE-FINDINGS.md) and
confirmed the missing step: after the binary check, setup must run
**`spt adapter add [--github <repo>]`** to ACTIVATE. The current skill has no such step, and (Point
2, operator) no already-installed branch at all — it is a degenerate installer-floor stub far below
the LOCKED v1 `{1..7}` scope.

## Operator decisions (this session, 2026-06-15)

1. **Proceed with the setup slice (B).** Activation (A — un-break the local adapter) is fulfilled by
   the operator **dogfooding the plugin**, not a separate step here.
2. **End-user `--github` target = `SaberMage/spt-claude-code`** (operator: "this repo is published
   there"). ⚠ See Open Question 1 — the monorepo layout conflicts with `adapter add --github`'s
   root-`manifest.toml` expectation; topology must be resolved before the end-user branch is wired.

## Ground truth (verified against live `spt 0.7.2` this session)

- `spt adapter add --help`: PATH = **"a dir holding `manifest.toml`, or the manifest file itself"**;
  `--github user/repo` clones under `adapters/_github/`, **manifest-first**, then conducts the
  declared `[update]` avenue once. **No subpath flag.** "Install is the first update."
- Our manifest is **`adapter/claude-spt.toml`** (a subdir, *not* named `manifest.toml`); no
  `manifest.toml` exists anywhere in the repo. → the **local** activation form that works today is
  the *manifest-file-itself* form: `spt adapter add ./adapter/claude-spt.toml`.
- `claude-spt` reads **`deregistered`** in the registry (Phase-D int tests register→clean-up by
  design) — re-adding re-activates.
- Extractor/runner = `tools/claude-spt-digest` + `tools/claude-spt-psyche` (source). Command
  templates are **opaque, resolved from PATH at runtime** — so for the adapter to *function* (digest
  + Psyche), those binaries must be **built and on PATH**, independent of manifest registration.

## Open questions (resolve before wiring the blocked parts)

1. **[BLOCKER — doyle, asked 2026-06-15 owl Q1–Q3] End-user `--github` target topology.**
   `adapter add --github` looks for `manifest.toml` at the **clone root**, no subpath. Our dev repo
   is a monorepo (manifest in `adapter/`). So `--github SaberMage/spt-claude-code` would miss.
   Need doyle's ruling: monorepo subpath support? or dedicated adapter repo (root = `manifest.toml`
   + `strings/`)? or a published orphan-branch/release-artifact whose root is the manifest? **This
   decides repo topology + what string the setup `--github` branch uses.** Local-dir activation is
   unblocked regardless.
2. **End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.** Command templates
   resolve from PATH; a casual end-user has neither binary. How do they install (ride `install.sh`?
   ship in the `--github` adapter repo per doyle's "manifest + extractor/runner binaries"? a
   `cargo install`?). Affects whether an activated adapter actually *functions* end-to-end. (Tied to
   C — the published adapter repo.)
3. **Setup context detection.** How does the skill tell "operator dogfooding from a repo checkout"
   (→ local-dir form) from "casual end-user, plugin only" (→ `--github` form)? Likely: probe for a
   local `adapter/claude-spt.toml` relative to a known root; else `--github`.

## Waves

### Wave 1 — the activation bridge (fulfills A on dogfood) — `REQ-SETUP-ACTIVATE`
**Scope:** make `/sptc:setup`'s binary-present path **activate + verify**, not no-op.
- Rewrite step 1 of both bodies (the self-contained `plugin/sptc/skills/setup/SKILL.md` floor **and**
  the file-backed `adapter/strings/skills/setup.md`): after `command -v spt && spt --version`, check
  whether `claude-spt` is **registered & active** (`spt adapter list` parse). If active → report +
  stop. If absent/`deregistered` → **activate**:
  - **local dev / operator dogfood:** `spt adapter add ./adapter/claude-spt.toml` (manifest-file
    form) when a repo-local manifest is detectable (OQ3).
  - **end-user:** `spt adapter add --github <target>` — **wired once OQ1 resolves** (target TBD).
- **Verify** activation: `spt adapter list` shows `claude-spt` active (not `deregistered`); spot a
  profile resolve (`spt adapter get-string claude-spt:live …` or `spt api … capability`).
- Keep the absent-binary install path (current step 2/3) intact — install **then** activate.
- Idempotent + safe to re-run (mirrors the bootstrap's contract).
- **Evidence:** doc = both bodies; impl = the activation+verify step; int = a registration
  re-activate assertion (`ci/manifest/registration-int.sh` extension, or a new `setup-activate-int`)
  — `deregistered → active`, profile resolves, registry left clean. Activate
  `REQ-SETUP-ACTIVATE = ["doc","impl","int"]`.
- **Note the binary-on-PATH caveat (OQ2)** in the body: activation registers the manifest;
  digest/Psyche need the tool binaries present (built + on PATH) to *function*.

### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)
Staged, not built now (JIT). From `SCOPE.md` §"/spt:setup" LOCKED {1,2,3,4,5,6,7}:
- **#4 already-installed branch** (new subnet / join=add-this-machine / show-code / just-add-endpoint)
  — the natural extension of Wave 1's active-adapter path; pairs with `/sptc:subnet` (already ships).
- **#1 `cc`/`cc <id>` launcher** at project root — **dep:** full-fat M12 `spt endpoint run` picker
  ("lands in a later wave" per `endpoint run --help`; REQ-DIST-SHORTCUT-BASENAME int is held on it).
- **#2** offer `.gitignore` the launchers (rides #1).
- **#3 create first subnet** — QR of the TOTP seed + self-elevating window (elevation design LOCKED,
  `SCOPE.md`; unbuilt). **dep:** elevation machinery.
- **#5 legacy owl migration** — detect `claude_skill_owl`/owl → migrate identity+agents+psyche.
- **#6 OS-service registration** (always-on daemon) — **dep:** spt-core service support.
- **#7 ccs profile wiring** — if `~/.ccs` present; also offer to install ccs. Pairs with the shipped
  `claude-spt:ccs` profile (REQ-CCS-PROFILES).
- Deferred per SCOPE: **#8** off-subnet Psyche sync, **#9** doctor/verify-at-end (operator: "except 9").

## Gate (every wave)
`sh ci/run-gates.sh` PASS + `traceable-reqs check` green. Commit `Co-authored by: perri`.

## Status
- **Plan + `REQ-SETUP-ACTIVATE` seeded (this commit).** Wave-1 build **HELD on OQ1** (doyle topology
  ruling) for the end-user `--github` branch; the **local-dir activation path is buildable now** and
  is what the operator's dogfood exercises. Resume Wave 1 on doyle's reply.


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

# JIT plan — `/sptc:setup` activation bridge (F-005) → grow toward LOCKED v1 setup {1–7}

> Next slice after the cplugs first-publish (b1e2895). Goal: make `/sptc:setup` actually
> **activate** the claude-spt adapter after the binary check (the F-005 post-install bridge), so a
> freshly-installed plugin yields a *registered & active* adapter — not a `deregistered` one. Then
> stage the richer LOCKED v1 setup paths (`SCOPE.md` §"/spt:setup" = {1..7}) as later waves.
> Public-surface-only still binds (AGENTS.md).

## Why (the dogfooding finding, 2026-06-15)

An agent ran `/sptc:setup` on a fresh install: `spt 0.7.2` present → skill reported "No install
needed" and **stopped**. But `spt adapter list` showed **`claude-spt: … deregistered`** — the
adapter surface (profiles/strings/hints/`[digest]`) was inert, `/sptc:*` UPS-injection had nothing
to source. **Binary present ≠ adapter active.** doyle triaged F-005 (docs/SPT-CORE-FINDINGS.md) and
confirmed the missing step: after the binary check, setup must run
**`spt adapter add [--github <repo>]`** to ACTIVATE. The current skill has no such step, and (Point
2, operator) no already-installed branch at all — it is a degenerate installer-floor stub far below
the LOCKED v1 `{1..7}` scope.

## Operator decisions (this session, 2026-06-15)

1. **Proceed with the setup slice (B).** Activation (A — un-break the local adapter) is fulfilled by
   the operator **dogfooding the plugin**, not a separate step here.
2. **End-user `--github` target = `SaberMage/spt-claude-code`** (operator: "this repo is published
   there"). ⚠ See Open Question 1 — the monorepo layout conflicts with `adapter add --github`'s
   root-`manifest.toml` expectation; topology must be resolved before the end-user branch is wired.

## Ground truth (verified against live `spt 0.7.2` this session)

- `spt adapter add --help`: PATH = **"a dir holding `manifest.toml`, or the manifest file itself"**;
  `--github user/repo` clones under `adapters/_github/`, **manifest-first**, then conducts the
  declared `[update]` avenue once. **No subpath flag.** "Install is the first update."
- Our manifest is **`adapter/claude-spt.toml`** (a subdir, *not* named `manifest.toml`); no
  `manifest.toml` exists anywhere in the repo. → the **local** activation form that works today is
  the *manifest-file-itself* form: `spt adapter add ./adapter/claude-spt.toml`.
- `claude-spt` reads **`deregistered`** in the registry (Phase-D int tests register→clean-up by
  design) — re-adding re-activates.
- Extractor/runner = `tools/claude-spt-digest` + `tools/claude-spt-psyche` (source). Command
  templates are **opaque, resolved from PATH at runtime** — so for the adapter to *function* (digest
  + Psyche), those binaries must be **built and on PATH**, independent of manifest registration.

## Open questions (resolve before wiring the blocked parts)

1. **[BLOCKER — doyle, asked 2026-06-15 owl Q1–Q3] End-user `--github` target topology.**
   `adapter add --github` looks for `manifest.toml` at the **clone root**, no subpath. Our dev repo
   is a monorepo (manifest in `adapter/`). So `--github SaberMage/spt-claude-code` would miss.
   Need doyle's ruling: monorepo subpath support? or dedicated adapter repo (root = `manifest.toml`
   + `strings/`)? or a published orphan-branch/release-artifact whose root is the manifest? **This
   decides repo topology + what string the setup `--github` branch uses.** Local-dir activation is
   unblocked regardless.
2. **End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.** Command templates
   resolve from PATH; a casual end-user has neither binary. How do they install (ride `install.sh`?
   ship in the `--github` adapter repo per doyle's "manifest + extractor/runner binaries"? a
   `cargo install`?). Affects whether an activated adapter actually *functions* end-to-end. (Tied to
   C — the published adapter repo.)
3. **Setup context detection.** How does the skill tell "operator dogfooding from a repo checkout"
   (→ local-dir form) from "casual end-user, plugin only" (→ `--github` form)? Likely: probe for a
   local `adapter/claude-spt.toml` relative to a known root; else `--github`.

## Waves

### Wave 1 — the activation bridge (fulfills A on dogfood) — `REQ-SETUP-ACTIVATE`
**Scope:** make `/sptc:setup`'s binary-present path **activate + verify**, not no-op.
- Rewrite step 1 of both bodies (the self-contained `plugin/sptc/skills/setup/SKILL.md` floor **and**
  the file-backed `adapter/strings/skills/setup.md`): after `command -v spt && spt --version`, check
  whether `claude-spt` is **registered & active** (`spt adapter list` parse). If active → report +
  stop. If absent/`deregistered` → **activate**:
  - **local dev / operator dogfood:** `spt adapter add ./adapter/claude-spt.toml` (manifest-file
    form) when a repo-local manifest is detectable (OQ3).
  - **end-user:** `spt adapter add --github <target>` — **wired once OQ1 resolves** (target TBD).
- **Verify** activation: `spt adapter list` shows `claude-spt` active (not `deregistered`); spot a
  profile resolve (`spt adapter get-string claude-spt:live …` or `spt api … capability`).
- Keep the absent-binary install path (current step 2/3) intact — install **then** activate.
- Idempotent + safe to re-run (mirrors the bootstrap's contract).
- **Evidence:** doc = both bodies; impl = the activation+verify step; int = a registration
  re-activate assertion (`ci/manifest/registration-int.sh` extension, or a new `setup-activate-int`)
  — `deregistered → active`, profile resolves, registry left clean. Activate
  `REQ-SETUP-ACTIVATE = ["doc","impl","int"]`.
- **Note the binary-on-PATH caveat (OQ2)** in the body: activation registers the manifest;
  digest/Psyche need the tool binaries present (built + on PATH) to *function*.

### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)
Staged, not built now (JIT). From `SCOPE.md` §"/spt:setup" LOCKED {1,2,3,4,5,6,7}:
- **#4 already-installed branch** (new subnet / join=add-this-machine / show-code / just-add-endpoint)
  — the natural extension of Wave 1's active-adapter path; pairs with `/sptc:subnet` (already ships).
- **#1 `cc`/`cc <id>` launcher** at project root — **dep:** full-fat M12 `spt endpoint run` picker
  ("lands in a later wave" per `endpoint run --help`; REQ-DIST-SHORTCUT-BASENAME int is held on it).
- **#2** offer `.gitignore` the launchers (rides #1).
- **#3 create first subnet** — QR of the TOTP seed + self-elevating window (elevation design LOCKED,
  `SCOPE.md`; unbuilt). **dep:** elevation machinery.
- **#5 legacy owl migration** — detect `claude_skill_owl`/owl → migrate identity+agents+psyche.
- **#6 OS-service registration** (always-on daemon) — **dep:** spt-core service support.
- **#7 ccs profile wiring** — if `~/.ccs` present; also offer to install ccs. Pairs with the shipped
  `claude-spt:ccs` profile (REQ-CCS-PROFILES).
- Deferred per SCOPE: **#8** off-subnet Psyche sync, **#9** doctor/verify-at-end (operator: "except 9").

## Gate (every wave)
`sh ci/run-gates.sh` PASS + `traceable-reqs check` green. Commit `Co-authored by: perri`.

## Status
- **Plan + `REQ-SETUP-ACTIVATE` seeded (this commit).** Wave-1 build **HELD on OQ1** (doyle topology
  ruling) for the end-user `--github` branch; the **local-dir activation path is buildable now** and
  is what the operator's dogfood exercises. Resume Wave 1 on doyle's reply.


Plan + REQ written. Verifying `traceable-reqs check` stays green (REQ seeded inactive), then committing.


Bash

cd "C:/Users/decid/Documents/projects/spt-claude-code" && (command -v traceable-reqs >/dev/null 2>&1 && traceable-reqs check 2>&1 | tail -20 || (echo "traceable-reqs not on PATH; trying common spots..."; for p in "$HOME/.cargo/bin/traceable-reqs" ./traceable-reqs; do [ -x "$p" ] && "$p" check 2>&1 | tail -20 && break; done))

Run traceable-reqs check


  [OK] REQ-DOCS-DRIFT  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       Generated docs (llms.txt) are CI-gated against drift: a deterministic generator's output must match what's checked in, and the book must build
  [OK] REQ-DOCS-SITE  required: [doc, impl]  stages: +doc +impl -unit -int
       docs-site/ builds with mdBook from src/ (themed, Diátaxis-shaped, all-real-content — no placeholders)
  [OK] REQ-HAZARD-MSYS-PATHCONV  required: [unit]  stages: -doc -impl +unit -int
       Hook wrappers read the CC payload from stdin, never from a /-leading positional argv (Git-Bash/MSYS path-mangles those on Windows)
  [OK] REQ-HAZARD-PERCH-COLLISION  required: [unit]  stages: +doc +impl +unit +int
       The acceptance harness spawns every nested claude SUT under a DISPOSABLE identity (SPT_AGENT_ID=sptc-ci-<n>), never a live agent's perch id — a colliding id tears down the live agent's perch + poll stream (name-keyed, last-establish-wins)
  [OK] REQ-PARITY-AUDIT  required: [doc]  stages: +doc -impl -unit -int
       The adapter's operative skill/profile surface is reconciled against the SCOPE.md LOCKED parity-trim (KEEP/ADD/DROP/TRANSFORM): every divergence is either resolved or logged as an accepted gap in docs/PARITY.md — the 'proven parity' record the sptc->spt succession flip gates on
  [OK] REQ-SETUP-ACTIVATE  required: []  stages: -doc -impl -unit -int
       /sptc:setup, after confirming the spt binary is present, ACTIVATES the claude-spt adapter (`spt adapter add` — the manifest file in local dev; `--github <published-adapter-repo>` for end-users) so profiles/strings/hints/[digest] go live, then verifies (adapter no longer `deregistered`). Binary-present is NOT a no-op — this is the F-005 post-install activation bridge.
  [OK] REQ-SKILL-LIVE  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       /sptc:live upgrades THIS CC session to a LiveAgent: the claude-spt:live profile overlays [session.psyche_init] (daemon spawns the Psyche), the claude-spt-psyche runner keeps the Psyche claude alive (one --continue turn per pulse, NOT one-shot `claude -p`), and the live body activates the :live composite + a resident Monitor relay as the single delivery pipe
  [OK] REQ-SKILL-SUBNET  required: [doc, int]  stages: +doc -impl -unit +int
       The adapter ships subnet membership skill(s) (create/join/show-code) wrapping the published `spt subnet <verb>` surface — the LOCKED-ADD cross-subnet entrypoint (v1 topology is mandatory, SCOPE)
  [OK] REQ-SKILL-VERSION  required: []  stages: -doc -impl -unit -int
       /spt:version reports the spt-core-tracked manifest/binary version (the version-of-truth, not the marketplace skeleton version)
  [OK] REQ-UPS-INJECTION  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       UserPromptSubmit hook detects /sptc:X and injects X's real instructions as additionalContext (SKILL.md files stay skeletons); must be empirically confirmed UPS fires on slash-commands


`traceable-reqs check` green — `REQ-SETUP-ACTIVATE [OK]` (seeded inactive). Committing plan + REQ.


cd "C:/Users/decid/Documents/projects/spt-claude-code" && git add SETUP-SLICE-PLAN.md traceable-reqs.toml && git commit -m "plan(setup): JIT setup-slice — /sptc:setup activation bridge (F-005) + REQ-SETUP-ACTIVATE

Wave 1 = make the binary-present path ACTIVATE the adapter (spt adapter add)
+ verify (not no-op) — the F-005 post-install bridge. Later waves stage LOCKED
v1 setup {1..7}. End-user --github target topology blocked on doyle (OQ1);
local-dir activation unblocked. REQ-SETUP-ACTIVATE seeded inactive.

Co-authored by: perri" 2>&1 | tail -3

Commit setup-slice plan + REQ


[main 5ab2d11] plan(setup): JIT setup-slice — /sptc:setup activation bridge (F-005) + REQ-SETUP-ACTIVATE
 2 files changed, 115 insertions(+)
 create mode 100644 SETUP-SLICE-PLAN.md


**B underway — plan landed (`5ab2d11`), build gated on one doyle answer.**

Done this turn:
- `SETUP-SLICE-PLAN.md` — Wave 1 = the activation bridge (binary-present path must `adapter add` + verify, not no-op); later waves stage LOCKED v1 {1–7} with deps flagged.
- `REQ-SETUP-ACTIVATE` seeded (inactive) — `traceable-reqs check` green.
- Ground truth verified against live 0.7.2 (exact `adapter add` semantics, the `deregistered` state, the PATH-resolved tool binaries).

**The build blocker (1 question, doyle pinged):** `adapter add --github` looks for `manifest.toml` at clone **root**, no subpath flag. Our monorepo keeps it at `adapter/claude-spt.toml`. So `--github SaberMage/spt-claude-code` won't find it as-is. doyle Q1–Q3 asks: monorepo-subpath support? dedicated adapter repo? or published artifact whose root is the manifest? — **that answer decides repo topology + the exact `--github` string the skill uses.**

What's unblocked vs blocked:
- **Unblocked (operator dogfood path):** local-dir activation — `spt adapter add ./adapter/claude-spt.toml` works today.
- **Blocked (end-user path):** the `--github` branch string + whether C needs a *separate* repo (your "published at spt-claude-code" collides with the root-`manifest.toml` rule).

Holding Wave-1 authoring for doyle's reply (arrives via the stream — no poll needed) rather than hardcoding a guessed target. Two heads-up beyond the blocker:
- **Binary delivery (OQ2):** end-users have neither `claude-spt-digest` nor `claude-spt-psyche` on PATH — activation registers the manifest but digest/Psyche won't *function* until those ship. Tied to C.
- **Your "repo published at spt-claude-code"** likely can't be the direct `--github` target (monorepo). Probably need a dedicated adapter-root repo or a published artifact — doyle's Q2 settles it.

Want me to build the unblocked local-dir activation path now (concrete progress, operator-dogfood-ready), or hold the whole of Wave 1 until doyle's topology ruling lands so I author both branches in one pass?


<task-notification>
<task-id>bp4sffhfb</task-id>
Monitor event: "« spt event »"
<event><EVENT-PART seq="1/8" id="0d0eda6c" type="msg" from="doyle">Monorepo --github — answered from source (registry::register + source_manifest_file). Classification: DOC-GAP — all in spt-core source, not the published docs. I'm fixing the docs (below); build to this now:

Q1 — ROOT-ONLY, confirmed in code (not just undocumented). source_manifest_file: a DIR source resolv</EVENT-PART>
<EVENT-PART seq="2/8" id="0d0eda6c">es to `&lt;dir&gt;/manifest.toml` EXACTLY — root of the given dir, exact filename, NO scan, NO subpath. `--github user/repo` registers the clone ROOT, so it reads `&lt;clone-root&gt;/manifest.toml`. Your `adapter/claude-spt.toml` misses on both counts (subdir + name). There is no subpath code path.

Q2 — dedicated published adapter r</EVENT-PART>
<EVENT-PART seq="3/8" id="0d0eda6c">epo whose ROOT is `manifest.toml` (named exactly that) + `strings/` + the binaries your manifest points at (digest extractor, psyche runner). That repo is the end-user `--github` target. Keep the monorepo's `adapter/claude-spt.toml` for LOCAL dev — the file-form `spt adapter add ./adapter/claude-spt.toml` takes any path + any filename. So: m</EVENT-PART>
<EVENT-PART seq="4/8" id="0d0eda6c">onorepo (file-form) for dev, dedicated root-manifest repo for `--github`. Confirms the &quot;own published repo&quot; I flagged earlier.

Q3 — NOT the whole clone. The mode follows your [update] avenue:
- delegated (yours: `claude plugin update spt`) -&gt; POINTER mode: copies NOTHING into adapters/&lt;name&gt;/; reads manifest + st</EVENT-PART>
<EVENT-PART seq="5/8" id="0d0eda6c">rings/ LIVE from the durable adapters/_github/&lt;safe&gt; clone, for life.
- file_pull / no [update] -&gt; COPY mode: copies manifest.toml + strings/ into adapters/&lt;name&gt;/ ONLY.
Either way the manifest is resolved at clone-ROOT (root-only holds in BOTH modes; the mode only changes copy-vs-read-live afterward). KEY: your pointed-at</EVENT-PART>
<EVENT-PART seq="6/8" id="0d0eda6c"> BINARIES (extractor, runner) are NOT auto-copied in either mode — only strings/ is. So make them resolvable on the target: absolute / on PATH, or — in pointer mode — shipped in the repo at the manifest's paths so they resolve from the durable _github clone. Verify how your [digest]/[session] command templates resolve their binary paths,</EVENT-PART>
<EVENT-PART seq="7/8" id="0d0eda6c"> and ship accordingly.

NET for claude-spt: delegated -&gt; pointer mode -&gt; --github repo = root manifest.toml + strings/ + binaries; the _github clone is the live home. Local dev unaffected.

I'm adding the distribution-repo topology to the activation docs now (root manifest.toml requirement, --github root-only, copy-vs-pointer</EVENT-PART>
<EVENT-PART seq="8/8" id="0d0eda6c"> by avenue, where binaries live). Build to the above; doc lands shortly. No rush noted — this just decides your repo shape.</EVENT-PART></event>
</task-notification>


<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


doyle fully unblocked it (8 parts, complete). Repo topology decided:

- **Q1 ROOT-ONLY (code-confirmed):** dir source → `<dir>/manifest.toml` exactly, no scan/subpath. Our `adapter/claude-spt.toml` misses on both. It's another **doc-gap** (in source, not published) — doyle's patching docs.
- **Q2:** dedicated **published adapter repo**, root = `manifest.toml` (exact name) + `strings/` + the binaries. That's the `--github` target. Monorepo `adapter/claude-spt.toml` stays for local dev (file-form takes any path/name).
- **Q3:** not the whole clone. Our `[update]=delegated` → **pointer mode**: copies nothing, reads manifest+`strings/` **live from the durable `adapters/_github/` clone**. **KEY: binaries are NOT auto-copied** — only `strings/`. So `claude-spt-digest`/`claude-spt-psyche` must be on PATH (or shipped in the repo at manifest-referenced paths to resolve from the clone).

Recording the ruling, then building Wave 1 (now fully unblocked).


Edit

## Open questions (resolve before wiring the blocked parts)

1. **[BLOCKER — doyle, asked 2026-06-15 owl Q1–Q3] End-user `--github` target topology.**
   `adapter add --github` looks for `manifest.toml` at the **clone root**, no subpath. Our dev repo
   is a monorepo (manifest in `adapter/`). So `--github SaberMage/spt-claude-code` would miss.
   Need doyle's ruling: monorepo subpath support? or dedicated adapter repo (root = `manifest.toml`
   + `strings/`)? or a published orphan-branch/release-artifact whose root is the manifest? **This
   decides repo topology + what string the setup `--github` branch uses.** Local-dir activation is
   unblocked regardless.
2. **End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.** Command templates
   resolve from PATH; a casual end-user has neither binary. How do they install (ride `install.sh`?
   ship in the `--github` adapter repo per doyle's "manifest + extractor/runner binaries"? a
   `cargo install`?). Affects whether an activated adapter actually *functions* end-to-end. (Tied to
   C — the published adapter repo.)
3. **Setup context detection.** How does the skill tell "operator dogfooding from a repo checkout"
   (→ local-dir form) from "casual end-user, plugin only" (→ `--github` form)? Likely: probe for a
   local `adapter/claude-spt.toml` relative to a known root; else `--github`.

## Open questions

1. **[RESOLVED — doyle, owl 2026-06-15, from source] End-user `--github` target topology.**
   `adapter add` is **ROOT-ONLY, code-confirmed** (`source_manifest_file`): a dir source resolves to
   `<dir>/manifest.toml` **exactly** (exact filename, no scan, no subpath); `--github user/repo`
   reads `<clone-root>/manifest.toml`. Our `adapter/claude-spt.toml` misses on both counts → a
   **doc-gap** (it's in spt-core source, not the published docs; doyle is patching the activation
   docs). **Ruling:**
   - **Local dev** keeps the monorepo `adapter/claude-spt.toml`; activate via the **file-form**
     `spt adapter add ./adapter/claude-spt.toml` (takes any path + any filename).
   - **End-user `--github`** needs a **DEDICATED published adapter repo** (Wave C) whose **root** is
     `manifest.toml` (named exactly) + `strings/` + the binaries the manifest references.
   - **Copy-vs-pointer by `[update]` avenue:** claude-spt's avenue is `delegated`
     (`claude plugin update spt`) → **POINTER mode**: spt-core copies **nothing** into
     `adapters/<name>/`; it reads `manifest.toml` + `strings/` **live from the durable
     `adapters/_github/<safe>` clone**, for life. (`file_pull`/no-`[update]` = COPY mode instead.)
     Root-only holds in both modes.
2. **[RESOLVED via Q3 ruling] End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.**
   doyle: the manifest-referenced **binaries are NOT auto-copied** in either mode (only `strings/`
   is). So they must be **resolvable on the target**: absolute path, on PATH, or — in our pointer
   mode — **shipped in the `--github` repo at the manifest's referenced paths** so they resolve from
   the durable `_github` clone. **Action:** our command templates reference the binaries by **bare
   name** (`claude-spt-digest …`, `claude-spt-psyche …`) ⇒ resolved from **PATH**. So end-user
   delivery must put both on PATH (ride the installer) OR we switch the manifest to clone-relative
   paths + ship the binaries in the Wave-C repo. **Decide in Wave C** (lean: ship on PATH via the
   installer — keeps templates portable). Folded into Wave C.
3. **Setup context detection.** Skill probes for a local `adapter/claude-spt.toml` (operator
   dogfooding from a checkout → file-form) else uses `--github <Wave-C repo>` (casual end-user).


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

## Open questions

1. **[RESOLVED — doyle, owl 2026-06-15, from source] End-user `--github` target topology.**
   `adapter add` is **ROOT-ONLY, code-confirmed** (`source_manifest_file`): a dir source resolves to
   `<dir>/manifest.toml` **exactly** (exact filename, no scan, no subpath); `--github user/repo`
   reads `<clone-root>/manifest.toml`. Our `adapter/claude-spt.toml` misses on both counts → a
   **doc-gap** (it's in spt-core source, not the published docs; doyle is patching the activation
   docs). **Ruling:**
   - **Local dev** keeps the monorepo `adapter/claude-spt.toml`; activate via the **file-form**
     `spt adapter add ./adapter/claude-spt.toml` (takes any path + any filename).
   - **End-user `--github`** needs a **DEDICATED published adapter repo** (Wave C) whose **root** is
     `manifest.toml` (named exactly) + `strings/` + the binaries the manifest references.
   - **Copy-vs-pointer by `[update]` avenue:** claude-spt's avenue is `delegated`
     (`claude plugin update spt`) → **POINTER mode**: spt-core copies **nothing** into
     `adapters/<name>/`; it reads `manifest.toml` + `strings/` **live from the durable
     `adapters/_github/<safe>` clone**, for life. (`file_pull`/no-`[update]` = COPY mode instead.)
     Root-only holds in both modes.
2. **[RESOLVED via Q3 ruling] End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.**
   doyle: the manifest-referenced **binaries are NOT auto-copied** in either mode (only `strings/`
   is). So they must be **resolvable on the target**: absolute path, on PATH, or — in our pointer
   mode — **shipped in the `--github` repo at the manifest's referenced paths** so they resolve from
   the durable `_github` clone. **Action:** our command templates reference the binaries by **bare
   name** (`claude-spt-digest …`, `claude-spt-psyche …`) ⇒ resolved from **PATH**. So end-user
   delivery must put both on PATH (ride the installer) OR we switch the manifest to clone-relative
   paths + ship the binaries in the Wave-C repo. **Decide in Wave C** (lean: ship on PATH via the
   installer — keeps templates portable). Folded into Wave C.
3. **Setup context detection.** Skill probes for a local `adapter/claude-spt.toml` (operator
   dogfooding from a checkout → file-form) else uses `--github <Wave-C repo>` (casual end-user).

# JIT plan — `/sptc:setup` activation bridge (F-005) → grow toward LOCKED v1 setup {1–7}

> Next slice after the cplugs first-publish (b1e2895). Goal: make `/sptc:setup` actually
> **activate** the claude-spt adapter after the binary check (the F-005 post-install bridge), so a
> freshly-installed plugin yields a *registered & active* adapter — not a `deregistered` one. Then
> stage the richer LOCKED v1 setup paths (`SCOPE.md` §"/spt:setup" = {1..7}) as later waves.
> Public-surface-only still binds (AGENTS.md).

## Why (the dogfooding finding, 2026-06-15)

An agent ran `/sptc:setup` on a fresh install: `spt 0.7.2` present → skill reported "No install
needed" and **stopped**. But `spt adapter list` showed **`claude-spt: … deregistered`** — the
adapter surface (profiles/strings/hints/`[digest]`) was inert, `/sptc:*` UPS-injection had nothing
to source. **Binary present ≠ adapter active.** doyle triaged F-005 (docs/SPT-CORE-FINDINGS.md) and
confirmed the missing step: after the binary check, setup must run
**`spt adapter add [--github <repo>]`** to ACTIVATE. The current skill has no such step, and (Point
2, operator) no already-installed branch at all — it is a degenerate installer-floor stub far below
the LOCKED v1 `{1..7}` scope.

## Operator decisions (this session, 2026-06-15)

1. **Proceed with the setup slice (B).** Activation (A — un-break the local adapter) is fulfilled by
   the operator **dogfooding the plugin**, not a separate step here.
2. **End-user `--github` target = `SaberMage/spt-claude-code`** (operator: "this repo is published
   there"). ⚠ See Open Question 1 — the monorepo layout conflicts with `adapter add --github`'s
   root-`manifest.toml` expectation; topology must be resolved before the end-user branch is wired.

## Ground truth (verified against live `spt 0.7.2` this session)

- `spt adapter add --help`: PATH = **"a dir holding `manifest.toml`, or the manifest file itself"**;
  `--github user/repo` clones under `adapters/_github/`, **manifest-first**, then conducts the
  declared `[update]` avenue once. **No subpath flag.** "Install is the first update."
- Our manifest is **`adapter/claude-spt.toml`** (a subdir, *not* named `manifest.toml`); no
  `manifest.toml` exists anywhere in the repo. → the **local** activation form that works today is
  the *manifest-file-itself* form: `spt adapter add ./adapter/claude-spt.toml`.
- `claude-spt` reads **`deregistered`** in the registry (Phase-D int tests register→clean-up by
  design) — re-adding re-activates.
- Extractor/runner = `tools/claude-spt-digest` + `tools/claude-spt-psyche` (source). Command
  templates are **opaque, resolved from PATH at runtime** — so for the adapter to *function* (digest
  + Psyche), those binaries must be **built and on PATH**, independent of manifest registration.

## Open questions (resolve before wiring the blocked parts)

1. **[BLOCKER — doyle, asked 2026-06-15 owl Q1–Q3] End-user `--github` target topology.**
   `adapter add --github` looks for `manifest.toml` at the **clone root**, no subpath. Our dev repo
   is a monorepo (manifest in `adapter/`). So `--github SaberMage/spt-claude-code` would miss.
   Need doyle's ruling: monorepo subpath support? or dedicated adapter repo (root = `manifest.toml`
   + `strings/`)? or a published orphan-branch/release-artifact whose root is the manifest? **This
   decides repo topology + what string the setup `--github` branch uses.** Local-dir activation is
   unblocked regardless.
2. **End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.** Command templates
   resolve from PATH; a casual end-user has neither binary. How do they install (ride `install.sh`?
   ship in the `--github` adapter repo per doyle's "manifest + extractor/runner binaries"? a
   `cargo install`?). Affects whether an activated adapter actually *functions* end-to-end. (Tied to
   C — the published adapter repo.)
3. **Setup context detection.** How does the skill tell "operator dogfooding from a repo checkout"
   (→ local-dir form) from "casual end-user, plugin only" (→ `--github` form)? Likely: probe for a
   local `adapter/claude-spt.toml` relative to a known root; else `--github`.

## Waves

### Wave 1 — the activation bridge (fulfills A on dogfood) — `REQ-SETUP-ACTIVATE`
**Scope:** make `/sptc:setup`'s binary-present path **activate + verify**, not no-op.
- Rewrite step 1 of both bodies (the self-contained `plugin/sptc/skills/setup/SKILL.md` floor **and**
  the file-backed `adapter/strings/skills/setup.md`): after `command -v spt && spt --version`, check
  whether `claude-spt` is **registered & active** (`spt adapter list` parse). If active → report +
  stop. If absent/`deregistered` → **activate**:
  - **local dev / operator dogfood:** `spt adapter add ./adapter/claude-spt.toml` (manifest-file
    form) when a repo-local manifest is detectable (OQ3).
  - **end-user:** `spt adapter add --github <target>` — **wired once OQ1 resolves** (target TBD).
- **Verify** activation: `spt adapter list` shows `claude-spt` active (not `deregistered`); spot a
  profile resolve (`spt adapter get-string claude-spt:live …` or `spt api … capability`).
- Keep the absent-binary install path (current step 2/3) intact — install **then** activate.
- Idempotent + safe to re-run (mirrors the bootstrap's contract).
- **Evidence:** doc = both bodies; impl = the activation+verify step; int = a registration
  re-activate assertion (`ci/manifest/registration-int.sh` extension, or a new `setup-activate-int`)
  — `deregistered → active`, profile resolves, registry left clean. Activate
  `REQ-SETUP-ACTIVATE = ["doc","impl","int"]`.
- **Note the binary-on-PATH caveat (OQ2)** in the body: activation registers the manifest;
  digest/Psyche need the tool binaries present (built + on PATH) to *function*.

### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)
Staged, not built now (JIT). From `SCOPE.md` §"/spt:setup" LOCKED {1,2,3,4,5,6,7}:
- **#4 already-installed branch** (new subnet / join=add-this-machine / show-code / just-add-endpoint)
  — the natural extension of Wave 1's active-adapter path; pairs with `/sptc:subnet` (already ships).
- **#1 `cc`/`cc <id>` launcher** at project root — **dep:** full-fat M12 `spt endpoint run` picker
  ("lands in a later wave" per `endpoint run --help`; REQ-DIST-SHORTCUT-BASENAME int is held on it).
- **#2** offer `.gitignore` the launchers (rides #1).
- **#3 create first subnet** — QR of the TOTP seed + self-elevating window (elevation design LOCKED,
  `SCOPE.md`; unbuilt). **dep:** elevation machinery.
- **#5 legacy owl migration** — detect `claude_skill_owl`/owl → migrate identity+agents+psyche.
- **#6 OS-service registration** (always-on daemon) — **dep:** spt-core service support.
- **#7 ccs profile wiring** — if `~/.ccs` present; also offer to install ccs. Pairs with the shipped
  `claude-spt:ccs` profile (REQ-CCS-PROFILES).
- Deferred per SCOPE: **#8** off-subnet Psyche sync, **#9** doctor/verify-at-end (operator: "except 9").

## Gate (every wave)
`sh ci/run-gates.sh` PASS + `traceable-reqs check` green. Commit `Co-authored by: perri`.

## Status
- **Plan + `REQ-SETUP-ACTIVATE` seeded (this commit).** Wave-1 build **HELD on OQ1** (doyle topology
  ruling) for the end-user `--github` branch; the **local-dir activation path is buildable now** and
  is what the operator's dogfood exercises. Resume Wave 1 on doyle's reply.

-## Open questions (resolve before wiring the blocked parts)

-1. **[BLOCKER — doyle, asked 2026-06-15 owl Q1–Q3] End-user `--github` target topology.**

-   `adapter add --github` looks for `manifest.toml` at the **clone root**, no subpath. Our dev repo

-   is a monorepo (manifest in `adapter/`). So `--github SaberMage/spt-claude-code` would miss.

-   Need doyle's ruling: monorepo subpath support? or dedicated adapter repo (root = `manifest.toml`

-   + `strings/`)? or a published orphan-branch/release-artifact whose root is the manifest? **This

-   decides repo topology + what string the setup `--github` branch uses.** Local-dir activation is

-2. **End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.** Command templates

-   resolve from PATH; a casual end-user has neither binary. How do they install (ride `install.sh`?

-   ship in the `--github` adapter repo per doyle's "manifest + extractor/runner binaries"? a

-   `cargo install`?). Affects whether an activated adapter actually *functions* end-to-end. (Tied to

-3. **Setup context detection.** How does the skill tell "operator dogfooding from a repo checkout"

-   (→ local-dir form) from "casual end-user, plugin only" (→ `--github` form)? Likely: probe for a

-   local `adapter/claude-spt.toml` relative to a known root; else `--github`.

+1. **[RESOLVED — doyle, owl 2026-06-15, from source] End-user `--github` target topology.**

+   `adapter add` is **ROOT-ONLY, code-confirmed** (`source_manifest_file`): a dir source resolves to

+   `<dir>/manifest.toml` **exactly** (exact filename, no scan, no subpath); `--github user/repo`

+   reads `<clone-root>/manifest.toml`. Our `adapter/claude-spt.toml` misses on both counts → a

+   **doc-gap** (it's in spt-core source, not the published docs; doyle is patching the activation

+   - **Local dev** keeps the monorepo `adapter/claude-spt.toml`; activate via the **file-form**

+     `spt adapter add ./adapter/claude-spt.toml` (takes any path + any filename).

+   - **End-user `--github`** needs a **DEDICATED published adapter repo** (Wave C) whose **root** is

+     `manifest.toml` (named exactly) + `strings/` + the binaries the manifest references.

+   - **Copy-vs-pointer by `[update]` avenue:** claude-spt's avenue is `delegated`

+     (`claude plugin update spt`) → **POINTER mode**: spt-core copies **nothing** into

+     `adapters/<name>/`; it reads `manifest.toml` + `strings/` **live from the durable

+     `adapters/_github/<safe>` clone**, for life. (`file_pull`/no-`[update]` = COPY mode instead.)

+2. **[RESOLVED via Q3 ruling] End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.**

+   doyle: the manifest-referenced **binaries are NOT auto-copied** in either mode (only `strings/`

+   is). So they must be **resolvable on the target**: absolute path, on PATH, or — in our pointer

+   mode — **shipped in the `--github` repo at the manifest's referenced paths** so they resolve from

+   the durable `_github` clone. **Action:** our command templates reference the binaries by **bare

+   name** (`claude-spt-digest …`, `claude-spt-psyche …`) ⇒ resolved from **PATH**. So end-user

+   delivery must put both on PATH (ride the installer) OR we switch the manifest to clone-relative

+   paths + ship the binaries in the Wave-C repo. **Decide in Wave C** (lean: ship on PATH via the

+   installer — keeps templates portable). Folded into Wave C.

+3. **Setup context detection.** Skill probes for a local `adapter/claude-spt.toml` (operator

+   dogfooding from a checkout → file-form) else uses `--github <Wave-C repo>` (casual end-user).


### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)

### Wave C — the dedicated published adapter repo (the end-user `--github` target) — **on A's critical path**
**Why:** the operator's A-fulfilling dogfood is "install the **plugin**" (the end-user path) → setup
runs `adapter add --github <repo>` → so that repo must EXIST and be correctly shaped. The monorepo
`SaberMage/spt-claude-code` **cannot** be it (root-only rule). **Decision needed (operator):** repo
name + creation (SaberMage org credentials) + the binary-delivery choice (OQ2: on-PATH-via-installer
vs clone-relative-paths-in-repo).
- Lay out repo **root** = `manifest.toml` (the monorepo's `adapter/claude-spt.toml`, renamed) +
  `strings/` (copied) + (per OQ2 decision) the built `claude-spt-digest` + `claude-spt-psyche`.
- A `ci/publish/` step that **generates** this repo from the monorepo `adapter/` (rename + copy +
  drop binaries) so the two never drift — mirrors `package-skeleton.sh` for the cplugs side.
- Verify end-to-end: a clean machine `spt adapter add --github <repo>` → active + a profile resolves
  + digest/Psyche binaries resolve. New REQ (`REQ-DIST-ADAPTER-REPO`) when this wave starts.

### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)


### Wave C — the dedicated published adapter repo (the end-user `--github` target) — **on A's critical path**
**Why:** the operator's A-fulfilling dogfood is "install the **plugin**" (the end-user path) → setup
runs `adapter add --github <repo>` → so that repo must EXIST and be correctly shaped. The monorepo
`SaberMage/spt-claude-code` **cannot** be it (root-only rule). **Decision needed (operator):** repo
name + creation (SaberMage org credentials) + the binary-delivery choice (OQ2: on-PATH-via-installer
vs clone-relative-paths-in-repo).
- Lay out repo **root** = `manifest.toml` (the monorepo's `adapter/claude-spt.toml`, renamed) +
  `strings/` (copied) + (per OQ2 decision) the built `claude-spt-digest` + `claude-spt-psyche`.
- A `ci/publish/` step that **generates** this repo from the monorepo `adapter/` (rename + copy +
  drop binaries) so the two never drift — mirrors `package-skeleton.sh` for the cplugs side.
- Verify end-to-end: a clean machine `spt adapter add --github <repo>` → active + a profile resolves
  + digest/Psyche binaries resolve. New REQ (`REQ-DIST-ADAPTER-REPO`) when this wave starts.

### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)

# JIT plan — `/sptc:setup` activation bridge (F-005) → grow toward LOCKED v1 setup {1–7}

> Next slice after the cplugs first-publish (b1e2895). Goal: make `/sptc:setup` actually
> **activate** the claude-spt adapter after the binary check (the F-005 post-install bridge), so a
> freshly-installed plugin yields a *registered & active* adapter — not a `deregistered` one. Then
> stage the richer LOCKED v1 setup paths (`SCOPE.md` §"/spt:setup" = {1..7}) as later waves.
> Public-surface-only still binds (AGENTS.md).

## Why (the dogfooding finding, 2026-06-15)

An agent ran `/sptc:setup` on a fresh install: `spt 0.7.2` present → skill reported "No install
needed" and **stopped**. But `spt adapter list` showed **`claude-spt: … deregistered`** — the
adapter surface (profiles/strings/hints/`[digest]`) was inert, `/sptc:*` UPS-injection had nothing
to source. **Binary present ≠ adapter active.** doyle triaged F-005 (docs/SPT-CORE-FINDINGS.md) and
confirmed the missing step: after the binary check, setup must run
**`spt adapter add [--github <repo>]`** to ACTIVATE. The current skill has no such step, and (Point
2, operator) no already-installed branch at all — it is a degenerate installer-floor stub far below
the LOCKED v1 `{1..7}` scope.

## Operator decisions (this session, 2026-06-15)

1. **Proceed with the setup slice (B).** Activation (A — un-break the local adapter) is fulfilled by
   the operator **dogfooding the plugin**, not a separate step here.
2. **End-user `--github` target = `SaberMage/spt-claude-code`** (operator: "this repo is published
   there"). ⚠ See Open Question 1 — the monorepo layout conflicts with `adapter add --github`'s
   root-`manifest.toml` expectation; topology must be resolved before the end-user branch is wired.

## Ground truth (verified against live `spt 0.7.2` this session)

- `spt adapter add --help`: PATH = **"a dir holding `manifest.toml`, or the manifest file itself"**;
  `--github user/repo` clones under `adapters/_github/`, **manifest-first**, then conducts the
  declared `[update]` avenue once. **No subpath flag.** "Install is the first update."
- Our manifest is **`adapter/claude-spt.toml`** (a subdir, *not* named `manifest.toml`); no
  `manifest.toml` exists anywhere in the repo. → the **local** activation form that works today is
  the *manifest-file-itself* form: `spt adapter add ./adapter/claude-spt.toml`.
- `claude-spt` reads **`deregistered`** in the registry (Phase-D int tests register→clean-up by
  design) — re-adding re-activates.
- Extractor/runner = `tools/claude-spt-digest` + `tools/claude-spt-psyche` (source). Command
  templates are **opaque, resolved from PATH at runtime** — so for the adapter to *function* (digest
  + Psyche), those binaries must be **built and on PATH**, independent of manifest registration.

## Open questions

1. **[RESOLVED — doyle, owl 2026-06-15, from source] End-user `--github` target topology.**
   `adapter add` is **ROOT-ONLY, code-confirmed** (`source_manifest_file`): a dir source resolves to
   `<dir>/manifest.toml` **exactly** (exact filename, no scan, no subpath); `--github user/repo`
   reads `<clone-root>/manifest.toml`. Our `adapter/claude-spt.toml` misses on both counts → a
   **doc-gap** (it's in spt-core source, not the published docs; doyle is patching the activation
   docs). **Ruling:**
   - **Local dev** keeps the monorepo `adapter/claude-spt.toml`; activate via the **file-form**
     `spt adapter add ./adapter/claude-spt.toml` (takes any path + any filename).
   - **End-user `--github`** needs a **DEDICATED published adapter repo** (Wave C) whose **root** is
     `manifest.toml` (named exactly) + `strings/` + the binaries the manifest references.
   - **Copy-vs-pointer by `[update]` avenue:** claude-spt's avenue is `delegated`
     (`claude plugin update spt`) → **POINTER mode**: spt-core copies **nothing** into
     `adapters/<name>/`; it reads `manifest.toml` + `strings/` **live from the durable
     `adapters/_github/<safe>` clone**, for life. (`file_pull`/no-`[update]` = COPY mode instead.)
     Root-only holds in both modes.
2. **[RESOLVED via Q3 ruling] End-user binary delivery for `claude-spt-digest` / `claude-spt-psyche`.**
   doyle: the manifest-referenced **binaries are NOT auto-copied** in either mode (only `strings/`
   is). So they must be **resolvable on the target**: absolute path, on PATH, or — in our pointer
   mode — **shipped in the `--github` repo at the manifest's referenced paths** so they resolve from
   the durable `_github` clone. **Action:** our command templates reference the binaries by **bare
   name** (`claude-spt-digest …`, `claude-spt-psyche …`) ⇒ resolved from **PATH**. So end-user
   delivery must put both on PATH (ride the installer) OR we switch the manifest to clone-relative
   paths + ship the binaries in the Wave-C repo. **Decide in Wave C** (lean: ship on PATH via the
   installer — keeps templates portable). Folded into Wave C.
3. **Setup context detection.** Skill probes for a local `adapter/claude-spt.toml` (operator
   dogfooding from a checkout → file-form) else uses `--github <Wave-C repo>` (casual end-user).

## Waves

### Wave 1 — the activation bridge (fulfills A on dogfood) — `REQ-SETUP-ACTIVATE`
**Scope:** make `/sptc:setup`'s binary-present path **activate + verify**, not no-op.
- Rewrite step 1 of both bodies (the self-contained `plugin/sptc/skills/setup/SKILL.md` floor **and**
  the file-backed `adapter/strings/skills/setup.md`): after `command -v spt && spt --version`, check
  whether `claude-spt` is **registered & active** (`spt adapter list` parse). If active → report +
  stop. If absent/`deregistered` → **activate**:
  - **local dev / operator dogfood:** `spt adapter add ./adapter/claude-spt.toml` (manifest-file
    form) when a repo-local manifest is detectable (OQ3).
  - **end-user:** `spt adapter add --github <target>` — **wired once OQ1 resolves** (target TBD).
- **Verify** activation: `spt adapter list` shows `claude-spt` active (not `deregistered`); spot a
  profile resolve (`spt adapter get-string claude-spt:live …` or `spt api … capability`).
- Keep the absent-binary install path (current step 2/3) intact — install **then** activate.
- Idempotent + safe to re-run (mirrors the bootstrap's contract).
- **Evidence:** doc = both bodies; impl = the activation+verify step; int = a registration
  re-activate assertion (`ci/manifest/registration-int.sh` extension, or a new `setup-activate-int`)
  — `deregistered → active`, profile resolves, registry left clean. Activate
  `REQ-SETUP-ACTIVATE = ["doc","impl","int"]`.
- **Note the binary-on-PATH caveat (OQ2)** in the body: activation registers the manifest;
  digest/Psyche need the tool binaries present (built + on PATH) to *function*.

### Later waves — LOCKED v1 setup paths {1..7} (each its own slice + REQ; deps flagged)
Staged, not built now (JIT). From `SCOPE.md` §"/spt:setup" LOCKED {1,2,3,4,5,6,7}:
- **#4 already-installed branch** (new subnet / join=add-this-machine / show-code / just-add-endpoint)
  — the natural extension of Wave 1's active-adapter path; pairs with `/sptc:subnet` (already ships).
- **#1 `cc`/`cc <id>` launcher** at project root — **dep:** full-fat M12 `spt endpoint run` picker
  ("lands in a later wave" per `endpoint run --help`; REQ-DIST-SHORTCUT-BASENAME int is held on it).
- **#2** offer `.gitignore` the launchers (rides #1).
- **#3 create first subnet** — QR of the TOTP seed + self-elevating window (elevation design LOCKED,
  `SCOPE.md`; unbuilt). **dep:** elevation machinery.
- **#5 legacy owl migration** — detect `claude_skill_owl`/owl → migrate identity+agents+psyche.
- **#6 OS-service registration** (always-on daemon) — **dep:** spt-core service support.
- **#7 ccs profile wiring** — if `~/.ccs` present; also offer to install ccs. Pairs with the shipped
  `claude-spt:ccs` profile (REQ-CCS-PROFILES).
- Deferred per SCOPE: **#8** off-subnet Psyche sync, **#9** doctor/verify-at-end (operator: "except 9").

## Gate (every wave)
`sh ci/run-gates.sh` PASS + `traceable-reqs check` green. Commit `Co-authored by: perri`.

## Status
- **Plan + `REQ-SETUP-ACTIVATE` seeded (this commit).** Wave-1 build **HELD on OQ1** (doyle topology
  ruling) for the end-user `--github` branch; the **local-dir activation path is buildable now** and
  is what the operator's dogfood exercises. Resume Wave 1 on doyle's reply.

+### Wave C — the dedicated published adapter repo (the end-user `--github` target) — **on A's critical path**

+**Why:** the operator's A-fulfilling dogfood is "install the **plugin**" (the end-user path) → setup

+runs `adapter add --github <repo>` → so that repo must EXIST and be correctly shaped. The monorepo

+`SaberMage/spt-claude-code` **cannot** be it (root-only rule). **Decision needed (operator):** repo

+name + creation (SaberMage org credentials) + the binary-delivery choice (OQ2: on-PATH-via-installer

+- Lay out repo **root** = `manifest.toml` (the monorepo's `adapter/claude-spt.toml`, renamed) +

+- A `ci/publish/` step that **generates** this repo from the monorepo `adapter/` (rename + copy +

+- Verify end-to-end: a clean machine `spt adapter add --github <repo>` → active + a profile resolves

+  + digest/Psyche binaries resolve. New REQ (`REQ-DIST-ADAPTER-REPO`) when this wave starts.


## Status
- **Plan + `REQ-SETUP-ACTIVATE` seeded (this commit).** Wave-1 build **HELD on OQ1** (doyle topology
  ruling) for the end-user `--github` branch; the **local-dir activation path is buildable now** and
  is what the operator's dogfood exercises. Resume Wave 1 on doyle's reply.

## Status
- **OQ1/OQ2 RESOLVED (doyle, owl 2026-06-15).** Repo topology decided: monorepo file-form for dev;
  dedicated root-`manifest.toml` repo for `--github` (pointer mode, binaries on PATH). Wave 1 is now
  **fully unblocked** — authoring both activation branches.
- **Wave C is on A's critical path:** the operator's "dogfood the plugin" = end-user path = needs the
  dedicated `--github` repo to exist. Surfaced to operator (repo name + creation + OQ2 binary choice).