You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make the Coven automation scheduler deterministic, restart-safe, bounded, and diagnosable under real operating conditions: sleep/wake, clock changes, daylight-saving transitions, daemon restart, duplicate processes, slow or unavailable runtimes, cancellation races, delivery failure, and ambiguous side effects.
The completion criterion is not “the 60-second thread fired.” It is that every eligible occurrence reaches one explainable durable disposition without silent loss, duplicate execution, false success, or an unrecoverable stale lease.
Current implementation baseline
The landed scheduler already provides valuable foundations:
SQLite occurrence fencing;
claim leases and expired-lease recovery;
latest-only misfire behavior;
overlap refusal;
daemon tick and scheduled dispatch;
shared manual/scheduled runtime launch;
run ledger and atomic output delivery.
The remaining reliability contract is incomplete:
scheduling is driven by a fixed sleeping thread and wall-clock reads;
startup does not have a separately specified immediate-reconciliation contract;
definition changes do not yet have a canonical wake/replan mechanism;
local timezone is not an immutable IANA timezone binding;
DST gap/fold and host-timezone-change semantics are not published;
retries/backoff/jitter and failure classification are not first-class;
cancellation acknowledgement and cancellation/completion races are not fully modeled;
scheduler leadership/fencing for more than one process is not specified;
shutdown/drain behavior and stuck-runtime recovery need explicit state transitions;
virtual-time, crash-point, chaos, and sustained-load certification are absent.
Time abstraction
Introduce an injected scheduler clock and wake source used by production and tests:
production waits use a monotonic deadline recalculated from authoritative wall time;
tests use deterministic virtual time with no wall-clock sleeps;
creation/update/activation/pause/cancel and daemon shutdown can wake the scheduler;
scheduler startup performs an immediate reconcile before the first timed wait;
every pass records scheduled start, actual start, duration, planned/claimed/dispatched/recovered counts, and error class;
a backward/forward wall-clock jump produces a recorded replan rather than duplicate or permanently delayed work;
no correctness assertion depends on a sub-second timing margin on shared CI.
Timezone and DST contract
Replace ambiguous durable local semantics with an explicit versioned timezone binding:
accept UTC and IANA TZID in the stable contract;
treat local as compatibility input resolved to an exact IANA zone at activation/import where the platform can prove it;
record the timezone database/version used for planning where practical;
changing host timezone must not silently reinterpret an active definition;
changing a definition timezone creates a new definition revision and replans only future occurrences.
Ratify and vector-test safe v1 defaults:
nonexistent local wall time during a spring-forward gap is skipped with a durable reason rather than silently shifted;
repeated wall time during a fall-back fold produces one occurrence under an explicit deterministic fold rule, with the chosen offset recorded;
leap-day, month/year boundary, end-of-month, and supported weekly rules are deterministic;
unsupported RRULE vocabulary fails at validation rather than being approximated;
system sleep and daemon downtime use the declared misfire policy, not one event per missed minute.
Alternative gap/fold policies may be added later as explicit versioned variants; they must never be inferred.
Retry and failure classification
Define failure classes before adding automatic retry:
validation/contract failure — never retry;
identity/authority/capability refusal — never retry without new authorization evidence;
scheduler/store transient — retry scheduler operation, not the familiar action;
runtime admission/unavailable before side effect — bounded retry allowed;
runtime started with known failed outcome — retry only when action policy permits;
ambiguous runtime/side-effect outcome — recovery_required, no automatic retry;
delivery commit failure after successful execution — retry idempotent delivery only, never rerun the familiar action;
cancellation/timeout — explicit policy, never silently converted to retry.
Implement bounded exponential backoff with deterministic full jitter in production and seeded deterministic jitter in tests. Persist retry policy, notBefore, attempt number, failure class, and exhaustion reason. Add a circuit/quarantine state for repeated failures so a broken routine does not create an unbounded storm.
Cancellation and timeout
Model cancellation as requested → acknowledged/reconciled → terminal.
Persist who requested cancellation, when, scope, and reason.
Fence cancel against the exact run/attempt and current runtime correlation.
Define completion-vs-cancel and timeout-vs-completion races with one convergent terminal result.
A runtime that cannot confirm stop enters recovery-required or a narrowly defined timeout terminal state; it is not assumed stopped.
Disabling/deleting a definition prevents future planning but does not rewrite an in-flight run.
Daemon shutdown has a bounded drain policy and records every active attempt left for restart reconciliation.
Lease, leadership, and fencing
Even for a local-first v1, prevent accidental duplicate schedulers:
use a scheduler-leader lease or equivalent single-writer guard in the Coven store;
issue monotonic fencing generations for scheduler ownership and occurrence claims;
require the current fence on every state transition and settlement;
reject stale workers/processes after lease transfer;
prove two daemon processes sharing one store cannot both dispatch the same occurrence;
define what remains unsupported for network filesystems or multi-host shared SQLite.
Multi-host routing remains P2; this issue prevents unsafe accidental concurrency without pretending SQLite is a distributed consensus system.
Crash/restart matrix
Inject a crash or process stop after each consequential boundary:
definition revision commit;
occurrence planning;
claim commit;
command adoption;
runtime dispatch request;
runtime session creation;
first runtime event;
runtime terminal observation;
run settlement;
output/delivery temp write;
delivery rename/commit;
receipt commit;
event/changefeed publication.
For each point, restart must converge to exactly one durable, explainable disposition. Missing evidence must never become success, and an ambiguous mutating action must never be replayed automatically.
Backpressure and retention
Bound eligible/claimed work per pass.
Bound global and per-routine concurrency.
Bound runtime admissions and delivery work.
Avoid holding SQLite writer transactions during runtime/network waits.
Index due, lease-expiry, active-run, history, and event queries.
Bound logs/events/receipts and enforce retention without breaking required audit/recovery evidence.
Report queue depth, oldest eligible age, planning lag, claim lag, start lag, active count, and database contention.
No command may mutate raw lifecycle rows directly.
Verification
Deterministic tests
virtual-time next/due computation;
wake-on-definition/cancel/shutdown;
immediate startup reconcile;
UTC and IANA timezone vectors;
DST gap/fold vectors;
clock forward/backward jumps;
sleep/wake and latest-only misfire;
seeded backoff/jitter;
retry exhaustion/quarantine;
cancellation races;
lease renewal/expiry/fencing;
duplicate scheduler processes;
delivery-only retry;
bounded batch/backpressure.
Integration and chaos
kill/restart at every crash boundary;
SQLite busy/locked/transient I/O failures;
runtime unavailable, slow, duplicate, lost, and out-of-order observations;
daemon shutdown with active work;
corrupt/unreadable definition or event data;
disk full during run/delivery/receipt commit;
sustained due-occurrence load and history retention.
Proposed SLO gates
Ratify exact targets from measured baselines, but require at minimum:
zero duplicate dispatches for one occurrence fence in certification;
zero silent missed eligible occurrences;
bounded p99 planning/start lag under the supported local load profile;
bounded recovery time after daemon restart;
bounded database growth and scheduler pass duration;
zero false-success outcomes under injected failures;
zero unbounded retry, log, event, or receipt growth.
Acceptance criteria
Production scheduling uses the injected clock/wake abstraction; tests use virtual time.
Startup, shutdown, definition changes, clock jumps, sleep/wake, timezone, and DST semantics are documented and executable.
Retry is failure-class-aware, bounded, persisted, and refuses ambiguous or unauthorized replay.
Cancellation and timeout races converge to one authoritative state.
Scheduler and occurrence fencing prevent duplicate dispatch by competing local processes.
The complete crash matrix passes without silent loss, duplicate execution, or false success.
Operator commands diagnose and safely reconcile every supported nonterminal/stuck state.
Load/SLO and retention evidence is attached to the exact release candidate.
Non-goals
Active-active distributed scheduling.
Multi-host consensus over SQLite.
Automatically retrying unknown external side effects.
Adding every RRULE feature or timezone policy in v1.
Bead packet
Create one P0 Bead mapped exactly to this issue. It depends on #855 for normative states/errors and the #816 foundation. It blocks conformance certification and production-ready claims. Split implementation into test-first child tasks for clock/timezone, retries, cancellation, leader/fencing, crash matrix, diagnostics, and load/retention; retain this issue as the public outcome.
Parent program: #854
Protocol dependency: #855
Foundation: #816
Outcome
Make the Coven automation scheduler deterministic, restart-safe, bounded, and diagnosable under real operating conditions: sleep/wake, clock changes, daylight-saving transitions, daemon restart, duplicate processes, slow or unavailable runtimes, cancellation races, delivery failure, and ambiguous side effects.
The completion criterion is not “the 60-second thread fired.” It is that every eligible occurrence reaches one explainable durable disposition without silent loss, duplicate execution, false success, or an unrecoverable stale lease.
Current implementation baseline
The landed scheduler already provides valuable foundations:
The remaining reliability contract is incomplete:
localtimezone is not an immutable IANA timezone binding;Time abstraction
Introduce an injected scheduler clock and wake source used by production and tests:
Requirements:
Timezone and DST contract
Replace ambiguous durable
localsemantics with an explicit versioned timezone binding:UTCand IANATZIDin the stable contract;localas compatibility input resolved to an exact IANA zone at activation/import where the platform can prove it;Ratify and vector-test safe v1 defaults:
Alternative gap/fold policies may be added later as explicit versioned variants; they must never be inferred.
Retry and failure classification
Define failure classes before adding automatic retry:
recovery_required, no automatic retry;Implement bounded exponential backoff with deterministic full jitter in production and seeded deterministic jitter in tests. Persist retry policy,
notBefore, attempt number, failure class, and exhaustion reason. Add a circuit/quarantine state for repeated failures so a broken routine does not create an unbounded storm.Cancellation and timeout
Lease, leadership, and fencing
Even for a local-first v1, prevent accidental duplicate schedulers:
Multi-host routing remains P2; this issue prevents unsafe accidental concurrency without pretending SQLite is a distributed consensus system.
Crash/restart matrix
Inject a crash or process stop after each consequential boundary:
For each point, restart must converge to exactly one durable, explainable disposition. Missing evidence must never become success, and an ambiguous mutating action must never be replayed automatically.
Backpressure and retention
Operator controls
Provide safe commands/actions for:
No command may mutate raw lifecycle rows directly.
Verification
Deterministic tests
Integration and chaos
Proposed SLO gates
Ratify exact targets from measured baselines, but require at minimum:
Acceptance criteria
Non-goals
Bead packet
Create one P0 Bead mapped exactly to this issue. It depends on #855 for normative states/errors and the #816 foundation. It blocks conformance certification and production-ready claims. Split implementation into test-first child tasks for clock/timezone, retries, cancellation, leader/fencing, crash matrix, diagnostics, and load/retention; retain this issue as the public outcome.