Expand description
Coverage rule (Python — issue #26; TypeScript — issue #31; exemptions — issue #32).
Enforces the README’s Coverage rule: a library’s unit suite must meet the
configured floor, with test files excluded from the denominator. This module
is the deterministic core — given a parsed coverage report and the thresholds
from config, an evaluate function decides pass/fail. Producing the report
(shelling out to the language’s coverage tool) is a thin layer on top, kept
separate so the guarantee is testable without that toolchain installed.
Python (#26) uses coverage.py: a single total, branch coverage on. Given a
CoverageReport and Thresholds, evaluate decides pass/fail, and
measure shells out to coverage. TypeScript (#31) is the twin: vitest
reports four independent metrics (lines / branches / functions / statements),
so it carries its own TypeScriptThresholds, VitestReport, and
evaluate_typescript / measure_typescript pair — sharing only the
Outcome type. Its subprocess layer shells out to vitest.
Files exempted from coverage in config (issue #32) are omitted from the
denominator alongside the test files; the caller resolves them
(crate::config::resolve_exempt) and passes their paths to measure /
measure_typescript.
Structs§
- Baseline
- The committed coverage baseline — the last recorded coverage per language. Keyed by language so one file serves a multi-language repo; a language with no entry has no ratchet (the floor still applies). The TypeScript and Rust keys land with their slices.
- Coverage
Report - A coverage.py JSON report (
coverage json), pared to what the checks need: thetotals(the floor and ratchet) and the per-filefilesblock (patch coverage, #132). Unmodeled fields (metadata, per-function/class data) are ignored. - File
Coverage - Per-file coverage detail from a coverage.py report (one
filesentry) — what patch coverage (#132) reads to decide whether a changed line is covered. Unmodeled fields (the summary, per-function/class data) are ignored. - Python
Baseline - The recorded Python baseline: the last total percent the unit suite cleared.
- Thresholds
- The coverage floor to enforce, from a
[<language>].coveragetable. - Totals
- The
totalsblock of a coverage.py report. - Type
Script Thresholds - The four vitest coverage floors, from a
[typescript].coveragetable. Each is an independent percent the unit suite must meet — vitest measures all four. - Vitest
Metric - One metric’s totals from a vitest json-summary block, pared to what the check needs: the covered percent and the denominator size.
- Vitest
Report - A vitest
coverage-summary.jsonreport, pared to thetotalblock the check needs. Per-file entries and unmodeled fields are ignored. - Vitest
Totals - The
totalblock of a vitest json-summary report — the four metrics this rule enforces. vitest also emitsbranchesTrue, which the check ignores.
Enums§
- Outcome
- The result of checking a report against the thresholds.
Constants§
- BASELINE_
PATH - Where the committed coverage baseline lives, relative to the scanned root —
beside the measured tree, the way
--configresolves alongside it.
Functions§
- evaluate
- Decide whether
reportmeetsthresholds. - evaluate_
ratchet - Decide whether
percentregresses belowbaseline, the recorded total the suite must not drop under.None(nothing recorded) is no ratchet →Outcome::Pass. Carries the same hair of float tolerance asevaluateso a percent that rounds to the baseline isn’t failed by noise. - evaluate_
typescript - Decide whether
reportmeets every threshold inthresholds. - measure
- Run the unit suite under coverage.py in
rootand check it againstthresholds. - measure_
patch_ report - Run the Python unit suite under coverage.py in
rootwith every source underrootmeasured (coverage run --source=.) and return the parsed report — so an untested source shows in thefilesblock as wholly uncovered rather than vanishing. The per-file detail is what patch coverage (#132) reads;omitis as inmeasure(an exempt file stays out of the run, so its changed lines are lifted). - measure_
patch_ typescript - Run the TypeScript unit suite under vitest in
rootand return the uncovered lines per file — keyed by the absolute path vitest reports, the caller re-keying toroot-relative to match the diff. A line is uncovered when it carries a statement the suite never executed, or the source of a branch a path of which the suite never took (the v8 analogue of the Python arm’s missing line / missing branch).excludeis thecoverage-rule exemptions, dropped from the run so an exempt file’s changed lines are lifted.npxresolves the project-localvitest, so it and@vitest/coverage-v8must be installed underroot. - measure_
report - Run the Python unit suite under coverage.py in
rootand return the parsed report — the totals the floor (evaluate) and the ratchet (evaluate_ratchet) both read.omitis as inmeasure. - measure_
typescript - Run the unit suite under vitest coverage in
rootand check it againstthresholds. - parse_
report - Parse a coverage.py JSON report (the output of
coverage json). - parse_
vitest_ report - Parse a vitest json-summary report (
coverage-summary.json). - read_
baseline - Read the committed baseline at
root/BASELINE_PATH, orNonewhen the file is absent — an absent baseline means no ratchet, the same way a missing config means nothing is exempt.