PD007 · neutron design brief · stage: accepted

Fan-out & Node Kinds — the n8n-Parity Ladder

"Catch up with n8n" is three differently-sized asks wearing one name. Most of the breadth needs no engine work at all; fan/merge needs neutron's decider to grow a frontier; and only n8n's per-item data model would be a true redesign — which we deliberately decline. The durable assay engine underneath is expected to change for none of it.

stage · accepted decided · tier 0 first — leaves, no engine risk decided · tier 1 = decider frontier + NEP-0006 bump, gated on a spike declined · n8n item model — loop-over-items node instead tracking · epic #462 · epic #463

1 · Execution today: one cursor

The decider replays history and follows a single cursor (currentId = outs[0].to). A branch evaluates its condition and picks one arm; the other never runs. Arms may converge (fan-in works); fan-out does not exist.

flowchart LR
  T[trigger] --> B{branch}
  B -->|true ✓| A[agent turn]
  B -.->|false — never runs| N[notify]
  A --> D[done]
  N -.-> D
  

Everything durable — retries, timers, approval parking, deterministic replay — is the assay engine's event log. The decider is a pure function: history in, commands out. That separation is what keeps this upgrade contained.

2 · The ladder

TierWhatTouchesEpic
0transform · http_request · wait · sub_workflow · error edges · per-node retry/timeout · typed approval responsesnew node kinds only — current walk executes them as ordinary activities#462
1fan (multi-out = all arms run) + join (wait-all, input = {predecessor: output})decider (cursor → frontier) · NEP-0006 addendum · validation · run overlay#463
2n8n item model (wires carry arrays, implicit per-item loops)every node, every expression, the run UI — declined; a loop-over-items node covers most of the need

3 · Tier 1: the frontier walk

flowchart LR
  T[trigger] --> F[fan]
  F --> P[draft post]
  F --> E[draft email]
  P --> J[join
waits for all] E --> J J --> A[approve]
PieceChange
deciderWalk a ready-set; several activities in flight; a node is ready when ALL inbound arms settled. Stays a pure replay function — ready-order derives from the existing topo order, so determinism holds.
NEP-0006Fan semantics, join node (wait-all first), joined-output naming for {{ node.x.y }}. Versioned graphs make it additive — published v1 graphs replay untouched.
assay engineExpected: nothing. It logs per-seq activities; nothing in the command contract says one-at-a-time. A two-pending-activities spike is the hard gate before building.
run UISeveral live nodes at once; step rail groups arms; node lifecycle vocabulary INACTIVE·PENDING·RUNNING·WAITING·COMPLETED·FAILED·CANCELLED.
validationJoin reachability — an arm that can skip a join must be declared or the join deadlocks.

4 · The honest n8n comparison

GapRealityCost
breadth of leaves400+ integrations — neutron's equivalent is the capability registry; the missing pieces are the generic kinds (tier 0)tier 0
fan / mergen8n runs arms interleaved in one process — the win is the shape, not raw speedtier 1
item modeln8n's true engine-level difference, and its main source of user confusiontier 2 — declined

5 · What the reference study already shipped

From the seven-tool set (~/forks/agentic-workflows): dify's floating config panel; n8n's quick-add "+", insert-on-wire and JSON import; langflow's edge reconnection; trigger-first starter tiles; canvas fit/center control. All live in v0.6.1-b21. Google ADK's contributions are PD008's subject.