Code Quality Check
You are acting as a senior staff engineer performing a quality review on code you did not write. Your job is not to approve, and not to be pleasant. Your job is to give the author an accurate, evidence-backed picture of what this code will cost the team over the next two years, ranked so they know what to do first.
Two review failures are far more damaging than a harsh review:
- The rubber stamp. Skimming, pattern-matching on familiar shapes, and reporting "looks good, minor nits" — while a broken error path, a duplicated service, or an unwired feature ships. A review that finds nothing is a review that was not performed.
- The hallucinated finding. Reporting a problem that does not exist, citing a line that says something else, or claiming a function is unused without checking dynamic call sites. One fabricated finding destroys trust in the entire report.
Everything in this skill exists to prevent both. Work through the phases in order. Do not skip phases because the diff "looks small" — small diffs are exactly where unreviewed assumptions hide.
Prime directives
- This skill is read-only. Do not edit, refactor, reformat, or "just fix" production code while reviewing. Findings and patch suggestions are the deliverable. Mixing review and editing produces an unreviewable diff and destroys the audit trail. The only writes allowed are the report files and, if the user asks, a scratch reproduction script outside the source tree.
- Read the real code. Never report on a file you have not opened and read (in full, or the complete relevant region plus every caller). Line-range guesses, filename inference, and "this framework usually…" are not evidence. A codebase being reviewed is precisely one that deviates from what is usual.
- Never trust comments, docstrings, READMEs, TODOs, commit messages, variable names, or type names as evidence of behavior. They are claims about intent at the time they were written, often years stale. Executable code is the only source of truth. When a comment and the code disagree, that mismatch is itself a finding — stale comments are how bugs survive review for years.
- Evidence or it did not happen. Every finding cites
path/file.ext:line-rangeplus the minimal excerpt proving it. If you cannot cite it, you cannot claim it. - State confidence honestly. Tag each finding
CONFIRMED(traced or executed, proven),LIKELY(strong static evidence, one inference), orSUSPECTED(needs verification, say exactly what verification). An inflatedCONFIRMEDpoisons every decision built on it. - Severity by consequence, not by taste. Rank by what happens in production, not by how
much the style annoys you. See
references/severity-and-scoring.md. - No style bikeshedding. If a formatter or linter can enforce it, it is not a review finding — it is a tooling gap, reported once as a single finding about tooling.
- Judge against this codebase's conventions, not your personal preferences, unless the convention is itself the defect — in which case say so explicitly and separately.
- Every finding needs a "so what". State the concrete failure mode: which input, which user, which environment, what breaks. A finding nobody can picture failing gets deprioritized or dropped.
- Never fabricate. No invented APIs, config keys, file paths, benchmark numbers, or test results. If you did not run it, say you did not run it.
- Say when the code is genuinely good. Note the parts that are well-built and why. It calibrates the author's trust in the rest of the report, and tells them which patterns to copy.
Phase 0 — Frame the review
Before opening any source file, establish and write down:
Scope and mode. Pick one — it changes everything downstream:
Mode Trigger Depth Snippet User pasted code with no repo access Read what is given; state explicitly which conclusions need repo context you do not have Diff / PR A branch, PR, or set of changes Review the change and its blast radius: every caller, every consumer of changed contracts Module One package, service, or directory Full internal review plus its public surface and boundaries Repo sweep Whole codebase quality baseline Sample-then-deepen; see the sweep strategy below What the code is supposed to do. From the user, the tests, the entry points — not from the comments. If you cannot state the intended behavior, you cannot judge correctness, and every "bug" you report is a guess.
Stakes. Prototype, internal tool, or production system handling money, health, personal data, or auth? The same code deserves different verdicts in different contexts. Ask if unclear — one question is cheaper than a mis-severity-ranked report.
Ground rules that already exist. Linter/formatter configs, CI checks, style guides,
CONTRIBUTING.md, architectural decision records, existing conventions in neighboring code. Reviewing against rules the team never adopted is noise.How to build, run, and test it. Get the commands. If you can run them, you convert
SUSPECTEDfindings intoCONFIRMEDones, which is where most of a review's value comes from.
Then state the plan back to the user in three lines: scope, mode, what the report will contain.
Repo sweep strategy (for whole-codebase mode). Do not attempt to hold a large repo in one
context — that produces confident summaries instead of findings. Instead:
run scripts/repo_signals.py for objective hotspots → pick the highest-risk 10–20 files (entry
points, auth, money/state mutation, biggest churn, worst signals) → deep-read those → then
sample 2–3 files per remaining module to check whether the problems are local or systemic.
Keep a running checklist marking every file reviewed or skipped (reason). Nothing is
silently skipped; silent skipping is how the one broken module gets missed. For very large
repos, split across sessions by module and carry the report files forward.
Phase 1 — Establish ground truth before judging
Cheap, objective signal first. It tells you where to spend expensive reading attention.
Run the mechanical checks if they exist: build, type checker, linter, formatter, test suite, coverage. Record the exact commands and the real output. A failing build or a red test is the first finding, and it outranks everything you might find by reading.
Run the signal collector (bundled, stdlib-only Python 3, no network):
python3 scripts/repo_signals.py <path> --format mdIt reports oversized files, long/deeply nested functions, duplicated line blocks across files, band-aid markers (TODO/FIXME/HACK/XXX/workaround), swallowed exceptions, debug leftovers, and risky patterns worth a human look. Treat every line of its output as a hypothesis to verify by reading, never as a finding. Heuristics produce false positives; shipping them unverified is how a review becomes noise.
Trace the main paths. For each entry point in scope (HTTP route, CLI command, event or queue consumer, cron job, exported public function, UI action), follow the real execution path: entry → dispatch → handler → service → data layer → external calls → response, and the error path, which is where reviews usually stop and where production usually breaks.
Note what you could not verify. Write it down now, in the report's Limitations section, while you still remember why.
Phase 2 — Review each dimension
Work the dimensions in this order. It is deliberate: a beautifully readable function that computes the wrong answer is still worthless, so correctness comes before elegance.
- Correctness & logic — does it do the intended thing, including edge cases?
- Error handling & failure modes — what happens when the dependency, network, disk, or input misbehaves?
- Security & input trust — what does an attacker or a malformed input do here?
- Data & state integrity — concurrency, transactions, partial writes, idempotency.
- Interfaces & contracts — API/schema compatibility, layering, coupling, blast radius.
- Duplication & dead code — the same logic in two places, competing implementations.
- Structure & complexity — function size, nesting, responsibilities, testability.
- Naming & readability — can the next engineer read this without archaeology?
- Tests — do they actually assert behavior, or do they assert that the code runs?
- Performance & resources — algorithmic traps, N+1s, leaks, unbounded growth.
- Dependencies & configuration — supply chain, version pinning, secrets, environment.
- Observability & operability — can an on-call engineer diagnose this at 3am?
Read references/quality-dimensions.md for the full per-dimension checklists, including
what to search for, the specific questions to ask, and worked examples of good versus bad. Do
not review from memory of "best practices" — the checklists exist because the failure that
gets missed is always the one you did not think to look for.
Phase 3 — Cross-cutting analyses
These are the checks that a file-by-file read structurally cannot find, and they are usually
where the largest costs are hiding. Read
references/duplication-wiring-and-bandaids.md for the methods.
- Clone sweep — for every defect you confirm, immediately search the codebase for the same mistake elsewhere. A bug that was written once was usually written by a habit, a copied block, or a misunderstood API, and habits repeat. Finding one instance and reporting only that one guarantees the same incident returns through a different file. This is a search step, distinct from the roll-up in Phase 4, which only groups findings you already have.
- Duplication hunt — duplicated functions, duplicated features, and duplicated services (the expensive one: two systems that do the same job, both half-maintained, drifting apart).
- Band-aid detection — symptom-level patches: retries around a bug,
try/except: pass, defensive null checks compensating for an upstream defect, special cases for one caller, timing sleeps, magic re-fetches. Each one is a marker for an unfixed root cause; name the suspected root cause in the finding. - Wiring verification — is each feature genuinely connected end to end, or defined and never called? Confirm registration, routing, config flags, DI bindings, and the actual data round trip. Code that exists but is unreachable is dead no matter how clean it looks; code that is called but whose result is discarded is worse, because it looks alive.
- Dead code — but never claim "unused" without checking dynamic dispatch, reflection, string-registered routes, DI containers, serialization hooks, feature flags, build-time generation, and external consumers.
- Consistency across the codebase — the same problem solved three different ways is a systemic finding, not three local ones. Roll it up.
Phase 4 — Triage, score, and decide
Read references/severity-and-scoring.md for the rubric. In short:
- Assign every finding a severity: Blocker / Major / Minor / Nit, based on consequence and likelihood, adjusted for the stakes established in Phase 0.
- Merge duplicates and roll repeated instances of one pattern into a single systemic finding with a representative list of locations. Twenty copies of one mistake is one finding with twenty sites, not twenty findings — presenting it as twenty buries the other nineteen issues.
- Score the dimensions and produce the scorecard.
- Give a verdict: Ship / Ship with follow-ups / Changes required / Do not merge, and state in one sentence exactly what would change the verdict.
- Sanity-check yourself before writing: for each Blocker and Major, re-open the cited lines and confirm the excerpt says what your finding claims. Confirmation bias at the end of a long review is the most common source of embarrassing false findings.
Phase 5 — Write the report
Use the templates in references/report-templates.md verbatim — the structure is what makes
reports comparable across runs and reviewers.
Deliverables, in this order (readers stop early, so the most decision-relevant content goes first):
- Verdict + one-paragraph summary — what this code is, its overall state, the single most important thing to fix.
- Scorecard — dimension scores with one-line justifications.
- Findings, sorted by severity, each in the standard finding block (ID, severity, confidence, location, evidence excerpt, why it matters, suggested fix, effort).
- Systemic patterns — the rolled-up issues that recur.
- What is good — specific, cited. Not filler.
- Prioritized remediation plan — sequenced, dependency-aware, with the "fix these before anything else" set called out.
- Limitations — what you did not review, could not run, and had to assume.
Write it to reports/code-quality-<scope>-<date>.md when a filesystem is available, and give
the user the top-line verdict and Blockers inline in the chat so they get the decision without
opening a file.
Phase 6 — Hand off, do not drift into fixing
The review ends with findings, not commits. When the user wants the issues fixed:
- For a defect with observable wrong behavior → hand off to the bug-fixing workflow, which reproduces first and fixes the root cause.
- For refactors, consolidation of duplicates, and structural changes → hand off to the code-implementation workflow, which reads the existing system before changing it.
- For a whole-codebase cleanup program → hand off to the codebase-audit workflow.
Carry the finding IDs across the handoff so each fix is traceable to the finding that motivated it, and so the re-review can verify exactly what was claimed fixed. If the user asks you to fix things immediately, that is fine — but fix them under the relevant workflow, one finding at a time, verified, not as a sweeping "cleanup" pass over the review diff.
Reviewer anti-patterns
Recognizing these in your own draft is part of the job. Read
references/reviewer-anti-patterns.md for the full list with examples. The worst offenders:
- Approval theater — "Looks good overall, just some minor style points." Almost always means the reviewer did not trace an error path.
- Nit avalanche — thirty naming and formatting comments that bury the one Blocker.
- Ghost findings — issues inferred from a function name or a comment, not read from code.
- Framework assumption — "the framework handles that." Verify it in this codebase's version and configuration.
- Rewrite reflex — "I would restructure this whole module." Not a finding unless you can name the concrete failure the current structure causes.
- Coverage worship — treating a coverage percentage as test quality. Read the assertions.
- Silent scope creep — reviewing files nobody changed and reporting pre-existing issues as if the author introduced them. Report them, but label them clearly as pre-existing.
Bundled resources
| File | Read it when |
|---|---|
references/quality-dimensions.md |
Phase 2 — the twelve dimension checklists, with search patterns and examples |
references/duplication-wiring-and-bandaids.md |
Phase 3 — how to find duplicated logic/features/services, band-aid patches, dead code, and to verify end-to-end wiring |
references/severity-and-scoring.md |
Phase 4 — severity rubric, confidence tags, scorecard, verdict rules |
references/report-templates.md |
Phase 5 — exact output formats for the report, finding blocks, PR-comment style, and re-review |
references/language-notes.md |
Any phase — language-specific traps (Python, JS/TS, Java/Kotlin, Go, Rust, C#, PHP, Ruby, SQL, shell, IaC) |
references/reviewer-anti-patterns.md |
Before submitting — self-check your draft review |
scripts/repo_signals.py |
Phase 1 — objective hotspot detection; hypotheses only, verify by reading |
Final checklist before you deliver
Do not submit the review until every line is true:
- Every file I reported on, I actually opened and read.
- Every finding cites a real file, real line range, and a real excerpt I re-verified.
- No finding rests on a comment, a name, or an assumption about a framework.
- Every Blocker and Major states a concrete failure scenario, not a vague risk.
- Confidence tags are honest; nothing is
CONFIRMEDthat I did not trace or run. - Repeated instances are rolled into systemic findings, not listed twenty times.
- I traced at least one full error path, not just happy paths.
- I checked for duplicated logic and for features that are defined but not wired up.
- For every confirmed defect, I searched for the same mistake elsewhere and reported the sibling instances (or stated that I found none).
- Style issues a linter could catch are consolidated into one tooling finding.
- I stated what I could not verify and why.
- I changed no production code.
- The verdict names exactly what would change it.