Add scheduled recurring agent runs - #386
Open
0x92 wants to merge 2 commits into
Open
Conversation
start() called rescheduleAll(), which recomputed every enabled schedule's next run from now. A stored time in the past was therefore replaced with a future one before the first tick ever looked at it, so the tick had nothing overdue to find: lastRunStatus never became 'skipped' and the history showed no sign that the run had been due at all. The same erasure took out runs that were meant to happen. A schedule two minutes late is inside SCHEDULE_MISS_GRACE_MS and should start; instead it was moved to the next occurrence and dropped. rescheduleAll also rewrote the next run of schedules that were not overdue in any sense, including one a user had just saved. reconcileOnStart() now decides only the two things startup can decide: a schedule with no next run at all gets one, and one that is late beyond the grace period is written off as missed. Everything else keeps its stored time and the tick decides, which is where that belongs. The missed-run bookkeeping tick() already did moves into recordMissed() so both paths write the same thing — one skipped entry per schedule, not one per interval of downtime, because computeNextRun counts from now. The existing tests drove tick() with a hand-built overdue row and never called start(), which is exactly where the bug lived.
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.
Description
Let a project start agent sessions on a schedule: a fixed prompt, at a fixed time, in a fresh worktree.
Pane already knows how to create a session from a prompt — this makes that repeatable without a person present. Nightly bug sweeps, a weekly dependency check, a "review yesterday's diffs" pass every morning: the work that is worth doing regularly but never worth remembering.
A new Scheduled runs entry in the project's menu manages them.
What it does
Every day at 03:00 — next run in 4h 12m). Cron is more expressive than anyone actually needs here and impossible to render as a sentence.claude, ornonefor a plain terminal) and an optional worktree/branch template.ON DELETE CASCADE).How it works
scheduleCalculator.tsis pure and holds every decision about when:computeNextRun,isDue,isMissed. Time zones, daylight saving and "the next weekly run when today already passed" are the parts that break silently, so they are unit-tested directly rather than through the scheduler.ScheduleManagerticks every 30s and asks the calculator; it talks to storage through a smallScheduleStoreinterface, so its behaviour is tested without a database.createSessionAndWait, solastSessionIdis the real session id rather than a queue job id — the difference only shows up when you click the link.scheduled_runs, plus an index on(enabled, next_run_at_ms)so the tick is a single indexed lookup.schedules:*): the schedule belongs to the machine that runs the agents.Type of Change
Checklist
pnpm typecheckandpnpm lintlocallypnpm electron-devCritical Areas Modified
Additional Notes
Schema note:
schema.sqlis split on the statement separator at startup, so a;inside a comment breaks the database. The new block is written accordingly.Tested in the running app, not only in unit tests: a schedule was created, fired on its own tick, produced a real session in a fresh worktree, recorded its outcome, and was then disabled and deleted. Missed-run handling was exercised by moving a schedule's due time into the past.