Wire Reference — Contracts, Ports, and Matching

Scoped reference for Wire's type surface: contracts, labeled port clauses, sum groups, and the port-key match rule `=>` uses.


On this page
  1. Nodes, Ports, And Edges
  2. Port Syntax
  3. Port Keys
  4. Cardinality
  5. Sum Groups
  6. Empty Boundary Sides

Wire Reference — Contracts, Ports, and Matching

Contracts are named typed interfaces. Ports are labeled node-boundary slots typed by contracts. => connects output ports to input ports when their contract and label match exactly.

Nodes, Ports, And Edges

A node declaration supplies both graph identity and a typed boundary:

node classify
  <- evidence: EvidenceSet;
  -> accepted: AcceptedSet;
  -> rejected: RejectedSet;
  = @review.classify (evidence);

The identifier classify names the node. The <- clauses declare input ports. The -> clauses declare output ports. The body after = is the implementation behind that boundary.

The graph edge operator connects already-declared ports:

source
  => classify
classify
  => reviewer

An edge never evaluates an expression and never changes payload shape. Boundary adaptation belongs to the producer node’s egress adapter, the consumer node’s ingress adapter, or an explicit pure node between them.

flowchart LR
    ProducerOut[producer output port<br/>label + contract]
    ConsumerIn[consumer input port<br/>same label + compatible contract]
    ProducerOut ==>|=>| ConsumerIn

Port Syntax

<- label: Contract;
-> label: Contract;
-> ok: Value | error: ExecutorError;

Authored ports require labels. Labels are routing identity. A labeled port never matches an unlabeled port, and there is no wildcard label.

Port Keys

A port key is:

(direction, contract, label)

=> matches the contract and label, with direction reversed: output to input. Each endpoint port may participate in at most one edge created by a connect expression.

Boundary adaptation belongs to node ingress/egress adapters or to explicit pure nodes, not to the edge. => only checks that an already-produced output port resource satisfies a consumer input obligation.

Cardinality

All authored ports are cardinality-one at the graph boundary. During open composition, unmatched inputs and outputs remain exposed as boundary obligations. If => would add two edges out of the same output or two edges into the same input, the composition is rejected. Implicit fan-out and implicit fan-in are never valid Wire topology.

In a closed actualized graph, every actualized input port instance must have exactly one producer edge. Every actualized output port instance must be consumed exactly once: by one edge to a downstream input, or by an explicit terminal egress, sink, or exported boundary discharge.

=> does not duplicate output resources. If one output must feed several consumers, author a fresh generated node family or an explicit fan-out, sharing, persistence, broadcast, projection, or record↔ports adapter node that consumes the source once and produces fresh output port instances:

node fan_out_score
  <- score: Score;
  -> for_audit: Score = score;
  -> for_decision: Score = score;

Wire no longer has <- [Contract] implicit list aggregation. To gather many values, author an explicit transformation node:

node merge
  <- mechanism: AnalysisFragment;
  <- timing: AnalysisFragment;
  <- beneficiaries: AnalysisFragment;
  -> merged: AnalysisFragment;
  = @review.report_merge ({
    fragments = [mechanism, timing, beneficiaries];
  });

Sum Groups

Sum groups are output-only:

-> value: AnalysisFragment | error: ExecutorError;

Exactly one variant fires per evaluation. Each variant has its own label and contract and matches downstream ports independently.

Empty Boundary Sides

Executor nodes may have empty input or output port sets when their registered executor projection admits that shape:

node log_event
  <- event: Event;
  = @artifact.log (event);

Wire does not assign special source/sink semantics in syntax. Empty boundary sides are ordinary typed interface facts. Terminal behavior comes from the registered executor or the explicit execution boundary that consumes or discharges the adjacent port instances.