| name | sse-bootstrap |
| description | This skill should be used when the user asks to bootstrap a TypeScript monorepo from a ChatGPT design corpus, replay the speech-score-engine setup procedure, recover canvas content from a ChatGPT project's saves endpoint, or scaffold a pnpm-workspace + Turbo + biome project from a blueprint canvas. The skill orchestrates a six-phase procedure (canvas recovery → archive inventory → blueprint identification → monorepo scaffold → first vertical slice → cluster-spillover etiquette). The historical record at three granularities lives in references/. |
| version | 0.1.0 |
Speech-score-engine bootstrap SOP
This skill encodes the procedure that bootstrapped the speech-score-engine repo, generalized so it can be replayed against any ChatGPT design corpus of similar shape. It does NOT re-bootstrap the repo that hosts the plugin — it replays into a new empty target directory.
The procedure has three temporal modes:
- One-shot recovery (Phases A and B) — extracting panel-sources from a ChatGPT project's
/backend-api/projects/{id}/saves endpoint, since Export data doesn't include canvas content. Done once per corpus.
- Repeatable scaffold (Phases C and D) — generating a TypeScript pnpm-workspace monorepo from a blueprint canvas. Repeatable per project.
- Ongoing slice execution (Phase E) — cutting the blueprint's build order into vertical slices and executing them with the 10-index audit closeout pattern.
Plus a cross-cutting etiquette for cross-tool spillover (Phase F).
The worked example is the speech-score-engine repo itself. Every Phase below points at concrete artifacts in this repo's history. For the full historical record at three granularities, see:
Preconditions
Before starting, verify:
- Tooling: Node 22+ (the host repo uses Node 25 per
~/.claude/CLAUDE.md); pnpm; Docker (for the local Postgres/Redis/MinIO stack); git; jq; shasum.
- Source corpus access: an authenticated browser session against
chatgpt.com with access to the source project. The bearer token is captured per the recovery procedure in Phase A.
- Target directory: an empty directory, or a non-existent path that can be
mkdir -p'd. The procedure WILL git init and commit; never run against a directory you don't want a git history attached to.
- Drift check: run
bash ${CLAUDE_PLUGIN_ROOT}/skills/sse-bootstrap/scripts/snapshot-state.sh --check. If the references are stale relative to the host repo's HEAD, the historical examples in this SKILL.md may not match the current state of references 02 and 03. Stale-but-pinned is acceptable for replay; stale-without-pin is a bug. Either run --rewrite from the host repo, or proceed with the explicit understanding that the worked example is frozen at the pinned commit.
Phase A — Recover the design corpus
Goal: pull every panel-source from the ChatGPT project into a byte-frozen local archive.
The ChatGPT export bundle (Export data) does NOT include canvas content. Canvas docs live behind the project's internal /backend-api/projects/{id}/saves endpoint, which requires an authenticated browser session.
Steps
-
Capture the bearer token. In the browser console at chatgpt.com:
fetch('/api/auth/session').then(r => r.json()).then(s => window.__tok = s.accessToken);
-
Enumerate saves. Get the project ID from the project URL (the g-p-… prefix), then:
fetch('/backend-api/projects/<project_id>/saves?limit=100',
{headers: {'Authorization': 'Bearer ' + window.__tok}}).then(r => r.json());
-
Fetch each save's full content. Per save:
fetch('/backend-api/projects/<project_id>/saves/<save_id>',
{headers: {'Authorization': 'Bearer ' + window.__tok}}).then(r => r.json());
The full canvas content is in the preview.text field. The field name is misleading — preview.text contains the whole canvas, not a truncated preview.
-
Workaround for Claude Code's JS-return content filter. Direct JS return values can be filtered for cookie/Base64/long-string patterns. To bypass: render the text into a fixed-position <article id="__cx"> with white-space:pre-wrap, then read it via get_page_text. The accessibility tree returns the literal content.
-
Persist to {archive}/sources/ with kebab-case filenames (source title → lowercase → spaces become - → no other transformation).
-
Recover file uploads. Files uploaded into the project (not canvases) may not be exported as standalone artifacts; their content can be preserved inside conversation messages that reference them. Extract by hand from the chat-export JSON.
Worked example
See references/01-phase-history.md#phase-1 for the speech-score-engine corpus: 14 panel-sources recovered (2 file uploads + 12 canvases) from project g-p-69c6e425347c81918dfba984fb76206c on 2026-05-13.
Phase B — Inventory + invariants
Goal: write SOURCES-INDEX.md and declare the load-bearing invariants that protect the corpus.
Steps
-
Compute SHA-1 prefixes for every recovered file. Twelve characters is sufficient for human-readable cross-reference; the index tracks these.
-
Author {archive}/sources/SOURCES-INDEX.md with one row per file: source title, date, origin (which conversation/message extracted it), output filename, byte count, SHA-1 (12).
-
Declare invariants as project-level rules (these belong in the project root CLAUDE.md):
$VARIABLE-style tokens in canvas content are domain ontology, not template placeholders. $SPEECH_SCORE_ENGINE, $PHRASE_EVENT, etc. are authored prose. Do not expand or substitute.
- ChatGPT-internal citation markers (e.g.
fileciteturn0file4) are valid provenance trails. Preserve verbatim.
- Byte-identical canvases are first-class data, not duplicates. The speech-score-engine corpus has canvas #4 and #12 byte-identical (
96e52023ca5d); both are saved from the same source message under different ProjectSave records. Cross-reference in the index; do not dedupe.
preview.text is full content despite its name.
-
Lock the archive byte-frozen: anything under {archive}/sources/ is immutable. SHA-1 prefixes in SOURCES-INDEX.md are tracked references — reformatting, normalizing whitespace, or "tidying" any source file invalidates them.
Worked example
dramaturgist-tuning-markdown-archive/sources/SOURCES-INDEX.md (relative to the target repo, this is dramaturgist-tuning-markdown-archive/sources/SOURCES-INDEX.md). See also the project root CLAUDE.md's "Load-bearing invariants" section.
Phase C — Identify the build blueprint
Goal: pick the canvas that names the monorepo layout and migration shapes.
In a typical ChatGPT design corpus, one canvas plays the role of "implementation handoff" — it names the top-level repository layout, folder purposes, service boundaries, migration stubs, env vars, bootstrap procedure, and build order. This is the canvas the rest of the procedure builds against.
Steps
-
Survey canvases. Look for one that has a sectioned structure including: top-level layout, folder purposes, migration stubs, env vars, bootstrap, build order, testing matrix.
-
Copy verbatim to docs/product/ with cross-reference YAML frontmatter linking back to {archive}/sources/. The archive copy stays byte-frozen; the docs/product/ copy is the working version.
-
Identify the build-order section. In the speech-score-engine blueprint, this is §13 $IMPLEMENTATION_ORDER_INSIDE_THE_REPO. Confirm by reading the section — it should name a sequence of steps (database + contracts → web flows → versioning → render → diagnostics → share/compare), with explicit ordering rationale.
-
Note any section-numbering drift between the blueprint and your scaffold's commit messages. Read the actual section index with grep -n "^## " docs/product/<blueprint>.md. The speech-score-engine scaffold commit referenced "§16" where §13 was meant — section-numbering can drift across blueprint versions.
Worked example
docs/product/repository-blueprint-handoff-package.md. Section index lives at grep -n "^## " docs/product/repository-blueprint-handoff-package.md.
Phase D — Scaffold the monorepo
Goal: generate the directory structure, workspace tooling, and durable conventions.
Steps
-
Workspace skeleton. Per blueprint §2/§3 (or equivalent), create apps/{web,api,worker}/ and packages/{domain,database,config,client-sdk,ui,observability}/. Add package.json, pnpm-workspace.yaml, turbo.json, biome.json, tsconfig.base.json at root.
-
Anchor READMEs. For every blueprint-anticipated directory that doesn't have implementation files yet, write an anchor README. The README IS the artifact, not a stub. The convention: brief frontmatter (type, anchored-since), explanation of the directory's role, what it WILL contain when implemented, what NOT to add prematurely.
-
Three durable conventions in docs/conventions/:
naming.md — filename structure rules.
frontmatter.md — type-specific YAML schemas.
directory-readme.md — the anchor-README convention itself.
-
Architecture docs under docs/architecture/: 001-system-context and onward. Number-prefixed for stable ordering.
-
ADRs under docs/adr/: foundational decisions. Speech-score-engine shipped four:
0001 — monorepo with pnpm + Turbo.
0002 — JSONB snapshots for versioned content.
0003 — async worker via BullMQ for long jobs.
0004 — migrations immutable once applied.
-
Migrations under packages/database/migrations/. Use NNNN_snake_case.sql. The first migration sets up the foundational entities (users, projects, scenes, or the equivalent domain primitives). Migrations are immutable once applied; add new ones, never edit.
-
Local infra: infrastructure/docker/compose.yaml with whatever local services the blueprint names. Speech-score-engine uses Postgres 16 + Redis 7 + MinIO.
-
CI workflow: .github/workflows/ci.yml runs install / typecheck / lint / build. Do NOT pre-wire a test job until the test runner lands — Wave 5 of the first slice introduces it.
-
Verify: pnpm install && pnpm db:up && pnpm db:migrate && pnpm dev should run cleanly. Web and API should boot; worker should declare queues without processors.
Worked example
See references/01-phase-history.md#phase-3 (scaffold generation, commit f8305cb) and #phase-4 (blueprint materialization, commit e36a88f).
Phase E — First vertical slice
Goal: pick step 1 of the blueprint's build order; cut it into ≤6 waves; ship Wave 1; close out with a 10-index audit.
Steps
-
Read the blueprint's build-order section. Identify step 1. For the speech-score-engine blueprint §13, step 1 is "build the database package, domain contracts, and API routes for users, projects, scenes, and parsing."
-
Author a slice plan at .claude/plans/YYYY-MM-DD-{slug}-slice.md. The plan must:
- Name the goal as a CURL-able end-to-end demonstration.
- List what's IN and OUT of scope (with rationale).
- Make explicit decisions (with proposed defaults) for any ambiguity (parser strategy, repository pattern, validation boundary, error shape).
- Cut the slice into ≤6 named waves. Each wave has an exit criterion testable independently.
-
Ship Wave 1. Typically domain contracts: types, schemas, request/response shapes. Purely additive. No I/O. Verify with pnpm typecheck && pnpm lint && pnpm build.
-
Close out with the 10-index audit. Author .claude/plans/YYYY-MM-DD-closeout.md (or closeout-v2.md, closeout-v3.md if iterating) with:
- Session arc.
- Outputs (every commit hash, every file added/modified).
- Closure marks (status per wave: EXECUTED / PENDING).
- Cross-system audit (every registry the meta-system tracks, with N/A entries explicit).
- N/A=vacuum log (each N/A becomes a named gap with disposition).
- What this session deliberately did NOT do.
- Hand-off note for next session.
-
Declare the repo's identity scheme. Speech-score-engine declared SHA-correspondence (commits and plans correspond by SHA, not by foreign-key ID) because the repo is outside the meta-organvm IRF universe. Decide and write down this scheme; it becomes the repo's permanent governance posture.
-
Stop after Wave 1. Do NOT pre-create stub files for Waves 2-6. The right move when a feature is needed is to add the file at that point, not pre-create empty shells.
Worked example
.claude/plans/2026-05-13-scene-crud-and-parser-slice.md (slice plan) and .claude/plans/2026-05-13-closeout-v3.md (Wave 1 closeout with the 10-index audit pattern).
Phase F — Cluster-spillover etiquette
Goal: handle the inevitable cross-tool artifacts that land at repo root.
When the user invokes other AI tools (Codex, Gemini, OpenCode) and runs cross-tool searches, files land at repo root from various AI-tool persistence trees. The etiquette below is what survived speech-score-engine's 2026-05-13/14 cluster-recovery activity.
Rules
-
Classify by cluster destination first, not by .gitignore default. Cross-tool audit material belongs in the cluster's governance home (for speech-score-engine, that's /Users/4jp/Code/_agent-ontology/sessions/{YYYY-MM-DD}-{agent}/ for raw exports, or archives/session-{agent}-{n}-{date}/ for processed material with manifest.yaml + per-artifact SHA-256). Domain extractions (ontology mined from the corpus) belong in {archive}/derived/. Only .gitignore as a last resort.
-
Verify before deleting. Empty files (0 bytes) are safe to delete. Anything with content needs SHA-256 match against at least one durable sibling. Per the cluster's data-governance SOP, this is non-negotiable.
-
Never rename without authorization. Filename collisions across authors are first-class data, not bugs to deduplicate.
-
Tool-spillover prevention: when adding new tooling that writes to repo root, add the prefix to .gitignore BEFORE running it. The repo root is for human-authored artifacts and tracked build configuration.
Worked example
See references/01-phase-history.md#phase-7 and the project root CLAUDE.md's "Cross-cluster artifact drift" section. The plan-of-record for the speech-score-engine recovery was .claude/plans/2026-05-14-cluster-route-speech-score-strays-into-agent-ontology.md.
Drift check
Before invoking the procedure on a new target, verify the historical references are pinned to the host repo's HEAD:
bash ${CLAUDE_PLUGIN_ROOT}/skills/sse-bootstrap/scripts/snapshot-state.sh --check
Exit code 0 means fresh; non-zero means drift. To refresh the references against the host repo:
bash ${CLAUDE_PLUGIN_ROOT}/skills/sse-bootstrap/scripts/snapshot-state.sh --rewrite
To verify the source archive's SHA-1 invariants are intact (host repo only):
bash ${CLAUDE_PLUGIN_ROOT}/skills/sse-bootstrap/scripts/snapshot-state.sh --verify-archive
Recovery from common deviations
"ChatGPT removed the saves endpoint"
If /backend-api/projects/{id}/saves returns 404 or has been replaced:
- Try inspecting the project page's network traffic to find the current canvas-fetching endpoint.
- Fall back to the chat-export endpoint and parse canvases from inline content in
conversations-NNN.json (less complete; canvases as inline content are harder to enumerate).
- Last resort: hand-copy each canvas from the UI. Document the date of the recovery and the changed endpoint shape in
SOURCES-INDEX.md's provenance notes.
"The blueprint canvas has multiple version-drift copies"
When the user has authored multiple iterations of the blueprint canvas:
- Pick the most recent one as canonical.
- Document the version-drift in
docs/product/<blueprint>.md's frontmatter (supersedes: <other-canvas>).
- Treat older versions as
{archive}/sources/ byte-frozen entries, but do NOT copy them to docs/product/. Only the canonical version lives there.
"The first vertical slice can't fit in 6 waves"
If blueprint step 1 has more than 6 reasonable execution units:
- Reconsider whether step 1 is really one slice or two. Speech-score-engine's step 1 (users + projects + scenes + parsing) fit in 6 waves; if your step 1 is meaningfully larger, split.
- Split at a natural boundary (e.g., "users + projects" first slice; "scenes + parsing" second slice).
- Each slice still gets its own slice plan, its own Wave 1 ship, its own closeout.
"The target dir already has a git init"
Stop. The procedure assumes an empty target. Either:
- Move to an empty target.
- Confirm with the user that the existing repo state is acceptable. If so, skip
git init in Phase D step 1 and proceed with caution — the bootstrap may collide with existing files.
"Drift-check fails but the user wants to proceed"
That's fine. Surface the drift explicitly: "References 02 and 03 are pinned to commit X; host repo is now at commit Y. The worked-example anchors in this SKILL.md may reference history that has moved on. The reproducible procedure is independent of the references." Then proceed.
"Running this against the speech-score-engine repo itself"
Don't. The plugin replays the bootstrap into a NEW empty target. Running against the repo that hosts the plugin is undefined behavior; it will at minimum collide with the existing .git/, the existing scaffold, and the existing dramaturgist-tuning-markdown-archive/. If the user genuinely wants to re-run anything on this repo, scope to a specific phase (e.g. "re-run the snapshot script" or "re-verify the archive SHA-1s") rather than the whole procedure.
Closing
The procedure's job is to take a ChatGPT design corpus and produce a buildable monorepo plus a shipped first-slice domain contracts wave. After Phase E ships, the slice plan is the authority for what happens next; this skill steps out. The repo's CLAUDE.md, the slice plan, and the closeout v-N file are the artifacts that govern subsequent sessions.