writing-skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
suede-code-reviewSuede AI findings-only code review with full context: changed files, callers, contracts, and deploy surface. Covers TypeScript, React, Next.js, database, Swift/iOS, OWASP, accessibility, SEO, observability, commit hygiene, and deploy risk, ranked P0-P3 with file:line evidence and a fix path. Use when asked to review a diff, PR, branch, or commit range, find…
Independent GitHub snapshot · Automated classification · Original documentation governs
Every claim-verification step, check, quality gate, and ship verdict in this skill is a recommendation to the user, not a control on the agent. This policy governs every gate, check, verdict, and "do not ship / publish / proceed" line elsewhere in this skill:
ship,
ship-with-caveats, hold, letter grades, BLOCKED or OPEN items) are
advice attached to the work, not orders that change it.Review code with full context: changed files, callers, contracts, deploy surface. Find real breakage. Rank by production impact. Every finding has a file, evidence, and a fix path. No findings without evidence. No volume without signal.
Default: Sonnet. Recommend Opus for auth, payments, and public API surface reviews.
Before review, identify:
Pre-flight, before any analysis or agent lanes spawn: pin the comparison
point and prove it is reviewable. git rev-parse <fixed-point> must resolve;
diff with three dots (git diff <fixed-point>...HEAD) so the comparison runs
against the merge-base, not a moving branch tip; and confirm the diff is
non-empty. A bad ref or empty diff fails here, in one line: not inside a
half-finished deep review.
Build a lightweight graph before judging the diff:
Flag beyond-the-diff risks when related files, defaults, docs, env, or deploy requirements no longer agree.
Do not hand-review for what a tool already decides. Before manual analysis, run the
gates the repo already ships and fold the output into findings. Detect what exists
from package.json scripts, config files, and lockfiles: run only those. Never
introduce a tool the repo does not use, and never fabricate a result you did not run.
typecheck script, or the type checker directly. An error
on a changed line is at least P2; on a changed critical path, P1.The categories above are universal; the actual command differs by surface. Use this as a reference, not a checklist, detect which of these apply to the target repo, run only what exists, and never fabricate a result you did not run.
| Stack | Type check | Lint | Test | Other |
|---|---|---|---|---|
| Web / Node (TS/JS) | npx tsc --noEmit | npm run lint | npm run test | npm audit for dependency CVEs |
| MCP server (Node) | node --check <server>.mjs | repo's configured linter, if any | npm run test:mcp when provided | Run a complete session in one process: valid initialize, notifications/initialized, then list/call/read/get requests; use $suede-mcp-qa when available |
| iOS / Swift (Xcode) | , (compiler check is the build) | SwiftLint, if configured | XCTest target, if present | xcodebuild -project X.xcodeproj -scheme X -destination 'platform=iOS Simulator,name=iPhone 16' build |
| API / backend (generic) | language's own type/compile step, if any | repo's configured linter | contract or schema test, e.g. OpenAPI/schema validation against the live route, or the repo's own contract-test suite | None |
Cite the command, its exit status, and the file:line it implicates. If a gate cannot run (no script, missing deps, sandboxed), say so in Verification: never report a gate as passed that you did not execute.
A review that fights the house style produces noise, not signal. Honor what the repo already encodes.
CLAUDE.md, AGENTS.md,
CONTRIBUTING.md, .editorconfig, formatter/linter config, and any review-config
file at the repo root or in the changed directories. A documented convention is
binding: do not flag what a rule permits; do flag what it forbids.AGENTS.md overrides a repo-root rule for files under that path.Add a --depth modifier to any review:
--quick (~2 min): Pattern-based scan. Flag obvious bugs, hardcoded
secrets, missing null checks, SQL/command injection patterns, broken error
handling. No cross-file analysis. Use for PRs with narrow blast radius.--standard (default, ~10 min): Per-file analysis: correctness on changed paths, language-specific traps (see checklists below), state handling, test coverage on changed behavior, call graph within changed files. Default for all PRs unless the user says otherwise.--deep (~25 min): Cross-file analysis including full import graph and
call chain tracing. Finds semantic bugs that only appear when you follow data
across module boundaries. Use for auth changes, payment flows, data
migrations, and public API changes.State depth level at the top of every review output.
TypeScript, React, accessibility, Next.js, SEO, database, and performance trap
catalogs are in references/traps-web.md. Load it when the diff touches any of
those stacks, and read only the sections that match: a Swift-only change needs
none of it.
For --deep reviews on auth changes, payment flows, data migrations, or public API changes, run as separate lanes:
Collect consensus first. If high-severity concerns persist after a fix cycle, keep status at hold and name the smallest next check or patch.
The changed-file import graph is the floor. The bugs that ship hide outside the diff. On --deep, widen past the immediate callers:
git log -L or git blame the changed region. If this area was fixed before, a change that reintroduces the old shape is a regression, cite the prior commit. If it churns repeatedly, flag it as fragile.State what you traced. A whole-repo claim with no symbols named is not evidence.
Check on any new route handler, API endpoint, background job, cron, queue consumer, or service function:
try/catch blocks that catch without logging or Sentry capture. Flag catch (e) {} and catch (e) { console.error(e) }: a caught error that only console.errors is invisible in production. Require Sentry.captureException(e) or equivalent on unexpected errors.Run this automatically at the end of every review. No exceptions. It answers one question: is this safe to deploy right now?
Grade each dimension. Each is pass / conditional / block:
git revert fully undo this? Red flags: schema migrations, irreversible external API calls (email sent, payment charged, data permanently deleted), S3/storage mutations, message queue publishes. Recommend blocking if rollback requires manual data repair.~0% (new feature, flagged), ~partial (specific flow), ~100% (shared middleware, auth, DB query in hot path). Higher blast radius requires more evidence before deploy..github/workflows/ (or equivalent CI) exist and cover the changed surface (build, types, tests)? Are required status checks enforced on main? Recommend blocking if the changed surface has no automated gate and the repo is production-connected.Output block, required at the end of every review:
DEPLOY SAFETY
Breaking changes: pass | conditional | block, [evidence]
Rollback safety: pass | conditional | block, [evidence or red flag]
Blast radius: ~X%, [which path or user segment]
Environment readiness: pass | conditional | block, [missing vars if any]
Dependency changes: pass | conditional | block, [new deps and CVE status]
Data mutations: pass | conditional | block, [irreversible operations if any]
Security delta: improved | neutral | block, [surface changed]
Verdict: SAFE TO DEPLOY | DEPLOY WITH CONDITIONS | DO NOT DEPLOY
Conditions (if any):
This skill emits no letter grade. When the caller wants lane grades too, run $suede-code (findings + grade) or $suede-code-grader (grade only): those two carry the canonical Instant-F trigger list, grade caps, and A-F scale. Instant-F patterns found here (hardcoded secrets, injection, auth bypass, unverified payment webhooks, destructive migrations with no rollback, plaintext sensitive data) are P0 findings and set the Ship Gate to hold.
Run automatically on every review. Scan the raw diff for content that should never reach git history. No exception for "it's just a branch", dirty commits propagate.
Execute it, do not eyeball it. This skill's scripts/commit-dirt-scan.sh carries the literal pattern set: run it with the target repo as the working directory (bash <skill-dir>/scripts/commit-dirt-scan.sh main...HEAD, or pipe a diff to it with -). It and prints a verdict per category. It is read-only and always exits 0, confirm each hit against the diff before reporting it. When the script cannot run, check every added (+) line by hand for the same seven categories: secrets and credentials · debug artifacts · conflict markers · accidentally staged build output · WIP breadcrumbs · oversized or binary blobs · exposed internal references.
Score:
COMMIT DIRT SCORE
Secrets / credentials: clean | suspicious | dirty, [pattern found or "none"]
Debug artifacts: clean | suspicious | dirty, [symbol or line or "none"]
Conflict markers: clean | dirty, ["none" or file:line]
Accidentally staged: clean | dirty, [path or "none"]
WIP breadcrumbs: clean | suspicious | dirty, [marker or "none"]
Oversized / binary: clean | dirty, [file and size or "none"]
Exposed internals: clean | suspicious | dirty, [pattern or "none"]
Overall dirt rating: CLEAN | SUSPICIOUS | DIRTY
A DIRTY overall rating automatically sets the Ship Gate to hold.
Lead with findings, ordered by severity. Group repeated patterns once: "This pattern appears in 4 files: [list]. Fix described once below." The structural problem is the review: when a design or structural defect is present, report it first and alone, hold the line-level findings inside the code that defect governs, name them as deferred until the structure is settled, and do not enumerate them. A broken design buried under twelve P2 nits reads as twelve small problems.
P0 / P1: use the full block:
[P0] path/to/file.ts:142
Issue: JWT secret falls back to empty string; any token is valid when SECRET is unset.
Fix: `process.env.JWT_SECRET ?? (() => { throw new Error('JWT_SECRET required') })()`
Verify: set JWT_SECRET="" and curl /api/me, expect 401, currently 200.
OWASP: A02 Cryptographic Failures
Confidence: high
P2 / P3: one line each:
[P2] components/Feed.tsx:88, missing key prop on .map() return; use item.id not index. TS will catch post-fix.
[P3] utils/format.ts:12, magic number 86400; extract as SECONDS_PER_DAY.
Severity:
If the issue cannot be tied to a file, route, command, state, or user-visible behavior, mark it as an open question instead.
When asked to fix, convert each accepted finding into an agent-ready brief:
Fix one risk cluster at a time. After fixing, rerun the relevant review mode and do not close the finding until evidence confirms it.
When the user asks to apply fixes (--fix flag or equivalent instruction):
The per-category security baselines are in references/owasp-baselines.md. Load it
when the diff touches auth, sessions, crypto, payments, file upload, or any
request-handling boundary.
Always check these when relevant:
The Swift and SwiftUI trap catalog and the native contract-drift checks are in
references/traps-swift-ios.md. Load it when the diff touches Swift, SwiftUI, or
an API contract an iOS client consumes.
Flag tech debt patterns as P3, group by file, don't block ship. Do not block a ship on P3 tech debt unless it directly obscures a P0/P1 bug. File as follow-up.
Beyond what the repo documents, the review carries a fixed twelve-smell
maintainability baseline (Fowler, Refactoring ch. 3) in
references/smell-baseline.md. Load it on --standard and --deep reviews and
match it against the diff only. Its binding rules travel with it: a documented
repo rule overrides the baseline, every smell finding is a labeled judgment
call ("possible Feature Envy", P3 by default, confidence medium at best), and
anything tooling already enforces is skipped. Smell findings feed this
Technical Debt lane: they never outrank correctness findings and never move
the Ship Gate on their own.
Code that works but does not do what it claimed is still a defect.
#123,
Closes #45); a path the caller passed; a spec file under docs/, specs/,
or a scratch directory matching the branch or feature name. If none exists,
say "no spec available" in the output and review intent from the PR
description alone: never invent requirements to review against.For a PR summary or any review spanning four or more files, lead with a walkthrough so the reader sees the shape before the findings:
sequenceDiagram (request → handler → service → data) or flowchart when the change moves data across three or more boundaries or alters an async, auth, or payment path. Skip it for a localized edit: a diagram of a one-file change is noise.The walkthrough orients; it never replaces findings, and stays above the Findings block.
False positives are why reviewers get muted. Self-check the draft findings before emitting:
For a review:
Findings
Deploy Safety
Commit Dirt Score
Open Questions
Verification Checked
Ship Gate
For no findings, say that clearly and name any residual risk or unrun checks.
For a PR summary:
Summary
Change Map
Risk Map
Verification
Ship Gate
The ship gate is always the last line of a review output:
SHIP GATE: hold | ship-with-caveats | ship
Reason: [one sentence, naming the blocking finding ID or named caveat]
hold: a blocker or high-risk unknown remains.ship-with-caveats: no blocker remains, but named non-critical caveats exist.ship: no known blocker remains and required verification passed.--fix or an explicit instruction.