AGPL-3.0-or-later · forever.

the flow

Two doors, one graph

Tasks link through two doors: with binds values, after orders effects. The engine reads those bindings and builds the run graph · nothing else creates an edge.

Defined by spec/03 · the DAG

The two doors

with: binds a value and IS a data edge · after: orders on outcome and IS a control edge. Nothing else creates an edge; there is no dependency list to maintain beside the file.

with · a value edgesource
think:  with:    gather: ${{ tasks.gather.output }}  infer:    prompt: |      Summarize · ${{ with.gather }}
after · a control edgesource
announce:  after: { changelog: success }  invoke:    tool: "nika:notify"

The edge kinds

The run graph speaks a closed set of edge kinds: value bindings, the two observations, control, recovery and the reserved finally. Unknown kinds are reader-tolerated by law · new ones arrive with the spec.

  • valuea with binding referencing a task output · carries the binding name
  • terminal-observationa status or timing read in with · settles with the producer
  • failure-observationan error read in with · flows only when the producer failed
  • controlan after entry · carries its gate predicate
  • recoveryan on_error.recover reference · a parking read, not an ordering edge
  • finallyW5reserved · named so the enum is complete before the trace wave gives cleanup identity

real nika inspect payloads per kind land with the first W2+ release train (engine captures are release-gated by law) · until then every kind above links its conformance fixtures through the matrix below.

The gate predicates

An after entry gates on producer state: succeeded, failed, skipped or terminal. The full producer-status by predicate matrix is fixture-proven upstream · the site replays it, never re-derives it.

  • successfire when the producer completed clean
  • failurefire when the producer failed terminally
  • skippedfire when the producer was gated out
  • terminalfire when the producer reached any terminal state

The gate, exhaustively

Producer state by consumer edge form: 40 cells, 35 run against the reference model (the spec authors every verdict), 5 statically dead. Pick a cell; the site replays the fixture truth, it never re-derives it.

producer ↓ · form →with-valuewith-statuswith-errorafter-successafter-failureafter-skippedafter-terminalwhen-truewhen-falseno-edge
success
failure
skipped
cancelled

Waves

The engine reads every edge and runs Kahn fronts: tasks with no unmet producer start together, each wave as wide as the graph allows. max_parallel caps a fan-out politely · fail_fast decides whether one failure drains the batch · when: is business logic AFTER the gate admits a task, never the gate itself.

Decisions

ratified · ships with the decisions wave: nika:decide and the Decision IR join this page when the resync brings the W-DEC canon.