Repository navigation
feat(pstack): add merge-gate and route every merge through it - #15
Conversation
…h pr merge merge-gate --pr <n> [--repo <owner/name>] [--check] reads the PR once at its current head and merges only when six requirements hold: open, ready, no conflicts and based on the default branch; every non-Bugbot check passed; no unresolved review thread; the latest pstack-verdict covers the exact change by verdict-hash.sh; Codex's review state names this head as completed; and any AGENTS.md or CLAUDE.md change carries Lee's lee-approves-instruction-files line for that exact text. It merges with --match-head-commit, reads the PR back, and logs every run to <pstack store>/merge-gate/runs.tsv. watch-pr/github.ts only gains exports for its gh runner and JSON readers. Linear: LH-86 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shipping step 4 merges only with merge-gate, step 1 says how a verifier records its verdict so the gate can read it, and poteto-mode's Shipping trigger now covers any merge, including one an agent's own plan schedules. A passing --check logs would-merge, so the retro log never counts a dry run as a merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5508a5e4f1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
pstack-verdict: FAIL head=5508a5e4f15315291b94fe1a44f254f0df38fb61 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol
Shipping and prose review: step 1's verdict line matches the parser when populated with full SHAs and a single provider/model token. Step 4 uses the executable that exists and correctly describes Bugbot exclusion, exact patch hashing, Codex head binding, instruction-file hashes, and the GitHub-only scope. The poteto-mode trigger covers a merge scheduled by an agent's own plan. These edits are restrained and clear under Lee's writing guidance. Step 4's safety promise is limited by findings 1-4. The diff changes no AGENTS.md or CLAUDE.md. One nonblocking refusal-text observation: the live #11 thread preview spends most of its 120-character allowance on badge Markdown and cuts its actual title at “state ma”. The file and URL remain useful. Keep the readable first line or remove badge markup before shortening it. Verification in an isolated worktree at the head above: The seven added review assertions expected refusal or a read error, and failed as follows. They were review probes only; no implementation files were edited. The reader probes substituted a local read-only Confirmed GitHub SHA fetching in a fresh bare object store. PR #7's force-push timeline names Live probes were all PR #10, exit 1PR #11, exit 1PR #12, exit 0PR #13, exit 0PR #14, exit 1PR #15, exit 1 |
Order comments by REST id so a later verdict or Codex summary posted in the same second wins, and an edit to an older Codex summary cannot hide a newer pending review. Treat a page with no usable hasNextPage or endCursor, and a commit missing statusCheckRollup, as read errors. Re-read the PR's base and head just before merging and refuse if either moved; when read-back still shows a merge into another base, say MERGED INTO THE WRONG BASE and log wrong-base. Log usage errors. Strip badge images and HTML from thread previews. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a merge-queue branch gh pr merge only queues the PR, which could then land after the gate's checks went stale. The gate reads the base branch's merge queue before merging and refuses instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
pstack-verdict: FAIL head=859847800da0e5593e1bfb913fc7b82498a70730 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 2. The specific round-1 probes are fixed, but the gate still accepts two other incomplete-read shapes.
These are malformed-response reproductions, not claims that live GitHub returned either response. Each used the real gate and readers, a real temporary git remote, and a fake Round-1 fixes checked.
Shipping and poteto-mode wiring remain minimal and clear. The verdict line matches the parser, every merge trigger routes through Shipping, and Shipping names the executable present in this change. No AGENTS.md or CLAUDE.md is changed. watch-pr changes exports only. I reviewed every changed file and the bootstrap, git/hash, and reader dependencies in the isolated worktree at the head above. Required checks. Independent probes. Actual usage-error run. Live checks. Open PRs at the start were #11-15. I ran each plus merged #10 using the executable from the reviewed worktree, each with a fresh temporary PSTACK_STORE. These are the complete captured outputs. #11's earlier open thread had been resolved by this round. #15 correctly remained refused on the round-1 FAIL and pending Codex state. PR #10PR #11PR #12PR #13PR #14PR #15 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 859847800d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ad error A check node without a type and a comment without a body were dropped or read as empty, so a failed check could vanish and an older PASS could outrank an unreadable newer verdict. Both now stop the gate with exit 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
pstack-verdict: FAIL head=d6487511dbcd3782b54b3ae4b28fc6702e6c5b37 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 3. Both round-2 fixes are confirmed. One additional incomplete-read case still passes.
This is a malformed-response probe, not a claim that live GitHub omitted this field. My fake Round-2 fixes independently reproduced. I ran the same fixtures through the real gate with the reader from 8598478 and with the reader at d648751. Swapping the reader isolates the two changes in this commit. The current errors are plain and specific. An explicitly empty comment body remains readable. A normal failed check still refuses. Whole-PR review. I read both earlier verdicts in full, both task briefs, the source retro brief and decisions, FORK.md, every changed file in full, and the bootstrap, hash, git and watch-pr reader/type dependencies. Shipping's executable path, verdict format, Bugbot exclusion and GitHub-only scope match the implementation. The poteto-mode trigger includes merges an agent schedules itself. The wording remains minimal and clear. No AGENTS.md or CLAUDE.md is changed in the PR. watch-pr's changes are exports only. I did not reopen the accepted last-read/base race; the final head/base recheck and explicit wrong-base reporting remain present. I audited the default-branch read, PR reader, checks and thread pagination, issue-comment paging and parsing, merge-queue read, and read-back parser. Additional independent probes confirm that missing PR state/mergeability/draft/head/base, missing comment ID/user/timestamps/URL, missing thread resolution/body, missing rollup, malformed pagination and missing mergeQueue fail closed. An explicit null rollup is permitted by the contract, including when it appears during pagination; I did not count that exploratory observation as a finding. Checks run in my isolated worktree. The repository suite includes its existing fake-only merge-path tests. Every gate invocation in my independent probes and all executable runs used Live executable checks. The executable was the one at the reviewed head. Each run used a fresh temporary PSTACK_STORE. Open PRs were #11-15. Complete captured output follows. PR #10PR #11PR #15 |
A comment whose user had no type counted as a person, so an unreadable bot comment could satisfy the instruction-file approval. A missing type is now a read error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6833f84e8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
pstack-verdict: FAIL head=d6833f84e82def7c2304a75181787735d8e08192 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 4. The missing-account-type fix is confirmed, but three other malformed-comment reads still turn a refusal into a pass. All three are boundary validation findings, not claims that live GitHub returned these malformed responses.
The counterexamples use the actual The round-3 regression was independently checked with identical instruction-file fixtures and a copy of the old reader, without editing implementation files. Missing I traced every read the gate uses, including the reused watch-pr PR parser, and checked the author's remaining leniency classifications:
I read all three earlier verdict comments in full, both task briefs, the source retro brief and decisions, FORK.md, every changed file in full, and the bootstrap, hash, git, and watch-pr dependencies. The whole-PR review found no additional prose or wiring blocker. Shipping's executable, verdict format, Bugbot exclusion, exact-change hash and GitHub-only scope agree with the implementation. The poteto-mode trigger covers merges an agent schedules itself. The wording is minimal and clear. No AGENTS.md or CLAUDE.md is changed by the PR. watch-pr changes exports only. The accepted base-race window is not a finding in this round. Required checks in the isolated worktree at the head above: The independent probe run exited 1 because eight assertions expected a read error and received exit 0. Its complete outcome list follows. An initial exploratory harness run reused mutable fixtures; I fixed fixture isolation and reran. The outcomes below come from fresh cloned fixtures. Independent probes, 89 casesConfirmed live SHA fetching in a fresh bare object store. Live executable checks used fresh temporary stores. Open PRs at the time were #11-15. #10 refused as merged, #11 would merge, and #15 refused on its open threads, latest FAIL, and running Codex review. These are the complete outputs, including the run-log rows. No live merge command was run. Live --check outputs and logs |
A comment now needs a positive, unique id, a non-empty login and one of GitHub's account types. Only a User account counts as a person, so an unknown type can no longer approve instruction-file changes, and a malformed newer comment can no longer hide behind an older one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
pstack-verdict: FAIL head=807cdeae093d05bb5ace7b280dac86bd32a86563 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 5. The account-type and comment-ID fixes are confirmed. The empty-login fix still misses the whitespace-only case already reported in round 4.
Threat-model classification. This is a missing structural validation check on an author field that decides a pass. It is the whitespace counterexample from round 4, not a new hypothetical response category and not a claim that GitHub returns whitespace logins. The real Round-4 fixes confirmed. Unknown account types, including empty, Whole-PR review. I read all four prior verdict comments, both task briefs, the source retro brief and decisions, FORK.md, every changed file in full, and the bootstrap, verdict-hash, and watch-pr dependencies. The Shipping verdict format matches the parser, its merge command names the executable present here, and its Bugbot exclusion, exact-change hashes, Codex head binding, and GitHub-only scope match the implementation. poteto-mode's trigger includes merges scheduled by the agent's own plan. The prose is minimal and clear. No AGENTS.md or CLAUDE.md is changed by this PR. watch-pr's diff adds exports only. The accepted base-retarget window is not a finding. I found no additional prose or wiring blocker under the stated scope. Earlier fixes also remain effective in the independent probes. A higher-ID FAIL wins even in a reversed same-second array. Editing an older completed Codex comment does not hide a newer pending summary. Missing comment fields, unreadable check discriminators, missing rollup, and incomplete check/thread continuations error. Explicit null rollup permits no checks. Failed checks, open threads, merge queues, and changed verdict patches refuse. An identical patch rebased onto the new base carries its verdict. Required checks. These ran in my isolated worktree at the head above. An initial drift-check attempt raced with temporary test files I had placed inside the scanned skill tree. It failed with ENOENT. I moved my artifacts outside that tree and reran the drift checks sequentially after the suite completed; the outputs above are the successful reruns. This was my harness setup, not a PR defect. The required suite includes its existing fake-only merge-path tests. Every independent gate invocation and live executable run used Confirmed live fetching of the force-pushed-away SHA used in earlier rounds, from a fresh bare object store. The final fresh fetch still gives merge base d46bc58, and GitHub still reports head 807cdea. Open PRs were #11-15. Independent probe output and complete live outputs with temporary-store run logs follow. Independent probes, 46 casesLive --check output and run logs |
A whitespace login passed the empty check and could hide a newer Codex summary. Logins now must match GitHub's login pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
pstack-verdict: FAIL head=b512b0a4246723d590263e715670f8db5e1f5705 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 6. The round-5 whitespace finding is fixed. The stronger pattern introduces one P2 regression for valid GitHub logins.
Round-5 fix confirmed. Independent fixtures reproduce exit 0 with the reader from 807cdea for a newer pending Codex summary whose login is a space, tab, or newline. The current reader returns exit 2 for all three. Empty and mixed whitespace also error. Normal user, hyphenated user, and bot logins remain readable. The existing regression test is included in the passing suite. Whole-PR review. Read the verification and build briefs, source retro brief and decisions, FORK.md, rounds 4 and 5 in full, every changed file in full, and the bootstrap, verdict-hash and watch-pr dependencies. Shipping's executable and verdict format match the implementation. Its Bugbot exclusion, exact-change hashes, Codex head binding and GitHub-only scope agree with the contract. The poteto-mode trigger includes agent-scheduled merges. The prose is minimal and clear. No AGENTS.md or CLAUDE.md is changed. watch-pr's diff adds exports only. No additional blocker was found under the specified threat model. The accepted base-retarget race is not a finding. Earlier fixes remain effective in the independent probes. Higher-ID FAIL wins in a reversed same-second array. An edit to an older completed Codex summary cannot hide a newer pending summary. Unknown account types, invalid or duplicate comment IDs, missing comment fields, unreadable check discriminators, missing rollup and incomplete continuations error. Failed checks and merge queues refuse. Explicit null rollup permits no checks. Verification. All work ran in an isolated worktree at the head above. Every independent gate invocation and live executable run included A fresh fetch still reports merge base d46bc58. GitHub still reports head b512b0a. Open PRs were #11-15. Complete independent probe results and live outputs follow. Independent probe outputLive --check output and temporary-store run logs |
The GitHub login pattern rejected Enterprise managed user names, which contain underscores, so an ordinary comment from such a user stopped the gate. The check now rejects only empty or blank logins, which is what the whitespace finding needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39929c4b1d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
pstack-verdict: FAIL head=39929c4b1d144bda64f545c6f0ed873b3cb7bc32 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 7. The round-6 Enterprise Managed User regression is fixed. One remaining P2 affects the accuracy of merge reporting and the retro log.
Round-6 fix confirmed. With an ordinary comment by Whole-PR review. Read the verification/build briefs, source retro brief and decisions, FORK.md, rounds 5 and 6 in full, every changed file in full, and the bootstrap, verdict-hash and watch-pr reader/type dependencies. Shipping's verdict line matches the parser and its command names the executable present here. Its Bugbot exclusion, exact-change hashing, Codex head binding and GitHub-only scope match the contract. poteto-mode includes agent-scheduled merges. The prose is minimal and clear. No AGENTS.md or CLAUDE.md is changed by this PR. watch-pr changes exports only. I did not reopen the explicitly accepted base-retarget race or add identity/authentication requirements beyond the brief. Checks and independent probes. Work ran in an isolated worktree at the head above. Every independent gate invocation and live executable run included --check and used a temporary PSTACK_STORE. The independent harness rejects every write command. The required repository suite includes its existing fake-only merge-path tests. No live merge was attempted. The independent probes cover prior comment-ordering fixes, invalid/duplicate IDs, missing comment fields, unknown account types, unreadable checks, incomplete pagination, open threads, merge queues, failed checks, Bugbot exclusion, stale verdicts and identical rebases. Finding 1 is in the write-result reporting path, which the --check-only probes do not execute. An initial test command ran from the repository root and also scanned unrelated orchestrate tools. That broader run reported 243 pass and 21 failures/errors, including missing A final fresh fetch still reports the merge base above, and GitHub still reports head 39929c4. Live --check refuses merged #10, would merge #11, and refuses #15 because six review threads remain open and the previous independent verdict is FAIL. Codex's summary now reports this head completed. Independent probe outputComplete live --check outputs and temporary-store logs |
When the gate's merge command fails but read-back shows the PR merged into trunk, the gate printed NOT MERGED. It now says the PR merged but not through the gate, and logs merged-elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
pstack-verdict: PASS head=5857fa261586b09b6420f303c6f53cc5c753afd1 base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Round 8. No findings under the PR's stated threat model. Round-7 fix confirmed. The new repository regression at Whole-PR review. Read both briefs, the source retro brief and decisions, FORK.md, the round-6 and round-7 verdict comments in full, every changed file in full, and the bootstrap, verdict-hash and watch-pr reader/type dependencies. Shipping's executable path and verdict format match the implementation. The requirements cover checks, unresolved threads, exact-change verdict hashes, current-head Codex completion and exact instruction-file approval. Bugbot exclusion matches the explicit name-based contract. The poteto-mode trigger covers agent-scheduled merges. Origin is explicitly unsupported for gate execution. The prose is clear and confined to the requested procedural change. No AGENTS.md or CLAUDE.md is changed. watch-pr's changes add exports only. I judged GitHub values as trusted and checked the reads that could allow a pass for structural omissions. I did not impose new authentication requirements on verdict or approval comments or reopen the accepted base-retarget window. No new finding met the requested classifications. Independent checks. A fresh actual-reader harness runs main with --check for every case and rejects merge commands. All 53 cases behaved as expected, with 243 gh reads and zero merge commands. It covers the EMU fix, whitespace logins, invalid/duplicate IDs, missing comment fields, unknown account types, same-second verdict ordering, edits to old verdicts and Codex summaries, stale hashes and Codex SHAs, identical rebases, unreadable checks, incomplete pagination, open threads, merge queues and unapproved instruction changes. All independent gate invocations and live executable runs included --check and used a temporary PSTACK_STORE. The required repository suite includes its existing fake-only merge-path tests; the red regression run also uses only that fake. No live merge was attempted. A fresh bare object store fetched force-pushed-away commit ab543f1 from GitHub by SHA and read it as a commit. A final fresh fetch still reports the merge base above, and GitHub still reports head 5857fa2. Live --check refuses merged #10, would merge #11, and refuses #15 for its six unresolved review threads, prior FAIL verdict and running Codex review. PASS here is the code-review verdict; those live gate requirements still need handling before a merge. Regression red on 39929c4Independent probe outputComplete live --check output and temporary-store log |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5857fa2615
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ng before merging - Count a pstack-verdict or lee-approves-instruction-files line only from a comment whose author_association is OWNER, MEMBER or COLLABORATOR. The no-verdict refusal lists the verdict lines it ignored. - Read and judge every requirement again right before gh pr merge, and refuse with NOT MERGED and the lapsed requirement. - Ignore only Bugbot's own check runs: the cursor app's runs named Bugbot. - Refuse while the review decision is CHANGES_REQUESTED. - Refuse while auto-merge is armed, printing the command that disarms it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7915870bb7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
pstack-verdict: PASS head=7915870bb738d1ec4fec3ac59b08d717f18aee0c base=d46bc580ce06f6bf60f15bb6a125d339cfa012b8 by=codex/gpt-6.1-sol Final verification. No blocking or backlog findings under the coordinator's threat model and final-round stop rule. I reviewed the whole PR at this head, including every changed file, Shipping and poteto-mode wiring, FORK.md, the source retro brief and decisions, both implementation briefs, the round-8 verdict and all six accepted bot findings. No AGENTS.md or CLAUDE.md changes appear in the PR. watch-pr's diff adds exports only. I confirmed all five fixes myself.
Seven selected regression tests covering all five fixes fail against the 5857fa2 implementation and pass against 7915870. I copied the head's scripts to an isolated temporary tree, replaced cli.ts, gate.ts, github.ts and read.ts with their 5857fa2 versions, and ran the same tests there. The old implementation returns success where each new regression expects refusal. All merge-path tests use the existing fake GitHub implementation. The actual-reader probe CLI rejects every merge command, and all my independent main calls include --check. My separate actual-reader probes run 37 cases through --check. At this head all 37 match the expected exit and produce 207 gh reads with zero merge commands. Running that same probe script against the isolated 5857fa2 implementation produces 24 mismatches and zero merge commands. This verifies the behavior independently of the added tests. The remaining concurrency window is accepted as described in the PR scope. The second read is not an atomic GitHub snapshot. A mutable fact can change after its own final read while the other reads, git work or merge request run. --match-head-commit pins the head. It does not pin the base or review state. A late base retarget is detected by the existing wrong-base read-back. I have not measured or assumed a fixed duration for this window. Required checks and outputs: All live gate invocations included --check with PSTACK_STORE in a temporary directory. No live merge or auto-merge change was attempted. The first live sweep refused merged #10 and safely refused #11, #12 and #13 while GitHub reported UNKNOWN mergeability. On the final read GitHub reports #15 OPEN and MERGEABLE with autoMergeRequest null. Its final --check output below remains the merge-readiness result. This PASS is the independent code verdict; the coordinator still handles any outstanding live requirements. Independent actual-reader probe outputRegression red output on 5857fa2Regression green output on 7915870Live check sweepFinal live check of PR 15 |
Why
The retro found PRs merged on heads no verdict saw, with unread review findings, and while a bot review was still running. Those merges skipped Shipping, whose trigger only named "asked to land or ship". Lee chose one script that every agent merge goes through, reviewed at every retro.
What changed
scripts/merge-gate/merge-gate --repo <owner/name> --pr <n> [--check]. At the PR's current head it refuses unless checks passed (Bugbot ignored), no review thread is open, the latestpstack-verdict:line's hash matches the current change, Codex's summary names this head as completed, and any AGENTS.md or CLAUDE.md change has Lee'slee-approves-instruction-files: <hash>line. Then it merges with--match-head-commitand reads the PR back. Every run appends a row to<pstack store>/merge-gate/runs.tsv.Scope
GitHub only. On Origin, Shipping says to stop and report.
The approval line can't prove Lee wrote it, because agents act under his token. It makes approval a deliberate, exact-text step and the gate's refusal says agents never post it.
Threat model: the gate guards against agents skipping steps, not a lying GitHub. It checks the shape of every GitHub read that could turn a refusal into a pass and treats a bad shape as a read error. It trusts the values GitHub returns.
Verdict and approval lines count only from the repo's owner, members or collaborators, because the repo is public.
Right before merging, the gate reads and checks everything again. A change between that last read and GitHub performing the merge is missed. That window was not measured (LH-118). A retarget in that window is reported as MERGED INTO THE WRONG BASE.
Tradeoffs
Blast Radius
Every agent merge now needs a counterpart verdict line and a Codex review of the head. A repo without Codex review set up will refuse until that is set up or Lee rules otherwise.
Verification
bun test: 162 pass,typecheckclean. Tests use a real git remote that serves force-pushed-away SHAs, and a fakeghthat proves every call names--repo. Five rules were broken one at a time, and each break failed a test.--checkon the live repo: refuses merged fix(pstack): reuse a verdict only when the exact whole-PR diff matches #10 and fix(pstack): five small skill fixes from the 2026-10-17 retro #11 (open thread, stale verdict, stale Codex), with plain reasons. Would merge docs(fork): read FORK.md before an upstream merge, a push, or a PR #12 and feat(orch): edit and remove standing orders #13.node scripts/check-t3-port.mjsclean, its tests 32 pass.Linear: LH-86
🤖 Generated with Claude Code