Skip to content

Set up Mergepatrol - #97

Merged
joaquim-verges merged 3 commits into
mainfrom
mergepatrol/config
Oct 30, 2026
Merged

joaquim-verges merged 3 commits into
mainfrom
mergepatrol/config

Conversation

@merge-loop

@merge-loop merge-loop Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

This PR adds .mergepatrol/mergepatrol.yml with the settings below. Once it merges into main, Mergepatrol runs a merge queue on this repo: add the mergepatrol label to a PR to queue it.

  • Trigger label: mergepatrol
  • Batch size: 8
  • Resolver: Anthropic claude-opus-5-5, effort medium
  • Verify commands: pnpm install --frozen-lockfile, pnpm check --error-on-warnings, pnpm knip, pnpm typecheck, pnpm --filter @bugpatrol/site typecheck (all of CI's build except pnpm test, which needs a browser the job sandbox lacks)
  • Fix failed checks: on, up to 2 attempts

It also adds the mergepatrol agent skill, at .agents/skills/mergepatrol/SKILL.md and .claude/skills/mergepatrol/SKILL.md, so coding agents in this repo queue their PRs instead of merging them.

To change the settings later, edit the file, or use the Mergepatrol dashboard, which opens a PR like this one.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@vercel

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
bugpatrol Ready Ready Preview Oct 30, 2026 4:10pm UTC

Request Review

Copy link
Copy Markdown
Contributor

Verdict on the verify-command gap

Can this config let a broken commit reach main? Not one that build would catch. The repo's real hole is elsewhere: Determinism isn't required (see below).

Evidence, from Mergepatrol's source (agent-labs-dev/mergepatrol@cfed12b) and this repo's ruleset:

  • The merge gate is the trunk's required checks, read live before every merge. checks_verdict (crates/mergepatrol/src/queue.rs) evaluates the pushed head against required_checks, which comes from /rules/branches/main. Main's ruleset requires build (GitHub Actions). build runs everything the repo has: pnpm check --error-on-warnings, knip, tsc --build, the bundle, the site typecheck and build, and pnpm test.
  • Every commit the queue pushes gets its own build run before it can merge. That covers a rebase, a resolver's resolution, and a fix_ci commit. The App's pushes trigger pull_request workflows (this PR's own bot commit got CI). GitHub's ruleset also refuses the merge independently while build is red.
  • Batches don't bypass it. A batch is tested as one branch against the same required checks, and GitHub then merges each PR, as on any non-strict trunk.
  • So verify: [] was not a path to main. It meant the agent could push an unchecked resolution or fix, which build would then reject and eject. It also meant the agent had nothing it was allowed to run to check its own work: verify commands are the only Bash the resolver may call (crates/resolver/src/claude.rs).

What I changed (commit 2e7c9e7, signed and Verified, fast-forward on top of 5d2a25e, no history rewritten)

verify:
  - pnpm install --frozen-lockfile
  - pnpm check --error-on-warnings
  - pnpm knip
  - pnpm typecheck
  - pnpm --filter @bugpatrol/site typecheck

These mirror CI's build job except pnpm test. I ran each one from a clean install with Playwright browsers hidden, to match the job sandbox. All pass, in 2s, 2s, 2s, 8s and 2s, well inside Mergepatrol's 600s per-command limit.

pnpm test is deliberately left out. Without Chromium it fails 13 tests across 8 files (browserType.launch: Executable doesn't exist). Mergepatrol's job image (node:24-bookworm-slim) has no browser, browser system libraries or ffmpeg, so pnpm test would eject every PR the agent touched. build still runs the tests on the pushed head before any merge.

Note: the Nebula push path rebuilt this commit on the current main tree. The branch now differs from main only in this PR's three files, and CI ran against today's main.

The gap that does let a broken commit through (needs a repo admin, not this PR)

Main's ruleset requires only build. flake-check and runner-image (Determinism) are not required. Mergepatrol waits only for required checks, so it would merge a PR whose Determinism run is red. Until now that relied on a human seeing the red X; an unattended queue removes that human. Determinism has passed on every one of its last 15 runs on main, so making both checks required is low risk.

Ask: add flake-check and runner-image (integration 15368, GitHub Actions) to ruleset 24027928's required status checks. The App token I'm using can't edit rulesets.

Current CI on this PR

build, flake-check, runner-image, Socket and Vercel all pass. The four review-smoke jobs fail with Model returned 401: "User not found" from OpenRouter. That workflow has failed this way on every PR since 2026-10-22, so the OPENROUTER_API_KEY repo secret is dead. It's unrelated to this PR and not required.

Recommendation: safe to merge once the ruleset change above is made. It's also safe to merge before then, if you accept that Determinism stays advisory for queued PRs.

Copy link
Copy Markdown
Contributor

Follow-up: the Determinism gap is closed in this PR

The gap: main's ruleset (24027928) requires one check, build. Mergepatrol decides on the required checks alone. In Checks::verdict (crates/github/src/checks.rs:28-41, agent-labs-dev/mergepatrol@cfed12b), any check not in the trunk's required list is never read once at least one check is required. So a PR with a red flake-check or runner-image (Determinism) would merge from the queue.

Why verify can't close it: verify commands run only after an agent resolution or fix (crates/mergepatrol/src/job.rs:262 and :329), never on a clean rebase. They also run in a job image with no browser. Mergepatrol's config has no other knob for checks: its fields are label, batch_size, resolver, verify, fix_ci and branches.

The fix, needing no Mergepatrol or ruleset change (commit 60d4880, signed and Verified, fast-forward on 2e7c9e7):

  • CI's old build job is renamed checks.
  • determinism.yml is now a reusable workflow (on: workflow_call) that CI calls.
  • A new build job needs: [checks, determinism], runs on always(), and fails unless every need's result is success. always() matters: a job skipped after a failed need counts as passed for a required check, to GitHub and to Mergepatrol (checks.rs:130 maps skipped to Passed).
  • The required check name is still build, so the ruleset needs no edit.

Checks:

  • actionlint is clean on both workflows.
  • I ran the gate script against sample needs payloads: all success passes, determinism: failure fails, and skipped/cancelled fails.
  • On this PR, build passes (4s), checks (2m11s), determinism / flake-check and determinism / runner-image pass, and Socket and Vercel pass.

Still red, unrelated: the four review-smoke jobs fail with OpenRouter 401 User not found, as on every PR since 2026-10-22. The OPENROUTER_API_KEY repo secret needs rotating. They aren't required, so they block neither GitHub nor Mergepatrol.

This replaces the ruleset change I asked for in my earlier comment; no admin action is needed for the queue to be safe. Safe to merge.

joaquim-verges and others added 3 commits October 30, 2026 09:09
Co-authored-by: Nebula AI Agent <277912164+nebula-ai-agent[bot]@users.noreply.github.com>
The queue's agent can commit a conflict resolution or a CI fix to a PR
branch. With `verify: []` it pushed that commit unchecked and relied on
the required `build` check alone to catch a bad one. Required `build`
still gates every merge, so this was not a path to main, but it let
the agent push a broken resolution and gave it nothing to check its own
work with.

These mirror CI's `build` job except `pnpm test`, which needs Chromium
and ffmpeg that Mergepatrol's job image does not have. Each was run
locally from a clean install with browsers hidden: install 2s, check 2s,
knip 2s, typecheck 8s, site typecheck 2s, all well under the 600s
per-command limit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-authored-by: Nebula AI Agent <277912164+nebula-ai-agent[bot]@users.noreply.github.com>
Main's ruleset requires one check, `build`. Mergepatrol merges once the
trunk's required checks pass and ignores the rest (Checks::verdict in
crates/github/src/checks.rs), so a PR whose Determinism run was red
would merge from the queue. Until now only a person reading the red X
stopped that.

The old `build` job is now `checks`. Determinism becomes a reusable
workflow that CI calls. A new `build` job needs both and fails unless
each succeeded. It runs on always(), because a job skipped after a
failed need counts as passed, to GitHub and to Mergepatrol (checks.rs
maps skipped to Passed) alike. The check name is unchanged, so the
ruleset needs no edit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-authored-by: Nebula AI Agent <277912164+nebula-ai-agent[bot]@users.noreply.github.com>

Copy link
Copy Markdown
Contributor

Branch cleanup: mergepatrol/config now sits on current main (3344208) as three Verified commits: de6a01a Set up Mergepatrol, 868c1ea Set Mergepatrol verify commands, 9b6537e Make the required build check wait on Determinism. The diff is back to its real size, 5 files, +124/−4. The tree is byte-identical to the old head 60d4880. The only change is that the replayed copy of #99 is gone. CI on 9b6537e passed (build, checks, determinism / *).

Review smoke 401: this does not block this PR any more. Review smoke only runs when a PR touches packages/**, examples/**, action.yml, pnpm-lock.yaml or its own workflow, and the replayed #99 content was what made it run here. The failure itself is still real and affects the whole repo:

  • Workflow Review smoke, jobs api (step "Run one patrol cycle") and review (cli|dashboard|fixture-app) (the ./ action step). Both read OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}.
  • Log: Model returned 401: {"error":{"message":"User not found.","code":401}}. The env shows OPENROUTER_API_KEY: ***, so the secret is set and was passed to the job. The PR came from a same-repo branch, so this is not the fork-secrets case.
  • OpenRouter returns exactly that body for a well-formed key it doesn't recognise. I checked with a dummy sk-or-v1-… key. A missing key returns No cookie auth credentials found instead. So the stored key has been deleted or revoked, or its account is gone. The secret name, scope and workflow wiring are all correct.
  • Last green run: 2026-10-16 (run 38860459462). Every run since 2026-10-22 has failed with the same 401, including ci: pin every GitHub Action to a commit SHA #94, chore(deps): bump the actions group with 7 updates #95/ci: fix the review smoke on Dependabot PRs and under SHA pinning #96 and t3/backend-app-coverage-plan.

Needs a repo/org admin: replace the OPENROUTER_API_KEY Actions secret on agent-labs-dev/bugpatrol (or the org secret, if that's where it lives; this token can't list secrets). The new value should be a live OpenRouter API key, shaped sk-or-v1-<64 hex>, from an account with credit. Re-run any Review smoke afterwards to confirm. Nothing in this PR needs to change.

@joaquim-verges
joaquim-verges merged commit aa3b40b into main Oct 30, 2026
8 checks passed

This branch was successfully deployed

1 active deployment
Preview — 9b6537e3 Deployed Oct 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant