Skip to content

fix(coverage): honor repository coverage source instead of excluding tools #2010

Open

Description

@seonghobae

Defect

ContextualWisdomLab/newsdom-api declares its owned Python coverage boundary in pyproject.toml as:

[tool.coverage.run]
source = ["src/newsdom_api", "tools"]
branch = true

[tool.coverage.report]
fail_under = 100

but the live repository test workflow invokes:

uv run pytest --cov=src/newsdom_api --cov-branch --cov-report=term-missing --cov-fail-under=100

The explicit --cov=src/newsdom_api narrows coverage.py's source selection and excludes production tools/*.py, even though the project-level authority includes tools and fleet quality policy requires owned production statement/branch coverage 100%.

Exact evidence

Consumer canary: ContextualWisdomLab/newsdom-api#820@d1424fdd05b6fc8a7acffbfe9593f67971e2b376, tests run 34112404701, pytest job 101711385647.

The job collected 492 tests and tests/test_tools_export_jsonl.py passed all 9 tests, but the coverage table contained only src/newsdom_api/* and reported 829 statements / 254 branches at 100%. No tools/export_jsonl.py row was measured. The run ultimately failed for unrelated CHANGELOG regressions; those were repaired by normal descendant 28d63d699abb2d777f988e56fac5d32486dc9f97, whose tests run 34112582990 is terminal SUCCESS. That success still uses the same narrowed workflow command, so it is not evidence of 100% statement/branch coverage for the exporter.

Current workflow path in consumer: .github/workflows/tests.yml; current command is the explicit --cov=src/newsdom_api invocation above. The consumer should not add # pragma: no cover, reduce thresholds, or maintain an ad-hoc second coverage contract to compensate.

Owner boundary

CI/review/security/release is the organization .github foundation responsibility. Keep the consumer feature PR focused on its domain behavior. Repair this through the canonical reusable workflow/thin-caller or organization CI contract rather than proliferating per-repository coverage semantics.

RED

A deterministic contract should prove that when a repository declares more than one production coverage source, an explicit workflow --cov=<subset> can still produce a nominal 100% report while an owned source tree is unmeasured. newsdom-api provides the concrete canary: tools/export_jsonl.py executes in tests but is absent from the coverage report.

GREEN acceptance

  • Central/reusable Python coverage execution honors the repository's declared [tool.coverage.run].source, or otherwise consumes an immutable trusted source list without narrowing it in a leaf caller.
  • On unchanged newsdom-api#820 exact head, the coverage report includes both src/newsdom_api and tools, with production statement coverage 100% and branch coverage 100%.
  • Missing/unmeasured production source is fail-closed, not treated as 100%.
  • Existing 100% threshold, warning-as-error behavior, test execution and branch protection remain intact.
  • No coverage exclusion marker, test deletion, source-neutral retrigger, self-approval, or gate weakening.
  • The repaired central workflow is exact-SHA validated, documented, and released/versioned if consumed cross-repository; the consumer then bumps to that immutable release and re-proves exact-head GREEN.

This issue is evidence/acceptance only from the fleet loop; no .github source/docs/refs/PR-state was mutated.

Activity

  1. seonghobae commented on Sep 9, 2026

    @seonghobae
    ContributorAuthor

    Fresh owner-path canary from ContextualWisdomLab/newsdom-api#832@330f21c043948f0cbe75ce5605501a0eabc110b4 exposes a second, independent coverage-authority defect in the same central gate. Required Coverage gate run 34288889002, job 102273598128 (Validate coverage) executed the leaf test command successfully: 738 passed, 4 skipped, coverage.xml/coverage.json were produced, and the reports were about 93.4–93.8% line coverage (coverage.py total rounded 94.00%). The validator then printed Resolved coverage threshold: 90.0 but failed the same job with coverage.py total 94.00% failed floor 100.00% in Validate project-owned coverage artifact.

    This is not a #832 lockfile/source regression. The failing run is owned by this central repository and the leaf delta is only uv.lock (pypdf 6.15.0 -> 6.16.1). It also should not be repaired by lowering a real 100% quality contract: the causal defect is that threshold resolution and threshold enforcement disagree about the authoritative floor.

    RED: a deterministic fixture where the resolved authoritative threshold is 90.0 and measured coverage is 94.0 must not subsequently be compared with an unexplained 100.0 floor; conversely, if policy authority is actually 100.0, the resolver must report 100.0 and its provenance before validation.

    GREEN: use one authenticated threshold value/source throughout resolution, artifact validation, summary, and terminal verdict; fail closed on conflicting threshold authorities rather than silently choosing a different floor. Pin repository/head/base/run identity and preserve source-tree completeness. Do not accept coverage exclusions, --cov-fail-under=0 as terminal authority, synthetic status, optimistic timeout, predecessor evidence, or a leaf no-op retrigger. After the central exact-head fixture is GREEN, re-evaluate the unchanged #832 head (or its ordinary descendant if the base has advanced) and require the required Coverage gate to terminate successfully before merge.

    This comment is evidence/acceptance only; no .github source/docs/refs/PR-state was changed by the fleet loop.

  2. seonghobae commented on Sep 13, 2026

    @seonghobae
    ContributorAuthor

    Owner-attribution check against the cited runs, 2026-09-13:

    Defect 1 (--cov=src/newsdom_api narrows the declared source) is repository-owned, not central. Run 34112404701 is newsdom-api/.github/workflows/tests.yml (referenced_workflows empty — no reusable workflow from this repository is involved), and quality-gate.yml:37 carries the same command. The declared [tool.coverage.run].source = ["src/newsdom_api", "tools"] is overridden by the CLI flag, exactly as described. Registered with the owner: ContextualWisdomLab/newsdom-api#860 (minimal fix: drop the explicit --cov= or add --cov=tools; keep the 100% floor). A central reusable Python test workflow that forbids leaf narrowing would be a new scope decision, not a repair of existing central code.

    Defect 2 as quoted could not be reproduced from the cited evidence. Job 102273598128 belongs to .github run 34288889002 (opencode-review-dispatch.yml @ 7fd571dbc), job coverage-evidence; its failing step is Measure test and docstring evidence, not "Validate coverage" / "Validate project-owned coverage artifact". The strings Resolved coverage threshold: 90.0, failed floor 100.00% and coverage.py total 94.00% appear nowhere in that run's 11,680-line log, and git log -S finds them in no revision of this repository's workflows or scripts/ci. The actual terminal error in that job is:

    ::error::Trusted base Python lock preflight failed for uv.lock; only incomplete hash closures or explicit Python interpreter incompatibility may be deferred …
      pillow==12.3.0 … Expected <hashes from uv.lock> … Got 251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b
    

    i.e. the consumer's uv.lock hash set for pillow==12.3.0 did not contain the wheel the trusted preflight downloaded — a lock/hash-closure fail-closed, which is the class handled by the open lock-validation lanes (#1398, #2094), not a coverage-threshold disagreement. No threshold-authority defect is evidenced by this run; if one exists it needs a run whose log actually shows the two conflicting floors.

    Leaving this issue open for the owner to re-scope (defect 1 → consumer issue above; defect 2 → withdraw or re-evidence).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: highHigh-priority or P1 work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions