Skip to content

fix: make Pi primary watcher away-mode aware and retire watcher markers on teardown - #14

Open
BohnBawerick wants to merge 5 commits into
mainfrom
fm/fm-pi-watch-afk-double-presentation
Open

fix: make Pi primary watcher away-mode aware and retire watcher markers on teardown#14
BohnBawerick wants to merge 5 commits into
mainfrom
fm/fm-pi-watch-afk-double-presentation

Conversation

@BohnBawerick

Copy link
Copy Markdown
Owner

Intent

Make the Pi primary watcher extension away-mode aware so the same wake is never presented twice while state/.afk exists, and retire window-keyed and task-keyed watcher internal markers during cleanup in bin/fm-teardown.sh alongside the status-presentation row so a torn-down task's pane can no longer produce stale wakes. Provide test coverage for away-mode wake suppression and marker retirement.

What Changed

  • Added isAfkActive() checks in .pi/extensions/fm-primary-pi-watch.ts to suppress wake message delivery, arm process spawning, actionable close restoration, and continuity retries while state/.afk is active.
  • Implemented fm_wake_retire_task_markers in bin/fm-wake-lib.sh and called it during task teardown in bin/fm-teardown.sh to clean up task-keyed and window-keyed watcher internal markers.
  • Updated supervision and continuity documentation in docs/ and added regression tests in tests/fm-pi-watch-extension.test.sh and tests/fm-teardown.test.sh.

Risk Assessment

✅ Low: The change cleanly implements away-mode awareness in the Pi watcher extension and marker retirement during task teardown with thorough behavioral tests.

Testing

Executed targeted automated test suites for the Pi watcher extension, task teardown, away-mode lifecycle, and wake triage, followed by end-to-end evidence captures demonstrating away-mode wake suppression and task marker retirement; all checks passed.

Evidence: Pi watch extension away-mode wake suppression and stand-down log

Source: Pi watch extension away-mode wake suppression and stand-down log

Demonstrates Pi primary watcher extension checking state/.afk: startArm stands down with away-mode guidance, wake delivery via sendUserMessage is suppressed during away mode, and normal wake delivery resumes after away mode is cleared.

===============================================================================
DEMONSTRATION: Pi Primary Watcher Extension Away-Mode (state/.afk) Awareness
===============================================================================

>>> Phase 1: Arming request while away mode (state/.afk) is ACTIVE
state/.afk created. Calling fm_watch_arm_pi tool...
Result ok: true
Result message: watcher: away mode active - supervise daemon owns watcher supervision
Total wake prompts delivered into Pi session: 0
Verdict: Extension stood down without launching an arm process.

>>> Phase 2: Arming request when away mode is INACTIVE (normal mode)
state/.afk removed. Calling fm_watch_arm_pi tool...
Result ok: true
Result message: watcher: started Pi extension arm child 1; future ordinary re-arms are automatic; call fm_watch_arm_pi again only after a later notification says the cycle is missing, failed, or unhealthy
Arm child 1 is running in background.

>>> Phase 3: Away mode activated while arm child running -> actionable wake occurs
Writing state/.afk...
Arm child finishes with actionable wake (signal: task-1.status)...
Total wake prompts delivered into Pi session during AFK: 0
Verdict: Wake delivery and successor arm restart were BOTH suppressed by away mode.

>>> Phase 4: Away mode cleared and watcher re-armed
state/.afk removed. Re-arming Pi watcher extension...
Result ok: true
Result message: watcher: started Pi extension arm child 2; future ordinary re-arms are automatic; call fm_watch_arm_pi again only after a later notification says the cycle is missing, failed, or unhealthy
Arm child 2 is running in background.

>>> Phase 5: Actionable wake occurs while away mode is INACTIVE
Arm child finishes with actionable wake (signal: task-1.status)...
[Pi.sendUserMessage delivered wake prompt to primary session]:
--------------------------------------------------------------------------------
⁣FIRSTMATE_OP: v1 watcher: FIRSTMATE WATCHER WAKE: signal: /tmp/pi-afk-evid-1787318463124/home/state/task-1.status

Run bin/fm-wake-drain.sh first and handle the queued wake. Watcher continuity is extension-owned.
--------------------------------------------------------------------------------
Total wake prompts delivered after normal mode wake: 1
Verdict: Wake was successfully delivered into Pi session via sendUserMessage and successor continuity restored.
Evidence: fm-teardown.sh window-keyed and task-keyed marker retirement log

Source: fm-teardown.sh window-keyed and task-keyed marker retirement log

Demonstrates bin/fm-teardown.sh retiring all 11 task-keyed (.seen-*, .hb-surfaced-*) and window-keyed (.stale-*, .hash-*, .count-*, .wedge-escalations-*, .paused-*) watcher markers during task cleanup so torn-down panes cannot produce stale wakes.

===============================================================================
DEMONSTRATION: Watcher Marker Retirement on Task Teardown (bin/fm-teardown.sh)
===============================================================================

Task ID: task-x1
Window Target: default:w4W:pM (escaped marker key: default_w4W_pM)

>>> [1] State Directory Contents BEFORE Teardown:
-------------------------------------------------------------------------------
.count-default_w4W_pM
.hash-default_w4W_pM
.hb-surfaced-task-x1
.paused-default_w4W_pM
.paused-rechecked-default_w4W_pM
.paused-resurfaced-default_w4W_pM
.seen-task-x1_status
.seen-task-x1_turn-ended
.stale-default_w4W_pM
.stale-since-default_w4W_pM
.wedge-escalations-default_w4W_pM
task-x1.meta
task-x1.status
task-x1.turn-ended
-------------------------------------------------------------------------------
Observed: 11 active watcher internal markers + metadata / signal files present.

>>> [2] Executing bin/fm-teardown.sh task-x1 --force...
-------------------------------------------------------------------------------
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no watcher has a fresh beacon (last beat: never, grace 300s).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  repair a missing or failed watcher cycle with the Pi tool fm_watch_arm_pi, or restart Pi with -e /home/paiva/.no-mistakes/worktrees/3437026af8a8/01M0J64T8WE5Y4MS4BP82SFGSW/.pi/extensions/fm-primary-turnend-guard.ts -e /home/paiva/.no-mistakes/worktrees/3437026af8a8/01M0J64T8WE5Y4MS4BP82SFGSW/.pi/extensions/fm-primary-pi-watch.ts if the extensions are not loaded.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
teardown task-x1 complete (window default:w4W:pM, worktree /tmp/fm-teardown-marker-demo.SuPXdM/wt)
Backlog: task-x1 just finished. Run tasks-axi done task-x1 --note "local main", then run tasks-axi ready for dependency-cleared candidates, check date gates, and dispatch only work whose blockers are gone and date is due.
-------------------------------------------------------------------------------

>>> [3] State Directory Contents AFTER Teardown:
-------------------------------------------------------------------------------
(No task-related markers or metadata remaining in state directory)
-------------------------------------------------------------------------------

>>> [4] Verification Checklist:
  - Task metadata (task-x1.meta): RETIRED
  - Task turn-ended (task-x1.turn-ended): RETIRED
  - Status seen marker (.seen-task-x1_status): RETIRED
  - Turn-ended seen marker (.seen-task-x1_turn-ended): RETIRED
  - Heartbeat surfaced marker (.hb-surfaced-task-x1): RETIRED
  - Window stale markers (.stale-default_w4W_pM, .stale-since-default_w4W_pM): RETIRED
  - Window hash & count markers (.hash-default_w4W_pM, .count-default_w4W_pM): RETIRED
  - Window wedge escalation marker (.wedge-escalations-default_w4W_pM): RETIRED
  - Window pause markers (.paused-default_w4W_pM, .paused-rechecked-*, .paused-resurfaced-*): RETIRED

Verdict: All 11 window-keyed and task-keyed watcher internal markers successfully retired.
The torn-down task's pane/window cannot leave leftover hash/stale state behind to produce stale wakes.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • ./tests/fm-pi-watch-extension.test.sh
  • ./tests/fm-teardown.test.sh
  • ./tests/fm-afk-return.test.sh
  • ./tests/fm-afk-launch.test.sh
  • ./tests/fm-wake-queue.test.sh
  • ./tests/fm-wake-drain-unread-status.test.sh
  • ./tests/fm-watch-arm.test.sh
  • ./tests/fm-watch-checkpoint.test.sh
  • ./tests/fm-watch-triage.test.sh
  • node /tmp/generate_pi_afk_evidence.mjs
  • /tmp/generate_teardown_marker_evidence.sh
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Generated ship, scout, dreamer, and secondmate briefs now include
literal needs-decision and resolved lines with [key=<slug>] before
the colon, matching the documented position.
…osts

Linux remote-job start stacked supervisors when worker.pid was stale, so
heavy e2e scripts leaked process groups and missed observable waits.
Stop stray supervisors for that code root before launching another.

Tests now wait on observables instead of pid 1 or tick counts, reap
daemons by pid, skip a herdr pane that never becomes ready, and hoist
repeated PR-check fixtures.
@BohnBawerick
BohnBawerick force-pushed the fm/fm-pi-watch-afk-double-presentation branch from 0101618 to 672c6d0 Compare August 21, 2026 18:56
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