Skip to content

Coverage Policy

FieldValue
TypeSkill Resource
Source~/.copilot/skills/quality/references/coverage-policy.md
DescriptionNot specified

Source Content

Coverage Policy

The single number this skill enforces is >=50% line coverage, one of ADR-005’s release gates. This file explains what that floor means, what it does not, and how to keep it from becoming theater.

Table of contents

The floor

Per ADR-005, the test gate requires at least 50% line coverage and must pass before any merge. Below the floor, the build fails and the PR cannot land.

It is deliberately a floor, not a goal. Fifty percent is the minimum at which a suite is doing meaningful work; it is not an aspiration to stop at, nor a ceiling to chase to 100%. Teams may set a higher per-package threshold where risk warrants — they may never set a lower one.

Read it as risk, not as a target

A coverage percentage is a proxy, and proxies are gameable. Read it correctly:

  • Lines are the cheapest signal. Line coverage says a line ran, not that its behavior was checked. High line coverage with weak assertions is weak testing wearing a green badge.
  • Direct coverage at code that breaks badly. Payments, auth, data integrity, and irreversible actions deserve coverage long before glue code does. Find the uncovered branches there first.
  • A covered line with no assertion is uncovered in spirit. If removing the expect would not fail the test, the line is decorative.
  • 50% of the right code beats 90% of the wrong code. Use the report to find risky gaps, not to manufacture a number.

When asked “what’s our coverage gap?”, the answer is never “raise the threshold.” It is “here are the next N uncovered business-critical branches, ranked by the cost of them breaking.”

Anti-gaming rules

These keep the floor honest:

  • No assertion-free tests to walk lines. A test that renders a component and asserts nothing is padding, not coverage.
  • No snapshot-only suites for behavior. Snapshots catch unintended markup change; they do not verify behavior and should not be the only test for a component.
  • No /* istanbul ignore */ to hide real logic. Ignore comments are for genuinely untestable lines (defensive default: on an exhaustive switch), not for skipping hard cases.
  • No coverage on the test files themselves, fixtures, or mocks counted toward the number.

Exclusions

Exclude code that produces noise rather than signal. Configure these out of the coverage denominator:

  • Generated code — *.gen.ts, routeTree.gen.ts, codegen output, OpenAPI/Zod-generated types.
  • Type-only files — *.d.ts, pure type/interface modules with no runtime.
  • Barrel files — index.ts re-exports.
  • Config and build scripts — vite.config.ts, *.config.*, tooling.
  • Story files and test utilities — *.stories.tsx, test/, __mocks__/.
  • Trivial constant maps and enums with no logic.

Excluding glue is not gaming — it focuses the percentage on code where a test could actually find a bug.

The full release gate

Coverage is one check among several. ADR-005 requires all of these to pass before merge:

GateWhat it checks
pnpm typecheckNo type errors
pnpm buildBuilds clean
pnpm lintLint clean
pnpm testTests pass, >=50% line coverage
jest-axeNo new WCAG 2.2 AA violations
Lost PixelNo unreviewed visual regression (never Chromatic)
Bundle budgetBundle size within budget
Docs gateStory present + a docs page (ADR-021)

A PR is releasable only when every row is green. The coverage floor is necessary, not sufficient — passing it while failing jest-axe or Lost Pixel still blocks the merge.

See the source of record: ADR-005: Accessibility & Release Gates.