8000 feat(automations): schedule, at and relative triggers as timers by adeelahmad · Pull Request #450 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(automations): schedule, at and relative triggers as timers - #450

Merged
adeelahmad merged 1 commit into
mainfrom
claude/project-thread-gauy4d
Oct 16, 2026
Merged

adeelahmad merged 1 commit into
mainfrom
claude/project-thread-gauy4d

Conversation

@adeelahmad
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: Lens could keep timers (#446), but nothing turned an automation's "every weekday at 07:00", "at 18:00 on Friday" or "30 minutes before the event starts" into one.

After: app/domain/timers.py sets, moves and calls off the timers behind an automation's schedule, at and relative triggers, and lists what an automation has coming in words ("Every weekday at 07:00: next on Fri 16 Oct at 07:00 (Europe/London)"). When one fires, the automation fires with a clock.tick activity (a new kind, never stored) or with the activity that set the timer. Workflow studio M4, part 2 of 3. Nothing changes for an install until automations are stored (M6), which calls these on save.

How:

  • schedule_automation(db, automation) runs on save, switch-on and switch-off. It sets one timer per schedule trigger (sched-<id>-<as>, kind schedule.next, re-armed in its claim through schedule.next_after, so DST works as routines have it). It also sets one per at trigger that is still to come (at-<id>-<as>). A waiting timer whose trigger is unchanged is left alone, so an overdue one can still catch up. Changed ones are set anew and the rest are cancelled. Switched off, everything is cancelled.
  • relative(db, automation, alias, activity, field, offset) keys its timer by automation, trigger and the activity's object (rel-<id>-<as>-<object id>), so a moved calendar event moves its timer rather than adding a second one. A time more than 5 minutes past is skipped and returns a note for the run log.
  • upcoming(db, automation, n) and clock_state(db, automation) serve M6's API and the builder. untrusted marks a description that quotes outside text (an event title).
  • schedule.describe now reads weekdays, weekends, single days and days of the month ("at 09:00 on the 20th of every month"), so the existing GET /api/v1/routines/schedule preview gets better too.
  • automations.fire is reached through an import guard (_provided), since M6 isn't merged. Until then a fired trigger records "automations aren't built yet" on last.error, and a schedule still re-arms.

Defaults I picked (reversible):

  • A date-only field value is midnight UTC; the person's time zone is under Refine later.
  • clock.tick is noisy and never stored, so it reaches automations without filling the timeline.
  • A relative time more than 5 minutes past is skipped, not fired late (the catch-up window covers downtime, not stale events).

Motivation and Context

Workflow studio M4 (/mnt/project-files/workflow-studio/briefs/M4.md, plan section 3.10). M6 calls schedule_automation on save and relative from its trigger matcher, and exposes upcoming. Part 3 adds actions that wait (later).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (make hooks checks it on commit).
  • I added or updated tests.
  • My change requires documentation updates, and I have updated docs/ accordingly.
  • Users need more than the title to understand it, so I wrote it under ## Unreleased in CHANGELOG.md. (n/a: nothing reaches people until M6 stores automations)

Done questions (AGENTS.md)

  • Goal: part 2 of M4, merged on green CI; part 3 follows.
  • Agents: M6 exposes upcoming and the automation API; clock.tick shows in GET /api/v1/activities/kinds for agents writing triggers; the schedule preview is already in the API.
  • Zero setup: no new table, setting or prerequisite.
  • Fewest clicks: n/a, no UI here (the builder comes in M9).
  • Configurable: n/a, no new setting (catch-up came in feat(automations): timers that outlast a restart and fire once #446).
  • Light: one timer per trigger, indexed; no polling beyond feat(automations): timers that outlast a restart and fire once #446's.
  • Private and secure: no new route or outside input. Relative timers are capped per automation (feat(automations): timers that outlast a restart and fire once #446's 1000). Event titles in descriptions are marked untrusted. Threat model n/a.
  • Cost: no model calls.
  • User decides: nothing runs until a person saves an automation with these triggers; defaults unchanged.
  • Upgrades: no stored data changes shape.
  • Honest: docs/automations.md labels the timers built and says automations set them once they are stored; waiting actions planned.
  • Tests: tests/domain/test_timer_triggers.py covers schedule re-arm and catch-up, DST, at once, relative moves/skips/cancels, saving again, switch-off, upcoming, clock_state and describe. Docs: docs/automations.md (Time, kinds table, Refine later). Run on embedded SurrealDB and a 3.2.4 server. No generated files change.
  • Open: no new dependencies.
  • Reported in the thread; refine-later items are in docs/automations.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KfD6cia42GiEZakbs74jxY


Generated by Claude Code

timers.schedule_automation sets one timer per schedule trigger (its next
time, re-armed as it fires, DST as schedule.py has it) and per at trigger
still to come, leaves timers a trigger still wants alone so they can catch
up, calls off the rest, and cancels everything when the automation is off.
timers.relative sets a relative trigger's timer per automation, trigger and
object, so a moved calendar event moves its timer; past times are skipped
with a note. When they fire, automations.fire gets a clock.tick activity
(a new kind, never stored) or the activity that set the timer.
timers.upcoming lists what an automation has waiting, in words, and
schedule.describe reads weekdays, single days and days of the month.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KfD6cia42GiEZakbs74jxY
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.

2 participants

0