This repository was archived by the owner on Aug 25, 2026. It is now read-only.
fix: fleet-sync follows branch upstream on controlled forks - #89
Merged
Merged
Conversation
Prefer the local default branch's configured upstream (e.g. fork/main) as the sync base instead of hardcoding origin/<default>. Controlled-fork homes keep origin fetching the upstream owner while main tracks fork; comparing only to origin/main false-STUCK a delivery-current clone. Also fetch the delivery remote when it differs from origin.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Make fleet-sync follow controlled-fork delivery upstream so delivery-current clones stop false-STUCK against diverged origin/main
What Changed
bin/fm-fleet-sync.shto resolve each clone’s sync base from its configured default-branch upstream, refresh the selected remote and branch safely, and prune after refresh.fork/mainwhileorigin/maindiverges.Risk Assessment
✅ Low: The change is well-bounded and the latest fixes preserve the controlled-fork behavior while avoiding redundant origin fetches and force-updating delivery refs safely.
Testing
The focused suite, full behavior suite, and direct CLI scenario all completed successfully. The worktree remained clean, and CLI evidence was captured in the dedicated temporary evidence directory.
Evidence: Controlled-fork CLI transcript
--- delivery-current clone with diverged origin/main --- main=6321ccd fork/main=6321ccd origin/main=9bd3848 forked: already current --- same clone after delivery advance --- forked: synced 6321ccd..0d50709 main=0d50709 fork/main=0d50709 origin/main=9bd3848Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 3 issues found → auto-fixed (4) ✅
bin/fm-fleet-sync.sh:267- Required criterion: "Make fleet-sync follow controlled-fork delivery upstream so delivery-current clones stop false-STUCK against diverged origin/main." Contradicting hunk: line 267 accepts the configured upstream only when "$upstream^{commit}" is already cached; otherwise line 271 falls back to origin/<default>. A delivery-current clone with a missing fork/main tracking ref can therefore be judged against diverged origin/main again. Resolve and fetch the configured upstream before fallback, or confirm this fallback is intentional.bin/fm-fleet-sync.sh:332- If a cached non-origin tracking ref remains while its remote is missing, line 332 silently skips the delivery fetch, and later validation still accepts the stale BASE. This can report already-current or fast-forward from obsolete delivery state. Require the selected remote to exist and refresh successfully before accepting the cached ref.tests/fm-fleet-sync.test.sh:511- The controlled-fork test pre-fetches fork at line 511 and then checks an already-current clone. It never proves that fleet-sync refreshes a changed fork/main, so an implementation that omits or misroutes the new delivery fetch would still pass. Advance the delivery remote after setup, remove this pre-fetch, and assert the sync and resulting HEAD.🔧 Fix: Refresh fork upstream before fleet sync; focused tests pass
2 warnings still open:
bin/fm-fleet-sync.sh:343- If the branch has a stale or incomplete config (remote=forkbut no validmerge),resolve_sync_basefalls back toorigin/$DEFAULT, while this block still forces a fetch offorkand returnsskippedwhen it is unavailable. Keep the selected fetch remote consistent with the resolved BASE.bin/fm-fleet-sync.sh:351- The delivery remote is fetched afterprune_gone_branchesruns. Branches tracking that remote can therefore remain locally present for one extra sync cycle after deletion. Run gone-branch pruning after all selected remotes have been refreshed.🔧 Fix: Align fetch remote with resolved base; prune after refresh
4 warnings still open:
bin/fm-fleet-sync.sh:338-${BASE%%/*}cannot distinguish the remote from the branch when the configured upstream is local (remote=.withrelease/main) or when a remote name contains/. The script can fetch the wrong remote or skip a valid local upstream. Preserve the selected remote separately from BASE.bin/fm-fleet-sync.sh:347- A successful fetch only proves that the remote's configured refspec completed. If that refspec omits the configured merge branch, an oldfork/mainremains and line 364 accepts it as the sync base, allowing false-current or stale fast-forward decisions. Fetch the selected branch explicitly or verify the tracking ref was refreshed.bin/fm-fleet-sync.sh:347- Controlled-fork projects now perform two serial remote fetches, but bootstrap's default timeout remainsmax(20, 5 + 3 * origin-backed project count). A slow origin fetch can consume the budget before the delivery fetch completes, leaving the clone stale until a later run. Include delivery fetches in the timeout budget or enforce per-fetch limits.tests/fm-fleet-sync.test.sh:538- The controlled-fork test advances and removesfork/mainbefore its only sync call, so it proves ref refresh for a delivery-behind clone but not the primary delivery-current case wheremain == fork/mainwhileorigin/maindiverges. Add an initial sync assertion for that state before retaining the refresh scenario.🔧 Fix: Separate upstream refs, refresh branches, and budget bootstrap
2 warnings still open:
bin/fm-fleet-sync.sh:358- Every normal origin-tracked project now performs the initial origin fetch plus the secondary generic origin fetch and explicit branch fetch because fallback setsSYNC_REMOTE=origin. This triples network work and adds new failure points. Only run the secondary delivery-fetch sequence for non-origin remotes.bin/fm-fleet-sync.sh:376- The explicit delivery refspec lacks a leading+, so a force-pushed or rebased delivery branch can fail with a non-fast-forward remote-tracking update. Fleet sync then skips instead of refreshing the delivery base. Force-update the remote-tracking refspec safely.🔧 Fix: Avoid origin refetches and force-update delivery refs
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bash bin/fm-run-behavior-tests.shbash tests/fm-fleet-sync.test.shbash bin/fm-run-behavior-tests.shDirectbin/fm-fleet-sync.shcontrolled-fork scenario with divergedorigin/mainFinalgit status --porcelain=v1check✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.