Skip to main content

Implementation Plan: Scheduled Work Updates

Feature ID: scheduled-updates Spec: ./spec.md Status: Done (Retrospective) Last updated: 2026-05-01


1. Architecture Summary

2. Tech Choices

ConcernChoiceRationale
Cron runtimeTrigger.dev schedules.taskPrinciple IV; survives restarts, dashboards, retries
Mutual exclusionSQL CAS (UPDATE … WHERE nextRunAt IS NOT NULL)The schedule row IS the lock; no Redis or DistributedTaskLock
DriftscheduledFor anchor preserved at claimBounded drift across the lifetime of the schedule
BillingUsageLedgerEntry rows on completionPer-run accounting, separate from plan caps

3. Data Model

  • work_schedules table with columns: id, workId, userId, cadence, status, nextRunAt, scheduledFor, lastRunAt, lastRunStatus, failureCount, maxFailureBeforePause, alwaysCreatePullRequest, billingMode, providerOverrides, createdAt, updatedAt.
  • usage_ledger table for per-run accounting.
  • Migrations:
    • Initial table creation.
    • Addition of every_3_hours, every_8_hours, every_12_hours to the cadence enum (additive).
    • Addition of scheduledFor column for drift correction (nullable).
    • Addition of providerOverrides column (jsonb, nullable).

4. API Surface

MethodEndpointDescription
GET/api/works/:id/scheduleRead schedule + allowed cadences
PUT/api/works/:id/scheduleCreate/update schedule
DELETE/api/works/:id/scheduleCancel schedule (resets to disabled)
POST/api/works/:id/schedule/runRun-now (preserves slot if ahead)

5. Plugin / Web / CLI

  • Web: schedule settings form on the work detail page; "Run Now" button; status badges.
  • CLI: ever-works work schedule … commands wrap the API.
  • Plugin facades: schedule resolution honours providerOverrides — capabilities are looked up with the override-aware scope.

6. Background Jobs

The dispatcher cron task is the entry point. It uses no separate locks (see work-schedule-dispatcher.md deep-dive for the reasoning).

7. Security & Permissions

  • All endpoints require work edit rights.
  • Cron tasks run with elevated DB access (no per-user auth scope).
  • Schedule rows are readable by work owners and members.

8. Observability

  • Per-tick summary returned to Trigger.dev with counts + per-schedule outcomes.
  • Auto-pause emits a notification via NotificationsService.
  • Activity log entries on each dispatch (work_scheduled_run).

9. Risks & Mitigations

RiskMitigation
Slow tick overlaps next tickCAS claim ensures at-most-once dispatch per slot
Worker crash mid-generationZombie recovery flips stuck schedules to ERROR after timeout
Drift accumulationscheduledFor anchor prevents drift across runs
Billing leak on cancelUsage ledger entries only added on completion, not on dispatch

10. Constitution Reconciliation

See spec.md §9 — all gates satisfied.

11. References

  • Spec: ./spec.md
  • Internal architecture: docs/agent-services/work-schedule-dispatcher.md
  • Cross-cutting: architecture/trigger-integration §10 (cron dispatcher task), architecture/cache (CAS claim contract uses the same TypeORM tier as the cache table)
  • Implementation files: see spec §10.