Skip to content

Routines (1/2): the scheduler - #23

Merged
httpsphl merged 2 commits into
mainfrom
feat/routines
Sep 29, 2026
Merged

httpsphl merged 2 commits into
mainfrom
feat/routines

Conversation

@httpsphl

Copy link
Copy Markdown
Owner

Routines, part 1 (R1): the scheduler in the daemon. A routine makes a bot work on its own at set times. The design (spec section 20) ships with it; the app's screens are in the next PR.

What changes

  • Schedules: weekly (days of the week at a time), every N minutes (5 minutes to a week) or a 5-field cron expression, each in the routine's own time zone. Calendar times follow the wall clock: a time the clock skips runs right after the jump, one it repeats runs once.
  • Firing: at its time the daemon posts the owner's request to the bot on the usual message path (stored first, delivered by the courier, retried), with an envelope that names the routine, the local time it is for and that nobody is watching live.
  • Rules: a run still open skips the next time, or lets one wait with overlap: queue; a paused bot skips its times; times missed while the daemon was away run once for the latest, or not at all with missed: skip (a time up to 2 minutes late counts as on time); turning a routine back on counts from now; run now fires outside the schedule; archiving a bot archives its routines.
  • How a run ends: with the turn that began with its message, done or failed on an error. A dead message, a process that ends mid-turn, or a daemon that stopped mid-turn (found at the next start) also fail the run.
  • Zones: jiff, with the IANA database it bundles on Windows. The daemon evaluates cron itself, walking the days in the routine's zone.
  • Storage: migration 0008 (routines, routine_runs, messages.routine_id). Protocol: routines.list/create/update/setEnabled/runNow/archive/runs, notifications routine.changed and routine.run, Message.routineId and kind routine. The app gets the types and a fake.
  • The spec also records the M5 reboot check (section 14): after a reboot the daemon came up 1 s after logon with the app closed, and the bot was back 13 s later.

Tested

  • cargo fmt, clippy -D warnings and cargo test: new tests for the schedule math (New York's 2026 jump and repeat, São Paulo and Lisbon zones, a 0 0 29 2 * cron that next runs in 2028, validation), cron parsing, the store, and 11 integration tests on FakeRuntime with a manual clock (on time, overlap skip and queue, missed run once and skip, paused bot, run now, a failed turn, a dead message, a process and a daemon gone mid-turn, turning off, archiving). pnpm check passes.
  • The real Claude Code run is in the next PR, with the app.

Routines are the first item after the MVP: a bot works on its own on a
weekly schedule, an interval or a cron expression, in the routine's own
time zone. Each run is a message the owner wrote, delivered into the
bot's one conversation through the courier like any other, so it is
durable and needs no second session. A run ends with the turn its
message started; overlapping runs are skipped (or one waits), paused bots
skip, and missed times run once when the computer is back.

The schedule is stored as structured JSON so the app can show and edit
it in plain words; cron stays behind "Advanced". Milestones R1 (daemon)
and R2 (app) start once M5 is closed.
A routine makes a bot work on its own: weekly at a time, every N minutes
or on a cron expression, in its own time zone. When its time comes, the
daemon posts the owner's request to the bot on the usual message path,
with an envelope that names the routine, the local time it is for and
that nobody is watching. The run ends with the turn that began with
that message: done, or failed on an error, a dead message, a process
that ended mid-turn or a daemon that stopped mid-turn.

A run still open skips the next time (or lets one wait, with queue), a
paused bot skips its times, and times missed while the daemon was away
run once for the latest (or not at all). Run now fires outside the
schedule. Archiving a bot archives its routines.

Zones use jiff with the IANA database it bundles on Windows. The daemon
evaluates cron itself, walking the days in the routine's zone: a time
the clock skips runs right after the jump, one it repeats runs once.

The app gets the protocol (routines.* and two notifications) and a fake;
its screens come in R2. The spec also records the M5 reboot check.
This was referenced Sep 29, 2026
@httpsphl
httpsphl enabled auto-merge September 29, 2026 12:25
@httpsphl
httpsphl merged commit bca29b4 into main Sep 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant