Twinned from https://github.com/cfsh/ninefold/issues/586 by tools/beads/import_github.py's reconcile pass.
tools/reviewer/README.md states the invariant absolutely:
> a green label must never certify a head the reviewer hasn't seen
The mechanism delivers it *eventually*, not never. Labels are re-derived per dispatcher tick, so between a push and the next tick — up to a full interval, ~30m — a PR keeps rev:pass while its verdict covers an older sha.
PR #578 at 17:33Z:
``` head = 1c3a0b4 labels = rev:pass, tier:2 verdict: REVIEWER-VERDICT sha=f8b16e9 ... result=CONVERGED ```
poll.py reported it correctly and loudly — NFR ... [STALE(sha-mismatch)] — because it compares the verdict sha against the live head on every read. The label did not, because nothing recomputes it until the dispatcher next sweeps. Two views of the same fact disagreeing, and only one of them is what a human looks at.
The label *is* the human interface. README.md builds the queue around it:
| 🟢 rev:pass | reviewer PASS or CONVERGED on current head | review/approve this |
and the documented filter is label:rev:pass,rev:escalated. So during the window, a PR whose newest commits no bot has read is sitting in the "ready for you" queue, described as passing *on current head*. Aedan approving on that basis has been told something that is not true — harmless when the push was a typo fix, less so when it was three behaviour changes, which is exactly what mine was.
It is also the one direction the design says it will not go. README.md explains the head-move trigger was widened to every verdict specifically to close *"the seam where an unapproved green PR rebuilt with no comment sat at rev:pending indefinitely — invisible to Aedan (yellow reads as 'wait')"*. That closed yellow-when-it-should-be-green. This is green-when-it-should-be-yellow, which is the more expensive direction.
dispatch.py --reconcile-only <n> does exactly the right thing in two API calls and spawns nothing. The gap is only that nobody runs it at push time. Options:
rev:pending is the honest state. One gh call in the push path.review_now.py reconciles first. Natural home now that #578 gives sessions a way to reach the dispatcher on demand, but it only helps sessions that call it.poll.py's *"nothing in this repo reads dispatch.log"*, false for fifty lines).Unclaimed. Found working #576; not folding it into that chunk.
None.
No comments.