Let agents merge only edge changes
Some folders of a codebase are its core: the parts where a mistake breaks everything else, such as the engine, the database schema or the security checks. Other folders are edges: pages, docs, tests and small tools, where a mistake stays small.
The merge policy lets agents keep merging edge changes as soon as the checks pass, and makes a change to the core wait for a person. You decide which paths are core. Until you list some, nothing is core and nothing changes.
What it does
For each pull request (a proposed change on GitHub), AgentX reads the list of changed files and posts a status named agentx/merge-policy on its latest commit:
| The pull request | Status | Description starts with |
|---|---|---|
| changes no core path | success | "edge only" |
| changes a core path and a person approved it | success | "core paths changed … approved by …" |
| changes a core path and was opened by a person | success | "core paths changed … opened by …" |
| changes a core path, no approval yet, required mode | pending | "core paths changed … waiting for a person" |
| changes a core path, no approval yet, advisory mode | success | "[advisory] core paths changed" |
| changes a core path and someone requested changes | pending | "core paths changed … requested changes" |
| its changed files could not be read | error | "could not read the changed files" |
"Opened by a person" means opened by a GitHub account that AgentX does not post with. A person's own pull request passes without a second review, because it is their change rather than an agent's. The accounts AgentX posts with (its GitHub App, the owner of its personal token, any account listed for an agent, and the accounts your other AgentX machines post with) always count as agents. So if one account both runs AgentX and opens your own pull requests, every core pull request from it needs an approval: the card or a review from someone else.
A renamed file counts at its old path too, so moving a file out of a core folder is a core change. A pull request with 3,000 changed files or more counts as core, because GitHub may not list them all.
A pull request that changes a core path also gets a label,
core-changeunless you choose another, so you can find these in the pull request list. The label comes off again when a later push no longer touches a core path.Every pull request still runs the full CI (the automatic tests GitHub runs). The policy adds a check; it never skips one.
The policy never merges anything and never changes your branch settings. The status only blocks a merge once you make it a required check (below).
How a person approves
An approval belongs to one commit. A new push needs a new approval.
- On GitHub: an Approve review on the latest commit, from someone other than the pull request's author and other than the accounts AgentX posts with, who is an owner, member or collaborator of the repository. If you set
approvers, only those logins count. Each person's latest review is the one that counts: a later "Request changes" or a dismissal takes their approval back, and a standing "Request changes" from anyone who counts holds the pull request. - On your approvals card: in required mode, AgentX also raises a card for you (the same cards as in Approvals) that asks whether to approve the pull request at that commit. YES approves it; within about a minute the status turns green. This is the way to approve when one GitHub account opens every pull request, because GitHub does not let an author approve their own pull request.
Before you start
- Browser: make sure the GitHub channel already works: an issue in the repository reaches an agent and gets a comment.
- Browser: on GitHub, open the AgentX GitHub App's settings, then Permissions. Give it Commit statuses: Read and write, Pull requests: Read and Issues: Read and write (labels are issue labels). With a personal token instead, it needs the
reposcope. - Browser: in the repository's Settings › Webhooks, open the AgentX webhook and tick Pull requests and Pull request reviews.
Turn it on
Terminal: open
agentx.jsonand add your core paths underquality.mergePolicy. Start inadvisorymode. The paths below are only an example; list your own:json"quality": { "mergePolicy": { "enabled": true, "mode": "advisory", "corePaths": ["src/engine/**", "src/auth/**", "db/migrations/**"], "edgePaths": ["src/engine/fixtures/**"] } }*stays inside one folder,**crosses folders, and a folder name on its own covers everything under it. A file that matchesedgePathsis edge even inside a core folder.Terminal: restart the daemon with
agentx daemon restart --when-idle.Browser: open or push to a pull request and look at its checks list.
From advisory to required
In advisory mode a core change is marked but never held. Run it like this for a few days to see which pull requests count as core, and adjust the paths.
To make core changes wait for a person, once the repository owner agrees:
- Terminal: set
"mode": "required"inagentx.jsonand restart the daemon. - Browser: in the repository's Settings › Branches, edit the rule for
mainand addagentx/merge-policyto the required status checks. Turn on Do not allow bypassing the above settings, or an admin account (which agents may use) can merge anyway.
Settings
Under quality.mergePolicy:
| Key | Type | Default | What it does |
|---|---|---|---|
enabled | boolean | false | Turns the policy on. Off, no status or label is posted. |
mode | "advisory" or "required" | "advisory" | Advisory passes an unapproved core change with "[advisory]". Required leaves it pending until a person approves. |
corePaths | list of patterns | [] | Files that count as core. Empty: nothing is core, every pull request is "edge only". |
edgePaths | list of patterns | [] | Exceptions carved out of corePaths. |
label | text | "core-change" | The label put on a core pull request. |
approvers | list of GitHub logins | [] | Only these logins' reviews count. Empty: owners, members and collaborators of the repository, except the author and AgentX's own accounts. |
ownerCard | boolean | true | In required mode, raise an approvals card for each unapproved core commit. |
Check it worked
- Browser: have an agent open a pull request that changes only an edge file. Its checks list shows
agentx/merge-policygreen with "edge only". - Browser: have an agent open a pull request that changes a core file. It gets the
core-changelabel, andagentx/merge-policyreads "core paths changed" with the file names. - Required mode: the status is pending, and a card "Core change waiting: …" is in your approvals. Answer YES. Within about a minute the status turns green with "approved by".
- Browser: push a new commit to that pull request. The status is pending again and a new card asks about the new commit.
If something is wrong
- No
agentx/merge-policystatus. Check thatquality.mergePolicy.enabledistrueand that the webhook sends Pull requests events. Drafts are skipped until they are marked ready. Terminal: look for[merge-policy]lines in the daemon log. - The log says "check failed: GitHub POST …/statuses/…: 403". The App or token cannot write commit statuses. Give it Commit statuses: Read and write.
- The log says "label failed". The App or token cannot write labels. Give it Issues: Read and write. The status is still posted.
- A GitHub approval does not turn the status green. The approval must be on the latest commit, from someone who is not the author and not an AgentX account, and the webhook must send Pull request reviews events. If
approversis set, the login must be in it. - No card in required mode.
ownerCardmay befalse, or the agent routed to the repository already has the most cards waiting allowed. The log says "owner card not raised" and why. Approve on GitHub, or answer older cards first. - Every pull request is "edge only".
corePathsis empty, or its patterns do not match. Paths are relative to the repository root, without a leading/. - A core change was merged anyway. The status is only advisory until
agentx/merge-policyis a required check on the branch and admins cannot bypass it.
