PRs While You Sleep: Auto-Apply and Tiered Auto-Merge Internals
How a card becomes a branch, a branch becomes a PR, and — under six gates — a PR becomes a merge, with no one watching.
Once GitHub is connected and a repo selected, yeet-seo can turn a card — a detected, scored fix — into an actual pull request against your codebase, and under the right autonomy settings, merge it without a human in the loop. This is the mechanism behind the did.prs_opened and awaiting_approval.prs_awaiting_merge arrays you see in a check report. This guide covers the internals: how a URL maps to a file, what each fix type actually edits, and the exact gate sequence a PR has to clear before it merges itself.
It's worth being explicit about the two separate decisions bundled into "autonomous PRs," because they carry very different risk: opening a PR is reversible by construction — nothing lands until someone (or something) merges it — while merging one changes production. yeet-seo treats these as genuinely separate authorizations rather than one "autonomy level," which is why the gate list below exists as a distinct, stricter checklist layered on top of whatever governs auto-apply.
Connecting the repo
From the dashboard, connect GitHub and select the repo backing the workspace's properties. yeet-seo needs write access to open branches and PRs; merge permission is a separate, later gate (see below) — connecting the repo does not by itself authorize auto-merge.
URL → file mapping
Given a tracked URL, yeet-seo resolves it to a source file using framework heuristics rather than a fixed convention, because "the file that renders /playbook/foo" differs by stack:
- Next.js (app router) — resolves to
app/playbook/foo/page.tsx(or the matching dynamic segment), and reads/writes the exportedmetadataobject directly rather than string-patching JSX - Next.js (pages router) — resolves to
pages/playbook/foo.tsxand itsHeadusage - Astro, Nuxt, and static-site generators — resolved via each framework's routing convention (file-based routes, content collections) with the equivalent front-matter or head-tag targets
If the mapping is ambiguous — a URL with no clean file match, e.g. behind custom middleware routing — the card stays open with a lower confidence score rather than guessing at a file to edit; low confidence keeps it out of auto-apply eligibility entirely (see the confidence floor below).
What each fix type edits
| Subcategory | Edit |
|---|---|
meta_tags | Replaces title/description — via the Next.js metadata export where applicable, or the equivalent head tag elsewhere |
schema_markup | Injects JSON-LD as a script block immediately before </head> |
technical_seo | Flips an erroneous noindex robots directive, or inserts a missing canonical tag |
llms_txt | Creates or updates an llms.txt file at public/ or static/, whichever the detected framework serves as its static root |
cannibalization | Adjusts internal linking/canonicalization between competing URLs — this one almost always surfaces as a hypothesis first (see outcome priors) rather than a direct edit |
Example JSON-LD injection, illustrating the "before </head>" placement:
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article", "headline": "..." }
</script>
</head>
Branch naming and the PR
Every auto-applied fix opens on a branch named yeet-seo/fix-{id}-{subcategory} — e.g. yeet-seo/fix-44a1-meta_tags — so you can grep your branch list for anything yeet has touched. The PR description links back to the card and the check that produced it. If you're scripting anything against the repo — a bot that annotates PRs, a dashboard that groups them — the branch prefix yeet-seo/ is the stable thing to match on; the {id}-{subcategory} suffix is what you'd parse out to join back against the card via the API or MCP tools.
The six auto-merge gates
Auto-apply (opening the PR) and auto-merge (landing it) are separately gated. A PR only self-merges if all six of the following hold:
- Auto-merge is explicitly opted into for the workspace
- The current autonomy mode allows it
- The fix's subcategory is in the safe set
- Confidence is at or above a hard 0.85 floor
- The PR is at least 10 minutes old (a cooling-off window for a human to intervene)
- CI is green — or there are no checks configured — and the PR is mergeable (no conflicts)
That 0.85 floor is not negotiable by autonomy mode: even auto_apply_aggressive, which will apply any fix type at ≥0.75 confidence, still will not merge below 0.85. Aggressive mode widens what gets attempted; it does not lower the merge bar. Full mode semantics are in the autonomy modes guide.
Where does a given fix's confidence number actually come from? Not from the strength of the detection alone — the investigator calibrates it against the fix_outcomes ledger for that subcategory, so a meta_tags fix in a workspace with a strong verified history for that subcategory clears 0.85 more easily than an equally plausible-looking fix in a subcategory that has historically regressed often. See the outcome priors guide for exactly how that calibration works and how to query it yourself before deciding how far to open the gates.
Controlling it via MCP or REST
PUT /api/v1/autonomy
Authorization: Bearer yseo_your_key_here
Content-Type: application/json
{
"mode": "auto_apply_safe",
"auto_merge": true
}
Or via MCP, the equivalent is the set_autonomy tool, taking the same { mode?, auto_merge? } shape — both fields optional, so you can flip auto_merge without touching mode or vice versa. This is one of the higher-stakes write calls in the tool set; see MCP setup for scope requirements before an agent is allowed to call it unattended.
If it goes wrong
Every auto-merged PR has a revert path — reverting the commit un-does the file edit, and the card's outcome tracking picks up the reversal the same way it picks up a manual revert. Merges (and reverts) are detected via webhook/commit inspection against the branch, which is what advances a card from prs_awaiting_merge/applied into the verifier's queue — see how yeet verifies fixes for what happens next.
Quick FAQ
Q: Can auto-merge work with branch protection rules requiring review?
A: No — gate 6 requires the PR to be mergeable; a branch protection rule mandating human review blocks the merge regardless of the other five gates, and the PR sits in prs_awaiting_merge until a human approves it.
Q: Does auto-apply run in propose_only mode?
A: No — propose_only only creates cards/hypotheses for review; nothing is applied or merged until a human (or an agent with write scope) explicitly acts on it.
Q: What happens to a PR that never reaches CI green?
A: It stays open awaiting manual merge or close; auto-merge simply never fires for it, and it doesn't block other fixes from applying.