Skip to content

The fork's main has no ruleset and no branch protection, so a PASS is only advisory and an unreviewed pull request can be squash-merged #812

Closed

Description

@Birfy

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' }}: the pull_request mode reports and never fails. That is deliberate (Merge gate is 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.mjs refuses correctly (hold, a newest conclusion that is not a PASS, a missing agent-pr), but it is a script somebody has to run before merging. Nothing rejects PUT /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:

  1. merge the workflow, then prove it on a real pull request: one deliberately missing agent-pr must yield failure with the guard's reason, and one complete pull request must yield success on the same check (this also proves a PATCH update flips one check on one tip).
  2. 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.
  3. 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

  1. GET /repos/Birfy/FlyBot/rulesets lists one active ruleset on refs/heads/main: enforcement: active, bypass_actors: [], current_user_can_bypass: never, strict_required_status_checks_policy: false, requiring at least the gate's check and tests-ok.
  2. A throwaway pull request with no labels cannot be merged: PUT /pulls/<n>/merge answers 405 or 422 naming the required check, and the gate's check run on that head is failure with the guard's exact REFUSE reason for it.
  3. Adding agent-pr and posting Verdict: PASS at <tip> turns that same check success without a new commit (a label added or a comment posted must re-evaluate it), and the merge endpoint stops refusing.
  4. One new commit returns the check to failure even with agent-pr present: a PASS is bound to a tip.
  5. Adding hold makes the check failure while a valid PASS still names the tip.
  6. tests-ok must be green at the tip before the merge is allowed.
  7. Ordinary pull requests keep showing merge-gate as a report: no PR sits on "Expected — waiting for status" (Merge gate is 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-error from the report job instead of adding a real gate: that re-introduces Merge gate is 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

  1. added
    bugSomething isn't working
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    area:automationScheduled tasks and automation
    on Oct 23, 2026
  2. Birfy commented on Oct 23, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev

    Claiming #812. Branch fix/812-fork-merge-gate, cut from f20cfa37.

    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/--rollback script (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 missing agent-pr and 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.

  3. self-assigned this
    on Oct 23, 2026
  4. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    and removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 23, 2026
  5. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:automationScheduled tasks and automationbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions