The Queen only manages: the publisher never arms auto-merge, a reviewer bee gates every merge (#5525) - #5526
Conversation
…er bee gates every merge Owner's rule of 2026-10-02 overrides "the Queen's accept IS the merge" (2026-10-01, #5422). tools/queen/publish.py still opens a pull request for a head she accepted, but no longer runs gh pr merge --auto; its reconcile pass only disarms auto-merge on open queen-* pull requests. --self-test parses the module's own syntax tree and fails on any gh pr merge argv that is not --disable-auto. auto-merge-ready-prs.yml now merges only pull requests carrying the bee-reviewed label, applied after the head commit. The Queen's verdict is not a merge trigger. Closes #5525 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
…vs and gh api merges Reviewer bee's fixes to #5526. - auto-merge-ready-prs.yml: `committedDate` is when a commit was made, not when it reached the branch, so a commit made before the bee-reviewed label and pushed after it passed the gate unreviewed. The head's time is now the latest of its committer date, the first check run started on it and the last head_ref_force_pushed event. Every read fails closed. - publish.py --self-test: also reads tuple argvs and gh api merge routes (/pulls/N/merge, enablePullRequestAutoMerge, mergePullRequest). Five planted regressions each turn it red; two of them (tuple, REST) passed before. Census: quiet "named a path but not quiet" 150 -> 155, re-blessed. The merger step now names three more GitHub API paths (commits/<sha>, commits/<sha>/check-runs, issues/<n>/events) and #5526 itself added the first three; none is in a quiet shape ("steps in a quiet shape" stays 31). Refs #5525 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
PR DashboardGenerated at: 2026-10-02 08:52:53 UTC
Summary
Seal Status
|
gHashTag
left a comment
There was a problem hiding this comment.
Reviewer bee: PASSED (posted as a comment -- GitHub refuses an approval from the PR's own account).
Pushed bfbe762 with two fixes found in review:
- Workflow timing hole.
commits[-1].committedDateis when a commit was made, not when it reached the branch: a commit made beforebee-reviewedand pushed after it passed unreviewed. Head time is now max(committer date, first check run started on headRefOid, lasthead_ref_force_pushed), every read fails closed. Live on this PR after labelling:label 09:06:01Z >= head 08:52:42Z (commit 08:49:05Z, run 08:52:42Z)-- the check-run date is the one that decided. Unlabelled PRs (#5452) skip. Label removed -> absent -> skip; removed and re-added -> latestlabeledevent wins. - Self-test blind spots. Planted in scratch copies: arm on publish, disarm turned arm,
--adminon the disarm were red before; a tuple argv andgh api -X PUT .../pulls/N/mergewere GREEN. Nowmerge_callsreads tuples andapi_merge_routesfinds/merge,enablePullRequestAutoMerge,mergePullRequest: all five red, clean treeok: 24 shapes. - Census
quietre-blessed: named-path 150 -> 155 (this PR's own API paths), quiet shapes stay 31; that was the cli-tri failure on d202773, now green.
Gates: YAML parses, bash -n on the extracted step OK (actionlint not installed); pre-commit and pre-push (tri hooks) PASSED. CI: required validate, check-linked-issue, parse-ratchet pass; Corpus Ratchet (68 unexpected) and Seal Coverage (647 seals) fail identically on master 8d0ed64 -- pre-existing.
Not established: that only reviewer bees apply the label (anyone with triage can). Also the scheduled merger's existing APPROVED-review gate cannot be met by PRs authored by the account the bees use, so in practice these PRs are merged by hand after review -- pre-existing, not changed here.
…6 hardening) Reviewer-bee fix on top of the author's gate. The gate compared the bee-reviewed label against the head commit's committer date only. A commit made at 10:00 and pushed at 10:10 carries 10:00, so a label put on at 10:05 passed unreviewed code; a force-push back to an older SHA carries an older date still. Same hole gHashTag/t27#5526 closed in f9a6c9b. Now the head's time is max(committer date, first check run started on the head, last head_ref_force_pushed event). The gate also judges exactly the head the merge step pins (payload head.sha) and refuses if the API head has moved. Every read throws on an API error, which fails the step and skips the merge: fail closed. Simulated with mocked API: normal PASS; late push, force-push to old SHA, no label, no approval, head moved all REFUSE; read error throws. actionlint clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #5581 (Refs #5547). The gate checks the bee's approval against HEAD_SHA, but the merge step ran `gh pr merge N` with no SHA. The find loop walks up to 50 PRs with five API reads each, so a push landing on an early PR after it was judged and before the merge step was merged as code no bee reviewed -- the late-push hole #5526 closed for labels, reopened between steps. find-ready now also emits `ready_heads` ("pr:sha"); the merge step reads it through env (not ${{ }} interpolated into the script), validates each entry, and passes --match-head-commit, so GitHub refuses a moved head. merger_gate_selftest.py asserts the pinned output and the flag; the PR's previous workflow fails the new check (negative control). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nts only its approval (#5581) * feat(bees): reviewer bees approve as their own GitHub App; merger counts only its approval The owner's account authors every bee pull request and GitHub refuses self-approval, so a reviewer bee using the owner's token could only leave COMMENTED and auto-merge-ready-prs never fired (#5526). - tools/bees/manifest.json: private t27-bees app, no webhook; pull requests write, issues write, contents/checks/metadata read. - tools/bees/bee-app create|convert: manifest flow on 127.0.0.1:8727, key saved mode 600 under ~/.config/t27-bees, app id and key PATH in the Keychain; client_secret and webhook_secret are discarded. Owner runs it. - tools/bees/bee-token: RS256 JWT via openssl, traded for a one-hour installation token scoped to one repository. Never prints a secret except the token itself on stdout. Self-test: 33 checks, throwaway key. - auto-merge-ready-prs.yml: the counted approval is the latest decisive review by vars.BEE_REVIEWER_LOGIN (default t27-bees[bot]), APPROVED, of the head SHA, submitted after the head arrived; the bee-reviewed label must be applied by the same login. Malformed login or unreadable reviews fail closed. - tools/bees/merger_gate_selftest.py: runs the workflow's own script against a stub gh with real jq; 11/11 here, 9/11 fail on master. Census moved: quiet "named a path but not quiet" 155 -> 161 (re-blessed in tools/census/quiet.txt). The six new candidate lines are the merger's fail-closed guards (login shape check, bot-label check, the reviews fetch, the bot review state / SHA / time checks); none of them is a quiet pass, "steps in a quiet shape" stays 31. No app, key or secret was created here: the owner's steps are in tools/bees/README.md. Closes #5547 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(merger): merge only the head the gate judged (--match-head-commit) Review of #5581 (Refs #5547). The gate checks the bee's approval against HEAD_SHA, but the merge step ran `gh pr merge N` with no SHA. The find loop walks up to 50 PRs with five API reads each, so a push landing on an early PR after it was judged and before the merge step was merged as code no bee reviewed -- the late-push hole #5526 closed for labels, reopened between steps. find-ready now also emits `ready_heads` ("pr:sha"); the merge step reads it through env (not ${{ }} interpolated into the script), validates each entry, and passes --match-head-commit, so GitHub refuses a moved head. merger_gate_selftest.py asserts the pinned output and the flag; the PR's previous workflow fails the new check (negative control). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(census): re-bless quiet census after the merge-step head pin Census moved: quiet "named a path but not quiet" 161 -> 162, measured by cli-tri `tri census pin --gate` on 9247d64. The new candidate is the merge step's ready-entry guard added in 9247d64 (pr number / 40-hex SHA shape check before --match-head-commit); it fails the merge on a malformed entry, it is not a quiet pass. "steps in a quiet shape" stays 31. Refs #5547 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…age (t27#5526 hardening) Reviewer-bee fix on top of the author's gate. reviewerBeeGate compared the bee-reviewed label against the head commit's committer date only. A commit made at 10:00 and pushed at 10:10 carries 10:00, so a label put on at 10:05 passed unreviewed code; a force-push back to an older SHA carries an older date still. Same hole gHashTag/t27#5526 closed in f9a6c9b. Now the head's time is the latest of its committer date, the first check run started on the head, and the last head_ref_force_pushed event. Events are read page by page to the end (a force-push on an unread page would fail open); more than 30 pages is refused. Every read or parse failure refuses. Tests: three new github_client tests (late push, force-push to old SHA, unreadable responses fail closed, Stamp ordering). zig 0.15.2: `zig test src/tri/github_client.zig` 18/18 pass; `zig build tri` builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…VIEW before hand-off Reviewer-bee fix. "bee-reviewed added after the last commit" is the late-push hole gHashTag/t27#5526 closed in f9a6c9b: a commit dated before the review but pushed after it would pass. Say "after the head arrived" (latest of commit date, first check run, last force-push). FINALIZE also told the loop to commit RINGS.md "IN REVIEW" AFTER the hand-off, which would void the reviewer bee's label every time. Moved it before the hand-off and said: push nothing more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… APPROVED) (#805) * fix(queen-bot): merge only what a reviewer bee passed (bee-reviewed + APPROVED) Owner's rule 2026-10-02: no automation merges on its own verdict. The merge step now requires an APPROVED review and the bee-reviewed label applied after the head commit (same gate as gHashTag/t27#5526), and pins the merge to the checked head sha. Also: PR body passed via env instead of shell interpolation under pull_request_target, untrusted checkout dropped, dead check_suite trigger removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(queen-bot): date the head by its arrival, not its commit (t27#5526 hardening) Reviewer-bee fix on top of the author's gate. The gate compared the bee-reviewed label against the head commit's committer date only. A commit made at 10:00 and pushed at 10:10 carries 10:00, so a label put on at 10:05 passed unreviewed code; a force-push back to an older SHA carries an older date still. Same hole gHashTag/t27#5526 closed in f9a6c9b. Now the head's time is max(committer date, first check run started on the head, last head_ref_force_pushed event). The gate also judges exactly the head the merge step pins (payload head.sha) and refuses if the API head has moved. Every read throws on an API error, which fails the step and skips the merge: fail closed. Simulated with mocked API: normal PASS; late push, force-push to old SHA, no label, no approval, head moved all REFUSE; read error throws. actionlint clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(tri): gate every merge on the reviewer bee; pipeline no longer auto-merges Reviewer-bee fix. The workflow gate was not the only merge path in this repo: src/tri carries a copy of trinity's tri, and `tri cloud pipeline` still called cloudMergePR on its own verdict (a green local build), and GitHubClient.mergePr merged anything it was asked to (gh pr merge / PUT /pulls/N/merge) with no gate. Ported the gate from gHashTag/trinity#1242 (with the reviewer-bee hardening pushed there): mergePr refuses unless the PR has an APPROVED review and the `bee-reviewed` label applied after the head's arrival -- the latest of its committer date, its first check run and the last force-push, events read to the last page -- and pins the merge to the checked head sha. Every read failure refuses. The pipeline leaves the PR open for a reviewer bee; `tri pr merge` reports the refusal. zig 0.16.0 (this repo's CI version): `zig test src/tri/github_client.zig` 18/18 pass; `zig build tri` builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… passed (#1242) * fix(merge): no self-armed merges; tri merges only what a reviewer bee passed Owner's rule 2026-10-02: no automation merges on its own verdict. - t27-world-scan.yml: stop arming gh pr merge --squash --auto on the PR the job opens; disarm any earlier arming; the PR waits for a reviewer. - tri cloud pipeline: no automatic cloudMergePR after a green local build. - GitHubClient.mergePr (tri pr merge, tri cloud merge): refuse unless the PR has an APPROVED review and the bee-reviewed label applied after the head commit (gate of gHashTag/t27#5526); merge pinned to that head sha. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(github_client): date the head by its arrival, read every events page (t27#5526 hardening) Reviewer-bee fix on top of the author's gate. reviewerBeeGate compared the bee-reviewed label against the head commit's committer date only. A commit made at 10:00 and pushed at 10:10 carries 10:00, so a label put on at 10:05 passed unreviewed code; a force-push back to an older SHA carries an older date still. Same hole gHashTag/t27#5526 closed in f9a6c9b. Now the head's time is the latest of its committer date, the first check run started on the head, and the last head_ref_force_pushed event. Events are read page by page to the end (a force-push on an unread page would fail open); more than 30 pages is refused. Every read or parse failure refuses. Tests: three new github_client tests (late push, force-push to old SHA, unreadable responses fail closed, Stamp ordering). zig 0.15.2: `zig test src/tri/github_client.zig` 18/18 pass; `zig build tri` builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Closes #5525
Owner's rule, 2026-10-02, overriding "the Queen's accept IS the merge" (2026-10-01, #5422): the Queen only manages -- she assigns, judges, accepts and sends back. She does not merge. A merge happens only after a reviewer bee (a code-review agent with real tools) has reviewed and verified the pull request.
What changes
tools/queen/publish.py: still publishes (opens a PR for) a branch only when the Queen accepted its current head. It no longer armsgh pr merge --auto --squashaftergh pr create.reconcile_openno longer arms anything; it only disarms auto-merge on any openqueen-*PR, whatever her verdict. The module docstring states the new rule with date and owner quote.--self-testgains 5 shapes: it parses the module's own AST and fails if any literalgh pr mergeargv is not--disable-auto(forbids--auto,--squash,--merge,--rebase,--admin). A mutation that re-arms--auto --squashon the disarm call turns it red (verified locally). It is already run byqueen-publish.ymlbefore every publish..github/workflows/auto-merge-ready-prs.yml: skips any PR without thebee-reviewedlabel, or whose most recentbee-reviewedlabeling predates the head commit (a push after review is unreviewed code). The Queen's verdict is not read there. Existing gates kept: L1 reference, an APPROVED review, all checks green.bee-reviewedcreated in this repo.docs/now/entry.Measured
python3 tools/queen/publish.py --self-test->ok: 20 shapes ...gh pr list --state open --json autoMergeRequest: no open PR in this repo currently has auto-merge armed, so nothing was disarmed by hand.Not established
specs/queen/dispatch.t27PUBLISH_RULE, "the Queen's accept is the merge") encodes the rule this PR retires; it should be revised or closed before it lands.Author bee: not merging this myself -- waiting for a reviewer bee.
🤖 Generated with Claude Code