code-critic · diff
git:20260928.1507ddb to git:20261004.cccdee6
221 added, 389 removed. Audit A to A.
---
name: code-critic
description: >
- Code review checklist and coding standards, extended per project by
- whatever file AGENTS.md's Review & Planning Guidance section names
- (defaulting to docs/agent-rules/code-critic.md). Invoked as /code-critic
- for an ad-hoc review, or applied by the code-critic sub-agent in the
- /feature workflow. (Named code-critic so it does not shadow Claude Code's
- bundled code-review skill.)
- ---
-
- # /code-critic — Code Review
-
- Apply this skill to review code changes against project standards.
-
- ---
-
- ## Stance
-
- Treat the implementation as a hypothesis under attack. Your default
- assumption is that something is wrong; your job is to find what.
-
- Confirmation bias is the dominant failure mode of AI code review — guard
- against it by actively trying to disconfirm the implementation rather than
- verifying that it looks reasonable. If you cannot find a fault after
- genuine effort, that is itself a finding worth stating explicitly (see the
- Output Format section).
-
- ---
-
- ## Before Reviewing
-
- ### Selecting the diff
-
- In the `/feature` workflow the implementation is committed before review, so
- a bare `git diff` (working tree) shows nothing — review the branch's
- committed changes against its base, the default branch named in `AGENTS.md`
- → *Commands*: `git diff <default-branch>...HEAD` (or
- `git log -p <default-branch>..HEAD`). Invoked ad-hoc on uncommitted work,
- review the working-tree diff instead. If unsure what changed, check
- `git status` and `git log --oneline` first.
-
- Note for ad-hoc use: the push gate records a commit SHA
- (`scripts/review-ok.sh`), so a review meant to unlock a push must cover the
- committed state — commit first, then review.
-
- ### Architecture Decision Records
-
- Check if a `docs/adr/` directory exists. If it does, list the ADRs you read by
- number in the review output. If none seemed relevant
- to the diff, say so explicitly — silence is not acceptable, since it is
- indistinguishable from skipping the step.
-
- If the diff contradicts an ADR, quote the contradicting ADR clause and the
- offending diff line, and flag it as `FAIL`.
-
- ### Implementation Plan
-
- If plan text was provided (inline in the prompt, or via a file path), use it
- before reviewing. Use it as follows:
- - **Approval Summary / Acceptance Criteria**: the human-approved contract.
- Verify every `AC-<slug>-n` has a committed test (via the `[AC-<slug>-n]`
- tags in Test Strategy) that would fail if the criterion were broken — a
- criterion without one is `FAIL`.
- - **Contract** section (if present): cross-check the diff's routes, form
- fields/params, response shapes, error rendering, and schema changes
- against it. An undiscussed deviation from the approved Contract is `FAIL`.
- - **Types anywhere in the plan** (Contract, Approach, Requirements — even
- when Contract is "None"): types (nullable vs non-null, optional vs
- required) are part of the contract, not just names and presence.
- Explicitly diff every parameter/field type the plan states against the
- diff's actual signature; do not infer the type from the inputs the tests
- use. A non-nullable parameter standing in for a plan-specified nullable
- one is `FAIL` even if every test passes, since a real caller carrying the
- untested value (e.g. an actual `null`) cannot satisfy the signature. The
- reverse (nullable/optional where the plan says non-null/required) is
- `FAIL` too, unless the review input documents an approved deviation.
- - **Requirements** section: the source of truth for what should have been built —
- used to verify Plan Compliance and that all specified edge cases are handled.
- - **Approach** section: the agreed implementation strategy — used to verify the
- code follows the intended design rather than an ad-hoc alternative.
- - **Edge Cases** section: the enumerated scenarios that must be handled.
- Verify every `EDGE-<slug>-n` has a committed test (via the `[EDGE-<slug>-n]`
- tags in Test Strategy) that would fail if the handling strategy were
- broken — an edge case without one is `FAIL`.
- - **Test Strategy** section: the agreed test coverage — cross-reference against
- the actual tests written.
- - **Files** section: the planned file manifest — cross-check against the diff. A
- file in the diff that is not listed here (or listed but left untouched) is an
- undiscussed change; flag the mismatch and judge whether it is in scope.
- - **Out of Scope** section: the explicit boundary — do NOT flag as missing
- anything listed here, and DO flag as scope creep any code that strays into it.
-
- If no plan was provided, skip the Plan Compliance checklist section entirely.
-
- **Test evidence.** The review verifies coverage statically; whether the
- suite actually ran and passed on the reviewed state is separate evidence.
- In the `/feature` workflow that evidence is passed in (the summary of the
- latest full test-suite run). Treat that summary as a record of the run, not
- independent proof — it is produced by the implementing agent, and this
- review has no independent way to confirm it (whether the project's own CI
- provides that is outside this skill's scope). If no evidence was provided
- and you cannot (or may not) run the suite yourself, do not assume it is
- green — raise an Open Question: "no evidence the test suite ran on the
- reviewed state".
-
- When flagging a plan compliance issue, **quote the exact line from the plan**
- that the diff violates, alongside the diff line that violates it. Paraphrasing
- the plan is not enough — the developer needs to see the literal mismatch.
-
- ### Reading Beyond the Diff
-
- You may read any file in the repository. The diff is the unit under review,
- but surrounding code, tests, configuration, and migrations are fair context —
- and often necessary to judge whether the change is correct. Some
- project-specific rules below may explicitly require it (cross-referencing a
- sibling file, checking that a registration or annotation is present).
-
+ Reviews code changes against project standards and the approved
+ plan; returns PASS/FAIL/NEEDS_DECISION per checklist item plus open
+ questions. Use when the user asks for a code review of a branch or change,
+ or after implementation and before opening a PR.
+ license: MIT
+ metadata:
+ author: André Cunha
---
- ## Coding Standards
-
- ### Single Responsibility
-
- **Functions:** A function should do one thing. If a function contains a
- conditional branch that handles a fundamentally different concern (e.g. an
- admin path bolted onto a regular-user path, or a parsing path inside a
- persistence call), flag it. Severity:
- - New function introduced with mixed concerns → `FAIL`
- - Existing function extended with a clearly unrelated branch → `FAIL`
- - Borderline case where extraction would hurt readability → `NEEDS_DECISION`
-
- **Classes:** A class has too many responsibilities if you can identify more than
- one independent reason it would need to change.
-
- When reviewing new code that touches an existing class:
- - If the new code **introduces** a class with too many responsibilities → `FAIL`
- - If the new code **significantly worsens** an existing violation (e.g., adding
- several more methods to an already oversized class) → `FAIL`
- - If the new code **extends** an already-oversized class without making it
- meaningfully worse → `NEEDS_DECISION`: flag the pre-existing debt and let the
- developer decide whether to refactor now, file tech debt, or accept it
-
- ### Error Handling
- - In business logic, never use generic catch-all error handling. At process
- boundaries (top-level controllers, scheduled jobs, async task entry points)
- a catch-all that logs and translates to a domain error is acceptable —
- judge by *where* the catch lives, not just *what* it catches.
- - Every error must include context about what operation failed and why.
- - Errors in critical paths must be logged with structured fields.
-
- ### Naming
- - Functions should describe what they do: `calculateShippingCost`, not `calc` or
- `process`.
- - Boolean variables/functions should read as questions: `isValid`, `hasPermission`.
-
- ### Tests
-
- You are responsible for both **test quality** (structure, naming, pattern) AND
- **test completeness** (coverage of the spec AND beyond). The `/adversarial-qa` skill is
- purely exploratory/adversarial in a running browser — it does not verify that
- the committed tests cover the plan, so that responsibility lives here.
-
- **Quality:**
- - Every public function with non-trivial behaviour must have tests covering
- the happy path AND edge cases. Trivial delegators, generated code, plain
- data classes, and pure getters are exempt — but if you exempt a function,
- state which one and why in the review.
- - Test names must describe the scenario: `test_order_fails_when_inventory_insufficient`,
- not `test_order_2`.
- - Use the Given-When-Then pattern.
- - Never test implementation details — test behaviour.
- - The same disconfirmation stance applies to the tests themselves: check
- what a test's assertion actually compares, not what its name or comment
- claims — a test that would pass regardless of correctness (e.g. an
- expression compared to itself) proves nothing.
- - Tests that encode the plan's Test Strategy (the `[AC-<slug>-n]`-tagged ones
- especially) are the contract, not implementation detail: a diff that
- weakens, loosens, or deletes one so the suite passes is `FAIL` unless the
- review input documents an approved plan deviation covering it.
-
- **Completeness — against the plan:**
- - Every Requirement and every enumerated Edge Case in the plan must have at
- least one test that would fail if the requirement were broken.
- - Every branch introduced in the implementation (error paths, validation
- failures, authorization denials, empty/null handling) must be exercised.
-
- **Completeness — beyond the plan (critical analysis):**
-
- Read the implementation diff and actively try to break it. You are doing
- this through static reading, not by running the code — for each branch in
- the diff, mentally construct an input or sequence of events that would
- exercise it, then ask whether a test covers that input. The plan is a
- starting point, not a ceiling. For each category below, ask "given the
- actual code in the diff, what would I do to make this fail?":
-
- - **Implicit branches**: `if`, `when`/`switch`, `?:`, early returns, exception
- handlers introduced by the implementation but not called out in the plan.
- Each one is a behaviour worth testing.
- - **Boundary values**: 0, 1, max, min, off-by-one, empty collections,
- single-element collections, exactly-at-limit vs just-over-limit. Plans
- rarely enumerate these exhaustively.
- - **Input shapes the plan didn't mention**: null, blank strings, whitespace,
- unicode, very long strings, leading/trailing spaces, mixed case, duplicates,
- unsorted input.
- - **State and concurrency**: stale reads, double submits, retries on the same
- resource, partial writes, what happens if the operation is invoked twice.
- - **External dependency failure modes**: timeouts, 4xx vs 5xx responses,
- malformed payloads, slow responses — wherever the code calls out.
- - **Security-adjacent gaps**: authz checks on every entry point, not just the
- one the plan mentioned; injection-shaped inputs on any field that hits a
- query, template, or shell.
-
- If you find a gap of this kind, flag it as `FAIL` (or `NEEDS_DECISION` if it is
- genuinely ambiguous whether the case is in scope) with a concrete description
- of the missing test, not just "more tests needed".
-
- ### Privacy and Data Protection
+ # /code-critic
- Prefer build-enforced tests over prose here (same doctrine as the
- build-enforced guidance below). Any project holding personal data should
- implement these three fitness tests — until they exist, they are backlog
- items, not per-PR checklist prose:
+ Review code changes against project standards.
- 1. **Deletion by design** — every table with a user FK either cascades on
- account deletion or appears in an explicit, commented allowlist.
- 2. **Public-surface whitelist** — the model rendered on public/
- unauthenticated surfaces is a distinct type whose fields are asserted
- against a whitelist, so a sensitive field cannot be added silently. (If
- public pages currently render from the full domain object, that
- restructuring is the prerequisite — worth its own task.)
- 3. **No personal data in logs** — log statements must not reference
- sensitive/user-content field symbols or contact-detail fields.
+ Stance: the implementation is a hypothesis under attack. Assume something is
+ wrong and try to disconfirm it; don't verify that it "looks reasonable". No
+ fault found after genuine effort → state that explicitly (*Disconfirmation
+ Attempt*). Apply the same stance to the tests (see *Tests*).
- For any of these that IS implemented, the reviewer's only duty is the
- standard build-enforced check: the diff must not WEAKEN the enforcement
- (deleting or disabling the test, adding an unexplained allowlist entry,
- restructuring code out of the test's scan scope). A weakened enforcement
- is `FAIL`. For any not yet implemented, check the corresponding invariant
- by hand only on diffs that touch it (new user-FK tables; public-view
- rendering; new/changed log statements).
+ ## Input
- Prose residue the tests cannot catch (diff-scoped, manual):
+ - Plan text (optional; inline or file path)
+ - Test evidence: summary of the latest full test run (optional)
+ - The diff is not an input: step 1 selects it
- - **Indirect serialization into logs** — logging rich objects (`toString()`
- of an entity, dumped request params) that embed personal data. `FAIL`.
- - **Personal data in URLs** — emails, phone numbers, or values embedding
- them in query params or path segments; URLs land in access logs and
- browser history. `FAIL`.
+ ## Steps
- Consent, retention, and data-classification rules are deliberately NOT
- per-PR review items — they are product flows to be built as tasks and then
- protected by tests, not per-diff checklist prose.
+ ### 1. Select the diff
- ---
+ - Work committed: `git diff <default-branch>...HEAD` or
+ `git log -p <default-branch>..HEAD`; default branch from `AGENTS.md` →
+ *Commands*
+ - Work uncommitted: working-tree diff
+ - Unsure → `git status`, `git log --oneline`
+ - You may read any file in the repo; the diff is the unit under review
- ## Project-Specific Rules
+ ### 2. ADRs
- This skill is project-agnostic; each project extends it without editing it.
- Check the repo-root `AGENTS.md` (not a module-level one) for a **Review &
- Planning Guidance** section. If it has a
- "Code review guidance" entry, read the file it names. If `AGENTS.md` has no
- such section, or the section exists but has no "Code review guidance"
- entry, fall back to checking `docs/agent-rules/code-critic.md` directly. If
- an entry names a file that doesn't exist, treat it the same as "no file
- found" below, but say so specifically (a named-but-missing file is a broken
- pointer worth surfacing, not just an absent extension).
+ - `docs/adr/` exists → list the ADRs read by number in the output; none
+ relevant → say so explicitly (silence reads as skipped)
+ - Diff contradicts an ADR → `FAIL`; quote the ADR clause and the diff line
- If a file is found, apply every constraint in it alongside the base
- standards above: where it states a severity, use it exactly as stated
- (including the don't-weaken doctrine for anything it marks as
- build-enforced); where it states none — a pre-existing project doc without
- this skill's format, such as a style guide, `CONTRIBUTING.md`, or an
- engineering handbook — judge severity yourself using this skill's normal
- `PASS`/`FAIL`/`NEEDS_DECISION` framework. Either way, treat any PRIVACY
- anchors it contains as binding on the privacy rules above (sensitive
- categories, public surfaces, existing fitness tests), regardless of
- whether the rest of the file follows this skill's structure.
+ ### 3. Plan compliance (skip entirely if no plan)
- If no file is found either way, proceed with the base standards alone and
- say so in the review output (one line) — the gap should be visible, not
- silent.
+ Per plan section:
+ - **Approval Summary / Acceptance Criteria**: every `AC-<slug>-n` has a
+ committed test tagged `[AC-<slug>-n]` that would fail if the criterion
+ broke. Missing → `FAIL`
+ - **Edge Cases**: same for every `EDGE-<slug>-n` / `[EDGE-<slug>-n]`.
+ Missing → `FAIL`
+ - **Contract** (skip if "None"): diff's routes, fields/params, response
+ shapes, error rendering, schema match. Undiscussed deviation → `FAIL`
+ - **Types anywhere in the plan** (Contract, Approach, Requirements, even
+ when Contract is "None"): nullable/non-null and optional/required are part
+ of the contract
+ - Diff every parameter/field type the plan states against the actual
+ signature; don't infer from the tests' inputs
+ - Mismatch either way → `FAIL`, even if tests pass, unless the review input
+ documents an approved deviation
+ - **Requirements**: all addressed (source of truth for what to build)
+ - **Approach**: code follows it; no undiscussed alternative design; all plan
+ steps accounted for
+ - **Files**: diff matches the manifest. File in diff but not listed (or
+ listed but untouched) → undiscussed change; flag, judge scope
+ - **Out of Scope**: don't flag listed items as missing; flag code straying
+ into it as scope creep
+ - **Test Strategy**: cross-reference against actual tests
+ - Quote the exact plan line and the exact violating diff line; never
+ paraphrase the plan
- ---
+ ### 4. Test evidence
- ## Review Checklist
+ - Judge test coverage by reading the code and tests; never run the suite
+ - Test run summary provided → treat it as the implementer's record that the
+ suite ran and passed, not as independent proof
+ - No summary provided → raise Open Question: "no evidence the test suite ran
+ on the reviewed state"; never assume green
- Review every change against this checklist. For each item, state one of:
+ ### 5. Apply standards
- - `PASS` — the rule applies to this diff and the diff complies. Cite specific
- diff lines that demonstrate compliance for non-trivial items (test
- coverage, edge cases, error paths, security-adjacent code). Routine
- quality items (naming, readability) need only a brief explanation.
- - `PASS (N/A)` — the rule does not apply to this diff (e.g., security checks
- on a CSS-only change). Briefly say why.
- - `FAIL` — rule violated, and you can cite the line and the rule that breaks.
- Reserve `FAIL` for findings you are confident in. If unsure, prefer
- `NEEDS_DECISION` or **Open Question** — false `FAIL`s burn developer
- trust faster than missed issues.
- - `NEEDS_DECISION` — the correct approach is ambiguous and requires
- developer input. State the options.
- - **Open Question** — concerns where the diff *might* be wrong but you
- cannot verify from source alone (depends on runtime config, prod data
- shape, deployment topology, external service behaviour). State the
- question and what evidence would resolve it. Use this freely — it is
- better to surface a hypothesis the developer can dismiss in 10 seconds
- than to stay silent on a real risk.
+ **Single responsibility**
+ - Functions do one thing. Branch for a different concern (admin path in a
+ user path, parsing inside persistence):
+ - New function with mixed concerns → `FAIL`
+ - Existing function extended with an unrelated branch → `FAIL`
+ - Borderline, extraction hurts readability → `NEEDS_DECISION`
+ - Classes: too many responsibilities = more than one independent reason to
+ change
+ - New class with too many → `FAIL`
+ - Change significantly worsens an existing violation → `FAIL`
+ - Change extends an oversized class without making it meaningfully worse →
+ `NEEDS_DECISION` (flag the debt; developer chooses refactor / tech debt /
+ accept)
- ### Architecture
+ **Error handling**
+ - No generic catch-all in business logic. At process boundaries (top-level
+ controllers, scheduled jobs, async entry points) a catch-all that logs and
+ translates to a domain error is fine; judge by where it lives
+ - Every error carries context: what operation failed and why
+ - Critical-path errors logged with structured fields
- _If a layer/architecture fitness test enforces boundaries (see the layer
- rule in the AI Workflow plugin's own documentation), do NOT re-derive them
- by hand — verify only that the diff does not **weaken** it: deleting or
- disabling the test, widening a package glob, adding an unexplained
- exemption, or moving code out of the scanned layer. A weakened enforcement
- is `FAIL`._
+ **Naming**
+ - Functions say what they do (`calculateShippingCost`, not `calc`/`process`)
+ - Booleans read as questions (`isValid`, `hasPermission`)
- - [ ] Changes respect service boundaries and existing ADRs
- - [ ] No business logic in infrastructure or API layers
- - [ ] No new dependencies introduced without justification
+ **Tests** (you own quality AND completeness)
+ - Quality:
+ - Every public function with non-trivial behaviour has happy-path and edge
+ tests. Exempt: trivial delegators, generated code, plain data classes,
+ pure getters. State each exemption and why
+ - Names describe the scenario (`test_order_fails_when_inventory_insufficient`)
+ - Given-When-Then; test behaviour, not implementation details
+ - Check what each assertion actually compares, not its name/comment. A test
+ that passes regardless of correctness (expression compared to itself)
+ proves nothing
+ - Diff weakens, loosens, or deletes a plan-derived test (esp. `[AC-…]`) to
+ pass the suite → `FAIL`, unless the input documents an approved plan
+ deviation
+ - Completeness, against the plan: every Requirement and Edge Case has a test
+ that would fail if it broke; every branch the implementation introduces
+ (error paths, validation failures, authorization denials, empty/null) is
+ exercised
+ - Completeness, beyond the plan: statically, per branch in the diff, build an
+ input or event sequence that exercises it and ask whether a test covers it.
+ For each category ask "what would I do to make this fail?":
+ - Implicit branches (`if`, `when`/`switch`, `?:`, early returns, exception
+ handlers) not in the plan
+ - Boundary values: 0, 1, max, min, off-by-one, empty, single-element,
+ at-limit vs just-over
+ - Input shapes: null, blank, whitespace, unicode, very long, leading/trailing
+ spaces, mixed case, duplicates, unsorted
+ - State/concurrency: stale reads, double submit, retries, partial writes,
+ invoked twice
+ - External dependency failure: timeouts, 4xx vs 5xx, malformed payloads,
+ slow responses
+ - Security-adjacent: authz on every entry point (not just the planned one);
+ injection-shaped input on any field reaching a query, template, or shell
+ - Gap found → `FAIL` (or `NEEDS_DECISION` if scope is ambiguous) with a
+ concrete description of the missing test
- ### Plan Compliance _(skip if no plan was provided)_
- - [ ] Implementation follows the Approach described in the plan — no undiscussed
- design alternatives introduced
- - [ ] All steps in the plan are accounted for in the changes
- - [ ] Every acceptance criterion (`AC-<slug>-n`) in the Approval Summary
- maps to a committed test tagged `[AC-<slug>-n]` that would fail if the
- criterion were broken
- - [ ] Every edge case (`EDGE-<slug>-n`) in the Edge Cases section maps to a
- committed test tagged `[EDGE-<slug>-n]` that would fail if the handling
- strategy were broken
- - [ ] Diff matches the plan's Contract section — routes, fields, response
- shapes, error rendering, schema _(skip if Contract is "None")_
- - [ ] Every parameter/field type the plan states anywhere (nullable vs
- non-null, optional vs required) matches the diff's actual signature
- - [ ] All requirements from the Requirements section are addressed
- - [ ] Files touched in the diff match the plan's Files manifest — no undiscussed
- files (a file in the diff but not in the manifest is an undiscussed change)
- - [ ] No code introduced inside the plan's Out of Scope boundary
+ **Privacy and data protection**
+ - Prefer build-enforced tests. Any project holding personal data should have
+ three fitness tests (backlog items until they exist, not per-PR prose):
+ 1. Deletion by design: every table with a user FK cascades on account
+ deletion or is in an explicit, commented allowlist
+ 2. Public-surface whitelist: the model rendered on public/unauthenticated
+ surfaces is a distinct type with fields asserted against a whitelist
+ (public pages rendering from the full domain object → restructuring is
+ the prerequisite, its own task)
+ 3. No personal data in logs: log statements don't reference
+ sensitive/user-content or contact-detail fields
+ - Implemented ones: only check the diff doesn't WEAKEN them (deleting or
+ disabling the test, unexplained allowlist entry, code restructured out of
+ scan scope) → weakening is `FAIL`
+ - Not implemented: check the invariant by hand only on diffs touching it
+ (new user-FK tables; public-view rendering; new/changed log statements)
+ - Manual residue, `FAIL`:
+ - Indirect serialization into logs (rich-object `toString()`, dumped
+ request params)
+ - Personal data in URLs (emails, phones, or values embedding them in query
+ params or path segments)
+ - Consent, retention, data-classification: NOT per-PR items (product flows,
+ built as tasks then protected by tests)
- ### Code Quality
- - [ ] Every function has a single responsibility
- - [ ] Classes have a single reason to change — new classes assessed per the Single
- Responsibility standard above; existing classes flagged if the change worsens
- the violation
- - [ ] Error handling is specific, not generic catch-all
- - [ ] Code is readable — a new team member could follow the logic without extra context
- - [ ] No implicit assumptions that should be explicit (add comments or types)
+ **Architecture**
+ - A layer/architecture fitness test exists → don't re-derive boundaries by
+ hand; only check the diff doesn't weaken it (deleting/disabling it,
+ widening a package glob, unexplained exemption, code moved out of the
+ scanned layer) → `FAIL`
- ### Edge Cases
- - [ ] All edge cases identified in the plan (`EDGE-<slug>-n`) are explicitly
- handled _(if plan provided)_
- - [ ] Null/empty/zero/negative inputs are handled where applicable
- - [ ] Concurrent access scenarios are considered where applicable
- - [ ] Failure modes of external dependencies are handled (timeouts, retries, fallbacks)
+ ### 6. Project rules
- ### Tests
- - [ ] Tests cover the happy path
- - [ ] Tests cover every Requirement and Edge Case identified in the plan _(if plan provided)_
- - [ ] Every branch introduced by the implementation (error paths, validation
- failures, authorization denials, null/empty handling) is exercised
- - [ ] Boundary values are tested where applicable (0, 1, max, min,
- off-by-one, empty/single-element collections, exactly-at-limit vs
- just-over-limit)
- - [ ] Implicit input shapes are covered where applicable (null, blank,
- whitespace, unicode, very long, duplicates, mixed case)
- - [ ] State/concurrency scenarios are covered where applicable (double
- submit, retry, partial writes, idempotency)
- - [ ] External dependency failure modes are covered where the code calls
- out (timeouts, 4xx/5xx, malformed responses)
- - [ ] Critical analysis performed: list any plausible scenarios the plan did
- not enumerate that should also be tested, and flag missing ones as `FAIL`
- - [ ] Test names describe the scenario being tested
- - [ ] Tests follow the Given-When-Then pattern
- - [ ] No tests that only verify implementation details
- - [ ] No tautological assertions — each test's assertion compares independent
- expressions and could fail if the behaviour were broken
+ - Repo-root `AGENTS.md` (not module-level) → *Review & Planning Guidance* →
+ "Code review guidance" entry → read the file it names
+ - No such section/entry → `docs/agent-rules/code-critic.md`
+ - Entry names a missing file → treat as no file found, and say so
+ specifically (broken pointer)
+ - File found:
+ - Apply every constraint alongside the base standards (step 5)
+ - Stated severity → use as stated (incl. don't-weaken doctrine for
+ build-enforced items)
+ - No stated severity (style guide, `CONTRIBUTING.md`, handbook) → judge
+ with `PASS`/`FAIL`/`NEEDS_DECISION`
+ - PRIVACY anchors in it bind the privacy rules in step 5 regardless of
+ format
+ - No file found → base standards only; say so in one line in the output
- ### Project-Specific
- - [ ] Every applicable item from the project's review guidance (via
- `AGENTS.md`'s Review & Planning Guidance section, or
- `docs/agent-rules/code-critic.md` if unspecified) evaluated — or its
- absence stated as one line in the output
+ ### 7. Review Checklist
- ### Privacy and Data Protection
- - [ ] Privacy fitness tests not weakened — no deleted/disabled test, no
- unexplained allowlist entry, no code restructured out of scan scope
- - [ ] Invariants without a backing test yet, checked by hand where the diff
- touches them: deletion-by-design (new user-FK tables), public-surface
- whitelist (public-view rendering), no personal data in logs (new/changed
- log statements)
- - [ ] No indirect serialization of personal data into logs (rich-object
- `toString()`, dumped request params) and no personal data in URLs
+ Evaluate every item; state a verdict for each.
- ### Security (general)
- - [ ] No secrets or credentials in code
- - [ ] Input validation on all external inputs
- - [ ] Authorization checks where required
+ Verdicts:
+ - `PASS`: applies and complies. Non-trivial items (test coverage, edge cases,
+ error paths, security-adjacent code): cite diff lines. Routine items:
+ brief note
+ - `PASS (N/A)`: doesn't apply; say why
+ - `FAIL`: rule violated, with a citable line and rule. Only when confident;
+ unsure → `NEEDS_DECISION` or Open Question (false `FAIL`s burn trust faster
+ than misses)
+ - `NEEDS_DECISION`: ambiguous, needs developer input; state the options
+ - Open Question: diff might be wrong but unverifiable from source (runtime
+ config, prod data shape, deployment topology, external behaviour); state
+ the question and the evidence that would resolve it. Use freely
- ---
+ Items:
+ - **Architecture**: respects service boundaries and ADRs · no business logic
+ in infrastructure/API layers · no new dependency without justification
+ - **Plan compliance** (if plan), one verdict each:
+ - every `AC-<slug>-n` has a committed `[AC-<slug>-n]` test that would fail
+ if the criterion broke
+ - every `EDGE-<slug>-n` has a committed `[EDGE-<slug>-n]` test that would
+ fail if the handling broke
+ - Contract matches (skip if "None")
+ - plan-stated types match the signatures
+ - Requirements addressed
+ - Approach followed, all plan steps accounted for
+ - Files match the manifest
+ - nothing inside Out of Scope
+ - **Code quality**: single responsibility (functions, classes) · specific
+ error handling · readable by a new team member · no implicit assumptions
+ that should be explicit comments/types
+ - **Edge cases**: plan's `EDGE-<slug>-n` explicitly handled (if plan) ·
+ null/empty/zero/negative · concurrent access · external dependency failure
+ (timeouts, retries, fallbacks), each where applicable
+ - **Tests**: happy path · every plan Requirement and Edge Case (if plan) ·
+ every introduced branch · boundaries · input shapes · state/concurrency ·
+ dependency failure modes (each where applicable) · critical analysis done,
+ unenumerated scenarios listed, missing ones `FAIL` · scenario-describing
+ names · Given-When-Then · no implementation-detail tests · no tautological
+ assertions
+ - **Project-specific**: every applicable item from step 6 evaluated, or its
+ absence stated in one line
+ - **Privacy**: fitness tests not weakened · hand-checked invariants where the
+ diff touches them · no indirect serialization into logs, no personal data
+ in URLs
+ - **Security**: no secrets/credentials in code · input validation on all
+ external inputs · authorization where required
- ## Output Format
+ ## Output
```
### Review Summary
[1-2 sentence overall assessment]
### PASS
- - [item]: [explanation; for non-trivial items, cite diff lines like
- src/foo/Bar.ext:42-58]
+ - [item]: [explanation; non-trivial items cite diff lines like src/foo/Bar.ext:42-58]
### PASS (N/A)
- - [item]: [why this category does not apply to this diff]
+ - [item]: [why it doesn't apply]
### FAIL
- [item]: [what's wrong, suggested fix, diff line reference]
### NEEDS_DECISION
- - [item]: [the ambiguity and the options available]
+ - [item]: [the ambiguity and the options]
### Open Questions
- - [hypothesis]: [the question you cannot answer from source alone, and the
- evidence that would resolve it — runtime config, prod data, deployment
- topology, external service behaviour]
+ - [hypothesis]: [the question, and the evidence that would resolve it]
### ADRs Reviewed
- [List ADR numbers you read, or state "none relevant" with one sentence why.]
+ [ADR numbers read, or "none relevant" + one sentence why.]
### Disconfirmation Attempt
[REQUIRED if FAIL and NEEDS_DECISION are both empty]
- Describe specifically what you tried in order to find issues — which
- inputs you considered, which failure modes you probed, which edge
- cases you inspected, which diff sections you examined. A bare
- "looks good" or "no issues found" is not acceptable. State the methods
- you applied (pre-mortem, boundary probe, dependency-failure probe,
- adversarial input probe) and the specific outcomes.
+ What you specifically tried: inputs considered, failure modes probed, edge
+ cases inspected, diff sections examined, methods applied (pre-mortem,
+ boundary probe, dependency-failure probe, adversarial input probe) and
+ their outcomes. "Looks good" / "no issues found" is not acceptable.
```
- If you find any `NEEDS_DECISION` items or **Open Questions**, clearly label
- them so the orchestrating agent can surface them to the developer. Do not
- make these decisions yourself.
-
- Do NOT modify any code. Output only the review.
+ - Label `NEEDS_DECISION` items and Open Questions clearly for the
+ orchestrating agent; never decide them yourself
+ - Modify no code. Output only the review