From bb1268f8420082c478421e6831b07c568a6fd2b3 Mon Sep 17 00:00:00 2001 From: Exploit Intel Date: Wed, 19 Aug 2026 04:28:26 -0400 Subject: [PATCH] Tighten the coverage gate to the measured floor Four gaps against the campaign standard in eipv3-quality-campaign.md. This repository was already the closest to it: four gates, required-version, the mypy stale-exemption guard, an ASCII-dash check nothing else has, and every Action pinned across all three workflows. The coverage gate was 90 against a measured 93.24 floor, so three points of slide were allowed. Now 92, in all four places that carry the figure: both the quality and the release workflow, AGENTS.md, and CONTRIBUTING.md. Raising only the pull-request gate would have left the path that publishes to PyPI as the lax one, which is backwards, and CONTRIBUTING.md ships inside the sdist so a stale figure would have been published with the package. pytest-cov moves from >=5 to ==7.1.0 and coverage is pinned at ==7.15.4. They produce the gated number, and coverage.py's statement set is not stable across its own releases. build gains the <2 cap that both workflows already apply, so a local build no longer resolves differently from CI. twine keeps its range, but not for the reason an earlier draft of this message gave. `twine check` is a hard step in both workflows, so a gate does depend on its version. Pinning it in requirements-dev.txt would not have helped: the constraint the gate actually uses is the literal "twine>=6,<7" inside each workflow, and the strictness comes from the unpinned transitive readme-renderer. The warn_unused_configs comment claimed an exemption cannot outlive the errors it was added for. That is false: the flag fires only when an override names a module mypy never processes, so a module whose errors were fixed keeps its exemption silently. AGENTS.md now records that this suite's coverage is terminal-width dependent. Rich sizes output to the terminal, so a wide one executes render branches a narrow one does not: 93 percent unset or at 80 columns, 95 at 140. CI has no tty and sees 93. --- .github/workflows/quality.yml | 2 +- .github/workflows/release.yml | 2 +- AGENTS.md | 8 +++++++- CONTRIBUTING.md | 2 +- pyproject.toml | 8 +++++--- requirements-dev.txt | 5 +++-- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index ea4b97b..c267ef8 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -54,7 +54,7 @@ jobs: - name: Pytest run: >- python -m pytest -q - --cov=eip_search_v3 --cov-report=term-missing --cov-fail-under=90 + --cov=eip_search_v3 --cov-report=term-missing --cov-fail-under=92 package: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67a330a..ecbc2be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,7 +51,7 @@ jobs: run: | ruff check src tests python -m pytest -q -m 'not live' \ - --cov=eip_search_v3 --cov-report=term-missing --cov-fail-under=90 + --cov=eip_search_v3 --cov-report=term-missing --cov-fail-under=92 - name: Build and validate distributions run: | diff --git a/AGENTS.md b/AGENTS.md index 93b2468..e4a966f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,10 +42,16 @@ python -m pip install -e . ruff check src tests ruff format --check src tests mypy -pytest -q -m 'not live' --cov=eip_search_v3 --cov-fail-under=90 +pytest -q -m 'not live' --cov=eip_search_v3 --cov-fail-under=92 ! git grep --untracked -n -I -P '[\x{2013}\x{2014}]' -- . # CI rejects en/em dashes ``` +Run that with a narrow or unset `COLUMNS`. Rich sizes its output to the terminal, +so a wide terminal executes render branches a narrow one does not: this suite +reports 93 percent unset or at 80 columns and 95 percent at 140. CI has no tty and +sees 93, so a wide local terminal will suggest roughly twice the headroom that +actually exists. + CI enforces that dash check, the coverage floor, and a packaging job that asserts CLI help text and examples, so changing a banner or an example string can fail the build. `CONTRIBUTING.md` carries the full local suite. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c17de74..65a75e7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ Run the local quality suite before opening a pull request: ```sh ! git grep -n -I -P '[\x{2013}\x{2014}]' -- . # CI rejects en/em dashes ruff check src tests -pytest -q -m 'not live' --cov=eip_search_v3 --cov-fail-under=90 +pytest -q -m 'not live' --cov=eip_search_v3 --cov-fail-under=92 python -m build python -m twine check dist/* ``` diff --git a/pyproject.toml b/pyproject.toml index 52eb720..14cda97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,9 +44,11 @@ where = ["src"] python_version = "3.12" files = ["src"] ignore_missing_imports = true -# Report an override that matches nothing, so an exemption cannot outlive the -# errors it was added for. mypy prints that as a note and still exits 0, so the -# CI step greps for it and fails. +# Report an override that names a module mypy never processes, so a renamed or +# deleted entry cannot linger. mypy prints that as a note and still exits 0, so +# the CI step greps for it and fails. Note the limit: this does NOT catch a +# module whose errors were fixed but whose exemption stayed, because the module +# still exists and is still processed. warn_unused_configs = true # Type checking is a ratchet, not an allowlist. Everything is checked by default diff --git a/requirements-dev.txt b/requirements-dev.txt index 8ac1883..eaa8e49 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,7 @@ -build>=1.2 +build>=1.2,<2 twine>=6,<7 pytest==8.4.2 -pytest-cov>=5 +pytest-cov==7.1.0 ruff==0.16.3 mypy==2.3.1 +coverage==7.15.4