Development record
abcd-managed repos need PR-queue hygiene when branch protection requires up-to-date branches: a queued auto-merge PR whose base moved sits BEHIND forever because GitHub auto-merge never updates branches. Two delivery rungs per basics-built-in/SOTA-delegated: (1) protocol-level now — after arming auto-merge, poll mergeStateStatus and run gh pr update-branch on BEHIND (works with the agent's own token, CI triggers normally); (2) scaffolded CI later — abcd scaffolds an update-branch workflow into managed repos, which requires a PAT/GitHub-App secret because the default GITHUB_TOKEN's pushes do not trigger workflows (the recursion suppression trap), or points at a merge queue where the plan allows. Same scaffolding family as itd-93's release gate; same merged-work-hygiene family as itd-95.
abcd-managed repos need PR-queue hygiene when branch protection requires up-to-date branches: a queued auto-merge PR whose base moved sits BEHIND forever because GitHub auto-merge never updates branches. Two delivery rungs per basics-built-in/SOTA-delegated: (1) protocol-level now — after arming auto-merge, poll mergeStateStatus and run gh pr update-branch on BEHIND (works with the agent's own token, CI triggers normally); (2) scaffolded CI later — abcd scaffolds an update-branch workflow into managed repos, which requires a PAT/GitHub-App secret because the default GITHUB_TOKEN's pushes do not trigger workflows (the recursion suppression trap), or points at a merge queue where the plan allows. Same scaffolding family as itd-93's release gate; same merged-work-hygiene family as itd-95.
Second occurrence, 2026-08-11, on a single-commit record change (PR #213): auto-merge armed cleanly, an unrelated branch merged and moved the base, and the pull request then held at BEHIND indefinitely with auto-merge still armed and every check green. Updating the branch cleared it, CI re-ran on the updated head, and the merge completed unattended. Rung 1 as written is confirmed against the agent's own token; the 2026-08-11 decision is to ship rung 1 first per script-first-mvp and carry rung 2's credential question into the itd-107 grill.
INVARIANT, recorded because the convenient fix is the wrong one: the strict status-check policy is what makes concurrent additive auto-merge safe, and it is never relaxed to smooth this stall. Record ids are minted under a filesystem lock that serialises two sessions sharing one checkout but does not span checkouts, so two branches can each mint the same id and each pass the record gate in isolation — the duplicate exists only in the merged result, and strict is what forces that result to be gated before the second merge lands. Updating the branch resolves BEHIND while preserving the gate; dropping strict resolves it by removing the gate.
Remedy grounds (2026-09-29)
- SOTA check: GitHub's merge-queue guide (https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue, read 2026-09-29) gives the up-to-date guarantee without the author updating the branch, but only on organisation-owned public repositories or Enterprise Cloud private ones, and required Actions checks need the
merge_grouptrigger; the workflow-trigger guide (https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/triggering-a-workflow, read 2026-09-29) confirms events made with GITHUB_TOKEN start no new workflow run, dispatch events excepted. - abcd's own repository already runs a queue with strict kept (
.abcd/work/rulesets/main-protection.json), so the queue is the preferred rung where available and the App-token workflow the fallback; the App shape matches ruling H2 for dependency pushes. - Rejected: relaxing strict to clear BEHIND, which removes the gate the record's invariant keeps.
Frontmatter
| id | iss-172 |
|---|---|
| type | issue |
| lifecycle | open |
| severity | minor |
.abcd/work/issues/open/iss-172-abcd-managed-repos-need-pr-queue-hygiene.md
open on GitHub ↗ · commit history ↗
References2
- itd-107Autonomous Routines Assemble From One Versioned Templaterelated
- itd-2610261025516272Private repos land checked work without renting CIrelated
mentions11
- dcn-26081100000000012026-08-11 — Pull-request lifecycle automation for autonomous rounds settled
- dcn-26090100000000062026-09-01 — The strict up-to-date policy stays in front of the merge queue, and the branch update is automated instead (maintainer, ruling on iss-2609012202237613 against the two directions it names). Every auto-merge pull request opened tonight sat `BEHIND` outside the queue until a hand-run update, because auto-merge enqueues only a CLEAN pull request and the strict policy makes a behind pull request never CLEAN; the queue that exists to test a pull request against the current base therefore never received it. The queue's group commit does gate the merged result, so dropping strict would preserve the duplicate-id gate iss-172 records as an invariant, but the maintainer keeps strict and ships iss-172's first rung: `scripts/pr-keep-current.sh` walks every armed pull request and asks the forge to merge the base into any that is `BEHIND` and not queued, `--watch` repeating until none is armed. Rejected for now: relaxing strict (belt and braces are kept on purpose); a scaffolded update-branch workflow (rung 2, still needing a token whose pushes trigger checks, carried by itd-107). CONTRIBUTING no longer claims branches never need updating.
- iss-2609012202237613Every auto-merge pull request opened tonight (#571, #572, #574) sat BEHIND with queue entry null until a hand-run update-branch, while #570 and #573 entered the queue only because they happened to be up to date at the moment they were armed. Cause: main-protection combines the merge queue (grouping ALLGREEN, merge method MERGE, mirrored 2026-08-19) with strict_required_status_checks_policy true. Auto-merge enqueues a pull request only when its merge state is CLEAN, and under the strict policy a pull request behind main is never CLEAN, so it cannot enter the queue whose whole purpose is to test it combined with the current base. Every merge from the queue moves main and knocks the next un-queued pull request BEHIND again, so a batch of parallel PRs needs one manual update per merge. iss-172 records the invariant that strict is never relaxed because it is what gates the merged result against a duplicate record id minted by two checkouts; that reasoning predates the queue, and the queue now gates exactly that merged result (the group commit on top of main runs every required check before anything lands), so strict adds no gate the queue does not already hold and costs the queue its entry. itd-115 promises the queue removes this toil. Directions, for the maintainer to rule: (1) set strict false in the live ruleset and the mirror, keeping the queue as the gate, and record the ruling against iss-172's invariant; (2) keep strict and automate iss-172 rung 1, an update-branch loop after arming auto-merge, which is what tonight's session runs by hand.
- iss-2609020716561070The main ruleset requires a pull request to be up to date with its base before its checks count, and the merge queue already provides that guarantee by building each entry on top of the queue ahead of it; keeping both means every merge invalidates every open branch, so an autonomous run had to run scripts/pr-keep-current.sh after each of eleven merges and a peer session's overnight merges churned every branch this run held. GitHub's own guidance says the queue removes the need for the up-to-date requirement. Worth deciding whether the strict requirement still earns its place (iss-172 argued it gates a duplicate record id, which the timestamp mint since made moot).
- iss-2609181223354098A push to a pull request after auto-merge is armed on a merge queue can be dropped silently, and the bundled COMMITTING rules do not say so. Reported from the Gropius managed repository on 2026-09-18 (its own ledger carries it under its own id): with auto-merge armed and the entry already queued, a later push to the branch was not what the queue merged; the repository lost two commits and re-landed them in a second pull request. The failure is the forge's, not abcd's: a queue builds its entry from the head it took at enqueue time, and a push after that either removes the entry (to be re-armed) or, when the entry is already merging, lands nothing, and the pull request's merged state looks the same either way. The lesson is portable to every managed repository whose ruleset routes through a queue, which is why the session asked for a line in the bundled COMMITTING domain: after arming auto-merge on a queue, do not push again; if a push is needed, disarm first, push, re-arm, and confirm the merged sha contains the last local commit before deleting the branch. Sibling of iss-172 (queued entries left BEHIND) and iss-2609020716561070 (the up-to-date requirement beside a queue); this one is the dropped push, which neither covers. Recorded as a process observation; the routing (a COMMITTING rule, a line in the intake runbook, or both) is the product thinker's.
- iss-2609211105011322A pull request that goes BEHIND main under the strict ruleset never enqueues: the merge queue requires an up-to-date branch, and auto-merge armed on a PR that then falls behind waits forever without a word. The only recovery is scripts/pr-keep-current.sh, a forge update-branch that lives outside abcd; the pilot run hit it on its first lane (PR 647, update-branch at 23:37Z after a sibling merged) and every later lane was sequenced around it by hand. Nothing abcd prints at push or PR time names the condition, the remedy or the sequencing rule (one lane in the queue at a time when they share a file). Wanted: the launch or capture surface that opens a PR says the rule, and a verb or the keep-current script is reachable from the plugin surface, so an orchestrating agent does not learn it from a stalled queue.
- itd-93abcd Scaffolds a Release Gate That Works on the First Try
- itd-95Disembark Grounds A Lifeboat's Open Questions On A Repo's TODO And FIXME Markers
- itd-115A Ready PR Merges Without Ever Wedging BEHIND
- itd-2610110940216682Every change is checked in full once, on exactly what lands
- itd-2610141646469491A cheap watcher wakes an agent only when something needs action