Repository navigation
Description
Problem
The first half of squash-merge.sh (about 230 of its 376 lines) refuses a merge unless the inputs it relies on still hold: the draft names this pull request; the review stamp covers the draft, pull request, live head, base branch and base commit; gh acts as the configured account; the pull request is open, ready, mergeable, CLEAN, approved where required and green by the latest run of every check; and the commit-msg gates pass. The confirmation chain and the post-confirmation re-read are child 25. It is under the shell freeze in #588, and no later step can walk a merge back.
Part of #324, within #588. Child 10 in #324's Children list. Replaces the precondition half of packages/agents/source/skills/merge-pr/shared/scripts/squash-merge.sh.
Acceptance criteria
- AC1: Given
agentrepo merge runarguments, when they include--confirmed,--expected-head=<40 hex>and a pull request number, then they are accepted; given any other flag, a non-numeric value or a repeated number, then the command exits 1 with the usage line; given an expected head that is not 40 lowercase hex characters, then it exits 1 withExpected head must be a full commit SHA. - AC2: Given unattended mode and
--confirmed, when the command runs, then it exits 1 with "Unattended workflows refuse --confirmed; use pre-approval or delegation." - AC3: Given no
SQUASH_AGENTMSG, an empty one, or one drafted for another pull request, when the command runs, then it exits 1 and merges nothing. - AC4: Given no stamp, or a stamp that does not cover the draft bytes, pull request, live head, base name and base commit, when the command runs, then it exits 1 and names the review command to rerun; given
--expected-headdiffering from the reviewed head, then it exits 1; given any mode, attended or unattended, the stamp's recorded trusted-policy bindings (policy digest, status and authority) are validated under the contract of refactor(agents): port review snapshots and stamps to Go #769 and refactor(agents): port trusted review policy and prompt assembly to Go #763, including refactor(agents): port trusted review policy and prompt assembly to Go #763's intentional correction that an unrelated trusted-ref commit with unchanged policy keeps the stamp fresh, and a change to policy content, status or authority makes the command exit 1; given unattended mode only, the stamp's recorded repository configuration is also validated, and a change to it makes the command exit 1. - AC5: Given a configured
gh_loginthat differs from the active account, when the command runs, then it exits 1 before any write; given none configured, then it prints that the check is skipped. - AC6: Given mergeability reported UNKNOWN, when the command runs, then it waits up to
MERGE_MERGEABLE_WAITseconds (default 60) polling everyMERGE_MERGEABLE_POLL(default 3), re-checks the stamp after any wait, and exits 1 if still UNKNOWN. - AC7: Given a pull request that is not OPEN, is a draft, is not MERGEABLE or CLEAN, has a failing, still-running, absent or unreadable check, or an unknown fork flag, when the command runs, then it exits 1 with the matching message and the same hand-off to the fix-pr, watch-pr or rebase skill.
- AC8: Given a review decision of
REVIEW_REQUIREDorCHANGES_REQUESTED, when the command runs, then it exits 75 withWAITING_REVIEWon stderr and merges nothing. - AC9: Given the squash lint or the trailer check against the collapsed commits fails, or
commit-lintis absent, when the command runs, then it exits 1 and merges nothing. - AC10: Non-functional: authority comes from machine configuration only, and the command runs against fakes on macOS, Linux and Windows in CI.
Scope and non-goals
Scope: the argument handling and every precondition of agentrepo merge run before gate activation, ported from merge-workflow.bats cases.
Non-goal: gate activation, the confirmation chain and the post-confirmation re-read (child 25). Non-goal: the merge write (child 11) and cleanup (child 12). Non-goal: editing the shell script before child 14.
Approach
Meet AC1 to AC10 with failing cases first: for each refusal, run the shell script and the Go command on the same fake-gh state and compare status, streams and files written. Mechanism is the implementer's choice.
Dependencies
Blocked by: #862, #865, #868, #863, #333, #769.
Prerequisites: #769 (stamp library), #321 and #333.
Size
M. One pull request.
Verify plan
- AC1, AC2, AC3: usage and refusal table with the shell script as oracle, including a short expected head.
- AC4: stamp mutation cases, one per bound field, run through
agentrepo merge run, plus attended cases that change the policy content, the policy status and the authority (each refused) and one that adds an unrelated trusted-ref commit with the policy unchanged (accepted), the same four cases repeated unattended, and an unattended case that changes the recorded repository configuration (refused). - AC5, AC6, AC7, AC8: fake-
ghstate table, with a fake clock for the wait, asserting exit 75 andWAITING_REVIEWfor the review decisions. - AC9: stub
commit-lintandmise. - AC10: authority keys supplied from the repository file and ignored; the CI matrix run.
- Definition of done: D1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification. D2 an independent review approves the exact merged head, and every finding has a recorded disposition. D3 required checks pass with no gate loosened. D4 the leak scans the repository specifies are clean, and every post made for this work passes the per-post leak review before it is posted. D5 every commit is signed. D6 the documentation matches the change or the Verification says why there is no impact. D7 every commit has an
Assisted-bytrailer and the pull request has theprovenance:agent-assistedlabel. D8 the pull request stays within the size limits. D9 follow-ups are filed as issues and listed under Related. D10 the merge closes the issue through a closing reference, the board shows Done, and the finalStatus:comment names the merge commit.
Risks
A precondition that passes where the shell refused would let an unreviewed message reach the default branch. One parity case per refusal is the control. Undo: revert; the shell script is untouched.
Operator authority
None here, since the Go files are new.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-agent commentedon Oct 27, 2026
Refinement: READY — The merge refuses unless the message, stamp, pull request and checks agree
Model: gpt-6-astra
Child 10 The merge refuses unless the message, stamp, pull request and checks agree
Verdict: READY
Checked: AC4 now validates trusted-policy bindings in both modes, while repository-configuration validation remains unattended-only. This matches the mode boundary at
packages/agents/source/lib/lib.sh:695and policy validation outside it atpackages/agents/source/lib/lib.sh:700. Verification covers changed policy content, status and authority, plus unchanged-policy freshness in both modes, incorporating live #763’s correction.Gaps: None.
Split: None needed.
Definition of done
The definition of done for this issue (Feature). Tick each item and give its evidence.
check-leaks.shwith the repository's private-strings list, and the leak review of each post.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why.provenance:agent-assistedlabel.Status:comment names the merge commit.mise run checkis green, and so are the coverage floorsmise run cover-go-checkandmise run cover-py-check, whichcheckdoesn't run.packages/agents/source/commits whatmise run generate-skills, thenmise run skill-tokens, thenapm installrewrite, in that order, andcheck-generated-skills(part oflint) passes.docs/agent-skills-migration.mdor the adoption docs, or the PR's Verification says "No consumer impact" and why.Round: 1 of 3