---
title: "Drafts by what they lack"
description: "Every draft card grouped by what it lacks to become stable, with what each one needs."
canonical: "https://goodcodereview.com/drafts"
updated: "2026-10-25"
---

# Drafts by what they lack

Each draft card names what keeps it from stable in a `lacks:` line. This page groups the 129 drafts by that reason. [How a draft becomes stable](https://github.com/n0nuser/goodcodereview/blob/main/docs/PROMOTION.md) gives the bar. To promote one, open a [Promote a draft issue](https://github.com/n0nuser/goodcodereview/issues/new?template=promote-draft.yml).

## Too few organisations back a clause of the Rule (100)

- [code-ai-pr-disclosure](https://goodcodereview.com/codebase.html#code-ai-pr-disclosure) (codebase): disclosure has the Linux kernel and Ghostty; needs a third org that asks for it and for an author who can explain the code
- [code-documented-setup-runs](https://goodcodereview.com/codebase.html#code-documented-setup-runs) (codebase): one vendor's guidance (cursor/plugins) backs it; needs two more orgs that test the setup commands
- [code-flaky-test-quarantine](https://goodcodereview.com/codebase.html#code-flaky-test-quarantine) (codebase): quarantine with owner and ticket has Dropbox and Shopify; rerun-verified return to the gate has Dropbox only
- [fn-atomic-related-updates](https://goodcodereview.com/function.html#fn-atomic-related-updates) (function): only one vendor's review skill backs it; the all-or-nothing principle has no cited org
- [fn-bool-arg-at-callsite](https://goodcodereview.com/function.html#fn-bool-arg-at-callsite) (function): only the author's own Python review guide backs it; no independent org
- [fn-distinct-types-for-ids](https://goodcodereview.com/function.html#fn-distinct-types-for-ids) (function): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [fn-empty-collection-not-none](https://goodcodereview.com/function.html#fn-empty-collection-not-none) (function): only the author's own Python review guide backs it; no independent org
- [fn-english-identifiers](https://goodcodereview.com/function.html#fn-english-identifiers) (function): PEP 8 and LLVM give the rule and PEP 3131 argues the other way; needs a third org that mandates English
- [fn-known-keys-get-a-type](https://goodcodereview.com/function.html#fn-known-keys-get-a-type) (function): only the author's own Python review guide backs it; no independent org
- [fn-no-anonymous-tuples](https://goodcodereview.com/function.html#fn-no-anonymous-tuples) (function): only the author's own Python review guide backs it; no independent org
- [fn-no-check-then-act-across-await](https://goodcodereview.com/function.html#fn-no-check-then-act-across-await) (function): only the author's own Python review guide backs it; no independent org
- [fn-no-getattr-for-known-names](https://goodcodereview.com/function.html#fn-no-getattr-for-known-names) (function): only the author's own Python review guide backs it; no independent org
- [fn-no-magic-values](https://goodcodereview.com/function.html#fn-no-magic-values) (function): Google's review guide is the only backer; needs two more orgs
- [fn-no-pass-through-wrapper](https://goodcodereview.com/function.html#fn-no-pass-through-wrapper) (function): Ousterhout is the only backer, through two links to one author; needs two more orgs
- [fn-no-stringly-typed-returns](https://goodcodereview.com/function.html#fn-no-stringly-typed-returns) (function): only the author's own Python review guide backs it; no independent org
- [fn-propagate-dont-swallow](https://goodcodereview.com/function.html#fn-propagate-dont-swallow) (function): only the author's own Python review guide backs it; no independent org
- [fn-resource-lifetime](https://goodcodereview.com/function.html#fn-resource-lifetime) (function): one blog post on structured concurrency backs it; needs two more orgs
- [fn-specific-exceptions-only](https://goodcodereview.com/function.html#fn-specific-exceptions-only) (function): the Go wiki and an Ousterhout summary back it; needs a third independent org
- [fn-test-oracle-independent](https://goodcodereview.com/function.html#fn-test-oracle-independent) (function): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [fn-variants-as-tagged-union](https://goodcodereview.com/function.html#fn-variants-as-tagged-union) (function): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [inc-postmortem-owned-actions](https://goodcodereview.com/incident.html#inc-postmortem-owned-actions) (incident): an owner and due date on each action has no org; Dropbox and Shopify mention action items without naming either
- [mod-behaviour-lives-with-state](https://goodcodereview.com/module.html#mod-behaviour-lives-with-state) (module): only the author's own Python review guide backs it; no independent org
- [mod-central-config](https://goodcodereview.com/module.html#mod-central-config) (module): "one settings module" has no org; Uber and Cabify back only keeping knobs out of code
- [mod-deep-modules](https://goodcodereview.com/module.html#mod-deep-modules) (module): Ousterhout is the only backer, and Martin disagrees; needs two more orgs
- [mod-inject-boundary-collaborators](https://goodcodereview.com/module.html#mod-inject-boundary-collaborators) (module): only the author's own Python review guide backs it; no independent org
- [mod-internals-unreachable](https://goodcodereview.com/module.html#mod-internals-unreachable) (module): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [mod-layers-point-inward](https://goodcodereview.com/module.html#mod-layers-point-inward) (module): only the author's own Python review guide backs it; no independent org
- [mod-no-import-side-effects](https://goodcodereview.com/module.html#mod-no-import-side-effects) (module): only the author's own Python review guide backs it; no independent org
- [mod-no-logic-in-constructors](https://goodcodereview.com/module.html#mod-no-logic-in-constructors) (module): only the author's own Python review guide backs it; no independent org
- [mod-no-module-mutable-state](https://goodcodereview.com/module.html#mod-no-module-mutable-state) (module): only the author's own Python review guide backs it; no independent org
- [mod-no-wire-types-in-public-api](https://goodcodereview.com/module.html#mod-no-wire-types-in-public-api) (module): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [mod-no-wrong-abstraction](https://goodcodereview.com/module.html#mod-no-wrong-abstraction) (module): Metz and Dodds back inlining; the re-split remedy has no third org, and the Counterpoint still cites an unsourced count
- [mod-proto-enum-zero-unspecified](https://goodcodereview.com/module.html#mod-proto-enum-zero-unspecified) (module): the _UNSPECIFIED name has Google only; a zero value with no meaning has Google and Dropbox
- [mod-thin-entry-point](https://goodcodereview.com/module.html#mod-thin-entry-point) (module): only the author's own Python review guide backs it; no independent org
- [prod-a11y-audit-before-launch](https://goodcodereview.com/production.html#prod-a11y-audit-before-launch) (production): "before a public launch" has GOV.UK only; the audit content has GOV.UK, W3C and Deque
- [prod-slo-error-budget](https://goodcodereview.com/production.html#prod-slo-error-budget) (production): gating releases on the error budget has no backing row
- [prod-wide-events-bounded-labels](https://goodcodereview.com/production.html#prod-wide-events-bounded-labels) (production): Honeycomb is the only backer, and the Rule does not mention bounded labels; needs two more orgs
- [svc-api-cache-control](https://goodcodereview.com/service.html#svc-api-cache-control) (service): IETF and Zalando back it; needs a third org
- [svc-api-contract-tests](https://goodcodereview.com/service.html#svc-api-contract-tests) (service): Pact is the only backer; OpenAPI does not back contract tests and provider verification is not asserted
- [svc-api-documented-errors](https://goodcodereview.com/service.html#svc-api-documented-errors) (service): OpenAPI requires one response per operation; the stricter rule is Zalando's alone
- [svc-api-naming-consistent](https://goodcodereview.com/service.html#svc-api-naming-consistent) (service): Zalando and Microsoft back it, and they disagree on casing; needs a third org that asks for consistency
- [svc-api-problem-json](https://goodcodereview.com/service.html#svc-api-problem-json) (service): IETF and Zalando back it; needs a third org
- [svc-api-retry-after](https://goodcodereview.com/service.html#svc-api-retry-after) (service): IETF and Zalando back it; needs a third org
- [svc-api-specific-status-codes](https://goodcodereview.com/service.html#svc-api-specific-status-codes) (service): IETF and Zalando back it; needs a third org
- [svc-api-trace-context](https://goodcodereview.com/service.html#svc-api-trace-context) (service): W3C is the only backer; needs two more orgs that forward trace headers on every call
- [svc-async-content-reserves-space](https://goodcodereview.com/service.html#svc-async-content-reserves-space) (service): injected content and ads have Google only; the image-dimensions part has Google and Mozilla
- [svc-best-effort-optional-deps](https://goodcodereview.com/service.html#svc-best-effort-optional-deps) (service): best-effort calls have Netflix, Uber and Cabify; counting every fallback has Cabify only
- [svc-circuit-breaker-bulkhead](https://goodcodereview.com/service.html#svc-circuit-breaker-bulkhead) (service): "per dependency" has Microsoft only; needs two more orgs that limit concurrency per downstream
- [svc-cli-destructive-dry-run](https://goodcodereview.com/service.html#svc-cli-destructive-dry-run) (service): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [svc-cli-non-interactive](https://goodcodereview.com/service.html#svc-cli-non-interactive) (service): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [svc-saga-steps](https://goodcodereview.com/service.html#svc-saga-steps) (service): Azure is the only backer; needs two more orgs that require idempotent steps and compensations
- [svc-stream-dont-materialise](https://goodcodereview.com/service.html#svc-stream-dont-materialise) (service): the Node.js backpressure guide is the only backer, and its claim is Node-specific
- [sys-cache-cold-start](https://goodcodereview.com/system.html#sys-cache-cold-start) (system): AWS is the only backer; needs two more orgs
- [sys-constraint-not-valid](https://goodcodereview.com/system.html#sys-constraint-not-valid) (system): PostgreSQL docs are the only backer; needs two more orgs that add constraints in two steps
- [sys-health-liveness-readiness](https://goodcodereview.com/system.html#sys-health-liveness-readiness) (system): AWS is the only backer; needs two more orgs
- [sys-index-concurrently](https://goodcodereview.com/system.html#sys-index-concurrently) (system): PostgreSQL and GitLab back it; needs a third org
- [sys-leader-two-leaders](https://goodcodereview.com/system.html#sys-leader-two-leaders) (system): AWS is the only backer; needs two more orgs
- [sys-migration-lock-timeout](https://goodcodereview.com/system.html#sys-migration-lock-timeout) (system): PostgreSQL and GitLab back it; the lock-queue reason is inferred; needs a third org
- [chg-agent-grounded-code](https://goodcodereview.com/change.html#chg-agent-grounded-code) (change): only an arXiv package-hallucination study backs checking every import and call; needs two more orgs
- [chg-agent-independent-review](https://goodcodereview.com/change.html#chg-agent-independent-review) (change): a person's sign-off has Stripe and Dropbox; the fresh-context reviewer option has 0 orgs; needs one more firm org or that option cut
- [chg-agent-mock-asserting-tests](https://goodcodereview.com/change.html#chg-agent-mock-asserting-tests) (change): Google and cursor/plugins back it; Go backs a side remark and Feathers points the other way
- [chg-api-spec-in-same-change](https://goodcodereview.com/change.html#chg-api-spec-in-same-change) (change): OpenAPI and Zalando back it; needs a third org
- [chg-approval-tied-to-patch](https://goodcodereview.com/change.html#chg-approval-tied-to-patch) (change): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [chg-chestertons-fence](https://goodcodereview.com/change.html#chg-chestertons-fence) (change): only Feathers backs a characterization test before a rewrite; Spolsky backs not rewriting from scratch
- [chg-delete-legacy-after-migration](https://goodcodereview.com/change.html#chg-delete-legacy-after-migration) (change): "in the same change" has cursor/plugins and Stripe; Dropbox, GitHub, Shopify and Slack delete in a later step
- [chg-devex-breaking-config](https://goodcodereview.com/change.html#chg-devex-breaking-config) (change): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [chg-fix-root-cause-not-symptom](https://goodcodereview.com/change.html#chg-fix-root-cause-not-symptom) (change): one vendor's guidance (cursor/plugins) backs it; needs two more orgs
- [chg-flag-owner-retirement](https://goodcodereview.com/change.html#chg-flag-owner-retirement) (change): the owner clause has Dropbox only; default, removal date and ticket have no company source
- [chg-matches-spec](https://goodcodereview.com/change.html#chg-matches-spec) (change): checking the change against the spec has Google, plus Dropbox for security only; needs a third org
- [chg-migration-add-column-rewrite](https://goodcodereview.com/change.html#chg-migration-add-column-rewrite) (change): PostgreSQL docs are the only backer; needs two more orgs
- [chg-name-attack-surface](https://goodcodereview.com/change.html#chg-name-attack-surface) (change): no source says to list the attack surface in the description; OWASP and Mozilla back only a threat-model trigger
- [chg-no-silenced-diagnostics](https://goodcodereview.com/change.html#chg-no-silenced-diagnostics) (change): reason and ticket on each suppression has cursor/plugins only; Stripe tracked suppressions as a group
- [chg-no-special-case-branches](https://goodcodereview.com/change.html#chg-no-special-case-branches) (change): one vendor's review skill backs it, with no data; needs two more orgs
- [chg-proto-no-field-type-change](https://goodcodereview.com/change.html#chg-proto-no-field-type-change) (change): "no field type change" has Google only; Uber and Cabify back renumbering and the buf breaking gate instead
- [chg-proto-reserve-removed-fields](https://goodcodereview.com/change.html#chg-proto-reserve-removed-fields) (change): protobuf.dev is the only backer; needs two more orgs that require reserved on removal
- [chg-rollback-path](https://goodcodereview.com/change.html#chg-rollback-path) (change): no org says to state the undo in the change description; Uber and Stripe describe a rollback ability only
- [chg-ui-change-screenshots-and-keyboard-pass](https://goodcodereview.com/change.html#chg-ui-change-screenshots-and-keyboard-pass) (change): reporting the keyboard pass has two PR templates; the 200% zoom clause has W3C only
- [py-await-check-then-act](https://goodcodereview.com/pack-python.html#py-await-check-then-act) (function): only the author's own Python review guide backs it; no independent org
- [py-cancellation](https://goodcodereview.com/pack-python.html#py-cancellation) (service): the asyncio docs are the only backer; needs a second independent source on cancellation
- [py-class-earns-its-instance](https://goodcodereview.com/pack-python.html#py-class-earns-its-instance) (module): the Go wiki and the author's own guide back it; needs a third independent org
- [py-docstrings-google](https://goodcodereview.com/pack-python.html#py-docstrings-google) (function): Google's review guide is the only backer; needs two more orgs
- [py-error-hierarchy](https://goodcodereview.com/pack-python.html#py-error-hierarchy) (module): only the author's own Python review guide backs it; no independent org
- [py-field-only-when-adds](https://goodcodereview.com/pack-python.html#py-field-only-when-adds) (module): only the author's own Python review guide backs it; no independent org
- [py-frozen-dataclass-over-tuple](https://goodcodereview.com/pack-python.html#py-frozen-dataclass-over-tuple) (function): only the author's own Python review guide backs it; no independent org
- [py-httpx-client-lifespan](https://goodcodereview.com/pack-python.html#py-httpx-client-lifespan) (module): only the author's own Python review guide backs it, and its Counterpoint concedes the default timeout is fine
- [py-imports](https://goodcodereview.com/pack-python.html#py-imports) (module): only the author's own Python review guide backs it; no independent org
- [py-init-assign-only](https://goodcodereview.com/pack-python.html#py-init-assign-only) (module): only the author's own Python review guide backs it; no independent org
- [py-init-py-empty](https://goodcodereview.com/pack-python.html#py-init-py-empty) (module): only the author's own Python review guide backs it; no independent org
- [py-modern-typing](https://goodcodereview.com/pack-python.html#py-modern-typing) (function): only the author's own Python review guide backs it; no independent org
- [py-no-cast](https://goodcodereview.com/pack-python.html#py-no-cast) (function): only the author's own Python review guide backs it; no independent org
- [py-no-init-or-model-tests](https://goodcodereview.com/pack-python.html#py-no-init-or-model-tests) (module): only the author's own Python review guide backs it; no independent org
- [py-no-silenced-diagnostics](https://goodcodereview.com/pack-python.html#py-no-silenced-diagnostics) (change): only the author's own Python review guide backs it; no independent org
- [py-paths-from-file](https://goodcodereview.com/pack-python.html#py-paths-from-file) (function): only the author's own Python review guide backs it; no independent org
- [py-pydantic-validation](https://goodcodereview.com/pack-python.html#py-pydantic-validation) (module): only the author's own Python review guide backs it; no independent org
- [py-pytest-parametrize](https://goodcodereview.com/pack-python.html#py-pytest-parametrize) (function): only the author's own Python review guide backs it; no independent org
- [py-ruff-gate](https://goodcodereview.com/pack-python.html#py-ruff-gate) (change): only the author's own Python review guide backs it; no independent org
- [py-settings-pydantic-settings](https://goodcodereview.com/pack-python.html#py-settings-pydantic-settings) (module): only the author's own Python review guide backs it; no independent org
- [py-strenum-not-strings](https://goodcodereview.com/pack-python.html#py-strenum-not-strings) (function): only the author's own Python review guide backs it; no independent org
- [py-task-reference](https://goodcodereview.com/pack-python.html#py-task-reference) (service): the asyncio docs are the only backer; needs a second independent source on task lifetime
- [py-test-hygiene](https://goodcodereview.com/pack-python.html#py-test-hygiene) (module): Shopify backs the Why only; Stripe test clocks are a product feature, so the Rule has no org

## A source is a plan, a definition, or a summary rather than a stated practice (18)

- [code-file-lines-ceiling](https://goodcodereview.com/codebase.html#code-file-lines-ceiling) (codebase): backers are a dev.to summary and a blog post; no org states a file-length ceiling or the 1,000-line figure
- [code-scoped-validation-loop](https://goodcodereview.com/codebase.html#code-scoped-validation-loop) (codebase): every backer describes CI test selection, not a documented local command; needs orgs that document one
- [fn-comments-survive-context](https://goodcodereview.com/function.html#fn-comments-survive-context) (function): the only backer is a dev.to summary of Ousterhout; needs two orgs that ban time-bound comments
- [fn-name-intermediate-conditions](https://goodcodereview.com/function.html#fn-name-intermediate-conditions) (function): the only backer is a dev.to summary of Ousterhout; needs two orgs that say to name sub-conditions
- [mod-fowler-smells](https://goodcodereview.com/module.html#mod-fowler-smells) (module): no Fowler or Beck source; backers are an Ousterhout summary and Google's review guide, mapped by hand
- [mod-mock-at-boundaries-only](https://goodcodereview.com/module.html#mod-mock-at-boundaries-only) (module): Airbnb mocks services in load tests and Cabify runs a real gRPC server; neither states the Rule
- [mod-no-utils-grab-bag](https://goodcodereview.com/module.html#mod-no-utils-grab-bag) (module): the only backer is a dev.to summary of Ousterhout; needs two orgs that say to name helpers after a concept
- [mod-one-name-per-concept](https://goodcodereview.com/module.html#mod-one-name-per-concept) (module): Netflix backs the converse, one concept per name; Slack's aliases are narrow; no org states the Rule
- [mod-prefer-sync-api](https://goodcodereview.com/module.html#mod-prefer-sync-api) (module): the sans-io and async-pressure posts are opinion and neither states this as a rule; the card combines them
- [mod-subtype-passes-parent-tests](https://goodcodereview.com/module.html#mod-subtype-passes-parent-tests) (module): Liskov and Wing state the substitution rule; none says to run the parent's tests, which is the card's proxy
- [prod-shadow-compare-before-cutover](https://goodcodereview.com/production.html#prod-shadow-compare-before-cutover) (production): Netflix, Stripe, Airbnb and GitHub describe doing it; none recommends it as a practice for others
- [svc-authn-by-default](https://goodcodereview.com/service.html#svc-authn-by-default) (service): only Microsoft and Spring say why auth by default; Django, Rails and NestJS describe the default without a reason
- [svc-dlq](https://goodcodereview.com/service.html#svc-dlq) (service): Dropbox's dead-letter queue is a proposal, not a practice; needs a third org that runs it
- [svc-rate-limit-by-cost](https://goodcodereview.com/service.html#svc-rate-limit-by-cost) (service): Shopify, GitHub and Airbnb describe cost-based limits; none recommends it, and Uber dropped a bytes-based quota
- [svc-request-id-logging](https://goodcodereview.com/service.html#svc-request-id-logging) (service): the W3C spec does not mention logs; only Honeycomb backs putting the id on every log line
- [sys-cells-limit-blast-radius](https://goodcodereview.com/system.html#sys-cells-limit-blast-radius) (system): Netflix and Slack run cells; Airbnb's multi-cluster store and Cloudflare's postmortem describe failure domains, not cells
- [chg-reuse-before-write](https://goodcodereview.com/change.html#chg-reuse-before-write) (change): the backers are the kernel style guide and secondary summaries; no source describes searching for an existing helper first
- [chg-review-comment-format](https://goodcodereview.com/change.html#chg-review-comment-format) (change): Google and Orosz recommend labels; Cloudflare and Dropbox describe their own tool output, not a rule for reviewers

## A reviewer could not mark the Rule FAIL at its level (3)

- [mod-cohesive-unit](https://goodcodereview.com/module.html#mod-cohesive-unit) (module): "one cohesive concept" is hard to mark FAIL; the Ousterhout backer is a secondary summary
- [mod-validate-at-boundary-once](https://goodcodereview.com/module.html#mod-validate-at-boundary-once) (module): nobody backs "once"; without it the FAIL, hand-rolled checks in the handler, would pass
- [chg-new-query-has-plan](https://goodcodereview.com/change.html#chg-new-query-has-plan) (change): without "attach the plan" a change review has nothing to mark FAIL; attaching has GitLab only

## It overlaps a stable card (3)

- [inc-perf-regression-guard](https://goodcodereview.com/incident.html#inc-perf-regression-guard) (incident): the guard half is the stable code-perf-budget-in-ci Rule; the postmortem-action half has Google SRE and Cloudflare only
- [svc-api-safe-idempotent-methods](https://goodcodereview.com/service.html#svc-api-safe-idempotent-methods) (service): the GET half is already in stable svc-csrf-state-changing; PUT and DELETE have IETF only
- [chg-new-api-has-usage](https://goodcodereview.com/change.html#chg-new-api-has-usage) (change): its FAIL shapes, an unused option and a one-implementation Protocol, are the stable mod-yagni Rule

## The card contradicts itself (1)

- [svc-api-spec-matches-impl](https://goodcodereview.com/service.html#svc-api-spec-matches-impl) (service): the Rule makes the spec the source of truth, then allows generating it from code; pick one

## The maintainer keeps it as a draft (4)

- [code-a11y-check-in-ci](https://goodcodereview.com/codebase.html#code-a11y-check-in-ci) (codebase): kept draft by Pablo's call; no org backs failing the build on a violation
- [svc-page-title-per-route](https://goodcodereview.com/service.html#svc-page-title-per-route) (service): kept draft by Pablo's call; W3C, Mozilla and A11y Project back the Rule
- [svc-security-event-logging](https://goodcodereview.com/service.html#svc-security-event-logging) (service): kept draft by Pablo's call
- [svc-security-headers](https://goodcodereview.com/service.html#svc-security-headers) (service): kept draft by Pablo's call
