Tarski/ docsJoin the waitlist

Scheduling

Standing cron, interval, and one-shot schedules whose exactly-once fires enter the lineage as ordinary observations — never a second source of truth.

The workspace scheduler lets an app declare standing schedules — cron calendars, fixed intervals (every), and one-shots (at) — that deterministically append schedule fire observations into a lineage. The scheduler is an input authority only: it never derives facts, creates intents, or executes effects. “Every weekday at 09:00, refresh the feed” composes exactly like everything else:

schedule fire observation → mapper atoms → rules → intent.* → declared effect capability

Fire observations

Fires arrive as schedule.tick observations (reserved source capability:scheduler) carrying the schedule id and digest, the scheduled_for instant, the fire kind (occurrence, catch_up, or manual), DST and catch-up metadata, the timezone-database version, and your declared payload under data.

Occurrence identity is (lineage_id, schedule_id, scheduled_for), appended through the idempotent observation contract — crash recovery and authority handover resolve to the original receipt, so “exactly once” is structural. Every schedule mutation itself appends a control observation with actor context, making the registry rebuildable from the lineage.

Declaring and managing schedules

Manifest-declared schedules live in tarski.toml under [schedules.<id>] and reconcile at activation; the API can pause, resume, and trigger them, but update and removal fail closed with schedule.manifest_origin_immutable — the manifest stays authoritative. Dynamic schedules are managed by CLI:

tarski schedule list
tarski schedule create
tarski schedule preview
tarski schedule pause
tarski schedule trigger
tarski schedule fires
tarski schedule simulate

The cron dialect is five-field with names, ranges, lists, steps, ?, L, W, #, and @hourly-style aliases. Restricting both day fields without a ? fails closed. DST gaps fire once at the transition instant (marked dst_adjusted); folds fire the earlier instant. Occurrence computation is a pure function pinned by a golden conformance corpus.

Per-schedule catch-up policy covers downtime: skip, fire_once (default), or a bounded fire_all.

Firing authority

Exactly one firing authority exists per lineage, bound to the committed effect-authoritative activation: local live (tarski serve / tarski dev), local offline catch-up (tarski run), or the hosted durable scheduler (which wakes hibernated workspaces when fires come due). Replay, verification, shadow builds, and fixtures consume recorded fire observations — they never fire.

Verifying scheduled behavior

tarski schedule simulate renders the exact fire observations across a virtual window as fixture JSONL — byte-identical across runs — so scheduled behavior is tested like any other behavior. tarski verify includes a schedules check: manifest definitions validate, fixture fires must match the payload contract, and simulation determinism is re-proven per run.

When a fire produces no effects, tarski run names why with stable zero-effect reasons: schedule_fire.no_intent_derived, schedule_fire.no_effect_admitted, effect_authority.shadow, http.credential.unresolved, or effect_request.blocked.