Observed 2026-08-28 on jbkkz/requivo PR #198, filed from outside.
#1803 established the rule and #1804 swept the renders that still had their own copy of the arithmetic. The github-pr watch poller has a third copy, it was in neither sweep, and it is the one that wakes a session up.
What was observed
Two check runs named fragment on one head SHA (41830bf):
98915655232 fragment conclusion=cancelled started=16:37:39Z completed=16:37:39Z
98915659848 fragment conclusion=success started=16:37:42Z completed=16:37:50Z
This is #1803's discriminator satisfied exactly: the successful leg started strictly after the cancelled one completed, three seconds later. Not the overlapping code-scanning shape #1640 exists to protect. The forge agrees, reporting the PR MERGEABLE with no conflicts, and gh-check:pr:198 enumerates both runs correctly.
The poller emitted:
<channel watcher_source="github-pr" id="198" event="checks_failed" ...>
Where it comes from
presets/watch/sources/github-pr/poller.py::_rollup_state flattens the rollup into a list of state strings and asks:
if any(s in ("FAILURE", "TIMED_OUT", "CANCELLED", "ACTION_REQUIRED",
"STARTUP_FAILURE", "ERROR") for s in statuses):
return "FAILURE"
There is no grouping by name and no timing, so every leg on the SHA votes, including one that a later leg of the same name replaced. Its docstring says it "mirrors the heuristic the GitHub UI uses", and that was true before #1803 decided the heuristic was wrong here.
CANCELLED is the state where this bites hardest, and not by accident: a workflow with cancel-in-progress cancels the older run because a newer one started. The cancellation is the supersession. So the shape most likely to be superseded is the one the poller is guaranteed to see, on every repo that uses a concurrency group.
Why the push half is worse than the read half
#1803's cost was a reader looking twice, and it says so: "A loud false alarm costs a reader one look." That trade is right for an op somebody chose to run. It does not transfer to an event.
A checks_failed arriving on the channel is unsolicited. Nobody asked a question; the session is interrupted and told a pull request is failing. When the answer is wrong the reader has no local evidence that anything is off, because the whole point of the channel is that they were not looking. And it is sticky: _rollup_state's result is stored as checks_state and the next tick only emits on a change, so a PR that goes wrongly-red stays wrongly-red on the board until some other transition moves it.
Scope, measured rather than assumed
presets/watch/sources/github-pr/poller.py — affected. Its own arithmetic, no supersed anywhere in the file, in 0.51.0.
presets/watch/tiers/gh_prs.py — not affected. It imports _checks and goes through pr._reconcile_checks, so it consumes the fixed arithmetic. The radar board and the poller disagree about the same pull request for this reason, which is its own smell.
presets/_checks.py, github/pr.py, github/pr_merge.py, github/pr_create.py — carry the rule, as of A superseded check run is a third state, not a red leg (#1792) #1803/Three more renders still count a superseded check run as red: git-status, dashboard and gh-pr-create #1804.
Two notes on how this was seen
The channel event was produced by 0.47.0 (dated 2026-08-16), which this repo's ./supertool symlink is pinned to and which predates #1803 entirely, so on that version every render was red, not just the poller's. That is a local staleness problem and not yours.
What is yours is that I then read 0.51.0 and _rollup_state is unchanged there: same any(...) over ungrouped states, same CANCELLED in the tuple, no timing. I have not run 0.51.0 against this SHA, so the claim about it is read off the source rather than measured, and it is the only claim here that is.
What would settle it
The poller should not own a fourth answer to a question _checks.py already answers. #1803's own self-review found the same shape — the defect was a second call site, and it was pinned with a source guard that there is exactly one tally arithmetic in the op. The same guard, extended over presets/watch/, would have caught this one before it was reported.
If the poller cannot import _checks cheaply enough for a polling loop, the narrower fix is to apply #1803's discriminator where the states are collected: group the rollup by check name, and drop a leg when another leg of the same name started strictly after it completed. That rule is already written and already tested; what is missing is that this file never asked for it.
Observed 2026-08-28 on
jbkkz/requivoPR #198, filed from outside.#1803 established the rule and #1804 swept the renders that still had their own copy of the arithmetic. The
github-prwatch poller has a third copy, it was in neither sweep, and it is the one that wakes a session up.What was observed
Two check runs named
fragmenton one head SHA (41830bf):This is #1803's discriminator satisfied exactly: the successful leg started strictly after the cancelled one completed, three seconds later. Not the overlapping code-scanning shape #1640 exists to protect. The forge agrees, reporting the PR
MERGEABLEwith no conflicts, andgh-check:pr:198enumerates both runs correctly.The poller emitted:
Where it comes from
presets/watch/sources/github-pr/poller.py::_rollup_stateflattens the rollup into a list of state strings and asks:There is no grouping by name and no timing, so every leg on the SHA votes, including one that a later leg of the same name replaced. Its docstring says it "mirrors the heuristic the GitHub UI uses", and that was true before #1803 decided the heuristic was wrong here.
CANCELLEDis the state where this bites hardest, and not by accident: a workflow withcancel-in-progresscancels the older run because a newer one started. The cancellation is the supersession. So the shape most likely to be superseded is the one the poller is guaranteed to see, on every repo that uses a concurrency group.Why the push half is worse than the read half
#1803's cost was a reader looking twice, and it says so: "A loud false alarm costs a reader one look." That trade is right for an op somebody chose to run. It does not transfer to an event.
A
checks_failedarriving on the channel is unsolicited. Nobody asked a question; the session is interrupted and told a pull request is failing. When the answer is wrong the reader has no local evidence that anything is off, because the whole point of the channel is that they were not looking. And it is sticky:_rollup_state's result is stored aschecks_stateand the next tick only emits on a change, so a PR that goes wrongly-red stays wrongly-red on the board until some other transition moves it.Scope, measured rather than assumed
presets/watch/sources/github-pr/poller.py— affected. Its own arithmetic, nosupersedanywhere in the file, in 0.51.0.presets/watch/tiers/gh_prs.py— not affected. It imports_checksand goes throughpr._reconcile_checks, so it consumes the fixed arithmetic. The radar board and the poller disagree about the same pull request for this reason, which is its own smell.presets/_checks.py,github/pr.py,github/pr_merge.py,github/pr_create.py— carry the rule, as of A superseded check run is a third state, not a red leg (#1792) #1803/Three more renders still count a superseded check run as red: git-status, dashboard and gh-pr-create #1804.Two notes on how this was seen
The channel event was produced by 0.47.0 (dated 2026-08-16), which this repo's
./supertoolsymlink is pinned to and which predates #1803 entirely, so on that version every render was red, not just the poller's. That is a local staleness problem and not yours.What is yours is that I then read 0.51.0 and
_rollup_stateis unchanged there: sameany(...)over ungrouped states, sameCANCELLEDin the tuple, no timing. I have not run 0.51.0 against this SHA, so the claim about it is read off the source rather than measured, and it is the only claim here that is.What would settle it
The poller should not own a fourth answer to a question
_checks.pyalready answers. #1803's own self-review found the same shape — the defect was a second call site, and it was pinned with a source guard that there is exactly one tally arithmetic in the op. The same guard, extended overpresets/watch/, would have caught this one before it was reported.If the poller cannot import
_checkscheaply enough for a polling loop, the narrower fix is to apply #1803's discriminator where the states are collected: group the rollup by check name, and drop a leg when another leg of the same name started strictly after it completed. That rule is already written and already tested; what is missing is that this file never asked for it.