Skip to content

test(coverage): require 100% coverage for changed Python code - #1139

Closed
doublewhy wants to merge 8 commits into
devfrom
ASR-505-coverage-ratchet-successor
Closed

test(coverage): require 100% coverage for changed Python code#1139
doublewhy wants to merge 8 commits into
devfrom
ASR-505-coverage-ratchet-successor

Conversation

@doublewhy

@doublewhy doublewhy commented Aug 12, 2026

Copy link
Copy Markdown

Plain-language summary

Context. OpenRAE already runs a large unit and integration test suite, and CI publishes coverage to SonarCloud.

Problem. The old gate looked only at overall line coverage and allowed the repository to remain above a 50% average. A new or edited branch could therefore be untested while CI still passed. Changes could also evade measurement by narrowing Coverage.py configuration, moving reports, omitting repository tooling, or using exclusions that looked structural but still ran at runtime.

Fix. This PR measures both statements and branches across shipped Python and repository tooling. It requires every changed executable statement and every exit from a changed branch to run, validates the coverage configuration and report paths, and records an honest whole-repository baseline that may rise but cannot be lowered. Existing untested legacy code is tracked by the aggregate ratchet; this PR does not claim that the whole repository is already at 100% coverage.

Closes #1104.

What changed

  • Enables Coverage.py branch data and measures shipped packages, tools/, noxfile.py, and the Hatch build hook.
  • Requires distinct, non-empty unit and integration coverage artifacts before combining them.
  • Compares changed Python with the exact base SHA supplied by CI and rejects unknown or non-ancestor bases.
  • Requires 100% coverage for changed executable lines and changed branch exits, including multiline conditions, match guards, comprehensions, and deletion-only semantic edits.
  • Maps physical edits to their executable owners so continuation-line changes cannot disappear between Git's line model and Coverage.py's statement model.
  • Rejects coverage pragmas or configuration changes that hide changed runtime code.
  • Treats TYPE_CHECKING and Protocol exclusions as structural only when their imports and namespaces cannot be rebound dynamically; eagerly evaluated annotations, defaults, decorators, and class bases remain coverage obligations.
  • Publishes canonical repository-rooted XML and JSON reports with repository-relative filenames for SonarCloud.
  • Keeps tools/coverage_ratchet.json at a canonical path and rejects lowering or deleting it after adoption. The recorded historical floors remain 89.739% statements and 75.638% branches.

Verification

Rebased without conflict onto exact base 96b20ae8422fae9936bae928bbd8a1c14d2001da; candidate head 9ec37b568ed83b962783f143e318db31a675fbaa.

  • Eight-commit range-diff: behavior preserved; only import-context movement from changes already merged into dev.
  • Focused adversarial coverage and Nox tests on CPython 3.12.13: 344 passed, 1 deselected.
  • Local unit lane: 7,058 passed, 1 skipped. Local integration lane: 59 passed, 2 skipped.
  • Local two-artifact combine accepted distinct unit (6,709,248 bytes) and integration (3,543,040 bytes) inputs and passed the policy.
  • Local combined result: 77,273 / 85,710 statements (90.156%) and 20,474 / 26,802 branches (76.390%), above both monotonic floors.
  • Changed-code gate: 626 / 626 executable lines and 240 / 240 branch exits covered.
  • Repository policy, requirement governance, contracts, static checks, docs, Ruff formatting, and Ruff lint passed.
  • Hosted Ubuntu exact-head CI run 31665503280, verify job 94339074943: all deterministic lanes passed, including 7,058 unit tests, 59 integration tests, and the pinned Isabelle proof. The production combine printed COVERAGE_POLICY_PASS against exact base 96b20ae8422fae9936bae928bbd8a1c14d2001da.
  • Hosted coverage artifact: 77,273 / 85,710 statements (90.156%) and 20,473 / 26,802 branches (76.386%). Its XML contains one /home/runner/work/rae/rae source and 833 repository-relative filenames, with no absolute or escaping filenames.
  • Hosted fuzz, supply-chain, real Docker integration, Docs, CodeQL, GitGuardian, and title checks passed.
  • Sonar job 94340403950 parsed the canonical XML, passed the quality gate, and completed successfully.

Scope and merge notes

This PR is independently based on current dev. It does not include Python compatibility, runtime, libvirt, OCI, or release-admission changes except where those changes are already present in the base. The coverage floor was not weakened during the refresh.

@doublewhy
doublewhy marked this pull request as ready for review August 13, 2026 00:13
@doublewhy
doublewhy marked this pull request as draft August 13, 2026 00:13
@doublewhy
doublewhy marked this pull request as ready for review August 13, 2026 00:14
@Brad-Edwards

Copy link
Copy Markdown
Collaborator

Thanks for the thorough work on this. After review, we’re going to decline this PR and submit a smaller replacement.

The replacement will retain the useful measurement improvements—branch coverage, complete repository-owned Python scope, and canonical reports—while enforcing the repository’s 90% coverage policy through standard Coverage.py capabilities.

We will omit the manual ratchet, 100% changed-code requirement, and custom semantic hardening. The hardening threat model is inconsistent with ADR-015, which treats repository-mutable policy as protection against accidental regressions rather than an adversarial security boundary. Because this checker and its invocation remain editable in the same PR, the implementation also cannot provide the claimed tamper resistance.

The revised coverage policy and its relationship to ADR-014 will be documented before implementation. Thank you for the careful investigation and extensive testing; it helped clarify the narrower change we need.

@doublewhy
doublewhy marked this pull request as draft August 13, 2026 03:57
@doublewhy
doublewhy force-pushed the ASR-505-coverage-ratchet-successor branch from ac98e2f to 9ec37b5 Compare August 13, 2026 03:57
@doublewhy
doublewhy marked this pull request as ready for review August 13, 2026 04:09
@doublewhy

Copy link
Copy Markdown
Author

Closing as superseded by #1143, merged into dev as 8c9365cad7d1d4610cca45cf3c91cbe9c8933a83. #1143 keeps branch visibility and the fixed 90% aggregate line floor without the manual ratchet or 100% changed-code gate.

@doublewhy doublewhy closed this Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants