feat(coverage): deterministic test-coverage gate on deploy-staging->deploy edge (ORCH-027)
Introduce a deterministic (no-LLM) coverage sub-gate that blocks coverage degradation before a task branch merges into `main`. Existing gates judge only by the FACT of passing (check_ci_green / check_tests_passed / merge-gate re-test), not by completeness — so a batch autonomous run (ORCH-088) silently erodes coverage. Pattern mirrors the security-gate (ORCH-022): leaf src/coverage_gate.py (never-raise) + thin check_coverage_gate in QG_CHECKS + _handle_coverage_gate splice in advance_stage, run AFTER merge-gate (measured on the caught-up HEAD that lands in main) and BEFORE image-freshness (fail before the expensive docker rebuild). - measure_coverage: pytest --cov=src --cov-report=json in the per-branch worktree -> line coverage %; None on tool error -> fail-open + WARNING by default (FR-6). - compute_coverage_verdict (pure): absolute | baseline | both + epsilon (NFR-4 anti-flap); baseline None -> bootstrap (absolute-only). - coverage_baseline DB table (additive, CREATE TABLE IF NOT EXISTS) + ratchet-up in _handle_merge_verify (deploy->done): atomic compare-and-set under merge-lease, never decreases; bootstrap on first merge. - Artefact 18-coverage-report.md (coverage_status: frontmatter, single source of truth); GET /queue `coverage` block; FAIL -> Telegram; optional POST /coverage/baseline override. - Flags ORCH_COVERAGE_* (kill-switch + self-hosting-only scope) -> enduro untouched; STAGE_TRANSITIONS / existing check_* / verdict keys byte-for-byte unchanged (NFR-5/AC-8). - pytest-cov==5.0.0 added to requirements.txt. Tests: tests/test_coverage_gate.py (TC-01..TC-15). Frozen QG-registry anti-regress tests + deploy-staging edge tests updated for the new sub-gate. Full suite green. Docs: README / adr-0029 / PIPELINE_DOCS / 18-coverage-report.md template (architecture stage) + CHANGELOG / CLAUDE.md / .env.example (this PR). Refs: ORCH-027 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
22
.env.example
22
.env.example
@@ -372,6 +372,28 @@ ORCH_SECURITY_SCAN_TIMEOUT_S=300
|
||||
ORCH_SECURITY_DEP_AUDIT_FAIL_CLOSED=false
|
||||
ORCH_SECURITY_SECRETS_BLOCK=true
|
||||
|
||||
# ORCH-027: coverage-gate (deterministic test-coverage) on the deploy-staging ->
|
||||
# deploy edge, run AFTER the merge-gate and BEFORE image-freshness. Measures line
|
||||
# coverage of src/ with pytest-cov in the per-branch worktree, compares to an absolute
|
||||
# floor and/or the ratchet baseline of `main`; FAIL -> rollback to development +
|
||||
# developer-retry (cap 3). Verdict in the 18-coverage-report.md frontmatter
|
||||
# (coverage_status:). See ADR-001-coverage-gate.md.
|
||||
# GATE_ENABLED -> global kill-switch; false -> pipeline 1:1 as before ORCH-027.
|
||||
# GATE_REPOS -> CSV of repos where the gate is REAL; empty -> only self-hosting.
|
||||
# MIN_PERCENT -> absolute floor (% line coverage) for policy absolute/both.
|
||||
# POLICY -> absolute | baseline | both (default both).
|
||||
# EPSILON -> noise tolerance (%) at the boundary (anti-flap).
|
||||
# TOOL_FAIL_CLOSED -> strict mode: a coverage-tool error -> FAIL instead of the
|
||||
# default fail-open + warning (anti-loop). Default false.
|
||||
# RUN_TIMEOUT_S -> wall-clock budget for the pytest --cov run.
|
||||
ORCH_COVERAGE_GATE_ENABLED=true
|
||||
ORCH_COVERAGE_GATE_REPOS=
|
||||
ORCH_COVERAGE_MIN_PERCENT=0.0
|
||||
ORCH_COVERAGE_POLICY=both
|
||||
ORCH_COVERAGE_EPSILON=0.5
|
||||
ORCH_COVERAGE_TOOL_FAIL_CLOSED=false
|
||||
ORCH_COVERAGE_RUN_TIMEOUT_S=900
|
||||
|
||||
# ORCH-021: post-deploy production monitoring + degradation reaction. After the
|
||||
# terminal deploy->done transition for an applicable repo, a reserved-agent job
|
||||
# `post-deploy-monitor` (no LLM, modelled on deploy-finalizer) probes prod over a
|
||||
|
||||
Reference in New Issue
Block a user