From catalyst
Use when ending a session, switching context, approaching context limits, before /clear or /compact, when starting a fresh session that may have a prior handoff to resume, when context appears degraded, when briefing a subagent for an isolated subtask, when orchestrating multi-stage work as a pipeline, or when a session has braided across multiple threads that need to be forked into isolated self-contained work streams. Operates in six modes — WRITE (save state on the way out), READ (resume cleanly on the way in), RECOVER (rebuild state when degraded), REGROUND (mid-session read-only re-injection), BRIEF (produce inline minimum-viable context for a subagent), and SPLIT (fork a braided session into N self-contained briefs with user confirmation) — plus a PIPELINE orchestration that uses BRIEF as the briefing primitive across decompose → route → dispatch → synthesize. Feature-keyed via a three-tier ladder (explicit name → git branch → legacy single-slot), so parallel feature work doesn't clobber state. Use this skill liberally for any session that produced non-trivial decisions, any subagent dispatch that needs scoped context, any multi-stage task with distinct phases or concerns, or any session where work drifted across multiple distinct threads.
How this skill is triggered — by the user, by Claude, or both
Slash command
/catalyst:handoffThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A handoff is a **state packet** the next session, subagent, or pipeline stage can act on without re-explanation. Default `/compact` loses crucial details. Default subagent task descriptions either over-share (context bleed) or under-share (the subagent asks clarifying questions it can't actually ask). A proper handoff preserves only what matters, in the structure the next consumer needs.
A handoff is a state packet the next session, subagent, or pipeline stage can act on without re-explanation. Default /compact loses crucial details. Default subagent task descriptions either over-share (context bleed) or under-share (the subagent asks clarifying questions it can't actually ask). A proper handoff preserves only what matters, in the structure the next consumer needs.
This skill implements patterns from Anthropic's Harness Engineering for Long-Running Agentic Applications — context resets over compaction, structured artifact handoffs, planner / generator / evaluator separation, sprint contracts, and GAN-inspired iteration loops for subjective work.
One file cannot be both a concise re-entry prompt and a detailed project history. A handoff writes two:
| File | Purpose | Lifetime | Loaded |
|---|---|---|---|
<store>/<key>.json (or <store>/HANDOFF.json legacy slot) | Ephemeral brief — minimum payload to resume. Points at durable artifacts. | Overwritten on every WRITE for that key. | At the start of the next session for that key. |
.claude/PROJECT_STATE.md | Persistent narrative — accreting log of decisions, why, rejected paths, surprises. Project memory. | Prepended forever (newest first). Repo-level — single file. | On demand only — when a brief points the agent at it. |
The brief survives one session boundary per key. The narrative survives the project. PROJECT_STATE.md is intentionally NOT split per feature — cross-feature decisions matter for future features and must be co-located.
WRITE / READ / RECOVER determine the key for the brief in this order:
| Priority | Source | Resolved path | When |
|---|---|---|---|
| 1 | /handoff <name> | <store>/<name>.json | Explicit override. |
| 2 | git branch --show-current (sanitized /→-, cap 80) | <store>/<branch>.json | Default. |
| 3 | Not in a git repo, or detached HEAD | <store>/HANDOFF.json | Legacy single-slot fallback. |
<store> is the centralized handoffs dir printed by bash "$SCR/handoff-dir.sh" (or python3 "$SCR/handoff_paths.py"): anchored at the MAIN worktree (parent of git rev-parse --git-common-dir). Every linked worktree shares ONE store keyed by branch — resume any feature from any worktree. Detect "in a repo?" with git rev-parse --git-dir succeeding, never [ -d .git ] (.git is a file in a worktree). This supersedes the earlier per-worktree behavior.
Sticky session key: once a WRITE picks a key, subsequent WRITEs / RECOVERs in the same session use the same key. If the user switches branches mid-session, surface the change: "Branch switched. Future handoffs will target <new-key>.json. Confirm?"
BRIEF and PIPELINE modes do not persist, so they don't resolve a key — they may reference a key when telling a subagent which feature's narrative slice is relevant.
| Mode | Trigger | Persists? | Consumer |
|---|---|---|---|
| WRITE | Ending session, hitting context limit, before /clear or /compact, end of pipeline stage, user says "handoff" / /handoff | Disk: <store>/<key>.json (validated JSON) + prepend PROJECT_STATE.md | Next session |
| READ | Fresh session with brief(s) present, user wants to resume | None (loads into current context) | Current session |
| RECOVER | Context degraded mid-session — re-reads, contradictions, forgotten decisions | Disk: overwrites brief for current key; does NOT prepend narrative | Current session, post-/clear |
| REGROUND | Mid-session, recall degrading / decisions slipping into the middle | None (read-only re-injection) | Current session |
| BRIEF | About to dispatch a subagent and want it to start with the right minimum context | In-memory string passed to Agent tool task description; no disk | Subagent |
| SPLIT | Session braided across multiple threads (drifted mid-feature); want to fork into isolated sessions | Disk: N × <store>/<key>.json (validated) + ONE combined PROJECT_STATE entry | N next sessions (one per thread) |
The schema for the brief is shared across all six modes. Only persistence and consumer differ.
Plus PIPELINE mode — orchestration built on top of BRIEF (decompose → route → dispatch → synthesize). See its own section below.
Do NOT invoke for trivial sessions or one-step subtasks. Three-turn debug doesn't need a handoff. A rename across one file doesn't need a pipeline. Use judgement — if there's nothing a future consumer would lose, skip the skill.
The brief is a typed JSON document validated against the bundled brief.schema.json. WRITE builds it and passes it through handoff-validate.py (rejects incomplete/mistyped briefs); READ renders it via handoff-render.py. Required fields cannot be omitted — that is the point.
Helper-script location (read this first). The scripts (
handoff-dir.sh,handoff-validate.py,handoff-render.py,handoff_paths.py) ship inside the plugin, NOT in the user's project. Resolve them once at the start of any mode and reuse$SCR:SCR="${CLAUDE_PLUGIN_ROOT:-.}/scripts" # consumer project: $CLAUDE_PLUGIN_ROOT is set; inside the catalyst repo it's unset → ./scriptsThen call e.g.
bash "$SCR/handoff-dir.sh"andpython3 "$SCR/handoff-render.py" <key>. NEVER write a bare relativescripts/handoff-render.pyinto a resume prompt or run it from the user's repo — that path does not exist there. The durable resume entry point for the next session is the slash command/catalyst:handoff resume, which re-enters this skill and resolves$SCRagain.
{
"schema_version": "1",
"key": "<resolved-key>",
"timestamp": "<ISO-8601, shell-provided>",
"mode": "WRITE",
"resume": { "done_when": "<one verifiable check>", "resume_by": "<one sentence>",
"prompt": "<optional override>", "history_pointer": "<optional>" },
"state": {
"branch": "<branch>", "next_acceptance_check": "<next concrete check>",
"worktree": { "root": "<$CLAUDE_PROJECT_DIR>", "is_linked": false, "git_common_dir": "<absolute shared .git — git rev-parse --path-format=absolute --git-common-dir>" },
"diff_summary": "<optional>", "tests": [{"cmd": "...", "result": "pass"}],
"commands": [], "decisions": [], "rejected_paths": [], "open_risks": []
},
"files_read_first": [{"path": "...", "why": "..."}],
"files_skip": [{"path": "...", "why": "..."}]
}
Optional fields with nothing to say are omitted, never null/"none". Unknown fields are rejected by the validator (catches typos). mode is WRITE or RECOVER (the persisted modes); BRIEF renders the same shape in-memory without a file.
Apply the resolution ladder. Sticky within session — if you've already WROTE in this session, reuse that key unless the branch changed (surface the change).
Run in parallel where supported:
git branch --show-current
git status --short
git diff --stat
git log --oneline -10
git rev-parse --path-format=absolute --git-common-dir # state.worktree.git_common_dir
Record state.worktree.git_common_dir as the absolute SHARED common dir. The READ renderer compares it against the resuming session's git rev-parse --git-common-dir, so they must be the same value.
Caution: In a linked worktree, do not use
--absolute-git-dir— it returns the worktree-private dir (…/.git/worktrees/<name>), which will NOT match the renderer's--git-common-dirand fires a falseREPO MISMATCH. Use--path-format=absolute --git-common-dir(Git ≥ 2.31). Older Git fallback:cd "$(git rev-parse --git-common-dir)" && pwd. In the main checkout both resolve to the same…/.git.
From the session transcript, also note: tests run (pass/fail), commands that materially advanced the work, decisions that affect what the next session should do (not every decision — history belongs in the narrative), paths tried and rejected, open risks, the next concrete acceptance check.
Use the schema above. Include the Resume prompt section with paste-and-go text matching the resolved key. Keep under 200 lines.
Build the typed object. Write it to a temp file and run python3 "$SCR/handoff-validate.py" <tmp>.json; fix every reported field and re-run until it prints handoff-validate: OK. Then move it to <store>/<key>.json (<store> from "$SCR/handoff-dir.sh"). Then prepend a narrative entry to .claude/PROJECT_STATE.md (unchanged — still markdown).
If PROJECT_STATE.md doesn't exist, create it with this header first, then add the entry below the header:
# Project state — narrative log
Accretes over the life of the project. Each handoff prepends a new dated section above earlier entries.
Read sections selectively. The brief at `<store>/<key>.json` is the entry point; this file is the reference.
Caution: The header always stays on top. Insert the new entry immediately after the header block, above existing entries — never at the absolute top of the file. On a fresh file this means: write the header, then the entry beneath it (not the entry then the header). Verify the first line is still
# Project stateafter writing.
Prepend (NOT append) the entry directly below the header, above any existing entries:
## <ISO date> — [<key>] <short title>
### What was done
<2-5 bullets>
### Decisions (with rationale)
- **<decision>** — <why>. Rejected: <alternatives>.
### Surprises / lessons
<bullets or omit>
### Pointers
- <path>:<line-range> — <what's there>
ALWAYS print the Resume prompt verbatim at the end of the confirmation. The user should never need to open the brief file to find the paste-and-go text.
Handoff written (key: <key>, tier: <1|2|3>):
<store>/<key>.json (validated JSON)
.claude/PROJECT_STATE.md (+<n> lines prepended)
Next session — run `/catalyst:handoff resume` (or paste the Resume prompt):
> resume handoff '<key>': run `/catalyst:handoff resume` (READ mode), then continue. next acceptance check: <one-line check verbatim from the brief>.
The resume prompt MUST route through /catalyst:handoff resume — never a bare python3 scripts/handoff-render.py <key>. The helper scripts live in the plugin, not the user's project, so a relative script path fails everywhere except the Catalyst repo itself. The slash command re-enters this skill, which resolves $SCR and renders the brief.
A new session has loaded with one or more briefs present, and the user wants to resume.
Auto-resume (hook-driven): when
SessionStart-handoff-read.shis installed, a session opened via/clearor/compact(sourceclear/compact) gets the brief's five load-bearing fields — next step, done-when, next acceptance check, open risks, files-to-read-first — auto-rendered into context, so no explicit/handoff resumeis needed. Other sources (startup/resume) get a one-line announce instead. Run/catalyst:handoff resumeany time for the full READ render below.
$SCR (see Helper-script location), then <store> via bash "$SCR/handoff-dir.sh". List <store>/*.json (fall back to <store>/HANDOFF.json if no keyed files exist).python3 "$SCR/handoff-render.py" <key> and follow its output. Heed any !! BRANCH MISMATCH / !! REPO MISMATCH warning before continuing. If the brief was written in a different (linked) worktree — render prints Written in worktree: <root> (linked) and you're on another branch — tell the user the work lives in <root> and offer to cd there; don't resume in the wrong tree.files_read_first — load-bearing..claude/PROJECT_STATE.md by default. Open it only when the brief explicitly says to, or you hit a decision whose rationale you need.<key>. Next acceptance check: . Starting now."If the brief's timestamp is more than ~24h old, diff against current git state before resuming — the working tree may have moved.
The current session is degraded. Symptoms: agent forgets what it was doing, re-reads files, contradicts earlier decisions, repeats rejected approaches.
.claude/PROJECT_STATE.md.git log --oneline -20 and git diff on the working branch.python3 "$SCR/handoff-validate.py" <tmp>.json), and overwrite <store>/<key>.json.<store>/<key>.json. Run /clear, then paste this Resume prompt OR run /catalyst:handoff resume:" — and ALWAYS print the literal Resume prompt verbatim right below (the Resume prompt comes from handoff-render.py output — paste-and-go, not a pointer).The current session is still intact but recall is degrading — decisions slip into the low-recall "middle" of the context window, key acceptance checks are being re-derived instead of repeated verbatim, or files-to-keep are being re-read unnecessarily.
REGROUND is a read-only mid-session re-injection: it renders only the load-bearing fields of the brief (goal, locked decisions, files to keep in view) as a compact block, then returns. No disk write, no PROJECT_STATE update.
session-health hook emits a per-turn degradation signal and recommends reground as the recovery recipe.python3 "$SCR/handoff-render.py" --reground <key>
# or with an explicit file path:
python3 "$SCR/handoff-render.py" --reground --file <path>
Read the output aloud into the working context, then continue. No branch or repo context is needed — REGROUND is read-only and does not perform any mismatch checks.
resume.done_when + state.next_acceptance_checkstate.decisions (first five, bulleted)files_read_first paths with their whyIt deliberately omits: ## Summary, Written in worktree, BRANCH MISMATCH, REPO MISMATCH, rejected paths, open risks, diff summary, and the resume prompt. Those belong to READ/RECOVER, not to a mid-session re-grounding.
The current session drifted across multiple distinct threads — one feature discussion braided into another, decisions from two separate efforts are entangled, or the context window now carries state that belongs in N different futures. SPLIT forks the session into N self-contained briefs so that each next session starts clean and focused.
SPLIT is pure orchestration over WRITE machinery: it builds N typed briefs using the same validate → move flow WRITE uses, plus one combined PROJECT_STATE fork entry. No new scripts required.
Helper-script location. Resolve
$SCRonce at the start (same as WRITE/RECOVER):SCR="${CLAUDE_PLUGIN_ROOT:-.}/scripts"
Read the session transcript. Identify the distinct threads of work — decisions, files touched, open questions — that belong together. For each candidate thread, produce a one-line summary:
Thread N: <one-line summary>
Key suggestion: <kebab-slug> (model proposes; user edits)
Owns: <the decisions / files / next-check that belong here>
Next acceptance check: <one verifiable check for this thread>
Open risks: <any risks specific to this thread>
Present the full proposal as a numbered list to the user. Keep the list compact (≤5 lines per thread). Soft cap: ≤4 threads. If you find more than 4, prefer fewer coarser threads — or recommend RECOVER instead, which is better for severely fragmented context.
Wait for the user to review and approve the proposal. The user may:
SPLIT writes NO files until the user explicitly confirms. The human owns the thread boundary. Do not proceed to Step 3 until confirmation is received.
For each confirmed thread, in sequence:
$SCR (already done in Step 1; reuse it).state.decisions, state.rejected_paths, state.open_risks, state.next_acceptance_check.state.decisions array verbatim — true isolation, no new fields. Shared files are copied into each relevant brief's files_read_first array. Each brief stays a normal, schema-valid brief that happens to duplicate the shared slice; there is no shared_context field or extra top-level key.files_read_first scoped to this thread's work (plus any shared-file copies from the step above).python3 "$SCR/handoff-validate.py" <tmp>.json; fix every reported field and re-run until it prints handoff-validate: OK.<store>/<key>.json (where <store> = bash "$SCR/handoff-dir.sh").Each brief must be independently resumable — the consumer of thread B must not need thread A's brief on disk. The duplication of shared decisions across briefs is intentional: it makes each brief a self-sufficient context packet.
Prepend exactly ONE entry to .claude/PROJECT_STATE.md covering ALL threads. Use this heading format:
## <ISO date> — [split: <keyA>, <keyB>, ...] <short why>
### What was done
- Session covered both <keyA> (<summary>) and <keyB> (<summary>).
- Forked into <N> self-contained briefs; each continues independently.
### Shared decisions (cross-cutting)
- **<decision>** — <why>. Applies to all forks.
### Per-thread pointers
- `<keyA>`: <path>:<line-range> — <what's there>
- `<keyB>`: <path>:<line-range> — <what's there>
The header # Project state must remain the first line of the file. Insert this entry immediately after the header block, above any existing entries (same rule as WRITE). Do NOT write one entry per thread — one combined entry only.
If PROJECT_STATE.md doesn't exist, create it with the standard header first, then add the entry.
Print one resume prompt per thread:
Split complete — <N> briefs written:
Thread 1 (<keyA>): <store>/<keyA>.json (validated)
Resume: /catalyst:handoff resume <keyA> (or paste the resume prompt from that brief)
Thread 2 (<keyB>): <store>/<keyB>.json (validated)
Resume: /catalyst:handoff resume <keyB>
One combined fork entry prepended to .claude/PROJECT_STATE.md.
Next: /clear, then resume each thread in a fresh session.
You may keep one thread alive in the current session — /clear and resume with the key you want to continue.
| Situation | Preferred mode |
|---|---|
| One thread, context degraded | RECOVER |
| One thread, recall slipping mid-session | REGROUND |
| Session has 2-4 distinct threads, still coherent | SPLIT |
| Context is severely fragmented (>4 threads, no clear owner) | RECOVER first, then SPLIT |
| About to dispatch a bounded subtask | BRIEF |
You're about to dispatch a subagent for a bounded subtask. The subagent needs the minimum context that makes its job possible — no more.
key, schema_version, and any file path (no disk write).resume block becomes ## Task (named for the subagent's perspective).If the subagent needs a specific PROJECT_STATE.md entry, name it: "see PROJECT_STATE.md ## 2026-05-20 — [feat-jwt-expiry] JWT library migration if you need the migration rationale" — never paste the entry.
Multi-stage orchestration built on top of BRIEF. Patterns codified here track Anthropic's harness-engineering framework — they're not bespoke to Catalyst; they're how Anthropic ships reliable long-running agents.
When a task is large enough to need a pipeline, the default decomposition is into three roles:
| Role | Owns | Context profile |
|---|---|---|
| Planner | Expands a high-level prompt into a detailed spec: scope, milestones, success criteria. Ambitious on what to build, deliberately light on implementation specifics — planner errors cascade into the generator. | Loads project context, light on tooling. |
| Generator | Executes the work — writes code, files, content. Iterates through the units the planner defined. | Heavy on file tools (Edit, Write, Bash), domain-specific context. |
| Evaluator | Tests outputs against explicit criteria. Uses LIVE interaction where possible (run app, run tests, navigate UI via Playwright MCP) — not static review of artifacts. | Read-only, with the criteria + the running application/tests, NOT the generator's transcript. |
Variants: Researcher = read-only Planner producing findings; Reviewer = read-only Evaluator focused on critique; Implementer = Generator synonym.
A sprint contract is a two-party agreement on "what done looks like" for a unit of work, established BEFORE the generator codes.
Without an upfront contract, the generator self-defines "done" and the evaluator grades a moving target. The contract bridges high-level planning ("add JWT leeway") with testable acceptance (pnpm test src/auth/auth.spec.ts:42-78 passes 6/6, no other tests regress, no edits outside src/auth/").
The generator MUST NOT also be the evaluator. Anthropic's data: "when asked to evaluate work they've produced, agents tend to respond by confidently praising the work — even when, to a human observer, the quality is obviously mediocre."
Enforce by:
This is one of the highest-leverage anti-patterns in the whole skill.
For subjective domains (design, content, code-for-readability), single-pass evaluation often isn't enough. A bounded iterate loop:
generator → artifact → evaluator → score + critique → (if below threshold) generator (refined) → ...
Use the loop for: subjective tasks; multiple soft constraints that compete (performance vs readability); creative work.
Do NOT use for: binary pass/fail tasks (tests pass or don't); tasks the generator can verify itself (compile, lint, type-check are deterministic).
Orchestrator owns the loop — generator and evaluator never talk directly.
If "just do it inline", abort. Don't dispatch for a trivial task.
Pick one axis:
| Axis | Use when | Example |
|---|---|---|
| By concern | One feature has cross-cutting concerns | API, DB, tests, docs |
| By module | The change touches independent modules | payments, notifications, auth |
| By stage | Clear pipeline of phases | research → plan → implement → review |
For each subtask: name role (planner/generator/evaluator/etc), inputs needed (pointers, prior-stage outputs), expected output shape.
| Pattern | Trigger conditions (ALL hold) | Risk if wrong |
|---|---|---|
| Parallel | ≥2 unrelated tasks, no shared state, no file overlap | Merge conflicts, inconsistent state |
| Sequential | Any task depends on another's output, or shared files at risk | Wasted time on serialized independent work |
| Background | Research / analysis, results not blocking | Lost results if not checked back |
Default when ambiguous: sequential.
Before any dispatch:
Pipeline plan:
Stage 1 (parallel):
- researcher-A: <subtask> → returns: <output>
- researcher-B: <subtask> → returns: <output>
Stage 2 (sequential, depends on Stage 1):
- planner: <subtask> → returns: <output>
User intervenes here if they want a different shape.
Before any Generator dispatch, negotiate the sprint contract with the evaluator (see Sprint contracts above). Approved contract becomes the generator's brief. Skip the handshake for stages without a generator (e.g., research-only stages).
For each subagent, call BRIEF mode to render the task description. Hand to the Agent tool. Each brief ≤30 lines, no narrative inlined, pointers only.
After subagents return, combine outputs into one coherent result. Name the synthesis act in your chat response — "Combining the three reviews:" or "Merging Stage-1 outputs into the plan:". Pasting outputs is NOT synthesis.
| Pipeline shape | What synthesis means |
|---|---|
| Multiple files / modules | One coherent commit, no internal contradiction |
| Multi-stage (research → plan → implement) | Each stage consumes prior stage's structured result |
| Parallel review (security + perf + correctness) | One report, unified severity scale, duplicates merged |
If synthesis isn't a clear act, the decomposition was wrong.
After a successful pipeline:
"This pipeline worked. Save as
.claude/pipelines/<name>.mdfor re-use?"
If yes:
# Pipeline: <name>
## When to use
<one sentence describing the trigger shape>
## Decomposition axis
<concern | module | stage>
## Stages
1. **<stage-name>** (parallel | sequential | background)
- Subagent role: <e.g. researcher, planner>
- Brief contract: <inputs, expected output>
2. ...
## Synthesis
<how the orchestrator combines stage outputs>
v0.3 only writes templates. Reading them back via /pipeline run <name> is v0.4.
If your own context grows large during the pipeline, invoke WRITE on the current feature key to preserve synthesis-in-progress. The next session can resume mid-flight.
<store>/ # centralized handoffs dir ("$SCR/handoff-dir.sh")
├── HANDOFF.json # legacy / no-git fallback (tier 3)
├── feat-jwt-expiry.json
└── refactor-auth-middleware.json
<project_root>/
├── .claude/
│ ├── PROJECT_STATE.md # repo-level narrative (still markdown)
│ └── pipelines/ # saved pipeline templates
│ └── audit-then-plan.md
All are gitignored by default. Commit them if the team wants shared state.
Legacy .md briefs are dropped pre-1.0. No automatic migration:
.claude/handoffs/*.md files are not read by the new tooling. Run "$SCR/handoff-dir.sh" to locate the new store."$SCR/handoff-validate.py", and place it in <store>/.<store>/HANDOFF.json is the tier-3 fallback slot (replaces HANDOFF.md).pnpm test src/auth/ shows auth.spec.ts green" is.Bad (vague, unvalidated):
{ "key": "feat-jwt-expiry", "notes": "worked on auth, some tests failing, continue tomorrow" }
Good (typed, validated, immediately actionable):
{
"schema_version": "1",
"key": "feat-jwt-expiry",
"timestamp": "2026-05-24T01:42:00Z",
"mode": "WRITE",
"resume": {
"done_when": "pnpm test src/auth/auth.spec.ts passes 6/6",
"resume_by": "fix JWT expiry check in src/auth/middleware.ts — add leeway parameter"
},
"state": {
"branch": "feat/jwt-expiry",
"next_acceptance_check": "pnpm test src/auth/auth.spec.ts passes 6/6",
"worktree": {"root": "/repo", "is_linked": false, "git_common_dir": "/repo/.git"},
"diff_summary": "2 files, +18/-6 in src/auth/",
"tests": [{"cmd": "pnpm test src/auth/auth.spec.ts", "result": "fail"}],
"decisions": [
"Use Date.now() (UTC ms) — not new Date() (alloc in hot path)",
"JWT lib is jose, not jsonwebtoken (see PROJECT_STATE.md 2026-05-20 [feat-jwt-expiry])",
"Operator is <= not <"
],
"rejected_paths": ["< operator (off-by-one)", "new Date() (alloc)"],
"open_risks": ["Clock skew not addressed yet"]
},
"files_read_first": [
{"path": "src/auth/middleware.ts", "why": "file under repair"},
{"path": "src/auth/auth.spec.ts", "why": "failing tests at lines 42-78"}
],
"files_skip": [
{"path": "src/auth/types.ts", "why": "stable"},
{"path": "src/users/*", "why": "unrelated"},
{"path": ".claude/PROJECT_STATE.md", "why": "historical only; decisions above are binding"}
]
}
The good version answers "what do I do first, what is success, what should I not redo" — and handoff-validate.py confirms it is complete before it reaches disk.
Every component of this skill encodes an assumption about what the current model can't do reliably alone:
"Every component in a harness encodes an assumption about what the model can't do on its own, and those assumptions are worth stress testing." — Anthropic
Review this skill annually (or when a new flagship model lands). Strip scaffolding that no longer earns its complexity. Document removals in PROJECT_STATE.md so the next reviewer knows what was tried and why it was retired.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub adrijshikhar/catalyst --plugin catalyst