feat(flows): node registry + executor with topo-order dispatch (NF-2) #345

Merged
code-lead merged 1 commit from feat/323-nf2-registry-executor into main 2026-04-24 12:13:24 +00:00
Collaborator

Summary

First slice of the node-flows runtime. Lands a self-contained registry + executor under apps/server/src/domain/flows/ with zero touch-points to HTTP, infrastructure, or existing domain code.

  • types.ts — Graph/Plan/ExecutionContext shapes plus typed errors (FlowPlanError, ContextFrozenError, ContextMissError).
  • registry.tsMapRegistry with register/get/has/list/compile. compile(graph) validates node types, port-type compatibility (with any + wildcard * ports), detects cycles, and topo-sorts into layered waves via Kahn's algorithm. Ships the v1 built-in catalog: source, router.filter|switch|all|race|try, template.string, util.log|guard|delay.
  • executor.tsexecute(plan, registry, trigger, opts). Walks waves with Promise.all, wraps each node in a per-handler timeout (default 60 s, override via args.timeout_ms; util.delay is exempt), honours an external AbortSignal, propagates FILTER_DROP skips downstream, freezes every context write, and cascades errors → downstream skipped.

Test plan

  • 53 unit tests across registry.test.ts + executor.test.ts — topo ordering, fan-out, fan-in via router.all, router.race, router.filter pass/drop, router.switch matched-only-fires, template.string interpolation, util.guard false → flow error, util.delay timing, external AbortController cancel, per-node timeout, port-type mismatch rejection, cycle detection, dot-path resolution into upstream outputs, frozen-context invariant, unresolved-ref error.
  • bun test apps/server/src/domain/flows/ — 53 pass / 0 fail.
  • bun x turbo run typecheck --filter=@claude-hooks/server clean.
  • bun x biome check apps/server/src/domain/flows/ clean.

Out of scope

  • forge.* and agent.* node families (NF-3).
  • HTTP endpoints, event-log wiring, persisted flow definitions (NF-4+).
  • Dashboard UI for authoring graphs.

Closes #323

## Summary First slice of the node-flows runtime. Lands a self-contained registry + executor under `apps/server/src/domain/flows/` with zero touch-points to HTTP, infrastructure, or existing domain code. - **`types.ts`** — Graph/Plan/ExecutionContext shapes plus typed errors (`FlowPlanError`, `ContextFrozenError`, `ContextMissError`). - **`registry.ts`** — `MapRegistry` with `register/get/has/list/compile`. `compile(graph)` validates node types, port-type compatibility (with `any` + wildcard `*` ports), detects cycles, and topo-sorts into layered waves via Kahn's algorithm. Ships the v1 built-in catalog: `source`, `router.filter|switch|all|race|try`, `template.string`, `util.log|guard|delay`. - **`executor.ts`** — `execute(plan, registry, trigger, opts)`. Walks waves with `Promise.all`, wraps each node in a per-handler timeout (default 60 s, override via `args.timeout_ms`; `util.delay` is exempt), honours an external `AbortSignal`, propagates `FILTER_DROP` skips downstream, freezes every context write, and cascades errors → downstream `skipped`. ## Test plan - [x] 53 unit tests across `registry.test.ts` + `executor.test.ts` — topo ordering, fan-out, fan-in via `router.all`, `router.race`, `router.filter` pass/drop, `router.switch` matched-only-fires, `template.string` interpolation, `util.guard` false → flow error, `util.delay` timing, external `AbortController` cancel, per-node timeout, port-type mismatch rejection, cycle detection, dot-path resolution into upstream outputs, frozen-context invariant, unresolved-ref error. - [x] `bun test apps/server/src/domain/flows/` — 53 pass / 0 fail. - [x] `bun x turbo run typecheck --filter=@claude-hooks/server` clean. - [x] `bun x biome check apps/server/src/domain/flows/` clean. ## Out of scope - `forge.*` and `agent.*` node families (NF-3). - HTTP endpoints, event-log wiring, persisted flow definitions (NF-4+). - Dashboard UI for authoring graphs. Closes #323
feat(flows): node registry + executor with topo-order dispatch (NF-2)
All checks were successful
qa / qa (pull_request) Successful in 4m9s
qa / dockerfile (pull_request) Successful in 14s
c2f930eb02
Adds the first slice of the node-flows runtime under apps/server/src/domain/flows/:
  - `types.ts`      — Graph/Plan/ExecutionContext shapes + typed errors.
  - `registry.ts`   — MapRegistry with `compile(graph)` (type-check, port-type
                      compatibility, Kahn-topo waves) and the v1 built-in
                      node catalog (`source`, `router.*`, `template.string`,
                      `util.log|guard|delay`).
  - `executor.ts`   — layer-by-layer `execute()` with per-node timeout, external
                      AbortController, FILTER_DROP skip-propagation, frozen
                      append-only context, error-downstream-skipped semantics.
  - Test coverage: 53 unit tests across both files — topo ordering, fan-out,
                   fan-in, router.race + switch + filter branches, port-type
                   rejection, cycle detection, dot-path resolution, frozen
                   context, timeout + external cancel, guard abort.

Closes #323

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
code-lead deleted branch feat/323-nf2-registry-executor 2026-04-24 12:13:26 +00:00
Sign in to join this conversation.
No reviewers
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!345
No description provided.