@dennisrongo/skills 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -92,23 +92,32 @@ node bin/claude-skills.js list
92
92
 
93
93
  | Skill | What it does |
94
94
  |---|---|
95
+ | [`api-contract-review`](./skills/api-contract-review/SKILL.md) | Review an API's contract as a **promise to consumers you can't see** — HTTP endpoints, webhooks, published events, SDK-facing types. Two evidence rules do the work: a **breaking** verdict requires a before/after diff of a consumer-visible element (`git show` the old DTO/spec vs. the working tree — removed/renamed fields, type changes, requiredness tightened on requests, status-code or enum semantics changed under the same name), and an **inconsistency** finding requires citing the in-repo precedent being violated (error envelope, naming, pagination style, auth placement — grep the siblings first or don't flag it). Also checks the day-one invariants that can't be retrofitted: collections paginate from the start, retryable writes are idempotent, errors carry a machine-usable `code`, no ORM entities serialized wholesale, timestamps/money carry explicit units. Reports **Breaking / Design / Questions**, ranked — zero findings is a valid outcome. Distinct from [`code-review`](./skills/code-review/SKILL.md) (implementation quality): this reviews the *surface*. Triggers on "review this API", "is this a breaking change", "check backward compatibility", "review the contract", or `/api-contract-review`. |
95
96
  | [`code-review`](./skills/code-review/SKILL.md) | Production-readiness review of **uncommitted** working-tree changes (staged + unstaged). Hunts DRY violations, dead code, leaky abstractions, premature abstraction, magic values, missing error handling, debug residue, missing migrations / flags / logs, and other common best-practice gaps — prioritized correctness → DRY/design → tests → security → performance → production-readiness → readability. On non-trivial diffs, convenes a **lens council**: parallel `Explore` sub-agents reviewing through distinct lenses (correctness / design / security / tests / production-readiness), followed by an **adversarial critique round** that challenges each lens's blocking flags against context from the others — false positives demoted, contradictions surfaced for the user, multi-lens findings promoted. Small diffs skip the council. Auto-detects and runs the project's tests and build (`npm`, `pytest`, `dotnet`, `go`, `cargo`, `Makefile`, monorepo orchestrators) and gates the verdict on them being green. **Never edits code unprompted** — produces a categorized report (`blocking` / `suggestion` / `nit` / `praise`) with `file:line` citations, then asks per-finding before fixing. Distinct from [`pr-review`](./skills/pr-review/SKILL.md), which scopes to committed branch work. Triggers on "code review", "review the diff", "is this production ready", "DRY check", or `/code-review`. |
96
97
  | [`codebase-explainer`](./skills/codebase-explainer/SKILL.md) | Produce a durable onboarding artifact for a repo — writes `ONBOARDING.md` (or `docs/ONBOARDING.md` if `docs/` exists) with a tight **read this first** minimum, system overview, dependency map (top-level prod deps + how each is actually used in *this* codebase, with key call site), startup flow (entry point → bootstrap → config), auth flow (or an explicit "no auth detected" when there isn't one), and the 5–15 important files — every claim backed by a `file:line` citation. Walks the repo with **parallel Explore sub-agents** to stay context-safe on big projects, refreshes an existing `ONBOARDING.md` in place instead of rewriting from scratch, and is opinionated about what *not* to include (no dev/test/types deps, no 40-file "important files" lists, no fabricated auth flows, no dates that rot). Built for revisiting a project after months away — and for new teammates landing in an unfamiliar repo. Composes with [`improve-codebase-architecture`](./skills/improve-codebase-architecture/SKILL.md) when shallow-module clusters surface and [`handoff`](./skills/handoff/SKILL.md) for session-level state. Triggers on "explain this codebase", "onboard me", "give me a tour", "where do I start", "I haven't looked at this in months", or `/codebase-explainer`. |
97
98
  | [`conventional-commits`](./skills/conventional-commits/SKILL.md) | Write git commit messages that follow the [Conventional Commits](https://www.conventionalcommits.org/) spec (`feat`, `fix`, `chore`, `docs`, …), auto-prefixed with the ticket number from the current branch (e.g. `feature/12345-...` → `#12345`) and a project tag (`API` / `CLIENT` / `CONSOLE` / `DB`) when detectable from the diff. Both prefixes are omitted when they don't apply. Triggers on commit-message requests. |
98
99
  | [`diagnose`](./skills/diagnose/SKILL.md) | Disciplined diagnosis loop for hard bugs and performance regressions — reproduce → minimise → hypothesise → instrument → fix → regression-test. Forces a fast, deterministic feedback loop before any guessing. On non-trivial cases, Phase 3 convenes a **hypothesis council**: parallel `Explore` sub-agents — one per candidate hypothesis — each defending its case with falsifiable predictions and `file:line` evidence from the actual codebase, followed by a cross-examination round that drops defenders who couldn't find supporting evidence and ranks the survivors. Trivial bugs skip the council and use 1–2 inline hypotheses. Uses tagged `[DEBUG-...]` instrumentation that's trivially cleaned up, and ends with a post-mortem on what would have prevented the bug. Triggers on "diagnose this" / "debug this" / bug reports / flaky tests / perf regressions. |
99
100
  | [`dotnet-onion-api`](./skills/dotnet-onion-api/SKILL.md) | Scaffold a new .NET solution (Web API + Worker microservices) using ONION architecture and EF Core, codifying battle-tested layered patterns and explicitly removing common legacy pitfalls (sproc-centric repos with reflection, EF6 on netstandard2.1, polling console workers, mutable base-service state, missing `CancellationToken`). Three modes — full solution scaffold, add-a-feature slice, add-a-worker microservice. Resolves TFM and NuGet versions at scaffold time (not hard-coded). |
101
+ | [`e2e-verify`](./skills/e2e-verify/SKILL.md) | Verify a change end-to-end in a real browser, routed by one question: **who needs this check to run again?** Nobody → **ephemeral**: run [Expect](https://github.com/millionco/expect) if installed (explicit non-prod `--url`, `--no-cookies` by default) or have Claude drive the browser directly — walking the flows the *diff* touches, verifying via DOM/accessibility state, and checking the console + network log after each flow (a page that looks right while logging exceptions is a finding). CI-forever (money/auth/signup/checkout/deletion) → **durable**: Playwright tests committed to the repo under [`write-tests`](./skills/write-tests/SKILL.md) discipline — extend the repo's existing e2e setup, `getByRole`/`getByTestId` selectors never CSS chains, no sleeps, API-seeded independent tests, every test **proven red-capable** with both runs quoted. The evidence rule that holds across every engine: an AI-walked flow yields *"no issues found in the paths walked"* with paths enumerated and observations quoted — never "e2e passes"; unobserved behavior is "not verified", never "works". Hard gate: no production targets, no real user cookies. Triggers on "verify this in the browser", "test it end to end", "e2e test this", "write playwright tests", "run expect", "smoke test the UI", or `/e2e-verify`. |
100
102
  | [`grill-with-docs`](./skills/grill-with-docs/SKILL.md) | Interview-driven design review. Stress-tests a plan, RFC, or feature idea against the project's existing domain model and documented decisions — one question at a time with `AskUserQuestion`, sharpening fuzzy terminology and surfacing contradictions with the codebase. Updates `CONTEXT.md` (glossary) inline as terms resolve and writes ADRs to `docs/adr/` only when the decision is hard to reverse, non-obvious, and had real trade-offs. Writes no production code — composes with [`plan-and-build`](./skills/plan-and-build/SKILL.md) for the implementation handoff. Triggers on "grill me", "stress-test this plan", "challenge this design", "/grill-with-docs", or a pasted RFC. |
101
103
  | [`handoff`](./skills/handoff/SKILL.md) | Capture a session hand-off before context runs out — writes a dated `.claude/handoffs/*.md` (objective, progress, decisions, files, open issues, ready-to-paste next-session prompt) plus a lightweight memory pointer so a fresh Claude session can resume cleanly. |
102
104
  | [`improve-codebase-architecture`](./skills/improve-codebase-architecture/SKILL.md) | Surface architectural friction and propose **deepening opportunities** — refactors that collapse clusters of shallow modules into one deep module with a real seam. Walks the codebase with an Explore sub-agent, applies the **deletion test** to suspected pass-throughs, presents numbered candidates (files / problem / solution / benefits) using `CONTEXT.md` for the domain and a strict architecture glossary (module / interface / seam / depth / leverage / locality) for the structure, then drops into a grilling loop with optional parallel sub-agent interface design ("Design It Twice"). Updates `CONTEXT.md` inline as new concepts get named and offers an ADR only when a rejection is load-bearing. Composes with [`grill-with-docs`](./skills/grill-with-docs/SKILL.md) for glossary + ADR discipline and [`plan-and-build`](./skills/plan-and-build/SKILL.md) for the implementation handoff. Writes no production code. Triggers on "improve architecture", "architecture review", "find refactoring / deepening opportunities", "find shallow modules", "make this more testable", or `/improve-codebase-architecture`. |
105
+ | [`migration-safety`](./skills/migration-safety/SKILL.md) | Review a schema migration for **production safety under live traffic** — the three failure axes are locks, deploy ordering, and irreversibility. Destructive ops (drops, renames — a rename IS a drop+add to running old code — type narrowing, `NOT NULL` tightening) are blockers unless an **expand → migrate readers → contract-in-a-later-release** plan is stated. Lock findings must name the engine, the specific lock, and its duration driver (no "might be slow" — and no flagging what's actually free, like a defaulted nullable add on modern PG/SQL Server). Checks the deploy-order contract **both ways** (old code on new schema during rollout, new-code data on old schema during rollback), separates backfills from DDL, and demands an honest rollback verdict per migration (an auto-generated down that drops a column does *not* restore its data). **Never executes** migrations or any SQL. Distinct from [`sql-review`](./skills/sql-review/SKILL.md) (T-SQL antipatterns in procs): this judges schema changes against the deploy timeline. Triggers on "review this migration", "is this migration safe", "will this lock the table", "zero-downtime migration", or `/migration-safety`. |
103
106
  | [`nextjs-app-router`](./skills/nextjs-app-router/SKILL.md) | Scaffold a new Next.js (App Router) **fullstack** app — TypeScript, **NextAuth (Auth.js v5)**, **Prisma + PostgreSQL**, Route Handlers as the backend, Redux Toolkit + RTK Query, Tailwind + shadcn/ui (Radix), React Hook Form + Zod. **API-driven by deliberate choice**: pages are `'use client'`, all data flows UI → RTK Query → `/api/**` Route Handlers → Prisma. No `fetch()` in server components, no Server Actions, no async `page.tsx`. Confirms the database (Postgres + Prisma) and NextAuth providers with the user before writing files. Forbids the usual pitfalls (custom JWT cookies alongside NextAuth, multiple `createApi`/`PrismaClient` instances, `serializableCheck: false`, `@ts-ignore`, mixed `moment`/`date-fns`, `styled-components` alongside Tailwind, case-sensitive folder dupes, `dangerouslySetInnerHTML` without sanitization, Route Handlers that skip `requireSession()` or trust client-sent user IDs, `prisma db push` in CI). Three modes — full project scaffold, add-a-feature slice (page + form + Route Handler + Zod schema + RTK Query endpoints + Prisma model), add-an-API-slice. Resolves package versions at scaffold time (not hard-coded). |
104
107
  | [`plan-and-build`](./skills/plan-and-build/SKILL.md) | Plan-first feature builder. Grills the user about the feature (à la `grill-with-docs`) until the design is unambiguous, detects the project's stack and conventions, presents a plan, and gates on `ExitPlanMode` approval before writing any code. When Phase 3 hits a genuine design fork (service-layer vs. CQRS, new table vs. nullable columns, sync vs. background job, etc.) and Phase 2 didn't settle it, runs **Design It Twice**: two parallel sub-agents each draft the BEST plan for one side of the named axis, then an inline debate names three wins for each and recommends one — the user sees a single recommended plan with a one-line "considered alternative" note so they can redirect with one sentence. Skipped when an existing pattern in the repo already dictates the approach. Builds TDD-first with NUnit when a .NET API changes — appending to the matching test class if one already exists rather than forking a parallel one — reuses existing patterns, keeps comments minimal, and generates EF Core / migration files **without ever** running `dotnet ef database update` or any DDL/SQL against the user's database. Triggers on "build/add/implement a feature", "/plan-and-build", or a pasted feature spec. |
105
108
  | [`pr-review`](./skills/pr-review/SKILL.md) | Structured review of a local branch, **grouped per `#NNN` task** referenced in commit messages, prioritized correctness → design → tests → security → performance → readability, with categorized feedback (`blocking` / `suggestion` / `question` / `nit` / `praise`). On non-trivial tasks, convenes a **per-task lens council**: parallel `Explore` sub-agents through distinct lenses (correctness / design / security / tests) on that task's diff only, followed by an **adversarial critique round** that demotes false-positive blockers when another lens defuses them, surfaces contradictions as `question` items for the user, and promotes findings raised by multiple lenses independently. Small tasks skip the council. The council never crosses task boundaries — each `#NNN` gets its own verdict. Triggers on "review my PR", "review the diff", "review my branch", or `/pr-review`. |
109
+ | [`safe-refactor`](./skills/safe-refactor/SKILL.md) | Execute a behavior-preserving refactor as a **sequence of proofs, not a rewrite**. Writes the behavior contract first (public surface, side effects, error types — the falsifiable definition of "preserved"), audits the safety net (every contract item mapped to a covering test, characterization tests written via [`write-tests`](./skills/write-tests/SKILL.md) for the gaps — **no net, no refactor**, and "the change is simple" is not an exemption), locks a quoted-green baseline, then moves in single mechanical transformations with the suite green between steps. Renames are **grep-verified repo-wide** (strings, routes, reflection, and serialized names don't compile-check). The **assertion-change tripwire**: if fixing a red step means changing a test's expected value, stop — that's a behavior change wearing a refactor's clothes; surface it, never silently absorb it. Ends with an adversarial diff read hunting the smuggled change (reordered side effects, dropped `await`, widened catch). Completes the chain: [`improve-codebase-architecture`](./skills/improve-codebase-architecture/SKILL.md) names the target, this makes the move. Triggers on "refactor this", "clean this up without changing behavior", "extract/inline/split", "rename across the codebase", or `/safe-refactor`. |
110
+ | [`security-review`](./skills/security-review/SKILL.md) | Attacker's-eye security audit of a diff, branch, or module — maps trust boundaries, then walks a fixed catalog: missing authn **and object-level authz** (IDOR is the most common real miss), client-sent identity trusted in queries, injection (SQL / command / path traversal / XSS), secrets in code or logs (a committed secret means *rotate*, not delete-the-line), SSRF, open redirects, insecure deserialization, mass assignment, crypto misuse, dependency CVEs (only via an actual audit-tool run with output quoted — otherwise `dependencies: not checked`). The gate that keeps it honest: every finding must state a one-sentence **attack path** (*who* does X → gains Y) or be demoted to hardening advice; every finding is re-derived by tracing input to sink (untraced pattern-matches are labeled `unconfirmed`); the report never claims "secure" — only "nothing found in the classes checked", plus the explicit unchecked list. Zero findings is a valid outcome. Never edits code unprompted. Distinct from the security *lens* in [`code-review`](./skills/code-review/SKILL.md) / [`pr-review`](./skills/pr-review/SKILL.md): this is the dedicated deep pass for trust-boundary changes. Triggers on "security review", "is this secure", "check for vulnerabilities", "audit the auth", "threat model this", or `/security-review`. |
106
111
  | [`ship-it`](./skills/ship-it/SKILL.md) | Pre-launch **operational-readiness** gate for a feature, release, or branch — the complement to [`code-review`](./skills/code-review/SKILL.md). Walks a fixed 10-category checklist (logging, error handling, telemetry, feature flags, migrations, rollback strategy, secrets, local-first storage, auth, update strategy) against the named scope and produces a structured report with PASS / GAP / N/A per item — every PASS backed by a `file:line` citation, every GAP labelled `no evidence found at <path>`, every N/A justified in one line. The final verdict groups findings as **Blocking** (secrets in code, missing authz on a new endpoint, destructive migration without rollback, no way to disable the change in prod) / **Should-fix** / **N/A with reason** / **Passing**, then asks per-blocker whether to draft a fix. **Never edits code unprompted** and **forces scope before auditing** — a PR, a flag, a release tag, or a module — so the output stays actionable. Distinct from `code-review` (diff quality) and `pr-review` (branch / per-task review): `ship-it` is the operational gate that catches what diff-level reviews don't surface. Triggers on "is this ready to ship?", "ship-it check", "production checklist", "pre-launch checklist", "release readiness", or `/ship-it`. |
107
112
  | [`sql-review`](./skills/sql-review/SKILL.md) | Pre-commit SQL code review for uncommitted `.sql` changes (staged + unstaged). Detects 17 antipattern classes that map to **real production incident causes** — `sp_send_dbmail` in CATCH blocks (masks the real exception as a misleading permission denial), broken retry patterns (`@retry` declared without a surrounding `WHILE` loop), swallowing CATCH blocks (no `THROW`/`RAISERROR`/log), **new tables created without a primary key or any index** (the silent perf-then-deadlock killer), parameter-vs-column type mismatches (8152 truncation risk), `EXEC()` string concatenation without `sp_executesql` parameters (SQL injection), `NOLOCK` inside transactional write paths, `UPDATE`/`DELETE` without `WHERE`, cursors without `READ_ONLY FORWARD_ONLY LOCAL`, hardcoded environment values (emails, server names, paths, linked servers), cross-DB references like `msdb.dbo.*`, missing `SET NOCOUNT ON`, missing `GRANT EXECUTE` on `CREATE PROC`, `BEGIN TRANSACTION` outside `TRY`/`CATCH` with `XACT_STATE` handling, and vestigial control-flow comments hinting at refactor leftovers (e.g. `-- end while loop` with no `WHILE`). **Scope-aware** — full-file scan for new files, diff-only scan for modified files so legacy antipatterns in untouched parts of a large SP don't flood the report. Categorizes findings as `BLOCKER` / `WARN` / `INFO` with `file:line` citations and per-finding fix recommendations. **Never edits SQL unprompted** — produces the report, then asks per fix. Distinct from [`code-review`](./skills/code-review/SKILL.md), which carries the general best-practice catalog without SQL-specific patterns. Triggers on `/sql-review`, "review my SQL", "review the SQL diff", "lint the SQL", "check my SQL changes", "SQL pre-commit check", or "audit my stored proc". |
108
113
  | [`task-executor`](./skills/task-executor/SKILL.md) | Disciplined execution loop for a single, already-defined task — Understand → Inspect → Plan → Execute incrementally → Validate after every change → Track assumptions → Update progress. Forces a strict per-turn output format with six fixed sections (**Goal** / **Current understanding** / **Files to inspect** / **Plan** / **Progress** / **Risks** / **Assumptions**) so the work stays legible and resumable instead of devolving into ad-hoc edits across turns. When the inspection working set spans multiple layers (controller + service + persistence + tests), Phase 2 convenes an **inspection council**: parallel `Explore` sub-agents — one per layer slice — each map their area and return `file:line`-cited findings on existing patterns, wiring points, and sibling test classes; the main session aggregates the results into `Current understanding` so the working context window stays free for the strict per-turn output the executional phase keeps emitting. Small inspection sets (≤ ~5 files, one layer) skip the council and read inline. Enters Plan Mode after inspection and gates on `ExitPlanMode` approval before writing any code; every plan step is then one logical change followed by an immediate validation (test, build, type-check, curl, page load) before the next checkbox ticks. Assumptions are tracked explicitly until confirmed by code or the user — and promoted into `Current understanding` or killed, never silently carried. Composes downward from [`plan-and-build`](./skills/plan-and-build/SKILL.md) (which interviews the user to design the feature) and routes back to it when the user invokes this skill on a fuzzy spec. Triggers on `/task-executor`, "Work on task: …", or any concrete, already-defined task handed to Claude for execution. |
109
114
  | [`tauri-2-app`](./skills/tauri-2-app/SKILL.md) | Scaffold a new Tauri 2 desktop app (Rust backend + TypeScript/React frontend) using a thin-frontend / rich-Rust-backend architecture with modular `commands/`, `state/`, `storage/`, `platform/` traits, `error/` macros, single-instance + updater plugins wired correctly, capability JSON per window, encrypted secrets at rest, `spawn_blocking` for sync work, and typed frontend command hooks — while forbidding common pitfalls (committed `.backup`/`.orig`/`.temp` files, plaintext API keys in `settings.json`, tokens in `localStorage`, `cfg!(target_os)` in command bodies instead of trait-based platform code, hand-rolled date math instead of `chrono`, raw `std::fs` bypassing capability checks, blocking I/O inside async commands, missing `windows_subsystem = "windows"` in `main.rs`, `devtools: true` in release, hardcoded bundle identifiers / updater pubkeys / CDN URLs). Three modes — full project scaffold, add-a-command end-to-end, add-a-Rust-module slice. Resolves Cargo + npm versions at scaffold time (not hard-coded). |
115
+ | [`think-like-fable`](./skills/think-like-fable/SKILL.md) | An operating manual for rigorous reasoning, written as a senior operator handing their craft to a sharp junior — applied to whatever task is at hand rather than replacing it. Eight disciplines, each with the procedure, a worked example, and the failure it prevents: read the need behind the literal ask, decompose into **independently checkable** pieces, spend effort where the risk lives (not where the work is easy or interesting), verify load-bearing claims by **re-deriving** them instead of recognizing them ("a claim about code you haven't opened is a hypothesis"), tag every claim **verified / inferred / assumed** in the text, attack your own conclusion before handing it over, and communicate answer → reasoning → risk in that order. Names the seven mistakes that look like competence and aren't (thoroughness theater, fluent overclaiming, premature agreement, complexity as signal, silent scope repair, momentum completion, deference to your own prior output) and ends with a five-question self-test to run on every answer before sending. Triggers on "think like fable", "/think-like-fable", "be rigorous", "are you sure?", "don't guess", or any high-stakes analysis where a confident wrong answer is worse than a slow right one. |
116
+ | [`upgrade-deps`](./skills/upgrade-deps/SKILL.md) | Upgrade dependencies as a **verification exercise, not a version edit**. Inventory comes from the tool (`npm outdated` / `dotnet list package --outdated` / `pip list --outdated` / `cargo outdated` — never from training-data memory of "latest"), baseline suite quoted green before anything moves, patch/minor bumps batched, **majors strictly one at a time**: read the actual changelog across every crossed version (a breaking-change claim without a citation is a hypothesis), grep the repo for each breaking API (cite the call sites, or state the negative: "no usage — grep for `X` returned nothing"), list behavioral changes that don't grep (changed defaults, stricter parsing) as named **runtime risks** with the test that would catch each — or the admission that none would. Red bump → one informed retry → revert, mark **blocked** with the quoted error, move on. Never silences peer conflicts with `--force`/`--legacy-peer-deps` without surfacing the override. Reports a per-package table (from → to, breaking changes affecting *this* repo, evidence, result) plus the honest residue. Triggers on "upgrade dependencies", "update packages", "bump X", "is it safe to upgrade", "fix the npm audit", "handle the dependabot PRs", or `/upgrade-deps`. |
110
117
  | [`write-a-skill`](./skills/write-a-skill/SKILL.md) | Author a new Claude Code skill — interview-driven scaffolding that produces a properly-structured `SKILL.md` (trigger-rich YAML description, "When to use", workflow, examples, anti-patterns), drops it in the right location (library `skills/`, project `./.claude/skills/`, or global `~/.claude/skills/`), updates the README skills table when extending this library, and runs a review checklist focused on the failure mode that matters most — under-triggering descriptions. Triggers on "create/write/add a skill", "/write-a-skill", or a pasted SKILL.md URL with "one like this". |
111
118
 
119
+ | [`write-tests`](./skills/write-tests/SKILL.md) | Author tests whose only job is to **fail when the behavior breaks** — everything else (coverage %, test count, green checkmarks) is a gameable proxy. Ranks WHAT to test by risk (error paths, money, auth, deletion, retry/idempotency, date math outrank happy paths), checks for existing coverage first (**zero new tests is a valid outcome** — cite the existing test), asserts observable behavior only (return values, persisted state, real-boundary calls — never internal call order), and **proves every new test can fail**: TDD-red first, or mutate the behavior → confirm red → revert → confirm green, both runs quoted. A test never seen red is decoration; a green claim without a quoted run is `tests: not run`. Mocks only boundaries you don't own (network, clock, fs, db) using the repo's existing double convention. For untested legacy code: **characterization tests** that pin actual behavior — bugs included, labeled — before anything changes ([`safe-refactor`](./skills/safe-refactor/SKILL.md) depends on this). Test pain gets reported as design feedback, not mocked through. Triggers on "write tests", "add tests / coverage", "test this", "add a regression test", "TDD this", "characterization tests", or `/write-tests`. |
120
+
112
121
  Run `skills list` to see this list with install status, or browse [`skills/`](./skills) directly.
113
122
 
114
123
  ## How Claude Code finds these skills
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dennisrongo/skills",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "A curated, fine-tunable library of Claude Code skills. Install globally or per-project via npx.",
5
5
  "bin": {
6
6
  "skills": "bin/claude-skills.js"
@@ -32,3 +32,11 @@ Step-by-step guidance for Claude on how to handle the task.
32
32
  ## Notes
33
33
 
34
34
  Any caveats, edge cases, or things to watch out for.
35
+
36
+ <!-- Author reminders (delete before shipping):
37
+ - Description carries 3+ concrete trigger phrases — it's the only field Claude reads to decide.
38
+ - Give every rule that matters a ❌/✅ pair (same output done badly, then well).
39
+ - Any assertion the skill asks for needs an evidence gate — name the check that licenses it.
40
+ - Report-producing skills: state "zero findings is a valid outcome".
41
+ -->
42
+
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: api-contract-review
3
+ description: Review an API's contract as a promise to consumers — detects breaking changes by diffing the before/after surface (removed/renamed fields, type changes, tightened requiredness, status-code changes), and judges design by the repo's OWN precedent (error envelope, naming, pagination, auth placement) with every consistency finding citing the in-repo convention being violated. Covers versioning, idempotency on retryable writes, pagination on collections, and status-code semantics. Use this skill whenever the user says "review this API", "review the endpoint", "API design review", "is this a breaking change", "check backward compatibility", "review the contract", "review this OpenAPI/swagger spec", or "/api-contract-review" — even if they don't name the skill. Distinct from code-review (implementation quality); this reviews the SURFACE consumers depend on.
4
+ ---
5
+
6
+ # API Contract Review
7
+
8
+ An API contract is a promise made to code you can't see and can't fix. This skill reviews the promise, not the implementation: what a consumer can observe — paths, methods, fields, types, requiredness, status codes, error shapes, headers, ordering and pagination semantics — and whether this change keeps, extends, or breaks it. Two evidence rules do the work: **breaking** requires a before/after diff of a consumer-visible element, and **inconsistent** requires a citation of the in-repo precedent being violated.
9
+
10
+ ## When to use this skill
11
+
12
+ - The user says "review this API", "API design review", "is this a breaking change", "check backward compat", "review the contract", "review this OpenAPI spec", "/api-contract-review".
13
+ - A new endpoint, GraphQL type, gRPC service, webhook payload, or event schema is being added or changed.
14
+ - `plan-and-build` is designing an endpoint and the contract deserves its own pass before implementation.
15
+
16
+ Do **not** auto-trigger for internal function signatures or module interfaces (that's `code-review` / `improve-codebase-architecture` territory) — this skill is for surfaces crossed by consumers who deploy independently: HTTP APIs, published events, webhooks, SDK-facing types.
17
+
18
+ ## Workflow
19
+
20
+ 1. **Establish the before and the after.** For a change: the old contract is `git show` of the previous handler/spec/DTO, the new one is the working tree — read both; a breaking-change verdict without the before-state in hand is a hypothesis. For a brand-new endpoint there is no "before", so the compat section reduces to forward-compat design (step 4). Identify the consumers if discoverable (other repos, mobile apps, webhook subscribers, "unknown external") — unknown consumers raise the cost of every breaking change and the report should say so.
21
+ 2. **Diff the consumer-visible surface for breaking changes.** Breaking = an existing valid consumer interaction stops working or changes meaning. The checklist, each judged by before/after citation:
22
+ - Removed or renamed: path, method, field, enum value, header.
23
+ - Type changes (string→int, scalar→object, nullable→non-null in responses).
24
+ - Requiredness tightened on **requests** (new required field/param, stricter validation rejecting previously-valid input).
25
+ - Semantics changed under the same name: status code for the same condition, default value, sort order consumers observe, pagination behavior, error `code` values, ID format.
26
+ - Response fields **removed or now-sometimes-absent** (additive response fields are non-breaking for tolerant readers — but check the repo's serializer isn't strict).
27
+ - ❌ "Changing this field feels risky." — no before/after, not a verdict.
28
+ - ✅ "Breaking: `status` response field was `\"active\"|\"disabled\"` (git show `UserDto.cs:14`), now adds `\"suspended\"` — consumers with exhaustive enum handling will throw. New enum values in responses are breaking unless the contract documents open enums; nothing in the spec says so."
29
+ 3. **Judge design by local precedent, not by taste.** Before flagging anything as inconsistent, grep the sibling endpoints and read at least two. Then check the new surface against what THIS repo does: error envelope shape (find the canonical one; new endpoint must return it, not a fresh ad-hoc `{message}` — cite both), naming (`camelCase` vs `snake_case`, plural collections, ID field naming), auth placement (same middleware/guard pattern as siblings — compose with `security-review` if it's absent entirely), pagination style (cursor vs offset, envelope keys), timestamp format, route casing. A consistency finding without the cited precedent is an opinion; drop it or label it one.
30
+ 4. **Check the design invariants that hurt later.** These apply even with zero consumers today, because they're near-impossible to retrofit:
31
+ - **Collections paginate from day one** — an unpaginated list endpoint is a time bomb; adding pagination later breaks every consumer.
32
+ - **Retryable writes are idempotent** — POSTs that create money-adjacent or non-deduplicable resources need an idempotency key or a natural dedup constraint; name which.
33
+ - **Status codes carry their standard meaning** — 200-with-error-body, 404 for authz denials (unless deliberate resource-hiding, then say so), 500 for validation failures: each flagged with the observed code and the condition.
34
+ - **Errors are machine-usable** — a stable `code` field, not prose-only messages consumers will regex.
35
+ - **Nothing leaks that can't be unshipped** — internal IDs, stack traces, ORM entity fields serialized wholesale (grep: does the handler return the entity type or a DTO?). Every response field is a permanent promise; flag fields with no evident consumer need.
36
+ - **Timestamps and money have explicit units/zones/currency** — `amount: 4200` with no currency or minor-unit convention is a production incident on layaway.
37
+ 5. **Report in three ranked sections.** (a) **Breaking** — each with before/after citations and the migration path (version bump per the repo's existing strategy, additive alternative, deprecation window); (b) **Design** — invariant violations and precedent-cited inconsistencies; (c) **Questions** — semantics you couldn't determine from code (is this enum open? is this endpoint consumer-facing at all?). Zero findings is a valid outcome — an additive, precedent-matching endpoint should get a short pass, not invented nits. Never edit code or specs unprompted.
38
+
39
+ ## Examples
40
+
41
+ ### Example 1: "is this a breaking change?"
42
+
43
+ **User:** "I'm renaming `customer_id` to `customerId` in the orders response — breaking?"
44
+
45
+ **Claude:** Diffs before/after (breaking: field rename is remove+add for every existing reader), greps the repo — every other response uses `snake_case`, so the rename also breaks local convention rather than fixing it (cited: 9 sibling DTOs). Recommends: keep `customer_id`; if the target is a casing migration, that's an API-version-level change, not a field edit.
46
+
47
+ ### Example 2: new endpoint pass
48
+
49
+ **User:** "Review the contract for the new `/api/reports` endpoints before I build them."
50
+
51
+ **Claude:** No before-state → forward-compat pass: flags the unpaginated `GET /reports` (day-one invariant), flags `POST /reports/generate` returning 200 with the result inline when generation takes minutes (should be 202 + status resource — cites the repo's existing export endpoint doing exactly that), confirms error envelope and naming match siblings, asks one question (open or closed enum for `format`?).
52
+
53
+ ## Anti-patterns
54
+
55
+ - ❌ Declaring "breaking" or "safe" without reading the before-state — the diff of the surface is the entire evidence base.
56
+ - ❌ Imposing REST doctrine the repo doesn't follow ("should be HATEOAS", "must be plural nouns") when siblings consistently do otherwise — local consistency beats global convention; flag the doctrine mismatch once as a question, at most.
57
+ - ❌ Consistency findings with no cited precedent — grep the siblings first or don't flag it.
58
+ - ❌ Treating additive response fields as breaking, or new required request fields as safe — the asymmetry (requests: consumers write them; responses: consumers read them) is the whole compat model.
59
+ - ❌ Passing an unpaginated collection endpoint because "there won't be much data" — volume assumptions don't survive; retrofitting pagination breaks every consumer.
60
+ - ❌ Reviewing the handler's implementation quality (naming, DRY, perf) — that's `code-review`; scope discipline keeps this report actionable.
61
+ - ✅ Before/after-cited breaking verdicts, precedent-cited consistency findings, day-one invariants checked, questions kept separate from findings.
62
+
63
+ ## Notes
64
+
65
+ - Spec-first repos (OpenAPI/proto/GraphQL SDL): review the spec diff as the contract and verify the implementation actually matches it (spot-check one handler against its spec entry — drift between the two is itself a finding). Code-first repos: the serialized DTOs + routes are the contract.
66
+ - Deprecation over deletion: when a breaking change is genuinely wanted, the recommendation is the repo's existing versioning/deprecation mechanism if one exists (grep for it) — inventing a versioning strategy is a `grill-with-docs` conversation, not a review finding.
67
+ - Apply `think-like-fable`: the risk lives in the unknown consumers, so compat verdicts get the re-derivation effort; "safe" claims are labeled by what was actually diffed; the report leads with the one change the user must not merge as-is.
@@ -22,6 +22,16 @@ If you find issues, **do not start editing**. Produce the findings report first.
22
22
 
23
23
  This rule overrides any general "be helpful, fix it" instinct. A drive-by refactor mid-review collapses the user's mental model of what changed.
24
24
 
25
+ ## Evidence rules
26
+
27
+ A claim about code you haven't opened this session is a hypothesis — verify it or label it as one.
28
+
29
+ - **Read beyond the hunk.** Before flagging anything, `Read` the full enclosing function — and the whole file when it's small. Most false "missing null check" / "unhandled error" findings dissolve when you see the guard 10 lines above the hunk, or the caller that validates. A finding based only on diff-hunk context is not reportable.
30
+ - **Grep before claiming absence.** "Dead code", "unused", "never called", "duplicated elsewhere" each require a repo-wide `Grep` for the identifier first. Cite the search in the finding: *"no callers found (`grep -rn 'buildQuery' src/`)"*.
31
+ - **Quote, don't paraphrase.** Failing test output, error messages, and load-bearing identifiers go into findings verbatim (trimmed). A paraphrased error message loses the exact token that matters.
32
+ - **Zero findings is a valid outcome.** Never invent findings to appear thorough — thoroughness is measured by what you checked, and the report already lists that (build, tests, lenses run). An empty Blockers section with a green build is a good report.
33
+ - **User framing is input, not conclusion.** "The auth part is fine, just check the parser" does not exempt the auth part. Weight attention toward the ask, but never skip a category on the user's say-so.
34
+
25
35
  ## Workflow
26
36
 
27
37
  1. **Snapshot the diff.** Run in parallel:
@@ -38,7 +48,7 @@ This rule overrides any general "be helpful, fix it" instinct. A drive-by refact
38
48
  - `Cargo.toml` → `cargo build`, `cargo test`
39
49
  - `Makefile` → check for `test` / `build` targets first
40
50
  - Monorepo (`turbo.json`, `nx.json`, `pnpm-workspace.yaml`) → use the orchestrator
41
- 4. **Run tests, then build.** Tests first (faster signal). If tests pass, run the build. Capture output. If a command doesn't exist or fails to start, note it and continue — don't fabricate a green result.
51
+ 4. **Run tests, then build.** Tests first (faster signal). If tests pass, run the build. Capture output. If a command doesn't exist or fails to start, note it and continue — don't fabricate a green result. A result you didn't observe is **not run** (report ⚠️ not detected), never "passed".
42
52
  5. **Review.** Decide single-pass vs. lens council (see [Lens council](#lens-council-for-non-trivial-diffs)):
43
53
  - **Single-pass (inline)** when the diff is small and tightly scoped — roughly: < 100 lines changed, < 5 files, no security-sensitive paths (auth, crypto, input validation, file/SQL/shell sinks). Walk the priority list yourself; faster on trivial changes.
44
54
  - **Lens council** otherwise. Spawn parallel `Explore` sub-agents — one per lens — then run an adversarial critique round before reporting.
@@ -59,13 +69,20 @@ These rules govern the fix-application phase only — they don't change the repo
59
69
 
60
70
  ## Categories
61
71
 
62
- - **`blocking`** — must fix before ship: bug, broken contract, security hole, build/test failure, missing migration, hard-coded secret.
72
+ - **`blocking`** — must fix before ship: bug, broken contract, security hole, build/test failure, missing migration, hard-coded secret. **Burden of proof:** a `blocking` finding must include a one-sentence concrete failure scenario (*this input/state → this wrong outcome*). If you cannot write that sentence, demote to `suggestion`.
63
73
  - **`suggestion`** — would improve the code; user can take or leave. DRY consolidations, dead-code removal, missing error handling on non-critical paths.
64
74
  - **`nit`** — style/preference; never blocks.
65
- - **`praise`** — something done well. Include at least one when there's something genuine to praise.
75
+ - **`praise`** — something done well, cited to a specific `file:line` (*"the retry wrapper at `http.ts:40` is exactly right for this flaky API"*). Generic filler ("nice clean code!") is worse than omitting the section. Include one only when it's genuine.
66
76
 
67
77
  Lead each finding with the *why*. "This swallows the exception so a failure here is silently lost" beats "add error handling".
68
78
 
79
+ Same finding, written badly and well:
80
+
81
+ - ❌ **B1. Add error handling to `fetchUser`** — `api/user.ts:42`. *(No failure scenario, no consequence, one citation — reads as a reflex; the reviewer can't verify it or weigh it.)*
82
+ - ✅ **B1. Unhandled rejection on deleted user** — `api/user.ts:42`. **Why:** `fetchUser` rejects on 404, but `ProfilePage` (`pages/profile.tsx:18`) never catches — visiting a deleted user's profile renders a blank page with an unhandled rejection. **Fix:** catch in `ProfilePage` and render the not-found state.
83
+
84
+ The ✅ names the trigger, the concrete consequence, and both `file:line` sites — verifiable without re-deriving it.
85
+
69
86
  ## What to look for
70
87
 
71
88
  Priority order — review top-to-bottom, stop wasting tokens on lower categories once a higher one is on fire.
@@ -162,7 +179,7 @@ Performance (§5), readability (§7), and style (§8) usually roll into Design
162
179
  1. **Spawn in parallel.** Send a **single message** with N `Agent` calls (`subagent_type=Explore`). Each lens gets:
163
180
  - The full diff (or the slice relevant to its files when the diff is huge).
164
181
  - **One** lens with its checklist verbatim from [What to look for](#what-to-look-for).
165
- - Instructions: "Find issues **only in your lens.** Categorize each as `blocking` / `suggestion` / `nit`. Cite `file:line` for every finding. Lead each finding with the *why*. If your lens has no findings, say 'no findings' explicitly. Report in ≤500 words."
182
+ - Instructions: "Find issues **only in your lens.** Read the full enclosing function before flagging — hunk-only findings are not reportable. Categorize each as `blocking` / `suggestion` / `nit`; a `blocking` must state a one-sentence concrete failure scenario. Cite `file:line` for every finding. Lead each finding with the *why*. If your lens has no findings, say 'no findings' explicitly — do not pad. Report in ≤500 words."
166
183
  2. **Collect findings.** Each agent returns its list. Don't publish yet.
167
184
  3. **Critique round.** Read all lenses side by side, then do an adversarial pass before the report:
168
185
  - **Challenge every `blocking`** — "is this actually exploitable / actually a bug / would this actually break in production?" Demote to `suggestion` or drop if the answer is no when you read the surrounding code.
@@ -257,6 +274,10 @@ End with the offer. Wait for the user's choice. Apply only the approved set, the
257
274
  - ❌ DRY-ing prematurely — calling out three similar lines as duplication when the right call is to leave them. Note the pattern; flag only when the abstraction is clearly warranted.
258
275
  - ❌ Padding the report with style nits when there are correctness blockers.
259
276
  - ❌ Hand-wavy findings without `file:line`.
277
+ - ❌ Flagging from the diff hunk alone. Read the enclosing function first — the guard is often 10 lines above the hunk.
278
+ - ❌ Claiming "unused" / "dead" / "duplicated elsewhere" without a repo-wide grep for the identifier.
279
+ - ❌ A `blocking` with no concrete failure scenario. Can't write "this input → this wrong outcome"? It's a `suggestion`.
280
+ - ❌ Inventing findings on a clean diff to look thorough. Zero findings + green build is a valid, complete report.
260
281
  - ❌ Convening the lens council on a 15-line diff. Single-pass it.
261
282
  - ❌ Spawning the lens agents serially instead of in parallel — one message, N agents.
262
283
  - ❌ Skipping the critique round and publishing the raw union of lens findings. False-positive blockers erode trust fast.
@@ -41,21 +41,25 @@ If an `ONBOARDING.md` already exists, this is **refresh mode**: read it first, t
41
41
  Spawn `subagent_type=Explore` calls in a **single message** so they run concurrently. Brief each agent self-containedly — it has no conversation context. Default fan-out:
42
42
 
43
43
  - **System overview** — what this project actually does, key domains, top-level modules, public-facing surfaces (HTTP routes / CLI commands / exported APIs).
44
- - **Dependency map** — top-level prod deps only (skip dev/test/types). For each: what it does *in this codebase* (not generic), and the load-bearing call site (`file:line`). If a dep is genuinely non-obvious (niche library, internal fork, name that doesn't reveal its purpose), the agent MAY check `context7` (or any docs-MCP server available in the environment) for a one-line "what is this library" — `context7__resolve-library-id` → `context7__query-docs`. Skip the lookup for well-known libraries (React, Express, Prisma, etc.) — the *generic* description is what we're trying to avoid; what matters is how it's used *here*.
44
+ - **Dependency map** — top-level prod deps only (skip dev/test/types). For each: what it does *in this codebase* (not generic), and the load-bearing call site (`file:line`). If a dep is genuinely non-obvious (niche library, internal fork, name that doesn't reveal its purpose), the agent MAY check `context7` (or any docs-MCP server available in the environment) for a one-line "what is this library" — `context7__resolve-library-id` → `context7__query-docs`. Skip the lookup for well-known libraries (React, Express, Prisma, etc.) — the *generic* description is what we're trying to avoid; what matters is how it's used *here*. The "how it's used here" line requires a call site the agent actually opened. If no call site is found, the row reads **"declared but no usage found"** — that's a finding (candidate for removal), not a gap to paper over with a guess from the package name.
45
45
  - **Startup flow** — entry point → bootstrap → config loading → server start. A numbered sequence with `file:line` per step.
46
- - **Auth flow** — login/session/token handling, middleware/guards, user model, where authorization decisions are made. If none, the agent must say "no auth detected" explicitly so Step 3 doesn't fabricate one.
47
- - **Important files** — the 5–15 files a new contributor *must* know about, each with a one-line "why it matters."
46
+ - **Auth flow** — login/session/token handling, middleware/guards, user model, where authorization decisions are made. This section must be a **traced code path** — a middleware/guard/session check the agent read this session, cited `file:line` — never an inference from an auth library appearing in the manifest. If none, the agent must say "no auth detected" explicitly AND state what was searched (e.g. "grepped for middleware, `session`, `jwt`, `[Authorize]`, guards — no hits") so Step 3 doesn't fabricate one.
47
+ - **Important files** — the 5–15 files a new contributor *must* know about, each with a one-line "why it matters." A file earns its slot by being load-bearing, and the agent names the evidence per file: imported widely (roughly how many importers), owns a core domain concept, or is an entry point. "Looks important" is not evidence.
48
48
 
49
49
  Each agent reports back in ≤300 words with `file:line` citations. Don't ask Explore to read entire files — ask for the specific answer plus citations.
50
50
 
51
51
  ### 3. Synthesize ONBOARDING.md
52
52
 
53
- Write the artifact to `docs/ONBOARDING.md` if a `docs/` directory exists, otherwise `ONBOARDING.md` at repo root. Sections, in this order:
53
+ Write the artifact to `docs/ONBOARDING.md` if a `docs/` directory exists, otherwise `ONBOARDING.md` at repo root.
54
+
55
+ **No-fabrication gate:** every claim in the file traces to a probe run this session — a file an agent read, a grep it ran. If a claim can't name its probe, it's a hypothesis: verify it or omit it. Never fill a section by inference from framework conventions ("Next.js apps usually…").
56
+
57
+ Sections, in this order:
54
58
 
55
59
  1. **Read this first** — 3–7 bullets max. The minimum a fresh contributor needs to not be dangerous.
56
60
  2. **System overview** — 1–3 paragraphs. What it does, who it serves, the dominant architectural shape.
57
61
  3. **Startup flow** — numbered, with `file:line` per step.
58
- 4. **Auth flow** — same shape, or a one-liner "No authentication layer — this is X" if the agent confirmed none.
62
+ 4. **Auth flow** — same shape, or a one-liner "No authentication layer — this is X (searched: middleware, session/token handling, guards)" if the agent confirmed none.
59
63
  5. **Dependency map** — table: `Dependency | What it does here | Key call site`.
60
64
  6. **Important files** — bulleted list with `file:line` and a one-line "why it matters."
61
65
  7. **Project glossary** *(optional)* — only if `CONTEXT.md` exists or domain terms surfaced repeatedly during exploration.
@@ -97,7 +101,10 @@ If making this teammate-accessible would help, mention `ShareOnboardingGuide`
97
101
  - ❌ Generic framework descriptions ("This is a Next.js app."). Call out what makes THIS codebase non-obvious — the custom session helper, the funky background job runner, the legacy module that traps newcomers.
98
102
  - ❌ Listing every dependency including dev/test/types. Prod + top-level only.
99
103
  - ❌ "Important files" with 40 entries. 5–15 is the budget. If you can't pick, you don't understand the codebase yet — Explore more.
100
- - ❌ Inventing an auth flow when there isn't one. If the agent reports no auth, the section says "No authentication layer." That's load-bearing information for a future reader.
104
+ - ❌ Inventing an auth flow when there isn't one. If the agent reports no auth, the section says "No authentication layer" plus what was searched. That's load-bearing information for a future reader.
105
+ - ❌ Auth described from the manifest instead of the code. ❌ "Uses NextAuth for authentication" because `next-auth` sits in `package.json` vs. ✅ "Requests hit `middleware.ts:8` → `auth()` from `lib/auth.ts:12`; unauthenticated users redirect at `middleware.ts:19`." Trace the path or write "none detected (searched: …)".
106
+ - ❌ Papering over a dependency with no found call site. "Declared but no usage found" goes in the table verbatim — it's a finding.
107
+ - ❌ Important files picked by vibes. Each entry names its evidence: import count, domain concept owned, or entry-point role.
101
108
  - ❌ Reading whole source files into the main context. Sub-agents return summaries with `file:line` citations — trust them.
102
109
  - ❌ Claims without `file:line` citations. A claim the next reader can't verify rots fast.
103
110
  - ❌ Hard-coded dates ("as of November 2025") in the file body. Git history is the timestamp.
@@ -46,7 +46,7 @@ Before composing the message, gather two pieces of context from the repo.
46
46
  1. Run `git rev-parse --abbrev-ref HEAD` to get the current branch name.
47
47
  2. Take the last `/`-separated segment of the branch (so `feature/12345-fix_this_bug` becomes `12345-fix_this_bug`).
48
48
  3. If that segment starts with one or more digits followed by `-`, `_`, or end-of-string, those leading digits are the ticket number.
49
- 4. If no leading numeric ID is found, **omit `#<ticket>` from the message entirely** — do not invent one and do not prompt the user for it.
49
+ 4. If no leading numeric ID is found, **omit `#<ticket>` from the message entirely** — do not invent one, do not guess one from conversation context, do not reuse a stale number mentioned earlier in the session, and do not prompt the user for it. The branch name is the only source of truth for the ticket.
50
50
 
51
51
  Examples:
52
52
 
@@ -81,6 +81,11 @@ How to decide:
81
81
  3. Breaking changes get a `!` after the type / scope (e.g., `#12345 (API) feat!: drop support for Node 16`) and a `BREAKING CHANGE:` footer.
82
82
  4. Inner `type(scope)` is optional and usually redundant once `(PROJECT)` is present. Only use it when it adds real specificity beyond the project tag (e.g., `#12345 (API) fix(auth): ...` when "auth" narrows further than "API").
83
83
  5. Body explains the *why*, not the *what*. Wrap at 72 chars.
84
+ 6. The description states **what changed** at the level a reader scanning a changelog needs; the *why* goes in the body. A description that only restates the type ("fix bug") carries no information — rewrite it.
85
+ - ❌ `fix: fix bug in login`
86
+ - ✅ `fix: reject expired refresh tokens instead of issuing new access tokens`
87
+ 7. The type must match the **diff**, not the user's phrasing. The user saying "quick fix" while the staged diff adds a new endpoint means `feat`, not `fix`. Determine the type from `git diff --staged` output you actually read this session — never from the conversation summary or the user's wording alone.
88
+ 8. If the staged diff contains two unrelated changes (e.g., an auth bug fix plus a new export page), say so and suggest splitting into two commits — do not paper over it with a vague umbrella description like `chore: various updates`.
84
89
 
85
90
  ## Workflow
86
91
 
@@ -89,7 +94,7 @@ When the user asks for a commit message:
89
94
  1. Get the current branch with `git rev-parse --abbrev-ref HEAD` and extract the ticket number per the rules above.
90
95
  2. Inspect the staged diff: `git diff --cached` (or `git diff` if nothing is staged).
91
96
  3. From the changed file paths, determine the project tag — or decide to omit it.
92
- 4. Categorize the change into one of the types.
97
+ 4. Categorize the change into one of the types — based on the diff you just read, not on how the user described the work.
93
98
  5. Write a concise description.
94
99
  6. If the change is non-trivial, add a body explaining the rationale.
95
100
  7. Flag breaking changes explicitly.
@@ -131,6 +136,8 @@ BREAKING CHANGE: clients reading `user.email` must update to `user.email_address
131
136
  - ❌ `Fix: Bug in login page.` (capitalized, trailing period)
132
137
  - ❌ `feat: added the ability to export CSV files` (past tense)
133
138
  - ❌ `#12345 (CLIENT) feat: added export.` (past tense + trailing period)
134
- - ❌ Inventing a ticket number when the branch doesn't have one
139
+ - ❌ Inventing a ticket number when the branch doesn't have one — or guessing one from conversation context
140
+ - ❌ `fix: quick fix per request` when the staged diff adds a new endpoint (type from the user's phrasing, not the diff — should be `feat`)
141
+ - ❌ `chore: various updates` covering two unrelated changes — flag the split instead
135
142
  - ❌ Forcing a `(PROJECT)` tag when the diff doesn't actually map to API / CLIENT / CONSOLE / DB
136
143
  - ✅ `#12345 (CLIENT) feat: add CSV export`
@@ -70,6 +70,11 @@ Confirm:
70
70
  - [ ] The failure is reproducible across multiple runs (or, for non-deterministic bugs, reproducible at a high enough rate to debug against).
71
71
  - [ ] You have captured the exact symptom (error message, wrong output, slow timing) so later phases can verify the fix actually addresses it.
72
72
 
73
+ **Quote error text verbatim — never paraphrase.** The load-bearing token is usually the exact column name, status code, or line number, and paraphrase loses it. The difference between what the error says and what you remember it saying is where diagnosis dies.
74
+
75
+ - ❌ "some kind of null error in the billing code"
76
+ - ✅ `NullReferenceException at BillingService.cs:84 in HandleSubscriptionEvent` — the `:84` is what distinguishes hypothesis 2 from hypothesis 4.
77
+
73
78
  Do not proceed until you reproduce the bug.
74
79
 
75
80
  ## Phase 3 — Hypothesise
@@ -82,6 +87,22 @@ Each hypothesis must be **falsifiable**: state the prediction it makes.
82
87
 
83
88
  If you cannot state the prediction, the hypothesis is a vibe — discard or sharpen it.
84
89
 
90
+ **Evidence gate.** A claim about code you haven't opened this session is a hypothesis, not evidence. Cite `file:line` only for lines you actually read; "X is never called" only after you grepped for callers. Label everything else as unverified.
91
+
92
+ ### Mundane first
93
+
94
+ Exotic hypotheses (framework bug, compiler bug, race condition) are almost always wrong. Before ranking any of them above a boring cause, eliminate the boring ones — each is a 30-second check:
95
+
96
+ - **Is the code you're reading the code that's running?** Stale build artifact, uncompiled change, cached bundle, old container image. Add a marker log and confirm it appears in the output.
97
+ - **Right branch, right env, right database?** Check `git branch`, the connection string, the env vars actually loaded.
98
+ - **Did the input actually reach the function?** Log at the entry point before theorising about the logic inside.
99
+ - **Typo / off-by-one / wrong variable** in the most recently changed lines (`git diff`).
100
+ - **Config not loaded** — the setting exists but the process never read it.
101
+
102
+ When the behavior makes no sense, you are looking at the wrong code, the wrong process, or the wrong environment — not at an exotic bug.
103
+
104
+ **The user's diagnosis is hypothesis #1, not the conclusion.** If the user says "it's probably the cache layer" or "should be a quick fix", rank it, state its falsifiable prediction, and test it like the others. Never skip falsification because the user sounded sure — confident framing is not evidence.
105
+
85
106
  ### Decision gate: inline vs. hypothesis council
86
107
 
87
108
  - **Inline (skip the council)** when the cause is obvious from one read: a typo in the diff that introduced the bug, a one-file change with a clear root cause, a trivial null/undefined at an obvious site. Form 1–2 hypotheses directly.
@@ -123,8 +144,14 @@ Tool preference:
123
144
 
124
145
  **Perf branch.** For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, `performance.now()`, profiler, query plan), then bisect. Measure first, fix second.
125
146
 
147
+ **When a probe command fails:** read the full error output — don't skim it. Change exactly one thing based on what it says, retry once. Two failures on the same probe = stop and report; never retry verbatim, never proceed as if it ran, never report an observation you didn't see.
148
+
149
+ **Stop-digging rule.** After ~3 probe cycles that neither confirm nor falsify the leading hypothesis, stop probing it. Go back to Phase 3 with the evidence gathered so far and re-rank — probes that keep coming back ambiguous usually mean the hypothesis is wrong, not that it needs one more probe. Tunneling on hypothesis #1 is the failure mode this rule breaks.
150
+
126
151
  ## Phase 5 — Fix + regression test
127
152
 
153
+ **The accepted hypothesis must explain EVERY observed symptom.** A hypothesis that explains 2 of 3 symptoms is a different bug or an incomplete cause. Before writing the fix, walk the symptom list from Phase 2 and check each one off against the hypothesis — an unexplained symptom means back to Phase 3, not "probably unrelated".
154
+
128
155
  **Minimal comments.** Default to no comments in the fix or the regression test. Add one only when the *why* is non-obvious — a workaround for a specific upstream bug (with a link), a subtle invariant the code relies on, a domain rule that isn't visible from the names. Never write block headers, never restate *what* the next line does, never leave `// TODO` without an issue link. One short line max — no multi-line comment blocks. Names carry the *what*; comments earn their place only when they carry *why*.
129
156
 
130
157
  Write the regression test **before the fix** — but only if there is a **correct seam** for it.
@@ -157,6 +184,10 @@ Required before declaring done:
157
184
 
158
185
  - Jumping to a fix before building a feedback loop — you're guessing, not diagnosing.
159
186
  - A single hypothesis becomes "the cause" without falsification — anchoring.
187
+ - Adopting the user's "it's probably X" as fact. It's hypothesis #1 — rank it and falsify it like the rest.
188
+ - Ranking a race condition or framework bug above "stale build" before checking the boring causes.
189
+ - Citing `file:line` for code never opened this session, or asserting "never called" without grepping.
190
+ - Accepting a hypothesis that explains most symptoms. Most is not all; the remainder is a different bug or the real cause.
160
191
  - Running the hypothesis council for a one-line typo bug. Ceremony for its own sake. Inline 1–2 hypotheses is fine when the cause is staring at you.
161
192
  - Spawning defender sub-agents serially instead of in parallel — one message, N agents.
162
193
  - A defender that returns "could not find supporting evidence" gets ranked anyway. If the code doesn't back the hypothesis, drop it.
@@ -42,6 +42,17 @@ The user explicitly does **not** want a hard-coded `<TargetFramework>` baked int
42
42
  3. If unsure which is the current LTS, fetch the latest .NET support policy via context7 (`mcp__plugin_context7_context7__resolve-library-id` → `query-docs` for ".NET release schedule" / "dotnet support policy") or WebFetch `https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core`. Quote the version you picked back to the user before generating.
43
43
  4. Pin EF Core, ASP.NET Core, and `Microsoft.Extensions.*` package versions to the **latest stable for that TFM** — look them up via context7 (`Microsoft.EntityFrameworkCore`, `Microsoft.AspNetCore.Authentication.JwtBearer`, etc.) rather than guessing. Never hand-paste a version you don't have a source for.
44
44
  5. State the chosen TFM and package versions in your reply before writing files, so the user can object before scaffolding.
45
+ 6. Concrete resolution commands when context7 is unavailable: `dotnet package search <PackageId> --take 1` or WebFetch `https://api.nuget.org/v3-flatcontainer/<package-id-lowercase>/index.json` (last non-preview entry = latest stable). Never write a version string you did not just resolve this session — no versions from memory, no wildcards, no invented numbers.
46
+
47
+ **API-drift guard.** The version you resolved in this step decides the API shape — training-data memory is the least trustworthy source in this workflow. Highest-risk hallucination zones:
48
+
49
+ - EF Core APIs across majors (e.g. `HasCheckConstraint` moved into `ToTable(t => t.HasCheckConstraint(...))` in EF7; query/interceptor APIs get renamed between majors).
50
+ - Hosted-service and `Host` builder idioms — `Host.CreateApplicationBuilder` (post-.NET 7) vs the older `CreateDefaultBuilder` callback style; don't mix the two.
51
+ - TFM defaults: newer TFMs flip `<Nullable>` / `<ImplicitUsings>` behavior — templates must match the resolved TFM, not a remembered one.
52
+ - OpenAPI/Swagger: .NET 9+ templates dropped Swashbuckle for built-in `Microsoft.AspNetCore.OpenApi` (`AddOpenApi()` / `MapOpenApi()`). Pick the approach matching the resolved TFM; never wire both.
53
+ - Test stack majors: xunit v3 ships as the `xunit.v3` package with different runner wiring than `xunit` 2.x; AutoMapper 13+ self-registers (no `.Extensions.Microsoft.DependencyInjection` package). Match templates to what you resolved, not to package names from memory.
54
+
55
+ If you are not certain a symbol exists in the resolved version, verify it (context7 docs lookup, or read the restored package surface under `~/.nuget/packages/`) **before** writing code that depends on it.
45
56
 
46
57
  ### Step 2 — Gather inputs (ask once, in one batch)
47
58
 
@@ -66,11 +77,16 @@ Use the **templates in `references/templates/`** as the source of truth for file
66
77
  - Create directories before files. On Windows shell use PowerShell `New-Item -ItemType Directory -Force`.
67
78
  - After scaffolding, run `dotnet sln add` for every project and `dotnet build` to verify the solution compiles. Report build output to the user.
68
79
  - Do **not** run `dotnet new` to create the projects — write the `.csproj` and `.cs` files directly from templates so the layout matches exactly.
80
+ - If a `dotnet new` template IS run anyway (user's insistence): **the SDK wins on formats it owns** (`.sln` contents, `obj/`/`bin/` artifacts), **this skill wins on everything else** — overwrite template boilerplate with the skill's templates, keep this skill's project split and folder names. Reconcile deliberately and list every deviation in your report; never silently abandon the skill's patterns, never fight the SDK on formats it owns.
69
81
 
70
82
  ### Step 4 — Verify and report
71
83
 
72
- - Run `dotnet build` from the solution root. If it fails, fix and rebuild — never leave a broken scaffold.
84
+ - Run `dotnet build` from the solution root. If it fails, fix the **first** error (later errors are usually cascade) and rebuild — never leave a broken scaffold.
73
85
  - Run `dotnet test` if any test project exists.
86
+ - Do **not** run `dotnet ef migrations add` or `dotnet ef database update` yourself unless the user confirmed a reachable database — report the migration command as a next step instead. The delivery bar is the build gate, not the migration.
87
+ - Known failure signature: `NETSDK1045` ("The current .NET SDK does not support targeting …") means the TFM you picked outruns the installed SDK — re-run `dotnet --list-sdks` and re-pin to the highest installed LTS; do not install a new SDK unprompted.
88
+ - **A scaffold that hasn't compiled is not delivered.** Paste the actual proof lines in your report (`Build succeeded.` / `0 Error(s)`, and the `Passed! - Failed: 0` test summary). Never report success from memory of the steps you intended, and never report partial success as success — if something is red, say exactly what is red.
89
+ - **CLI failure protocol** (applies to `dotnet new`, `dotnet sln add`, `dotnet build`, `dotnet test`): read the full error output, change exactly one thing, retry once. If the same step fails twice, stop scaffolding and surface the verbatim error to the user — do not keep generating files on top of a broken base, and do not re-run the identical command hoping for a different result.
74
90
  - Reply with a short summary: solution path, projects created, TFM chosen, package versions, next steps (e.g. "run `dotnet ef migrations add Initial -p src/{{Solution}}.Infrastructure -s src/{{Solution}}.Api`").
75
91
 
76
92
  ## Solution layout (canonical)
@@ -143,6 +159,9 @@ Every one of these is forbidden in generated code. See [`references/anti-pattern
143
159
  3. `src/{{Solution}}.Application/` (csproj + assembly marker + `Common/` with `IUserContext`, `Result<T>` if requested, `IUnitOfWork` port, `IRepository<T>` port).
144
160
  4. `src/{{Solution}}.Infrastructure/` (csproj + `Persistence/AppDbContext.cs` + `Persistence/EntityConfigurations/` folder + `Persistence/UnitOfWork.cs` + `Auth/UserContext.cs` + `DependencyInjection.cs` with `AddInfrastructure`).
145
161
  5. `src/{{Solution}}.Api/` (csproj + `Program.cs` + `Extensions/` folder + `Middlewares/ExceptionHandlerMiddleware.cs` + `Controllers/BaseController.cs` + `appsettings.json`/`appsettings.Development.json`).
162
+
163
+ **Checkpoint:** `dotnet sln add` items 1–5 and `dotnet build` now, before generating workers and tests — a failure here localizes to the core projects; a failure after the full tree does not. Apply the Step-4 failure protocol at this checkpoint too.
164
+
146
165
  6. `src/{{Solution}}.Workers.<Name>/` per worker requested.
147
166
  7. `tests/{{Solution}}.UnitTests/` (csproj + xUnit + NSubstitute + AutoFixture).
148
167
  8. `tests/{{Solution}}.IntegrationTests/` (csproj + `Microsoft.AspNetCore.Mvc.Testing` + `Testcontainers.MsSql`) — only if user asked for it.
@@ -173,7 +192,7 @@ For entity `{{Feature}}` (e.g. `Customer`):
173
192
 
174
193
  Template for the full slice is in [`references/templates/feature-slice.md`](references/templates/feature-slice.md).
175
194
 
176
- After generating: `dotnet build` then `dotnet test`. Both must pass.
195
+ After generating: `dotnet build` then `dotnet test`. Both must pass — apply the Step-4 proof-and-failure protocol (paste the green lines; the same step failing twice = stop and surface the verbatim error).
177
196
 
178
197
  ### Mode 3 — `add-worker`
179
198
 
@@ -223,11 +242,29 @@ Look these up via context7 — do not hand-paste versions:
223
242
  - `Testcontainers.MsSql` (integration tests only)
224
243
  - `Microsoft.AspNetCore.Mvc.Testing` (integration tests only)
225
244
 
245
+ ## Final self-audit (mechanical — grep, don't recall)
246
+
247
+ The **Eliminate** list is easy to hold at file 1 and forgotten by file 30. After generating and before the final build, grep the generated tree — every command must return nothing:
248
+
249
+ ```bash
250
+ grep -rn "Thread.Sleep\|while (true)" src/ # polling-loop workers
251
+ grep -rnE "catch\s*(\(\s*Exception[^)]*\))?\s*\{\s*\}" src/ # swallowed exceptions
252
+ grep -rn "ExpandoObject\|DataRow\|SqlDataAdapter" src/ # sproc-era / reflection data access
253
+ grep -rn "GetService<" src/*/Program.cs # hosted services booted by hand
254
+ grep -rn "Newtonsoft" src/ # unless a dependency demanded it
255
+ grep -rln "public async Task" src/ | xargs grep -Ln "CancellationToken" # async surface with no ct anywhere
256
+ grep -rn "System.Data.Entity\|\"EntityFramework\"" src/ # EF6 leaking into an EF Core solution
257
+ grep -rn "CreateDefaultBuilder" src/ # mixed host-builder idioms
258
+ grep -rn "/// <summary>" src/ # XML doc blocks on internal members
259
+ ```
260
+
261
+ A hit means fix it and re-run the grep — never rationalize it away or report it as acceptable.
262
+
226
263
  ## Verification checklist before reporting "done"
227
264
 
228
265
  - [ ] `dotnet build` exits 0.
229
266
  - [ ] `dotnet test` exits 0 (if tests were generated).
230
- - [ ] No `.csproj` references violate the ONION rule (verify with `grep`/`Select-String` for cross-layer `ProjectReference`).
267
+ - [ ] No `.csproj` references violate the ONION rule. Concrete check: `grep "ProjectReference" src/*/*.csproj` Domain shows zero hits, Application references only Domain, Api/Workers never reference each other.
231
268
  - [ ] No file contains any pattern from the **Eliminate** list.
232
269
  - [ ] `Program.cs` is under ~50 lines (everything else is in extension methods).
233
270
  - [ ] Domain project's `.csproj` has zero `<ProjectReference>` entries.