@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 +9 -0
- package/package.json +1 -1
- package/skills/_template/SKILL.md +8 -0
- package/skills/api-contract-review/SKILL.md +67 -0
- package/skills/code-review/SKILL.md +25 -4
- package/skills/codebase-explainer/SKILL.md +13 -6
- package/skills/conventional-commits/SKILL.md +10 -3
- package/skills/diagnose/SKILL.md +31 -0
- package/skills/dotnet-onion-api/SKILL.md +40 -3
- package/skills/e2e-verify/SKILL.md +88 -0
- package/skills/grill-with-docs/SKILL.md +19 -3
- package/skills/handoff/SKILL.md +11 -1
- package/skills/improve-codebase-architecture/SKILL.md +11 -1
- package/skills/migration-safety/SKILL.md +59 -0
- package/skills/nextjs-app-router/SKILL.md +36 -3
- package/skills/plan-and-build/SKILL.md +11 -1
- package/skills/pr-review/SKILL.md +25 -1
- package/skills/safe-refactor/SKILL.md +62 -0
- package/skills/security-review/SKILL.md +65 -0
- package/skills/ship-it/SKILL.md +15 -5
- package/skills/sql-review/SKILL.md +20 -0
- package/skills/task-executor/SKILL.md +15 -2
- package/skills/tauri-2-app/SKILL.md +28 -4
- package/skills/think-like-fable/SKILL.md +101 -0
- package/skills/upgrade-deps/SKILL.md +60 -0
- package/skills/write-a-skill/SKILL.md +29 -0
- package/skills/write-tests/SKILL.md +68 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-review
|
|
3
|
+
description: Attacker's-eye security review of a diff, branch, or module — walks a fixed vulnerability catalog (missing authz on new endpoints, injection, secrets in code/logs, trusting client-sent identity, SSRF, path traversal, insecure deserialization, mass assignment, broken crypto, unsafe redirects, dependency CVEs) where every finding must name a concrete attack path (attacker does X → gains Y) or be demoted to hardening advice. Never claims "secure", only "nothing found in the classes checked". Use this skill whenever the user says "security review", "is this secure", "check for vulnerabilities", "audit the auth", "threat model this", "pentest mindset", "check for injection", or "/security-review" — even if they don't name the skill. Distinct from code-review/pr-review (security is one lens there); this is the dedicated deep pass.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Security Review
|
|
7
|
+
|
|
8
|
+
A defensive security audit of code you're shipping, run with an attacker's questions: what does this trust that it shouldn't, and what can I reach that I shouldn't. The output discipline is what makes it useful — every finding carries an attack path, every "pass" carries the evidence that was checked, and the report never claims more than it verified. "No vulnerabilities" is not a claim this skill can make; "none found in these classes, with these checks, and here's what wasn't checked" is.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- The user says "security review", "is this secure", "check for vulnerabilities", "audit the auth", "threat model this", "check for injection", "/security-review".
|
|
13
|
+
- New endpoints, auth changes, file handling, payment paths, or user-generated-content rendering are about to ship.
|
|
14
|
+
- `ship-it` or `code-review` surfaces a security concern that needs a dedicated pass.
|
|
15
|
+
|
|
16
|
+
Do **not** auto-trigger on every diff — `code-review` carries a security lens for routine work; this skill is the deep pass when the change touches trust boundaries or the user asks. This skill reviews and reports; it never writes exploit tooling, and it never edits code unprompted.
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
1. **Fix the scope first.** A diff, a branch, a module, or an endpoint list — force the user to name it if ambiguous (one `AskUserQuestion`). Then map the trust boundaries inside that scope: every place data crosses from less-trusted to more-trusted (HTTP input, file upload, queue message, webhook, env/config, DB values rendered back out). Effort follows boundaries — a 500-line diff with one new endpoint gets most scrutiny on the endpoint.
|
|
21
|
+
2. **Walk the catalog against the scope.** For each class, the check is named — run it, don't vibe it:
|
|
22
|
+
- **Missing authn/authz** — for every new/changed route or handler, locate the auth check (middleware registration, guard attribute, explicit session call) and cite `file:line`. Then check *object-level* authz: does the handler verify the caller may touch **this** record, or only that they're logged in? Absence of either is a finding. Compare against how sibling endpoints in the repo do it.
|
|
23
|
+
- **Trusting client-sent identity** — grep handlers in scope for user/account/tenant IDs read from body, query, or headers and used in queries or writes. The ID must come from the session/token.
|
|
24
|
+
- **Injection** — SQL/query built by string concatenation with external input (must be parameterized); shell commands from input; path traversal (user input joined into filesystem paths without normalization + prefix check); XSS (external input rendered without the framework's escaping — grep for `dangerouslySetInnerHTML`, `innerHTML`, `v-html`, `Html.Raw`, raw template filters).
|
|
25
|
+
- **Secrets** — grep the scope for key/token/password-shaped literals and connection strings; check that secrets aren't logged (grep log calls near auth/config code) or committed in config. A finding is the **value** in the repo, not the reference: `process.env.STRIPE_KEY` / a secret-manager call is the correct pattern, never a finding; `sk_live_4eC39...` in code or a committed `.env` is. If a real secret is already committed, rotation is the fix — deleting the line doesn't un-leak it; git history keeps it.
|
|
26
|
+
- **SSRF & redirects** — any outbound request whose URL contains external input; any redirect target taken from a parameter without an allowlist.
|
|
27
|
+
- **Insecure deserialization / mass assignment** — deserializing external input into types with dangerous side effects; binding request bodies directly to DB entities so a caller can set `isAdmin`/`role`/`price` (check for an explicit DTO/allowlist between input and model).
|
|
28
|
+
- **Crypto misuse** — hand-rolled hashing/encryption, fast hashes (MD5/SHA-x) for passwords instead of bcrypt/argon2/scrypt, `Math.random()`-class RNG for tokens, comparing secrets with `==` instead of constant-time compare.
|
|
29
|
+
- **Dependency CVEs** — only via an actual tool run (`npm audit`, `dotnet list package --vulnerable`, `pip-audit`, `cargo audit`); quote the output. If no tool ran, the report says `dependencies: not checked` — never "dependencies look fine".
|
|
30
|
+
3. **Evidence-gate every finding.** A finding must state, in one sentence, the attack path: *who* (unauthenticated user / any logged-in user / tenant B / insider) does *what* → gains *what*. No constructible path → demote to **hardening** (still reported, clearly separated). Severity from the path itself: **critical** = unauthenticated or cross-tenant data access/mutation, RCE, secret exposure; **high** = authenticated privilege escalation or injection with real reachable input; **medium** = requires unusual preconditions; **hardening** = defense-in-depth with no current path.
|
|
31
|
+
- ❌ "The `userId` parameter could be dangerous." — no actor, no gain, not a finding.
|
|
32
|
+
- ✅ "`GET /api/invoices/{id}` checks login but not ownership (`InvoiceController.cs:41` — no tenant filter in the query): any logged-in user who increments `id` reads other customers' invoices. Critical (IDOR)."
|
|
33
|
+
4. **Verify before reporting.** For each finding, re-derive it: open the file, trace the input to the sink, confirm no sanitizer/guard sits between them (search the call chain, not just the hunk — the guard may live in middleware or a base class). A pattern-matched finding you didn't trace is labeled **unconfirmed** in the report, never stated in the same register as a traced one. Zero findings is a valid outcome and must be reported without padding.
|
|
34
|
+
5. **Report.** Findings ranked by severity, each with `file:line`, attack path, and a recommended fix direction (not applied). Then the coverage statement: which catalog classes were checked with what evidence, and which were **not** checked (e.g. "infra/deployment config out of scope, dependencies not audited — no lockfile in scope"). End by asking per-finding whether to draft the fix — never edit unprompted.
|
|
35
|
+
|
|
36
|
+
## Examples
|
|
37
|
+
|
|
38
|
+
### Example 1: new endpoint pass
|
|
39
|
+
|
|
40
|
+
**User:** "Security review the payments branch before I merge."
|
|
41
|
+
|
|
42
|
+
**Claude:** Scopes to the branch diff, maps boundaries (2 new endpoints, 1 webhook), finds the webhook skips signature verification (traced: raw body straight to the handler, `webhooks.ts:23`) — critical, forged payment confirmations; finds sibling endpoints use `requireSession` but the new refund route registers outside the auth router — high; runs `npm audit` (quotes: 0 high). Coverage note: XSS class N/A (no rendering in scope), crypto N/A.
|
|
43
|
+
|
|
44
|
+
### Example 2: honest zero
|
|
45
|
+
|
|
46
|
+
**User:** "Check this date-formatting utility PR for vulnerabilities."
|
|
47
|
+
|
|
48
|
+
**Claude:** Walks the catalog; no external input reaches a sink (verified: all call sites pass server-generated dates). Report: zero findings, one hardening note (no input-length guard), explicit "not checked: dependencies (no manifest change)". No invented findings to look thorough.
|
|
49
|
+
|
|
50
|
+
## Anti-patterns
|
|
51
|
+
|
|
52
|
+
- ❌ Findings without an attack path — severity theater. If you can't say who gains what, it's hardening advice.
|
|
53
|
+
- ❌ Claiming "this code is secure" — the only honest claim is "nothing found in the classes checked", plus the unchecked list.
|
|
54
|
+
- ❌ Reporting a pattern-match ("string concatenation near SQL") without tracing whether external input actually reaches it — half of these have a parameterizer or validator one frame up.
|
|
55
|
+
- ❌ Marking everything critical. The severity ladder is defined by the attack path; a finding needing admin access plus a misconfigured proxy is not critical.
|
|
56
|
+
- ❌ "Fixing" a committed secret by deleting the line — history retains it; the finding is "rotate this credential".
|
|
57
|
+
- ❌ Skipping object-level authz because authentication exists — IDOR is the most common real-world miss, and it lives exactly in that gap.
|
|
58
|
+
- ❌ Editing code or adding "quick fixes" unprompted — report, ask, then fix.
|
|
59
|
+
- ✅ Scope → boundaries → named checks with citations → attack-path-gated findings → coverage statement including what was NOT checked.
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
|
|
63
|
+
- This skill is defensive: it reviews code the user owns or is authorized to audit. It doesn't produce working exploits — a one-sentence attack path is the proof standard, a PoC payload is not required and not offered beyond what's needed to demonstrate the flaw to the developer.
|
|
64
|
+
- Language/framework specifics come from the repo: find how THIS codebase does auth, validation, and escaping (grep for the middleware/guards), then hunt for the places in scope that deviate from it — deviation from the local safe pattern is the highest-yield query.
|
|
65
|
+
- Apply `think-like-fable`: effort at the boundaries (§3), every finding re-derived not recognized (§4), unconfirmed labeled out loud (§5), and attack your own report — the finding you're most confident in is the one to re-trace.
|
package/skills/ship-it/SKILL.md
CHANGED
|
@@ -20,7 +20,8 @@ Do **not** auto-trigger when the user is asking about diff-level code quality, D
|
|
|
20
20
|
|
|
21
21
|
- **Recommend, don't refactor.** This is an audit. Never edit code unprompted. After the report, ask per-blocker whether the user wants a fix drafted.
|
|
22
22
|
- **Evidence is mandatory.** Every PASS must cite `file:line`. "I checked, it looks fine" is not a PASS — that's a GAP labelled `couldn't verify`.
|
|
23
|
-
- **
|
|
23
|
+
- **Name the probe.** Every PASS also names the exact check that produced its evidence — the grep pattern + path, the file you read, or the command you ran. If you didn't run a probe for an item, it's GAP labelled `not checked` — never PASS. A result you didn't observe doesn't exist.
|
|
24
|
+
- **N/A needs a reason grounded in the scope.** The justification must derive from an observed fact about *this* scope, with the probe that established it (e.g. *"no files under `migrations/` in the diff (`git diff --stat`) → migrations N/A"*) — never a guess from the project type. Don't fabricate gaps for categories that don't apply.
|
|
24
25
|
- **Stay in your lane.** Don't re-do `code-review`'s work. If the user asks about DRY / dead code / test coverage, defer.
|
|
25
26
|
|
|
26
27
|
## Workflow
|
|
@@ -40,6 +41,8 @@ Echo the scope back in one line before starting Phase 2 (*"Auditing branch `feat
|
|
|
40
41
|
|
|
41
42
|
For each category: state the criterion in one line, search the codebase for evidence, mark PASS / GAP / N/A. Use `Grep` and `Read` aggressively; spawn an `Explore` sub-agent for any category where the search would take more than 3 queries.
|
|
42
43
|
|
|
44
|
+
Record each probe as you run it — the report cites them. A probe is a specific `Grep` pattern + path, a `Read` of a named file, or a command with its observed output. A sub-agent's result counts as a probe only if the sub-agent names its own probes and citations; "the agent said it's fine" is not evidence. Where a check depends on the user (dashboards, runbooks, rollout plans), record their answer as the probe (*"user confirmed: alert added to Grafana billing board"*) — an unanswered question stays GAP.
|
|
45
|
+
|
|
43
46
|
#### 1. Logging
|
|
44
47
|
|
|
45
48
|
**What good looks like:** Structured logs (JSON or key=value), correlation / request IDs propagated, levels used correctly (`error` ≠ `info`), no secrets / tokens / PII in log output, errors logged with stack + context, not just the message.
|
|
@@ -118,12 +121,17 @@ Group findings into four buckets. Order matters — blocking first.
|
|
|
118
121
|
- **<category>:** <one-line problem> — `<file:line>`
|
|
119
122
|
|
|
120
123
|
## N/A
|
|
121
|
-
- **<category>:** <one-line reason>
|
|
124
|
+
- **<category>:** <one-line reason grounded in the scope> (probe: `<what established it>`)
|
|
122
125
|
|
|
123
126
|
## Passing
|
|
124
|
-
- **<category>:** <one-line evidence> — `<file:line>`
|
|
127
|
+
- **<category>:** <one-line evidence> — `<file:line>` (probe: `<grep pattern / file read / command>`)
|
|
125
128
|
```
|
|
126
129
|
|
|
130
|
+
Same PASS, written badly and well:
|
|
131
|
+
|
|
132
|
+
- ❌ `**Logging:** structured logging in place — src/billing/` — no line, no probe; unverifiable, could have been written without looking.
|
|
133
|
+
- ✅ `**Logging:** new invoice paths log via structured logger with request ID — src/billing/invoice.ts:31 (probe: grep -n "logger\." src/billing/ → 6 call sites, all pass ctx.reqId)` — anyone can rerun the probe and land on the same line.
|
|
134
|
+
|
|
127
135
|
**Blocking = any one of:**
|
|
128
136
|
- Secrets in code / logs / committed config.
|
|
129
137
|
- Missing authz on a new endpoint or screen.
|
|
@@ -145,8 +153,8 @@ After the report, ask: *"Want me to draft fixes for the blocking items, or stop
|
|
|
145
153
|
|
|
146
154
|
**Claude:**
|
|
147
155
|
1. Echoes scope: *"Auditing `feat/billing-v2` against `main` — 14 files changed."*
|
|
148
|
-
2. Walks the 10 categories, citing `file:line` per finding.
|
|
149
|
-
3. Reports: 2 blocking (missing authz on `POST /api/v2/invoices
|
|
156
|
+
2. Walks the 10 categories, citing `file:line` per finding and the probe that produced it.
|
|
157
|
+
3. Reports: 2 blocking (missing authz on `POST /api/v2/invoices` — `no tenant predicate in routes/invoices.ts:24-51, read top-to-bottom`; no rollback for the `currency_code NOT NULL` migration), 4 should-fix, 1 N/A (local-first storage — *"no client-side store in scope: `grep -rl 'localStorage\|indexedDB' src/billing/` → 0 hits, server-only module"*), 3 passing with probes named.
|
|
150
158
|
4. Asks whether to draft fixes for the blockers.
|
|
151
159
|
|
|
152
160
|
### Example 2: Module-scoped audit
|
|
@@ -167,6 +175,8 @@ After the report, ask: *"Want me to draft fixes for the blocking items, or stop
|
|
|
167
175
|
## Anti-patterns
|
|
168
176
|
|
|
169
177
|
- ❌ Marking a category PASS without a `file:line` citation. "Looks fine" is a GAP labelled `couldn't verify`.
|
|
178
|
+
- ❌ PASS on vibes — a PASS with no named probe (the grep / read / command that produced the evidence) is a GAP labelled `not checked`.
|
|
179
|
+
- ❌ N/A from a guess about the project type. Derive it from the scope and name the probe: *"no schema files in this diff (`git diff --stat`) → migrations N/A"*.
|
|
170
180
|
- ❌ Inventing GAPs in N/A categories. A server-only service genuinely has no local-first storage layer — say so and move on.
|
|
171
181
|
- ❌ Reviewing diff quality (DRY, dead code, missing tests) under the ship-it banner. Defer to `code-review`.
|
|
172
182
|
- ❌ Editing code mid-audit. The report comes first, then the user picks what to fix.
|
|
@@ -46,6 +46,20 @@ SQL changes are particularly sensitive because they often run against production
|
|
|
46
46
|
|
|
47
47
|
Lead each finding with the *why*. "This swallows the original error and surfaces a misleading permission denial" beats "add `;THROW;`".
|
|
48
48
|
|
|
49
|
+
## Pattern hit ≠ finding
|
|
50
|
+
|
|
51
|
+
The 17 checks are pattern matches. A ripgrep hit is a **candidate** — before reporting it, `Read` the whole procedure/batch it sits in; severity depends on context the pattern can't see. Concrete demotions:
|
|
52
|
+
|
|
53
|
+
- `WITH (NOLOCK)` hit, but the proc is a read-only reporting proc with no `INSERT`/`UPDATE`/`DELETE` → **WARN** at most, not BLOCKER (check #13 blocks only when the same proc writes the tables it dirty-reads).
|
|
54
|
+
- `DECLARE @retry` with no `WHILE @retry` in sight → check for a `GOTO`-label retry loop consuming it before flagging; only report when nothing reads the variable.
|
|
55
|
+
- New `CREATE TABLE` with no index, but it's a static lookup/config table seeded with a handful of rows in the same diff → **WARN** with a one-line reason, not BLOCKER (the deadlock incident needs growth under concurrent writes).
|
|
56
|
+
|
|
57
|
+
Every reported finding must:
|
|
58
|
+
1. **Quote the offending SQL verbatim** — the exact line(s) from the file, not a paraphrase. Severity turns on exact tokens.
|
|
59
|
+
2. For `BLOCKER` / `WARN`: state the concrete production incident in one sentence (*this state → this outcome*, e.g. "first deadlock under load → SP silently gives up, rows never written"). If you can't write that sentence after reading the full proc, demote one level.
|
|
60
|
+
|
|
61
|
+
Zero findings is a valid outcome — a clean diff gets a clean report. Never stretch INFO items into WARNs to fill sections; thoroughness is the 17 checks you ran, which the report shows.
|
|
62
|
+
|
|
49
63
|
## What to check
|
|
50
64
|
|
|
51
65
|
Use ripgrep for detection. The patterns below are starting points — adapt to the actual diff text.
|
|
@@ -148,6 +162,7 @@ Use ripgrep for detection. The patterns below are starting points — adapt to t
|
|
|
148
162
|
## Blockers (<N>)
|
|
149
163
|
|
|
150
164
|
### B1. <short title> — `path/to/file.sql:<line>`
|
|
165
|
+
**Evidence:** `<offending SQL fragment, quoted verbatim>`
|
|
151
166
|
**Why:** <root cause / production consequence — one line>
|
|
152
167
|
**Fix:** <concrete recommendation — one line>
|
|
153
168
|
|
|
@@ -156,6 +171,7 @@ Use ripgrep for detection. The patterns below are starting points — adapt to t
|
|
|
156
171
|
## Warnings (<N>)
|
|
157
172
|
|
|
158
173
|
### W1. <short title> — `path/to/file.sql:<line>`
|
|
174
|
+
**Evidence:** `<offending SQL fragment, quoted verbatim>`
|
|
159
175
|
**Why:** ...
|
|
160
176
|
**Fix:** ...
|
|
161
177
|
|
|
@@ -220,6 +236,10 @@ End with the offer. Wait for the user's choice.
|
|
|
220
236
|
- ❌ Suggesting autofixes for `BLOCKER` items without asking. SQL deploys to production; user confirmation gates the change.
|
|
221
237
|
- ❌ Listing a `nit` when there's a `BLOCKER` next to it. Lead with severity.
|
|
222
238
|
- ❌ Hand-wavy findings without `file:line`.
|
|
239
|
+
- ❌ Reporting a raw ripgrep hit without reading the surrounding procedure. A pattern match is a candidate; the proc's full context sets the severity (see [Pattern hit ≠ finding](#pattern-hit--finding)).
|
|
240
|
+
- ❌ Paraphrasing the offending SQL instead of quoting it verbatim. `WITH (NOLOCK)` vs `READPAST`, `@retry` vs `@retryCount` — the exact token is the finding.
|
|
241
|
+
- ❌ A `BLOCKER` with no one-sentence production-incident scenario. Can't name the incident? It's a `WARN`.
|
|
242
|
+
- ❌ Padding a clean diff with stretched findings. Zero findings is a valid report.
|
|
223
243
|
- ❌ Inventing antipatterns not in [What to check](#what-to-check). This is a fixed catalog — extending it is a `write-a-skill` change, not a per-run improvisation.
|
|
224
244
|
- ❌ Running on non-SQL files. The skill is `.sql`-scoped; mixed diffs route to `code-review` for the non-SQL parts.
|
|
225
245
|
- ✅ Diff-scoped scan for modified files, full scan for new files, findings categorized + cited + offered as fixes.
|
|
@@ -125,11 +125,21 @@ If the user pushes back, revise and re-present. Do not partial-implement against
|
|
|
125
125
|
|
|
126
126
|
Walk the plan one step at a time. For each step:
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
0. **Re-anchor.** Re-read the `Goal` section and this step's validation criterion from `Plan` before touching anything. Thirty seconds of re-reading is what keeps turn 20 aligned with turn 1 — drift is silent and this is the only cheap defense.
|
|
129
|
+
1. **Make the smallest change that completes the step.** No drive-by refactors, no "while I'm here" fixes, no batched edits across multiple steps. Done means the step's criterion, nothing more — improvements you notice (missing validation, refactor opportunity, extra config) go into `Risks` as findings, not into the diff.
|
|
129
130
|
2. **Validate immediately.** Run the test, build, type-check, lint, curl the endpoint, or load the page — whichever signal is appropriate for that step. If there's no automated signal at all, say so explicitly in `Progress`; don't pretend there is one.
|
|
130
|
-
3. **Tick the checkbox** with a
|
|
131
|
+
3. **Tick the checkbox** with evidence that is an **observed artifact from this turn** — a pasted output line, an exit code, a status code. A claim is not evidence.
|
|
132
|
+
- ❌ `tests pass` — an assertion; nothing was observed.
|
|
133
|
+
- ✅ `dotnet test → Passed! 42 passed, 0 failed, 0 skipped` — pasted from output you just saw.
|
|
134
|
+
If you didn't run it this turn, you can't tick it.
|
|
131
135
|
4. **Re-emit the full per-turn output** before moving to the next step.
|
|
132
136
|
|
|
137
|
+
When a command fails:
|
|
138
|
+
|
|
139
|
+
- Read the **full** error output — the load-bearing detail is usually in the last lines you'd skim past.
|
|
140
|
+
- Change exactly one thing based on what the error says, then retry once.
|
|
141
|
+
- Two failures on the same step = stop. Add the verbatim error to `Risks` and surface to the user. Never retry verbatim, and never continue as if the command succeeded — a result you didn't observe is not a result.
|
|
142
|
+
|
|
133
143
|
When a validation fails:
|
|
134
144
|
|
|
135
145
|
- Do not move on.
|
|
@@ -160,6 +170,9 @@ When every checkbox is ticked:
|
|
|
160
170
|
- ❌ Convening the inspection council for a 3-file task. Ceremony for its own sake. Inline reads are the default — escalate only when the inspection set genuinely spans multiple layers.
|
|
161
171
|
- ❌ Spawning the inspection sub-agents serially instead of in parallel — one message, N `Agent` calls. Serial defeats the context-protection rationale.
|
|
162
172
|
- ❌ Letting a sub-agent slice overlap with another's. If two slices would re-read the same files, merge them first.
|
|
173
|
+
- ❌ Ticking a checkbox with claimed evidence (`tests pass`) when the command wasn't run this turn. Evidence is pasted observation, not memory or assertion.
|
|
174
|
+
- ❌ Retrying a failed command verbatim, or proceeding as if it succeeded. Read the error, change one thing, retry once; twice failed = `Risks` + stop.
|
|
175
|
+
- ❌ Gold-plating a step: extra config options, defensive layers, speculative hooks the plan didn't call for. Findings go to `Risks`; the diff stays the size of the step.
|
|
163
176
|
- ✅ Same six headers every turn, one step at a time, one validation per step, assumptions tracked explicitly until confirmed or killed.
|
|
164
177
|
|
|
165
178
|
## Examples
|
|
@@ -43,6 +43,8 @@ The user does **not** want hard-coded Cargo / npm versions baked into the skill.
|
|
|
43
43
|
3. Pin the Rust edition to `2021` unless the user asks otherwise.
|
|
44
44
|
4. Quote the resolved versions back to the user before generating, so they can object.
|
|
45
45
|
5. Default to **npm** unless `pnpm` or `bun` is present and the user prefers it.
|
|
46
|
+
6. Concrete resolution commands when context7 is unavailable: `npm view @tauri-apps/api version`, `cargo search <crate> --limit 1`, or WebFetch `https://crates.io/api/v1/crates/<crate>` (`max_stable_version`). Never write a version you did not just resolve this session — no versions from memory, no invented numbers.
|
|
47
|
+
7. **Tauri 1.x is poison.** Training data is full of v1 patterns that look plausible and fail on v2. Never emit: `import { invoke } from '@tauri-apps/api/tauri'` (the v2 path is `@tauri-apps/api/core`), a `tauri.allowlist` or top-level `tauri` key in `tauri.conf.json` (v2 uses `app` / `bundle` / `plugins` + `capabilities/*.json`), or v1 plugin names/APIs. If you are not certain a conf key, capability permission string, or plugin API exists in Tauri 2, verify it against the installed schema (`node_modules/@tauri-apps/cli/config.schema.json`; valid permission strings appear in `src-tauri/gen/schemas/` after the first build) or the plugin's docs **before** writing code that depends on it. Capability `permissions` entries use the short plugin name (`dialog:allow-open`, `fs:allow-read-file`) — never a `tauri-plugin-` prefix. Note that `cargo check` compiles `tauri-build`, which validates `tauri.conf.json` and `capabilities/*.json` — a schema or unknown-permission error there is a JSON problem; fix the conf/capability file against the schema, don't edit Rust code to appease it.
|
|
46
48
|
|
|
47
49
|
### Step 2 — Gather inputs (ask once, in one batch)
|
|
48
50
|
|
|
@@ -71,14 +73,17 @@ Use the **templates in [`references/templates/`](references/templates/)** as the
|
|
|
71
73
|
- Create directories before files. On Windows shell use PowerShell `New-Item -ItemType Directory -Force`.
|
|
72
74
|
- Do **not** run `create-tauri-app` to bootstrap — write the files directly from templates so the layout matches the conventions in [`references/folder-layout.md`](references/folder-layout.md). Use `npm install` after `package.json` is written, then `cargo fetch` from `src-tauri/` to seed the Cargo cache.
|
|
73
75
|
- For icons, run `npx @tauri-apps/cli icon <path-to-source.png>` once a source image exists, or generate a 1024×1024 placeholder with `sharp` if the user wants. Do **not** commit a placeholder square as the final icon — surface it as a TODO.
|
|
76
|
+
- If a generator IS run (`create-tauri-app` at the user's insistence, `npx @tauri-apps/cli icon`, `tauri signer generate`) and its output differs from this skill's layout: **Tauri wins on file locations it mandates** (`src-tauri/` shape, `capabilities/`, `gen/`, icon paths), **this skill wins on everything Tauri doesn't mandate** (the `commands/`/`state/`/`storage/`/`platform/` module split, frontend hooks layout). Reconcile deliberately and list every deviation in your report — never force the skill layout over a framework requirement, never silently abandon the skill's patterns.
|
|
74
77
|
|
|
75
78
|
### Step 4 — Verify and report
|
|
76
79
|
|
|
77
80
|
- Run `npm install` (or chosen PM).
|
|
78
|
-
- Run `cd src-tauri && cargo build` — must exit 0. (Don't run `tauri dev` in CI — it opens a window.)
|
|
81
|
+
- Run `cd src-tauri && cargo build` — must exit 0. (Don't run `tauri dev` in CI — it opens a window.) If a full `cargo build` is prohibitively slow in this environment, `cargo check` is the minimum acceptable bar — state which one you ran.
|
|
79
82
|
- Run `cd src-tauri && cargo test` — must exit 0 if any tests were generated.
|
|
80
|
-
- Run `npm run build` (frontend) — must exit 0.
|
|
83
|
+
- Run `npm run build` (frontend) — must exit 0. `cargo check` + `npm run build` together are the floor; a full `tauri build` is optional (slow).
|
|
81
84
|
- Optionally run `npm run tauri build -- --debug` if the user wants a debug bundle; skip in CI by default since it's slow.
|
|
85
|
+
- **A scaffold that hasn't compiled is not delivered.** Paste the actual proof lines in your report (cargo's `Finished` profile line, `test result: ok`, Vite's `✓ built in ...`). 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.
|
|
86
|
+
- **CLI failure protocol** (applies to `npm install`, `cargo build`/`check`/`test`, `npm run build`): read the full error output — for cargo, fix the **first** error; later ones are usually cascade. 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 a broken base, and do not re-run the identical command hoping for a different result.
|
|
82
87
|
- Reply with a short summary: project path, versions chosen, plugins wired, bundle identifier, next steps (e.g. "fill in the macOS `Info.plist` usage descriptions for any permissions you'll request", "generate updater keys with `npx tauri signer generate`", "run `npm run tauri dev`").
|
|
83
88
|
|
|
84
89
|
## Project layout (canonical)
|
|
@@ -236,6 +241,9 @@ Every one of these is forbidden in generated code. Rationale for each is in [`re
|
|
|
236
241
|
3. `src-tauri/Cargo.toml` (with target-specific deps + release profile), `src-tauri/build.rs`, `src-tauri/tauri.conf.json`, `src-tauri/Info.plist`, `src-tauri/entitlements.plist`, `src-tauri/capabilities/default.json`.
|
|
237
242
|
4. `src-tauri/icons/` — placeholder 1024×1024 PNG **only** if the user hasn't supplied one. Surface as TODO; tell them to run `npx @tauri-apps/cli icon icons/icon.png`.
|
|
238
243
|
5. `src-tauri/src/main.rs`, `src-tauri/src/lib.rs`, `src-tauri/src/error/mod.rs`, `src-tauri/src/state/mod.rs`, `src-tauri/src/storage/mod.rs`, `src-tauri/src/commands/mod.rs` + `src-tauri/src/commands/system.rs`, `src-tauri/src/platform/{mod,traits,macos,windows,linux,wrappers}.rs`, `src-tauri/src/settings/{mod,defaults,storage,commands}.rs`.
|
|
244
|
+
|
|
245
|
+
**Checkpoint:** run `npm install` then a first `cd src-tauri && cargo check` here, before optional modules — errors localize to the core tree, and this check runs `tauri-build`, which validates `tauri.conf.json` + `capabilities/*.json` and generates `src-tauri/gen/schemas/` (the authority for valid permission strings). Fix any conf/capability error now, per the Step-4 failure protocol, before writing more capability entries.
|
|
246
|
+
|
|
239
247
|
6. Optional: `src-tauri/src/encryption/mod.rs`, `src-tauri/src/tray.rs`, `src-tauri/src/commands/<more>.rs` based on user answers.
|
|
240
248
|
7. `src-tauri/tests/common/mod.rs` + at least one integration test file (e.g. `system_test.rs`) so CI has something real to run.
|
|
241
249
|
4. `npm install`.
|
|
@@ -261,7 +269,7 @@ For command `{{command}}` (snake_case) in module `commands/{{domain}}.rs`:
|
|
|
261
269
|
- Export the hook. Do **not** call `invoke()` inline in a component.
|
|
262
270
|
4. **Test**: add an integration test in `src-tauri/tests/{{domain}}_test.rs` that exercises the command's underlying function (the `#[tauri::command]` itself is hard to call without a full Tauri context — test the inner function).
|
|
263
271
|
|
|
264
|
-
After generating: `cd src-tauri && cargo build && cargo test` then `npm run build` from the project root.
|
|
272
|
+
After generating: `cd src-tauri && cargo build && cargo test` then `npm run build` from the project root. Apply the Step-4 proof-and-failure protocol — paste the green lines; the same step failing twice = stop and surface the verbatim error.
|
|
265
273
|
|
|
266
274
|
### Mode 3 — `add-module`
|
|
267
275
|
|
|
@@ -275,7 +283,7 @@ For module `{{module}}` (snake_case):
|
|
|
275
283
|
6. Add a `#[cfg(test)]` `mod tests { ... }` block at the bottom of `mod.rs` covering pure logic (no Tauri context required).
|
|
276
284
|
7. Add a `src-tauri/tests/{{module}}_test.rs` integration test if the module has cross-cutting behavior.
|
|
277
285
|
|
|
278
|
-
After generating: `cd src-tauri && cargo build && cargo test
|
|
286
|
+
After generating: `cd src-tauri && cargo build && cargo test` — Step-4 proof-and-failure protocol applies.
|
|
279
287
|
|
|
280
288
|
## NuGet... wait, this is Tauri. Cargo + npm packages (resolve latest stable at scaffold time)
|
|
281
289
|
|
|
@@ -320,6 +328,22 @@ Look these up at scaffold time — do not hand-paste versions:
|
|
|
320
328
|
|
|
321
329
|
## Verification checklist before reporting "done"
|
|
322
330
|
|
|
331
|
+
Run this as a **mechanical pass over the generated tree** — grep, don't recall. The Eliminate list is easy to hold at file 1 and forgotten by file 30. Start with this grep block; every command must return nothing:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
grep -rn "cfg!(target_os" src-tauri/src --include='*.rs' | grep -v "src/platform/" # platform checks outside platform/
|
|
335
|
+
grep -rn "@tauri-apps/api/tauri" src/ # v1 import path (v2 is /core)
|
|
336
|
+
grep -n "allowlist\|systemTray" src-tauri/tauri.conf.json # v1 config schema leaking in (v2: capabilities/, app.trayIcon)
|
|
337
|
+
grep -rn "tauri::api::" src-tauri/src --include='*.rs' # v1 Rust API paths (v2 moved these to plugins)
|
|
338
|
+
grep -rnE "pub (api_key|token|secret)\w*: String" src-tauri/src/ # plaintext secret fields (must be EncryptedApiKey)
|
|
339
|
+
grep -rn "localStorage.setItem\|sessionStorage.setItem" src/ # tokens/secrets in web storage
|
|
340
|
+
grep -n "\"devtools\": true" src-tauri/tauri.conf.json # devtools enabled in release config
|
|
341
|
+
grep -rn "std::fs::" src-tauri/src/commands/ # raw fs in command bodies
|
|
342
|
+
find src-tauri/src -name "*.backup" -o -name "*.orig" -o -name "*.temp" # WIP artefacts
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
A hit means fix it and re-run the grep — never rationalize it away. Then the full checklist:
|
|
346
|
+
|
|
323
347
|
- [ ] `npm install` succeeds.
|
|
324
348
|
- [ ] `cd src-tauri && cargo build` exits 0.
|
|
325
349
|
- [ ] `cd src-tauri && cargo test` exits 0 (if tests were generated).
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: think-like-fable
|
|
3
|
+
description: An operating manual for rigorous reasoning — how to read the real request beneath the words, decompose into independently-checkable pieces, spend effort where the risk lives, verify by re-derivation instead of plausibility, label known vs. guessed, attack your own conclusion, and communicate answer-first. Apply it to the task at hand; it changes HOW you work, not WHAT you do. Use this skill whenever the user says "think like fable", "/think-like-fable", "be rigorous", "think hard about this", "reason carefully", "are you sure?", "double-check that", "don't guess", or hands you a high-stakes decision, a tricky analysis, a root-cause question, or anything where a confident wrong answer is worse than a slow right one — even if they don't name the skill. Do not load it for trivial mechanical edits or casual questions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Think Like Fable
|
|
7
|
+
|
|
8
|
+
A senior operator's manual for a sharp junior. Not a rulebook to satisfy — a way of working to inhabit. Load it, then do the actual task under these disciplines. Every section is: the procedure, one example of it working, and the failure it prevents.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- The user says "think like fable", "/think-like-fable", "be rigorous", "think hard about this", "reason carefully", "are you sure?", "double-check that", or "don't guess".
|
|
13
|
+
- The task is a high-stakes decision, root-cause analysis, architecture call, security judgment, or data-loss-adjacent change — anywhere a confident wrong answer costs more than a slow right one.
|
|
14
|
+
- Another skill or agent prompt says to apply this manual to its work.
|
|
15
|
+
|
|
16
|
+
Do **not** load it for trivial mechanical edits, casual questions, or tasks another skill already governs end-to-end — this manual composes *under* task skills, it doesn't replace them.
|
|
17
|
+
|
|
18
|
+
## 1. Read what the request is actually asking
|
|
19
|
+
|
|
20
|
+
**Procedure:** Before answering, write one sentence: "The user needs ___ so that ___." If you can't fill the second blank, you don't understand the request yet. Check the literal ask against the inferred goal — when they diverge, serve the goal and say you did. Look for the question behind the question: a "how do I X" often means "I'm stuck on Y and think X will fix it."
|
|
21
|
+
|
|
22
|
+
**Example:** "How do I increase the connection pool size?" — literal ask: a config value. Actual need: their app is timing out. The right answer names the config *and* says "if you're seeing timeouts, pool exhaustion is usually a symptom — check for unclosed connections first."
|
|
23
|
+
|
|
24
|
+
**Prevents:** Perfectly executing the wrong task. The junior failure is answering the words; the expensive failure is the user discovering three exchanges later that you solved a question they didn't have.
|
|
25
|
+
|
|
26
|
+
## 2. Break the problem into independently checkable pieces
|
|
27
|
+
|
|
28
|
+
**Procedure:** Decompose so each piece has its own pass/fail test that doesn't depend on the other pieces being right. If two pieces can only be verified together, the cut is wrong — recut. Order pieces so the ones that would invalidate the others come first. A decomposition where step 5 can silently absorb an error from step 2 is a narrative, not a decomposition.
|
|
29
|
+
|
|
30
|
+
**Example:** "Why is this endpoint slow?" → (a) is it actually slow — measure; (b) is time in the DB, the app, or the network — one timer each; (c) within the winner, which call — profile. Each answer is checkable alone, and (a) can kill the whole investigation in one step.
|
|
31
|
+
|
|
32
|
+
**Prevents:** The chain-of-plausibility, where five individually-reasonable steps compound into a confident conclusion nothing ever tested.
|
|
33
|
+
|
|
34
|
+
## 3. Put the effort where the risk lives
|
|
35
|
+
|
|
36
|
+
**Procedure:** Before working, ask: "If this answer is wrong, which part is most likely to be the wrong part — and how bad is being wrong there?" Effort follows that product, not difficulty and not interest. The risky part is usually a boundary (auth, money, data deletion, concurrency, an interface you didn't write), an assumption everything downstream leans on, or the one claim you can't check. Say out loud which part got the scrutiny.
|
|
37
|
+
|
|
38
|
+
**Example:** A 200-line PR: 180 lines of UI layout, 20 lines changing a retry loop around a payment call. The 20 lines get 80% of the review. A double-charged customer costs more than a misaligned button.
|
|
39
|
+
|
|
40
|
+
**Prevents:** Uniform effort — polishing what's easy to check while the load-bearing assumption ships unexamined.
|
|
41
|
+
|
|
42
|
+
## 4. Verify by re-deriving, not by recognizing
|
|
43
|
+
|
|
44
|
+
**Procedure:** For any load-bearing claim, reconstruct it from ground truth through an independent path: run the code, re-do the arithmetic from the inputs, open the file, quote the doc. "It sounds right" and "I've seen this pattern" are recognition, not verification — recognition is exactly what fails on the cases that matter. A claim about code you haven't opened is a hypothesis and must be labeled as one. A result you didn't observe is "not run", never "passed".
|
|
45
|
+
|
|
46
|
+
**Example:** "This function is O(n²) because of the nested loop." Re-derive: open it — the inner loop runs over a fixed 3-element list. It's O(n). The pattern-match was confident and wrong.
|
|
47
|
+
|
|
48
|
+
**Prevents:** Plausible fabrication — the failure mode where fluency substitutes for evidence and the error is invisible precisely because the prose reads well.
|
|
49
|
+
|
|
50
|
+
## 5. Separate known from guessed, and label it out loud
|
|
51
|
+
|
|
52
|
+
**Procedure:** Every substantive claim carries one of three tags, in the text, not in your head: **verified** (I checked, here's how), **inferred** (follows from X, which I checked), **assumed** (unverified; if wrong, Y breaks). Never let an assumption silently upgrade itself by being repeated. When the whole answer hangs on one assumption, lead with it.
|
|
53
|
+
|
|
54
|
+
**Example:** ❌ "The webhook fails because the secret rotated." ✅ "The webhook fails on signature validation (verified — log line quoted below). The likeliest cause is a rotated secret (assumed — I can't see your dashboard; if the secret matches, look at clock skew next)."
|
|
55
|
+
|
|
56
|
+
**Prevents:** Confidence laundering — a guess stated in the same register as a fact, which the reader has no way to discount until it fails in production.
|
|
57
|
+
|
|
58
|
+
## 6. Attack your own conclusion before handing it over
|
|
59
|
+
|
|
60
|
+
**Procedure:** Once you have an answer, switch sides. Spend one honest pass asking: what evidence would prove this wrong, and did I actually look for it? What's the strongest alternative explanation, and why specifically is it worse? If you can't name a way your answer could be wrong, you haven't understood it — every real conclusion has a failure condition. Cheapest test: does the answer survive the most mundane explanation (typo, cache, wrong environment, stale data) being true instead?
|
|
61
|
+
|
|
62
|
+
**Example:** Conclusion: "the race condition is in the cache layer." Attack: if it were, the bug would also appear in the read-only path — does it? Check. It doesn't. Conclusion downgraded, actual cause found in the writer's lock ordering.
|
|
63
|
+
|
|
64
|
+
**Prevents:** First-hypothesis anchoring — where all subsequent effort collects support for the initial guess instead of testing it.
|
|
65
|
+
|
|
66
|
+
## 7. Communicate answer → reasoning → risk, in that order
|
|
67
|
+
|
|
68
|
+
**Procedure:** First sentence: the answer, decision-ready ("Yes, ship it", "It's the lock ordering in `flush()`", "Don't use library X"). Then the reasoning that earns it, shortest complete path only. Then the risk: what would change this answer, what you didn't check, what to watch for. Never make the reader excavate the conclusion from a chronology of your process.
|
|
69
|
+
|
|
70
|
+
**Example:** ❌ "First I looked at the logs, then I noticed…, which led me to…" ✅ "The crash is a null deref in `parse_header` on empty payloads (verified with a repro). Reasoning: … Risk: I only tested v2 payloads; if v1 traffic still exists, verify that path separately."
|
|
71
|
+
|
|
72
|
+
**Prevents:** Burying the lede — the reader skims, grabs a mid-paragraph detail as the takeaway, and acts on the wrong thing.
|
|
73
|
+
|
|
74
|
+
## 8. The mistakes that look like competence and aren't
|
|
75
|
+
|
|
76
|
+
Each of these *feels* like doing a good job. That's what makes them dangerous.
|
|
77
|
+
|
|
78
|
+
- **Thoroughness theater.** Ten findings where two matter. Exhaustiveness reads as rigor but is its absence — rigor is ranking. Say which two matter. Zero findings is a valid result.
|
|
79
|
+
- **Fluent overclaiming.** Polished prose at a fixed confidence level regardless of evidence. Calibration, not eloquence, is the skill. An expert's "I don't know, but here's how to find out" beats a fluent guess.
|
|
80
|
+
- **Premature agreement.** Adopting the user's framing ("since the cache is the problem…") as a conclusion. Their framing is input, not evidence — it's often where the bug hides, because it's the one thing they've stopped questioning.
|
|
81
|
+
- **Complexity as signal.** Reaching for the sophisticated explanation because it displays skill. Mundane causes are the base rate: check the typo before theorizing the distributed-systems failure.
|
|
82
|
+
- **Silent scope repair.** The task as specified has a hole; you patch it with a reasonable choice and don't mention it. The choice may be fine — the silence is the defect. Name every hole you filled.
|
|
83
|
+
- **Momentum completion.** Finishing because you've invested, when a mid-course finding meant the plan should change. Sunk work is not evidence the direction was right.
|
|
84
|
+
- **Deference to your own prior output.** Treating what you said earlier in the session as established fact. Your earlier claims have the same epistemic status as anyone's: whatever the evidence gave them.
|
|
85
|
+
|
|
86
|
+
## The self-test — run on every answer before sending
|
|
87
|
+
|
|
88
|
+
1. **Did I answer the question they needed, not just the one they typed?** (Can I state the need behind the ask in one sentence?)
|
|
89
|
+
2. **Which claim, if wrong, breaks this answer — and did I verify *that one* by re-deriving it, not recognizing it?**
|
|
90
|
+
3. **Is every unverified assumption labeled in the text, or is at least one guess wearing a fact's clothes?**
|
|
91
|
+
4. **Did I genuinely try to break this conclusion — can I name the observation that would prove it wrong?**
|
|
92
|
+
5. **Is the answer in the first sentence, and the risk stated at the end — or does the reader have to excavate both?**
|
|
93
|
+
|
|
94
|
+
Any "no" — fix it before sending. All five "yes" on a wrong answer is still possible; the test buys diligence, not certainty. Say so when the stakes warrant it.
|
|
95
|
+
|
|
96
|
+
## Anti-patterns
|
|
97
|
+
|
|
98
|
+
- ❌ Loading this skill and then narrating it ("Per section 4, I will now verify…") — inhabit the discipline silently; the user sees the *product* of it, not citations to it.
|
|
99
|
+
- ❌ Running the self-test as a checkbox ritual and passing everything — the test only works adversarially; a pass you didn't try to fail is not a pass.
|
|
100
|
+
- ❌ Applying full rigor to a trivial ask — a one-line factual question doesn't need a risk section. Depth scales with stakes (section 3 applies to the manual itself).
|
|
101
|
+
- ✅ Do the user's actual task under these disciplines and let the output show it: answer first, claims tagged, the riskiest part visibly the most scrutinized.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upgrade-deps
|
|
3
|
+
description: Upgrade project dependencies safely — inventories current→target versions from the actual manifest/lockfile, reads the real changelog/release notes for every major bump (a breaking-change claim without a changelog citation is a hypothesis), greps the codebase for each breaking API before declaring it safe, upgrades one major at a time with tests+build quoted green between batches, and reports a per-package table of what changed and what evidence backs "safe". Use this skill whenever the user says "upgrade dependencies", "update packages", "bump <package>", "is it safe to upgrade", "update to the latest", "fix the npm audit", "dependabot PR review", or "/upgrade-deps" — even if they don't explicitly say "dependency skill". Do not use for adding a NEW dependency (that's a design decision — plan-and-build) or diagnosing a breakage after an upgrade already happened (use diagnose).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Upgrade Deps
|
|
7
|
+
|
|
8
|
+
Upgrade dependencies as a verification exercise, not a version-number edit. The failure mode this skill exists to prevent: bump everything, build goes green, ship — then the runtime break surfaces in production because the breaking change lived in behavior, not in types. Every "safe to upgrade" claim here is backed by a named check: the changelog actually read, the breaking API actually grepped for, the suite actually run.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- The user says "upgrade dependencies", "update packages", "bump X to latest", "is it safe to upgrade X", "handle the dependabot/renovate PRs", "fix the audit warnings", "/upgrade-deps".
|
|
13
|
+
- A CVE or audit finding requires moving a package (composes with `security-review`).
|
|
14
|
+
- A framework/runtime upgrade (Node LTS, .NET major, Next.js major) that drags dependencies with it.
|
|
15
|
+
|
|
16
|
+
Do **not** auto-trigger for adding a new dependency (a design choice — route to `plan-and-build` / `grill-with-docs`) or for debugging an already-broken upgrade (`diagnose`). If the repo has no tests at all, say up front that upgrade safety cannot be verified beyond compile — and ask whether to proceed anyway or pin a minimal net first (`write-tests`).
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
1. **Inventory from the tools, not from memory.** Run the ecosystem's outdated-check (`npm outdated`, `dotnet list package --outdated`, `pip list --outdated`, `cargo outdated`, `go list -u -m all`) and quote the output. Training-data version knowledge is stale by construction — never state a "latest version" you didn't just read from a tool or registry. Note which entries are direct vs transitive: transitives usually move by bumping the parent or the lockfile, not the manifest.
|
|
21
|
+
2. **Confirm scope.** Everything? Security-only? One package? If the user didn't say and the outdated list is long, ask once (`AskUserQuestion`): the plan for "patch the CVE" and "get current across the board" are different sizes. Classify the in-scope list: **patch/minor** (batchable) vs **major** (one at a time, each with its own evidence).
|
|
22
|
+
3. **Lock the baseline.** Full test suite (single-run mode, never watch mode) + build, summaries quoted. A result you didn't observe is "not run", never "passed". Red baseline → stop and surface: you can't attribute post-upgrade failures on a pre-broken repo.
|
|
23
|
+
4. **For every major bump: read the actual release notes.** Fetch the changelog / GitHub releases / migration guide for the versions being crossed (all of them — v2→v4 means reading v3's breaking changes too). Extract the breaking-change list. No changelog found → say so and downgrade confidence explicitly ("no changelog located; upgrading on test coverage alone").
|
|
24
|
+
5. **Grep before declaring unaffected.** For each breaking change, search the repo for the removed/renamed API, changed config key, or altered default. Cite hits (each becomes a migration edit) or state the negative concretely: "no usage — repo grep for `<symbol>` returned nothing". Behavioral breaking changes (changed defaults, stricter parsing, timezone/locale changes) don't grep well — list them separately as **runtime risks** and name which test would catch each, or that none would.
|
|
25
|
+
- ❌ "v5 has breaking changes but they probably don't affect us."
|
|
26
|
+
- ✅ "v5 removes `parser.lenient` (changelog §2). Grep: 2 call sites — `config.ts:12`, `import.ts:88` — both need the new `strict:false` option. Also v5 changes default timezone handling (runtime risk: covered by `date-roundtrip` tests)."
|
|
27
|
+
6. **Upgrade in evidence-sized batches.** Patch/minor: one batch, then tests+build, quoted. Majors: strictly one package at a time — apply the bump plus its migration edits from step 5, run tests+build, quote, commit (`conventional-commits`, `chore:` or `fix:`), next. When a batch goes red: read the error, change exactly one thing, retry once; still red → revert that bump, mark the package **blocked** with the quoted error, and continue with the rest. Two failures on the same package is a report item, not a loop.
|
|
28
|
+
7. **Lockfile and peer hygiene.** Regenerate the lockfile with the ecosystem's tool and commit it with the manifest — never hand-edit it. Never silence resolution errors with `--force` / `--legacy-peer-deps` without surfacing what conflict is being overridden and getting a yes. For a transitive CVE with no direct bump available, prefer the ecosystem's override mechanism (`overrides` / `resolutions` / central package management) and label it as a pin to revisit.
|
|
29
|
+
8. **Report the table + the honest residue.** Per package: from → to, breaking changes affecting THIS repo (with the grep/changelog evidence), migration edits made, test result. Then the residue, stated plainly: blocked packages and why, runtime risks no test covers, anything held back deliberately (e.g. "next stayed on 14 — the 15 migration is its own task"). Zero-affected upgrades are a valid, common outcome — a clean table is the report, not a reason to pad.
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
|
|
33
|
+
### Example 1: the routine sweep
|
|
34
|
+
|
|
35
|
+
**User:** "Update this project's dependencies."
|
|
36
|
+
|
|
37
|
+
**Claude:** Runs `npm outdated` (quotes it: 14 minor, 3 major), confirms scope = all, baseline green (quoted), batches the 14 minors → suite green → commit; then majors one at a time: reads `zod` v4 release notes, greps the 3 renamed APIs (7 call sites migrated), suite green, commit; `eslint` v9 flat-config migration done the same way; third major's changelog reveals a Node engine bump beyond the repo's CI version → marked **blocked** with the evidence, not forced. Final table + residue.
|
|
38
|
+
|
|
39
|
+
### Example 2: CVE-driven, transitive
|
|
40
|
+
|
|
41
|
+
**User:** "npm audit is flagging lodash under some build plugin, fix it."
|
|
42
|
+
|
|
43
|
+
**Claude:** Runs `npm audit` (quotes the advisory + path), finds it transitive under a plugin whose latest still pins the bad range, adds an `overrides` entry, regenerates the lockfile, re-runs audit (quotes: 0), runs the build to prove the override didn't break resolution, labels the override as a revisit-when-upstream-fixes pin in the report.
|
|
44
|
+
|
|
45
|
+
## Anti-patterns
|
|
46
|
+
|
|
47
|
+
- ❌ Stating a package's latest version or breaking changes from memory — versions move; only tool output and fetched changelogs count.
|
|
48
|
+
- ❌ Bumping all majors at once — when the suite goes red you can't attribute the failure, and the debug costs more than the sequencing saved.
|
|
49
|
+
- ❌ "Build passes, so the upgrade is safe" — compilation proves the typed surface only; changed runtime defaults, dynamic access, and reflection sail through. Name the runtime risks instead of implying their absence.
|
|
50
|
+
- ❌ `--force` / `--legacy-peer-deps` / `--ignore-engines` applied silently to make the error go away — that's deferring the break to runtime and hiding the decision from the user.
|
|
51
|
+
- ❌ Hand-editing the lockfile, or committing the manifest without regenerating it.
|
|
52
|
+
- ❌ Retrying a red upgrade in a loop with mutations until something compiles — one informed retry, then revert, block, and report.
|
|
53
|
+
- ❌ Sneaking unrelated "while I'm here" refactors into upgrade commits — the diff should be bump + its migration edits, nothing else.
|
|
54
|
+
- ✅ Tool-derived inventory → changelogs actually read → breaking APIs grepped with citations → one major per commit, suite quoted between → table + honest residue.
|
|
55
|
+
|
|
56
|
+
## Notes
|
|
57
|
+
|
|
58
|
+
- Framework majors with published codemods (Next.js, React, MUI, AngularJS→ng) — check for an official codemod before hand-migrating; run it, then diff-review its output like any other change.
|
|
59
|
+
- Version-pinning policy belongs to the repo (exact pins vs ranges, Renovate config) — match what's there; don't impose a policy mid-upgrade.
|
|
60
|
+
- Apply `think-like-fable`: the risk lives in the majors and the runtime-behavior changes, so that's where the effort goes; every "unaffected" is a re-derived negative (grep quoted), never a vibe; the report leads with what the user must decide (blocked items, risks), not the chronology.
|
|
@@ -115,6 +115,30 @@ The description is the **only** field Claude reads when deciding whether to cons
|
|
|
115
115
|
|
|
116
116
|
The most common failure mode is **under-triggering** (Claude doesn't load the skill when it should). Err on the side of *more* trigger phrases — three is the floor, not the ceiling.
|
|
117
117
|
|
|
118
|
+
## Write for the weakest reader
|
|
119
|
+
|
|
120
|
+
The skill will be executed by whatever model loads it — often a smaller one. A top-tier model fills gaps with judgment; a weak one fills them with confident garbage. Encode the judgment explicitly. Preempt these predictable failure modes:
|
|
121
|
+
|
|
122
|
+
1. **Ungrounded claims.** If the skill has the model assert facts about code (reviews, audits, explainers), add evidence gates — name the exact check that licenses each kind of assertion. Include the rule verbatim: *a claim about code the model hasn't opened is a hypothesis and must be labeled as one.*
|
|
123
|
+
- ❌ "Flag unused exports." — the model flags whatever it doesn't recognize.
|
|
124
|
+
- ✅ "Flag an export as unused only after a repo-wide grep for its name returns no callers outside its own file. Read the whole function before judging it, not just the diff hunk."
|
|
125
|
+
2. **Severity inflation / padding.** Report-producing skills need burden-of-proof rules and an explicit *"zero findings is a valid outcome"* clause — otherwise weak models invent findings to look thorough.
|
|
126
|
+
- ❌ "Be rigorous about severity." — everything still gets marked critical.
|
|
127
|
+
- ✅ "A `blocker` must name a concrete failure scenario in one sentence (`user does X → wrong Y`). No scenario → demote to `suggestion`. Zero blockers is a valid result."
|
|
128
|
+
3. **Confabulated success.** Any skill that runs commands needs: *a result you didn't observe is "not run", never "passed"* — plus a failure protocol: read the error, change exactly one thing, retry once; two failures = stop and surface to the user.
|
|
129
|
+
- ❌ "Run the tests and fix any failures." — the model may report "tests pass" without running them.
|
|
130
|
+
- ✅ "Run the test command and quote its summary line in your report. If you did not run it, write `tests: not run`."
|
|
131
|
+
4. **Contrastive examples beat rules.** Weak models imitate examples more than they follow rules. Every rule that matters should carry a ❌/✅ pair — the *same* output done badly and well — with one line on why the ✅ wins. A rule without an example is a suggestion.
|
|
132
|
+
5. **Forking questions.** Interview-style skills need: *a question earns its slot only if different answers lead to different next steps.*
|
|
133
|
+
- ❌ "Should this be robust and user-friendly?" — every answer leads to the same next step; it's filler.
|
|
134
|
+
- ✅ "Postgres or SQLite?" — each answer changes the migration step that follows.
|
|
135
|
+
6. **Re-anchoring.** Multi-turn skills need a cheap ritual — or the executing model drifts from the objective as context grows.
|
|
136
|
+
- ❌ A 9-step workflow with no checkpoint — by step 6 the model is optimizing the wrong thing.
|
|
137
|
+
- ✅ "Before each step, restate the goal in one line. If the step doesn't serve it, stop."
|
|
138
|
+
7. **Context budget.** Every line of the skill is loaded into the executing model's window. Density over coverage — a 600-line skill degrades the very model it's trying to help. Cut before you split; split into `references/` before you exceed ~150 lines.
|
|
139
|
+
|
|
140
|
+
When reviewing a draft, simulate the weakest reader: for each instruction ask "could this be followed *wrong* while technically complying?" If yes, tighten it with a check, a threshold, or an example.
|
|
141
|
+
|
|
118
142
|
## When to add scripts or reference files
|
|
119
143
|
|
|
120
144
|
Default to a single `SKILL.md`. Only escalate when:
|
|
@@ -136,6 +160,9 @@ Before showing the draft to the user:
|
|
|
136
160
|
- [ ] Workflow steps are imperative and verifiable, not vibes ("Verify X exists", not "Be careful")
|
|
137
161
|
- [ ] At least one concrete example
|
|
138
162
|
- [ ] Anti-patterns section names plausible wrong behaviors, not strawmen
|
|
163
|
+
- [ ] Each rule that matters carries a ❌/✅ pair of the same output done badly and well
|
|
164
|
+
- [ ] Each assertion the skill asks the model to make has an evidence gate — the exact check that licenses it
|
|
165
|
+
- [ ] Report-producing skills state "zero findings is a valid outcome"; command-running skills state "a result you didn't observe is 'not run', never 'passed'"
|
|
139
166
|
- [ ] No time-sensitive info (specific dates, "as of 2026", model version numbers) unless load-bearing
|
|
140
167
|
- [ ] File is under ~150 lines; longer content is split into `references/`
|
|
141
168
|
- [ ] If targeting the library repo, README table row is added in alphabetical order
|
|
@@ -178,6 +205,8 @@ Before showing the draft to the user:
|
|
|
178
205
|
- ❌ Writing a vague description like "Helps with commits." — Claude won't trigger it. Always include explicit trigger phrases.
|
|
179
206
|
- ❌ Inventing trigger phrases the user didn't confirm — ask, don't guess.
|
|
180
207
|
- ❌ Padding `SKILL.md` with motivational prose. Every line should change Claude's behavior; if removing it changes nothing, cut it.
|
|
208
|
+
- ❌ Delegating judgment to the executing model ("use discretion", "be careful", "apply good judgment") — name the check, the threshold, and the fallback instead.
|
|
209
|
+
- ❌ Stating a load-bearing rule without a ❌/✅ pair — weak models imitate examples, not prose.
|
|
181
210
|
- ❌ Hard-coding model names, package versions, or dates that will rot. Resolve at runtime when possible.
|
|
182
211
|
- ❌ Putting executable behavior in `SKILL.md` prose when a 10-line script would be deterministic and cheaper.
|
|
183
212
|
- ❌ For library skills: drafting the SKILL.md but forgetting to update the README table — the skill is invisible to anyone browsing the repo.
|