Skip to content

feat(scheduled-tasks): implement one-time postponed tasks (Phase 1 of #771) - #846

Open
WXYZx wants to merge 7 commits into
open-mercato:mainfrom
WXYZx:feat/postponed-scheduled-tasks
Open

WXYZx wants to merge 7 commits into
open-mercato:mainfrom
WXYZx:feat/postponed-scheduled-tasks

Conversation

@WXYZx

@WXYZx WXYZx commented Aug 10, 2026

Copy link
Copy Markdown

Summary

Implements the Phase 1 vertical slice of .ai/specs/2026-08-01-postponed-tasks.md (approved design in #770): one-time postponed/scheduled tasks. Recurring schedules (.ai/specs/2026-08-01-recurring-tasks.md) are intentionally out of scope, per the sequencing in #771 ("implement postponed tasks first... after it is reviewed and ready, run recurring").

Closes part of #771 (postponed-task foundation only; recurring tracked separately).

Architecture mirrors the existing GitHub Automations feature as its own parallel module (no Automations code touched): project-local optional storage under .ai/cezar/ with atomic writes and per-entry salvage, a post-listen workspace coordinator with a single re-armed timer, a cross-process lease for mutations, durable reservation receipts, and ordinary launch through RunManager/RunStore with a synchronous flush before any run can be pumped so a crash can never lose or duplicate paid agent work.

What's included

  • packages/contract/src/scheduled-tasks.ts — wire schemas (definition, timing, template, runtime state, occurrences, request/response bodies), plus additive optional scheduledTask provenance on runRecordSchema.
  • packages/cezar/src/scheduled-tasks/ — storage (atomic JSON/ndjson, lease, salvage, compaction), IANA timing/preview calculation, coordinator, scheduler (bounded timer segments, crash-safe fire, startup reconciliation, Run-now consumption), task-template launch adapter.
  • packages/cezar/src/server/server.ts/api/v1/scheduled-tasks* route family (list/create/get/update/delete/pause/resume/run-now/preview, occurrence list/retry), coordinator/scheduler startup and shutdown wiring, scheduled-task-change SSE event.
  • packages/web/src/routes/scheduled-tasks/ — Scheduled list/detail/editor/history page, nav entry (clock icon, between Automations and Skills), SSE-driven refetch, run/group links, read-only/409 degradation states.
  • Tests mirroring the Automations suite's structure: storage salvage/atomic-write/lease, injected-clock scheduler, crash/reconciliation, task-template parity, route and contract-parity tests.

Known deviation from the spec (please weigh in)

The spec describes a Now/Later clock pill inside the existing New task composer. This PR does not touch the composer — scheduling is created from its own Scheduled editor instead, which accepts a workflow or single skill as the task source. This was a deliberate risk-reduction call to keep the composer's immediate-submit path (a hard compatibility surface: /new deep links, bookmarklets, existing shortcuts) completely untouched in this first PR. Consequences:

  • No composer-driven "Plan first → approve → save as scheduled" flow yet.
  • Duplicate opens a blank editor rather than pre-filling from the source definition.
  • Agent profile is a free-text field rather than the composer's populated picker.

Happy to follow up with the composer integration in a subsequent PR once the foundation itself is reviewed, if that's the preferred order.

Compatibility

  • POST /api/v1/runs, immediate New task, /new deep links/bookmarklets, workflow YAML, skill Markdown, and GitHub Automation wire shapes are unchanged.
  • All new storage/provenance is optional, additive, and .passthrough().
  • No new required config or CEZ_* variable.
  • A due occurrence always launches through the ordinary RunManager path — normal workspace/per-project capacity, worktree, and review rules stay authoritative.

Validation gate

Run locally on this branch:

  • npm run typecheck — pass (contract, client, server, web).
  • npm run build — pass (server, web, package-content check).
  • npm test — 5702/5706 passing. The 4 remaining failures are pre-existing and environment/locale-specific (git and Intl.NumberFormat emitting Polish-locale strings on the machine this was built on), reproduce identically on a clean upstream/main checkout, and are unrelated to this change: git-changes.test.ts (2, asserts English git error text) and directional-usage.test.tsx / agents-section.test.tsx (2, assert comma thousands-grouping).

Out of scope (tracked separately)

  • Recurring schedules (.ai/specs/2026-08-01-recurring-tasks.md).
  • Full real-browser end-to-end restart/crash journey and exhaustive accessibility sweep (spec's own Phase 2).
  • Composer Now/Later integration (see deviation above).

WXYZx and others added 7 commits August 10, 2026 19:02
Adds the closed wire schemas for the one-time scheduled-tasks API family, an
additive optional `scheduledTask` provenance field on RunRecord, and an
always-on `scheduledTasks` capability (spec 2026-08-01-postponed-tasks).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… adapter

Storage layer (atomic writes, per-entry salvage, lease-serialized re-read/merge,
append-only occurrences with compaction), a demand-independent workspace
coordinator, the single-timer workspace scheduler with bounded segments below
Node's timer horizon, crash-safe ordinary launch (provenance at record
construction + synchronous flush before pump), Run now consumption, and startup
reconciliation. Mirrors the GitHub Automations patterns as a separate feature.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…/RunStore

Adds a StartRunOptions carrying optional `scheduledTask` provenance and a
`defer`/`pumpQueue` split so the launch adapter can create records, flush them
synchronously, and only then make the queue pumpable — closing the crash window
where paid agent work would exist before its occurrence id is on disk.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nd startup wiring

Registers the project-scoped scheduled-tasks/occurrences routes (list, create,
get, update, delete, pause, resume, run-now, preview, occurrences, retry) with
lease-serialized mutations and 409 on contention; wires the coordinator +
workspace scheduler on the post-listen event with startup reconciliation; adds
the per-project store to ProjectContext; gitignores the new state files; and
records the routes in BACKWARD_COMPATIBILITY.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…oser serializer

Adds the mode-driven Scheduled route (list/detail/editor/history) with authoritative
timezone preview, run/group links, occurrence retry, SSE invalidation on
scheduled-task-change, and read-only/409 degradation; a ClockIcon Scheduled nav
item gated by the scheduledTasks capability; buildScheduledTaskTemplate beside
buildAutomationTask; and the api-client bindings. The New task composer's
immediate path is left byte-for-byte unchanged — the editor is self-contained.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Aug 10, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants