Flows YAML — linear executor with parallel block + audit writes #1064

Closed
opened 2026-05-10 15:38:50 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As the platform, I want a linear step-by-step executor with an optional parallel: block, so that the common case (sequence of ops) is trivial to read while rare fan-out cases stay expressible.

Resolves audit finding §1.1.3 (DAG model unused; wave executor + topo sort + cycle validator pay for capability nobody uses).

Acceptance criteria

Sequential execution

  • apps/server/src/domain/flows-yaml/executor.ts runs steps in order.
  • Per-step lifecycle: evaluate if: → resolve with: interpolations → run op → record flow_node_runs row.
  • Step error fails the flow unless continue-on-error: true.
  • if: false → step skipped, recorded with status skipped, flow continues.

Parallel block

  • steps[].parallel: [step, step, …] runs sub-steps concurrently with Promise.all.
  • Sub-step outputs visible to subsequent steps via steps.<parent_id>.outputs.<sub_id>.….
  • Any sub-step error fails the parallel block (default) or is captured (continue-on-error per sub-step).

Audit

  • flow_runs row opened on flow start (status running), closed on flow end (completed/failed/cancelled).
  • flow_node_runs rows hold step status, duration, output JSON, error JSON.
  • Schema rename: flow_node_runs.node_*step_* (Drizzle migration).
  • New column flow_runs.internal_trigger_source records parent flow/task id when fired by task.completed etc.

Determinism

  • When multiple flows match, executor sorts by priority desc then name asc.
  • concurrency.group (string, expression-evaluated) gates with mutex; cancel-in-progress: true aborts the in-flight run.

Tests

  • Sequence runs in order; mid-failure halts; continue-on-error keeps going.
  • Parallel runs concurrently (fake-timers assertion).
  • concurrency blocks second start until first finishes.
  • Audit rows match expected status sequence.

Out of scope

  • Replacing the legacy wave executor (covered by #flows-14 cutover).
  • Internal-trigger fan-out (covered by #flows-5).

References

  • Spec: docs/specs/flows-yaml.md §8.
  • Replaces: apps/server/src/domain/flows/executor.ts after cutover.
## User story As the platform, I want a linear step-by-step executor with an optional `parallel:` block, so that the common case (sequence of ops) is trivial to read while rare fan-out cases stay expressible. Resolves audit finding §1.1.3 (DAG model unused; wave executor + topo sort + cycle validator pay for capability nobody uses). ## Acceptance criteria ### Sequential execution - [ ] `apps/server/src/domain/flows-yaml/executor.ts` runs steps in order. - [ ] Per-step lifecycle: evaluate `if:` → resolve `with:` interpolations → run op → record `flow_node_runs` row. - [ ] Step error fails the flow unless `continue-on-error: true`. - [ ] `if:` false → step skipped, recorded with status `skipped`, flow continues. ### Parallel block - [ ] `steps[].parallel: [step, step, …]` runs sub-steps concurrently with `Promise.all`. - [ ] Sub-step outputs visible to subsequent steps via `steps.<parent_id>.outputs.<sub_id>.…`. - [ ] Any sub-step error fails the parallel block (default) or is captured (continue-on-error per sub-step). ### Audit - [ ] `flow_runs` row opened on flow start (status `running`), closed on flow end (`completed`/`failed`/`cancelled`). - [ ] `flow_node_runs` rows hold step status, duration, output JSON, error JSON. - [ ] Schema rename: `flow_node_runs.node_*` → `step_*` (Drizzle migration). - [ ] New column `flow_runs.internal_trigger_source` records parent flow/task id when fired by `task.completed` etc. ### Determinism - [ ] When multiple flows match, executor sorts by `priority` desc then `name` asc. - [ ] `concurrency.group` (string, expression-evaluated) gates with mutex; `cancel-in-progress: true` aborts the in-flight run. ### Tests - [ ] Sequence runs in order; mid-failure halts; `continue-on-error` keeps going. - [ ] Parallel runs concurrently (fake-timers assertion). - [ ] `concurrency` blocks second start until first finishes. - [ ] Audit rows match expected status sequence. ## Out of scope - Replacing the legacy wave executor (covered by #flows-14 cutover). - Internal-trigger fan-out (covered by #flows-5). ## References - Spec: `docs/specs/flows-yaml.md` §8. - Replaces: `apps/server/src/domain/flows/executor.ts` after cutover.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#1064
No description provided.