Repository navigation
Description
What is wrong
Every pull request this team opens is merged on Birfy/FlyBot (#23–#34 all merged there), but that repo's main has no mechanical gate at all:
GET /repos/Birfy/FlyBot/rulesets→[]GET /repos/Birfy/FlyBot/branches/main/protection→404 Branch not protected.github/workflows/merge-gate.yml:63—continue-on-error: ${{ github.event_name == 'pull_request' }}: thepull_requestmode reports and never fails. That is deliberate (Merge gateis not a required check on the merge queue, so a red gate does not block a merge #639) and has to stay..github/workflows/pass-label.yml:7— its own header: "It is a record, not a gate. It only ever adds the label"..github/scripts/enqueue-guard.mjsrefuses correctly (hold, a newest conclusion that is not a PASS, a missingagent-pr), but it is a script somebody has to run before merging. Nothing rejectsPUT /repos/Birfy/FlyBot/pulls/<n>/merge.
So on the repository where merges actually happen, a PASS is advisory. It has already leaked twice: #30 merged without agent-pr, and #32 carried pass but no agent-pr until a person noticed.
Expected behaviour
A merge on Birfy/FlyBot fails when the pull request head has no PASS naming that exact tip, no agent-pr, or carries hold — refused by GitHub rather than by a script. The decision must be enqueue-guard.mjs's own: import its decision function, do not copy the rules into a second place.
Order (owner decision, 2026-10-23)
The pull request ships the workflow, the script, the tests and an --apply / rollback write-up — it does not create the ruleset. The order is fixed:
- merge the workflow, then prove it on a real pull request: one deliberately missing
agent-prmust yieldfailurewith the guard's reason, and one complete pull request must yieldsuccesson the same check (this also proves aPATCHupdate flips one check on one tip). - only then the owner creates the ruleset: required =
enqueue-guard+tests-ok,bypass_actors: [],strict_required_status_checks_policy: false, with the ruleset JSON and the rollback in the repository. - verify an unlabelled merge is refused (405/422) and that a rollback really removes it.
Acceptance 1 and 2 below are verified after step 2; steps 1 and 3 are verified by the pull request log and the owner.
Acceptance
GET /repos/Birfy/FlyBot/rulesetslists one active ruleset onrefs/heads/main:enforcement: active,bypass_actors: [],current_user_can_bypass: never,strict_required_status_checks_policy: false, requiring at least the gate's check andtests-ok.- A throwaway pull request with no labels cannot be merged:
PUT /pulls/<n>/mergeanswers 405 or 422 naming the required check, and the gate's check run on that head isfailurewith the guard's exact REFUSE reason for it. - Adding
agent-prand postingVerdict: PASS at <tip>turns that same checksuccesswithout a new commit (a label added or a comment posted must re-evaluate it), and the merge endpoint stops refusing. - One new commit returns the check to
failureeven withagent-prpresent: a PASS is bound to a tip. - Adding
holdmakes the checkfailurewhile a valid PASS still names the tip. tests-okmust be green at the tip before the merge is allowed.- Ordinary pull requests keep showing
merge-gateas a report: no PR sits on "Expected — waiting for status" (Merge gateis not a required check on the merge queue, so a red gate does not block a merge #639).
Kill conditions
- A bypass actor, or an admin escape hatch that lets the check be skipped.
- A required context no run produces — every pull request stuck on "Expected" forever.
- The check green while the head has no PASS, or green on a stale PASS after a tip move.
- A second copy of the guard's rules; the two must not be able to disagree.
- Deleting
continue-on-errorfrom the report job instead of adding a real gate: that re-introducesMerge gateis not a required check on the merge queue, so a red gate does not block a merge #639.
Out of scope
- The upstream ruleset
25173372(ThinkFlowLab/FlyBot); Release owns it. - A merge queue on the fork — a ruleset is enough.
- Changing who may review, or the review policy.
- Backfilling labels on already-merged pull requests.
Activity
Birfy commentedon Oct 23, 2026
Written-by: Dev
Claiming #812. Branch
fix/812-fork-merge-gate, cut fromf20cfa37.The pull request carries the workflow (
.github/workflows/enqueue-guard.yml), the script that writes the check (gate-check.mjs), the ruleset body plus its--check/--apply/--rollbackscript (gate-ruleset.mjs,.github/agent/merge-gate-ruleset.json), and the tests. It does not apply the ruleset: that is a repository-protection change, so it stays the owner's action, and the order is fixed — merge the workflow, prove the check goes red on a pull request missingagent-prand green on a complete one, and only then apply the ruleset. Applied first, every open pull request reads "Expected — waiting for status" and none can merge.fix(automation): read the check runs from the endpoint's envelope
Read the body on a queue entry, and write enqueue-guard on merge_group (
Say where pull requests merge now: upstream through the queue, the fo…
fix(issue-ref): read a bare ThinkFlowLab#1234 only when the number st…
Refuse to enqueue when a comment asks not to merge this tip (ThinkFlo…