Each branch owns .daemon/schedule.json; daemon does discovery + firing via wake_branch() direct (path A). Owner IS the wake target, killing stale-target bugs. Proven live: drone @daemon run -> discovered @commons/wake-test -> wake_branch() fired -> @commons woke -> @devpulse received 'DAEMON TEST FIRED'. - handlers/schedule/discovery.py — scan branches for .daemon/schedule.json - handlers/schedule/runstate.py — per-job run-state tracking - modules/run.py — run-tick entry (wired into 5 modules) - scheduler_cron.py — rewired process_actions -> run_tick - old plugins (community_rotation, daily_audit, heartbeat) retired -> .archive - 448 tests (+61) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Modules
Business logic for DAEMON. One module per command.
Modules orchestrate work by calling handlers. They are the public API of the branch — drone routes commands here.