fix(bin): canonicalize watcher lock owner paths - #1894
Open
moneyteamameen wants to merge 3 commits into
Open
Conversation
4 tasks
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 queue item fix-guard-path-casing (FM-GUARD-001): watcher health and lock ownership must compare canonical Firstmate home and watcher paths so macOS case-insensitive GitHub/github spellings identify the same healthy watcher. Preserve fail-closed PID and identity validation, exact per-home isolation, cross-home safety boundaries, absent final watcher-leaf and symlink/realpath owner behavior, and all existing watcher lifecycle semantics. Add focused regressions for case-differing paths, cross-home mismatch, wrong live PID, dead PID, symlink paths, and the existing absent-leaf contract. Limit changes to bin/fm-wake-lib.sh and its directly relevant tests. Preserve evidence that tests/fm-pi-watch-extension.test.sh has an unrelated timing flake in its TypeScript-only hung-successor fixture; do not weaken or skip relevant watcher, wake, lock, guard, shell, or CI validation. Push a feature branch, create a PR, drive CI green, and never merge.
What Changed
Risk Assessment
✅ Low: The correction is well bounded: restart cleanup now uses the shared canonical owner boundary, strict PID/identity validation and cross-home isolation remain intact, and redundant polling canonicalization was removed.
Testing
Baseline inspection confirmed the supplied target and changed-file set; focused watcher-lock, watch-arm, turn-end guard, and Claude auto-arm tests passed, and an evidence-producing case-insensitive CLI restart confirmed canonical ownership, safe stale-lock replacement, and persisted state end to end. The supplied unrelated TypeScript-only Pi hung-successor timing flake was not rerun in this targeted phase, and its test remains unchanged; broad CI remains owned by the outer pipeline.
Evidence: Case-alias CLI end-to-end transcript
watcher: started pid=70871 (beacon fresh); the stale lock was replaced while the unrelated live PID remained alive, and both lowercase owner paths resolved to their canonical counterparts.Evidence: Focused watcher-lock regressions
Evidence: Watch-arm lifecycle regressions
Evidence: Turn-end guard regressions
Evidence: Claude Stop auto-arm regressions
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed ✅
bin/fm-wake-lib.sh:136- The requirement to “Preserve … all existing watcher lifecycle semantics” remains unmet for--restart. Canonical ownership is confined to this identity-strict helper: with case-differing spellings and a reused/wrong live PID, it correctly returns false, butfm-watch-arm.shthen callsclear_stale_recorded_watcher_lock, whose raw home/path comparisons reject the alias. The stale lock remains, so the replacement watcher cannot start—unlike the existing same-spelling reused-PID recovery. The new wrong-PID test checks only health rejection. Fixing this durably requires approval to exceed “Limit changes to bin/fm-wake-lib.sh…” by adding a shared path-only owner matcher used by restart cleanup, plus an end-to-end regression.bin/fm-wake-lib.sh:159-fm_watcher_healthycanonicalizes home and watcher here, thenfm_watcher_lock_matches_pidimmediately canonicalizes both again. In the arm’s 0.2-second confirmation and 0.5-second attachment loops, this adds two redundantrealpathprocesses per iteration on a path whose MSYS fork cost is explicitly documented as significant. Pass the original arguments directly and let the matcher own canonicalization.🔧 Fix: Fix aliased watcher restart recovery
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
git status --short --branchandgit diff --stat --name-status 70aeba855527f7693082f6dd1bc731e334d0269f..5c9f4d0ff1502ffe3f1e1f1e1f18141c130cb79bbash tests/fm-watcher-lock.test.shbash tests/fm-watch-arm.test.shbash tests/fm-turnend-guard.test.shbash tests/fm-claude-stop-autoarm.test.shCase-insensitive APFS end-to-end check: seeded canonicalGitHub/FmHomelock metadata with an unrelated live PID and stale identity, then ranFM_HOME=.../github/fmhome .../github/firstmate/bin/fm-watch-arm.sh --restartVerified the CLI-reported watcher PID was live and persisted, the unrelated PID remained alive, andrealpathmatched both stored owner paths to their canonical home and watcherRecheckedgit status --short --branch, evidence-file integrity, and cleanup withkill -0 70814/kill -0 70871✅ **Document** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.