You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Kernel: what takes a pull request out of the merge queue #33
Part of the epic "Epic: nine gaps in the Kernel, found in review".
Why. A queued pull request with no standing approval, or with a writer's open thread, stays queued and the Kernel does nothing. The Decision schema has no action for it, the Lifecycle has no transition the Factory makes out of queued, and a Hold label does not take it out either.
Done when
The Maintainer rules on what takes it out: the action, and whether a Hold does the same.
The action is in schemas/decision.schema.json and the transition in lifecycle/pull_request.json.
test_a_queued_pull_request_with_no_approval_leaves_the_queue passes with @pending removed, with its mutant.
The simulator has a fault for it: an approval withdrawn, or a writer's thread opened, while queued.
Advice from the Solution Architect persona, not a ruling. Asked while revising the pull request "Context for the Factory's authors: lessons, standards, decisions and the checks that hold them".
A lost approval: settled. Record 0007 and ADR-0013 decision 7 say the pull request leaves the queue (PRD FR-31).
A Pause: settled against, if a Pause stops every act. Dequeuing is an act, and under ADR-0013 decision 3 no Factory code runs. So under a Pause a queued pull request that loses its approval still merges, which is the failure in the lesson "The merge queue looked at reviews only on the way in". That consequence is the Maintainer's to accept or to carve out.
A Hold: open. (a) factory:hold dequeues, as the one change the Factory makes to a held item, with I-21 and the §4.7 Hold row reworded to say so; (b) it does not, and the Maintainer takes the pull request out by hand. Today kernel/derive.py reads the label before the queue, so a held, queued pull request merges.
Recommended: (a), for factory:hold and not for factory:hands-off. What would change this: a trial showing the Controller's App cannot dequeue, or loses the race to the merge. Trial P-2 covers entering the queue only.
#33 Kernel: what takes a pull request out of the merge queue
Working ruling (Solution Architect, delegated). The Maintainer may overturn it in review.
Question. What does the Kernel do with a queued pull request whose approval no longer stands for its content, or that an open gate or a Hold now stops?
Options.
The Decision is act, action dequeue, made by the Controller's App. factory:hold dequeues; factory:hands-off does not. This closes L-19.
dequeue for a lost approval or an open gate only. A held item still merges unless the Maintainer takes it out by hand.
Do nothing. L-19 stays open.
Ruling: 1.
FR-31 says a withdrawal "removes the pull request from the merge queue".
I-9 allows no approval, and so no merge, without Convergence on that content.
FR-23 says a Hold stops every Effect, and a merge is the last Effect. Dequeuing is a stop, not work, so it is the one change the Factory makes to a held item.
test_a_queued_pull_request_with_no_approval_leaves_the_queue passes with @pending removed. It gives queued, act, dequeue and reason approval_lost. A writer's thread or request for changes gives reason gate_open. A standing approval with no open gate gives nothing.
test_a_hold_takes_a_queued_pull_request_out: a Hold dequeues with reason human_hold; hands-off does not; a Pause defers with reason paused. Each of the three reasons has a mutant.
dequeue is added to schemas/decision.schema.json and its example. lifecycle/pull_request.json declares queued → converged, addressing, verifying, adjudicating and held, by factory, with bound max_acts_per_item (Kernel: how an act is recorded and bounded #37).
The simulator gains three faults while queued: an approval dismissed, a writer's thread opened, a Hold added.
Documents: design §4.1, the §4.7 Hold row and I-21 (add "except to take it out of the merge queue"); remove "not held yet" from decision 0007 and L-19.
Confidence. High on the rule; medium on the platform. I would rule otherwise if trial P-2, extended to removal from the queue, shows the App cannot dequeue or loses the race to the merge. A required check on merge_group that refuses unapproved content would then do the job.
Needs the Maintainer? Yes, on one point of risk: accepting that under a Pause, a queued pull request that loses its approval can still merge. It would then show up afterwards as a merge with no Override record (FR-28).
Maintainer ruling, 2026-10-14: the working ruling above stands, including the point of risk: under a Pause the dequeue defers like every other act, and a queued pull request that loses its approval while paused may merge, to be found afterwards as a merge with no Override record (FR-28). This story is ready to build after #34, #37 and #38.
Added scope, from the review of #34 (2026-10-15): a writer's request for changes, or thread, made after the item enters the merge queue is never read. derive.py returns queued first, and simulator seed 202 merges over the request. #34 pins this as a pending test (test_a_request_for_changes_made_while_queued_takes_it_out_of_the_queue) and a decision 0007 row, "not held yet". This story's dequeue should take that test off pending.
Working ruling: a queued pull request stays only while the Kernel can show it may merge
Working ruling (delegated), from the review and security passes on the branch for this story. The Maintainer may overturn it in review.
Question. The first build takes an item out of the queue for a lost approval, an open gate and factory:hold. The passes found other states that sort above the queue check and leave a queued item in the queue, so it merges:
another Hold: outside_not_admitted (factory:admit removed from a queued outside pull request) and too_large;
a read that fails: facts_incomplete and review_unreadable defer, and the queue merges meanwhile;
a required check now failing, or a required Lens added, after the item entered the queue.
Ruling. A queued pull request stays in the queue only when, read as if it were not queued, it would be approved and ready to merge. Every other reading takes it out with dequeue, the reason being the reason that reading gives (approval_lost, gate_open, human_hold, outside_not_admitted, too_large, a check's reason, and the unreadable reasons). Two exceptions stand: hands-off never acts, and under a Pause, or a Pause that cannot be read, the dequeue defers.
A dequeue is a stop, not work, so a read that fails takes the item out rather than leaving it in. I-13 gains "except to take a pull request out of the merge queue", the same exception I-21 gains.
FR-23: a Hold stops every Effect, and a merge is the last one. That holds for every Hold, not only factory:hold.
I-9: no merge without Convergence on that content. A check that fails while queued breaks Convergence.
Every deferred dequeue shows needs_you, not ready: under a Pause only the Maintainer can stop the merge.
Not here. Who set a label (factory:hands-off, factory:hold, factory:admit) and who resolved a thread are not in the pull request's facts. That is "Kernel: what a person placed, only a person ends" (#61), next but two in this epic's order.
Recorded. The simulator assumes the queue merges only after a whole, current read (a_pass_comes_before_the_merge). The rule's words are made to say that, and trial P-2 gains the question of whether the poller's cadence beats the queue. The ruling's fallback still stands: a required merge_group check that refuses content the Kernel would take out.
Confidence. High on the rule. I would rule otherwise if dequeuing on a read that fails were to empty the queue in normal running, for example because a list is read short on every large pull request. The trial would show that.
Maintainer ruling, 2026-10-15: accepted. Under a Pause, or a Pause that cannot be read, the dequeue defers like every other act (decision 0003). A queued pull request may then merge over a lost approval, a writer's request for changes or thread, a Hold, or a check that no longer passes. Only the lost approval is found afterwards by FR-28. Every deferred dequeue shows needs_you, so the Maintainer sees it before the merge, and the design names each case.
Activity
don-petry commentedon Oct 14, 2026
Advice from the Solution Architect persona, not a ruling. Asked while revising the pull request "Context for the Factory's authors: lessons, standards, decisions and the checks that hold them".
factory:holddequeues, as the one change the Factory makes to a held item, with I-21 and the §4.7 Hold row reworded to say so; (b) it does not, and the Maintainer takes the pull request out by hand. Todaykernel/derive.pyreads the label before the queue, so a held, queued pull request merges.Recommended: (a), for
factory:holdand not forfactory:hands-off. What would change this: a trial showing the Controller's App cannot dequeue, or loses the race to the merge. Trial P-2 covers entering the queue only.don-petry commentedon Oct 14, 2026
#33 Kernel: what takes a pull request out of the merge queue
Working ruling (Solution Architect, delegated). The Maintainer may overturn it in review.
Question. What does the Kernel do with a queued pull request whose approval no longer stands for its content, or that an open gate or a Hold now stops?
Options.
act, actiondequeue, made by the Controller's App.factory:holddequeues;factory:hands-offdoes not. This closes L-19.dequeuefor a lost approval or an open gate only. A held item still merges unless the Maintainer takes it out by hand.Ruling: 1.
dequeuedefers like every other act (Kernel: a Pause stops every act, not only Runs #30). No Factory code runs under a platform Pause (decision 0003).Acceptance criteria.
test_a_queued_pull_request_with_no_approval_leaves_the_queuepasses with@pendingremoved. It givesqueued,act,dequeueand reasonapproval_lost. A writer's thread or request for changes gives reasongate_open. A standing approval with no open gate givesnothing.test_a_hold_takes_a_queued_pull_request_out: a Hold dequeues with reasonhuman_hold; hands-off does not; a Pause defers with reasonpaused. Each of the three reasons has a mutant.dequeueis added toschemas/decision.schema.jsonand its example.lifecycle/pull_request.jsondeclaresqueued→converged,addressing,verifying,adjudicatingandheld, byfactory, with boundmax_acts_per_item(Kernel: how an act is recorded and bounded #37).Documents: design §4.1, the §4.7 Hold row and I-21 (add "except to take it out of the merge queue"); remove "not held yet" from decision 0007 and L-19.
Confidence. High on the rule; medium on the platform. I would rule otherwise if trial P-2, extended to removal from the queue, shows the App cannot dequeue or loses the race to the merge. A required check on
merge_groupthat refuses unapproved content would then do the job.Needs the Maintainer? Yes, on one point of risk: accepting that under a Pause, a queued pull request that loses its approval can still merge. It would then show up afterwards as a merge with no Override record (FR-28).
don-petry commentedon Oct 14, 2026
Maintainer ruling, 2026-10-14: the working ruling above stands, including the point of risk: under a Pause the dequeue defers like every other act, and a queued pull request that loses its approval while paused may merge, to be found afterwards as a merge with no Override record (FR-28). This story is ready to build after #34, #37 and #38.
don-petry commentedon Oct 15, 2026
Added scope, from the review of #34 (2026-10-15): a writer's request for changes, or thread, made after the item enters the merge queue is never read.
derive.pyreturnsqueuedfirst, and simulator seed 202 merges over the request. #34 pins this as a pending test (test_a_request_for_changes_made_while_queued_takes_it_out_of_the_queue) and a decision 0007 row, "not held yet". This story's dequeue should take that test off pending.don-petry commentedon Oct 15, 2026
Working ruling: a queued pull request stays only while the Kernel can show it may merge
Working ruling (delegated), from the review and security passes on the branch for this story. The Maintainer may overturn it in review.
Question. The first build takes an item out of the queue for a lost approval, an open gate and
factory:hold. The passes found other states that sort above the queue check and leave a queued item in the queue, so it merges:outside_not_admitted(factory:admitremoved from a queued outside pull request) andtoo_large;facts_incompleteandreview_unreadabledefer, and the queue merges meanwhile;Ruling. A queued pull request stays in the queue only when, read as if it were not queued, it would be approved and ready to merge. Every other reading takes it out with
dequeue, the reason being the reason that reading gives (approval_lost,gate_open,human_hold,outside_not_admitted,too_large, a check's reason, and the unreadable reasons). Two exceptions stand: hands-off never acts, and under a Pause, or a Pause that cannot be read, the dequeue defers.factory:hold.needs_you, notready: under a Pause only the Maintainer can stop the merge.Not here. Who set a label (
factory:hands-off,factory:hold,factory:admit) and who resolved a thread are not in the pull request's facts. That is "Kernel: what a person placed, only a person ends" (#61), next but two in this epic's order.Recorded. The simulator assumes the queue merges only after a whole, current read (
a_pass_comes_before_the_merge). The rule's words are made to say that, and trial P-2 gains the question of whether the poller's cadence beats the queue. The ruling's fallback still stands: a requiredmerge_groupcheck that refuses content the Kernel would take out.Confidence. High on the rule. I would rule otherwise if dequeuing on a read that fails were to empty the queue in normal running, for example because a list is read short on every large pull request. The trial would show that.
don-petry commentedon Oct 15, 2026
Maintainer ruling, 2026-10-15: accepted. Under a Pause, or a Pause that cannot be read, the dequeue defers like every other act (decision 0003). A queued pull request may then merge over a lost approval, a writer's request for changes or thread, a Hold, or a check that no longer passes. Only the lost approval is found afterwards by FR-28. Every deferred dequeue shows
needs_you, so the Maintainer sees it before the merge, and the design names each case.