Summary
prci_delta's review_transitions policy and the prci-toolkit census both authorize a closing
task transition (verifying) off a PR number that a purely lexical ladder guessed, and neither has any
test of whether that PR is actually the task's deliverable. I have now had three separate design
reviews reject three different ways of testing it, each with a measured counterexample, and the reason
they all fail is structural rather than a coding mistake: deliverable ownership is a relation between
a task and a PR, and no field on the PR carries it. So I am asking for the sufficiency standard rather
than guessing a fourth time.
Same file as #454, different defect. #454 is the 300s timeout that makes the gate fail open silently;
this is the ownership predicate on the path the gate takes once it does run. They are independently
decidable, which is why this is a separate issue rather than a second question on that thread.
The defect that started it
resolve.py's ladder is lexical by design (it runs before any GitHub call, RUNBOOK position 4, and is
imported by this gate). With no explicit pointer on a task it falls through to t2b-sourcefield, which
reads the task's **Source:** header, i.e. by construction the PR the work is about, not the thing it
ships. Reproduced cold from a preserved rundir:
tier=t2b-sourcefield pr=110910
prstate.json['110910']['author'] = alexey-milovidov # measured in the SAME pass
owned_red.merged_parent_verdict(tags, merged_pr=110910)
-> {'status': 'verifying', 'verdict': 'DELIVERABLE-MERGED'}
#110910 is a maintainer's own merged PR. The task's real deliverable was my open #110929. verifying
is a closing pipeline (merge-verifier auto-closes after a clean 2 day window), so the write would have
retired a live P0 task with its LOGICAL_ERROR open and its fix PR unreviewed. It was refused by hand.
owed_writes.census reads merged/state/mergedAt from the record and never reads the author
sitting beside them; grep -c author owed_writes.py is 0 for the whole file, and 2 for
config/cron/gates/prci_delta.py, both in prose comments.
Why all three PR-side signals fail, measured
| signal |
refuted by |
author == groeneai |
rejects my own robot-raised backports. #120408 (Backport #119868 to 26.8) is author=robot-ch-test-poll2, MERGED, and is the only live deliverable of an on_review task. Hand-authoring a backport is forbidden (@ pufit, 2026-04-17), so every backport of mine is robot-raised. A groeneai-only test strands that task in on_review permanently and re-fires a hold every pass. |
author is a known CI robot (fleet/known-bots.txt) |
accepts everybody's backports. robot-ch-test-poll2 is shared: #121933 assignees scanhex12, #121934 assignees nikitamikhaylov,vitlibar, both MERGED. The registry is documented as a human/bot routing list, and it is not evidence of ownership. |
groeneai in assignees |
cannot separate "my deliverable" from "a PR I was assigned to triage", which is routine. #120408's assignees are fm4v,groeneai, and that task's own record says my part there is triage plus the finish ledger and that nothing on it is pushable by me, ever. |
The one thing that does carry the relation is the task's own explicit pointer, and that is exactly what
is missing in the failing cases. resolved.json already records which tier fired, but nothing consumes
the tier as an authorization level.
Which sufficiency standard should authorize a closing transition?
- A Only an explicit deliverable pointer: tiers
t0-related_pr, t0b-bold-deliv, t1-saga,
t4-tag-deliv. Every inferred tier (t2b-sourcefield, t2c-paren, t3-prose, t8-tag, t9-title, ...)
is insufficient for a closing write, so those tasks hold and are reported per task until a human or
the publish saga records a pointer. Handles both cases above correctly. Cost: a hold class that needs a
human to clear, and I cannot tell you its size without your answer to the next sentence, because it
depends on whether the same standard applies to the non-closing transitions.
- B Keep an authorship screen, with a corroboration rule you specify. I could not find one that
survives the three rows above, but you may know a field I do not.
- C Neither. Accept the current behaviour and keep relying on the per-task mitigation
(overrides.json plus apply_overrides.py, or a deliverable-pr-<N> tag), which is what is in place
for the case above today.
Worth weighing explicitly, because the two failure directions are not symmetric: today's behaviour fails
silently and closes a live task, while A's failure mode is a loud, self-announcing hold.
One word is enough. The implementation plan is already written and reviewed to the point where only this
choice is missing, so whichever you pick I can apply it without re-investigating.
What I cannot do
fleet/prci-toolkit/ and config/cron/gates/prci_delta.py are not in this repository (contents/fleet
is a 404) and the workspace on the box is not a git repository, so propose_config_change has nothing to
open a pull request against, and my own rules forbid editing a gate or the toolkit from inside a monitor
tick. That is the same constraint as #454, and it is why I am asking here rather than pushing something.
Summary
prci_delta'sreview_transitionspolicy and theprci-toolkitcensus both authorize a closingtask transition (
verifying) off a PR number that a purely lexical ladder guessed, and neither has anytest of whether that PR is actually the task's deliverable. I have now had three separate design
reviews reject three different ways of testing it, each with a measured counterexample, and the reason
they all fail is structural rather than a coding mistake: deliverable ownership is a relation between
a task and a PR, and no field on the PR carries it. So I am asking for the sufficiency standard rather
than guessing a fourth time.
Same file as #454, different defect. #454 is the 300s timeout that makes the gate fail open silently;
this is the ownership predicate on the path the gate takes once it does run. They are independently
decidable, which is why this is a separate issue rather than a second question on that thread.
The defect that started it
resolve.py's ladder is lexical by design (it runs before any GitHub call, RUNBOOK position 4, and isimported by this gate). With no explicit pointer on a task it falls through to
t2b-sourcefield, whichreads the task's
**Source:**header, i.e. by construction the PR the work is about, not the thing itships. Reproduced cold from a preserved rundir:
#110910 is a maintainer's own merged PR. The task's real deliverable was my open #110929.
verifyingis a closing pipeline (
merge-verifierauto-closes after a clean 2 day window), so the write would haveretired a live P0 task with its
LOGICAL_ERRORopen and its fix PR unreviewed. It was refused by hand.owed_writes.censusreadsmerged/state/mergedAtfrom the record and never reads theauthorsitting beside them;
grep -c author owed_writes.pyis 0 for the whole file, and 2 forconfig/cron/gates/prci_delta.py, both in prose comments.Why all three PR-side signals fail, measured
author == groeneaiBackport #119868 to 26.8) isauthor=robot-ch-test-poll2, MERGED, and is the only live deliverable of anon_reviewtask. Hand-authoring a backport is forbidden (@ pufit, 2026-04-17), so every backport of mine is robot-raised. Agroeneai-only test strands that task inon_reviewpermanently and re-fires a hold every pass.author is a known CI robot(fleet/known-bots.txt)robot-ch-test-poll2is shared: #121933 assigneesscanhex12, #121934 assigneesnikitamikhaylov,vitlibar, both MERGED. The registry is documented as a human/bot routing list, and it is not evidence of ownership.groeneai in assigneesfm4v,groeneai, and that task's own record says my part there is triage plus the finish ledger and that nothing on it is pushable by me, ever.The one thing that does carry the relation is the task's own explicit pointer, and that is exactly what
is missing in the failing cases.
resolved.jsonalready records which tier fired, but nothing consumesthe tier as an authorization level.
Question (@alex-clickhouse)
Which sufficiency standard should authorize a closing transition?
t0-related_pr,t0b-bold-deliv,t1-saga,t4-tag-deliv. Every inferred tier (t2b-sourcefield,t2c-paren,t3-prose,t8-tag,t9-title, ...)is insufficient for a closing write, so those tasks hold and are reported per task until a human or
the publish saga records a pointer. Handles both cases above correctly. Cost: a hold class that needs a
human to clear, and I cannot tell you its size without your answer to the next sentence, because it
depends on whether the same standard applies to the non-closing transitions.
survives the three rows above, but you may know a field I do not.
(
overrides.jsonplusapply_overrides.py, or adeliverable-pr-<N>tag), which is what is in placefor the case above today.
Worth weighing explicitly, because the two failure directions are not symmetric: today's behaviour fails
silently and closes a live task, while A's failure mode is a loud, self-announcing hold.
One word is enough. The implementation plan is already written and reviewed to the point where only this
choice is missing, so whichever you pick I can apply it without re-investigating.
What I cannot do
fleet/prci-toolkit/andconfig/cron/gates/prci_delta.pyare not in this repository (contents/fleetis a 404) and the workspace on the box is not a git repository, so
propose_config_changehas nothing toopen a pull request against, and my own rules forbid editing a gate or the toolkit from inside a monitor
tick. That is the same constraint as #454, and it is why I am asking here rather than pushing something.