Repository navigation
chore(sutando-app): bump checkWatcher Timer from 30s → 5min - #699
Conversation
Per Chi 2026-05-14 23:15Z: with Claude Code's `Monitor` tool now driving `watch-tasks-stream.sh` as the canonical persistent watcher, the menu-bar Timer is purely a safety net (catches Monitor crash / session-restart race / tmux pane death). 30s polling was overkill; 5 min keeps recovery in human-interactive territory (worst-case lag = ~5 min stale before auto-restart) while cutting 12× the wake-ups. No behavioral change beyond cadence — `checkWatcher()` body itself, the "watcher" keystroke send, and the idle/queued-keystroke guards all unchanged. Tradeoff documented inline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sonichi
left a comment
There was a problem hiding this comment.
LGTM with 1 dead-code nit.
Strengths:
- Surgical: 1-line behavior change, body of
checkWatcher()untouched. - Comment block thoroughly preserves Chi's 2026-04-18 design context + names the new tradeoff explicitly.
pgrep -f watch-taskssubstring still matches the currentwatch-tasks-stream.sh(verified via livepgrep -fl watch-tasks→ matchesbash src/watch-tasks-stream.sh).
Nit — dead code (not blocking): inner throttle at main.swift:458 is Date().timeIntervalSince(lastWatcherAlert) < 120 — that's 120s, but the outer Timer now fires every 300s. Two consecutive ticks are always ≥300s apart, so the throttle never gates anything anymore. PR body says "60s" but the actual throttle is 120s; both are subsumed by the new 300s cadence. Could either drop the throttle entirely or document why it's still useful (e.g. for the case where checkWatcher() is invoked from another path).
Tradeoff acknowledged: worst-case 5min stale window before safety-net kicks in. Reasonable since Monitor is the primary watcher with its own keepalive — this is a backstop. PR body already calls this out.
Build verified locally on the diff. No regressions visible. Cleared to merge from my read.
…imer) Self-review: the inner `Date().timeIntervalSince(lastWatcherAlert) < 120` gate at main.swift:465 was strictly dead code under the new 300s outer Timer cadence — two consecutive ticks are always 300s apart, so the 120s window never gated anything. Drop the `lastWatcherAlert` var + the gate. Flood-protection is now solely the `watcherKeystrokesQueued()` capture-pane check + the Timer interval itself. Comment block updated to document the removal context. Build verified locally with swiftc -O. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
) * chore(sutando-app): bump checkWatcher Timer from 30s → 5min Per Chi 2026-05-14 23:15Z: with Claude Code's `Monitor` tool now driving `watch-tasks-stream.sh` as the canonical persistent watcher, the menu-bar Timer is purely a safety net (catches Monitor crash / session-restart race / tmux pane death). 30s polling was overkill; 5 min keeps recovery in human-interactive territory (worst-case lag = ~5 min stale before auto-restart) while cutting 12× the wake-ups. No behavioral change beyond cadence — `checkWatcher()` body itself, the "watcher" keystroke send, and the idle/queued-keystroke guards all unchanged. Tradeoff documented inline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(sutando-app): drop dead 120s inner throttle (subsumed by 300s Timer) Self-review: the inner `Date().timeIntervalSince(lastWatcherAlert) < 120` gate at main.swift:465 was strictly dead code under the new 300s outer Timer cadence — two consecutive ticks are always 300s apart, so the 120s window never gated anything. Drop the `lastWatcherAlert` var + the gate. Flood-protection is now solely the `watcherKeystrokesQueued()` capture-pane check + the Timer interval itself. Comment block updated to document the removal context. Build verified locally with swiftc -O. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Chi <wangchi@Chis-Mac-mini.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Bumps the menu-bar app's
checkWatcher()Timer cadence from 30s → 5 min (Timer.scheduledTimer(withTimeInterval: 300.0, ...)inSutando/main.swift:241). Per Chi 2026-05-14 23:15Z (yto the proposal at https://discord.com/channels/1485653766404444352/1499520683267592432).Why
With Claude Code's
Monitortool now drivingwatch-tasks-stream.shas the canonical persistent watcher (PR #693 retired the legacy one-shotwatch-tasks.sh), the menu-bar Timer is purely a safety net for:30s polling was overkill. 5 min keeps recovery in human-interactive territory (worst-case lag = ~5 min before auto-restart) while cutting 12× the menu-bar wake-ups → less battery, less log noise.
What this PR doesn't change
checkWatcher()body — idle-check,watcherKeystrokesQueued()guard,watcherkeystroke send all unchangedpgrep -f watch-taskssubstring match — still matches both the legacy script name (gone) and the currentwatch-tasks-stream.shTest plan
watch-tasks-stream.sh→ wait 5 min → confirm menu-bar nudges Claude Code withwatcherkeystrokeTradeoff
A voice task landing the moment Monitor dies waits up to 5 min before the safety net kicks in. Mitigation: Monitor is persistent + has its own keepalive against tmux session lifetime, so this scenario is rare.
🤖 Generated with Claude Code