Skip to content

feat(workflows): schedule workflows and inspect each occurrence's run - #36

Draft
Igloczek wants to merge 3 commits into
workflows/28-parallel-attentionfrom
workflows/29-scheduling
Draft

Igloczek wants to merge 3 commits into
workflows/28-parallel-attentionfrom
workflows/29-scheduling

Conversation

@Igloczek

@Igloczek Igloczek commented Oct 9, 2026 •

Copy link
Copy Markdown

Closes #29 · Parent spec #3 · Stack layer 5/5 (base: #35 workflows/28-parallel-attention)

Problem

Scheduled workflow occurrences passed input straight to start and left no record linking an occurrence to its run. The existing Scheduled tasks controls couldn't select a workflow, and users couldn't see what each occurrence actually started.

What this adds

  • Generic schedule-target contribution: WebPlugin.scheduleTargets adds a "Runs" choice (a prompt, or a plugin target) to Settings → Scheduled tasks. A target is offered only when the environment's catalog publishes it, and core scheduling imports no workflow code. Prompt schedules are unchanged.
  • Workflow target:
    • Project, saved workflow ("Currently saved: revision N" plus runnable status and reasons), workspace, and a bounded task.
    • The editor states the truth about revisions: "Each occurrence starts the workflow as it is saved when that occurrence runs, not necessarily revision N."
    • No required-input contract is invented.
  • Same start path as a manual start: each occurrence calls the shared saved-workflow start (startCatalog), keyed by its durable occurrence identity. It checks the stored result first, including legacy IDs, so redelivery or a lost ack gives one run and distinct occurrences give distinct runs. Permission ceilings and the pending-occurrence pipeline are unchanged. The host scheduler remains the only timing owner.
  • Occurrence history (Run history):
    • Bounded (20 entries plus a "more" flag, never a fake total) and redacted like every other workflow read.
    • Each receipt is linked to its exact run under the project it was recorded in, so history survives project edits.
    • Dispatch status (pending, dispatched, failed) is shown separately from workflow status (running, needs your decision, completed, …).
    • Revisions come from each run's own snapshot. A recreated schedule ID does not inherit old receipts.
    • Open run is withheld when that project no longer exists.
  • Plugin removal: the row stays saved and shows an actionable "unavailable" state. Timing, pause, and delete still work, and history returns when the plugin returns. Host edits no longer echo dispatchTarget; the server keeps the stored one.
  • Docs: "Schedule a workflow" in docs/user/workflows.md, plus docs/user/project-settings.md.

Validation

  • Server (Bun):
    • WorkflowsScheduling.integration.test.ts covers:
      • two authenticated environments
      • create, edit, pause, run-now
      • redelivery, and a dispatch cut off after commit
      • revision changes between occurrences, and restart
      • project relocation keeping run links; delete and recreate starting with empty history
      • plugin removed → edit timing → reinstall → run-now
      • prompt schedules alongside workflow schedules
      • a scheduled run following the same thread, report, gate, and completion path as a manual start
      • a scheduled parallel review forking reviewer threads
    • WorkflowsCatalogRedaction covers schedule history with a known secret.
    • The Schedule, ScheduleCatalog, PluginScheduleReceipt, PluginScheduledCeiling, PluginDiscoveryAndSchedule, PluginHost, OrchestratorMcpToolkit, and ScheduledTaskService suites pass.
  • Web:
    • WorkflowSchedule.integration.test.tsx covers the editor, history, Open run, the removed-project state, and the read-only and disconnected states.
    • PluginClientPermissions passes.
    • The unit tests in scheduleTargetLogic.test.ts use no mocks.
  • Static checks: typecheck, lint, and fmt are clean for touched packages. The only exception is the pre-existing binCli.ts TS2345.

Independent review

Three rounds by a separate Claude Opus 5.5 reviewer. Fixed:

  • history losing run links after a project edit
  • unredacted history titles and reasons
  • extra history re-reads
  • a mock-heavy dialog test, replaced with pure logic plus a real-server check
  • recreated IDs inheriting old receipts

Final verdict: APPROVED 5e8694119056373dd49a50c7cd562b14fddce3c2.

UI evidence

Real-browser verification is pending; the T3 Browser panel was unavailable.

Limitations

  • Plugin targets support "At a time" and "Every interval" only; webhook triggers stay prompt-only.
  • Runs left behind in a project the schedule moved away from refresh only when the schedule row changes, the dialog reopens, or the user presses Refresh.
  • The occurrence history read filters receipts by task_id without a dedicated index (capped, dialog-only). A migration was deliberately avoided.
  • Pre-existing, not changed here: the core scheduledTasks.upsert RPC accepts dispatchTarget (including dispatchLimits) from operate-scoped callers. This predates the stack and is worth a separate issue.

Implemented by Claude Opus 5.5 implementation agents and reviewed by an independent Claude Opus 5.5 agent (gilfoyle), orchestrated in Claude Code running in T3 Code.

🤖 Generated with Claude Code

@Igloczek
Igloczek added this pull request to stack #32 October 9, 2026 10:05
@Igloczek
Igloczek marked this pull request as ready for review October 10, 2026 13:07
@Igloczek
Igloczek force-pushed the workflows/29-scheduling branch from 5e86941 to f09807b Compare October 10, 2026 14:00
Igloczek and others added 3 commits October 10, 2026 20:02
Adds a generic plugin schedule-target contribution to the existing
Scheduled tasks controls, which the workflows plugin fills with a saved
workflow, workspace, and bounded task. Each occurrence starts through the
same saved-workflow start service keyed by its durable occurrence
identity, and a bounded occurrence history links each dispatch to its
exact run with dispatch and workflow status kept separate. The host
scheduler remains the only timing owner.

Refs #29

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Link schedule history to each occurrence's recorded project, refresh
history only on real receipt or run state changes with a lighter read,
cover the host dialog's target routing, keep recreated schedules from
inheriting old receipts, and align the unavailable-target guidance.

Refs #29

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…real seams

Redact titles, reasons, and receipt errors in schedule history, move the
host dialog's plugin submission decision into tested pure logic, keep
the server as the owner of existing dispatch targets, and withhold Open
run for runs whose project was removed.

Refs #29

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

Schedule workflows and inspect each occurrence's run

1 participant