Skip to content

fix(fleet): 24 of the 25 "stranded" locations were merged PRs - #40

Merged
github-actions[bot] merged 1 commit into
masterfrom
fix/stranded-merged-branches
Aug 26, 2026
Merged

fix(fleet): 24 of the 25 "stranded" locations were merged PRs#40
github-actions[bot] merged 1 commit into
masterfrom
fix/stranded-merged-branches

Conversation

@catomean

Copy link
Copy Markdown
Collaborator

fleet-stranded reported 25 stranded locations, 26 unpushed commits, oldest 25 days. I checked all 24 pruned-branch cases against GitHub: gh pr list --state all returns MERGED for every one.

Mechanism

The fleet's happy path is the bug trigger:

  1. agent branches in a worktree, pushes, opens a PR
  2. PR squash-merges → GitHub deletes the remote branch
  3. a later fetch --prune drops the tracking ref
  4. the local branch keeps branch.<n>.merge pointing at a ref that no longer resolves

rev-parse @{u} fails on step 4, so the old code took the same branch as never pushed and fell through to origin/main — where the pre-squash commit is unreachable by construction, since main got a different sha with the same content. The count could never reach zero. Not a stale number, a permanent one.

Fix

upstream GONEupstream ABSENT. The first is proof the branch did leave the machine, which is exactly what puts it out of scope for a guard whose job is finding work GitHub cannot see. Read the config with for-each-ref, then check whether the tracking ref resolves.

Tests

Three added, including the must-still-fire half:

  • pushed-then-deleted → 0 unpushed (reverting the fix turns this red: got 1)
  • never had an upstream → still counts
  • ahead of a live upstream → measured against the upstream, not origin/main

24 passed, 0 failed.

Result

before after
locations 25 6
unpushed commits 26 1

Same class as the four gates fixed yesterday: judging state that does not belong to the commit being checked.

🤖 Generated with Claude Code

The guard shipped yesterday reported 25 stranded locations and 26 unpushed
commits, oldest 25 days. `gh pr list --state all` says MERGED for 24 of them.
Every single one.

The mechanism is the fleet's own happy path. An agent branches in a worktree,
pushes, opens a PR, it squash-merges, GitHub deletes the remote branch, and a
later `fetch --prune` drops the tracking ref. What survives is a local branch
whose `branch.<n>.merge` is still configured and no longer resolves.

`rev-parse @{u}` fails on that, so the old code took the same path as a branch
that was never pushed at all and fell through to origin/main — where the
pre-squash commit is unreachable by construction, because main received
different sha carrying the same content. The count could therefore never reach
zero. It was not a stale number; it was a permanent one.

Upstream GONE is the opposite fact from upstream ABSENT: it is proof the branch
DID leave the machine, which is precisely what puts it out of scope for a guard
whose stated job is finding work GitHub cannot see. So read the config with
for-each-ref and check whether the tracking ref resolves, instead of asking one
question that both states answer the same way.

Three tests pin it, including the must-still-fire half — never-pushed work and
work ahead of a live upstream both still count. Reverting the fix turns the
first of them red.

Fleet after: 6 locations, 1 unpushed commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions
github-actions Bot merged commit 0c2ce25 into master Aug 26, 2026
1 check passed
@github-actions
github-actions Bot deleted the fix/stranded-merged-branches branch August 26, 2026 00:24
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