fix: preserve watcher continuity across session replacement - #97
Merged
Merged
Conversation
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
Port upstream kunchenguid/firstmate PR kunchenguid#3498 (fix(pi): preserve watcher continuity across session replacement) into dnth/firstmate, adapting to fork divergence and preserving OMP behavior. For Pi, every owning same-process replacement through /new, /resume, /fork, or reload must automatically re-arm on replacement session_start without a model turn and carry any actionable watcher close whose delivery overlapped session_shutdown to the replacement generation exactly once; compaction is explicitly not the cause and must remain unchanged. Audit OMP so /new, /resume, /fork, and reload use session_switch rather than replacement session_shutdown, preserve automatic re-arm, and carry not-yet-consumed actionable delivery across the replacement; adapt the watcher-owned branch-settlement fallback so rejected branch handling returns delivery to main without losing the durable wake. Preserve terminal shutdown, stale-generation exclusion, singleton child/retry ownership, turn-end guard behavior, and all other supported harness/backend behavior. Add process-backed portable regressions, maintain the env-gated live guards, update the authoritative supervision and verification documentation, follow the shared-core one-owner rule, avoid unrelated upstream drift, and require bin/fm-lint.sh to pass. Accepted exclusion: the OMP 18.1.5 /new once-only session-start-nudge omission reproduces identically on pristine origin/main, is pre-existing, is documented separately, and remains outside this kunchenguid#3498 port.
Firstmate-Validation-Generation: 7e1cb4c65acbad488e04f7f1467ba932
What Changed
Risk Assessment
✅ Low: The reviewed changes satisfy the stated Pi/OMP replacement continuity behavior, preserve stale-generation and terminal-shutdown guards, and introduce no additional source-verifiable defect requiring action.
Testing
Ran the focused process-backed Pi watcher, OMP primary replacement, and OMP branch supervision suites; all targeted continuity behaviors passed and produced direct CLI evidence. Credentialed live E2E guards remained skipped because their opt-in environment variables were unset. The separate strict Pi typecheck is blocked by an unrelated existing fm-calm.ts incompatibility with the installed Pi package.
Evidence: Pi watcher continuity regression output
Evidence: OMP replacement and branch supervision output
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 1 issue found → auto-fixed (4) ✅
.omp/extensions/fm-primary-omp.ts:269- The required authoritative supervision documentation update is incomplete. The changed OMP handler now performs replacement shutdown and re-arm onsession_switch(.omp/extensions/fm-primary-omp.ts:269-274), butdocs/omp-supervision-branch.md:25and:40-42still state that no live re-arm runs during/new//resume//forkand thatsession_startis the sole arm boundary. This contradicts the required criterion to “update the authoritative supervision and verification documentation”; please reconcile the architecture document before merging.🔧 Fix: Reconciled OMP session-switch supervision documentation
1 warning still open:
.omp/extensions/fm-branch-supervision-omp.ts:942- This lifecycle comment is now obsolete: it sayssession_startis the sole clean-boundary transition and that nosession_switchhandling is needed, while the adapter now re-arms onsession_switchfor session replacement. Update the comment to match the implemented contract so maintainers do not follow an incorrect lifecycle model.🔧 Fix: Updated OMP lifecycle comment for session-switch re-arm
1 error still open:
bin/fm-primary-watch-core.ts:476- If replacement handoff persistence fails,stopSessionGenerationqueues an in-process fallback but then rethrows at line 476. The OMPsession_switchhandler awaits this promise before callingwatch.sessionStart()(lines 270-273), so a filesystem error leaves the replacement generation unarmed and can strand the watcher despite the queued fallback. Report the failure without aborting the replacement shutdown/start sequence, or otherwise ensuresessionStart()still runs after this handled fallback.🔧 Fix: Preserved watcher re-arm after handoff persistence failure
1 error still open:
bin/fm-primary-watch-core.ts:803- A failed actionable delivery can strand the wake indefinitely. InprocessPendingActionables, anysendFollowUp/branch-delivery error is caught at line 797 and only surfaced via a tokenless failure notice; the originalpendingremains undelivered, but thefinallyblock schedules cleanup only when some item is already markeddelivered(line 803), and no retry is scheduled. With a transient host delivery failure and no later watcher close or session replacement, the durable actionable wake is never retried, violating the documented replay/no-lost-wake invariant. Schedule anotherprocessPendingActionablesattempt while undelivered pending items remain (or otherwise retain a bounded retry path).🔧 Fix: Scheduled retries for undelivered actionable wakes
✅ Re-checked - no issues remain.
.pi/extensions/fm-calm.ts:402- The strict Pi typecheck test is blocked by an unrelated existing fm-calm.ts API mismatch with the installed Pi package: onTerminalInput now requires a handler returning TerminalInputHandler, while fm-calm.ts returns void. The changed watcher adapter itself was exercised successfully by the process-backed extension regressions.bash tests/fm-pi-watch-extension.test.shbash tests/fm-omp-primary.test.shbash tests/fm-omp-branch-supervision.test.shbash tests/fm-pi-primary-types.test.sh(fails on pre-existingfm-calm.tsTerminalInputHandler mismatch)bash tests/fm-omp-primary-live-e2e.test.sh(env-gated skip)bash tests/fm-omp-branch-live-e2e.test.sh(env-gated skip)Verifiedgit status --shortis clean after tests✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.