Skip to content

feat(triggers): add the triggers package with cron, interval, and polling triggers - #820

Merged
sroussey merged 1 commit into
mainfrom
claude/optimistic-goldberg-d74u5n-triggers
Aug 16, 2026
Merged

feat(triggers): add the triggers package with cron, interval, and polling triggers#820
sroussey merged 1 commit into
mainfrom
claude/optimistic-goldberg-d74u5n-triggers

Conversation

@sroussey

Copy link
Copy Markdown
Collaborator

Rebuilt of #679 on current main, carrying the triggers work and nothing else. Supersedes #679.

Why a new branch

#679's payload sits inside a squashed PR merge (7e6ec7f35, "Validate trigger binding bounds and reject a reused runConfig.signal (#792)") spanning 223 files. So the branch also carried task-graph cache, ConditionalTask and FetchUrlTask changes unrelated to triggers — 231 unrelated files against 17 real ones.

That made it unmergeable by either route:

rebase merge
conflicting files 96 96 (84 mechanical CHANGELOG/package.json/lock)
substantive hunks 29, of which 14 two-sided

The two-sided hunks concentrate in RunPrivateCacheRepo / FsFolderTaskOutputRepository / TaskOutputRepository — the clearRun blob-ref path main reworked in "stop clearRun dangling blob refs". A wrong resolution there is invisible until a crash-resume. None of it belongs to this feature, so none of it is here.

What this branch contains

  • packages/triggersBaseTrigger, CronTrigger, IntervalTrigger, PollingTrigger, a UTC CronSchedule, and the Workflow binding layer.
  • Its six test files under packages/test/src/test/trigger/.
  • Workspace wiring: the dependency and tsconfig project reference in test and workglow, plus the workglow re-export and auto-bootstrap install. Vitest projects and test sections are derived, so they need no edit.

One task-graph change, carried deliberately

WorkflowRunConfig.signal, bridged onto the run's own controller by WorkflowRunContext.linkSignal. This is a real dependency, not a leftover: a trigger must cancel exactly the run its own fire started, and Workflow.abort() trips the single current-run controller — it would cancel whichever run happens to be current, which is the wrong granularity once two triggers drive one workflow.

It is additive (a new optional field, a new method, one line in run()), and its two Workflow.test.ts cases come with it. linkSignal uses a removable listener rather than AbortSignal.any, whose composite is retained per fire.

Verification

check result
bun scripts/test.ts trigger vitest 180/180
bun scripts/test.ts graph vitest 507/507 (incl. the 2 new runConfig.signal cases)
bun scripts/test.ts task-graph vitest 981/981
bun run build:types 42/42
bun run format clean

Diff is 34 files against main, with no conflicts.

The stacked review fixes in #812 have been rebased onto this branch (trigger 187/187) and retargeted here.


Generated by Claude Code

…ling triggers

Rebuilt on current main from the triggers work alone. The previous branch
carried its payload inside a squashed PR merge spanning 223 files, so it
also held task-graph cache, ConditionalTask and FetchUrlTask changes that
have nothing to do with triggers — 231 unrelated files against 17 real
ones. Merging that into main produced 29 conflict hunks, 14 of them
two-sided in the clearRun blob-ref path, where a wrong resolution is
invisible until a crash-resume. None of that belongs to this feature, so
none of it is here.

The package: BaseTrigger, CronTrigger, IntervalTrigger, PollingTrigger, a
UTC CronSchedule, and the Workflow binding layer, plus its six test files,
the workspace wiring (dependency + tsconfig references in `test` and
`workglow`) and the `workglow` re-export and auto-bootstrap install.

One task-graph change is carried across because the feature genuinely
depends on it, not as a leftover: `WorkflowRunConfig.signal`, bridged onto
the run's own controller by `WorkflowRunContext.linkSignal`. A trigger has
to cancel exactly the run its own fire started; `Workflow.abort()` trips
the single current-run controller and would cancel whichever run happens to
be current, which is the wrong granularity once two triggers drive one
workflow. It is additive — a new optional field, a new method, and one
line in `run()` — and its two Workflow tests come with it.

Verified on this branch: trigger 180/180, graph 507/507 (including the two
new runConfig.signal cases), task-graph 981/981, build:types 42/42,
prettier clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lgxtp7mQECdh7F2UT9CVwN
throw error;
} finally {
// Identity check: a later fire may already have claimed the tail.
if (workflowRunChains.get(workflow) === chain) workflowRunChains.delete(workflow);
@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 60.64% 39252 / 64721
🔵 Statements 60.13% 41198 / 68507
🔵 Functions 61.23% 7609 / 12426
🔵 Branches 48.96% 20077 / 41000
File CoverageNo changed files found.
Generated in workflow #3183 for commit 300724d by the Vitest Coverage Report Action

@sroussey
sroussey merged commit 0f1ae49 into main Aug 16, 2026
15 checks passed
@sroussey
sroussey deleted the claude/optimistic-goldberg-d74u5n-triggers branch August 24, 2026 18:50
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