agentscamp 0.1.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/LICENSE +21 -0
- package/README.md +64 -0
- package/content/agents/accessibility-auditor.md +66 -0
- package/content/agents/agent-architect.md +65 -0
- package/content/agents/agent-reliability-reviewer.md +40 -0
- package/content/agents/agent-tool-integration-engineer.md +38 -0
- package/content/agents/api-architect.md +84 -0
- package/content/agents/backend-developer.md +92 -0
- package/content/agents/browser-agent-engineer.md +37 -0
- package/content/agents/cloud-architect.md +72 -0
- package/content/agents/code-reviewer.md +69 -0
- package/content/agents/data-engineer.md +67 -0
- package/content/agents/data-scientist.md +79 -0
- package/content/agents/debugger.md +89 -0
- package/content/agents/dependency-manager.md +64 -0
- package/content/agents/devops-engineer.md +94 -0
- package/content/agents/documentation-engineer.md +52 -0
- package/content/agents/finetuning-engineer.md +43 -0
- package/content/agents/frontend-developer.md +78 -0
- package/content/agents/git-github-expert.md +66 -0
- package/content/agents/golang-pro.md +72 -0
- package/content/agents/graphql-architect.md +85 -0
- package/content/agents/kubernetes-specialist.md +87 -0
- package/content/agents/llm-cost-optimizer.md +39 -0
- package/content/agents/llm-evaluation-engineer.md +42 -0
- package/content/agents/llm-inference-engineer.md +42 -0
- package/content/agents/llm-integration-engineer.md +39 -0
- package/content/agents/llm-observability-engineer.md +41 -0
- package/content/agents/mcp-server-engineer.md +43 -0
- package/content/agents/ml-engineer.md +67 -0
- package/content/agents/mobile-developer.md +89 -0
- package/content/agents/performance-engineer.md +79 -0
- package/content/agents/postgres-migration-engineer.md +42 -0
- package/content/agents/prompt-engineer.md +58 -0
- package/content/agents/prompt-injection-auditor.md +42 -0
- package/content/agents/python-pro.md +77 -0
- package/content/agents/rag-pipeline-engineer.md +42 -0
- package/content/agents/react-specialist.md +83 -0
- package/content/agents/refactoring-specialist.md +78 -0
- package/content/agents/retrieval-engineer.md +41 -0
- package/content/agents/rust-pro.md +89 -0
- package/content/agents/security-auditor.md +78 -0
- package/content/agents/sql-pro.md +53 -0
- package/content/agents/sre-engineer.md +66 -0
- package/content/agents/system-architect.md +77 -0
- package/content/agents/terraform-specialist.md +73 -0
- package/content/agents/test-engineer.md +79 -0
- package/content/agents/typescript-pro.md +82 -0
- package/content/agents/vector-search-engineer.md +43 -0
- package/content/agents/voice-agent-engineer.md +38 -0
- package/content/agents/workflow-orchestrator.md +70 -0
- package/content/commands/add-docstrings.md +92 -0
- package/content/commands/add-human-approval.md +40 -0
- package/content/commands/add-mcp-server.md +50 -0
- package/content/commands/add-streaming-endpoint.md +34 -0
- package/content/commands/benchmark-rerankers.md +44 -0
- package/content/commands/breakdown-task.md +86 -0
- package/content/commands/commit.md +117 -0
- package/content/commands/create-pr.md +109 -0
- package/content/commands/db-migrate.md +47 -0
- package/content/commands/explain-code.md +71 -0
- package/content/commands/explain-error.md +98 -0
- package/content/commands/extract-function.md +107 -0
- package/content/commands/find-bug.md +93 -0
- package/content/commands/fix-failing-test.md +106 -0
- package/content/commands/new-component.md +119 -0
- package/content/commands/plan-feature.md +71 -0
- package/content/commands/profile-postgres-queries.md +41 -0
- package/content/commands/red-team-llm.md +45 -0
- package/content/commands/refactor.md +82 -0
- package/content/commands/review-pr.md +101 -0
- package/content/commands/run-evals.md +34 -0
- package/content/commands/scaffold-pgvector-schema.md +42 -0
- package/content/commands/scaffold-vllm-config.md +44 -0
- package/content/commands/security-scan.md +129 -0
- package/content/commands/set-perf-budget.md +47 -0
- package/content/commands/setup-claude-ci.md +60 -0
- package/content/commands/sync-branch.md +138 -0
- package/content/commands/update-readme.md +108 -0
- package/content/commands/write-tests.md +81 -0
- package/content/manifest.json +1709 -0
- package/content/skills/adr-writer.md +90 -0
- package/content/skills/branch-rebaser.md +86 -0
- package/content/skills/bundle-analyzer.md +77 -0
- package/content/skills/changelog-from-prs.md +81 -0
- package/content/skills/chunking-strategy-optimizer.md +34 -0
- package/content/skills/claude-settings-auditor.md +38 -0
- package/content/skills/conventional-commits.md +80 -0
- package/content/skills/coverage-gap-finder.md +72 -0
- package/content/skills/dead-code-finder.md +65 -0
- package/content/skills/dependency-audit.md +64 -0
- package/content/skills/embedding-index-tuner.md +34 -0
- package/content/skills/embedding-set-inspector.md +34 -0
- package/content/skills/finetune-dataset-builder.md +33 -0
- package/content/skills/graphrag-scaffolder.md +39 -0
- package/content/skills/hook-writer.md +39 -0
- package/content/skills/human-in-the-loop-gate.md +33 -0
- package/content/skills/llm-as-judge-scorer.md +33 -0
- package/content/skills/llm-eval-suite-scaffolder.md +30 -0
- package/content/skills/llm-guardrails-designer.md +33 -0
- package/content/skills/llm-output-schema-generator.md +32 -0
- package/content/skills/mcp-server-scaffolder.md +33 -0
- package/content/skills/mock-data-factory.md +75 -0
- package/content/skills/multimodal-document-extractor.md +39 -0
- package/content/skills/openapi-doc-writer.md +88 -0
- package/content/skills/plugin-scaffolder.md +38 -0
- package/content/skills/postgres-index-strategist.md +38 -0
- package/content/skills/pr-description.md +87 -0
- package/content/skills/prompt-cache-optimizer.md +34 -0
- package/content/skills/prompt-optimizer.md +40 -0
- package/content/skills/prompt-pii-redactor.md +33 -0
- package/content/skills/provider-fallback-wrapper.md +33 -0
- package/content/skills/qlora-finetune-runner.md +33 -0
- package/content/skills/readme-generator.md +84 -0
- package/content/skills/secret-scanner.md +65 -0
- package/content/skills/sql-optimizer.md +77 -0
- package/content/skills/test-scaffolder.md +74 -0
- package/content/skills/tool-definition-generator.md +33 -0
- package/content/skills/web-research-pipeline.md +39 -0
- package/dist/index.js +384 -0
- package/package.json +44 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "adr-writer"
|
|
3
|
+
description: "Write an Architecture Decision Record capturing a decision the user describes, in Michael Nygard ADR format (Status, Context, Decision, Consequences) with an added Considered Alternatives section. Use when recording a significant architectural or technology choice."
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Write"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Turn an architectural decision into a durable, reviewable record. The skill takes the decision the user describes, gathers the real constraints that shaped it from the repository, and writes a Nygard-style Architecture Decision Record — context and problem, the decision and its status, the consequences, and the alternatives that were considered and rejected. The result is a numbered, immutable document that explains *why* a choice was made to whoever reads the code in two years.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- You made a consequential, hard-to-reverse choice (datastore, framework, auth model, sync vs. async, monorepo vs. polyrepo) and want the reasoning captured before it's forgotten.
|
|
13
|
+
- You're starting an ADR log in a repo that has none, or adding the next record to an existing `docs/adr/` directory.
|
|
14
|
+
- A pull request changes architecture and a reviewer asked "where is this written down?"
|
|
15
|
+
- You're revisiting an old decision and need to supersede it with a new record instead of silently editing history.
|
|
16
|
+
|
|
17
|
+
> [!NOTE]
|
|
18
|
+
> An ADR is immutable once merged. You don't edit a decision to change it — you write a new ADR that supersedes it and flip the old one's status to `Superseded by ADR-NNNN`. Editing the substance of a merged record erases the history the log exists to preserve.
|
|
19
|
+
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
1. **Locate the ADR log.** Search for an existing directory — `docs/adr/`, `docs/decisions/`, `doc/adr/`, or `adr/`. Read one or two existing records to match the local heading set, status vocabulary, and front-matter (some logs use `MADR`, some `Nygard`, some carry a `date:`/`deciders:` block). If no log exists, default to `docs/adr/`.
|
|
23
|
+
2. **Assign the number and slug.** Find the highest existing `NNNN-*.md` and increment it, zero-padded to four digits (`0001`, `0002`, ...). Build the filename as `docs/adr/NNNN-kebab-title.md` from a short, decision-focused title (`0007-use-postgres-for-primary-store.md`). Never reuse or renumber an existing file.
|
|
24
|
+
3. **Detect the real constraints — don't invent them.** Mine the repo for evidence that shaped the decision instead of writing generic pros and cons:
|
|
25
|
+
- Read `package.json` / `requirements.txt` / `go.mod` / `Cargo.toml` for the current stack and what's already a dependency.
|
|
26
|
+
- Grep for the systems in play (`grep -ri "mongoose\|prisma\|pg\|sqlalchemy"`) to see what's actually wired up.
|
|
27
|
+
- Check `docker-compose.yml`, `*.tf`, CI config, and any `README`/`CLAUDE.md` for deployment targets, scale signals, and stated team conventions.
|
|
28
|
+
- Note the requirement that forces the decision (transactions, relational queries, a managed offering already in the cloud account, an existing team skillset).
|
|
29
|
+
4. **Write the record.** Use the Nygard section order: `# NNNN. Title`, then `## Status`, `## Context`, `## Decision`, `## Consequences` (split into *positive* and *negative* — be honest about the costs you're accepting), and `## Considered Alternatives` (an added section not in Nygard's original — list each rejected option with the specific reason it lost). Write in past/decided tense, name concrete tradeoffs, and cite the constraints from step 3 rather than restating textbook definitions.
|
|
30
|
+
5. **Set the status deliberately.** Use `Proposed` for an open decision under review, `Accepted` once it's agreed, `Deprecated` for an outdated record, or `Superseded by ADR-NNNN` when replaced. If this record retires an older one, update that file's status line to point here.
|
|
31
|
+
6. **Verify and report.** Confirm the filename number is unique, the title slug matches the heading, and every alternative has a stated reason for rejection. List the file you wrote, and flag any section you filled from assumption rather than repo evidence so the user can correct it before merging.
|
|
32
|
+
|
|
33
|
+
> [!WARNING]
|
|
34
|
+
> Don't pad the Consequences with only upsides. An ADR that lists no negative consequences is a sales pitch, not a decision record — the reviewer can't weigh a tradeoff you hid. Name the lock-in, the operational cost, or the capability you gave up.
|
|
35
|
+
|
|
36
|
+
## Examples
|
|
37
|
+
|
|
38
|
+
For the decision "choose Postgres over MongoDB for the primary datastore," the skill detects no `mongoose`/`prisma` is wired yet, sees a managed Postgres already in the cloud account, and writes `docs/adr/0001-use-postgres-as-primary-datastore.md`:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
# 0001. Use PostgreSQL as the primary datastore
|
|
42
|
+
|
|
43
|
+
## Status
|
|
44
|
+
|
|
45
|
+
Accepted — 2026-06-03
|
|
46
|
+
|
|
47
|
+
## Context
|
|
48
|
+
|
|
49
|
+
The billing and account services need ACID transactions across orders,
|
|
50
|
+
invoices, and ledger entries, and most read paths join three or more
|
|
51
|
+
entities. Our data is strongly relational with a stable schema. The team
|
|
52
|
+
already operates a managed Postgres instance in the existing cloud account
|
|
53
|
+
and knows SQL; no one has run MongoDB in production here.
|
|
54
|
+
|
|
55
|
+
## Decision
|
|
56
|
+
|
|
57
|
+
We will use PostgreSQL 16 as the primary datastore for all transactional
|
|
58
|
+
services, accessed through a single connection pool per service. Document-
|
|
59
|
+
shaped, schemaless data (audit blobs, webhook payloads) will live in
|
|
60
|
+
`jsonb` columns rather than a separate document database.
|
|
61
|
+
|
|
62
|
+
## Consequences
|
|
63
|
+
|
|
64
|
+
**Positive**
|
|
65
|
+
|
|
66
|
+
- Multi-row transactions and foreign keys enforce invariants in the
|
|
67
|
+
database instead of in application code.
|
|
68
|
+
- One datastore to operate, back up, and monitor — reuses the managed
|
|
69
|
+
instance and the team's existing SQL skills.
|
|
70
|
+
- `jsonb` covers the few semi-structured cases without a second system.
|
|
71
|
+
|
|
72
|
+
**Negative**
|
|
73
|
+
|
|
74
|
+
- Horizontal write scaling requires deliberate work (partitioning, read
|
|
75
|
+
replicas) if write volume outgrows a single primary.
|
|
76
|
+
- Schema changes need migrations and review; less forgiving than a
|
|
77
|
+
schemaless store during rapid early iteration.
|
|
78
|
+
|
|
79
|
+
## Considered Alternatives
|
|
80
|
+
|
|
81
|
+
- **MongoDB** — rejected: our access patterns are relational and need
|
|
82
|
+
cross-document transactions, which fight against its document model and
|
|
83
|
+
would push join logic into the application.
|
|
84
|
+
- **Postgres + a separate document DB** — rejected: doubles operational
|
|
85
|
+
surface for a small amount of semi-structured data that `jsonb` handles.
|
|
86
|
+
- **SQLite** — rejected: no managed multi-writer story for our concurrency
|
|
87
|
+
and availability needs.
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
After writing, report the path and note any section (e.g. projected write volume) that came from an assumption rather than a measured constraint, so the user can verify it before merging.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "branch-rebaser"
|
|
3
|
+
description: "Rebase the current branch onto its base and walk every conflict methodically, resolving each by understanding both sides. Use when your feature branch has fallen behind main and you want a clean, linear history without clobbering changes."
|
|
4
|
+
allowed-tools: "Read, Bash, Edit"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Bring the current branch up to date by rebasing it onto its base, replaying your commits one at a time on top of the latest upstream. The skill confirms the working tree is clean before touching anything, fetches the real base, then steps through conflicts deliberately — reading both versions of each hunk and reconstructing the intended result rather than blindly accepting one side — and finishes by rebuilding and re-running tests so you know the rebase preserved behavior, not just resolved markers.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- Your feature branch has fallen behind `main`/`master` and you want a linear history instead of a merge commit.
|
|
13
|
+
- A rebase is mid-flight with conflicts and you want each one resolved by intent, not by reflexively picking `--ours` or `--theirs`.
|
|
14
|
+
- You need the branch updated before opening or refreshing a PR, and CI must still pass afterward.
|
|
15
|
+
|
|
16
|
+
> [!NOTE]
|
|
17
|
+
> Rebasing rewrites commit SHAs. Only rebase branches you own. If others have based work on this branch or it is already shared, prefer a merge — or coordinate before rewriting history.
|
|
18
|
+
|
|
19
|
+
## Instructions
|
|
20
|
+
|
|
21
|
+
1. **Confirm a clean tree.** Run `git status --porcelain` and `git rev-parse --abbrev-ref HEAD`. If there are uncommitted changes, stop and have the user commit or stash them (`git stash push -u`) before proceeding — a rebase over a dirty tree loses work. Note the current branch name.
|
|
22
|
+
2. **Fetch the latest base.** Run `git fetch origin --prune` so you rebase onto what truly exists upstream, not a stale local ref.
|
|
23
|
+
3. **Identify the base — do not guess.** Detect it instead of assuming `main`:
|
|
24
|
+
- Prefer the configured upstream: `git rev-parse --abbrev-ref @{upstream}` (e.g. `origin/main`).
|
|
25
|
+
- Fall back to the repo's default branch: `git symbolic-ref refs/remotes/origin/HEAD` → strip to `origin/<branch>`.
|
|
26
|
+
- Confirm the branch is actually behind: `git rev-list --left-right --count HEAD...origin/<base>`. If the right-hand count is `0`, it's already up to date — report that and stop.
|
|
27
|
+
4. **Start the rebase.** Run `git rebase origin/<base>`. If it completes with no conflicts, skip to step 7.
|
|
28
|
+
5. **Resolve each conflict by understanding both sides.** For every conflicted file (`git diff --name-only --diff-filter=U`):
|
|
29
|
+
- Read the file and locate the `<<<<<<<` / `=======` / `>>>>>>>` markers. The top block (`HEAD`/`ours`) is the base's version; the bottom block (`theirs`) is *your* commit being replayed.
|
|
30
|
+
- Inspect both versions in isolation when unclear: `git show :2:<file>` (ours) and `git show :3:<file>` (theirs).
|
|
31
|
+
- Reconstruct the intended result so **both** changes survive — keep the upstream fix *and* your feature edit. Never delete a side just to clear the markers.
|
|
32
|
+
- Edit the file to the merged result, remove all conflict markers, then `git add <file>`.
|
|
33
|
+
6. **Continue, and repeat per commit.** Run `git rebase --continue`. Conflicts surface one replayed commit at a time, so return to step 5 for each new batch. If a commit becomes empty after resolution, `git rebase --skip` it. Use `git rebase --abort` to return to the pre-rebase state if anything looks wrong.
|
|
34
|
+
7. **Verify by building and testing.** Resolved markers are not proof of correctness. Run the project's build and test commands (detect them — e.g. `npm run build && npm test`, `pytest`, `go build ./... && go test ./...`). Fix any breakage the rebase introduced.
|
|
35
|
+
8. **Report and flag gaps.** Summarize how many commits replayed, which files conflicted and how each was resolved, and whether build/tests pass. Surface anything that needs a human eye (semantic conflicts the test suite may not catch, skipped commits). Do **not** force-push unless explicitly told to (see warning).
|
|
36
|
+
|
|
37
|
+
> [!WARNING]
|
|
38
|
+
> Updating a remote branch after a rebase requires a force-push, which rewrites history others may have pulled. Always use `git push --force-with-lease` (never bare `--force`) so you fail safely if the remote moved. If the branch is shared or backs an open PR with other contributors, **confirm with the user first** before pushing.
|
|
39
|
+
|
|
40
|
+
## Examples
|
|
41
|
+
|
|
42
|
+
A conflict-resolution loop on a branch two commits behind `origin/main`:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
$ git status --porcelain # clean tree, ok to proceed
|
|
46
|
+
$ git fetch origin --prune
|
|
47
|
+
$ git rev-list --left-right --count HEAD...origin/main
|
|
48
|
+
3 2 # 3 local commits, 2 upstream → behind, rebase
|
|
49
|
+
|
|
50
|
+
$ git rebase origin/main
|
|
51
|
+
Auto-merging src/config.ts
|
|
52
|
+
CONFLICT (content): Merge conflict in src/config.ts
|
|
53
|
+
error: could not apply 1f4a2b9... feat(config): add retry option
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`src/config.ts` shows both sides — upstream renamed the timeout field; your commit added a sibling key:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
<<<<<<< HEAD # ours: upstream's rename
|
|
60
|
+
requestTimeoutMs: 5_000,
|
|
61
|
+
======= # theirs: your new feature
|
|
62
|
+
timeout: 5000,
|
|
63
|
+
retries: 3,
|
|
64
|
+
>>>>>>> 1f4a2b9 (feat(config): add retry option)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Keep *both* intentions — adopt the upstream rename and carry your new key onto it:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
requestTimeoutMs: 5_000,
|
|
71
|
+
retries: 3,
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
$ git add src/config.ts
|
|
76
|
+
$ git rebase --continue
|
|
77
|
+
[detached HEAD 9c1d0e2] feat(config): add retry option
|
|
78
|
+
Successfully rebased and updated refs/heads/feat/retry.
|
|
79
|
+
|
|
80
|
+
$ npm run build && npm test # verify behavior, not just markers
|
|
81
|
+
✓ build passed ✓ 142 tests passed
|
|
82
|
+
|
|
83
|
+
$ git push --force-with-lease # only after confirming the branch isn't shared
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Reported: 3 commits replayed, 1 conflict in `src/config.ts` (resolved by adopting the upstream `requestTimeoutMs` rename while carrying `retries`), build and tests green.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "bundle-analyzer"
|
|
3
|
+
description: "Analyze a JS/TS production bundle and surface the biggest size wins — heavy dependencies, duplicate packages, missing code-splitting, oversized polyfills, and dev/server code leaking into the client. Use when a bundle is too large and you need a ranked, actionable reduction plan."
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Bash"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Inspect a JavaScript/TypeScript production bundle and find where the bytes actually go. The skill builds a stats report, attributes weight to specific modules and packages, and hunts for the patterns that bloat bundles in practice — a 200KB date library imported for one helper, two copies of the same package at different versions, a route that ships eagerly instead of lazily, a polyfill set targeting browsers you dropped years ago, or server-only code that slipped past the client boundary. It returns a ranked list of concrete reductions with the estimated savings of each, so you fix the 80KB win before the 4KB one.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- A production bundle (or a specific route/chunk) has grown past budget and you need to know exactly what to cut.
|
|
13
|
+
- You suspect duplicate packages, a heavyweight dependency, or a barrel import dragging in a whole library.
|
|
14
|
+
- A first-load or main chunk is too big and you want to know what should be code-split or deferred.
|
|
15
|
+
- You want to confirm dev-only tooling, source maps, or server code is not leaking into the client bundle.
|
|
16
|
+
|
|
17
|
+
> [!NOTE]
|
|
18
|
+
> Always measure the **production** build, not dev. Dev bundles include HMR runtime, unminified source, and no tree-shaking, so their sizes are meaningless for this analysis. Compare **gzip/brotli** transfer sizes, not raw bytes — that is what users actually download.
|
|
19
|
+
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
1. **Locate the build and detect the bundler.** Identify the toolchain before doing anything — do not guess. Check `package.json` scripts and lockfiles for `next`, `vite`, `webpack`, `rollup`, `esbuild`, or `@remix-run`. Note the package manager (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lockb`) since duplicate-detection commands differ per manager.
|
|
23
|
+
2. **Produce a stats report using the project's own analyzer.** Match existing config rather than bolting on a new tool:
|
|
24
|
+
- **Next.js** — run the production build and read its per-route First Load JS table; if `@next/bundle-analyzer` is wired up, run `ANALYZE=true npm run build`.
|
|
25
|
+
- **Vite/Rollup** — use `rollup-plugin-visualizer` if present, or build and inspect `dist/assets/*` sizes.
|
|
26
|
+
- **Webpack** — generate `--json` stats (`webpack --profile --json=stats.json`, which writes the file directly so console warnings don't corrupt the JSON) and analyze, e.g. with `source-map-explorer` over the emitted bundle + map.
|
|
27
|
+
- If no analyzer is configured, fall back to `npx source-map-explorer 'dist/**/*.js'` against the built output and its source maps.
|
|
28
|
+
3. **Attribute weight to packages, not just files.** Map the largest modules back to their npm packages. For each heavyweight dependency, determine whether it is fully used or pulled in by a barrel/side-effect import, and whether a lighter alternative exists (e.g. `date-fns`/`dayjs` over `moment`, native `Intl` over `numeral`, `lodash-es` with named imports over `lodash`).
|
|
29
|
+
4. **Detect duplicates and version skew.** Run `npm ls <pkg>` / `pnpm why <pkg>` / `yarn why <pkg>` on suspect packages to find the same library bundled at multiple versions, and check for both ESM and CJS copies of the same dep. Flag candidates for `resolutions`/`overrides` or dedupe.
|
|
30
|
+
5. **Find missing code-splitting and oversized polyfills.** Look for large modules in the entry/main chunk that are only needed on one route or behind an interaction (charts, editors, markdown renderers, PDF libs) — these belong behind `import()` / `next/dynamic` / `React.lazy`. Inspect the polyfill/transpile target (`browserslist`, `target` in `tsconfig`/`vite`/`tsup`) for `core-js` or regenerator-runtime bloat aimed at browsers you no longer support.
|
|
31
|
+
6. **Hunt for leaked dev/server code.** Grep the client bundle and imports for things that should never ship: test/mock files, `process.env` debug branches, server-only modules (`fs`, `crypto` server usage, DB clients, secrets), and dev dependencies imported from app code. In Next.js, confirm Server Component / `"use client"` boundaries are not dragging server modules into client chunks.
|
|
32
|
+
7. **Verify each proposed cut.** Do not estimate from intuition alone. Where feasible, apply the change behind the analyzer (or `--dry`) and re-run the build to measure the real delta. At minimum, cite the measured pre-change size from the stats report for every finding.
|
|
33
|
+
8. **Report a ranked plan.** Output findings ordered by estimated gzip savings, each with: the module/package, current size, the specific fix, the expected reduction, and a rough effort/risk rating. Flag anything you could not measure precisely so the user knows what to confirm.
|
|
34
|
+
|
|
35
|
+
> [!WARNING]
|
|
36
|
+
> Tree-shaking only works on side-effect-free ESM. A default or namespace import from a CJS package (or a package missing `"sideEffects": false`) pulls in the **whole** module regardless of what you use — so "import one helper" can still cost the full library. Verify the import shape, not just the import statement.
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
A ranked findings report for a Next.js app whose largest route shipped 412 KB of First Load JS:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
Bundle analysis — route /dashboard (First Load JS: 412 KB gzip → target 180 KB)
|
|
44
|
+
Ranked by estimated gzip savings:
|
|
45
|
+
|
|
46
|
+
1. moment + moment-timezone .................. 71 KB [HIGH]
|
|
47
|
+
Imported in 3 files for formatting only. Replace with date-fns
|
|
48
|
+
named imports (tree-shakeable). Est. -64 KB. Effort: M, Risk: low.
|
|
49
|
+
|
|
50
|
+
2. Duplicate react (18.2.0 + 18.3.1) .......... 44 KB [HIGH]
|
|
51
|
+
`npm ls react` shows two copies via an old @charting/core dep.
|
|
52
|
+
Add an override to pin a single version + dedupe. Est. -44 KB.
|
|
53
|
+
Effort: S, Risk: low.
|
|
54
|
+
|
|
55
|
+
3. recharts loaded eagerly in entry chunk ..... 38 KB [HIGH]
|
|
56
|
+
Only rendered below the fold on /dashboard. Move behind
|
|
57
|
+
next/dynamic({ ssr: false }). Est. -38 KB from First Load.
|
|
58
|
+
Effort: S, Risk: low.
|
|
59
|
+
|
|
60
|
+
4. lodash default import (whole library) ...... 24 KB [MED]
|
|
61
|
+
`import _ from "lodash"`. Switch to `lodash-es` + named imports
|
|
62
|
+
(debounce, groupBy). Est. -21 KB. Effort: S, Risk: low.
|
|
63
|
+
|
|
64
|
+
5. core-js polyfills for IE11 ................. 19 KB [MED]
|
|
65
|
+
browserslist still includes "ie 11". Drop it (no IE traffic in
|
|
66
|
+
analytics). Est. -19 KB. Effort: S, Risk: med (confirm targets).
|
|
67
|
+
|
|
68
|
+
6. server-only `pg` Pool pulled into client ... 12 KB [HIGH]
|
|
69
|
+
db/client.ts imported from a "use client" component. Move the
|
|
70
|
+
query behind a Server Action / route handler. Est. -12 KB +
|
|
71
|
+
removes a secret-leak vector. Effort: M, Risk: med.
|
|
72
|
+
|
|
73
|
+
Estimated total reduction: ~198 KB gzip (412 → ~214 KB).
|
|
74
|
+
Top 3 fixes alone recover 146 KB. Re-run the analyzer after each.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Re-run the build after applying the top findings to confirm the measured First Load JS dropped as projected, and re-check `npm ls` to verify the duplicate is gone.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "changelog-from-prs"
|
|
3
|
+
description: "Draft a release changelog by summarizing merged pull requests since the last tag. Use when preparing a release or writing release notes."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Turn a range of merged pull requests into a clean, human-readable changelog. This skill collects the PRs merged since the previous release tag, groups them by change type (features, fixes, breaking changes, and more), and drafts release notes that are accurate, scannable, and ready to paste into a GitHub release or `CHANGELOG.md`.
|
|
8
|
+
|
|
9
|
+
## When to use this skill
|
|
10
|
+
|
|
11
|
+
- You are cutting a new release and need release notes that reflect what actually shipped.
|
|
12
|
+
- You want a first draft of a `CHANGELOG.md` entry that follows [Keep a Changelog](https://keepachangelog.com/) conventions.
|
|
13
|
+
- You need to summarize a noisy list of merge commits into something a human reader can understand.
|
|
14
|
+
- You are reviewing what changed between two tags before deciding on a version bump.
|
|
15
|
+
|
|
16
|
+
> [!NOTE]
|
|
17
|
+
> This skill drafts notes from real PR data. It does not push tags or publish releases. Always review the draft before publishing.
|
|
18
|
+
|
|
19
|
+
## Instructions
|
|
20
|
+
|
|
21
|
+
1. **Find the last release tag.** Use the most recent semantic-version tag as the lower bound. If no tag exists, fall back to the first commit.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git describe --tags --abbrev=0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. **Collect merged PRs in the range.** Prefer the GitHub CLI so you get titles, numbers, authors, and labels. Use the merge date of the last tag as the cutoff.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
LAST_TAG=$(git describe --tags --abbrev=0)
|
|
31
|
+
SINCE=$(git log -1 --format=%cI "$LAST_TAG")
|
|
32
|
+
gh pr list --state merged --base main --limit 200 \
|
|
33
|
+
--search "merged:>$SINCE" \
|
|
34
|
+
--json number,title,author,labels,mergedAt
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. **Classify each PR.** Map it to a changelog section using labels first, then the title prefix (Conventional Commits style), then a judgment call:
|
|
38
|
+
- `feat` / `enhancement` -> **Added** or **Changed**
|
|
39
|
+
- `fix` / `bug` -> **Fixed**
|
|
40
|
+
- `breaking` / `!` in the title -> **Breaking Changes** (call these out at the top)
|
|
41
|
+
- `deprecate` -> **Deprecated**
|
|
42
|
+
- `security` -> **Security**
|
|
43
|
+
- `docs`, `chore`, `ci`, `test`, dependency bumps -> omit unless user-facing.
|
|
44
|
+
|
|
45
|
+
4. **Rewrite titles into reader-facing notes.** Drop the type prefix, use the imperative-to-past or noun phrasing the section expects, and explain the user impact rather than the implementation. Keep the PR number for traceability.
|
|
46
|
+
|
|
47
|
+
5. **Order and group.** Lead with breaking changes, then Added, Changed, Deprecated, Removed, Fixed, Security. Within a section, order by importance, not PR number.
|
|
48
|
+
|
|
49
|
+
6. **Suggest the version bump.** Breaking changes -> major; new features -> minor; fixes only -> patch. State the recommendation but let the user confirm.
|
|
50
|
+
|
|
51
|
+
7. **Emit the draft.** Output Markdown ready to paste, with a version header and date. Note any PRs you could not confidently classify so the user can review them.
|
|
52
|
+
|
|
53
|
+
> [!WARNING]
|
|
54
|
+
> Do not invent changes. If a PR title is ambiguous, list it under an "Uncategorized — needs review" heading instead of guessing its impact.
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
**Input** — three merged PRs since `v1.3.0`:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
#142 feat: add --json output flag to export command (label: enhancement)
|
|
62
|
+
#147 fix: prevent crash when config file is empty (label: bug)
|
|
63
|
+
#151 feat!: rename `--token` to `--api-key` (label: breaking)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Output** — drafted changelog entry:
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
## v1.4.0 — 2026-06-02
|
|
70
|
+
|
|
71
|
+
### Breaking Changes
|
|
72
|
+
- Renamed the `--token` flag to `--api-key` for clarity. Update scripts that pass `--token`. (#151)
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
- `export` now supports a `--json` flag for machine-readable output. (#142)
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
- Fixed a crash that occurred when the config file was empty. (#147)
|
|
79
|
+
|
|
80
|
+
> Recommended bump: minor → major (contains a breaking change). Suggested version: v2.0.0.
|
|
81
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "chunking-strategy-optimizer"
|
|
3
|
+
description: "Find the chunking strategy and size that maximizes retrieval quality for a specific corpus, by sweeping configurations against a fixed eval set instead of guessing. Use when RAG answers miss obvious content, when standing up a new corpus, or when picking chunk size/overlap."
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Bash"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Chunking is the highest-leverage, most-overlooked knob in retrieval: if the right passage never lands in a single chunk, no reranker or bigger model recovers it. This skill replaces "512 tokens with 50 overlap, because that's what the tutorial said" with a measured choice — sweep candidate strategies over a fixed eval set and pick the one that actually retrieves the answers.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- Standing up retrieval for a new corpus and you need a defensible chunking default.
|
|
13
|
+
- RAG answers miss content you can see exists in the source documents.
|
|
14
|
+
- Deciding chunk size, overlap, or strategy (token vs. sentence vs. recursive vs. semantic).
|
|
15
|
+
- Migrating embedding models and want to re-confirm chunking still holds up.
|
|
16
|
+
|
|
17
|
+
## Instructions
|
|
18
|
+
|
|
19
|
+
1. **Build a retrieval eval set first.** Collect 20–50 real questions and, for each, the passage(s) that contain the answer (the "gold" spans). Hand-label if needed — even 20 cases beat eyeballing. This set is the ground truth every configuration is scored against; freeze it.
|
|
20
|
+
2. **Define the candidate configurations.** A small grid, not a search of everything: 2–3 strategies (e.g. recursive, sentence, semantic) × 2–3 sizes (e.g. 256 / 512 / 1024 tokens) × overlap (0 / 10–15%). Hold the embedding model and retriever fixed so chunking is the only variable.
|
|
21
|
+
3. **Run each configuration end to end.** For each config: chunk the corpus (e.g. with [Chonkie](/tools/chonkie)), embed the chunks with the fixed model, index them, and run the eval queries.
|
|
22
|
+
4. **Score retrieval, not generation.** Report **recall@k** (does a gold passage appear in the top-k?) and a rank-aware metric like **nDCG@k** for k ∈ {5, 10, 20}. Generation quality is downstream noise here — measure whether the right chunk is retrieved at all.
|
|
23
|
+
5. **Pick the smallest config that clears the bar.** Prefer the configuration with the fewest/smallest chunks that hits your recall target — smaller chunks mean lower embedding cost, lower storage, and tighter prompts. Report the full table so the trade-off is visible.
|
|
24
|
+
6. **Re-check after any upstream change.** New embedding model, new document types, or a corpus that grew in a new direction all invalidate the result — re-run the sweep.
|
|
25
|
+
|
|
26
|
+
> [!WARNING]
|
|
27
|
+
> Never tune chunking without a frozen eval set and a baseline number. "The answers look better" is how silent recall regressions ship. If no eval set exists, building one is your first deliverable.
|
|
28
|
+
|
|
29
|
+
> [!TIP]
|
|
30
|
+
> Semantic chunking often wins on heterogeneous prose but costs embeddings at ingestion time; fixed-size recursive chunking is cheaper and frequently close. Let the numbers, not the brochure, decide.
|
|
31
|
+
|
|
32
|
+
## Output
|
|
33
|
+
|
|
34
|
+
A ranked table of configurations with recall@k and nDCG@k, the recommended configuration with its rationale, and the eval set itself (so the decision is reproducible and re-runnable).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "claude-settings-auditor"
|
|
3
|
+
description: "Audit every Claude Code settings layer — user, project, local, and managed — and report the effective merged configuration with its risks: over-broad Bash allows, missing deny rules for secrets, bypassPermissions defaults, unvetted MCP servers and hooks, and rules that never match. Use before trusting a new repo's checked-in settings, or to harden your own before handing the agent more autonomy."
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Bash"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Claude Code's behavior is the *merge* of up to five settings sources — and the merged result is what nobody ever reads. This skill reads it for you: every layer, precedence applied, with each risky or dead rule called out and a safer replacement proposed. Run it on a freshly cloned repo before working in it, or on your own setup before granting more autonomy.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- You cloned a repo with a checked-in `.claude/settings.json` (and maybe `.mcp.json` and hooks) and want to know what you're trusting before the first session.
|
|
13
|
+
- Your permission prompts feel wrong — too many, too few — and you want the effective rule set explained.
|
|
14
|
+
- You're about to loosen the reins (acceptEdits, broader allows, CI automation) and want the floor checked first.
|
|
15
|
+
|
|
16
|
+
## When NOT to use this skill
|
|
17
|
+
|
|
18
|
+
- You want to *write* a specific hook — that's [hook-writer](/skills/workflow/hook-writer).
|
|
19
|
+
- You're auditing the application's code for vulnerabilities — that's the [security-auditor](/agents/quality-security/security-auditor) agent; this skill audits the agent harness configuration itself.
|
|
20
|
+
|
|
21
|
+
## Instructions
|
|
22
|
+
|
|
23
|
+
1. **Collect every layer.** Read `~/.claude/settings.json`, `.claude/settings.json`, `.claude/settings.local.json`, and check for managed policy files (platform-specific admin paths). Include `.mcp.json` and any `.claude/hooks/` scripts referenced. Note which files exist, which are committed to the repo, and which are personal.
|
|
24
|
+
2. **Compute the effective configuration.** Apply precedence (managed > local > project > user) and the permission decision order (deny → ask → allow). Produce the merged permissions table, the active hooks by event, the MCP servers by scope, and the notable toggles (`defaultMode`, `enableAllProjectMcpServers`, `disableAllHooks`, `autoMemoryEnabled`).
|
|
25
|
+
3. **Hunt permission holes.** Flag, with severity: blanket allows (`Bash`, `Bash(*)`, `mcp__*` in allow), allows that swallow more than intended (`Bash(git *)` covers `git push --force`), **missing deny rules for secrets** (`.env*`, key files, cloud credential paths), `WebFetch` unbounded, and `bypassPermissions` as a default mode anywhere outside a container.
|
|
26
|
+
4. **Vet hooks and MCP servers as supply chain.** For each hook script: what does it execute, is the source readable, does any blocking hook fail open? For each MCP server: scope, provenance, whether secrets are inline instead of `${VAR}` expansion, and whether `enableAllProjectMcpServers` auto-approves more than the user realizes. Read the scripts — don't trust filenames.
|
|
27
|
+
5. **Find dead and shadowed rules.** Rules that can never fire (shadowed by an earlier deny, malformed pattern, the `Bash(ls *)`-vs-`lsof` word-boundary trap, tools that don't exist) are noise that breeds false confidence — list them for deletion.
|
|
28
|
+
6. **Report by severity, then propose the patch.** CRITICAL (acts now, dangerous), WARN (risky under the wrong prompt), INFO (hygiene). For each finding: the file and line, why it matters in one sentence, and the exact replacement rule. Offer the corrected settings JSON as a diff the user can apply — but do not modify files unless asked.
|
|
29
|
+
|
|
30
|
+
> [!NOTE]
|
|
31
|
+
> A checked-in settings file is the *team's* contract — recommend fixes to it as a PR suggestion, not a silent local edit, and keep personal loosening in `settings.local.json` where it belongs.
|
|
32
|
+
|
|
33
|
+
> [!TIP]
|
|
34
|
+
> The fastest wins are nearly universal: add `deny: ["Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)"]`, replace any bare `Bash` allow with the three or four commands actually used, and move `git push` to `ask`.
|
|
35
|
+
|
|
36
|
+
## Output
|
|
37
|
+
|
|
38
|
+
An effective-configuration summary (what wins, from which file), a severity-ordered findings list with file:line and one-line impact each, and a ready-to-apply corrected settings diff — plus the explicit list of things that looked unusual but are fine, so the next auditor doesn't re-litigate them.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "conventional-commits"
|
|
3
|
+
description: "Generate clear Conventional Commits messages from staged changes. Use when committing code and you want a well-structured, consistent commit message."
|
|
4
|
+
allowed-tools: "Bash"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
This skill inspects your staged changes and produces a commit message that follows the [Conventional Commits](https://www.conventionalcommits.org/) specification. It picks the right type and scope, writes a concise imperative subject, adds a body explaining the *why* when the change is non-trivial, and flags breaking changes correctly — so your history stays readable and your tooling (changelogs, semantic-release) keeps working.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- You have changes staged with `git add` and want to commit them.
|
|
13
|
+
- You want a consistent, spec-compliant message instead of free-form text.
|
|
14
|
+
- You are unsure which type (`feat`, `fix`, `chore`, …) fits the change.
|
|
15
|
+
- Your repo uses semantic versioning or automated changelog generation that depends on commit conventions.
|
|
16
|
+
|
|
17
|
+
> [!NOTE]
|
|
18
|
+
> This skill only reads and commits what is **already staged**. Stage the exact hunks you want first (`git add -p`). It will not stage files for you.
|
|
19
|
+
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
1. Read the staged diff to understand what actually changed:
|
|
23
|
+
```bash
|
|
24
|
+
git diff --cached
|
|
25
|
+
```
|
|
26
|
+
If nothing is returned, stop and tell the user there are no staged changes to commit.
|
|
27
|
+
2. Check the staged file list for scope hints (directory or package names):
|
|
28
|
+
```bash
|
|
29
|
+
git diff --cached --name-only
|
|
30
|
+
```
|
|
31
|
+
3. Choose the **type** from the staged changes:
|
|
32
|
+
- `feat` — a new user-facing capability
|
|
33
|
+
- `fix` — a bug fix
|
|
34
|
+
- `docs` — documentation only
|
|
35
|
+
- `style` — formatting, no logic change
|
|
36
|
+
- `refactor` — code change that neither fixes a bug nor adds a feature
|
|
37
|
+
- `perf` — performance improvement
|
|
38
|
+
- `test` — adding or correcting tests
|
|
39
|
+
- `build` / `ci` — build system or pipeline changes
|
|
40
|
+
- `chore` — maintenance, deps, tooling
|
|
41
|
+
4. Derive an optional **scope** in parentheses from the affected area (e.g. `auth`, `api`, `parser`). Omit it if the change is broad.
|
|
42
|
+
5. Write the **subject** line: `type(scope): summary`
|
|
43
|
+
- Imperative mood ("add", not "added" or "adds").
|
|
44
|
+
- No trailing period; aim for 50 characters, hard limit 72.
|
|
45
|
+
6. If the change is non-trivial, add a blank line then a **body** explaining the motivation and any context the diff alone does not convey. Wrap at ~72 columns.
|
|
46
|
+
7. If the change breaks compatibility, mark it: append `!` after the type/scope (e.g. `feat(api)!:`) **and** add a `BREAKING CHANGE:` footer describing the migration.
|
|
47
|
+
8. Add footers for issue references when relevant (e.g. `Refs: #123`, `Closes: #456`).
|
|
48
|
+
9. Present the proposed message to the user for confirmation, then commit:
|
|
49
|
+
```bash
|
|
50
|
+
git commit -m "feat(parser): add support for nested arrays" \
|
|
51
|
+
-m "Handles arbitrarily deep nesting by recursing on bracket pairs." \
|
|
52
|
+
-m "Closes: #128"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
Suppose `git diff --cached --name-only` shows `src/auth/session.ts` and the diff replaces a 1-hour token TTL with a configurable value, removing the old constant.
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
feat(auth)!: make session token TTL configurable
|
|
61
|
+
|
|
62
|
+
Replace the hardcoded 1-hour TTL with SESSION_TTL_SECONDS so deployments
|
|
63
|
+
can tune session lifetime without a rebuild. Falls back to 3600 when the
|
|
64
|
+
variable is unset.
|
|
65
|
+
|
|
66
|
+
BREAKING CHANGE: the SESSION_MAX_AGE constant has been removed. Set the
|
|
67
|
+
SESSION_TTL_SECONDS environment variable instead.
|
|
68
|
+
|
|
69
|
+
Closes: #214
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Commit it:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git commit \
|
|
76
|
+
-m "feat(auth)!: make session token TTL configurable" \
|
|
77
|
+
-m "Replace the hardcoded 1-hour TTL with SESSION_TTL_SECONDS so deployments can tune session lifetime without a rebuild. Falls back to 3600 when the variable is unset." \
|
|
78
|
+
-m "BREAKING CHANGE: the SESSION_MAX_AGE constant has been removed. Set the SESSION_TTL_SECONDS environment variable instead." \
|
|
79
|
+
-m "Closes: #214"
|
|
80
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "coverage-gap-finder"
|
|
3
|
+
description: "Run the project's coverage tool and identify the highest-value untested paths — error branches, edge cases, and critical modules — then propose specific test cases for each gap. Use when you have a coverage report but don't know where new tests will pay off most."
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Bash"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Turn a raw coverage report into a ranked, actionable plan. This skill runs the project's existing coverage tool, reads the per-line and per-branch data, and surfaces the gaps that actually matter — uncovered error handlers, unguarded edge cases, and critical modules with thin coverage — rather than nudging an arbitrary percentage upward. For each gap it proposes concrete, named test cases you can hand straight to a scaffolder. The goal is risk reduction per test written, not a green 100% badge.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- You have (or can generate) a coverage report but don't know which untested lines are worth testing first.
|
|
13
|
+
- A module is business-critical and you want to confirm its error paths and edge cases are exercised.
|
|
14
|
+
- You're triaging tech debt and need a prioritized list of test gaps instead of a wall of red lines.
|
|
15
|
+
|
|
16
|
+
> [!NOTE]
|
|
17
|
+
> Line coverage measures *executed* lines, not *correct* behavior. A function can be 100% covered by a test that asserts nothing. Treat coverage as a map of blind spots, not a quality score — prioritize gaps by blast radius, then verify the new tests actually assert something.
|
|
18
|
+
|
|
19
|
+
## Instructions
|
|
20
|
+
|
|
21
|
+
1. **Detect the test stack and coverage tool.** Do not guess — inspect the project:
|
|
22
|
+
- JS/TS: `package.json` for `vitest --coverage` / `jest --coverage` (look for `coverage` scripts or a `c8`/`nyc`/`@vitest/coverage-v8` dep).
|
|
23
|
+
- Python: `pytest --cov` (`pytest-cov`), `coverage run`, config in `pyproject.toml`/`.coveragerc`.
|
|
24
|
+
- Go: `go test -coverprofile`. Java: JaCoCo. Match whatever already runs in CI.
|
|
25
|
+
2. **Generate machine-readable coverage.** Run the tool to emit a structured report — `--coverage --coverage.reporter=json` (Vitest), `--cov --cov-report=json` (pytest), or `-coverprofile=cover.out` (Go). Parse the JSON/profile, not the pretty terminal table; you need per-file branch and line data. (For Vitest, `--coverage.reporter=json` writes `coverage/coverage-final.json` with per-file branch and line data; the unrelated `--reporter=json` is a *test-result* reporter — pass/fail/timing — and won't produce coverage.)
|
|
26
|
+
3. **Rank gaps by value, not size.** For every uncovered region, weight it by signals — uncovered `catch`/`except`/error returns, `if`/`switch` branches with no covered alternative, input validation, and modules central to the app (auth, payments, parsing, persistence). Down-rank generated code, trivial getters, and config glue. A 60%-covered payment module outranks a 40%-covered logging helper.
|
|
27
|
+
4. **Locate the exact untested paths.** For each top gap, read the source and name the specific uncovered branch (file, function, line range) and *why* it's untested — e.g. "the `429` retry branch is never hit because no test injects a rate-limit response."
|
|
28
|
+
5. **Propose concrete test cases.** For each gap, write one bullet per missing case stating the input/condition and the expected behavior — not "add tests for error handling," but "call `withRetry` with a stubbed client that throws `RateLimitError` twice then succeeds; assert it retries and returns the value." Hand these to `test-scaffolder` to generate.
|
|
29
|
+
6. **Verify the baseline and report.** Re-run coverage to confirm the numbers you're quoting are current, then output a prioritized gap list (highest value first) with file, current coverage, the risk, and the proposed cases. Flag any module you couldn't analyze (e.g. excluded from the report, untestable without a fixture).
|
|
30
|
+
|
|
31
|
+
> [!WARNING]
|
|
32
|
+
> Never chase 100%. Forcing coverage on glue code, framework boilerplate, or unreachable defensive branches produces brittle tests that assert nothing and slow the suite. Stop when the remaining gaps are low-risk — and say so explicitly in the report.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
Running coverage on a Vitest project and triaging the JSON report:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx vitest run --coverage --coverage.reporter=json
|
|
40
|
+
# reads coverage/coverage-final.json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Output — a prioritized gap list, not a flat percentage:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Coverage: 78% lines / 64% branches (412/640 branches)
|
|
47
|
+
|
|
48
|
+
HIGH VALUE
|
|
49
|
+
1. src/payments/charge.ts — 71% lines, 50% branches
|
|
50
|
+
Risk: the declined-card and idempotency-key-reuse branches are never exercised.
|
|
51
|
+
Propose:
|
|
52
|
+
- charge() with a gateway stub returning `card_declined` → asserts no DB write, throws PaymentError
|
|
53
|
+
- charge() called twice with the same idempotency key → asserts the second call returns the first result, no double charge
|
|
54
|
+
|
|
55
|
+
2. src/auth/verifyToken.ts — 83% lines, 60% branches
|
|
56
|
+
Risk: expired-token and malformed-signature paths uncovered.
|
|
57
|
+
Propose:
|
|
58
|
+
- verifyToken() with a token whose `exp` is in the past → asserts throws TokenExpiredError
|
|
59
|
+
- verifyToken() with a tampered signature → asserts throws InvalidSignatureError
|
|
60
|
+
|
|
61
|
+
MEDIUM VALUE
|
|
62
|
+
3. src/parse/csv.ts — 88% lines
|
|
63
|
+
Risk: quoted-field-with-embedded-comma branch untested.
|
|
64
|
+
Propose:
|
|
65
|
+
- parseCsv('"a,b",c') → asserts two fields ["a,b", "c"]
|
|
66
|
+
|
|
67
|
+
SKIP (low value)
|
|
68
|
+
- src/logger.ts (45%) — thin wrapper over console; defensive branches only.
|
|
69
|
+
- src/generated/*.ts — codegen output, exclude from coverage instead.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Hand the HIGH and MEDIUM cases to `test-scaffolder`, then re-run coverage to confirm the branches now flip green.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "dead-code-finder"
|
|
3
|
+
description: "Find genuinely unused code — unreferenced exports, unreachable files, and unused dependencies — and remove it safely with build/test verification. Use when trimming a codebase or untangling years of accreted cruft."
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Bash"
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Hunt down code that nothing references and delete it without breaking the build. The skill walks the dependency graph from the project's real entry points, flags exports no module imports, files no path reaches, and dependencies no source line uses — then removes them one at a time, re-running the build and tests after each deletion so a false positive surfaces immediately instead of in production.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- A codebase has accumulated dead exports, orphaned files, or leftover utilities after refactors and feature removals.
|
|
13
|
+
- `package.json` lists dependencies you suspect nothing imports anymore.
|
|
14
|
+
- You want a measured, verifiable cleanup pass — not a risky bulk delete.
|
|
15
|
+
|
|
16
|
+
> [!WARNING]
|
|
17
|
+
> "Unreferenced" is not the same as "unused." Code can be reached at runtime in ways static search misses: string-based requires (`require(`./handlers/${name}`)`), reflection/DI containers, framework entrypoints (route files, migrations, CLI commands, test setup), config-driven plugin loading, and anything that is part of a published **public API**. Treat these as live until proven otherwise. Verify every removal with the build **and** tests before moving to the next one.
|
|
18
|
+
|
|
19
|
+
## Instructions
|
|
20
|
+
|
|
21
|
+
1. **Locate the entry points.** Identify where execution actually begins — `main`/`exports`/`bin` in `package.json`, `next.config`/route conventions, `if __name__ == "__main__"`, CLI definitions, test runners. Everything reachable from these is live; the dead set is the complement.
|
|
22
|
+
2. **Detect the right tooling — do not guess.** Match the ecosystem and prefer purpose-built tools over hand-rolled grep:
|
|
23
|
+
- TS/JS: `knip` (exports, files, and deps in one pass), `ts-prune`, `depcheck`, or `eslint`'s `no-unused-vars`.
|
|
24
|
+
- Python: `vulture`, `deptry`, `ruff check --select F401`.
|
|
25
|
+
- Go: `staticcheck`/`go vet`, `golangci-lint`. Rust: `cargo +nightly udeps`, dead-code warnings.
|
|
26
|
+
Read the config these tools already respect; honor existing ignore lists.
|
|
27
|
+
3. **Build the candidate list, then triage.** For each candidate (unreferenced export, unreached file, unused dependency), grep the **whole repo** — including configs, test setup, CI scripts, dynamic-import strings, and docs — before trusting the tool. Drop anything matched by the dynamic-usage patterns in the warning above, and anything re-exported from a package's public entry point.
|
|
28
|
+
4. **Remove one thing at a time.** Delete a single export/file/dependency, then run the project's build and test commands. Never batch deletions across the verification step — a green-then-red transition must point at exactly one change.
|
|
29
|
+
5. **Verify after each removal.** Run the real commands (`npm run build && npm test`, `pytest`, `go build ./... && go test ./...`). A clean build and passing suite is the proof. If anything breaks, revert that single change and mark the candidate as a live-via-dynamic-usage false positive.
|
|
30
|
+
6. **Report and flag gaps.** List what was removed (with the verifying command output), what was kept and why, and any candidates that need human judgment — public-API surface, generated code, or dynamic usage your search could not rule out.
|
|
31
|
+
|
|
32
|
+
> [!NOTE]
|
|
33
|
+
> Run the cleanup on a branch and keep each removal as its own commit. If a deletion only surfaces a failure in CI or a downstream consumer, a granular history makes the exact revert trivial.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
Confirming an export is truly unused before deleting it — `formatLegacyDate` in `src/utils/date.ts`:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 1. Tool flags it as an unreferenced export
|
|
41
|
+
$ npx knip --include exports
|
|
42
|
+
src/utils/date.ts:42:14 - 'formatLegacyDate' is unused (exports)
|
|
43
|
+
|
|
44
|
+
# 2. Verify by hand across the WHOLE repo, including dynamic strings and configs
|
|
45
|
+
$ grep -rIn "formatLegacyDate" --include='*.ts' --include='*.tsx' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' .
|
|
46
|
+
src/utils/date.ts:42:export function formatLegacyDate(d: Date): string {
|
|
47
|
+
# Only the definition — no importers, no string references, no re-export in index.ts
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
One self-reference and nothing else: safe to delete. Remove it, then prove the codebase still compiles and passes:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
$ npm run build && npm test
|
|
54
|
+
✓ build succeeded
|
|
55
|
+
✓ 214 passed
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Contrast with a false positive — an export `knip` also flags, but grep finds reached dynamically:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
$ grep -rIn "handlers/" --include='*.ts' .
|
|
62
|
+
src/router.ts:18: const mod = await import(`./handlers/${route.name}`);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The static tool can't follow the template-literal import, so `handlers/checkout.ts` only *looks* orphaned. Keep it, document the dynamic load, and report it as a manual-review case rather than deleting it.
|