Skip to content

enqueue-guard: read the frozen list from main, not the pull request's base (old-base pull requests are not frozen) #1354

Closed as not planned

Description

@Birfy

The seal shipped in #1348 reads .github/agent/frozen-branches.json from the pull request's base commit (event.pull_request.base.sha). That was chosen so a branch cannot empty the list it is judged by, but it leaves a hole: any pull request whose base predates the seal is judged with no list at all.

That is not hypothetical. #1328 (base 8d0a99c1, opened before 6d1eb0be) was merged at 06:03:21Z on fb012a4b; its branch matches dev4/… but the tip was pushed by Cursor Agent, and its body carried the CURSOR_AGENT_PR_BODY marker — the seal would have refused it, and the guard's base read never saw a list to match against.

Proposal

Read the list from the default branch tip (GET /git/ref/heads/main → that commit) rather than the pull request's base, or from main and fall back to base only when main has no such file (e.g. right after the seal is first added). A pull request can still not edit the list it is judged by — it cannot edit main — so the property the base read protects is kept, and old-base pull requests stop being invisible to the seal.

Second half of the same hole: the release is "delete the file (or empty both arrays) on main", which keeps working unchanged under a main read.

Evidence to pin

  • A pull request whose base commit has no frozen-branches.json and whose branch matches a listed prefix is refused (it is allowed today).
  • The same pull request is still refused when its own diff edits the list (the self-unlock case, unchanged).
  • Deleting the file on main releases everything, including a pull request with an old base.
  • Reading main fails closed: an unreadable main file or a failed fetch freezes nobody only if that is the documented choice — state which, and pin it.

Scope

  • .github/scripts/enqueue-guard.mjs — the frozenList() source and the frozenRefusal() call site
  • .github/scripts/enqueue-guard.test.mjs — the cases above

Not allowed: core/, patches/, pass-label.yml, package*, .github/agent/frozen-branches.json.

Owner

Dev.

Constraint

This does not undo the #1328 merge and does not judge it — that is a separate decision. One PR.

Activity

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

    @Birfy
    CollaboratorAuthor

    Operational half of the same hole, from the #1328 timeline — worth a sentence in AGENTS.md next to the seal section, because it is the step that failed here:

    Converting a pull request to draft does not remove it from the merge queue. #1328 was marked ready at 05:59:38Z, entered the queue at 06:01:1xZ on gh-readonly-queue/main/pr-1328-807e592e, and merged at 06:03:21Z; the only counter-action taken before the merge was convertPullRequestToDraft, which left the queue entry in place. The instrument is dequeuePullRequest (GraphQL) first, then draft.

    So this issue has two deliverables:

    1. the code half (frozenList() reads main, not the pull request's base) with its cases;
    2. one sentence in AGENTS.md (Untrusted external agent branches, "Until it is lifted" paragraph): to hold one of these pull requests out of the merge queue, dequeue it — draft alone does not.

    AGENTS.md is added to the allowed files for this issue; core/, patches/, pass-label.yml, package* and .github/agent/frozen-branches.json stay out.

  3. Birfy commented on Oct 27, 2026

    @Birfy
    CollaboratorAuthor

    Absorbed into #1352 by owner decision — no PR will be opened for this issue. The code half (read the list from main, not the pull request's base; match by pull-request number as well as prefix/marker) and the AGENTS.md sentence about dequeuePullRequest both land in #1352, which is still unpushed-only-before-verdict: comments: 0, no PASS at its tip.

    One constraint found while specifying it: .github/agent/frozen-branches.json cannot be edited by a pull request (the guard refuses it precisely so a branch cannot empty the list), so #1328's number cannot be added there from this change. It goes into a constant inside .github/scripts/enqueue-guard.mjs instead (FROZEN_PULL_REQUESTS = {1328, 1346, 1330}), with the JSON keeping only the prefix/marker list it already has.

    Closing this as absorbed, kept for the record.

  4. removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 27, 2026
  5. added 2 commits that reference this issue on Oct 27, 2026
    2346077
    a13676f
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

    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