Coverage

By default the test-gap signal is a coarse heuristic: did the changeset touch any test file? Supply a line-coverage report and it becomes precise. It scores the fraction of the change’s added lines that are actually covered.

augur check --coverage lcov.info      # LCOV
augur check --coverage coverage.xml   # Cobertura XML
augur check --coverage jacoco.xml     # JaCoCo XML (Kotlin/Java)
augur check --coverage cover.out      # Go coverprofile
augur check --no-coverage             # disable auto-detection

All four parsers live in AugurKit and use Foundation only (no third-party dependency): Cobertura and JaCoCo via XMLParser, LCOV and Go coverprofiles by line parsing.

Supported formats

FormatTypical nameHow a line is instrumented / covered
LCOVlcov.infoDA:<line>,<hits>. Covered when hits > 0.
Coberturacoverage.xml<line number="N" hits="H"/>. Covered when hits > 0.
JaCoCojacoco.xml<line nr="N" ci="C"/> under <package><sourcefile>. Covered when ci (covered instructions) > 0; reported path is package@name/sourcefile@name.
Gocover.outpath:start.col,end.col stmts count blocks; every line in start…end. Covered when any covering block has count > 0.

Auto-detection

When --coverage is absent (and --no-coverage is not set), augur looks for a report at the repo root, trying these names in order and using the first that exists (logged to stderr):

lcov.info → coverage.xml → jacoco.xml → cover.out → coverage.out

The format is detected by extension first (.info → LCOV, .out → Go, .xml → Cobertura/JaCoCo), then by content sniffing: JaCoCo is distinguished from Cobertura by its <report>/<sourcefile> markers; a Go profile by its leading mode: line.

Scoring behavior

Per non-test, non-binary code file:

  • Has instrumented changed linesrisk = 1 − (covered ÷ instrumented), with a detail like 2/3 changed lines covered (67%).
  • Entirely absent from the report → high risk (0.7, “not in coverage report”).
  • No changed line was instrumented (e.g. only comments / blank lines changed), or no per-line data is available → falls back to the heuristic test-gap.
  • No coverage supplied at all → the original heuristic, unchanged.

Only instrumented changed lines count: a changed line the tool never instrumented (a comment, a blank line) contributes to neither the numerator nor the denominator. Added line ranges come from git diff --unified=0; only the file’s added lines are scored (not context or deletions).

Path-matching caveats

Coverage tools and git diffs often disagree on a leading path prefix (src/a.swift vs /build/checkout/src/a.swift). augur reconciles them by normalized longest-suffix matching at component boundaries: the report file sharing the most trailing path components with the diff path wins. An exact (normalized) match always wins.

Limitation: when two report files share an identical suffix (e.g. a/util.swift and b/util.swift both matched against a diff path util.swift), the match is ambiguous. It is resolved deterministically (shorter reported path, then lexicographically smallest), but it may not be the file you intended.

Recommendation: emit coverage with repo-relative paths where possible, so suffix matching is unambiguous.

Malformed input

The parsers degrade gracefully: malformed or empty LCOV/Cobertura/JaCoCo/Go inputs yield a sensible empty (or partial) report rather than crashing. An input whose format cannot be detected at all throws CoverageParser.ParseError.undetectableFormat.