ADR-0009: Quality gates¶
Status: Accepted Date: 2026-09-30 Deciders: Alex Nodeland
Context¶
relayr's guarantees are its reason to exist: an event bridged exactly once, a proposal made once however often a run retries, and loops that end. They hold only as far as the tests that pin them, and trunk-based development (ADR-0008) only works if CI can be trusted. Its siblings hold themselves to the same bar (artifactr ADR-0015, reflexr ADR-0013).
Decision¶
CI enforces these gates on every pull request and on main, the same as the siblings':
| Gate | Rule |
|---|---|
| Coverage | 100% line and branch coverage of src/relayr |
| Types | pyright strict for src/ and scripts/, standard for tests, with no inline suppressions |
| Lint and format | ruff, with Google-style docstrings on public API |
| Tests | pytest with warnings as errors, on Python 3.12, 3.13 and 3.14, plus a PostgreSQL job once the ledger's SQL adapter exists |
| Lockfile | uv sync --locked |
| Docs | The site builds in strict mode, and its lists render |
The only coverage exclusions are configured centrally in pyproject.toml (if TYPE_CHECKING:, Protocol bodies, @overload, assert_never, ...). tests/test_quality.py fails on any inline suppression: no # type: ignore, # pyright: ignore, # noqa or # pragma: no cover. Where a third-party library is untyped, a stub under typings/ is preferred to a suppression.
Consequences¶
- Easier: refactoring, and moving the libraries' pins, with confidence; untested code cannot merge.
- Harder: defensive code needs a test or needs to go.