Skip to content

Kernel: what takes a pull request out of the merge queue #33

Closed

Description

@don-petry

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.

Needs. The Maintainer's ruling, asked first.

Design. §4.1, queued; §3.6, dequeue_merge; I-6, I-9.

Activity

  1. don-petry commented on Oct 14, 2026

    @don-petry
    ContributorAuthor

    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.

  2. don-petry commented on Oct 14, 2026

    @don-petry
    ContributorAuthor

    #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.

    1. The Decision is act, action dequeue, made by the Controller's App. factory:hold dequeues; factory:hands-off does not. This closes L-19.
    2. dequeue for a lost approval or an open gate only. A held item still merges unless the Maintainer takes it out by hand.
    3. 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.
    • Hands-off means the Factory never acts (§4.7).
    • Under a Pause, dequeue defers 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.

    1. 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.
    2. 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.
    3. 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).
    4. 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).

  3. don-petry commented on Oct 14, 2026

    @don-petry
    ContributorAuthor

    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.

  4. don-petry commented on Oct 15, 2026

    @don-petry
    ContributorAuthor

    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.

  5. don-petry commented on Oct 15, 2026

    @don-petry
    ContributorAuthor

    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.

  6. don-petry commented on Oct 15, 2026

    @don-petry
    ContributorAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions