Description
ListWorkflowRunsParams.status accepts a single WorkflowRunStatus, with no array and no negation:
// @workflow/world@5.0.0-beta.27 — dist/runs.d.ts:154
export interface ListWorkflowRunsParams {
workflowName?: string;
status?: WorkflowRunStatus;
pagination?: PaginationOptions;
resolveData?: ResolveData;
}
So there is no supported way to ask a World for the runs that are not terminal. A caller must restate the non-terminal set itself and issue one paginated list() per status.
reenqueueActiveRuns already does exactly that:
// dist/recovery.js:15
for (const status of ['pending', 'running']) {
...
const page = await runs.list({ status, resolveData: 'none', ... });
The vocabulary to express this cleanly already exists in the same module:
// dist/runs.d.ts:12-19
export declare const TerminalWorkflowRunStatusSchema: z.ZodEnum<{ completed; failed; cancelled }>;
export declare const TERMINAL_WORKFLOW_RUN_STATUSES: ("completed" | "failed" | "cancelled")[];
export declare function isTerminalWorkflowRunStatus(status: string): status is TerminalWorkflowRunStatus;
and WorkflowRunSchema's discriminated union already names the complement as its non-final branch (status: z.enum(['pending', 'running']), dist/runs.js:120).
Impact
Any consumer that reconciles run state at startup or on a schedule must hardcode the runtime's status set, and that coupling is invisible to schema-level drift checks. workflow_runs.status is a Postgres enum, so changing its labels alters neither information_schema.columns nor any column type:
0004_remove_run_pause_status.sql removed the paused label and renamed the replacement type back to status.
0015_move_enums_to_workflow_schema.sql moves status, step_status, and wait_status from public into the workflow schema.
Both pass a column-level fingerprint untouched, so a consumer holding a hardcoded non-terminal list would silently select the wrong set afterward rather than failing loudly.
This is the same runs.list({ status, ... }) surface that #2978 identifies as unscoped in startup recovery.
Proposed direction
Let the caller express the set rather than restate it — for example status?: WorkflowRunStatus | WorkflowRunStatus[], or a terminal?: boolean discriminator implemented over the existing TERMINAL_WORKFLOW_RUN_STATUSES. Either keeps ownership of the status vocabulary inside the package, and would let reenqueueActiveRuns drop its per-status loop.
Happy to open a PR if you have a preferred shape.
Checked against @workflow/world@5.0.0-beta.27 and @workflow/world-postgres@5.0.0-beta.34.
Description
ListWorkflowRunsParams.statusaccepts a singleWorkflowRunStatus, with no array and no negation:So there is no supported way to ask a World for the runs that are not terminal. A caller must restate the non-terminal set itself and issue one paginated
list()per status.reenqueueActiveRunsalready does exactly that:The vocabulary to express this cleanly already exists in the same module:
and
WorkflowRunSchema's discriminated union already names the complement as its non-final branch (status: z.enum(['pending', 'running']),dist/runs.js:120).Impact
Any consumer that reconciles run state at startup or on a schedule must hardcode the runtime's status set, and that coupling is invisible to schema-level drift checks.
workflow_runs.statusis a Postgres enum, so changing its labels alters neitherinformation_schema.columnsnor any column type:0004_remove_run_pause_status.sqlremoved thepausedlabel and renamed the replacement type back tostatus.0015_move_enums_to_workflow_schema.sqlmovesstatus,step_status, andwait_statusfrompublicinto theworkflowschema.Both pass a column-level fingerprint untouched, so a consumer holding a hardcoded non-terminal list would silently select the wrong set afterward rather than failing loudly.
This is the same
runs.list({ status, ... })surface that #2978 identifies as unscoped in startup recovery.Proposed direction
Let the caller express the set rather than restate it — for example
status?: WorkflowRunStatus | WorkflowRunStatus[], or aterminal?: booleandiscriminator implemented over the existingTERMINAL_WORKFLOW_RUN_STATUSES. Either keeps ownership of the status vocabulary inside the package, and would letreenqueueActiveRunsdrop its per-status loop.Happy to open a PR if you have a preferred shape.
Checked against
@workflow/world@5.0.0-beta.27and@workflow/world-postgres@5.0.0-beta.34.