fix(bin): keep fleet clones cleanly synced - #18
Merged
Merged
Conversation
This was referenced Aug 4, 2026
|
Coverage note after merging current main: The current PR gate is green, but the replacement under-five-minute workflow does not execute the Herdr or portable test families. The Herdr evidence for this branch is the earlier run on head |
vipentti
pushed a commit
to vipentti/firstmate
that referenced
this pull request
Aug 5, 2026
* Add fleet default-branch sync * no-mistakes(review): Skip local-only projects during fleet sync * no-mistakes(review): Fix bootstrap sync timeout cleanup * no-mistakes(test): Suppress local-only bootstrap sync noise * no-mistakes(document): Synchronize fleet-sync documentation
This was referenced Aug 11, 2026
NewAiCoder
added a commit
to NewAiCoder/firstmate
that referenced
this pull request
Sep 26, 2026
… grace (kunchenguid#18) * fix(bin): derive the away-mode beacon grace from the poll cadence fm-turnend-guard.sh's away-mode branch required the watcher beacon to be fresh within the flat FM_GUARD_GRACE default (300s), but the daemon starts a fresh one-shot watcher only after it finishes handling the previous wake, and that handling can legitimately outrun a fixed 300s window under load (a slow registered check, a busy supervisor pane) with the daemon perfectly healthy throughout. That misread a live, correctly-cycling daemon as down and blocked the turn. Add fm_poll_derived_grace, the single owner of the existing max(300, FM_POLL + 60) formula two other callers already use, and have the away-mode branch derive its beacon grace from it instead of the flat default. A dead daemon pid or a beacon older than that grace still blocks, so a genuinely lapsed away mode still alarms; every other check on this page is unchanged. * no-mistakes(review): Dedup guard-grace formula to fm_poll_derived_grace in watch and autoarm * no-mistakes(test): summary: fix PATH-collision test hermeticity for node/orca missing-tool simulations * no-mistakes(test): fix(test): accept systemd-user subreaper as orphan target, not just ppid 1 * no-mistakes(document): docs: note away-mode poll-derived-grace tests in coverage list * no-mistakes(lint): fix(test): use read -ra to fix SC2206 word-splitting warning * no-mistakes(ci): Root cause: tests/fm-tool-update-check.test.sh declared a plain string variable named `tools` (built via `local ... tools=` then `tools="$tools,..."`) in two test functions. tests/lib.sh (sourced by the test file) independently declares a local array `local tools=("$@")` in fm_test_base_path_sans. ShellCheck's --external-sources cross-file analysis (used by fm-lint.sh) conflates the two same-named locals across files and flags the string usage as SC2178 (var used as array but assigned a string) and SC2128 (expanding an array without an index). Fix: renamed the string variable in both affected test functions (test_an_overlong_report_says_it_was_cut and test_a_finding_past_the_cut_is_still_reported) from `tools` to `tools_json`, eliminating the name collision. No behavior change. Verified: `shellcheck --shell=bash -x tests/fm-tool-update-check.test.sh` now exits 0 with zero warnings (previously reproduced SC2178/SC2128 exactly as in CI). Ran the full test file directly (`bash tests/fm-tool-update-check.test.sh`) — all 37 tests pass, including the two touched by the rename. The other lint-log lines (systemd-run "Killed" during memory-bounded shellcheck runs, and the external-sources fallback retries) are pre-existing infra behavior of fm-lint.sh's OOM-bounded scanning and retry fallback — they resolved themselves within the same run (logged as "retried without it and finished cleanly") and are not caused by this change; only the SC2178/SC2128 warnings caused the actual exit code 1 --------- Co-authored-by: NewAiCoder <170579485+NewAiCoder@users.noreply.github.com>
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Fix firstmate's pooled project clones drifting behind their remote defaults by adding a guarded fleet-sync helper that fetches origin and clean-fast-forwards each clone's checked-out default branch only when safe. The helper must skip local-only/no-origin projects, dirty clones, clones not on default, and diverged/non-fast-forward cases with concise one-line reasons, never force, stash, merge, or touch treehouse worktrees, and continue best-effort across all repos. Bootstrap should run the fleet refresh best-effort and stay quiet unless a repo could not sync, and successful PR-based teardown should refresh that project's clone after merge confirmation. Documentation in AGENTS.md must record the narrow write exception and bootstrap/teardown behavior, with CLAUDE.md tracking through the symlink; README should stay consistent with the toolbelt.
What Changed
bin/fm-fleet-sync.shto fetchoriginand clean-fast-forward checked-out default branches only when safe, skipping local-only, no-origin, dirty, non-default, and diverged clones with concise reasons.AGENTS.mdandREADME.mdto document the narrow fleet-sync write exception and the new bootstrap/teardown refresh behavior.Risk Assessment
✅ Low: The change is narrowly scoped to guarded clone refresh behavior, with safety checks for local-only, dirty, non-default, and non-fast-forward cases and no material review findings.
Testing
Exercised the user-facing shell workflow with real git repositories: the helper fast-forwarded only a clean default-branch clone, skipped dirty/non-default/diverged/local-only/no-origin cases safely, bootstrap suppressed expected local-only/no-origin noise while surfacing real skipped syncs, teardown refreshed the project clone after a simulated merge, and the worktree was clean afterward.
Evidence: Fleet sync and bootstrap CLI transcript
Showssync-safe: synced 98b7d1b..73e2118, unsafe clones skipped with concise reasons, and bootstrap emitting only dirty/diverged/non-defaultFLEET_SYNC:lines while suppressing local-only/no-origin skips.Evidence: Teardown refresh CLI transcript
Showsteardown-sync: synced 468a96e..4b26696andteardown refreshed project to origin: yesafter a simulated PR merge.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed (2) ✅
bin/fm-fleet-sync.sh:59-fm-fleet-sync.shonly skips projects without anoriginremote and never checksdata/projects.mdforlocal-onlymode. A project registered aslocal-onlybut still carrying anoriginremote would be fetched and potentially fast-forwarded, violating the intended local-only/no-remote write boundary; skip mode=local-onlybefore fetching or merging.🔧 Fix: Skip local-only projects during fleet sync
1 warning still open:
bin/fm-bootstrap.sh:30- The bootstrap timeout only kills the wrapper subshell, not thefm-fleet-sync.shprocess it launched, so a slow fetch/sync can continue fast-forwarding project clones after bootstrap has reportedFLEET_SYNC: fleet: skipped: bootstrap refresh timed outand deleted its temp files. Run the sync process in a killable process group or avoid claiming the refresh was stopped until the actual sync process has exited.🔧 Fix: Fix bootstrap sync timeout cleanup
✅ Re-checked - no issues remain.
🔧 **Test** - 1 issue found → auto-fixed ✅
bin/fm-bootstrap.sh:43- Bootstrap reports a registered local-only project asFLEET_SYNC: ... skipped: local-only project, even though local-only projects are expected to have no remote and the intended behavior says bootstrap should stay quiet for expected skips unless a repo could not sync.bin/fm-fleet-sync.sh <fixture-clone>against throwaway Git repos covering clean fast-forward, already-current, non-default branch, dirty working tree, diverged local branch, and no-origin repositoryFM_FLEET_SYNC_BOOTSTRAP_TIMEOUT=10 bin/fm-bootstrap.shwith a temporary registered[local-only]project underprojects/anddata/projects.mdgit status --shortafter cleanup to verify no working-tree artifacts remained🔧 Fix: Suppress local-only bootstrap sync noise
✅ Re-checked - no issues remain.
Inspected the target diff from363fa89f80a5e48147b15764e0ebcf1fe9c368ce...d7b8cd37c3b585fd9b881b8edc17da9954eb187cto identify the intended behavior and changed scripts/docs.Ran an end-to-end CLI harness that created real temporary git remotes/clones, driftedorigin/main, and executedbin/fm-fleet-sync.shacross safe, dirty, non-default-branch, diverged, local-only, and no-origin project clones.RanFM_FLEET_SYNC_BOOTSTRAP_TIMEOUT=20 bin/fm-bootstrap.shwith temporary registered projects and filtered its user-visibleFLEET_SYNC:output to verify expected local-only/no-origin skips stay quiet while unsafe skipped syncs are surfaced.Ranbin/fm-teardown.sh teardown-syncwith temporary git repos plus stubbedtreehouseandtmuxcommands to verify a completed PR-style teardown invokesfm-fleet-sync.shand fast-forwards the project clone after the simulated merge.Rangit status --shortafter cleanup to verify transient worktree test projects/state were removed.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.