Skip to content

fix: preserve watcher continuity across session replacement - #97

Merged
dnth merged 6 commits into
mainfrom
fm/port-3498-omp-pi-watcher-continuity
Sep 3, 2026
Merged

dnth merged 6 commits into
mainfrom
fm/port-3498-omp-pi-watcher-continuity

Conversation

@dnth

@dnth dnth commented Sep 3, 2026

Copy link
Copy Markdown
Owner

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

  • Reworked the shared primary watcher core to preserve continuity across owning session replacement, including automatic re-arm and exactly-once handoff of actionable shutdown-overlap deliveries.
  • Updated Pi and OMP integrations and OMP branch dispatch to retain durable wakes across replacement sessions while preserving generation, ownership, shutdown, and turn-end safeguards.
  • Added process-backed OMP/Pi regression coverage and refreshed supervision, watcher-continuity, and verification documentation.

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
bash tests/fm-pi-watch-extension.test.sh
ok - Pi session transitions auto-arm through a generation owner across /new /resume /fork/reload, stale callbacks, and quit
ok - Pi session replacement auto-arms and carries its in-flight actionable close
ok - Pi factory re-bind without shutdown retires the prior generation and exit fallback stays singular
Evidence: OMP replacement and branch supervision output
bash tests/fm-omp-primary.test.sh
ok - OMP /new /resume /fork and reload session_switch paths auto-arm and carry an in-flight actionable close
bash tests/fm-omp-branch-supervision.test.sh
ok - OMP extension load establishes the main supervision actor context
- Outcome: ⚠️ 1 warning across 1 run (2m29s)

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 on session_switch (.omp/extensions/fm-primary-omp.ts:269-274), but docs/omp-supervision-branch.md:25 and :40-42 still state that no live re-arm runs during /new//resume//fork and that session_start is 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 says session_start is the sole clean-boundary transition and that no session_switch handling is needed, while the adapter now re-arms on session_switch for 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, stopSessionGeneration queues an in-process fallback but then rethrows at line 476. The OMP session_switch handler awaits this promise before calling watch.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 ensure sessionStart() 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. In processPendingActionables, any sendFollowUp/branch-delivery error is caught at line 797 and only surfaced via a tokenless failure notice; the original pending remains undelivered, but the finally block schedules cleanup only when some item is already marked delivered (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 another processPendingActionables attempt while undelivered pending items remain (or otherwise retain a bounded retry path).

🔧 Fix: Scheduled retries for undelivered actionable wakes
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 warning
  • ⚠️ .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.sh
  • bash tests/fm-omp-primary.test.sh
  • bash tests/fm-omp-branch-supervision.test.sh
  • bash tests/fm-pi-primary-types.test.sh (fails on pre-existing fm-calm.ts TerminalInputHandler 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)
  • Verified git status --short is clean after tests
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@dnth
dnth merged commit f0ec61a into main Sep 3, 2026
15 checks passed
@dnth
dnth deleted the fm/port-3498-omp-pi-watcher-continuity branch September 3, 2026 23:35
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