| description | Top-level architecture codemap and invariants for covgate; read when understanding system boundaries, implementation modules, coverage/diff/gate data flow, or where to start for parser, metric, gate, CLI, rendering, and testing changes. |
|---|
This document describes the high-level architecture of covgate.
covgate is a local diff-coverage gate. It does not run tests itself and it does not own a language-specific coverage engine. Instead, it reads a native coverage report, identifies the lines changed in a Git diff, maps those changed lines onto a normalized internal coverage model, and then applies coverage rules only to the changed opportunities.
This file is intentionally short. It is a codemap and a set of architectural invariants, not a line-by-line implementation guide. For deeper investigation, use the files and documents named here as starting points.
At the highest level, covgate is a pipeline:
- Parse CLI input and repository-local defaults.
- Load a diff, either from a Git base ref or a precomputed unified diff file.
- Parse a native coverage artifact into
covgate's internal model. - Compute changed coverage metrics by intersecting normalized coverage opportunities with changed line ranges.
- Evaluate configured gate rules against those changed metrics.
- Render human-readable output to the console and optionally to Markdown.
The important design choice is that the gate operates on changed coverage opportunities, not on global project totals. That is the core product behavior.
src/main.rs is the CLI entry point. It supports two commands:
check, which runs the diff gaterecord-base, which records a stable per-worktree Git base ref for agent-style workflows
src/lib.rs is the execution pipeline for check. The run function is the best single place to read first if you want the whole flow in one screen.
src/cli.rs defines the clap surface.
src/config.rs resolves the effective runtime configuration from CLI flags plus covgate.toml. It is responsible for:
- choosing the diff source
- merging repository-local defaults with CLI overrides
- building the ordered list of gate rules
src/git.rs contains Git-specific helper behavior, especially the recorded-base workflow built around refs/worktree/covgate/base.
src/diff.rs turns either a Git base ref or a unified diff file into a list of changed files plus changed line ranges. From the rest of the system's perspective, this is the only shape a diff needs to have.
src/coverage/mod.rs auto-detects the report format and dispatches to a native-format adapter.
The format adapters are:
src/coverage/llvm_json.rssrc/coverage/coverlet_json.rssrc/coverage/istanbul_json.rs
Each adapter translates native report data into a shared CoverageReport. That shared model lives in src/model.rs.
src/model.rs defines the types that connect the whole program:
MetricKindGateRuleCoverageOpportunityCoverageReportComputedMetricCheckResult
If you are trying to understand what covgate fundamentally "means" by line, region, branch, or function coverage in a diff gate, this file defines the vocabulary.
src/metrics.rs computes changed metrics from a CoverageReport plus changed diff lines. This is where normalized opportunities become changed covered/total counts and uncovered changed opportunity lists.
src/gate.rs evaluates configured rules against those computed metrics. It does not know how coverage reports are parsed and it does not know how diffs are loaded. It only knows how to decide pass or fail from already-computed metrics.
src/render/console.rs renders the terminal summary.
src/render/markdown.rs renders the Markdown summary.
These renderers are downstream of the calculation model. They are presentation layers, not alternate coverage engines.
tests/ contains integration tests. The most important current boundaries are:
tests/cli_interface.rsfor command behavior and workflow semanticstests/cli_metrics.rsfor shared gate semantics across fixture familiestests/llvm_diff_regression.rsfor exact changed-opportunity and CLI-gate regressions on LLVM-backed fixtures
tests/support/mod.rs is the shared fixture harness.
xtask/src/main.rs contains repository-local build and validation tasks, including fixture coverage regeneration.
Native tools produce input artifacts. covgate parses those artifacts into its own internal model and computes gate results from that model. The core pass/fail behavior must remain explainable in terms of CoverageOpportunity, changed line overlap, and GateRule.
The decisive question is not "what is the project's global coverage?" The decisive question is "which coverage opportunities overlap the changed lines, and are those opportunities covered?"
This is why src/metrics.rs is a core architectural boundary. That module expresses the product's real contract.
LLVM, Coverlet, and Istanbul all have different native shapes. They must converge into one shared internal model before gating or rendering happens. Feature-specific logic in renderers or gate evaluation is a design smell unless it is purely presentational.
Console and Markdown output are views over computed results. They must not silently substitute another source of truth for totals or gate outcomes.
In particular, normal covgate summaries are calculation-backed, not pass-through views of native upstream summary fields. Native summaries are useful for comparison, investigation, and regression tests, but they are not the production source of truth for covgate output.
Overall coverage is a global informational summary. It reflects the state of the entire repository as provided by the coverage report. It must remain decoupled from gate-specific scoping or partitioning; even when multiple scoped gates are configured, there is only one repository-wide "Overall Coverage" section.
Coverage reports, Git diffs, and repository working directories often disagree about path shape. Each parser normalizes paths relative to the current repository root so diff matching can work across absolute and repo-relative inputs. A broken path-normalization change can make coverage look perfect by matching nothing.
record-base is not a side utility. It is part of the architecture for agent and sandbox workflows where standard remote refs are unavailable. The refs/worktree/covgate/base path is a stable architectural boundary between Git state discovery and diff gating.
The parser boundary is where lossy or tool-specific concepts are translated into covgate's shared model. When correctness questions arise, first ask whether the native report actually exposes the needed information.
The overlap check in SourceSpan::overlaps_line_range is simple, but it is the boundary that turns generic coverage data into diff coverage. Many user-visible gate results reduce to whether this mapping is correct.
ComputedMetric and CheckResult are the boundary objects between "what the tool believes" and "how the tool explains it." This is why summary rows and gate messages should stay downstream of the calculation model.
covgate is intentionally selective about accepted formats. The project prefers native, structural coverage formats over flattened interchange formats because diff gating depends on preserving executable structure.
This repository treats test fixtures as architectural assets, not just convenience data. Parser unit tests, CLI integration tests, and real-export diff regressions are the main way we prove that the normalization and gating model still matches reality closely enough to trust.
cargo xtask quick is the fast development loop.
cargo xtask validate is the broad validation sweep. It intentionally runs multiple validation commands and reports all pass/fail outcomes before returning a final exit code.
If you are new to the codebase, read in this order:
README.mdfor product intentsrc/lib.rsfor the end-to-end execution pathsrc/model.rsfor shared vocabularysrc/metrics.rsandsrc/gate.rsfor the diff-gating core- one parser module in
src/coverage/ - the relevant integration test in
tests/
If you are investigating LLVM summary mismatches specifically, start with:
docs/investigations/llvm-export-semantics-investigation.mddocs/investigations/function-coverage-debugging.mdtests/llvm_real_parity.rstests/llvm_diff_regression.rs