Repository navigation
Keep worktrees and PR-less branches on a fresh base #15938
Description
Activity
- addedarea: git-hygieneWave 0 · cluster Y — Git hygiene & stranded workWave 0 · cluster Y — Git hygiene & stranded work
on Sep 7, 2026 - added 10 commits that reference this issue
on Sep 9, 2026 github-actions commented
on Sep 11, 2026 on Sep 11, 2026 – with GitHub ActionsContributorMore actionsStatus against merged base (
24211c208, #16128). Four criteria met in code; AC4 is not met, and it cannot be met by waiting — leaving this open.Closes #15938does not fire on this base.AC1 — worktree creation branches from a freshly fetched
origin/Dev_new_gui— met.autobot-backend/services/task_workspace.py::56 _WORKSPACE_BASE_REF = os.environ.get("AUTOBOT_WORKSPACE_BASE_REF") or "origin/Dev_new_gui" :356 def _fetched_base_ref(root) -> fetches, then rev-parse --verify; an unresolvable ref RAISES :405 base_ref = _fetched_base_ref(root) :406 add_argv = ["git", "worktree", "add", "-b", branch, str(workspace_dir)] :407 if base_ref is not None: add_argv.append(base_ref)I checked the
Nonebranch because it looks like a fallback to HEAD. It is reachable only in a repository with no remotes at all, where HEAD is the only base that exists, and the docstring defends that case. A configured remote with the ref missing raises ("refusing to branch from the main tree's HEAD"), and a failinggit remotealso raises rather than being read as "no remotes".AC2 —
pr-preflight.shfails beyond the threshold, with the exact rebase command in the message — met.:50 MAX_BEHIND="${PREFLIGHT_MAX_BEHIND:-50}" fail "branch is $behind commits behind $BASE (limit $MAX_BEHIND), measured against $behind_basis" note "rebase before opening the PR: git fetch origin && git rebase $BASE"A non-numeric override fails rather than reading as a pass, and a failed fetch states that the count is a lower bound.
AC3 — root cause fixed in
auto-merge-base-into-parked-branches.yml, skip path observable — met in the file. Branches are sorted intoupdated / conflicted / current / skipped / pushfail / errored / unreachable, with::warning::lines for each non-success. The comment at:166names #15938 as the reason the--no-rebasewas removed.rescued/*is excluded by policy (EXCLUDED_PREFIXES, rationale at:32).AC5 — no mechanism added that mutates or removes a branch — met. The merger predates this work: added in
7952df898on 2026-08-30 (#15316). #16128 repaired an existing mechanism, and the workspace and preflight changes create and report; neither mutates.AC4 — re-run the inventory: no PR-less pushed branch more than 50 behind — not met. Measured today:
PR-less remote branches 42 more than 50 behind 30 rescued/* (excluded by policy) 19 ordinary work branches 11 worst: issue-13719 884, research-provider-quota-headroom 437issue-13719— the root-cause case AC3 names, at 781 behind when this was filed — is now 884 behind. The fix is not the reason: the fixed merger has not run, and on its schedule it never will. Scheduled workflows execute the default branch's copy, the default branch ismain, andmainis 310 commits behind with a merger that mentions #15938 zero times. Every run from 9–11 September reportshead=b94f51a4c3,main's tip. Detail and the current count are on #15318, which already tracks this.So AC4 needs one of two things, and neither is code in this repository:
mainsynced fromDev_new_gui, or the default-branch decision on decision(repo): default branch and Actions PR permission — two issues, no code in either #15834 / decision: the default branch is main, so Dependabot alerts, security-update PRs and scheduled workflows all read a branch no PR targets #16221, followed by a run of the fixed merger and a fresh inventory; or- a
workflow_dispatchof the merger onDev_new_gui's ref. That would demonstrate the fix but would not keep branches current, since the schedule would still run the old copy.
Two further notes for whoever closes this. AC4 has no stated exception, but the 19
rescued/*branches are excluded from the merger by documented policy. Closing it honestly means either amending AC4 to exclude them or accepting that they will never meet it.Status against base
a12b4bf79d, after #16128 (squash24211c208d): 3 of 5 criteria met, so this stays open. AC4 is unmet and AC5 needs an owner decision.AC Status Evidence 1. Worktree creation branches from a freshly fetched base met, ticked autobot-backend/services/task_workspace.py:388:_fetched_base_ref(:356) runsfetch --quiet origin Dev_new_gui;:405calls it and:407-408appends the result as theworktree add -bstart point. The base ref isorigin/Dev_new_gui(:56, envAUTOBOT_WORKSPACE_BASE_REF). If offline, it falls back to the last-known base with a warning (:389-392); if the ref can't be resolved, it errors (:396).2. pr-preflight.shfails behind the threshold, with the rebase commandmet, ticked scripts/pr-preflight.sh:50MAX_BEHIND="${PREFLIGHT_MAX_BEHIND:-50}";:228-229fail with "branch is N commits behind … (limit …)" plus the notegit fetch origin && git rebase $BASE; a non-numeric override fails (:217-220) instead of passing.3. Root cause for issue-13719fixed, and the skip path observablemet, ticked Root cause (#16128): the workflow ran git merge --no-rebase, agit pullflag thatgit mergerejects, so it never merged anything. Observable:summary()writes to$GITHUB_STEP_SUMMARY(:215), each branch gets an outcome line, there are annotations at:150,161,191,206,269,286, and an unexplained failure exits 1 (:271). The latest scheduled run, 34617902513 (2026-09-11 18:44 Riga), reportsissue-13719 is 894 behind … CONFLICTS — skipped. The merger runs now, and the reason it can't catch this branch up is visible.4. Inventory: no PR-less pushed branch more than 50 behind not met Re-run just now: 39 PR-less remote branches, 30 of them more than 50 behind. 19 are rescued/*, which the workflow excludes by design (header:32-33,EXCLUDED_PREFIXES:97). 11 are work branches:feat/gantt-timeline-view2783,issue-13719894,research-provider-quota-headroom447,issue-14100-unit-and-docs273,issue-13539-release-flip231,issue-15650-slm-shell-publish173,issue-15882-stale-base-rule126,issue-15868-ratchet-format121,issue-15909-extract-model-pricing120,issue-16025-gate-blindspots77,issue-16040-gate-state75. The latest run showsupdated=0 current=1 conflicted=19: every stale work branch conflicts, so no automated path brings them under 50. Each is unfinished work its owner has to land or record.5. No mechanism added that mutates or removes a branch left unticked, needs a decision #16128 added no new mechanism. It repaired the existing parked-branch merger, which pushes merge commits without forcing ( :191) and removes nothing. Whether a repaired merger that now actually changes branches meets "guard and report only" is the author's call. The same goes for whetherrescued/*counts toward AC4.What's left: a decision on AC5 and on the
rescued/*scope, plus owners for the 11 conflicted work branches.Stale-issue sweep (never auto-closed — Dev_new_gui wasn't GitHub's default branch at merge time). Verified against current
origin/main; leaving open.MET:
task_workspace.py:356_fetched_base_ref()used asbase_refforgit worktree add(:405-408);pr-preflight.sh'sMAX_BEHIND="${PREFLIGHT_MAX_BEHIND:-50}"(:50) with a rebase-failure message; the invalid--no-rebaseflag removed fromauto-merge-base-into-parked-branches.yml, non-conflict failures now bucketed aserroredand fail the job.NOT MET: AC4 — the delivering PR (#16128) states this itself, having re-run the inventory post-merge: "no PR-less pushed branch more than 50 commits behind. Measured now: 258 PR-less pushed branches, 206 of them more than 50 behind (worst: 2736)." This is a live-state fact the diff can't retroactively fix — the backlog needs the fixed workflow's 6-hourly cron to actually run and drain it over time.
Triage: both branches dead (both on the revival-hazard trap list); 3 of 5 ACs done, 2 need a fresh measurement
Both candidates (
issue-15938-fresh-base,rescue-15938-parked-branch-merger) are ~1870/unmeasured files off currentorigin/mainand both are flagged on the branch-freeze scan's revival-hazard trap list (predate a later fix elsewhere) -- not reviving either.issue-15938-fresh-base's own staleness is a small irony given its name.Confirmed done:
~/.claude/scripts/branch-for-issue:30branches frombase=$(git rev-parse origin/main)-- freshly resolved at creation time, matching AC1's own citation.scripts/pr-preflight.sh(#15933, already verdicted superseded/done elsewhere in this sweep) and.github/workflows/auto-merge-base-into-parked-branches.yml(#15306, also already verdicted in this sweep) both exist and match AC2/AC3's descriptions.Not verifying the remaining 2 ACs myself -- "re-run the inventory: no PR-less pushed branch more than 50 commits behind" needs a fresh, repo-wide branch-behind-count sweep, which is exactly the kind of large measurement already running in parallel as part of today's branch-freeze effort (931/710/150/560 population counts). Re-deriving a second, smaller version of that same sweep here would duplicate work rather than add to it. Given #15306's own 2026-08-30 measurement found 73 of 85 branches could not even merge cleanly (conflicts, not just staleness), I'd expect this AC to still be failing in practice even though the mechanism exists -- stated as an expectation, not a measurement, since I haven't run the count.
Not recommending closure -- 2 real ACs outstanding, pending the inventory re-run.
- addedneeds-decisionBlocked on an owner decision; options and a recommendation are on the issueBlocked on an owner decision; options and a recommendation are on the issue
on Oct 3, 2026 Closure check (2026-10-03): 4 of 5. The fifth contradicts the third and needs a ruling
Criterion 4: inventory re-run. Met. From the server (
git ls-remote --heads origin), there are 10 heads. Excludingmain,releaseandDev_new_guileaves 7, of which 5 are heads of open PRs. The 2 PR-less branches are each 1 commit behindorigin/main(1edec3064c):issue-16516-deliberate-hang(a parked scratch branch) andautomation/test-durations(the bot's refresh branch). 0 PR-less branches are more than 50 behind.Criterion 5: "No mechanism added that mutates or removes a branch — guard and report only." Not ticked, because it conflicts with criterion 3.
- Criterion 3 (ticked) required fixing
auto-merge-base-into-parked-branches.yml, and PR fix(ci): the parked-branch merger has never merged anything (#15938) #16128 did: "the parked-branch merger has never merged anything (Keep worktrees and PR-less branches on a fresh base #15938)". That workflow mutates PR-less branches: every 6 hours it mergesmaininto each behind branch and pushes. Observed today:github-actions[bot]mergedmainintoissue-16516-deliberate-hangtwice (5f227743d1,6c08dbd66e). - The workflow itself was added by Branches and worktrees drift from base unchecked: 0 of 86 worktrees current, 73 no longer merge #15306, not by this issue. So under a literal reading of "added", this issue added no mutating mechanism, and criterion 5 holds. Under the criterion's evident intent ("guard and report only"), this issue's own fix made a mutating mechanism actually mutate, and criterion 5 fails.
- Criterion 4 is met because of that mechanism.
Recommendation: read criterion 5 as "no new mutating mechanism", which is consistent with criterion 3 requiring the merger fix. Under that reading it is met and this issue closes. Labelled
needs-decision.Side note worth a line in
CLAUDE.md: it currently says "the auto-update bot only refreshes branches that already have a PR". That is true ofauto-update-pr-branches.yml, but PR-less branches are refreshed too, by this merger, which a session pushing a parked branch needs to know (its next push will be non-fast-forward).- Criterion 3 (ticked) required fixing
Stated plainly, so the next reader does not resolve it the other way: criteria 3 and 5 of this issue contradict each other as written. Criterion 3 (ticked) required repairing the parked-branch merger, and #16128 made it mutate PR-less branches. Criterion 5 forbids any mechanism that mutates a branch. Both cannot hold. The repair proposed above is to read 5 as "no new mutating mechanism". Do not satisfy criterion 5 by reverting #16128: criterion 4's measurement (0 PR-less branches more than 50 behind) depends on it.
Problem
Worktrees drift off the base and nothing catches it until push time. Read-only inventory taken
against current
origin/Dev_new_gui:issue-13140-slmapibaseissue-13719research-provider-quota-headroomissue-14529-refitissue-15036-landing-evidenceissue-15794-agent-org-gateEvery other worktree is 0 behind — those are the ones with an open PR, kept fresh by
auto-update-pr-branches.yml. The pattern is exact: freshness today is a side effect of having aPR. Before the first push there is no mechanism at all, and
issue-13719was committed to 22hours ago while 781 commits behind.
This is expensive in the direction that has no feedback: a stale base makes "is this already done?"
answer no when the truth is yes, so the session builds work that already exists, and reviving
such a branch can regress newer code.
Two distinct gaps
them, so no workflow can ever fix them. This half needs a local guard.
issue-13719is pushed, PR-less, and 781 commits behind — precisely the caseauto-merge-base-into-parked-branches.yml(cron0 */6) claims to cover, per its own commentthat PR-less branches are its reason to exist. It did not. Root-cause why before changing
anything else; the workflow may be silently skipping branches it should touch.
Scope
Local guard (gap 1) — the branch is the record, so the check belongs where work starts and where
it leaves:
origin/Dev_new_gui, never from a local refthat may itself be stale.
scripts/pr-preflight.sh(Local preflight must cover the 10 required checks #15933) fails when the branch is behind base by more than a threshold,so a stale branch cannot reach a PR.
call on every commit.
Server-side (gap 2) — fix
auto-merge-base-into-parked-branches.ymlso PR-less pushed branchesare actually kept current, and make its skips visible rather than silent.
Constraints:
Nothing here rebases, resets, or removes a branch a session may be using.
push; it never discards.
Acceptance criteria
origin/Dev_new_gui— cite the script and linescripts/pr-preflight.shfails on a branch behind base beyond the threshold, with the exact rebase command in the messageissue-13719(pushed, PR-less, 781 behind) identified and fixed inauto-merge-base-into-parked-branches.yml, with the skip path made observableImplementation Order
Wave: 2
Depends on: #15933
Umbrella: #15932