Summary
watch.sh computes its subscription (PAIRS / WHERE_PAIRS) once at startup and never reevaluates actas lock ownership afterwards (scripts/watch.sh:169-252 as of current main).
With mid-session role switching (actas alice → actas bob, where the previous role's lock is released after the new claim succeeds), this static subscription causes two stale states:
- A peer watcher started while a role was locked keeps omitting that role after the lock is released — the role gets no real-time delivery until some generic watcher happens to restart.
- A watcher started before a claim keeps receiving the newly claimed role, even though it is now exclusively owned by another session.
Suggested fix
Reevaluate lock ownership inside the poll loop (recompute PAIRS/WHERE_PAIRS each tick, or check lock mtimes and recompute on change) so lock transitions propagate to running watchers without a restart.
Workaround today
Watchers recompute subscriptions on restart, which happens at session start, actas, and drop — so the staleness self-heals on the next watcher restart, but a long-lived generic watcher can stay stale indefinitely.
Summary
watch.shcomputes its subscription (PAIRS/WHERE_PAIRS) once at startup and never reevaluates actas lock ownership afterwards (scripts/watch.sh:169-252 as of current main).With mid-session role switching (
actas alice→actas bob, where the previous role's lock is released after the new claim succeeds), this static subscription causes two stale states:Suggested fix
Reevaluate lock ownership inside the poll loop (recompute PAIRS/WHERE_PAIRS each tick, or check lock mtimes and recompute on change) so lock transitions propagate to running watchers without a restart.
Workaround today
Watchers recompute subscriptions on restart, which happens at session start, actas, and drop — so the staleness self-heals on the next watcher restart, but a long-lived generic watcher can stay stale indefinitely.