NF-2: Node registry + executor (no dispatch yet) #323

Closed
opened 2026-04-24 11:29:50 +00:00 by code-lead · 0 comments
Collaborator

As the platform, I want a typed node registry and a graph executor so that flows can be run against a TriggerEvent in unit tests, without touching HTTP or persistence.

Acceptance criteria

Registry

  • apps/server/src/domain/flows/registry.ts — declarative registry with typed input/output ports per node type.
  • Initial node types: source, router.filter, router.switch, router.all, router.race, router.try, template.string, util.log, util.guard, util.delay.
  • Port-type compatibility table enforced at load time.

Executor

  • apps/server/src/domain/flows/executor.ts — topological walker. Graph load builds a frozen plan; per-dispatch run walks it.
  • Context is an append-only ExecutionContext map keyed by node_id → port → value.
  • Per-node timeout (default 60 s; override via args.timeout_ms).
  • router.try wraps a branch and converts throws into a downstream err edge.
  • AbortSignal propagated; cancel refuses to fire the next wave.

Tests

  • 40+ unit tests covering: topo order, parallel fan-out, fan-in via router.all, router.race cancel-losers, error propagation, timeout, cancel, port-type mismatch rejection, cycle rejection.

Out of scope

  • forge.* and agent.* node implementations — NF-3.
  • SQLite persistence — NF-4.
  • HTTP surface — NF-7.

References

As the platform, I want a typed node registry and a graph executor so that flows can be run against a `TriggerEvent` in unit tests, without touching HTTP or persistence. ## Acceptance criteria ### Registry - [ ] `apps/server/src/domain/flows/registry.ts` — declarative registry with typed input/output ports per node type. - [ ] Initial node types: `source`, `router.filter`, `router.switch`, `router.all`, `router.race`, `router.try`, `template.string`, `util.log`, `util.guard`, `util.delay`. - [ ] Port-type compatibility table enforced at load time. ### Executor - [ ] `apps/server/src/domain/flows/executor.ts` — topological walker. Graph load builds a frozen plan; per-dispatch run walks it. - [ ] Context is an append-only `ExecutionContext` map keyed by `node_id → port → value`. - [ ] Per-node timeout (default 60 s; override via `args.timeout_ms`). - [ ] `router.try` wraps a branch and converts throws into a downstream `err` edge. - [ ] `AbortSignal` propagated; cancel refuses to fire the next wave. ### Tests - [ ] 40+ unit tests covering: topo order, parallel fan-out, fan-in via `router.all`, `router.race` cancel-losers, error propagation, timeout, cancel, port-type mismatch rejection, cycle rejection. ## Out of scope - `forge.*` and `agent.*` node implementations — NF-3. - SQLite persistence — NF-4. - HTTP surface — NF-7. ## References - Spec: [`specs/node-flows.md`](../src/branch/main/specs/node-flows.md) § Execution semantics. - Depends on NF-1 (#322).
Sign in to join this conversation.
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#323
No description provided.