@beevibe/scheduler
Server-side fallback. Picks up sessions when no daemon will, reaps orphans, handles cancellation.
The scheduler is the safety net. When a mesh ask targets an agent whose daemon is offline, the scheduler runs the session on the server. When a session crashes and leaves an orphan row, the scheduler cleans it up. It runs server-side, polls every 30 seconds, and is stateless — restart it whenever.
What it does, per cycle
1. Reap PID orphans
Sessions whose in-process worker died (process gone, no SIGCHLD picked up) get marked failed and released.
2. Claim server-fallback sessions
Pulls the next session whose target daemon is offline or whose dispatch is flagged for server-side spawn.
3. Check capacity
If the agent is at its max_task_sessions ceiling, the row goes back to pending for the next pass.
4. Provision and dispatch
Sets up the workspace and spawns the run via DispatchService. Streams events back through the same API endpoints the daemon uses.
Cancellation
Cancellation is wired through Postgres notifications. A POST /task/:id/cancel fires NOTIFY cancel_task. A dedicated Postgres client listens for those, finds the matching in-process session by its AbortController, and aborts. The CLI subprocess gets SIGTERM.
Post-dispatch nudges
Two automatic interventions:
- Crash recovery. If an agent finishes without calling
update_progress, the scheduler re-dispatches the same agent on the same runtime with acrash_recoveryintent. Stops the work from silently vanishing. - Parent rollup. When the last child of a parent task settles, the parent's status is rolled up. Approve, revise, cancel — all bubble correctly without a human refreshing.
Run it
pnpm --filter @beevibe/scheduler build
pnpm --filter @beevibe/scheduler start # node dist/main.js
pnpm --filter @beevibe/scheduler dev # watch mode
bash
Override the poll interval with POLL_INTERVAL_MS. Defaults to 30 seconds.
Health endpoint
GET /health returns a JSON snapshot. ok=false with HTTP 503 if polling has stopped or the last successful poll is more than 3× the interval ago.
{
"ok": true,
"polling": true,
"last_poll_at": "2026-05-16T15:42:11Z",
"in_flight_count": 2,
"poll_interval_ms": 30000
}
json
Source
For the worker-loop internals, capacity SQL, and PID-reaping logic, see packages/scheduler/README.md on GitHub.