Skip to main content

Scheduled runs — repo-owned cron

Your repo can declare cron schedules in its own .slipstream.json. The control plane fires each one as a first-class run — logged, ledgered, and visible on the dashboard and through the MCP — without any separate scheduler infrastructure on your side.

:::note A schedule is a monitor, not a commit verdict A scheduled run never posts the RunsGreen check, never ships, never merges, and never rolls or targets the executor fleet's own deploy path. Use schedules for proofs, health probes, and housekeeping — never for CI or CD. :::

Declaring a schedule

schedules is a recipe v2 field, alongside stages:

{
"version": 2,
"tenant": "k2k",
"stages": [
{ "name": "install", "cmd": "bun install --frozen-lockfile" },
{ "name": "test", "cmd": "bun test", "needs": ["install"] }
],
"schedules": [
{
"name": "nightly-health-probe",
"cron": "0 3 * * *",
"stages": [
{ "name": "install", "cmd": "bun install --frozen-lockfile" },
{ "name": "probe", "cmd": "bun run scripts/health-probe.ts", "needs": ["install"] }
]
}
]
}
FieldRequiredNotes
nameyesUnique within the recipe's schedules array.
cronyes5-field UTC cron expression, or an @hourly / @daily / @weekly / @monthly / @yearly nickname. Always UTC — there is no per-schedule timezone.
stagesyesInline v2 stage objects — the same shape as your CI stages, including needs, if_changed, secrets, and resource hints. A scheduled run resolves through the exact same stage-execution path a CI run does.
enabledno (default true)Set false to keep a schedule declared but paused. Removing an entry from schedules entirely also disables it — it is never deleted, so its run history and failure streak survive.

A scheduled stage may not deploy, roll the executor, or target the executor's own Fly app — validation refuses the whole schedules block if any stage does. Validation also refuses: an unparseable cron, an effective cadence faster than 5 minutes, more schedules than your repo's cap (default 5), and a duplicate name. A recipe with an invalid schedules block fails validation entirely — nothing half-lands.

These rules are enforced twice: once when a push adopts your schedules, and again when a fire resolves the schedule at that commit. A schedule whose stages stop passing validation fails the run with the named reason instead of executing — an already-adopted schedule cannot be turned into a deploy by a later push.

How firing works

  • Adoption reconciles your declared schedules into the platform on every default-branch push, independent of whether the feature flag is on — so a schedule is ready to fire the moment the platform operator flips it.
  • Firing happens on a 30-second dispatch tick that re-checks the platform flag, your repo's allowlist membership, the schedule's own enabled, and the platform kill switch / repo quarantine every time. An operator pulling the global brake stops your schedules too.
  • Missed fires: a schedule due within the last 10 minutes fires once; later than that, it skips forward to its next future occurrence instead of firing a backlog. A control-plane restart never produces a stampede of missed fires.
  • No overlap: if the previous run for a schedule is still in flight, the due occurrence is skipped (and counted in telemetry, not as a failure) rather than piling up concurrent runs.
  • Scheduled runs share the same 6-minute wall-clock ceiling as CI runs.

What a scheduled run is — and isn't

  • It appears on the dashboard's runs view under a scheduled filter, and in slipstream_status / slipstream_fleet_status like any other run. A red one is diagnosable with slipstream_diagnose.
  • It is excluded from CI health KPIs — a monitor going red is not a commit going red. Schedules have their own KPIs instead; see How a schedule is scored.
  • It posts no GitHub check — not the required RunsGreen check, not the legacy mirror. It cannot gate a PR.
  • It can never trigger ship-on-green or auto-merge, even if every stage is green.
  • A red scheduled run is rerunnable by run id through the API or the dashboard's Rerun button. A repo+sha rerun is refused — several schedules can fire at the same commit, so "rerun repo@sha" is ambiguous for this run kind. The slipstream_rerun MCP tool does not yet accept a run id, so today rerunning a scheduled run needs the API or the dashboard.

Three reds raise one alert

Three consecutive red runs for a schedule raise a single deduped critical alert on the dashboard's alerts feed; it does not repeat on the 4th or 5th red. A green run clears the counter. This is a convenience signal for schedule owners — it is separate from the platform's own deadman watch on the scheduler process itself, described in docs/CONTROL-PLANE.md § Scheduled runs.

How a schedule is scored

Each schedule carries its own KPIs over a rolling 30-day window, shown on the platform operator's Schedules view:

  • Lateness — how far after its due time a fire actually started, as a median and a worst case. This is the headline number. A schedule creeping from one minute late toward the ten-minute grace window is on its way to having fires silently skipped, and lateness is the only signal that shows it before that happens.
  • Success rate — the share of completed fires that passed. A schedule that has fired but not finished reads as "no result yet", never as 0%.
  • Duration — median and p95 wall-clock, so a monitor drifting toward the 6-minute ceiling is visible before it starts getting killed.
  • Recent outcomes — a compact history of the last several fires, newest first.

Two things deliberately do not count toward lateness. An operator rerun is scored for success and duration but not lateness — someone clicked, so measuring it against the original occurrence would say more about the human than the clock. And a fire that was skipped forward past the grace window is not a late run; it never ran at all.

Availability

Scheduled runs are a platform-operator-enabled feature — there is nothing in slipstream_onboard to turn them on yourself yet. Declaring schedules in your recipe is safe at any time (validation and adoption both work today); ask your platform operator to enable firing for the fleet.