Skip to content

coverage ratchet reports a bump when only the provenance moved #4087

Description

@chernistry

Correction (2026-08-18). The premise below — that the provenance-only write originates in _cmd_check's write path — is wrong, and was disproved on the thread. check reads its baseline out of the tree it checked out (the measured commit), which main has usually ratcheted past by the time that commit's CI run completes; the bump is correct against what it read and a no-op against the base the PR is opened onto. See this comment for the arithmetic and #4110 for the fix. The rest of this body is kept as written because the reproduction attempts against it are what located the real cause.

The coverage ratchet opened #4078 and #4085 carrying a diff that moves only provenance:

   "diff_coverage_floor_percent": 86,
-  "head_sha": "6902f699a30d1193a09a99129114af1b08920dfc",
+  "head_sha": "6bb9f3ed5990bf5c1d0c0d85f8d3a0789061824a",
   "line_rate": 0.8384,
-  "run_id": "31999416744",
+  "run_id": "32003768324",
   "total_coverage_percent": 83.84,
-  "updated_at": "2026-08-17T07:34:25+00:00"
+  "updated_at": "2026-08-17T08:43:49+00:00"
 }

line_rate and total_coverage_percent are byte-identical on both sides. Only head_sha, run_id and updated_at moved. A ratchet PR that raises nothing is noise on the queue: it costs a full CI matrix, it needs a human to look at it, and it trains reviewers to approve baseline PRs without reading the numbers — which is the one place the numbers are the entire point.

Expected

A ratchet fire that does not raise the high-water mark opens no PR, and says in its log why it declined.

Scope

The ratchet's decision path, not its measurement. coverage.xml is being produced correctly; the defect is downstream of it.

Proof

  • A unit test driving the exact numbers that produced chore(ci): ratchet coverage baseline up to 83.84% #4085, asserting no PR is proposed.
  • The refusal is logged as a ::notice:: naming the reason, and the run still ends green — a declined ratchet is an ordinary outcome, not a failure.
  • A test that a genuine rise still opens its PR, so the guard cannot pass by refusing everything.

Out of scope

  • The weekly bump-floor path, which writes with the measurement fields deliberately unchanged. Whatever shape the fix takes must not refuse it.
  • Changing the tolerance or the rounding.

The decision left to whoever takes this

Where the refusal belongs: in the write path, or at the decision point that gates the PR step. They are not equivalent, and the choice depends on which invariant you think is being violated. Name the one you took and why.

Metadata

Metadata

Labels

bugSomething isn't workingcigood first issueGood for newcomerssize/sup-for-grabsListed on up-for-grabs.net — no commitment, low friction

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions