Concerns
Last updated
Every card's rule on one page, and each row links to the full card. Pick one or more concerns to scope a review, such as performance only. A card matches when it lists any picked concern, topic, or level. The picks go in the address, for example ?concern=security,performance&level=function, so you can share the view. Add .md or use cards.json for the same view as text or JSON.
How to report each check
Report each check as PASS, FAIL, or N/A with file:line evidence. A FAIL carries the card's severity. Any block FAIL means request changes. A should-fix or discuss FAIL goes in the review but does not block.
Verdict: request changes - change, function - 2 block, 1 should-fix FAIL, 1 PASS, 14 N/A
FAIL [block] chg-expand-contract - src/a.py:42 - renames the column and drops the old one in one migration
FAIL [block] svc-sqli-authn - src/db.py:88 - proven: builds the WHERE clause with an f-string from request.args
FAIL [should-fix] chg-one-concern - src/b.py:7 - a logging rewrite rides along with the bug fix
PASS chg-breaking-change-taxonomy - src/c.py:15 - no signature or return shape changes
N/A: 14 cards, applies_when does not holdFilters
Concerns
Levels
Topics
A card appears under each concern or topic it lists, so a group view can repeat a card.
Checklist
- code-a11y-check-in-ci should-fixRun an automated accessibility check, such as axe on rendered pages, in the automated tests, and fail the test on a violation.
- code-adr discussKeep a short written record for each significant design choice (datastore, framework, deviation from a pattern) that states the context, the decision, and its consequences.
- code-build-hermetic should-fixBuild from declared inputs only, so that the same source revision gives the same artifact.
- code-ci-gates should-fixRequire review and passing build, tests, lint, and type checks on the default branch before merge, and leave nothing mechanical to reviewer vigilance.
- code-consistency-drift discussFor each recurring concern (errors, config, HTTP clients, logging), make one pattern the standard instead of leaving several as equal peers.
- code-dead-code should-fixDelete unreferenced functions and variables, and the branches of expired feature flags.
- code-dependency-licence-sbom should-fixGenerate an SBOM, and scan dependencies for known vulnerabilities on every change or on a schedule. Each ask is judged separately: name which one failed on the FAIL line.
- code-dependency-pinning blockCommit a lockfile with hashes and install from it in CI.
- code-docs-refs-resolve should-fixRun a link check in CI over the docs, so that every relative link and anchor they cite resolves.
- code-file-lines-ceiling discussSet a file-length limit in the linter (Pylint and SonarSource default to 1,000 lines), keep hand-written files under it unless a listed exception says otherwise, and split larger files by knowledge owned, not by execution order.
- code-flaky-test-quarantine should-fixReport every test that passes only on retry, move it to a quarantine with a named owner and a ticket, and return it to the merge gate only after it passes many reruns.
- code-perf-budget-in-ci should-fixWrite the performance budget down as a CI check that fails the build when it is exceeded.
- code-release-gated-on-ci should-fixMake a release or publish job depend on the checks passing for the tagged commit, never on the tag alone.
- code-rule-has-enforcer should-fixBack each written repo rule that a type, lint or CI check could enforce with that check, not with a line in an instruction file or a repeated review comment.
- code-scoped-validation-loop discussDocument a command that checks one package or path, with readable output, so a small change does not need the full-repo run.
- code-secret-scan blockScan for committed credentials, and treat any hit as leaked: revoke and replace it first. With no scanner present and no secret found, the FAIL is the missing control; evidence is "absent in <paths>". A platform scanner (GitHub secret scanning with push protection, GitLab secret detection) counts when it is enabled on the repo and covers history.
- code-test-fixtures-built-once should-fixBuild an expensive fixture once per test run, and reset state between tests with a rollback or a truncate, never a rebuild.
- code-test-selection-on-pr discussWhen the full suite is slower than the pull-request feedback target, run only the tests the change affects on the pull request, and run the full suite before deploy or on a schedule.
- code-vuln-remediation-window should-fixWrite down how long a known-vulnerable dependency may stay unfixed and fix or upgrade it inside that window.
- code-workflow-supply-chain blockPin every CI action to a full commit SHA, and keep code from an unreviewed change out of any job that holds secrets or can deploy.
- code-workload-identity should-fixExchange the platform's OIDC token for a short-lived cloud credential, and pin the trust policy to the workload.
- fn-aria-role-has-state-and-keys should-fixWhen a native element cannot do the job, give the custom widget the state attribute and the keys its role promises.
- fn-bool-arg-at-callsite discussReplace a boolean flag argument with an enum, keyword-only argument or two functions.
- fn-bounded-read-fails-at-cap should-fixWhen a size cap is reached, return an error; never hand back the first N bytes as if they were the whole input.
- fn-colour-not-sole-cue should-fixPair every colour that carries meaning with a second cue: text, an icon, a shape, or an underline.
- fn-comments-explain-why should-fixWrite comments that give a reason, a constraint, or a trade-off, and never restate what the next line does.
- fn-comments-survive-context should-fixWrite comments that remain true without outside context: no "currently", "for now" or "see the PR", and give a TODO the date or event that ends it.
- fn-confine-file-path blockResolve the final path and check that it stays inside the intended base directory before using it.
- fn-constant-time-secret-compare should-fixCompare a secret, token or MAC with the platform's constant-time function, never with
==or!=. - fn-csprng-for-secrets blockDraw every security-relevant random value from the platform CSPRNG.
- fn-destructive-confirm-or-undo should-fixMake a destructive action reversible with undo, or ask the user to confirm it before it runs.
- fn-dialog-focus-managed blockWhen a modal opens, move focus into it and keep Tab inside it. Make Escape close it.
- fn-disclosure-hides-only-secondary should-fixDo not hide a required field or information most users need behind a disclosure that starts closed.
- fn-distinct-types-for-ids should-fixGive arguments with different meanings distinct types, so a call that swaps them fails to type-check.
- fn-english-identifiers discussWrite identifiers and comments in English, unless the project policy names another language.
- fn-error-says-what-and-how should-fixShow each validation error next to its field, in plain words that name what is wrong and how to fix it.
- fn-fetch-only-needed-data should-fixFilter, count, and aggregate in the query, and select only the columns the code uses.
- fn-focus-indicator-visible blockKeep a visible focus indicator on every focusable element. Never set
outline: nonewithout a replacement. - fn-form-control-has-label blockTie every form control to a visible
<label>, withforand a matchingidor by wrapping it. A placeholder is not a label. - fn-guard-uri-decoding should-fixWrap
decodeURIComponenton user input in atry/catch, or parse withURLSearchParams, so that a malformed%sequence cannot throw. - fn-handle-rejected-promises should-fixHandle the rejection of every promise you start:
awaitit insidetry/catch, end the chain with.catch(), or return it to a caller that does. - fn-header-value-encoding blockSet every response header through the framework's header API, never by writing to the connection, and reject or encode CR and LF in any request-derived value.
- fn-heading-structure should-fixMark every heading with a real
<h1>to<h6>element, not a styleddiv,span, orp. - fn-img-alt-text should-fixGive every
<img>analtattribute: text that serves the image's purpose, oralt=""when the image is decorative. - fn-independent-work-concurrent should-fixStart independent I/O together and wait for all of it; run calls in sequence only when one needs the result of another.
- fn-join-dont-concat-in-loop should-fixBuild a string from a loop with a builder or a join, never with repeated
+=. - fn-jwt-verify-pinned blockVerify the signature against a fixed list of accepted algorithms, and check
issandaud, before reading any claim. - fn-keep-input-on-error should-fixAfter a failed validation or submit, show the form again with every value the user entered, correct or not.
- fn-label-above-field discussPut the visible label of a text input, select, or textarea directly above it.
- fn-length-budget discussSplit a function that passes the project's length limit (about 40 lines if it sets none) unless its body is one simple operation or one flat dispatch.
- fn-link-url-scheme-allowlist should-fixParse a URL that comes from data and allow only
https:(andhttp:ormailto:where needed) before you set it as a link target. - fn-mask-credentials-in-output should-fixMask credentials in list, show and debug output (keep only the last four characters), and print a full value only behind an explicit flag.
- fn-name-intermediate-conditions discussName each compound condition by assigning its sub-conditions to booleans that say what they mean.
- fn-no-blocking-call-in-async-code blockNever make a blocking I/O call or run long CPU work directly in async code; use the async API or hand the work to a thread or worker.
- fn-no-caller-mutation should-fixDo not mutate a parameter or an object the caller owns, unless the function is documented as mutating it.
- fn-no-check-then-act-across-await should-fixMake check-and-write one atomic operation where the state lives, and never split it across a suspension point.
- fn-no-eval-untrusted blockNever pass untrusted text to
eval,exec,new Function, or a template compiler. Pass it to a fixed template or a parser as data. - fn-no-getattr-for-known-names discussUse plain field access, and reserve dynamic access for genuinely dynamic names.
- fn-no-magic-values should-fixGive every meaningful literal a name: an enum member or a constant.
- fn-no-mass-assignment blockBind request data to a DTO or an explicit field allowlist, never straight onto the model.
- fn-no-native-deserialise-untrusted blockParse untrusted input with a data-only format, never with a native object deserialiser.
- fn-no-positive-tabindex should-fixWrite the DOM in reading order and never set
tabindexabove 0. - fn-no-prototype-pollution blockNever write an untrusted key into a plain object. Use a
Map, an object fromObject.create(null), or an allowlist of keys. - fn-no-raw-html-sink blockWrite untrusted text through an encoding sink (
textContent, auto-escaped template), never through a raw HTML sink. - fn-no-shell-with-input blockStart processes with the program and each argument as separate list items, and never through a shell string.
- fn-object-level-authz blockCheck that the caller may act on the specific record before returning or changing it.
- fn-parameter-limit should-fixSet a parameter-count limit in the project's linter, and keep signatures within it.
- fn-password-slow-hash blockHash passwords with Argon2id (or scrypt, bcrypt, PBKDF2) and a per-password salt from the library.
- fn-redirect-target-allowlist should-fixRedirect only to a local path or to a host on a server-side allowlist, never to a URL taken from the request as is.
- fn-reduced-motion-respected should-fixSwitch off or replace large, repeating, or interaction-triggered motion when
prefers-reduced-motion: reduceis set. - fn-regex-compiled-once should-fixCompile a regular expression once, at module or startup level, and reuse it.
- fn-rerun-safe-after-crash should-fixMake a state-changing operation give the same result on a second run and after a crash at any step, by deriving each step from current state and making leftovers recognisable as stale.
- fn-response-fields-explicit should-fixReturn a response type that lists each field, never the stored model or a generic dump of it.
- fn-specific-exceptions-only should-fixCatch only the specific exception you can handle in business code.
- fn-status-announced-live-region should-fixAnnounce an async status message through a live region (
role="status"orrole="alert"), and put arole="status"oraria-liveregion in the markup before its text changes. - fn-target-size should-fixMake each pointer target at least 24 by 24 CSS pixels, or space it so that a 24 px circle centred on it touches no other target and no other undersized target's circle.
- fn-test-behaviour-not-implementation should-fixAssert what a caller can observe through the public interface, so a change that keeps behaviour does not break the test.
- fn-test-oracle-independent should-fixTake a test's expected value from the requirement, not from the code under test.
- fn-tls-verify-on blockLeave certificate and hostname verification on in every environment that ships.
- fn-variants-as-tagged-union should-fixModel variants as a tagged union, and make every switch over it fail the build when a variant is unhandled.
- fn-xml-no-external-entities blockParse untrusted XML with external entity resolution turned off, for example through a hardened parser such as
defusedxml. - inc-perf-fix-has-profile-evidence should-fixTie the performance fix to evidence that names the bottleneck: a profile, a trace, or a USE check.
- inc-rollback-path-tested should-fixExercise each mitigation that a runbook names (rollback, failover, flag off) on a regular schedule.
- mod-behaviour-lives-with-state discussPut the invariants and calculations that read only one object's fields on that object.
- mod-bounded-fan-out discussSet a limit on how many other types or modules one unit depends on, and split a unit that passes it.
- mod-class-size-budget discussSplit a class that passes the project's size limit for fields, public methods or lines, unless it is a data record.
- mod-colour-tokens-meet-contrast should-fixMake every text and background token pair meet 4.5:1 (3:1 for large text), and every border, icon, and focus colour meet 3:1 against its neighbour.
- mod-deep-modules discussPrefer a small interface that hides its implementation, and add a member only when callers need it.
- mod-derive-dont-duplicate should-fixDerive a type, list or enum from the schema or list that owns it, or add a build check that fails when the two disagree.
- mod-fowler-smells discussName the smell, point to the line, and suggest the refactoring; do not file smells as taste.
- mod-inject-boundary-collaborators should-fixInject boundary collaborators through the constructor; do not construct them inside or reach for a global.
- mod-internals-unreachable should-fixKeep a module's internals unimportable and untouched from outside it. A caller uses the public surface, not a private file or member.
- mod-law-of-demeter discussCall methods on your direct collaborators, and do not call a method on an object that another call returned (a chain of two or more getters).
- mod-layers-point-inward should-fixMake dependencies point inward: surface, then logic, then boundary.
- mod-no-import-cycles should-fixKeep the dependency graph between modules or packages acyclic, and break a cycle by moving the shared part into a third module that both depend on.
- mod-no-import-side-effects should-fixKeep I/O at the edges: importing a package must not touch the network, read files, or read the environment.
- mod-no-logic-in-constructors should-fixAssign only in constructors, and put I/O, parsing, and heavy computation in a named factory.
- mod-no-module-mutable-state should-fixKeep no mutable state at module level; hold it on an instance.
- mod-no-shotgun-surgery discussKeep one decision in one module, and when a single change needs edits in many classes, move the scattered parts together.
- mod-no-utils-grab-bag should-fixPut a helper in the module that owns the concept, or in a new module named after the concept.
- mod-no-wrong-abstraction should-fixInline an abstraction that has grown flags for its callers.
- mod-one-name-per-concept should-fixUse one name for one concept across the codebase.
- mod-pooled-clients-built-once should-fixBuild pooled clients once at startup and reuse them.
- mod-proto-enum-zero-unspecified should-fixGive every protobuf enum a zero value named
<ENUM>_UNSPECIFIEDwith no real meaning. - mod-single-writer-per-state should-fixLet only one writer change a piece of state at a time, through a single owner, a queue that serialises the writes, or compare-and-swap, never by convention.
- mod-vetted-crypto-only blockEncrypt with an authenticated mode such as AES-GCM, and never reuse a nonce under one key.
- mod-yagni should-fixDo not build an abstraction or capability for a need that does not exist yet; add it when the need or a second use appears.
- prod-a11y-audit-before-launch should-fixBefore a public launch, run an accessibility audit against WCAG 2.2 AA that includes assistive technology, and link the report in the launch checklist.
- prod-alerts-symptoms-golden-signals should-fixPage on user-visible symptoms, such as error rate and latency, not on causes.
- prod-canary-staged-rollout blockRoll out in stages behind a canary, and abort by rule, not by judgment.
- prod-kill-switch-fallback should-fixMake a risky feature switchable off without a deploy, and exercise every fallback path in test or in production on a schedule.
- prod-latency-slo-percentile should-fixDefine latency SLOs and alerts on high percentiles, never on the mean.
- prod-load-test-before-launch should-fixLoad test before launch, past the expected peak, with pass and fail thresholds written down.
- prod-profile-on-demand discussMake a CPU and memory profile of a production instance obtainable, through a continuous profiler or a private profile endpoint.
- prod-shadow-compare-before-cutover should-fixBefore you move traffic to a new system, run it beside the old one on live or captured production traffic, diff the results, and cut over only when every mismatch is fixed or explained.
- prod-slo-error-budget discussDefine an SLO with an indicator and window, and use its remaining error budget to gate risky releases.
- svc-account-linking blockLink a federated identity to an existing account only after proving control of both, and key the link on the pair
issandsub, never on an unverified email or another profile claim. - svc-api-cache-control should-fixSet an explicit
Cache-Controlon every response a cache may store, useprivateorno-storefor user-specific data, addVaryfor any request header that changes the body, keep the origin'sCache-Controlauthoritative at the edge (no minimum TTL or force-cache override), and decide cacheability by the responseContent-Type, not the URL extension. - svc-api-conditional-writes should-fixReturn an
ETagon reads and honourIf-Matchon writes, answering 412 when the entity tag is stale. - svc-api-contract-tests should-fixRun a contract test for each cross-service call, derived from the consumer's real requests, and fail the provider's build when it breaks one.
- svc-api-deprecation-sunset should-fixBefore removing an endpoint, mark it
deprecatedin the spec and sendDeprecationandSunsetheaders. - svc-api-documented-errors should-fixDocument every error status each operation can return, with a schema and one example.
- svc-api-error-code-stable should-fixGive each error a stable machine-readable code that callers branch on, and never make them parse the message text.
- svc-api-key-scope should-fixIssue each API key with the narrowest scopes and a bounded lifetime, and rotate or revoke it after any exposure.
- svc-api-naming-consistent discussUse one casing convention per location (fields, query parameters, headers, paths) across the whole API, and state it in the API guide.
- svc-api-problem-json should-fixReturn errors as
application/problem+jsonwith astatusthat equals the HTTP status, and leave stack traces and internal detail out. - svc-api-retry-after should-fixSend
Retry-Afteron every 429 and 503, and set it no earlier than the time capacity returns. - svc-api-specific-status-codes should-fixReturn the most specific status code that fits: 201 with
Locationfor a create, 405 withAllowfor a wrong method, and a 4xx or 5xx for any failure. - svc-api-versioning-policy should-fixWrite down one versioning scheme for the API, and ship no breaking change inside a version it has published.
- svc-async-content-reserves-space should-fixReserve the space for late-loading content with set dimensions or an aspect ratio, so nothing already on screen moves.
- svc-auth-throttle-generic-errors blockLimit failed attempts per account, and return the same message and status code whether or not the account exists.
- svc-authn-by-default should-fixRequire authentication on every route by default, and mark each public route by name.
- svc-authz-central-deny-default blockRoute every request through one authorization layer that denies when no rule allows it.
- svc-best-effort-optional-deps should-fixGive each call to a non-critical dependency a short budget and a default, so its failure degrades the result instead of failing the critical path, and count every fallback.
- svc-bound-client-controlled-sizes should-fixCap every client-controlled size and count on the server: body bytes, string length, array items, page size and batch size.
- svc-bounded-background-tasks blockCap how many background tasks run at once, and never spawn one per input with no limit.
- svc-cache-key-completeness blockKey every request input that can change the response, and strip any other request value before it reaches a cached body.
- svc-circuit-breaker-bulkhead should-fixGive each critical dependency its own concurrency limit.
- svc-cli-destructive-dry-run should-fixGive a destructive command a preview flag that changes nothing and a flag that skips the confirmation prompt.
- svc-cli-exit-codes-and-streams should-fixExit non-zero when a command fails, and write results to stdout and errors and progress to stderr.
- svc-cli-non-interactive should-fixLet the caller turn every prompt off with a flag or an environment variable, so the command never waits on a terminal.
- svc-cors-allowlist should-fixAllow cross-origin access only to a fixed list of named origins, and never echo the request
Originheader back unchecked. - svc-csp-strict-script-src should-fixSend a
Content-Security-Policywhosescript-srcuses a per-response nonce or script hashes, withobject-src 'none'andbase-uri 'none'. - svc-csrf-state-changing blockRequire a CSRF token (or an equivalent header check) on every cookie-authenticated request that changes state, and never change state on GET.
- svc-decompression-cap should-fixCap the decompressed output of every decoder, and set the cap on the output rather than the compressed input.
- svc-dlq should-fixGive every consumer queue a dead-letter queue and keep a way to replay it after the fix. On an ordered queue, key the group or session to the unit that must stay ordered, so a poison message holds only its own unit.
- svc-export-scope blockScope an export to what the requesting principal may read.
- svc-fail-closed-defaults should-fixShip every security control switched on, with an empty allow-list denying everything.
- svc-host-header-trust blockBuild absolute URLs from configured values, answer only for a
Hoston an allowlist, and takeX-Forwarded-*values only from a trusted proxy. - svc-idempotency-key blockMake every retryable write idempotent: the caller sends a unique key, and a retry with the same key never applies the write twice.
- svc-invalid-input-is-4xx should-fixCheck each caller-supplied value against its allowed domain (range, allowed set, an id that must exist, an encoding the code can handle) at the boundary, and answer a failed check with a 4xx, never a 5xx.
- svc-list-endpoint-paginates should-fixPaginate every list endpoint, with a default page size and a server-side maximum.
- svc-mfa-step-up should-fixRequire a fresh authentication with an already-bound factor before sensitive actions and before adding, replacing or removing an MFA factor; an existing session alone is not enough.
- svc-no-redundant-entry should-fixDo not ask for information the user already gave in the same flow. Fill it in, or let the user pick it.
- svc-no-secrets-in-url should-fixSend tokens, keys, passwords, and personal data in a header or the request body, never in the path or query string.
- svc-oauth-code-flow-binding blockFinish the authorization-code flow with PKCE and a challenge method that keeps the verifier out of the authorization request (
S256), send the exact registeredredirect_uri(a native app on the loopback interface may vary the port), and reject the response unless this transaction'sstateor OIDCnoncematches and the ID token's signature,iss,audandexpcheck out. - svc-password-reset blockMake the reset token single-use and short-lived, and on success revoke every session.
- svc-rate-limit-quota should-fixEnforce a per-tenant quota on shared APIs and queues.
- svc-reflow-and-zoom should-fixMake the page usable at 320 CSS pixels wide and at 200% text zoom, with no sideways scrolling, no clipped content, and no blocked pinch-zoom.
- svc-request-framing blockReject a request that carries both
Transfer-EncodingandContent-Length, or remove one field at the first hop, and parse header framing strictly rather than with a leniency flag. - svc-retry-policy blockRetry only transient errors, with capped attempts and jittered exponential backoff.
- svc-saga-steps should-fixMake steps after the pivot idempotent and retryable, and make every compensation idempotent with a failure path.
- svc-saml-assertion-binding blockVerify the XML signature over the assertion you read, with the IdP's configured key rather than a key carried in the response, then require the assertion's
Audienceand its bearerSubjectConfirmationDataRecipientto name this SP, the responseDestinationto be this endpoint,InResponseToto match your request (absent for an IdP-initiated response),NotOnOrAfterto be current, and the assertion ID to be unseen. These are one step, verify the assertion, and each check is cited. - svc-session-lifecycle blockIssue a new session ID at login, and set
Secure,HttpOnlyandSameSiteon the session cookie. - svc-slow-operation-shows-progress should-fixShow that a slow action is under way, and show its progress when it runs long.
- svc-soft-delete-default should-fixFilter soft-deleted rows out of every read path by default, and make a read that includes them an explicit call.
- svc-sqli-authn blockPass untrusted data to queries as bound parameters, never by string concatenation or formatting.
- svc-stream-dont-materialise should-fixProcess large results as a stream with backpressure; do not load them whole into memory.
- svc-tenant-id-in-telemetry should-fixPut the verified tenant id on every tenant-scoped log, metric and audit record.
- svc-timeouts blockSet an explicit timeout on every remote call.
- svc-tls-modern-only should-fixAccept only TLS 1.2 and TLS 1.3 on servers.
- svc-update-rollback-on-failure should-fixWhen an update fails, restore the previous version instead of leaving a missing or half-written one.
- svc-update-verify-provenance should-fixVerify a downloaded update against a signature, an attestation or a pinned key, or against a checksum that reached you by another route than the file; a checksum fetched from the same host as the file does not count.
- svc-upload-validate-store blockAllowlist the file type, cap the size, and store each upload under a generated name where the server will not execute it.
- svc-webhook-replay-window should-fixReject an inbound signed message whose creation time is outside a short tolerance, and sign that time with the body so it cannot be swapped.
- sys-agent-tool-least-privilege blockGive the agent only the narrow tools and the minimal credentials its task needs.
- sys-cache-bounds-invalidation should-fixBound every cache by size and give its entries an expiry.
- sys-cells-limit-blast-radius discussSplit shared infrastructure into independent cells, each with its own control plane and storage, and route each tenant or request to one cell, so one failure stops only that cell.
- sys-consistent-ui-terms discussUse one label and one icon for the same action and the same concept across all screens.
- sys-fanout-leg-deadlines should-fixGive every leg of a fan-out its own deadline, and decide in code what happens when a leg misses it: a partial result, a hedged request, or an error.
- sys-health-liveness-readiness should-fixWire load balancers and restarters to liveness and local checks only, never to shared-dependency checks.
- sys-index-concurrently should-fixCreate indexes with
CONCURRENTLY, outside a transaction block, and handle a failed build that leaves an INVALID index. - sys-load-shedding-bounded-queues blockBound every queue and reject excess work cheaply.
- sys-lock-fencing blockCheck a correctness lock on the resource side (fencing token or compare-and-set), never by lock possession alone.
- sys-migration-expand-contract blockRun data backfills in batches, in a migration separate from the schema change.
- sys-migration-lock-timeout should-fixSet
lock_timeoutfor the migration session and retry on timeout. - sys-n-plus-one-pooling should-fixFetch related rows in one query or batch, never one query per row.
- sys-pii-minimise-retention should-fixGive every store of personal or sensitive data a retention period, and delete or anonymise the data when it ends.
- sys-prompt-injection blockValidate model output deterministically before code acts on it.
- sys-secrets-and-errors blockFail closed: a validation or auth error must deny, never continue, and an error response must not carry internals such as stack traces, SQL or tokens.
- sys-ssrf blockFetch a user-supplied URL only when its host matches a server-side allowlist.
- chg-agent-grounded-code should-fixVerify that every import and external call the agent wrote exists with that signature.
- chg-agent-independent-review should-fixGet sign-off from a person or a fresh-context reviewer who has the spec but not the author's reasoning; self-review by the writing session does not count.
- chg-approval-tied-to-patch should-fixTreat an approval or verification verdict as current only if the patch is unchanged: compare
git patch-idat the verdict commit with the current head. If the patches differ only in tests, docs, or lint config, the verdict can stand when the built output is the same; any other difference needs a fresh check. - chg-breaking-change-taxonomy blockTreat any change that callers can observe in a signature, return values, error types, defaults, or side effects as breaking until a consumer check says otherwise.
- chg-chestertons-fence should-fixAdd a characterization test before rewriting code you do not understand.
- chg-delete-legacy-after-migration should-fixWhen no consumer sits outside the repo, move every caller to the new API and delete the old one, and the tests that pinned its internals, in the same change.
- chg-devex-breaking-config should-fixFlag a change that renames or removes an environment variable, moves a secret, or remaps a port as breaking for developers and operators, and update every place that documents or sets it.
- chg-expand-contract blockEvolve shared contracts in steps: add the new form beside the old (expand), migrate every consumer, then remove the old form (contract) in a later change.
- chg-match-codebase-pattern should-fixFollow the established pattern nearby.
- chg-migration-add-column-rewrite should-fixAdd the column nullable or with a constant default, then fill volatile, computed, or identity values in batches.
- chg-name-attack-surface should-fixList any new attack surface in the description.
- chg-no-silenced-diagnostics should-fixName the rule, the reason, and a ticket on every suppression; a swallowed error, skipped test, or disabled check is a FAIL unless justified.
- chg-no-special-case-branches should-fixPut a new case behind its own function or type; do not add a one-off branch to a shared flow.
- chg-one-concern should-fixMake each change do one logical thing; if the description needs "and" between unrelated outcomes, split it.
- chg-perf-claim-evidence should-fixBack a performance claim with measured before-and-after numbers.
- chg-proto-no-field-type-change should-fixNever change the type of a protobuf field, switch it between repeated and scalar, or rename it while any consumer reads JSON or text format; add a new field instead.
- chg-proto-reserve-removed-fields should-fixWhen you delete a protobuf field or enum value, add
reservedfor its number and name in the same change, and never reuse a number. - chg-refactor-has-behaviour-pin should-fixPin current behaviour with a characterization test, snapshot or equivalence check before the refactor moves any structure.
- chg-refactor-separate should-fixPut refactors, renames, and reformatting in their own commit or PR, apart from behaviour changes.
- chg-reuse-before-write should-fixDo not add a helper that duplicates one already in the repo; search for it first.
- chg-review-signal discussDo not spend review comments on what a tool enforces or on minor style points; spend them on the findings that matter.
- chg-rollback-path should-fixState in the description how to undo the change.
- chg-size-ceiling discussSplit a change past about 400 changed lines or about 20 files, or say in the description why not; aim for about 200.
- chg-tests-ship-with-change blockShip new or changed behaviour in the same change as a test that fails if the behaviour breaks.
- chg-ui-change-screenshots-and-keyboard-pass should-fixA UI change shows before-and-after screenshots and says what a keyboard-only pass and a 200% zoom check found on the changed screens.
- chg-verify-before-claim blockBack every "works" or "bug" claim with something run: a repro, a test or command output.
- py-cancellation should-fixRe-raise
CancelledError(do not catch it via bareexceptorBaseException), and catchTimeoutErroroutside theasyncio.timeout()block. - py-class-earns-its-instance discussGive a class real state or a collaborator; otherwise write a module function.
- py-docstrings-google discussWrite a Google-style docstring only when it adds what the signature cannot say.
- py-field-only-when-adds discussUse
Field()only when it adds something (a constraint, an alias, or API docs), and set plain defaults directly. - py-httpx-client-lifespan should-fixPass an explicit
httpx.Timeoutto everyhttpxclient. - py-imports should-fixPut imports at module top, absolute only.
- py-modern-typing should-fixWrite
X | Noneand builtin generics, nottypingaliases. - py-no-cast should-fixDo not use
cast(); parse the boundary into a typed model, or narrow withisinstance. - py-no-init-or-model-tests should-fixCover
__init__and plain models through the behaviour that uses them. - py-paths-from-file should-fixResolve paths from
__file__, not the current working directory. - py-pytest-expensive-fixture-scope should-fixGive an expensive pytest fixture
scope="session"or"module"and isolate each test with a rollback, never a schema build or a seed load inside a function-scoped fixture. - py-pytest-parametrize should-fixWrite tests that differ only in inputs and expected values as one
@pytest.mark.parametrizetest. - py-ruff-gate should-fixEnable the Ruff rule sets E, F, I, B, UP, SIM, BLE, TID and D in CI.
- py-task-reference should-fixNever discard the result of
create_task; keep a reference and surface its exceptions, preferably through aTaskGroup. - py-test-hygiene discussKeep unit tests off external I/O (the network, the shared filesystem and the database) and off the real clock, and run tests that need them in a separate, slower tier.
- py-xdist-worker-isolated-state should-fixUnder pytest-xdist, give each worker its own database or other mutable resource, keyed by
worker_id, and build an expensive shared one once with a lock file.
What the badges mean
- blockmust be fixed before merge or release.
- should-fixfix it, but it need not block.
- discussraise it and decide together.
- stablevetted; use for verdicts.
- draftnot vetted; do not use for a verdict.
- Tool gate: what a linter or CI check could enforce instead of a reviewer.
Draft cards
74 draft cards
A draft card is not vetted. Report a FAIL of one under Draft findings, at should-fix at most, never in the ledger or the verdict. Each row links to the full card. How a draft becomes stable
- code-ai-pr-disclosure should-fixDisclose AI assistance in the PR, and have a human author who can explain and defend every changed line without the tool.
- code-documented-setup-runs should-fixKeep the setup, build and run commands in the README or contribution guide accurate: they work as written on a clean checkout, and any drift is fixed or reported.
- code-test-suite-time-budget should-fixRecord the suite's total time and its slowest tests on every CI run, and fail the build when the total or a single test passes a written budget.
- fn-empty-collection-not-none should-fixReturn an empty collection for "nothing found"; return
Noneonly when absent differs from empty. - fn-known-keys-get-a-type should-fixGive a fixed key set a record type: a model, a dataclass or a typed dict.
- fn-no-anonymous-tuples should-fixReturn a small named record, not a positional tuple, once the fields differ in meaning.
- fn-no-pass-through-wrapper should-fixDelete a method that only forwards, and keep wrappers that validate, adapt, or narrow.
- fn-no-stringly-typed-returns should-fixReturn a closed type (an enum, a tagged union or a sealed hierarchy) for a closed set of values, not a bare string. For a boolean flag, see fn-bool-arg-at-callsite.
- fn-propagate-dont-swallow should-fixChain the original cause when you translate an exception.
- fn-resource-lifetime should-fixGive every task and handle an owner that waits for it or closes it, on the error path too.
- inc-perf-regression-guard should-fixAdd an automated check that would have caught the regression (a benchmark, a budget, a load-test threshold, or a resource guard) as one of the postmortem's actions.
- inc-postmortem-owned-actions should-fixGive every postmortem action one named owner, a due date, and a tracker link.
- inc-review-asks-which-check should-fixEvery incident review names the check that should have caught the fault (a test, CI gate, review, canary or alert) and turns the gap into a new or fixed check.
- mod-central-config should-fixRead configuration in one settings module and pass it in; business code must not read the environment or hold knobs.
- mod-cohesive-unit discussKeep one cohesive concept per module.
- mod-mock-at-boundaries-only should-fixMock only at the process boundary (HTTP, DB, cloud, clock, I/O).
- mod-no-repeated-switches discussWhen the same switch or if-chain on one type appears in more than one place, replace the copies with polymorphism, unless each copy is an exhaustive switch over a closed type that fails the build when a case is missing.
- mod-no-wire-types-in-public-api should-fixExpose domain types in a module's public interface, and keep transport, storage and framework types behind it.
- mod-prefer-sync-api discussKeep logic in plain synchronous functions with no I/O, and add async wrappers at the edge only.
- mod-shim-fails-loudly should-fixA shim or stub must raise for every operation it does not implement; it must not return a success value such as 0,
Noneor an empty result for an unknown call. - mod-subtype-passes-parent-tests should-fixMake a subtype pass its parent's tests: accept every input the parent accepts, promise at least what it promises, and keep its invariants.
- mod-temporary-field discussMake a field a local variable or a parameter when every method that uses it assigns it before reading it.
- mod-thin-entry-point should-fixKeep the entry module to wiring (bootstrap, configuration, lifespan) and put no business logic in it.
- mod-validate-at-boundary-once should-fixValidate at the boundary, once, with a schema or model, so that inner layers receive typed, already-valid data.
- prod-wide-events-bounded-labels should-fixEmit one structured event per request carrying trace, tenant, build and flag state.
- svc-api-safe-idempotent-methods should-fixKeep GET, HEAD and OPTIONS free of side effects, and make PUT and DELETE give the same end state when repeated.
- svc-api-spec-matches-impl should-fixKeep the OpenAPI document as the source of truth, and generate it from the code or test the running service against it in CI.
- svc-api-trace-context should-fixForward
traceparentandtracestateon every outgoing call, keep the incoming trace id, and set a new parent id for each hop. - svc-page-title-per-route should-fixGive every page and every client-side view its own
<title>that says what it is. - svc-rate-limit-by-cost should-fixWhen request costs differ by orders of magnitude, charge each request its estimated cost against the quota instead of counting it as one.
- svc-request-id-logging should-fixPut the request or trace id on every log line written during a request.
- svc-security-event-logging should-fixLog every failed authentication with the account name and a timestamp.
- svc-security-headers should-fixSend
Strict-Transport-Securityon every HTTPS response. - sys-append-only-stores-have-retention should-fixGive every store that only grows (event, audit and history tables, log files, finished-job registries) a maximum age or count, and a job or setting that enforces it.
- sys-cache-cold-start should-fixCap and coalesce the cache-miss path so an empty cache cannot overwhelm the origin.
- sys-constraint-not-valid should-fixAdd the constraint
NOT VALID, then runVALIDATE CONSTRAINTin a separate step, and never leave the VALIDATE out. - sys-leader-two-leaders should-fixMake leader work safe if two leaders overlap: make it idempotent, check the lease before acting, and stop when renewal fails.
- chg-agent-mock-asserting-tests should-fixWrite tests that fail when the behaviour breaks, and reject tests that mostly assert on mocks, copy the implementation, or were edited to match new output without explanation.
- chg-api-spec-in-same-change should-fixUpdate the API spec in the same change that alters the routes, fields, status codes or headers it describes.
- chg-bot-approval-not-human should-fixDo not let a bot or agent approval satisfy a required human approval.
- chg-fix-root-cause-not-symptom should-fixIn a bug fix, state the cause you saw in evidence, and reject a guard, retry, sleep, longer timeout, swallowed error, cast, skipped or weakened test, or special case for the failing input that the cause does not justify.
- chg-flag-owner-retirement should-fixGive every new flag an owner, a default, and a removal condition or date, and ticket the removal.
- chg-matches-spec should-fixTrace every behaviour change in the diff to the stated requirement, and flag missing requirements and any change nobody asked for.
- chg-new-api-has-usage should-fixShip new API with at least one real caller in the same change, and fail speculative interfaces and options that nothing uses.
- chg-new-query-has-plan should-fixAttach the query plan for each new or rewritten query on a growing table, taken on production-sized data.
- chg-no-per-user-ide-files should-fixDo not commit a file that holds one developer's editor or IDE state; ignore those paths in the repository or a machine-wide exclude file, and keep the settings the team shares in the repository.
- chg-review-comment-format discussLabel each review comment with its severity: block, should-fix, or discuss.
- chg-review-rigour-by-risk should-fixSet the review tier from what the change touches, such as auth, billing, CI or release workflows, and not from who wrote it.
- chg-review-rounds-capped discussCap the number of review rounds; after the cap, re-review only the new diff and ask the author to rethink the approach if findings keep coming.
- chg-review-threads-resolved should-fixDo not merge while any review thread is open; each one ends as a fix or as a resolution with a stated reason.
- chg-sensitive-paths-human-owner should-fixName a human owner in CODEOWNERS for auth, billing, CI and release paths, and require that owner's approval.
- go-govulncheck-in-ci should-fixRun
govulncheck ./...in CI and fail the build on a reported vulnerability that your code calls. - go-http-client-timeout should-fixNetwork calls carry a deadline: a
context.Contextpassed toNewRequestWithContext, or anhttp.ClientwithTimeout, neverhttp.DefaultClientwithout either. - go-mod-readonly-verified should-fixCommit
go.sum, build in CI with-mod=readonly, and rungo mod verify. - go-no-init-side-effects discuss
init()does no I/O, reads no environment and does not depend on otherinit()functions; do that work frommain(). - go-test-race-in-ci should-fixCI runs the test suite with
go test -race ./.... - go-vet-lint-gate should-fixCI runs
go vetand a linter set that includes staticcheck and errcheck, and a finding fails the build. - go-wrap-errors-with-w should-fixCheck every returned
err; when you add context, wrap withfmt.Errorf("...: %w", err)unless the cause must stay hidden. - py-await-check-then-act should-fixWhen more than one worker or process can run, make check-then-act an atomic DB statement or constraint, because a Python lock covers one process only.
- py-error-hierarchy should-fixGive each package one base exception, with the specific ones in an
errorsmodule. - py-frozen-dataclass-over-tuple should-fixReturn a
@dataclass(frozen=True, slots=True)instead of a positional tuple. - py-init-assign-only should-fixKeep
__init__and__post_init__to assignments, and do I/O in a@classmethodfactory. - py-init-py-empty should-fixKeep
__init__.pyempty unless it re-exports the public API. - py-no-silenced-diagnostics should-fixSuppress a Python diagnostic only with a single named code and a reason on the same line.
- py-pydantic-validation should-fixValidate request data with a pydantic model, not hand-written checks.
- py-settings-pydantic-settings should-fixLoad env config with
BaseSettingsfrompydantic_settings. - py-strenum-not-strings should-fixUse
StrEnumfor fixed string sets andHTTPStatusfor HTTP codes. - py-test-collection-and-imports discussSet
testpathsin the pytest configuration. - typescript-mock-at-the-boundary should-fixFake the system boundary (network, clock, storage), for example with Mock Service Worker; do not
vi.mockyour own modules when a boundary fake would do. - typescript-no-floating-promises should-fixEvery Promise is awaited, returned, or given a
.catch; enable@typescript-eslint/no-floating-promises. - typescript-partial-mock-keeps-original should-fixA
vi.mockfactory spreadsawait importOriginal()and overrides only what the test needs; never swap an exported error class for a stub. - typescript-strict-mode should-fix
tsconfig.jsonsets"strict": true; switch off a single strict flag only with a written reason.