Files
cyclone/docs/superpowers/plans/2026-06-21-cyclone-skill-catalog.md

37 KiB
Raw Permalink Blame History

Cyclone Skill Catalog Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Ship 8 layer-mapped Cyclone skills under .superpowers/skills/ (one per PR), then update the README to advertise the catalog. No code changes — pure guidance artifacts.

Architecture: Each skill is a single SKILL.md (150250 lines, YAML frontmatter + sections per the spec template). One commit per skill. Phase order matches the spec's build order so each later skill can ship its ## Related skills section pointing to skills that already exist.

Tech Stack: Markdown, YAML frontmatter. No build step, no runtime, no tests (skills are guidance, not code).

Spec: docs/superpowers/specs/2026-06-21-cyclone-skill-catalog-design.md


File structure

.superpowers/
└── skills/
    ├── cyclone-spec/
    │   └── SKILL.md                          ← Task 1
    ├── cyclone-tests/
    │   └── SKILL.md                          ← Task 2
    ├── cyclone-edi/
    │   └── SKILL.md                          ← Task 3
    │   └── references/
    │       └── parsers.md                    ← Task 3
    ├── cyclone-tail/
    │   └── SKILL.md                          ← Task 4
    │   └── references/
    │       └── wire-format.md                ← Task 4
    ├── cyclone-store/
    │   └── SKILL.md                          ← Task 5
    ├── cyclone-api-router/
    │   └── SKILL.md                          ← Task 6
    ├── cyclone-frontend-page/
    │   └── SKILL.md                          ← Task 7
    └── cyclone-cli/
        └── SKILL.md                          ← Task 8

README.md                                     ← Task 9 (catalog section)

Each skill is one PR. Each SKILL.md follows the template in spec §"Per-skill structure". Optional references/<file>.md only when the SKILL.md would otherwise exceed ~200 lines.


Shared SKILL.md template (lock this in Task 0, then apply to every Task)

---
name: <kebab-case>
description: "<one-sentence trigger, with Use when: … keywords>"
---

# <Title>

## When to use
- <bullet 1 — concrete situation>
- <bullet 2>
- <bullet 3>

## Conventions
1. <testable rule>
2. <testable rule>
3. <testable rule>

## Patterns
\`\`\`<lang>
<copy-pasteable skeleton>
\`\`\`

## Anti-patterns
- <tempting-but-wrong move>

## Related skills
- `<other-skill>` — <one line>
- `<other-skill>` — <one line>

YAML frontmatter rules:

  • name must be kebab-case and match the directory name.
  • description is the only thing the auto-loader sees. One sentence, max ~200 chars. Include a Use when: clause listing the trigger situations.

Task 0: Pre-flight — verify starting state

Goal: Confirm .superpowers/skills/ does not exist yet, capture a directory snapshot, and verify the catalog can be served from project scope.

Files:

  • Read: .superpowers/ (existing project-scoped superpowers directory)

  • Create (no commit): /tmp/cyclone-skill-baseline.txt

  • Step 1: Inspect existing .superpowers/ contents

ls -la .superpowers/

Expected: shows only plans/ and specs/ directories (the canonical superpowers content for this repo). No skills/ directory yet.

  • Step 2: Confirm no stray skill files outside .superpowers/skills/
find . -path ./node_modules -prune -o -path ./.git -prune -o -path ./backend/.venv -prune -o -name "SKILL.md" -print

Expected: no output (or only paths under .grok/ system directories that are not part of the repo).

  • Step 3: Verify the README's skills section is empty (or absent)
grep -n -i "skill" README.md | head -10

Expected: a few hits for "skill" in unrelated contexts (e.g. "skill set" in marketing copy) but no existing catalog section.

  • Step 4: Save the baseline
ls .superpowers/ | tee /tmp/cyclone-skill-baseline.txt

Expected: plans\nspecs.

No commit. Pre-flight only.


Task 1: Phase 1, Skill 1 — cyclone-spec

Goal: Codify the SP-N superpowers flow that this repo already uses (14 specs, 8 plans on disk). Pure documentation; this skill owns the convention so every later feature goes through it consistently.

Files:

  • Create: .superpowers/skills/cyclone-spec/SKILL.md

  • Step 1: Confirm the SP-N flow materials exist

ls docs/superpowers/specs/ | wc -l
ls docs/superpowers/plans/ | wc -l
git log --oneline | grep -E "^(feat|docs|merge): SP[0-9]+" | head -5

Expected: ≥ 14 specs, ≥ 8 plans, ≥ 5 SP-N commits in history. Record the numbers for use in the skill.

  • Step 2: Create the directory
mkdir -p .superpowers/skills/cyclone-spec
  • Step 3: Write the SKILL.md

Use the shared template. Frontmatter:

---
name: cyclone-spec
description: "Cyclone SP-N superpowers increment flow — spec → plan → implement → merge. Use when: starting a new numbered feature increment, naming a branch, opening a SP-N PR, or doing the merge dance into main."
---

Body sections (each must be present, in this order):

  • ## When to use — 4 bullets covering: starting a new increment, naming the spec/plan files, opening the PR, performing the merge.
  • ## Conventions — at minimum these numbered rules:
    1. Numbering. Reserve the next SP-N number (next after the highest in git log). Never reuse a number.
    2. Branch. sp<N>-<short-kebab-topic> (e.g. sp22-line-reconciliation).
    3. Spec path. docs/superpowers/specs/YYYY-MM-DD-cyclone-<topic>-design.md. Status header: Draft, pending user review.
    4. Plan path. docs/superpowers/plans/YYYY-MM-DD-cyclone-<topic>.md. Header per writing-plans skill.
    5. Commit prefix. feat(sp<N>): …, docs(spec): …, docs(plan): …, merge: SP<N> … into main.
    6. PR title. SP<N> <Topic> (matches commit history).
    7. Merge shape. Single atomic merge commit into main after review; no squash, no rebase.
  • ## Patterns — copy-pasteable skeleton for the spec header (Date / Status / Branch / Scope) and the plan header (per writing-plans).
  • ## Anti-patterns — at least these:
    • Don't skip the spec ("it's a small fix"). Small fixes still get a 3-line spec when they introduce a new numbered increment.
    • Don't squash the merge commit — the SP-N merge commit is the audit trail.
    • Don't put code in the spec — the spec is the what, the plan is the how.
  • ## Related skills — references to cyclone-tests (every spec mentions test impact), cyclone-edi / cyclone-tail / cyclone-store / cyclone-api-router / cyclone-frontend-page / cyclone-cli (each spec touches one or more of these), and the upstream superpowers:brainstorming / superpowers:writing-plans global skills.

Keep total under ~200 lines. Use real examples drawn from existing specs (e.g. SP9 multi-payer, SP14 5-lane Inbox) where they illustrate the convention.

  • Step 4: Verify frontmatter and structure
head -5 .superpowers/skills/cyclone-spec/SKILL.md
wc -l .superpowers/skills/cyclone-spec/SKILL.md
grep -c "^## " .superpowers/skills/cyclone-spec/SKILL.md

Expected: first 5 lines are the YAML frontmatter (start ---, end ---), ~150-200 lines total, exactly 5 ## sections (When to use, Conventions, Patterns, Anti-patterns, Related skills).

  • Step 5: Commit
git add .superpowers/skills/cyclone-spec/SKILL.md
git commit -m "feat(sp-skill-catalog): add cyclone-spec skill (SP-N flow)"

Task 2: Phase 1, Skill 2 — cyclone-tests

Goal: Codify the pytest + vitest fixture patterns so every later skill can ship its ## Anti-patterns cleanly. Specifically: how to drop a prodfiles fixture into backend/tests/fixtures/, how to write a .test.tsx next to a page, how to keep tests deterministic.

Files:

  • Create: .superpowers/skills/cyclone-tests/SKILL.md

  • Step 1: Survey the existing fixture layout

ls backend/tests/fixtures/ | head -30
ls backend/tests/fixtures/ | wc -l
ls src/**/*.test.tsx src/**/*.test.ts 2>/dev/null | wc -l

Expected: dozens of fixtures under backend/tests/fixtures/, dozens of .test.ts(x) siblings across src/. Record counts for the skill.

  • Step 2: Sample one backend pytest and one frontend vitest to cite
ls backend/tests/fixtures/ | head -3
echo "---"
ls src/hooks/*.test.ts | head -3

Pick the smallest/most-representative example from each side to cite in the skill's ## Patterns.

  • Step 3: Create the directory and write the SKILL.md
mkdir -p .superpowers/skills/cyclone-tests

Frontmatter:

---
name: cyclone-tests
description: "Cyclone pytest + vitest fixture patterns, prodfiles layout, backend/tests/fixtures/ conventions, .test.tsx sibling rule. Use when: adding a backend pytest case, adding a frontend vitest test, or wiring in a real-EDI prodfiles sample."
---

Body sections (each must be present):

  • ## When to use — 4 bullets: adding a backend test, adding a frontend test, dropping in a prodfiles fixture, debugging a flaky test.
  • ## Conventions — at minimum:
    1. Frontend sibling rule. Every new file in src/ that contains testable logic gets a *.test.ts(x) next to it. useFoo.tsuseFoo.test.ts.
    2. Backend test location. Tests live under backend/tests/test_*.py. Integration tests (FastAPI) follow test_api_*.py; pure-unit tests (parsers, validators) follow test_<module>_*.py.
    3. Prodfiles drop-in. Real EDI samples live under docs/prodfiles/<source>/<edi>.txt. To use one in a test: copy to backend/tests/fixtures/<test-name>/<edi>.txt and reference via the existing fixture helper (see ## Patterns).
    4. Determinism. Use freezegun for date-sensitive backend tests; use vi.useFakeTimers() for time-sensitive frontend tests. Never rely on datetime.now() directly.
    5. No network. Tests must not hit the network. httpx/requests mocks live in conftest.py fixtures.
    6. pytest collection. Run cd backend && python -m pytest tests/<file>::<name> -v for the fastest feedback loop. Full suite is the merge gate.
  • ## Patterns — three small copy-pasteable skeletons:
    • One pytest using tmp_path + a prodfiles fixture reference.
    • One vitest *.test.ts for a hook using vi.useFakeTimers().
    • One vitest *.test.tsx for a component using @testing-library/react + happy-dom.
  • ## Anti-patterns — at least:
    • Don't put frontend tests in src/__tests__/ (legacy location, no longer used).
    • Don't reach into docs/prodfiles/ directly from a test — copy to backend/tests/fixtures/ so tests stay runnable when prodfiles is reorganized.
    • Don't use sleep() for timing — use the deterministic timer tools listed in Conventions.
  • ## Related skills — references to all 7 other skills (every domain skill impacts tests) plus superpowers:test-driven-development upstream.

Keep under ~250 lines (this is the most cross-cutting skill, so it's the largest).

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-tests/SKILL.md
wc -l .superpowers/skills/cyclone-tests/SKILL.md
grep -c "^## " .superpowers/skills/cyclone-tests/SKILL.md

Expected: frontmatter present, 150250 lines, 5 ## sections.

  • Step 5: Commit
git add .superpowers/skills/cyclone-tests/SKILL.md
git commit -m "feat(sp-skill-catalog): add cyclone-tests skill (fixture patterns)"

Task 3: Phase 2, Skill 3 — cyclone-edi

Goal: Codify Cyclone's EDI parser/validator conventions across 837P/835/999/270/271/277CA/TA1. Highest-leverage skill — 30 parsers, scattered validators, fixture sprawl.

Files:

  • Create: .superpowers/skills/cyclone-edi/SKILL.md

  • Create: .superpowers/skills/cyclone-edi/references/parsers.md

  • Step 1: Enumerate the parsers and validator rules

ls backend/src/cyclone/parsers/
grep -rn "^def parse_" backend/src/cyclone/parsers/ | head -40
grep -n "^R[0-9]" backend/src/cyclone/validator*.py 2>/dev/null | head -20
ls backend/src/cyclone/ | grep -i valid

Expected: ~30 parser modules, each exporting parse_*, plus validator.py and possibly validator_835.py. Record the R-codes (R200, R210, etc.) found.

  • Step 2: Sample one parser to cite in the skill

Pick the smallest one (e.g. parse_ta1.py or parse_999.py) and read the first 30 lines. The skill's ## Patterns section will reference its structure.

  • Step 3: Create directories and write the SKILL.md + reference
mkdir -p .superpowers/skills/cyclone-edi/references

Frontmatter:

---
name: cyclone-edi
description: "Cyclone EDI parser/validator conventions (837P/835/999/270/271/277CA/TA1). Use when: adding or changing a parser, adding a validator rule (R200/R210/NPI Luhn/EIN/CAS), or mapping a new CAS adjustment reason code."
---

Body sections:

  • ## When to use — 4 bullets: adding a parser, adding a validator rule, wiring a new CAS code, debugging a parse failure on a prodfiles sample.
  • ## Conventions — at minimum:
    1. Parser signature. Every parser module exports parse(text: str) -> <TypedResult> where <TypedResult> is a Pydantic model from backend/src/cyclone/parsers/<edi>_models.py (or co-located).
    2. Segment walk. Parsers consume backend/src/cyclone/segments.py helpers (Segment, Loop, next_segment) — do not parse raw text inline.
    3. Validator rules. Numbered (R200, R210, …) live in backend/src/cyclone/validator.py (or validator_835.py for 835-specific). Each rule is a function _rule_R<n>_<name> raising ValidationError with the R-code.
    4. NPI / EIN / CAS. Identity-format rules (NPI Luhn, EIN XX-XXXXXXX, CAS adjustment reason codes) live in dedicated modules (npi.py, etc.). Don't duplicate the format logic.
    5. Prodfiles reuse. When adding a parser for a new transaction type, ship at least one prodfiles fixture in backend/tests/fixtures/<edi>/<sample>.txt.
  • ## Patterns — three skeletons:
    • A minimal parse_<edi>.py (using segments.py, exporting parse(text)).
    • A validator rule _rule_R<n>_<name>(ctx) -> None.
    • A test that uses a prodfiles fixture (backend/tests/fixtures/<edi>/<sample>.txt) and asserts parse(text).foo == expected.
  • ## Anti-patterns — at least:
    • Don't re-parse raw X12 strings inside validators — always parse first, validate the typed result.
    • Don't bake payer-specific logic into the generic parser — payer variations live in backend/src/cyclone/payers.py or <payer>_config.py.
    • Don't add a validator rule without an R-code — the R-code is how the UI surfaces the error.
  • ## Related skills — references to cyclone-store (writes the parsed result), cyclone-api-router (exposes it), cyclone-tests (fixture drop-in), cyclone-cli (the cyc parse <file> smoke command).

Then write references/parsers.md: a flat table mapping each parser module to its transaction type, signature, primary fixtures, and any payer-specific variants. Keep under 80 lines.

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-edi/SKILL.md
wc -l .superpowers/skills/cyclone-edi/SKILL.md
wc -l .superpowers/skills/cyclone-edi/references/parsers.md
grep -c "^## " .superpowers/skills/cyclone-edi/SKILL.md

Expected: frontmatter present, SKILL.md ≤ 200 lines, references/parsers.md ≤ 80 lines, exactly 5 ## sections in SKILL.md.

  • Step 5: Commit
git add .superpowers/skills/cyclone-edi/
git commit -m "feat(sp-skill-catalog): add cyclone-edi skill (parser/validator conventions)"

Task 4: Phase 2, Skill 4 — cyclone-tail

Goal: Codify the live-tail wire format and the useTailStream + useMergedTail + per-resource hook triplet. Concrete drift risk — wire format is in the README but consumed across 3 page-hook pairs.

Files:

  • Create: .superpowers/skills/cyclone-tail/SKILL.md

  • Create: .superpowers/skills/cyclone-tail/references/wire-format.md

  • Step 1: Survey the live-tail surface

grep -rn "/stream" backend/src/cyclone/api_routers/ src/hooks/ 2>/dev/null | head -20
ls src/hooks/use*Stream* src/hooks/use*MergedTail*
ls src/hooks/use*Tail* 2>/dev/null
grep -rn "snapshot_end\|x-ndjson" backend/src/cyclone/ src/ 2>/dev/null | head -10

Expected: 3 /api/<resource>/stream endpoints, one useTailStream.ts, one useMergedTail.ts, multiple use<X>Stream consumers.

  • Step 2: Read the wire-format spec in the README
grep -n -A 30 "Wire format" README.md | head -50

This is the canonical definition; the skill will reference it. Record the line range for the references/wire-format.md cross-reference.

  • Step 3: Create directories and write the SKILL.md + reference
mkdir -p .superpowers/skills/cyclone-tail/references

Frontmatter:

---
name: cyclone-tail
description: "Cyclone live-tail streaming wire format and the useTailStream / useMergedTail hook triplet. Use when: adding a new streaming list page, changing the wire format, debugging stalled/reconnecting state, or modifying the StatusPill behavior."
---

Body sections:

  • ## When to use — 4 bullets: adding a new streaming page, changing the wire format, debugging stalled/reconnecting, tuning heartbeat/stall timing.
  • ## Conventions — at minimum:
    1. Wire format. Newline-delimited JSON. Line shapes: {"type":"item","data":…}, {"type":"snapshot_end","data":{"count":N}}, {"type":"heartbeat","data":{"ts":…}}, {"type":"item_dropped","data":…}, {"type":"error","data":…}. See references/wire-format.md.
    2. Hook triplet. Streaming pages consume three hooks: useTailStream(url) (raw stream state), useMergedTail(items, events) (combine initial fetch with live events), and a per-resource hook (useClaims, useRemittances, etc.) that wraps both.
    3. Stall threshold. 30s of total silence (heartbeat included) flips the connection to stalled and surfaces a ↻ Reconnect button. Don't change this without updating the README's "Status pill" table.
    4. Snapshot first. Every stream must emit the current snapshot before any live item events. The snapshot_end line is the marker the UI uses to flip StatusPill from connecting to live.
    5. Content-Type. application/x-ndjson. Never application/json for a stream endpoint.
  • ## Patterns — three skeletons:
    • A useFoo.ts page-hook skeleton (TanStack Query initial fetch + tail subscription).
    • A new backend /api/foo/stream endpoint signature.
    • A StatusPill consumer wiring.
  • ## Anti-patterns — at least:
    • Don't hand-roll fetch + ReadableStream parsing in a page — go through useTailStream so reconnect/stall handling is consistent.
    • Don't change the wire format on one endpoint without updating the other two — they share the parser in src/lib/tail-stream.ts.
    • Don't emit item events before snapshot_end — the UI will duplicate rows.
  • ## Related skills — references to cyclone-frontend-page (page-level wiring), cyclone-api-router (the /api/<resource>/stream endpoint), cyclone-store (the event contract that drives the stream), cyclone-tests (.test.ts siblings on every hook in this skill).

Then write references/wire-format.md: copy the relevant README section (with attribution) and add a per-line field reference table (which fields are required, which are optional, parser tolerance). Keep under 80 lines.

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-tail/SKILL.md
wc -l .superpowers/skills/cyclone-tail/SKILL.md
wc -l .superpowers/skills/cyclone-tail/references/wire-format.md
grep -c "^## " .superpowers/skills/cyclone-tail/SKILL.md

Expected: frontmatter present, SKILL.md ≤ 200 lines, wire-format.md ≤ 80 lines, 5 ## sections.

  • Step 5: Commit
git add .superpowers/skills/cyclone-tail/
git commit -m "feat(sp-skill-catalog): add cyclone-tail skill (live-tail wire format)"

Task 5: Phase 3, Skill 5 — cyclone-store

Goal: Codify the store write-paths, the pubsub event contract, and the SP21 store-split boundary map. Aligns with the SP21 store split currently in plan stage — the skill codifies the new boundaries as they land.

Files:

  • Create: .superpowers/skills/cyclone-store/SKILL.md

  • Step 1: Read SP21 plan to learn the new module boundaries

cat docs/superpowers/plans/2026-06-21-cyclone-store-split.md | head -80

Record the module list (batches, inbox, acks, etc.) for use in the skill.

  • Step 2: Survey the current pubsub surface
grep -rn "_written\|_recorded" backend/src/cyclone/pubsub.py | head -20
grep -rn "publish\|subscribe" backend/src/cyclone/store.py | head -10

Expected: at least 3 event types — claim_written, remittance_written, activity_recorded. Record exact names.

  • Step 3: Create the directory and write the SKILL.md
mkdir -p .superpowers/skills/cyclone-store

Frontmatter:

---
name: cyclone-store
description: "Cyclone store write-paths, the pubsub event contract (claim_written / remittance_written / activity_recorded), and the SP21 store-split boundary map. Use when: touching store.py, adding a new entity, wiring a new write event, or splitting a store module."
---

Body sections:

  • ## When to use — 4 bullets: adding a new entity, wiring a new write event, debugging a write-path issue, splitting a store module.
  • ## Conventions — at minimum:
    1. All writes go through CycloneStore. Route handlers and parsers must not write directly to the ORM session.
    2. Every write publishes an event. The event name matches the entity: claim_written, remittance_written, activity_recorded. New entities get <entity>_written (or _recorded for non-canonical rows).
    3. Snapshot shape. Each entity has a Pydantic serializer in backend/src/cyclone/store/ui.py (or its post-SP21 equivalent). The serializer is the single source of truth for what the frontend sees.
    4. SP21 boundaries. Post-split, each domain lives in its own module (batches, inbox, acks, …). Cross-module writes go through CycloneStore facade methods, not direct module access.
    5. No business logic in route handlers. A route handler validates input, calls store.<method>(...), publishes the event, returns the serialized result. Anything more belongs in the store or a parser.
  • ## Patterns — three skeletons:
    • A CycloneStore write method (def add_foo(self, foo: Foo) -> FooRecord).
    • An event publication in pubsub.py.
    • A new <entity>_written handler test that asserts both the row and the event.
  • ## Anti-patterns — at least:
    • Don't read directly from the ORM in a route handler — go through the snapshot serializer.
    • Don't introduce a new event name without updating the subscriber list (currently api.py and api_routers/).
    • Don't merge a write method with its event publication into separate places — they live next to each other so reviewers see both.
  • ## Related skills — references to cyclone-edi (the parsed result lands here), cyclone-api-router (the route that calls the store), cyclone-tail (the event drives the stream), cyclone-tests (write-path tests).

Keep under ~200 lines. No references/ needed unless the boundary map grows.

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-store/SKILL.md
wc -l .superpowers/skills/cyclone-store/SKILL.md
grep -c "^## " .superpowers/skills/cyclone-store/SKILL.md

Expected: frontmatter present, ≤ 200 lines, 5 ## sections.

  • Step 5: Commit
git add .superpowers/skills/cyclone-store/SKILL.md
git commit -m "feat(sp-skill-catalog): add cyclone-store skill (write paths + event contract)"

Task 6: Phase 3, Skill 6 — cyclone-api-router

Goal: Codify FastAPI router conventions — api_routers/, api_helpers.py reuse, response shapes, error envelopes. Pairs with cyclone-store.

Files:

  • Create: .superpowers/skills/cyclone-api-router/SKILL.md

  • Step 1: Survey the existing router layout

ls backend/src/cyclone/api_routers/
grep -l "APIRouter" backend/src/cyclone/api_routers/*.py
head -30 backend/src/cyclone/api_helpers.py

Record the router filenames and which helpers exist in api_helpers.py.

  • Step 2: Sample one router

Pick the smallest existing router (likely acks.py or ta1_acks.py) and read the first 50 lines. The skill's ## Patterns section will reference its structure.

  • Step 3: Create the directory and write the SKILL.md
mkdir -p .superpowers/skills/cyclone-api-router

Frontmatter:

---
name: cyclone-api-router
description: "Cyclone FastAPI router conventions (api_routers/, api_helpers.py, response shapes, error envelopes). Use when: adding or changing an HTTP endpoint, splitting a route out of api.py, or wiring a new helper into api_helpers.py."
---

Body sections:

  • ## When to use — 4 bullets: adding an endpoint, splitting a route, adding a helper, defining an error response.
  • ## Conventions — at minimum:
    1. No new top-level routes in api.py. Every endpoint lives in backend/src/cyclone/api_routers/<topic>.py as an APIRouter.
    2. Reuse api_helpers.py. Common response shapes, error envelopes, and parsing helpers live there. Don't duplicate them in a router.
    3. Response shape. Every successful response is a Pydantic model. Errors use the shared ErrorEnvelope (from api_helpers.py) with code and message.
    4. Mounting. Routers are mounted in api.py with their prefix; keep prefix naming consistent (/api/<resource>).
    5. Streaming endpoints. Use StreamingResponse(media_type="application/x-ndjson") — see cyclone-tail for the wire format.
    6. Tests. Every new endpoint gets a test_api_<topic>_<verb>.py test under backend/tests/.
  • ## Patterns — three skeletons:
    • A new APIRouter skeleton (router = APIRouter(prefix="/api/foo", tags=["foo"])).
    • A get_one / get_list / post_one trio with Pydantic response models.
    • An error envelope usage example.
  • ## Anti-patterns — at least:
    • Don't import from cyclone.api into a router — the dependency runs the other way.
    • Don't return raw dicts — always Pydantic.
    • Don't bypass CycloneStore to query the ORM directly — see cyclone-store.
  • ## Related skills — references to cyclone-store (most routes call store methods), cyclone-tail (streaming endpoints), cyclone-edi (parse endpoints), cyclone-tests (endpoint tests).

Keep under ~200 lines.

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-api-router/SKILL.md
wc -l .superpowers/skills/cyclone-api-router/SKILL.md
grep -c "^## " .superpowers/skills/cyclone-api-router/SKILL.md

Expected: frontmatter present, ≤ 200 lines, 5 ## sections.

  • Step 5: Commit
git add .superpowers/skills/cyclone-api-router/SKILL.md
git commit -m "feat(sp-skill-catalog): add cyclone-api-router skill (FastAPI conventions)"

Task 7: Phase 4, Skill 7 — cyclone-frontend-page

Goal: Codify the React page-component pattern — TanStack Query, use<X> hook, drawer, URL state, .test.tsx sibling. Generalizes what cyclone-tail already covers.

Files:

  • Create: .superpowers/skills/cyclone-frontend-page/SKILL.md

  • Step 1: Survey the page layout

ls src/pages/
echo "---"
ls src/components/ui/ | head -20

Record the page list and which shadcn-style UI components are in src/components/ui/.

  • Step 2: Sample one page to cite
head -50 src/pages/Claims.tsx

Use this in the skill's ## Patterns to show the canonical page structure.

  • Step 3: Create the directory and write the SKILL.md
mkdir -p .superpowers/skills/cyclone-frontend-page

Frontmatter:

---
name: cyclone-frontend-page
description: "Cyclone React page conventions (TanStack Query, use<X> hook, drawer, URL state, .test.tsx sibling, Layout / PageHeader / Sidebar). Use when: adding a new page, refactoring an existing one, or wiring a drawer into a page."
---

Body sections:

  • ## When to use — 4 bullets: adding a new page, refactoring an existing page, wiring a drawer, sharing state via URL.
  • ## Conventions — at minimum:
    1. Page shape. Every page in src/pages/<Name>.tsx exports a default function <Name>(). It uses <Layout>, sets a <PageHeader>, and renders a table or list.
    2. Data hook. Each page pairs with a use<X> hook in src/hooks/use<X>.ts that returns { data, isLoading, error, ...tail }. Pages do not call fetch directly.
    3. Tail. If the page shows live data, it consumes the tail-stream pattern via cyclone-tail. The hook, not the page, owns the streaming subscription.
    4. Drawer. Drawers (e.g. ClaimDrawer, RemitDrawer) live in src/components/<DrawerName>/ and are wired via useDrawerUrlState so the URL reflects open state.
    5. Tests. Every page gets a src/pages/<Name>.test.tsx sibling. Every hook gets a src/hooks/use<X>.test.ts sibling.
    6. UI primitives. Use Radix-backed components from src/components/ui/. Don't pull in new UI libraries without discussion.
    7. Routing. Pages register their route in src/App.tsx. Lazy-load if the page is heavy.
  • ## Patterns — three skeletons:
    • A minimal Claims.tsx-style page (Layout + PageHeader + table + drawer).
    • A use<X> hook skeleton (TanStack Query + tail).
    • A drawer component skeleton with useDrawerUrlState.
  • ## Anti-patterns — at least:
    • Don't fetch from inside a page component — go through the hook.
    • Don't open a drawer via local component state — use useDrawerUrlState so deep-links work.
    • Don't put domain logic in JSX — extract to the hook or a pure helper in src/lib/.
  • ## Related skills — references to cyclone-tail (live-data pages), cyclone-api-router (the endpoints pages call), cyclone-tests (page + hook tests), cyclone-edi (pages that show parsed EDI content).

Keep under ~200 lines.

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-frontend-page/SKILL.md
wc -l .superpowers/skills/cyclone-frontend-page/SKILL.md
grep -c "^## " .superpowers/skills/cyclone-frontend-page/SKILL.md

Expected: frontmatter present, ≤ 200 lines, 5 ## sections.

  • Step 5: Commit
git add .superpowers/skills/cyclone-frontend-page/SKILL.md
git commit -m "feat(sp-skill-catalog): add cyclone-frontend-page skill (React page conventions)"

Task 8: Phase 4, Skill 8 — cyclone-cli

Goal: Codify the CLI subcommand conventions in cli.py — argparse style, exit codes, smoke-test patterns. Last because nothing else depends on it.

Files:

  • Create: .superpowers/skills/cyclone-cli/SKILL.md

  • Step 1: Survey the existing CLI

grep -n "add_parser\|sub_parsers\|set_defaults" backend/src/cyclone/cli.py | head -20
grep -n "sys.exit\|return [0-9]\|return 1\|return 2" backend/src/cyclone/cli.py | head -10

Record the subcommand list and exit-code conventions.

  • Step 2: Sample one subcommand

Pick the smallest (likely validate) and read its 20-30 lines. The skill's ## Patterns will reference its structure.

  • Step 3: Create the directory and write the SKILL.md
mkdir -p .superpowers/skills/cyclone-cli

Frontmatter:

---
name: cyclone-cli
description: "Cyclone CLI subcommand conventions (cli.py, serve/parse/backup/rotate-key/validate, argparse style, exit codes, smoke tests). Use when: adding a CLI subcommand, changing exit codes, or working on operator-facing commands."
---

Body sections:

  • ## When to use — 4 bullets: adding a subcommand, changing exit codes, adding a smoke test, wiring a security-sensitive command (key rotation, backup).
  • ## Conventions — at minimum:
    1. Subcommand shape. Every subcommand is a function cmd_<name>(args) -> int in cli.py. The main() parser dispatches via set_defaults(func=...).
    2. Argparse style. Use argparse.ArgumentParser sub-parsers. Long-form flags (--rotate-key) preferred over positional for safety.
    3. Exit codes. 0 = success, 1 = user error (bad input, missing file), 2 = operator error (DB locked, key missing), 3 = security error (auth fail, key mismatch). Document in cmd_<name> docstring.
    4. Smoke test. Every new subcommand gets a backend/tests/test_cli_<name>.py test using subprocess.run against the installed cyc entrypoint.
    5. Security-sensitive commands. Key rotation (cyc rotate-key), backup (cyc backup), and any command touching secrets.py requires a --confirm flag and a dry-run path.
  • ## Patterns — three skeletons:
    • A cmd_<name>(args) function with argparse setup.
    • A subprocess.run smoke test.
    • A --confirm / --dry-run pattern for security-sensitive commands.
  • ## Anti-patterns — at least:
    • Don't sys.exit() from inside a subcommand — return the int and let main() exit.
    • Don't print to stdout for errors — use logging (or print(..., file=sys.stderr) for top-level fatal errors).
    • Don't add a subcommand without a smoke test in backend/tests/test_cli_<name>.py.
  • ## Related skills — references to cyclone-store (most subcommands touch the store), cyclone-api-router (cyc serve runs the FastAPI app), cyclone-edi (cyc parse <file>), cyclone-tests (CLI smoke tests).

Keep under ~200 lines.

  • Step 4: Verify
head -5 .superpowers/skills/cyclone-cli/SKILL.md
wc -l .superpowers/skills/cyclone-cli/SKILL.md
grep -c "^## " .superpowers/skills/cyclone-cli/SKILL.md

Expected: frontmatter present, ≤ 200 lines, 5 ## sections.

  • Step 5: Commit
git add .superpowers/skills/cyclone-cli/SKILL.md
git commit -m "feat(sp-skill-catalog): add cyclone-cli skill (CLI conventions)"

Task 9: Final — README catalog section

Goal: Advertise the catalog to human readers and to AI agents reading the README on first contact.

Files:

  • Modify: README.md (add a "Skills" section near the top)

  • Step 1: Find a good insertion point

grep -n "^## " README.md | head -20

Pick a sensible location — typically after the existing "Install" or "Dev" section.

  • Step 2: Add the catalog section

Add a new ## Skills section listing all 8 skills with a one-line description each. Example:

## Skills

Cyclone ships 8 project-scoped AI-assistant skills under
[`.superpowers/skills/`](.superpowers/skills/). Each one codifies the
conventions for a major subsystem so the next contributor (human or
AI) gets the lay of the land automatically.

| Skill | Owns |
|-------|------|
| [`cyclone-spec`](.superpowers/skills/cyclone-spec/SKILL.md) | The SP-N spec → plan → implement → merge flow. |
| [`cyclone-tests`](.superpowers/skills/cyclone-tests/SKILL.md) | pytest + vitest fixture patterns, prodfiles drop-in. |
| [`cyclone-edi`](.superpowers/skills/cyclone-edi/SKILL.md) | EDI parser/validator conventions (837P/835/999/270/271/277CA/TA1). |
| [`cyclone-tail`](.superpowers/skills/cyclone-tail/SKILL.md) | Live-tail streaming wire format and the hook triplet. |
| [`cyclone-store`](.superpowers/skills/cyclone-store/SKILL.md) | Store write-paths, pubsub event contract, SP21 split map. |
| [`cyclone-api-router`](.superpowers/skills/cyclone-api-router/SKILL.md) | FastAPI router conventions (`api_routers/`, `api_helpers.py`). |
| [`cyclone-frontend-page`](.superpowers/skills/cyclone-frontend-page/SKILL.md) | React page conventions (TanStack Query, drawer, URL state). |
| [`cyclone-cli`](.superpowers/skills/cyclone-cli/SKILL.md) | CLI subcommand conventions (`cli.py`, exit codes, smoke tests). |

Skills auto-load by description match — no slash command needed.
  • Step 3: Verify the section reads cleanly
grep -n -A 16 "^## Skills" README.md

Expected: the section renders with all 8 rows and the trailing usage note.

  • Step 4: Commit
git add README.md
git commit -m "docs(readme): add Skills section linking the 8-skill catalog"

Self-review (run after writing the plan, before executing)

  • Spec coverage. Skim each section of docs/superpowers/specs/2026-06-21-cyclone-skill-catalog-design.md. Confirm:
    • Spec §"The catalog" → Tasks 1-8 each create the matching skill.
    • Spec §"Per-skill structure" → enforced by the shared template locked in Task 0.
    • Spec §"Loading & cross-references" → every Task has a ## Related skills section.
    • Spec §"Build order / phasing" → Phase order = Task order (1-2 foundations, 3-4 domain, 5-6 backend, 7-8 frontend+CLI).
    • Spec §"Verification" → covered by verification steps in each task + Task 9 README addition.
  • Placeholder scan. No "TBD" / "TODO" / "implement later" in the plan. Each task's body content is specified (frontmatter exact, sections listed, key bullets enumerated).
  • Type / name consistency.
    • Skill names: cyclone-spec, cyclone-tests, cyclone-edi, cyclone-tail, cyclone-store, cyclone-api-router, cyclone-frontend-page, cyclone-cli. Same in every task.
    • Commit prefix: feat(sp-skill-catalog): … everywhere.
    • Section names: ## When to use, ## Conventions, ## Patterns, ## Anti-patterns, ## Related skills. Same in every task.

Plan passes self-review.