MODULO 6.5

⏰ Cron & Scheduling

7
Topicos
~60
Minutos
Deep
Nivel
Source
Tipo
1

📋 Architecture Overview

Layer 1 — Tools

CronCreate / Delete / List - model-facing API, validation, file I/O.

Layer 2 — Scheduler Core

cronScheduler.ts - 1s tick loop, chokidar file watcher, lock, jitter.

Layer 3 — Storage

.claude/scheduled_tasks.json + in-memory session store for ephemeral tasks.

Layer 4 — React Glue

useScheduledTasks - mounts scheduler in REPL, routes fires to message queue.

Layer 5 — Fleet Ops

cronJitterConfig.ts - GrowthBook-backed tuning pushed live without restart.

2

📝 CronTask Data Model

Each task has: id (8-hex UUID slice), cron (5-field local time), prompt, createdAt, lastFiredAt, recurring, permanent, durable, agentId. The durable flag never touches disk - writeCronTasks strips it.

💡 Two Flavors

One-shot (recurring: false): fire once, auto-delete. Recurring (recurring: true): fire, reschedule from now, auto-expire after 7 days.

3

🔄 Scheduler Lifecycle

Created once per REPL session. Lazy-enable design: chokidar and timers don't start until tasks exist. EnablePoll probes every 1s. Timer is unref'd so -p mode can exit.

💡 Catch-Up Prevention

Recurring tasks reschedule from 'now', not from computed fire time. If session blocked and 9am task fires at 9:05, next fire computes from 9:05.

4

🔒 Multi-Session Distributed Lock

Per-project scheduler lock prevents double-firing when multiple sessions share a directory. Lock liveness-probed by PID. Non-owners probe every 5 seconds to detect stale locks from crashed sessions.

💡 Session Tasks Are Lock-Exempt

Session-only tasks live in process-private memory - no shared file, no double-fire risk. Lock guard only applies to file-backed tasks.

5

📊 Load-Spreading Jitter

Deterministic per-task

jitterFrac = parseInt(taskId.slice(0,8), 16) / 0x1_0000_0000. Stable across restarts, uniform across fleet.

Recurring: forward jitter

Fires up to recurringFrac * interval late (cap: 15 min). Hourly with defaults: up to 6 min spread.

One-shot: backward jitter

Fires up to 90s early, only on :00/:30 minutes. Humans pick round times; firing early is invisible to user.

💡 GrowthBook Live Ops

Jitter config from tengu_kairos_cron_config feature flag. Ops can push changes during incident. Fleet converges within 60 seconds.

6

🚨 Missed Tasks & Startup

findMissedTasks() compares each task's first fire time from createdAt to now. Missed one-shots surfaced with injection-resistant prompt (adaptive backtick fence). Missed recurring tasks NOT surfaced - scheduler fires on first tick.

💡 Prompt Injection Defense

buildMissedTaskNotification() finds longest backtick run in prompt, opens fence with one more backtick. Prevents prompt injection via crafted backtick sequences.

7

🛑 Feature Gates & Kill Switches

GateTypeEffect
feature('AGENT_TRIGGERS')Build-timeDead-code elimination of entire cron module
CLAUDE_CODE_DISABLE_CRON=1Env varLocal override, kills all scheduling
tengu_kairos_cronGrowthBookFleet-wide kill switch, polled every 5 min
tengu_kairos_cron_durableGrowthBookKills disk persistence only, session cron stays
tengu_kairos_cron_configGrowthBookJitter tuning without deploy

📋 Resumo do Modulo

Tasks stored in .claude/scheduled_tasks.json; session-only tasks live in bootstrap/state.ts memory.
Scheduler polls at 1s intervals but lazy-enabled - chokidar and timers start only when tasks exist.
Per-project scheduler lock prevents double-firing across multiple sessions sharing a directory.
Jitter is deterministic per task ID - same task = same jitter across restarts.
Missed one-shot tasks surfaced with injection-resistant adaptive backtick fence prompt.
isKilled polled every tick - flipping GrowthBook flag stops all running schedulers within 5 minutes.
Voltar Proximo