fix(watch): coalesce delayed wake prompts and suppress obsolete notifications - #1164
Closed
pokorny344 wants to merge 7 commits into
Closed
fix(watch): coalesce delayed wake prompts and suppress obsolete notifications#1164pokorny344 wants to merge 7 commits into
pokorny344 wants to merge 7 commits into
Conversation
added 7 commits
July 27, 2026 16:32
# Conflicts: # .agents/skills/harness-adapters/SKILL.md
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
Deliver the already captain-approved delayed obsolete-notification correction upstream without losing its five exact local commit identities, integrate the latest upstream Firstmate changes through a merge commit, add the captain-requested .idea/ Git ignore, preserve every supervision and safety contract, and open a replacement upstream PR that supersedes closed PR 1141 and requests merge-commit landing so the captain's local main can return to normal updates.
What Changed
.pi/extensions/fm-primary-pi-watch.ts) and OpenCode plugin (.opencode/plugins/fm-primary-watch-arm.js) now revalidate actionable wake prompts against the durable queue before delivery: prompts for reasons already consumed by a completed drain are suppressed, delivery is deferred (with bounded retries) while the wake-queue mutation lock is held, and later watcher closes coalesce behind a pending handling turn instead of scheduling extra host prompts. The latch is released at Piagent_settled/ OpenCodesession.idle(orsession.deleted/session-scopedsession.error), only the latching send epoch can release it on failure, and a rejected send restores undelivered reasons by merging them without clobbering newer ones.tests/fm-pi-watch-extension.test.sh(real durable queue and drain script, real Pi 0.82.1 TUI and OpenCode 1.16.2 TUI runs, queue-lock deferral, stale-send suppression, send-epoch latch guarding, Pi rejection handling), and updatesdocs/watcher-continuity.mdplus supervision verification evidence to document the new ordering and release points..idea/to.gitignoreso JetBrains project directories stay untracked.Risk Assessment
✅ Low: All source-verifiable intent criteria are met (five exact captain-approved commit identities preserved and matching refs/pull/1141/head, true merge commit of origin/main with a clean conflict resolution, .idea/ gitignore added, no supervision contract weakened), the adapter state machines are correct against the verified wake-queue and lock semantics, no bin/ scripts changed, and the change carries exhaustive regression coverage including real-TUI evidence, leaving only informational observations.
Testing
Exercised the delivery shape with git-level proofs (five preserved commit SHAs matching closed PR 1141's head, true merge commit of current upstream main, lossless conflict resolution verified via merge-tree and stage diffs, live check-ignore demo of the .idea/ entry) and ran the repo's prescribed focus path on the merged tree: the 40-assertion fm-pi-watch-extension suite plus three static supervision-contract guard tests, all passing; no screenshot artifacts because this change has no rendered UI surface (git history, bash/TS watcher adapters, and docs), so CLI/git transcripts are the end-user-visible evidence. Opening the replacement PR itself belongs to the outer executor's PR phase.
Evidence: Delivery-shape evidence: commit identities vs PR 1141, merge parents vs upstream main, merge fidelity, .idea ignore demo
Evidence: fm-pi-watch-extension suite transcript (40 ok, exit=0) via bin/fm-test-run.sh
Evidence: Supervision-contract guard tests transcript (3 suites, 0 failed)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
.agents/skills/afk/SKILL.md- branch carries 5 commit(s) that exist on your local main branch but were never pushed to origin/main; rebasing would bundle this unrelated work (38 file(s)) into the PR:Push main to origin, or rebase your branch onto origin/main, before gating.
.pi/extensions/fm-primary-pi-watch.ts:515- The coalescing latch is released at the harness settle/idle event (Piagent_settled, OpenCodesession.idle) that can precede the injected handling turn when the latching send happened mid-turn. A watcher close arriving in that window schedules a second prompt whose later drain finds an empty queue (the first handling turn drains both records). This is benign - the second prompt is queue-revalidated at send time and the drain is idempotent - and it matches the documented release points in docs/watcher-continuity.md, but debuggers observing an occasional extra wake prompt with an empty drain should know it is a designed tradeoff, not a regression of the fix..opencode/plugins/fm-primary-watch-arm.js:239- The ~100-line flush/coalescing state machine (queuedWakeSnapshot, scheduleQueueLockRetry, flushWakePrompt, requestActionableWake, surfaceFailure) is duplicated nearly verbatim between the OpenCode plugin (JS) and the Pi extension (TS). This follows the repo's established per-harness self-containment convention (fm-operational-input is likewise duplicated per adapter), so no shared abstraction is demanded - but any future fix to this logic must be mirrored in both files, as this branch itself had to do across its five commits. The docs and paired regression tests already bind the two implementations together.✅ **Test** - passed
✅ No issues found.
git log --graph/--format='%H %P'over b29621b..14d2eb0 - confirmed the five exact local commits, the two-parent merge dd4ce67 (57e2c36 + b29621b), and the .idea ignore commit 14d2eb0git ls-remote origin refs/pull/1141/head refs/heads/main- proved PR 1141 head == 57e2c36 (tip of the five preserved commits) and remote main == the merge's upstream parentgh-axi pr view 1141- confirmed PR 1141 is closed and unmerged (superseded by this branch)git merge-tree --write-tree 57e2c36 b29621bcompared against dd4ce67's tree - only the genuine SKILL.md conflict differs, and stage-by-stage diffs proved the hand resolution keeps upstream's pi-signed changes and the branch's watcher-continuity line with no lost contentbin/fm-test-run.sh tests/fm-pi-watch-extension.test.sh- 40/40 assertions passed covering Pi and OpenCode wake coalescing, queue-lock deferral, stale-send suppression, send-epoch latch guarding, Pi rejection handling, session-lock ownership, and turn-end guard coordinationbin/fm-test-run.sh tests/fm-captain-translation-contract.test.sh tests/fm-documentation-audiences.test.sh tests/fm-instruction-owners.test.sh- all passed, guarding the hand-merged SKILL.md and changed docs against supervision-contract regressionsmanualgit check-ignore -v .idea/workspace.xml- matched by .gitignore:6:.idea/, and git status stayed clean with an untracked .idea directory present✅ **Document** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.