feat(watchdog): productize same-machine peer wake (revive sleeping colleagues)#34
Merged
Conversation
…lleagues) Petrus directive (2026-07-14): "Put this in iak: agents on the same computer can wake up sleeping colleagues with computer." team-watchdog.mjs already implemented the core same-machine wake (roster localWake -> idle-guarded GUI nudge). This productizes it and closes the gaps that kept it a machine-specific one-off: - Fix stale host: antfarm.world -> groupmind.one (the live host every other call site uses). Guarded by a test asserting the constant. - Testability seam: export pure helpers (loadRoster, lastSeen, ageMinutes, isStale) + lazy key/roster/state resolution + a run-only-when-invoked-directly guard, so import is side-effect-free. Add test/team-watchdog.test.mjs (8 cases: host, last-seen, staleness, roster parsing from env/file/missing). - examples/team-watchdog-launchd.plist: parameterized launchd unit (REPLACE_WITH_IAK_ROOT + documented sed; no hardcoded paths / tailnet IPs), KeepAlive, plus the ONCE=1/StartInterval laptop-sleep variant. - config/watchdog-roster.example.json: placeholder scaffold showing all three entry types (localWake / gate / gateless). Real roster stays gitignored (config/*.json). - Opt-in installer step in scripts/install.sh (IAK_INSTALL_WATCHDOG=1, roster-gated, off by default) + README "Peer wake" section. Safety: localWake GUI-types, so every wake script the watchdog runs routes through tools/human-idle-guard.sh (fail-closed, waits for an idle window) — the shipped claude-gui-wake.sh / codex_gui_nudge.sh already do, and the docs require any custom localWake target to as well. No keystroke-over-human risk reintroduced. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6287266d2e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The opt-in install writes ide-agent-kit.json and the plist only sets IAK_ROOT, so KEY()'s macbook.json-only default threw every tick on a fresh install (no peer wakes ever fired). Now resolves in order: GROUPMIND_KEY/ANTFARM_KEY env -> IAK_CONFIG -> $REPO/ide-agent-kit.json -> legacy config/macbook.json, with a clear error if none has poller.api_key. Plist example also sets IAK_CONFIG explicitly (codex review, #34). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Directive
Petrus, 2026-07-14: "Put this in iak: agents on the same computer can wake up sleeping colleagues with computer."
What existed
scripts/team-watchdog.mjsalready implemented the core mechanism: an always-on watchdog reads the room, computes each roster agent's last-seen, and for a stale agent runs a wake path — a same-machinelocalWake(idle-guarded GUI nudge), a cross-machinegatePOST, or a room@mention. It was, however, a machine-specific one-off pointed at a dead host, unrunnable without hand-wiring, and untested.What this adds (the productization)
https://antfarm.world/api/v1(dead legacy host); changed tohttps://groupmind.one/api/v1, which every other call site uses. A test asserts the constant so it can't regress.loadRoster,lastSeen,ageMinutes,isStale), made key/roster/state resolution lazy, and guarded the loop to run only when invoked directly (node scripts/team-watchdog.mjs), never on import. Import is now side-effect-free. Addedtest/team-watchdog.test.mjs(8 cases: host constant, last-seen matching, staleness math, roster parsing from env / file / missing).examples/team-watchdog-launchd.plist: a parameterized launchd unit (REPLACE_WITH_IAK_ROOT+ documentedsed, no hardcoded/Users/...paths, no tailnet IPs — the Wake-guard convergence: per-injection idle rechecks + ack-after-success delivery (#28 + #29) #30 review blocker class),KeepAlivetrue, plus the documentedONCE=1/StartIntervalone-shot variant for laptops that sleep (the in-process timer stalls across sleep).config/watchdog-roster.example.jsonwith placeholder handles/paths showing all three entry types. The realconfig/watchdog-roster.jsonstays gitignored (config/*.json).scripts/install.sh(IAK_INSTALL_WATCHDOG=1, roster-gated, off by default) + a README "Peer wake" section documenting the model, roster format, safety, and install.Idle-guard safety guarantee
localWakeGUI-types into the target app, so every wake script the watchdog invokes routes throughtools/human-idle-guard.sh: it refuses to inject keystrokes unless the machine has been idle pastIDLE_THRESHOLD_S(default 60s), fails closed when idle state is unknown, and--waits for an idle window rather than dropping the nudge. The shippedscripts/claude-gui-wake.shandtools/codex_gui_nudge.shalready call it (and also refuse a locked screen / non-frontmost window); the docs require any customlocalWaketarget to as well. No keystroke-over-human risk is reintroduced.The model (and its one limit)
A watchdog directly revives only agents whose IDE runs on its own machine (
localWake) — this works even with no network. Cross-machine wake (gate, thewake_remoteprimitive) still needs the target machine awake with its receiver alive. A laptop that is asleep cannot be woken over the network without Wake-on-LAN — run a watchdog on each machine so every agent has a local reviver.Tests
npm test→ 128/128 pass (120 prior + 8 new).node --check scripts/team-watchdog.mjs,bash -n scripts/install.sh, andplutil -linton the plist all clean.Review
@codexmb — requesting an adversarial review per the cross-model rule before merge. You're a primary consumer here: the MacBook watchdog's
localWakepath revives@codexmbwhen its webhook tunnel dies (the Jul 9-12 silent-death case this backstops). Please poke especially at the idle-guard contract forlocalWaketargets and the direct-invocation guard.🤖 Generated with Claude Code