1	#!/bin/sh
2	# Stage the sptc cplugs SKELETON into a marketplace clone — the runbook "per skeleton bump" cp
3	# mechanic as a real, idempotent, validated script. DRY-RUN by default: prints the plan and stages
4	# nothing. Never pushes (marketplace credentials + the commit/push are the operator's step).
5	# [impl->REQ-DIST-PLUGIN-SKELETON]
6	#
7	# Usage:
8	#   package-skeleton.sh                 # dry-run against the default $MARKET
9	#   package-skeleton.sh --apply         # actually copy the skeleton subset into $MARKET
10	#   MARKET=/path/to/cplugs/plugins/sptc package-skeleton.sh --apply
11	set -u
12	HERE=$(CDPATH= cd "$(dirname "$0")" && pwd)
13	ROOT=$(CDPATH= cd "$HERE/../.." && pwd)
14	PLUGIN="$ROOT/plugin/sptc"
15	MARKET="${MARKET:-$HOME/.claude/plugins/marketplaces/cplugs/plugins/sptc}"
16	APPLY=0
17	[ "${1:-}" = "--apply" ] && APPLY=1
18
19	# Validate first — refuse to stage an invalid / leaky skeleton.
20	echo "== validate skeleton =="
21	if ! sh "$HERE/validate-skeleton.sh" "$PLUGIN"; then
22	  echo "REFUSING to package: skeleton failed validation (fix above, then retry)." >&2
23	  exit 1
24	fi
25
26	# The skeleton SUBSET — exactly what cplugs carries (no binary, no manifest, no runtime state).
27	SUBSET=".claude-plugin/plugin.json hooks skills bootstrap.sh bootstrap.ps1"
28
29	echo
30	echo "== plan ($([ "$APPLY" -eq 1 ] && echo APPLY || echo DRY-RUN)) =="
31	echo "source : $PLUGIN"
32	echo "target : $MARKET"
33	for item in $SUBSET; do
34	  if [ -e "$PLUGIN/$item" ]; then echo "  stage  $item"; else echo "  WARN   missing source: $item"; fi
35	done
36
37	if [ "$APPLY" -ne 1 ]; then
38	  echo
39	  echo "DRY-RUN: nothing copied. Re-run with --apply to stage into \$MARKET, then commit+push the"
40	  echo "cplugs repo and 'claude plugin install sptc@cplugs' (see docs/RELEASE-RUNBOOK.md)."
41	  exit 0
42	fi
43
44	mkdir -p "$MARKET/.claude-plugin" "$MARKET/hooks" "$MARKET/skills" || { echo "FATAL: cannot create $MARKET"; exit 2; }
45	cp "$PLUGIN/.claude-plugin/plugin.json" "$MARKET/.claude-plugin/"
46	# Replace dir contents wholesale so removed skeleton files don't linger in the marketplace clone.
47	rm -rf "$MARKET/hooks" "$MARKET/skills"
48	cp -r "$PLUGIN/hooks" "$MARKET/hooks"
49	cp -r "$PLUGIN/skills" "$MARKET/skills"
50	for b in bootstrap.sh bootstrap.ps1; do [ -f "$PLUGIN/$b" ] && cp "$PLUGIN/$b" "$MARKET/"; done
51
52	echo
53	echo "STAGED into $MARKET. Next (operator): cd into the cplugs repo, 'git add plugins/sptc/',"
54	echo "commit + push, then 'claude plugin install sptc@cplugs' + /reload-plugins."
55	exit 0
56

#!/bin/sh
# Stage the sptc cplugs SKELETON into a marketplace clone — the runbook "per skeleton bump" cp
# mechanic as a real, idempotent, validated script. DRY-RUN by default: prints the plan and stages
# nothing. Never pushes (marketplace credentials + the commit/push are the operator's step).
# [impl->REQ-DIST-PLUGIN-SKELETON]
#
# Usage:
#   package-skeleton.sh                 # dry-run against the default $MARKET
#   package-skeleton.sh --apply         # actually copy the skeleton subset into $MARKET
#   MARKET=/path/to/cplugs/plugins/sptc package-skeleton.sh --apply
set -u
HERE=$(CDPATH= cd "$(dirname "$0")" && pwd)
ROOT=$(CDPATH= cd "$HERE/../.." && pwd)
PLUGIN="$ROOT/plugin/sptc"
MARKET="${MARKET:-$HOME/.claude/plugins/marketplaces/cplugs/plugins/sptc}"
APPLY=0
[ "${1:-}" = "--apply" ] && APPLY=1

# Validate first — refuse to stage an invalid / leaky skeleton.
echo "== validate skeleton =="
if ! sh "$HERE/validate-skeleton.sh" "$PLUGIN"; then
  echo "REFUSING to package: skeleton failed validation (fix above, then retry)." >&2
  exit 1
fi

# The skeleton SUBSET — exactly what cplugs carries (no binary, no manifest, no runtime state).
SUBSET=".claude-plugin/plugin.json hooks skills bootstrap.sh bootstrap.ps1"

echo
echo "== plan ($([ "$APPLY" -eq 1 ] && echo APPLY || echo DRY-RUN)) =="
echo "source : $PLUGIN"
echo "target : $MARKET"
for item in $SUBSET; do
  if [ -e "$PLUGIN/$item" ]; then echo "  stage  $item"; else echo "  WARN   missing source: $item"; fi
done

if [ "$APPLY" -ne 1 ]; then
  echo
  echo "DRY-RUN: nothing copied. Re-run with --apply to stage into \$MARKET, then commit+push the"
  echo "cplugs repo and 'claude plugin install sptc@cplugs' (see docs/RELEASE-RUNBOOK.md)."
  exit 0
fi

mkdir -p "$MARKET/.claude-plugin" "$MARKET/hooks" "$MARKET/skills" || { echo "FATAL: cannot create $MARKET"; exit 2; }
cp "$PLUGIN/.claude-plugin/plugin.json" "$MARKET/.claude-plugin/"
# Replace dir contents wholesale so removed skeleton files don't linger in the marketplace clone.
rm -rf "$MARKET/hooks" "$MARKET/skills"
cp -r "$PLUGIN/hooks" "$MARKET/hooks"
cp -r "$PLUGIN/skills" "$MARKET/skills"
for b in bootstrap.sh bootstrap.ps1; do [ -f "$PLUGIN/$b" ] && cp "$PLUGIN/$b" "$MARKET/"; done

echo
echo "STAGED into $MARKET. Next (operator): cd into the cplugs repo, 'git add plugins/sptc/',"
echo "commit + push, then 'claude plugin install sptc@cplugs' + /reload-plugins."
exit 0


Bash

cd "C:/Users/decid/Documents/projects/spt-claude-code" && echo "HEAD clean?"; git status --short; echo "---commune staged (tips)?---"; git status --short --untracked-files=no

Check working tree state


HEAD clean?
---commune staged (tips)?---


MARKET="$HOME/.claude/plugins/marketplaces/cplugs"; echo "MARKET=$MARKET"; ls -la "$MARKET" 2>&1 | head -30; echo "---is git?---"; git -C "$MARKET" rev-parse --show-toplevel 2>&1; echo "---remote---"; git -C "$MARKET" remote -v 2>&1

Inspect cplugs marketplace clone


MARKET=/c/Users/decid/.claude/plugins/marketplaces/cplugs
total 13
drwxr-xr-x 1 decid 197609   0 Apr  2 02:07 .
drwxr-xr-x 1 decid 197609   0 Jun 15 18:50 ..
drwxr-xr-x 1 decid 197609   0 May  1 19:37 .claude-plugin
drwxr-xr-x 1 decid 197609   0 Jun  2 14:33 .git
-rw-r--r-- 1 decid 197609 605 Apr  2 02:07 README.md
drwxr-xr-x 1 decid 197609   0 May  1 19:36 plugins
---is git?---
C:/Users/decid/.claude/plugins/marketplaces/cplugs
---remote---
origin	https://github.com/SaberMage/cplugs.git (fetch)
origin	https://github.com/SaberMage/cplugs.git (push)


Tree clean. cplugs clone is git, remote `SaberMage/cplugs`. Checking existing marketplace state + runbook.


MARKET="$HOME/.claude/plugins/marketplaces/cplugs"; echo "=== marketplace.json ==="; cat "$MARKET/.claude-plugin/marketplace.json" 2>&1; echo; echo "=== plugins/ ==="; ls -la "$MARKET/plugins" 2>&1; echo "=== plugins/sptc (if exists) ==="; ls -la "$MARKET/plugins/sptc" 2>&1; echo "=== git status cplugs ==="; git -C "$MARKET" status --short; git -C "$MARKET" log --oneline -3

Inspect marketplace.json and sptc state


=== marketplace.json ===
{
  "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
  "name": "cplugs",
  "description": "Private plugin marketplace",
  "owner": {
    "name": "SaberMage"
  },
  "plugins": [
    {
      "name": "spt",
      "description": "Spacetime agent messaging and live agent system for Claude Code",
      "author": {
        "name": "todlando"
      },
      "source": "./plugins/spt",
      "category": "development"
    },
    {
      "name": "screen-timelapse",
      "description": "MCP server for capturing screen timelapse sequences and compiling grid images for AI agent visual debugging",
      "author": {
        "name": "Reavo End"
      },
      "source": "./plugins/screen-timelapse",
      "category": "development"
    },
    {
      "name": "everything",
      "description": "Instant file search via voidtools Everything 1.5a HTTP API — skill teaches Claude to query the local Everything HTTP JSON endpoint. Invoke as /everything:search.",
      "author": {
        "name": "SaberMage"
      },
      "source": "./plugins/everything",
      "category": "productivity"
    }
  ]
}

=== plugins/ ===
total 16
drwxr-xr-x 1 decid 197609 0 May  1 19:36 .
drwxr-xr-x 1 decid 197609 0 Apr  2 02:07 ..
drwxr-xr-x 1 decid 197609 0 May  1 19:37 everything
drwxr-xr-x 1 decid 197609 0 Apr 13 00:51 screen-timelapse
drwxr-xr-x 1 decid 197609 0 May 17 04:26 spt
=== plugins/sptc (if exists) ===
ls: cannot access '/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc': No such file or directory
=== git status cplugs ===
33927ca spt: deploy v1.11.25
eb03327 spt: deploy v1.11.24
cc460b3 spt: deploy v1.11.23


cd "C:/Users/decid/Documents/projects/spt-claude-code" && sed -n '1,80p' docs/RELEASE-RUNBOOK.md 2>&1

Read release runbook head


# Release runbook

> How an spt-claude-code release ships. The spine is fixed (changelog · bump · regenerate
> docs · tag · publish · docs publish). **Release here is LIGHT: signing is DELEGATED to the
> `spt` binary — there is NO two-key signing ceremony in this project.** spt-claude-code is a
> thin adapter; the heavy signed-release machinery lives in spt-core, not here.

<!-- [<doc>->REQ-EXAMPLE-REL] (illustration; escaped per docs/TRACEABILITY.md) -->

## Publish targets

An spt-claude-code release lands in **two places**, by volatility:

1. **The `SaberMage/cplugs` marketplace** — the thin **skeleton plugin** (namespaced
   `/spt:*` skill skeletons, `hooks.json`, the SessionStart bootstrap, `plugin.json`). This
   is low-churn: it only changes on **structural** plugin changes, not on logic/instruction
   updates.
2. **The spt-core adapter registry** — the volatile bulk: the CC adapter **manifest**
   (`[digest]` extractor, profiles, strings, hints) **+ binary**. This publish is
   **spt-core-conducted** (the same framework that conducts adapter updates), not a plugin
   file push.

## One-time setup

No signing-key ceremony in this project. **Signing is delegated to the `spt` binary**, which
handles adapter manifest/binary integrity through spt-core's own signed-update framework. Keep
no release keys here. The only setup is marketplace/registry publish credentials for the two
targets above (a `cplugs` push token + whatever the spt-core adapter-registry publish step
requires).

## Per release

1. **Bump** the version (the plugin `plugin.json` version and/or the adapter manifest version —
   note these are distinct numbers; see Notes) if needed; **regenerate generated docs**
   (the mdBook `docs-site/` build + `llms.txt` / schema / CLI-help exports); land everything
   green.
2. **Write the user-facing changelog** — add a `## [<version>] - <date>` section at the top of
   `CHANGELOG.md` with **Added / Changed / Fixed** subsections. This section becomes the public
   release body verbatim, so it is the changelog every user reads. Rules:
   - **User-facing UX only.** What a person using the product notices or does differently. Name
     the actual commands / flags / surfaces they touch (`/spt:*` skills, `cc`, `/spt:setup`).
   - **No internal lingo** — no requirement ids, internal module names, commit hashes, or
     milestone / hazard codes. A reader who has never seen the source must understand every line.
   - **Flag breaking changes** prominently under Changed.
   - The release **fails loudly** if the tagged version has no `## [<version>]` section — the
     changelog is not optional.
3. **Tag**: `git tag <vX.Y.Z> && git push origin <vX.Y.Z>`. This triggers:
   - the **docs-publish workflow** — build `docs-site/` and publish to GitHub Pages (drift-gated;
     see `docs/DOCS-STRATEGY.md`).
4. **Publish** (light — signing delegated to `spt`):
   - **Skeleton plugin** → push to the `SaberMage/cplugs` marketplace **only when the plugin
     skeleton structurally changed** (new/removed skill skeleton, hook wiring, bootstrap, or
     `plugin.json`). Most releases do not bump the marketplace.
   - **Manifest + binary** → publish through the **spt-core adapter registry**; the `spt`
     binary performs signing/integrity as part of spt-core's adapter-update framework. You do
     **not** run a separate signing step.

## cplugs skeleton publish — concrete mechanics

<!-- [doc->REQ-DIST-PLUGIN-SKELETON] -->
The concrete cplugs marketplace steps, captured from the sister project's
`claude_skill_owl/docs/DEPLOY.md`. **Take only the SKELETON SUBSET.** spt-claude-code's cplugs
target is the **thin skeleton** — `/spt:*` skill skeletons, `hooks.json`, the SessionStart
bootstrap, `plugin.json`. **No binary, no manifest in cplugs** — the binary + adapter manifest
ride the **spt-core adapter registry** (spt-conducted; the *other* publish target above), so
none of owl's binary-lifecycle machinery applies here.

> **Now scripted (`ci/publish/`).** The validate + stage mechanics below are codified:
> `ci/publish/validate-skeleton.sh` is a binary installability gate (valid `plugin.json` with
> `name=sptc`; valid `hooks.json` whose referenced wrappers all exist; every skill has a
> `SKILL.md`; **no runtime-state / binary / manifest leak in the published surface**) — it runs in
> `ci/run-gates.sh` (the `skeleton-validate` gate) and is unit-tested by `tests/skeleton-validate.sh`.
> `ci/publish/package-skeleton.sh` codifies the per-bump copy below — validates first, **dry-run by
> default**, stages only the skeleton subset, never pushes (the marketplace commit/push stays the
> operator's step).

**One-time marketplace setup:**

```bash
# Clone the marketplace repo


yes, run the publish step and cplugs commt+push now


Note: `sptc` NOT in marketplace.json yet (only legacy `spt`, screen-timelapse, everything). Reading rest of runbook mechanics.


cd "C:/Users/decid/Documents/projects/spt-claude-code" && sed -n '80,200p' docs/RELEASE-RUNBOOK.md 2>&1

Read runbook concrete mechanics


# Clone the marketplace repo
git clone https://github.com/SaberMage/cplugs.git ~/.claude/plugins/marketplaces/cplugs
# Register a "cplugs" entry in ~/.claude/plugins/known_marketplaces.json
#   source: { source: "github", repo: "SaberMage/cplugs" }
```

**Per skeleton bump** (only when the skeleton *structurally* changes — see "Per release"):

```bash
# 1. Bump plugin.json version. The plugin manager compares this to the cached copy and
#    SKIPS the update entirely if they match — a stale version = a silent no-update.
# 2. Copy skeleton files (NO binary) into the marketplace clone:
MARKET=~/.claude/plugins/marketplaces/cplugs/plugins/sptc
cp -r skills/*  "$MARKET/skills/"
cp -r hooks/*   "$MARKET/hooks/"
cp .claude-plugin/plugin.json "$MARKET/.claude-plugin/"
# 3. Commit + push the cplugs repo:
cd ~/.claude/plugins/marketplaces/cplugs && git add plugins/sptc/ \
  && git commit -m "sptc: <change>" && git push
```

**Pointer flip** (the authoritative install-state update):

```bash
claude plugin install sptc@cplugs   # un-orphans + rewrites installed_plugins.json atomically
# then, inside Claude Code:
/reload-plugins
```

**Gotchas (these DO apply to the skeleton):**
- **Never hand-patch `installed_plugins.json`** (`jq`/`sed` are brittle; CC may silently reject).
  Use the `claude plugin install` CLI — it's the atomic pointer flip + orphan-marker cleanup.
- **No legacy manual-install dir alongside the marketplace install.** A `~/.claude/plugins/<name>/`
  regular dir coexisting with the marketplace cache install makes `/plugin` report the plugin
  **not installed** (CC enumerates both; the untracked one wins the conflict). Keep the two exclusive.
- **Restart the Claude Code session after install** so the SessionStart hook re-runs and repopulates
  the plugin's env (`$OWL`/`$LIVE` equivalents) in Bash subprocesses.

**Explicitly NOT ours** (owl ships a live self-migrating binary; the thin skeleton has none, so
skip all of it): `owl.exe` binary sync · the cache targeted-prune + keep-PREVIOUS-version logic ·
the seamless binary handoff (owl Phase 18.4/18.5) · `DEPLOY.ps1`'s build/handoff orchestration.

> **RULED (operator, 2026-06-14) — cplugs plugin name = `sptc`.** CC ties the skill prefix to the
> `plugin.json` name (no override), so skills surface as `/sptc:*`. **Succession:** once parity is
> proven, flip `plugin.json` name `sptc`→`spt` (skills → `/spt:*`) and retire/rename legacy owl's
> cplugs `spt` plugin in the same coordinated move — two plugins cannot share the `spt` name. The
> flip is a single substitution `s/sptc/spt/` (plugin dir, `plugin.json` name, marketplace path).

## Update path (dual, kept in sync)

Users receive updates two ways, and both must stay consistent:
- **File-pull (the real channel)** — spt-core conducts manifest + binary updates seamlessly;
  this is how logic and instruction churn reaches users. Version-of-truth = the
  manifest/binary version spt-core tracks (`spt adapter list` / `/spt:version`).
- **`claude plugin update` (cautionary, skeleton sync)** — only resyncs the low-churn
  marketplace skeleton on the rare structural bump. It is NOT the version-of-truth.

## Notes

- **Distinct numbers — never conflate them:** the **plugin (marketplace) version** (in
  `plugin.json`, bumps rarely) and the **adapter manifest/binary version** (spt-core-tracked,
  the user-visible version-of-truth). They move on independent schedules — the plugin can sit
  static across many manifest updates.
- **Trust model:** adapter manifest/binary integrity is the `spt` binary's responsibility via
  spt-core's signed-update framework — spt-claude-code defines no separate trust ceremony.
  (Claude Code has no plugin-file integrity check, which is why the skeleton plugin is safe to
  in-place-edit; only old version dirs orphan on update and are GC'd after 7 days.)


Full mechanics clear. One gap: `marketplace.json` has no `sptc` entry — required for `install sptc@cplugs` to resolve. First publish must add it. Checking source skeleton, then applying.


cd "C:/Users/decid/Documents/projects/spt-claude-code" && echo "=== plugin/sptc tree ==="; find plugin/sptc -maxdepth 2 -type f | sort; echo; echo "=== plugin.json ==="; cat plugin/sptc/.claude-plugin/plugin.json

Inspect source skeleton plugin


=== plugin/sptc tree ===
plugin/sptc/.claude-plugin/plugin.json
plugin/sptc/.claude/LIVE_AGENT_IDS.json
plugin/sptc/bootstrap.ps1
plugin/sptc/bootstrap.sh
plugin/sptc/hooks/_common.sh
plugin/sptc/hooks/hooks.json
plugin/sptc/hooks/session-end.sh
plugin/sptc/hooks/session-start.sh
plugin/sptc/hooks/stop.sh
plugin/sptc/hooks/subagent-start.sh
plugin/sptc/hooks/subagent-stop.sh
plugin/sptc/hooks/user-prompt-submit.sh

=== plugin.json ===
{
  "name": "sptc",
  "version": "0.1.0",
  "description": "Spacetime (spt) adapter for Claude Code — agent messaging, live agents, and spt-core bootstrap. Thin skeleton; logic rides the spt binary + adapter manifest (spt-core-conducted).",
  "author": {
    "name": "perri"
  },
  "keywords": ["spt", "spacetime", "messaging", "agents", "live", "claude-spt"]
}


cd "C:/Users/decid/Documents/projects/spt-claude-code" && echo "=== skills ==="; ls plugin/sptc/skills 2>&1; echo "=== skill dirs ==="; find plugin/sptc/skills -name SKILL.md 2>&1 | sort

Check skills dir


=== skills ===
commune
force-stop
list-agents
live
ready
send
setup
signoff
subnet
version
=== skill dirs ===
plugin/sptc/skills/commune/SKILL.md
plugin/sptc/skills/force-stop/SKILL.md
plugin/sptc/skills/list-agents/SKILL.md
plugin/sptc/skills/live/SKILL.md
plugin/sptc/skills/ready/SKILL.md
plugin/sptc/skills/send/SKILL.md
plugin/sptc/skills/setup/SKILL.md
plugin/sptc/skills/signoff/SKILL.md
plugin/sptc/skills/subnet/SKILL.md
plugin/sptc/skills/version/SKILL.md


10 skills (whoami dropped ✓, subnet added ✓). Running `--apply`.


cd "C:/Users/decid/Documents/projects/spt-claude-code" && sh ci/publish/package-skeleton.sh --apply 2>&1

Stage skeleton into cplugs clone


== validate skeleton ==
ok   plugin.json valid JSON
ok   plugin.json name=sptc
ok   plugin.json has version
ok   plugin.json has description
ok   hooks.json valid JSON
ok   hook wrapper present: hooks/session-end.sh
ok   hook wrapper present: hooks/session-start.sh
ok   hook wrapper present: hooks/stop.sh
ok   hook wrapper present: hooks/subagent-start.sh
ok   hook wrapper present: hooks/subagent-stop.sh
ok   hook wrapper present: hooks/user-prompt-submit.sh
ok   skill ok: commune
ok   skill ok: force-stop
ok   skill ok: list-agents
ok   skill ok: live
ok   skill ok: ready
ok   skill ok: send
ok   skill ok: setup
ok   skill ok: signoff
ok   skill ok: subnet
ok   skill ok: version
ok   published surface clean (no runtime/binary/manifest leak)

=== SKELETON: INSTALLABLE ===

== plan (APPLY) ==
source : /c/Users/decid/Documents/projects/spt-claude-code/plugin/sptc
target : /c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc
  stage  .claude-plugin/plugin.json
  stage  hooks
  stage  skills
  stage  bootstrap.sh
  stage  bootstrap.ps1

STAGED into /c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc. Next (operator): cd into the cplugs repo, 'git add plugins/sptc/',
commit + push, then 'claude plugin install sptc@cplugs' + /reload-plugins.


Staged. Now register `sptc` in marketplace.json (required for first publish), then verify staged tree.


1	{
2	  "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
3	  "name": "cplugs",
4	  "description": "Private plugin marketplace",
5	  "owner": {
6	    "name": "SaberMage"
7	  },
8	  "plugins": [
9	    {
10	      "name": "spt",
11	      "description": "Spacetime agent messaging and live agent system for Claude Code",
12	      "author": {
13	        "name": "todlando"
14	      },
15	      "source": "./plugins/spt",
16	      "category": "development"
17	    },
18	    {
19	      "name": "screen-timelapse",
20	      "description": "MCP server for capturing screen timelapse sequences and compiling grid images for AI agent visual debugging",
21	      "author": {
22	        "name": "Reavo End"
23	      },
24	      "source": "./plugins/screen-timelapse",
25	      "category": "development"
26	    },
27	    {
28	      "name": "everything",
29	      "description": "Instant file search via voidtools Everything 1.5a HTTP API — skill teaches Claude to query the local Everything HTTP JSON endpoint. Invoke as /everything:search.",
30	      "author": {
31	        "name": "SaberMage"
32	      },
33	      "source": "./plugins/everything",
34	      "category": "productivity"
35	    }
36	  ]
37	}
38

cplugs

Private plugin marketplace


Edit

    {
      "name": "everything",
      "description": "Instant file search via voidtools Everything 1.5a HTTP API — skill teaches Claude to query the local Everything HTTP JSON endpoint. Invoke as /everything:search.",
      "author": {
        "name": "SaberMage"
      },
      "source": "./plugins/everything",
      "category": "productivity"
    }
  ]

    {
      "name": "everything",
      "description": "Instant file search via voidtools Everything 1.5a HTTP API — skill teaches Claude to query the local Everything HTTP JSON endpoint. Invoke as /everything:search.",
      "author": {
        "name": "SaberMage"
      },
      "source": "./plugins/everything",
      "category": "productivity"
    },
    {
      "name": "sptc",
      "description": "Spacetime (spt) adapter for Claude Code — agent messaging, live agents, and spt-core bootstrap. Thin skeleton; logic rides the spt binary + adapter manifest (spt-core-conducted). Invoke as /sptc:*.",
      "author": {
        "name": "perri"
      },
      "source": "./plugins/sptc",
      "category": "development"
    }
  ]


The file C:\Users\decid\.claude\plugins\marketplaces\cplugs\.claude-plugin\marketplace.json has been updated successfully. (file state is current in your context — no need to Read it back)

    {
      "name": "everything",
      "description": "Instant file search via voidtools Everything 1.5a HTTP API — skill teaches Claude to query the local Everything HTTP JSON endpoint. Invoke as /everything:search.",
      "author": {
        "name": "SaberMage"
      },
      "source": "./plugins/everything",
      "category": "productivity"
    }
  ]

    {
      "name": "everything",
      "description": "Instant file search via voidtools Everything 1.5a HTTP API — skill teaches Claude to query the local Everything HTTP JSON endpoint. Invoke as /everything:search.",
      "author": {
        "name": "SaberMage"
      },
      "source": "./plugins/everything",
      "category": "productivity"
    },
    {
      "name": "sptc",
      "description": "Spacetime (spt) adapter for Claude Code — agent messaging, live agents, and spt-core bootstrap. Thin skeleton; logic rides the spt binary + adapter manifest (spt-core-conducted). Invoke as /sptc:*.",
      "author": {
        "name": "perri"
      },
      "source": "./plugins/sptc",
      "category": "development"
    }
  ]

cplugs

Private plugin marketplace

+      "description": "Spacetime (spt) adapter for Claude Code — agent messaging, live agents, and spt-core bootstrap. Thin skeleton; logic rides the spt binary + adapter manifest (spt-core-conducted). Invoke as /sptc:*.",


Bash

MARKET="$HOME/.claude/plugins/marketplaces/cplugs"; echo "=== staged sptc tree ==="; find "$MARKET/plugins/sptc" -type f | sort; echo; echo "=== marketplace.json valid JSON? ==="; python -c "import json,sys; json.load(open(r'$MARKET/.claude-plugin/marketplace.json')); print('valid; plugins:', [p['name'] for p in json.load(open(r'$MARKET/.claude-plugin/marketplace.json'))['plugins']])" 2>&1; echo; echo "=== git status ==="; git -C "$MARKET" status --short

Verify staged tree + marketplace.json validity + git status


=== staged sptc tree ===
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/.claude-plugin/plugin.json
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/bootstrap.ps1
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/bootstrap.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/_common.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/hooks.json
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/session-end.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/session-start.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/stop.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/subagent-start.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/subagent-stop.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/hooks/user-prompt-submit.sh
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/commune/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/force-stop/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/list-agents/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/live/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/ready/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/send/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/setup/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/signoff/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/subnet/SKILL.md
/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/skills/version/SKILL.md

=== marketplace.json valid JSON? ===
Traceback (most recent call last):
  File "<string>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '/c/Users/decid/.claude/plugins/marketplaces/cplugs/.claude-plugin/marketplace.json'

=== git status ===
 M .claude-plugin/marketplace.json
?? plugins/sptc/


Staged tree complete (10 skills, hooks, bootstraps, plugin.json). Python path mangled — validate JSON via node + git diff.


MARKET="$HOME/.claude/plugins/marketplaces/cplugs"; node -e "const m=require('$MARKET/.claude-plugin/marketplace.json'); console.log('marketplace.json valid; plugins:', m.plugins.map(p=>p.name).join(', '))" 2>&1; node -e "const p=require('$MARKET/plugins/sptc/.claude-plugin/plugin.json'); console.log('sptc plugin.json valid; name='+p.name+' version='+p.version)" 2>&1; echo "=== diff marketplace.json ==="; git -C "$MARKET" diff .claude-plugin/marketplace.json

Validate JSON via node + show diff


node:internal/modules/cjs/loader:1478
  throw err;
  ^

Error: Cannot find module '/c/Users/decid/.claude/plugins/marketplaces/cplugs/.claude-plugin/marketplace.json'
Require stack:
- C:\Users\decid\Documents\projects\spt-claude-code\[eval]
    at Module._resolveFilename (node:internal/modules/cjs/loader:1475:15)
    at wrapResolveFilename (node:internal/modules/cjs/loader:1048:27)
    at defaultResolveImplForCJSLoading (node:internal/modules/cjs/loader:1072:10)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1093:12)
    at Module._load (node:internal/modules/cjs/loader:1261:25)
    at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
    at Module.require (node:internal/modules/cjs/loader:1575:12)
    at require (node:internal/modules/helpers:191:16)
    at [eval]:1:9
    at runScriptInThisContext (node:internal/vm:219:10) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ 'C:\\Users\\decid\\Documents\\projects\\spt-claude-code\\[eval]' ]
}

Node.js v25.8.2
node:internal/modules/cjs/loader:1478
  throw err;
  ^

Error: Cannot find module '/c/Users/decid/.claude/plugins/marketplaces/cplugs/plugins/sptc/.claude-plugin/plugin.json'
Require stack:
- C:\Users\decid\Documents\projects\spt-claude-code\[eval]
    at Module._resolveFilename (node:internal/modules/cjs/loader:1475:15)
    at wrapResolveFilename (node:internal/modules/cjs/loader:1048:27)
    at defaultResolveImplForCJSLoading (node:internal/modules/cjs/loader:1072:10)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1093:12)
    at Module._load (node:internal/modules/cjs/loader:1261:25)
    at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
    at Module.require (node:internal/modules/cjs/loader:1575:12)
    at require (node:internal/modules/helpers:191:16)
    at [eval]:1:9
    at runScriptInThisContext (node:internal/vm:219:10) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ 'C:\\Users\\decid\\Documents\\projects\\spt-claude-code\\[eval]' ]
}

Node.js v25.8.2
=== diff marketplace.json ===
warning: in the working copy of '.claude-plugin/marketplace.json', LF will be replaced by CRLF the next time Git touches it
diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 38c5f58..f52083f 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -32,6 +32,15 @@
       },
       "source": "./plugins/everything",
       "category": "productivity"
+    },
+    {
+      "name": "sptc",
+      "description": "Spacetime (spt) adapter for Claude Code — agent messaging, live agents, and spt-core bootstrap. Thin skeleton; logic rides the spt binary + adapter manifest (spt-core-conducted). Invoke as /sptc:*.",
+      "author": {
+        "name": "perri"
+      },
+      "source": "./plugins/sptc",
+      "category": "development"
     }
   ]
 }


Diff correct. Node needs Windows paths — validating both JSON files.


M='C:/Users/decid/.claude/plugins/marketplaces/cplugs'; node -e "const m=require('$M/.claude-plugin/marketplace.json'); console.log('marketplace.json OK; plugins:', m.plugins.map(p=>p.name).join(', '))"; node -e "const p=require('$M/plugins/sptc/.claude-plugin/plugin.json'); console.log('sptc plugin.json OK; name='+p.name+' version='+p.version)"; node -e "const h=require('$M/plugins/sptc/hooks/hooks.json'); console.log('hooks.json OK')"

Validate JSON with Windows paths


marketplace.json OK; plugins: spt, screen-timelapse, everything, sptc
sptc plugin.json OK; name=sptc version=0.1.0
hooks.json OK


All JSON valid. Marketplace now lists `sptc`. Committing + pushing cplugs.


MARKET="$HOME/.claude/plugins/marketplaces/cplugs"; cd "$MARKET" && git add plugins/sptc/ .claude-plugin/marketplace.json && git status --short && echo "=== committing ===" && git commit -m "sptc: first publish — spt adapter skeleton v0.1.0 (10 skills, hooks, bootstrap)

Register sptc plugin in marketplace.json and stage the thin skeleton
(skills/hooks/bootstrap/plugin.json — no binary, no manifest). Invoke as /sptc:*.

Co-authored by: perri" 2>&1

Stage and commit cplugs


warning: in the working copy of '.claude-plugin/marketplace.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/.claude-plugin/plugin.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/bootstrap.ps1', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/bootstrap.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/_common.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/hooks.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/session-end.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/session-start.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/stop.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/subagent-start.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/subagent-stop.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/hooks/user-prompt-submit.sh', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/commune/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/force-stop/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/list-agents/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/live/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/ready/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/send/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/setup/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/signoff/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/subnet/SKILL.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'plugins/sptc/skills/version/SKILL.md', LF will be replaced by CRLF the next time Git touches it
M  .claude-plugin/marketplace.json
A  plugins/sptc/.claude-plugin/plugin.json
A  plugins/sptc/bootstrap.ps1
A  plugins/sptc/bootstrap.sh
A  plugins/sptc/hooks/_common.sh
A  plugins/sptc/hooks/hooks.json
A  plugins/sptc/hooks/session-end.sh
A  plugins/sptc/hooks/session-start.sh
A  plugins/sptc/hooks/stop.sh
A  plugins/sptc/hooks/subagent-start.sh
A  plugins/sptc/hooks/subagent-stop.sh
A  plugins/sptc/hooks/user-prompt-submit.sh
A  plugins/sptc/skills/commune/SKILL.md
A  plugins/sptc/skills/force-stop/SKILL.md
A  plugins/sptc/skills/list-agents/SKILL.md
A  plugins/sptc/skills/live/SKILL.md
A  plugins/sptc/skills/ready/SKILL.md
A  plugins/sptc/skills/send/SKILL.md
A  plugins/sptc/skills/setup/SKILL.md
A  plugins/sptc/skills/signoff/SKILL.md
A  plugins/sptc/skills/subnet/SKILL.md
A  plugins/sptc/skills/version/SKILL.md
=== committing ===
[main b1e2895] sptc: first publish — spt adapter skeleton v0.1.0 (10 skills, hooks, bootstrap)
 22 files changed, 549 insertions(+)
 create mode 100644 plugins/sptc/.claude-plugin/plugin.json
 create mode 100644 plugins/sptc/bootstrap.ps1
 create mode 100644 plugins/sptc/bootstrap.sh
 create mode 100644 plugins/sptc/hooks/_common.sh
 create mode 100644 plugins/sptc/hooks/hooks.json
 create mode 100644 plugins/sptc/hooks/session-end.sh
 create mode 100644 plugins/sptc/hooks/session-start.sh
 create mode 100644 plugins/sptc/hooks/stop.sh
 create mode 100644 plugins/sptc/hooks/subagent-start.sh
 create mode 100644 plugins/sptc/hooks/subagent-stop.sh
 create mode 100644 plugins/sptc/hooks/user-prompt-submit.sh
 create mode 100644 plugins/sptc/skills/commune/SKILL.md
 create mode 100644 plugins/sptc/skills/force-stop/SKILL.md
 create mode 100644 plugins/sptc/skills/list-agents/SKILL.md
 create mode 100644 plugins/sptc/skills/live/SKILL.md
 create mode 100644 plugins/sptc/skills/ready/SKILL.md
 create mode 100644 plugins/sptc/skills/send/SKILL.md
 create mode 100644 plugins/sptc/skills/setup/SKILL.md
 create mode 100644 plugins/sptc/skills/signoff/SKILL.md
 create mode 100644 plugins/sptc/skills/subnet/SKILL.md
 create mode 100644 plugins/sptc/skills/version/SKILL.md
Shell cwd was reset to C:\Users\decid\Documents\projects\spt-claude-code


Committed `b1e2895` (22 files). Pushing to `SaberMage/cplugs`.


MARKET="$HOME/.claude/plugins/marketplaces/cplugs"; cd "$MARKET" && git push origin main 2>&1

Push cplugs to GitHub


To https://github.com/SaberMage/cplugs.git
   33927ca..b1e2895  main -> main
Shell cwd was reset to C:\Users\decid\Documents\projects\spt-claude-code


Pushed: `33927ca..b1e2895` on cplugs main. **Published.**

Publish step done. Remaining = pointer flip (`claude plugin install sptc@cplugs` + `/reload-plugins`) — session-affecting (needs CC restart), holding for your go.

Updating plan ledger to record publish landed.


Edit

  dry-run green; llms.txt regen = no drift. Gate PASS + traceable green.
  **Remaining = OPERATOR's step only:** `package-skeleton.sh --apply` → cplugs commit/push →
  `claude plugin install sptc@cplugs`. Plan stops at validated dry-run (credentials + pointer flip
  are operator-owned).

  dry-run green; llms.txt regen = no drift. Gate PASS + traceable green.
- ✅ **PUBLISHED (2026-06-15, operator-authorized)** — `package-skeleton.sh --apply` staged the
  skeleton into the cplugs clone; `sptc` registered in `marketplace.json` (first publish — added
  alongside legacy `spt`/screen-timelapse/everything); cplugs commit **b1e2895** ("sptc: first
  publish — spt adapter skeleton v0.1.0") pushed to `SaberMage/cplugs` main (33927ca..b1e2895).
  **Remaining = pointer flip only:** `claude plugin install sptc@cplugs` + `/reload-plugins`
  (session-affecting — needs CC restart; held for operator).


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

  dry-run green; llms.txt regen = no drift. Gate PASS + traceable green.
- ✅ **PUBLISHED (2026-06-15, operator-authorized)** — `package-skeleton.sh --apply` staged the
  skeleton into the cplugs clone; `sptc` registered in `marketplace.json` (first publish — added
  alongside legacy `spt`/screen-timelapse/everything); cplugs commit **b1e2895** ("sptc: first
  publish — spt adapter skeleton v0.1.0") pushed to `SaberMage/cplugs` main (33927ca..b1e2895).
  **Remaining = pointer flip only:** `claude plugin install sptc@cplugs` + `/reload-plugins`
  (session-affecting — needs CC restart; held for operator).

# JIT plan — parity audit → fill LOCKED-ADD gaps → cplugs publish (as sptc)

> Next slice after the live sub-slice (4b042cc) + F-004 flip (692b67c). Goal: PROVE parity
> against the SCOPE.md LOCKED parity-trim, fill the remaining LOCKED-ADD gaps, then publish the
> thin skeleton to cplugs **as `sptc`** (NOT `spt` — succession flip stays gated, see
> [[succession-flip-gated]] / RELEASE-RUNBOOK). Public-surface-only still binds (AGENTS.md).

## Operator decisions (locked this session, 2026-06-15)
1. **Slice = audit + fill gaps + publish.** Build the absent LOCKED-ADD surface (subnet skills,
   ccs profiles), reconcile whoami, THEN publish as sptc. `new-alarm` stays **deferred** — doyle
   TRIAGED it (high-prio 2026-06-15) as an **ACCEPTED parity gap = "deferred-pending-arrangement-
   system", NOT missing**: spt-core has only the alarm event shape + relay handling + a test
   fixture; the durable timer is a deliberate deferral (DEFERRED.md:43, ADR-0018 Q4/V3), and the
   operator has a superseding "arrangement" system in mind. **Do NOT build an adapter-side stopgap
   timer** (throwaway vs the coming model), **no REQ minted**. Remove the dead stub (deferred ≠
   shipping a no-op skill); doyle loops me when the arrangement design surfaces.
2. **Drop the `/whoami` SKILL.** Honor the LOCKED SCOPE decision — core `spt whoami` stays
   (becomes the `endpoint list` alias in M12); the adapter ships no whoami skill.

## Parity matrix (current vs SCOPE LOCKED parity-trim)

| Legacy / target surface        | SCOPE disposition        | Adapter today          | Action (this slice)            |
|--------------------------------|--------------------------|------------------------|--------------------------------|
| /live /commune /ready /send    | KEEP                     | operative (file-backed)| ✓ none                         |
| /list-agents /signoff /force-stop | KEEP                  | operative              | ✓ none                         |
| /new-alarm                     | ACCEPTED GAP (deferred-pending-arrangement-system) | dead stub, no manifest | **remove stub**; no REQ, no build |
| /spt:setup /spt:version        | ADD                      | operative              | ✓ none                         |
| profiles + strings + hints     | ADD                      | wired (deep/live)      | ✓ none                         |
| **subnet skills (create/join/show-code)** | ADD (LOCKED)  | **ABSENT**             | **BUILD** (Phase C)            |
| **ccs profiles (claude-spt:glm …)** | ADD (LOCKED)        | **ABSENT**             | **BUILD** (Phase D)            |
| /whoami SKILL                  | DROP skill               | **operative (violation)** | **REMOVE** (Phase B)        |
| /fork /amend-signoff /revive /clear-psyche | DROP         | absent                 | ✓ none (confirm absent)        |

Public surface confirms the ADD gaps are buildable: `spt subnet {create,join,show-code,status}`
exists; ccs = profile overlays retargeting command templates (SCOPE §ccs, profile *templates*
only — user supplies their own ccs config/keys).

## Progress (this session)
- ✅ **Phase A** (b1db67f) — docs/PARITY.md matrix + REQ seed (REQ-PARITY-AUDIT [doc] satisfied;
  REQ-SKILL-SUBNET / REQ-CCS-PROFILES seeded). DROP set confirmed absent.
- ✅ **Phase B** (0595910) — whoami skill DROPPED (manifest + body + stub + hint + test repoints);
  dead new-alarm stub removed. Surface 11→9.
- ✅ **Phase C** (e3382a0) — /sptc:subnet skill added (one skill wrapping `spt subnet`).
  REQ-SKILL-SUBNET [doc,int] green on v0.7.2. how-to-subnet finding logged. Surface 9→10.
- ✅ **Phase D** (b15c1bf) — `claude-spt:ccs` profile. Scoped to bare `ccs` (default account, NOT
  glm/kimi — operator ruling); validated vs sister project claude_skill_owl. Spawn seam
  (`[profiles.ccs.session.self].command = "ccs"`, a drop-in for `claude`) + observability string
  leaf. Log-dir seam landed IN the extractor: claude-spt-digest now honors `CLAUDE_CONFIG_DIR`
  (owl `owlery::claude_projects_root` parity) — ccs relocates CC's transcript tree per-account, a
  runtime value with no static path, so no `[profiles.ccs.digest]` leaf. REQ-CCS-PROFILES
  [doc,impl,unit,int] green. Finding logged (SCOPE conflated ccs profiles vs accounts).
  **docs/PARITY.md verdict → PROVEN (adapter surface).** Gate PASS; registration-int OK on v0.7.2.
- ✅ **Phase E** (publish prep as sptc) — CHANGELOG.md created (`## [0.1.0] - 2026-06-15`,
  user-facing UX only); plugin.json bumped 0.0.1→0.1.0 (name stays `sptc`; version independent of
  the adapter-manifest version per RUNBOOK). validate-skeleton INSTALLABLE + package-skeleton
  dry-run green; llms.txt regen = no drift. Gate PASS + traceable green.
  **Remaining = OPERATOR's step only:** `package-skeleton.sh --apply` → cplugs commit/push →
  `claude plugin install sptc@cplugs`. Plan stops at validated dry-run (credentials + pointer flip
  are operator-owned).

## Phases (sequence; one commit + green gate each)

### Phase A — Parity audit artifact + REQ seed
- Write `docs/PARITY.md` (the matrix above + per-row evidence/finding) — the "proven parity"
  record the succession flip gates on. Tag `<!-- doc->REQ-PARITY-AUDIT -->`.
- Seed REQs in `traceable-reqs.toml` FIRST (before building): `REQ-SKILL-SUBNET`,
  `REQ-CCS-PROFILES`, `REQ-PARITY-AUDIT`. Activate stages as each phase lands.
- Confirm the DROP set is truly absent (grep no fork/revive/clear-psyche/amend-signoff residue).

### Phase B — Drop the whoami skill (honor LOCKED)
- Remove `whoami = { file = "skills/whoami.md" }` from manifest `[strings.skills]`.
- Delete `adapter/strings/skills/whoami.md` + `plugin/sptc/skills/whoami/`.
- **registration-int.sh** uses `skills.whoami` as the canonical file-backed + UPS-injection
  example (4b/4c) — repoint to a surviving skill (`skills.ready`).
- Redirect the `who am i` **hint** (currently → /sptc:whoami) to core `spt whoami` guidance.
- Audit REQ evidence: nothing is tagged `REQ-*` on whoami.md directly, but check
  `tests/hooks-parse.sh` / manifest-shortcut for whoami coupling before deleting.

### Phase C — Subnet skills (LOCKED ADD; public verbs exist)
- **Open shape decision (resolve at top of phase):** three skills
  (`/sptc:subnet-create|join|show-code`) vs one routing `/sptc:subnet` skill. Lean: match SCOPE's
  enumeration but as ONE `subnet` skill body that documents create/join/show-code (fewer
  surfaces, cleaner UX) — confirm before authoring.
- File-backed body(ies) `adapter/strings/skills/subnet*.md` (run `spt how-to subnet` / wrap the
  real `spt subnet …` verbs); manifest `[strings.skills]` entries; thin SKILL.md stub(s); hint(s).
- `REQ-SKILL-SUBNET` [doc,impl] (+ int via registration-int file-backed-resolve assertion).

### Phase D — ccs profiles (LOCKED ADD)
- **Research first** (mcp/context7 not needed — read SCOPE §ccs + the existing `[profiles.*]`
  command seams). ccs profile = a `[profiles.<glm|kimi>]` overlay that leaf-replaces the spawn /
  psyche / echo command templates to route through `ccs <profile> …`, with a per-profile `~/.ccs`
  log dir. Author profile *templates* only (no user keys).
- Add `[profiles.glm]` (+ maybe `[profiles.kimi]`) overlays; observable via `spt adapter
  get-string claude-spt:glm …` + resolves in registration-int (mirror the :deep/:live assertions).
- `REQ-CCS-PROFILES` [doc,impl] (+ int).

### Phase E — Publish prep (as sptc; NO name flip)
- **Create `CHANGELOG.md`** with a `## [<version>] - 2026-06-15` section (Added/Changed/Fixed,
  user-facing UX only, no internal lingo) — release fails loudly without it.
- **Bump `plugin.json`** `version` 0.0.1 → first real (structural first publish). Keep `name=sptc`.
- Run `sh ci/publish/validate-skeleton.sh` + `sh ci/publish/package-skeleton.sh` (DRY-RUN) green.
- Regenerate docs (mdBook + llms.txt) — drift gate green.
- The actual cplugs commit/push + `claude plugin install sptc@cplugs` stays the **operator's**
  step (credentials + pointer flip) — plan stops at a validated dry-run + a publish checklist.

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

## Open questions (resolve in-phase, don't block planning)
- Subnet skill shape: 3 skills vs 1 routing skill (Phase C top).
- ccs: which profiles ship as templates (glm only, or glm+kimi)? SCOPE names `claude-spt:glm`.
- plugin.json first-publish version number (0.1.0? matches adapter manifest 0.1.0, but RUNBOOK
  says keep them DISTINCT — pick independently).

## Findings carried (not ours to fix)
- new-alarm core alarm/deferred-pulse primitive (blocks new-alarm parity) — doyle.
- hard/no-grace force-stop primitive — doyle.
- Live relay int held for spt-core M11 counter-15 release ([[live-int-gated-m11-counter15]]).

## Done immediately before (context)
- 4b042cc live sub-slice (claude-spt-psyche runner + /sptc:live body, REQ-SKILL-LIVE [doc,impl,unit]).
- 692b67c F-004 flip (digest-proof int GREEN on v0.7.2, REQ-DIST-DIGEST-EXTRACTOR full).
- spt upgraded 0.7.1 → 0.7.2 (operator-approved daemon bounce).

-  **Remaining = OPERATOR's step only:** `package-skeleton.sh --apply` → cplugs commit/push →

-  `claude plugin install sptc@cplugs`. Plan stops at validated dry-run (credentials + pointer flip

+- ✅ **PUBLISHED (2026-06-15, operator-authorized)** — `package-skeleton.sh --apply` staged the

+  skeleton into the cplugs clone; `sptc` registered in `marketplace.json` (first publish — added

+  alongside legacy `spt`/screen-timelapse/everything); cplugs commit **b1e2895** ("sptc: first

+  publish — spt adapter skeleton v0.1.0") pushed to `SaberMage/cplugs` main (33927ca..b1e2895).

+  **Remaining = pointer flip only:** `claude plugin install sptc@cplugs` + `/reload-plugins`

+  (session-affecting — needs CC restart; held for operator).


Plan updated. Committing the ledger note to spt-claude-code.


Bash

cd "C:/Users/decid/Documents/projects/spt-claude-code" && git add PARITY-PUBLISH-PLAN.md && git commit -m "docs(plan): record cplugs first-publish landed (sptc v0.1.0, b1e2895)

Publish step ran operator-authorized: --apply staged the skeleton, sptc
registered in cplugs marketplace.json, commit b1e2895 pushed to
SaberMage/cplugs main. Only the pointer-flip (plugin install) remains.

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

Commit plan ledger note


[main 22102ee] docs(plan): record cplugs first-publish landed (sptc v0.1.0, b1e2895)
 1 file changed, 6 insertions(+), 3 deletions(-)


**Publish landed.** Summary:

| Step | Result |
|------|--------|
| `package-skeleton.sh --apply` | validated INSTALLABLE → staged skeleton into cplugs clone |
| `marketplace.json` register | added `sptc` entry (first publish; alongside spt/screen-timelapse/everything) |
| cplugs commit + push | **b1e2895** → `SaberMage/cplugs` main (`33927ca..b1e2895`) ✓ |
| spt-claude-code ledger | **22102ee** (local; not pushed — only cplugs push was authorized) |

`sptc` v0.1.0 now live on cplugs. 10 skills, hooks, bootstrap — no binary, no manifest (those ride spt-core registry).

**Pending your call:**
- **Pointer flip** — `claude plugin install sptc@cplugs` + `/reload-plugins`, then restart CC. Session-affecting; your go.
- **spt-claude-code push** — local commit 22102ee unpushed (you only authorized cplugs). Push it?

Succession flip (sptc→spt) still gated: needs legacy owl retired + spt-core M11 counter-15. Not touched.

Want pointer flip + repo push now?


installed the plugin. this is an agent's reaction to the setup skill, but two things: 1. the harness adapter surely isn't setup yet. its manifest needs installed via spt-core, and 2. aren't there supposed to be branching paths for the setup skill when spt-core is already installed? please confirm against CONTEXT.md/other relevant docs


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


installed the plugin. this is an agent's reaction to the setup skill, but two things: 1. the harness adapter surely isn't setup yet. its manifest needs installed via spt-core, and 2. aren't there supposed to be branching paths for the setup skill when spt-core is already installed? please confirm against CONTEXT.md/other relevant docs [Image #1]


[Image: source: C:\Users\decid\Documents\ShareX\Screenshots\2026-06\WindowsTerminal_d9w41EcoBV.png]


installed the plugin. this is an agent's reaction to the setup skill, but two things: 1. the harness adapter surely isn't setup yet. its manifest needs installed via spt-core, and 2. aren't there supp…


Reading setup skill body + CONTEXT against the screenshot's behavior.


1	---
2	name: setup
3	description: |
4	  Install or repair spt-core for this Claude Code session (mid-session installer).
5	allowed-tools: [Bash]
6	---
7
8	# /sptc:setup
9
10	> **Self-contained by necessity.** Unlike other `/sptc:*` skills, `setup` cannot rely on
11	> UPS-injection of its body: it runs precisely when spt-core may be **absent**, so
12	> `spt adapter get-string` (the injection source) is unavailable. The operative steps therefore live
13	> in this SKILL.md (the floor); the file-backed `[strings.skills].setup` body mirrors them for the
14	> spt-present repair path. See `docs/adr/0001-distribution-splits-by-volatility.md`.
15
16	Covers the mid-session install gap (ADR-0001): a user who installs the plugin mid-session has not had
17	a SessionStart bootstrap fire, so `/sptc:setup` runs the same invisible-installer bootstrap to fetch +
18	verify spt-core on demand.
19
20	**Do this:**
21
22	1. If spt-core is already present (`command -v spt && spt --version`), report the version and stop.
23	2. Otherwise run the published install-on-demand bootstrap (spt-releases
24	   `harness-contract/install-on-demand.md`):
25	   - **POSIX:** `curl -fsSL https://sabermage.github.io/spt-releases/install.sh | sh`
26	   - **Windows (PowerShell):** `irm https://sabermage.github.io/spt-releases/install.ps1 | iex`
27	3. `PATH` is not reloaded in this shell after a fresh install — verify with the absolute path:
28	   `"$HOME/.local/bin/spt" --version`. After this, `spt update` handles signed self-updates.
29

---
name: setup
description: |
  Install or repair spt-core for this Claude Code session (mid-session installer).
allowed-tools: [Bash]
---

# /sptc:setup

> **Self-contained by necessity.** Unlike other `/sptc:*` skills, `setup` cannot rely on
> UPS-injection of its body: it runs precisely when spt-core may be **absent**, so
> `spt adapter get-string` (the injection source) is unavailable. The operative steps therefore live
> in this SKILL.md (the floor); the file-backed `[strings.skills].setup` body mirrors them for the
> spt-present repair path. See `docs/adr/0001-distribution-splits-by-volatility.md`.

Covers the mid-session install gap (ADR-0001): a user who installs the plugin mid-session has not had
a SessionStart bootstrap fire, so `/sptc:setup` runs the same invisible-installer bootstrap to fetch +
verify spt-core on demand.

**Do this:**

1. If spt-core is already present (`command -v spt && spt --version`), report the version and stop.
2. Otherwise run the published install-on-demand bootstrap (spt-releases
   `harness-contract/install-on-demand.md`):
   - **POSIX:** `curl -fsSL https://sabermage.github.io/spt-releases/install.sh | sh`
   - **Windows (PowerShell):** `irm https://sabermage.github.io/spt-releases/install.ps1 | iex`
3. `PATH` is not reloaded in this shell after a fresh install — verify with the absolute path:
   `"$HOME/.local/bin/spt" --version`. After this, `spt update` handles signed self-updates.


CONTEXT.md


1	# /sptc:setup — operative instructions
2
3	> Delivered file-backed via the `claude-spt` adapter `[strings]`
4	> (`[strings.skills].setup = { file = "skills/setup.md" }`), resolved at injection time. The cplugs
5	> SKILL.md stays a thin skeleton (ADR-0001).
6
7	**Goal:** install or repair spt-core for this session — the mid-session installer that covers the
8	gap when no SessionStart bootstrap has fired (a user who installs the plugin mid-session).
9
10	**Do this:**
11
12	1. Check whether spt-core is already present: `command -v spt && spt --version`. If it reports a
13	   version, spt-core is installed — nothing to do; report the version and stop.
14	2. Otherwise run the published install-on-demand bootstrap (verbatim against the spt-releases
15	   contract, `harness-contract/install-on-demand.md`):
16	   - **POSIX:** `curl -fsSL https://sabermage.github.io/spt-releases/install.sh | sh`
17	   - **Windows (PowerShell):** `irm https://sabermage.github.io/spt-releases/install.ps1 | iex`
18	3. `PATH` is not reloaded in the current shell after a fresh install — verify with the absolute
19	   path for the first call: `"$HOME/.local/bin/spt" --version` (POSIX). Report the version.
20	4. After this initial bootstrap, `spt update` handles signed self-updates automatically — the user
21	   does not run setup again.
22
23	This is the same bootstrap the SessionStart hook runs; it is idempotent and safe to re-run.
24

# /sptc:setup — operative instructions

> Delivered file-backed via the `claude-spt` adapter `[strings]`
> (`[strings.skills].setup = { file = "skills/setup.md" }`), resolved at injection time. The cplugs
> SKILL.md stays a thin skeleton (ADR-0001).

**Goal:** install or repair spt-core for this session — the mid-session installer that covers the
gap when no SessionStart bootstrap has fired (a user who installs the plugin mid-session).

**Do this:**

1. Check whether spt-core is already present: `command -v spt && spt --version`. If it reports a
   version, spt-core is installed — nothing to do; report the version and stop.
2. Otherwise run the published install-on-demand bootstrap (verbatim against the spt-releases
   contract, `harness-contract/install-on-demand.md`):
   - **POSIX:** `curl -fsSL https://sabermage.github.io/spt-releases/install.sh | sh`
   - **Windows (PowerShell):** `irm https://sabermage.github.io/spt-releases/install.ps1 | iex`
3. `PATH` is not reloaded in the current shell after a fresh install — verify with the absolute
   path for the first call: `"$HOME/.local/bin/spt" --version` (POSIX). Report the version.
4. After this initial bootstrap, `spt update` handles signed self-updates automatically — the user
   does not run setup again.

This is the same bootstrap the SessionStart hook runs; it is idempotent and safe to re-run.


1	# spt-claude-code — glossary
2
3	> Authoritative for meaning (grill-with-docs convention). Glossary only — no
4	> implementation detail. Decisions/rationale live in `SCOPE.md` and `docs/adr/`.
5
6	**spt-claude-code** — the rebuilt Claude Code harness adapter. The `claude-spt`
7	adapter in spt-core terms. Simultaneously spt-core's v1 acceptance proof (legacy
8	parity), its first casual-end-user entrypoint (a CC plugin), and an invisible spt-core
9	installer. Built by maintainer perri from the public spt-releases surface only.
10
11	**claude-spt** — the adapter_name spt-claude-code registers under (rides every `api`
12	invocation + the manifest). The CC adapter's identity inside spt-core.
13
14	**legacy spt / `claude_skill_owl`** — the sister project; today's shipped CC integration
15	(owl.exe + `spt` plugin, v1.11.25). The parity *target* (user-facing features), not a
16	1:1 port — most of its machinery now lives in spt.exe.
17
18	**skeleton plugin** — the thin marketplace artifact on `SaberMage/cplugs`: namespaced
19	`/spt:*` skill stubs + hooks + a SessionStart bootstrap that installs spt-core. Low-churn;
20	the volatile bulk (binary + manifest) is spt-core-conducted, not in the plugin.
21
22	**fetch-stub skill** — a `/spt:X` SKILL.md that is a 2-line stub fetching its real
23	instructions at runtime from the adapter `[strings]` (`spt adapter get-string`/`skill-help`).
24	Keeps skill files static while instructions update via spt-core. Distinct from a `[hints]`
25	entry (proactive, keyword-triggered, UPS-hook-delivered).
26
27	**ccs profile** — a profile under spt-claude-code (`claude-spt:glm`, `claude-spt:kimi`)
28	that leaf-replaces the launch command + history/digest log dir to use the `ccs` backend.
29	NOT its own adapter — ccs is structurally Claude Code.
30
31	**`cc` launcher (capsule-style)** — a generated `cc`/`cc <id>` script at project root that
32	spawns-or-attaches a CC endpoint via spt-core's spt-hosted topology (broker PTY + inject +
33	attach). The spt-core realization of legacy's unbuilt "Capsule" milestone. _Avoid_: equating
34	it with psmux/sendkeys — spt-core's broker is the terminal host.
35
36	**casual end user** — a user who *uses* an spt-powered system mostly-invisibly, vs the
37	adapter/shell *developer* who is spt-core's nominal target. spt-claude-code serves casual
38	users: install the plugin, get spt-core for free.
39
40	**experimplate** — the standalone reusable project-workflow template (its own sibling repo)
41	extracted from spt-core's working style. spt-claude-code is its first consumer. Carries
42	traceable-reqs gating, JIT plans, grill-with-docs scaffolding, release/changelog, and
43	same-repo published-docs. Defined in its own folder, not here.
44

# spt-claude-code — glossary

> Authoritative for meaning (grill-with-docs convention). Glossary only — no
> implementation detail. Decisions/rationale live in `SCOPE.md` and `docs/adr/`.

**spt-claude-code** — the rebuilt Claude Code harness adapter. The `claude-spt`
adapter in spt-core terms. Simultaneously spt-core's v1 acceptance proof (legacy
parity), its first casual-end-user entrypoint (a CC plugin), and an invisible spt-core
installer. Built by maintainer perri from the public spt-releases surface only.

**claude-spt** — the adapter_name spt-claude-code registers under (rides every `api`
invocation + the manifest). The CC adapter's identity inside spt-core.

**legacy spt / `claude_skill_owl`** — the sister project; today's shipped CC integration
(owl.exe + `spt` plugin, v1.11.25). The parity *target* (user-facing features), not a
1:1 port — most of its machinery now lives in spt.exe.

**skeleton plugin** — the thin marketplace artifact on `SaberMage/cplugs`: namespaced
`/spt:*` skill stubs + hooks + a SessionStart bootstrap that installs spt-core. Low-churn;
the volatile bulk (binary + manifest) is spt-core-conducted, not in the plugin.

**fetch-stub skill** — a `/spt:X` SKILL.md that is a 2-line stub fetching its real
instructions at runtime from the adapter `[strings]` (`spt adapter get-string`/`skill-help`).
Keeps skill files static while instructions update via spt-core. Distinct from a `[hints]`
entry (proactive, keyword-triggered, UPS-hook-delivered).

**ccs profile** — a profile under spt-claude-code (`claude-spt:glm`, `claude-spt:kimi`)
that leaf-replaces the launch command + history/digest log dir to use the `ccs` backend.
NOT its own adapter — ccs is structurally Claude Code.

**`cc` launcher (capsule-style)** — a generated `cc`/`cc <id>` script at project root that
spawns-or-attaches a CC endpoint via spt-core's spt-hosted topology (broker PTY + inject +
attach). The spt-core realization of legacy's unbuilt "Capsule" milestone. _Avoid_: equating
it with psmux/sendkeys — spt-core's broker is the terminal host.

**casual end user** — a user who *uses* an spt-powered system mostly-invisibly, vs the
adapter/shell *developer* who is spt-core's nominal target. spt-claude-code serves casual
users: install the plugin, get spt-core for free.

**experimplate** — the standalone reusable project-workflow template (its own sibling repo)
extracted from spt-core's working style. spt-claude-code is its first consumer. Carries
traceable-reqs gating, JIT plans, grill-with-docs scaffolding, release/changelog, and
same-repo published-docs. Defined in its own folder, not here.


Setup skill scope confirmed: spt-core **binary** installer only. Checking ADR-0001 + SCOPE for whether manifest registration / richer branching was specified.


1	<!-- [doc->REQ-DIST-PLUGIN-SKELETON] -->
2	<!-- [doc->REQ-DIST-HOOKS-API] -->
3	<!-- [doc->REQ-DIST-BOOTSTRAP-INSTALL] -->
4	<!-- [doc->REQ-UPS-INJECTION] -->
5	# Distribution splits by volatility: a thin skeleton plugin, an spt-conducted manifest + binary
6
7	## Status
8
9	accepted (2026-06-14)
10
11	## Context
12
13	`spt-claude-code` is the `claude-spt` adapter — simultaneously spt-core's v1 acceptance proof,
14	its first casual-end-user entrypoint (a Claude Code plugin on `SaberMage/cplugs`), and an
15	invisible spt-core installer. It must ship as a CC plugin, yet almost all real logic now lives
16	inside the `spt` binary and the CC adapter manifest, both **conducted by spt-core**, not by the
17	plugin author.
18
19	Forces:
20
21	1. **Two very different churn rates.** Skill *instructions*, the `[digest]` extractor, profiles,
22	   strings, and hints change often. The plugin's *structure* (which skills exist, hook wiring,
23	   bootstrap) changes rarely. Coupling them to one release cadence means either over-bumping the
24	   marketplace or letting logic rot.
25	2. **Claude Code has no plugin-file integrity check.** In-place edits to an installed plugin do
26	   not orphan it; only *old version directories* orphan on a version bump (GC'd after 7 days).
27	   So low-churn structure is safe to ship via the marketplace, and high-churn logic does *not*
28	   need to ride the marketplace at all.
29	3. **The skill `/spt:` namespace must be preserved** (legacy parity). User-scope skills under
30	   `~/.claude/skills` cannot namespace (they surface as bare `/live`, collision-prone), so skills
31	   must stay **plugin-provided**.
32	4. **Users install mid-session**, so the plugin cannot assume a SessionStart fire has installed
33	   spt-core; the bootstrap and a `/spt:setup` skill must cover the gap.
34
35	## Decision
36
37	Split the adapter across **three layers by volatility** (see `SCOPE.md` §"Distribution
38	architecture"):
39
40	| Layer | Contents | Home | Churn |
41	|---|---|---|---|
42	| **Skeleton plugin** | namespaced `/spt:*` skill *skeletons*, `hooks.json`, SessionStart bootstrap, `plugin.json` | `SaberMage/cplugs` | low |
43	| **spt binary** | all logic | spt-core domain (signed, peer-propagated) | high |
44	| **CC adapter manifest** | `[digest]` extractor, profiles, strings, hints | spt-core adapter registry (**not** plugin files) | medium |
45
46	Concretely:
47
48	- **The marketplace plugin is a true thin skeleton.** It carries skill *skeletons* (frontmatter
49	  + a stub body), `hooks.json`, a SessionStart bootstrap, and `plugin.json` — **no binary, no
50	  manifest, no embedded logic.** [`REQ-DIST-PLUGIN-SKELETON`]
51	- **`hooks.json` delegates to `spt api`** rather than carrying adapter behavior. The hook commands
52	  invoke the spt binary's published `api` surface; the plugin ships no binary of its own (contrast
53	  legacy, which shipped `owl.exe` and called it directly). [`REQ-DIST-HOOKS-API`]
54	- **A SessionStart bootstrap installs spt-core when absent** — the invisible-installer pattern.
55	  A user who installs the plugin gets spt-core for free. [`REQ-DIST-BOOTSTRAP-INSTALL`]
56	- **Skill instructions are delivered by UPS-injection.** A `UserPromptSubmit` hook detects `/spt:X`
57	  in the prompt and injects X's real instructions as `additionalContext`, sourced from the adapter
58	  `[strings]` (file-backed, so the manifest doesn't bloat). SKILL.md files stay skeletons; the
59	  volatile instruction text lives in spt-core-conducted strings. [`REQ-UPS-INJECTION`]
60	- **The "bulk" install/update is manifest + binary**, conducted by spt-core's own framework (the
61	  file-pull channel), not a marketplace bump. The marketplace plugin rarely needs a version bump
62	  and never orphans an active install.
63
64	### Rejected alternatives
65
66	- **Global user-scope skills** (`~/.claude/skills`) — lose the `/spt:` namespace (bare `/live`,
67	  collision-prone). Rejected.
68	- **fetch-stub skills** (SKILL.md fetches its real body at runtime) — VETOED by the operator:
69	  adds terminal noise, latency, and an extra tool call per invocation. UPS-injection chosen
70	  instead. (`SCOPE.md` §"Skill-instruction delivery".)
71	- **A fat plugin shipping the binary** (legacy `owl.exe` model) — couples high-churn logic to the
72	  marketplace cadence and forces the binary/handoff/cache-prune machinery the thin skeleton has no
73	  need for. Rejected; logic rides the spt binary + adapter registry.
74
75	### Open / to-confirm
76
77	- **UPS-fires-on-slash-command — CONFIRMED (2026-06-15, ADR-0002 validation).** `UserPromptSubmit`
78	  fires on a `/sptc:X` slash-command with the token intact (`prompt:"/sptc:send doyle"` literal, hook
79	  fired, skill ran, on CC 2.1.177). The injection branch is built (`user-prompt-submit.sh`
80	  `sptc_skill_key` + `sptc_inject_skill`); the in-SKILL.md fallback is unneeded for injection (but
81	  `setup` stays self-contained — it runs when spt may be absent). (`REQ-UPS-INJECTION`.)
82	- **File-backed `[strings]` is an M12 spt-core dependency** — until M12 publishes, instruction
83	  bodies cannot be externalized; skeleton SKILL.md files may carry interim inline instructions.
84	  **Update 2026-06-15 — SATISFIED.** M12 (`spt 0.7.0`) ships file-backed `[strings]` as a
85	  value-position table pointer: `key = { file = "rel" }` over the per-adapter aux dir
86	  `adapters/<adapter>/strings/`, resolved lazily at `get-string` (containment-checked; copied on
87	  `adapter add`). Confirmed by live byte-test + spt-core ruling (`REQ-MANIFEST-5`, M12-W3). The
88	  dependency is met — skill bodies are externalized via this pointer (no manifest bloat); the
89	  interim-inline fallback is retired. The pointer syntax was merely **undocumented** on the published
90	  surface (now finding **F-003**, docs-only, doyle publishing). See `docs/SPT-CORE-FINDINGS.md`.
91
92	## Consequences
93
94	<!-- [doc->REQ-DIST-MANIFEST-SCHEMA] -->
95	- The marketplace plugin can sit static across many manifest/binary updates → the
96	  version-of-truth is the spt-core-tracked manifest/binary version (`spt adapter list` /
97	  `/spt:version`), **not** the marketplace `plugin.json` version. The CC adapter manifest
98	  (`adapter/claude-spt.toml`) is authored against spt-core's **published** `manifest.schema.json`
99	  (vendored at `adapter/manifest.schema.json`) and CI-gated against it (`ci/manifest/`). These are distinct numbers on
100	  independent schedules (see `docs/RELEASE-RUNBOOK.md`).
101	- New obligation: a dual update path kept in sync — file-pull (real) + a cautionary
102	  `claude plugin update` (skeleton sync only).
103	<!-- [doc->REQ-DIST-SHORTCUT-BASENAME] -->
104	- The manifest brands the `spt endpoint run` launcher shortcut **`cc-<id>`** via
105	  `shortcut_basename = "cc"` (the M12 `cc` launcher; the harness-agnostic default would be
106	  `spt-<id>`, and it matches the schema's own `spt-claude-code → cc` example). This launcher brand
107	  is **decoupled** from the `sptc` plugin name — the `s/sptc/spt/` succession (next bullet) renames
108	  the plugin, not this shortcut. (Operator-ruled 2026-06-15.)
109	- Forces the cplugs **plugin-name** question, now **ruled (operator, 2026-06-14)**: because CC
110	  invokes skills as `/<plugin>:<skill>` (the skill prefix is hard-tied to the `plugin.json` name —
111	  no override; confirmed against the official plugin docs), the marketplace plugin is named
112	  **`sptc`** and skills surface as **`/sptc:*`** for now. **Succession plan:** once `spt-claude-code`
113	  proves parity, flip `plugin.json` name `sptc`→`spt` (skills become `/spt:*`) and retire/rename
114	  legacy owl's cplugs `spt` plugin in the same coordinated move (two plugins cannot share the
115	  `spt` name). `sptc` is the single-substitution seam — the flip is `s/sptc/spt/`.
116	- Mints no new REQs beyond those already seeded for the skeleton milestone; this ADR is the
117	  `doc`-stage evidence for `REQ-DIST-PLUGIN-SKELETON`, `REQ-DIST-HOOKS-API`,
118	  `REQ-DIST-BOOTSTRAP-INSTALL`, and `REQ-UPS-INJECTION`.
119

<!-- [doc->REQ-DIST-PLUGIN-SKELETON] -->
<!-- [doc->REQ-DIST-HOOKS-API] -->
<!-- [doc->REQ-DIST-BOOTSTRAP-INSTALL] -->
<!-- [doc->REQ-UPS-INJECTION] -->
# Distribution splits by volatility: a thin skeleton plugin, an spt-conducted manifest + binary

## Status

accepted (2026-06-14)

## Context

`spt-claude-code` is the `claude-spt` adapter — simultaneously spt-core's v1 acceptance proof,
its first casual-end-user entrypoint (a Claude Code plugin on `SaberMage/cplugs`), and an
invisible spt-core installer. It must ship as a CC plugin, yet almost all real logic now lives
inside the `spt` binary and the CC adapter manifest, both **conducted by spt-core**, not by the
plugin author.

Forces:

1. **Two very different churn rates.** Skill *instructions*, the `[digest]` extractor, profiles,
   strings, and hints change often. The plugin's *structure* (which skills exist, hook wiring,
   bootstrap) changes rarely. Coupling them to one release cadence means either over-bumping the
   marketplace or letting logic rot.
2. **Claude Code has no plugin-file integrity check.** In-place edits to an installed plugin do
   not orphan it; only *old version directories* orphan on a version bump (GC'd after 7 days).
   So low-churn structure is safe to ship via the marketplace, and high-churn logic does *not*
   need to ride the marketplace at all.
3. **The skill `/spt:` namespace must be preserved** (legacy parity). User-scope skills under
   `~/.claude/skills` cannot namespace (they surface as bare `/live`, collision-prone), so skills
   must stay **plugin-provided**.
4. **Users install mid-session**, so the plugin cannot assume a SessionStart fire has installed
   spt-core; the bootstrap and a `/spt:setup` skill must cover the gap.

## Decision

Split the adapter across **three layers by volatility** (see `SCOPE.md` §"Distribution
architecture"):

| Layer | Contents | Home | Churn |
|---|---|---|---|
| **Skeleton plugin** | namespaced `/spt:*` skill *skeletons*, `hooks.json`, SessionStart bootstrap, `plugin.json` | `SaberMage/cplugs` | low |
| **spt binary** | all logic | spt-core domain (signed, peer-propagated) | high |
| **CC adapter manifest** | `[digest]` extractor, profiles, strings, hints | spt-core adapter registry (**not** plugin files) | medium |

Concretely:

- **The marketplace plugin is a true thin skeleton.** It carries skill *skeletons* (frontmatter
  + a stub body), `hooks.json`, a SessionStart bootstrap, and `plugin.json` — **no binary, no
  manifest, no embedded logic.** [`REQ-DIST-PLUGIN-SKELETON`]
- **`hooks.json` delegates to `spt api`** rather than carrying adapter behavior. The hook commands
  invoke the spt binary's published `api` surface; the plugin ships no binary of its own (contrast
  legacy, which shipped `owl.exe` and called it directly). [`REQ-DIST-HOOKS-API`]
- **A SessionStart bootstrap installs spt-core when absent** — the invisible-installer pattern.
  A user who installs the plugin gets spt-core for free. [`REQ-DIST-BOOTSTRAP-INSTALL`]
- **Skill instructions are delivered by UPS-injection.** A `UserPromptSubmit` hook detects `/spt:X`
  in the prompt and injects X's real instructions as `additionalContext`, sourced from the adapter
  `[strings]` (file-backed, so the manifest doesn't bloat). SKILL.md files stay skeletons; the
  volatile instruction text lives in spt-core-conducted strings. [`REQ-UPS-INJECTION`]
- **The "bulk" install/update is manifest + binary**, conducted by spt-core's own framework (the
  file-pull channel), not a marketplace bump. The marketplace plugin rarely needs a version bump
  and never orphans an active install.

### Rejected alternatives

- **Global user-scope skills** (`~/.claude/skills`) — lose the `/spt:` namespace (bare `/live`,
  collision-prone). Rejected.
- **fetch-stub skills** (SKILL.md fetches its real body at runtime) — VETOED by the operator:
  adds terminal noise, latency, and an extra tool call per invocation. UPS-injection chosen
  instead. (`SCOPE.md` §"Skill-instruction delivery".)
- **A fat plugin shipping the binary** (legacy `owl.exe` model) — couples high-churn logic to the
  marketplace cadence and forces the binary/handoff/cache-prune machinery the thin skeleton has no
  need for. Rejected; logic rides the spt binary + adapter registry.

### Open / to-confirm

- **UPS-fires-on-slash-command — CONFIRMED (2026-06-15, ADR-0002 validation).** `UserPromptSubmit`
  fires on a `/sptc:X` slash-command with the token intact (`prompt:"/sptc:send doyle"` literal, hook
  fired, skill ran, on CC 2.1.177). The injection branch is built (`user-prompt-submit.sh`
  `sptc_skill_key` + `sptc_inject_skill`); the in-SKILL.md fallback is unneeded for injection (but
  `setup` stays self-contained — it runs when spt may be absent). (`REQ-UPS-INJECTION`.)
- **File-backed `[strings]` is an M12 spt-core dependency** — until M12 publishes, instruction
  bodies cannot be externalized; skeleton SKILL.md files may carry interim inline instructions.
  **Update 2026-06-15 — SATISFIED.** M12 (`spt 0.7.0`) ships file-backed `[strings]` as a
  value-position table pointer: `key = { file = "rel" }` over the per-adapter aux dir
  `adapters/<adapter>/strings/`, resolved lazily at `get-string` (containment-checked; copied on
  `adapter add`). Confirmed by live byte-test + spt-core ruling (`REQ-MANIFEST-5`, M12-W3). The
  dependency is met — skill bodies are externalized via this pointer (no manifest bloat); the
  interim-inline fallback is retired. The pointer syntax was merely **undocumented** on the published
  surface (now finding **F-003**, docs-only, doyle publishing). See `docs/SPT-CORE-FINDINGS.md`.

## Consequences

<!-- [doc->REQ-DIST-MANIFEST-SCHEMA] -->
- The marketplace plugin can sit static across many manifest/binary updates → the
  version-of-truth is the spt-core-tracked manifest/binary version (`spt adapter list` /
  `/spt:version`), **not** the marketplace `plugin.json` version. The CC adapter manifest
  (`adapter/claude-spt.toml`) is authored against spt-core's **published** `manifest.schema.json`
  (vendored at `adapter/manifest.schema.json`) and CI-gated against it (`ci/manifest/`). These are distinct numbers on
  independent schedules (see `docs/RELEASE-RUNBOOK.md`).
- New obligation: a dual update path kept in sync — file-pull (real) + a cautionary
  `claude plugin update` (skeleton sync only).
<!-- [doc->REQ-DIST-SHORTCUT-BASENAME] -->
- The manifest brands the `spt endpoint run` launcher shortcut **`cc-<id>`** via
  `shortcut_basename = "cc"` (the M12 `cc` launcher; the harness-agnostic default would be
  `spt-<id>`, and it matches the schema's own `spt-claude-code → cc` example). This launcher brand
  is **decoupled** from the `sptc` plugin name — the `s/sptc/spt/` succession (next bullet) renames
  the plugin, not this shortcut. (Operator-ruled 2026-06-15.)
- Forces the cplugs **plugin-name** question, now **ruled (operator, 2026-06-14)**: because CC
  invokes skills as `/<plugin>:<skill>` (the skill prefix is hard-tied to the `plugin.json` name —
  no override; confirmed against the official plugin docs), the marketplace plugin is named
  **`sptc`** and skills surface as **`/sptc:*`** for now. **Succession plan:** once `spt-claude-code`
  proves parity, flip `plugin.json` name `sptc`→`spt` (skills become `/spt:*`) and retire/rename
  legacy owl's cplugs `spt` plugin in the same coordinated move (two plugins cannot share the
  `spt` name). `sptc` is the single-substitution seam — the flip is `s/sptc/spt/`.
- Mints no new REQs beyond those already seeded for the skeleton milestone; this ADR is the
  `doc`-stage evidence for `REQ-DIST-PLUGIN-SKELETON`, `REQ-DIST-HOOKS-API`,
  `REQ-DIST-BOOTSTRAP-INSTALL`, and `REQ-UPS-INJECTION`.


Found 18 files
PARITY-PUBLISH-PLAN.md
SPT_HARNESS_ADAPTER_TIPS.md
docs\SPT-CORE-FINDINGS.md
SKILLS-SLICE-PLAN.md
MANIFEST-PARITY-PLAN.md
plugin\sptc\skills\version\SKILL.md
adapter\strings\skills\version.md
docs\adr\0001-distribution-splits-by-volatility.md
plugin\sptc\skills\setup\SKILL.md
docs-site\src\introduction.md
docs\RELEASE-RUNBOOK.md
CPLUGS-PREP-PLAN.md
docs\CI.md
SKELETON-PLAN.md
docs\TRACEABILITY.md
HANDOFF.md
SCOPE.md
CONTEXT.md


ADR-0001 confirms it: manifest is a separate **medium-churn layer** (registered via `spt adapter add` — line 87 "copied on `adapter add`"), distinct from the binary. Checking SCOPE for setup's intended branching + how the manifest gets registered.


Grep

setup|adapter add|adapter registry|register|invisible install


36-| Plugin (marketplace) | namespaced `\spt:*` skill *skeletons*, `hooks.json` (call `spt api`), SessionStart bootstrap (installs spt-core if absent), `plugin.json` | `SaberMage/cplugs` | `claude plugin update` (rare structural changes only) | low |
37-| spt binary | all logic | spt-core domain | spt-core's own framework (signed, peer-propagated) | high |
38:| CC adapter manifest | `[digest]` extractor, profiles, strings, hints | spt-core adapter registry (NOT plugin files) | spt-core adapter-update (file-pull) | medium |
39-
40-- Skills stay **plugin-provided** → keep `\spt:` namespace (user-scope skills can't
--
77-not only bare adapter_name (profile model already supports composite addressing).
78-
79:## `/spt:setup` skill
80-
81-Needed because most users install the plugin **mid-session** (no SessionStart fire).
--
145-
146-**TRANSFORM** (LOCKED): Capsule→spt-hosted + `cc`; echo-commune Haiku JSONL→`[digest]`
147:extractor (M10); psyche-sync→subnet/`/spt:setup`; `doctor`→`spt doctor`/setup-verify;
148-working-perches→`api worker-start/stop`.
149-
150:**ADD** (LOCKED): `/spt:setup`, `/spt:version`, subnet skills (create/join/show-code),
151-profiles + strings + hints wiring, ccs profiles.
152-
--
170-v1 acceptance = legacy parity **AND** cross-subnet/PTY proof (spt-core's central value prop is
171-networking + PTY ownership). So **spt-hosted mode + local PTY attach + `spt endpoint run`
172:picker are MANDATORY v1.** → `cc` launcher is IN v1; `/spt:setup` #1 back in v1.
173-**Gating prerequisite: full-fat M12 (todlando builds it after this grill, BEFORE perri starts
174-spt-claude-code).** M12 deliverables incl. `spt endpoint run` (picker — see
--
197-- [ ] Docs split: what lands in experimplate vs spt-claude-code
198-- [ ] experimplate authoring: finalize skeleton + write INSTANTIATE.md
199:- [ ] (downstream) confirm `/spt:setup` #9 verify fold-inline vs deferred


79	## `/spt:setup` skill
80
81	Needed because most users install the plugin **mid-session** (no SessionStart fire).
82	Proposed paths:
83	1. Generate `cc`/`cc <id>` launcher (capsule-style) at project root
84	2. Offer `.gitignore` the launchers
85	3. Offer create first subnet — surfaces a **QR code** of the TOTP seed → spawns a window
86	   (self-elevating; see elevation + M12 dep #2)
87	4. If spt-core already installed → branch: new subnet / **join subnet (= add this machine)** /
88	   show join-code / just-add-endpoint  *(join == add-this-machine — collapsed)*
89	5. Legacy migration — detect claude_skill_owl/owl → migrate identity+agents+psyche
90	   (spt-core CONTEXT.md first-class commitment)
91	6. OS-service registration (always-on daemon)
92	7. ccs profile wiring — if `~/.ccs` present; **also offer to install ccs** (+1-sentence value
93	   prop) if absent
94	8. Psyche cross-machine sync — **in-subnet sync is AUTOMATIC** (confirmed, M4-D6c); only the
95	   optional off-subnet/hub-mode backup remains, retired-as-default → near-zero v1 surface
96	9. Doctor/verify at end
97
98	**LOCKED:** v1 = {1,2,3,4,5,6,7}, defer {8,9}. Item #1 (`cc` launcher) IS in v1 — depends on
99	full-fat M12 (gating prerequisite, todlando-built before perri starts). `cc` wraps
100	`spt endpoint run` defaulted to claude-spt. _Operator "9. agree" then "except 9" — deferred 9;
101	flag if verify should fold inline._
102
103	### `cc` launcher (capsule-style) — **LOCKED (design)**
104
105	= thin wrapper over spt-core's **spt-hosted topology** (broker PTY + inject + attach),
106	NOT a reimplemented psmux. `cc <id>` → `spt` spawns-or-attaches a CC endpoint in a broker
107	PTY. Reattach-if-exists / `--live` / `--resume` = spt-core spawn/resume seam semantics.
108	No-id picker = reuse spt-core's built-in id-resolution (don't reimplement legacy SEED-001).
109	Sendkeys hazards = spt-core's inject concern, not the adapter's.
110	**OPEN gap:** confirm spt-core "remote attach" covers *local user interactive attach* to a
111	hosted CC session (not just headless PTY).
112
113	### Elevation (subnet create/join/show-totp) — **LOCKED (design)**
114
115	Detect (interactive? elevated? desktop?) → least-friction path:
116	Windows = self-elevating UAC window; Linux+desktop = pkexec/polkit or x-terminal-emulator;
117	Linux+TTY = inline sudo; headless/no-TTY = print exact command, agent relays to user.
118	Question the premise: scope elevation to only steps that need it (service-install /
119	firewall / privileged-port) — subnet-create itself likely unprivileged.
120
121	## CI model
122
123	**LOCKED.** Wholly **agent-driven, autonomous, no LLM-in-the-loop**, on the existing

## `/spt:setup` skill

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

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

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

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

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

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

## CI model

**LOCKED.** Wholly **agent-driven, autonomous, no LLM-in-the-loop**, on the existing


also refer to the public spt-core docs: https://sabermage.github.io/spt-releases/harness-contract/integration-checklist.html


Both your points confirmed against docs. Verifying point 1 empirically — is `claude-spt` actually registered with the local binary?


Bash

export PATH="$HOME/AppData/Local/spt-core/bin:$PATH"; echo "=== adapter list ==="; spt adapter list 2>&1; echo "=== get-string probe (strings live?) ==="; spt adapter get-string claude-spt:setup 2>&1 | head -5; echo "=== exit $? ==="

Check if claude-spt adapter registered locally


=== adapter list ===
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)
=== get-string probe (strings live?) ===
error: the following required arguments were not provided:
  <KEY>

Usage: spt.exe adapter get-string <OPTION> <KEY>

=== exit 0 ===


Prompt: also refer to the public spt-core docs: https://sabermage.github.io/spt-releases/harness-contract/integration-checklist.html


`claude-spt: **deregistered**` — confirmed inert. Fetching the public integration checklist to ground the answer.


ToolSearch

Question: select:WebFetch


Question: select:WebFetch


WebFetch

Prompt: List the full step-by-step integration checklist for registering and activating a harness adapter with spt-core. Specifically: how does an adapter manifest get registered/added/activated (e.g. `spt adapter add`/register commands)? What is the difference between a registered and deregistered/active adapter? What steps must a user or installer run AFTER the spt binary is installed to make the adapter's profiles/strings/hints live? Quote exact commands.


# Harness Adapter Registration & Activation

## Registration Command

The exact command to register an adapter is:

```
spt adapter add <dir>
```

Per the docs: `"Parses + schema-validates + records the manifest; a bad field is rejected here, nothing half-registers."` This is a one-time operation that validates the manifest against the schema before any install/update occurs.

## Registered vs. Unregistered State

**Registered adapters:**
- Have passed manifest schema validation
- Are recorded in spt-core's adapter registry
- Can host sessions (if they meet Group 1 requirements)

**Unregistered adapters:**
- Cannot be used by spt-core
- Do not appear in the system until `spt adapter add` completes

## Post-Binary-Install Activation Steps

After installing the spt binary, a user must:

1. **Register the adapter manifest:**
   ```
   spt adapter add ./your-adapter
   ```

2. **Verify registration succeeded:**
   ```
   spt api … capability --adapter <name>
   ```
   This should echo your adapter's `hostable_types`, confirming it's active and discoverable.

There is no separate "activate" command—registration via `spt adapter add` is the activation step that makes the adapter's profiles and capabilities live to spt-core.


if there IS a docs gap, be sure to inform doyle


Both points confirmed — against SCOPE.md, ADR-0001, the live binary, and the public integration-checklist. You're right on both.

## Point 1 — adapter NOT set up. Correct.

Binary present ≠ adapter active. Three distribution layers (ADR-0001 / RELEASE-RUNBOOK "two places"):

| Layer | Churn | Home | Published? |
|-------|-------|------|-----------|
| Skeleton plugin (skills/hooks/bootstrap) | low | cplugs | ✅ just did (b1e2895) |
| spt binary | high | spt-core | ✅ present (0.7.2) |
| **CC adapter manifest** (digest/profiles/strings/hints) | medium | **spt-core adapter registry** | ❌ **NOT** |

Live proof — `spt adapter list`:
```
claude-spt: Harness Copy deregistered (from .../adapter)
```
**Deregistered** = inert. Per the public integration-checklist you linked, `spt adapter add <dir>` is the registration = activation step ("no separate activate command"). Until it runs:
- `spt adapter get-string claude-spt:*` returns nothing → **`/sptc:*` skill bodies don't inject** (UPS-injection sources from there)
- profiles (`:deep/:live/:ccs`), hints, `[digest]` extractor all dead

So screenshot's "No install needed" spoke **only to the binary**. The harness adapter is unregistered. (It shows `deregistered` because Phase-D int tests registered→cleaned-up, "registry left clean" — a real end-user flow has *no* adapter-add step at all.)

## Point 2 — missing branches. Correct.

SCOPE.md §`/spt:setup` **LOCKS v1 setup = paths {1,2,3,4,5,6,7}** (defer 8,9). Item #4 verbatim:
> *"If spt-core already installed → branch: new subnet / join subnet (=add this machine) / show join-code / just-add-endpoint"*

Shipped `setup` skill implements **none of {1–7}** — it's a degenerate installer-floor stub (`install-if-absent` + report-version + stop, per ADR-0001's self-contained minimum). Missing: cc-launcher (#1), gitignore (#2), subnet-create/QR (#3), **the already-installed branch (#4)**, owl migration (#5), service-reg (#6), ccs wiring (#7) — **and** `spt adapter add` itself (the prerequisite the whole surface needs, not even in the SCOPE list).

Not a regression — **unbuilt scope**. Parity slice (A–E) only delivered skill-surface *existence* + skeleton publish, never the v1 setup behavior.

## Two distinct gaps

- **A — blocking, fixable now:** adapter deregistered. `spt adapter add ./adapter` re-activates it → `/sptc:*` + profiles live this session. Also a missing setup-skill step + unpublished registry layer.
- **B — build slice:** setup skill is far below LOCKED v1 {1–7}. Needs a dedicated `SETUP-SLICE-PLAN.md`.

Want me to: **(1)** register the adapter now (`spt adapter add ./adapter`, verify with `spt api … capability`), **(2)** draft SETUP-SLICE-PLAN.md for the {1–7} branches + adapter-add step, or **(3)** both? Both are real findings worth logging in `docs/SPT-CORE-FINDINGS.md` / plan ledger regardless.


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


Need to check whether the gap is in spt-core's **public docs** (report to doyle) vs in **our** adapter (our work). The registration command IS documented — so probing whether the *distribution/publish* flow is documented, and reading our findings ledger.