Draft
An immutable, inspectable dataflow graph that captures a distributed computation without running it.
Think of a Draft as a recipe, not a meal. It records what should happen — a dependency graph of named operations — but touches no data and invokes no code. This lets a planner inspect, rewrite, and optimise the graph before committing to execution (E-2 rewrites, E-3 cost model, E-5 incremental execution, G2–G5 DAG consolidation).
Structure — dependency DAG
A Draft is a directed acyclic graph of DraftNodes. Each node wraps a DraftStage and carries the set of NodeIds it depends on (DraftNode.predecessors). A linear pipeline — built by chaining map/filter/embroider — is the degenerate path: each node has exactly one predecessor.
Building a Draft
Start with Warp.shuttle, then chain map, filter, and optionally embroider:
val draft: Draft<ByteArray> = Warp.shuttle(OpId("docs"))
.map(OpId("score"))
.filter(OpId("above-threshold"))
.embroider(OpId("rank"))Inspecting a Draft
nodes — all DraftNodes in topological order, with predecessor edges.
stages — topological-order view of stage types; backward-compatible with E-5 consumers (ConvergentExecution) that iterate the stage sequence.
isMonotone —
truewhen every stage is CoordinationKind.Free; no consensus needed. The planner can run the whole pipeline coordination-free.embroideries — all DraftStage.Embroider nodes in topological order. A path has at most one; G2
combinecan introduce more.embroidery — convenience accessor for the single DraftStage.Embroider, or
nullif none. Equivalent toembroideries.singleOrNull().
The no-execution guarantee
A Draft stores only symbolic OpIds — the names of registered operations. It has no access to an OpRegistry and no mechanism to invoke an Op. Nothing executes until E-5 provides a runtime.
Type Parameters
phantom type parameter representing the element type the pipeline would produce at execution time. Not instantiated in E-1; present for forward compatibility with E-5 typed wrappers.
See also
Samples
val draft: Draft<ByteArray> = Warp.shuttle(OpId("docs"))
.map(OpId("score"))
.filter(OpId("above-threshold"))
.embroider(OpId("rank"))
check(draft.stages.size == 4)
check(draft.isMonotone.not()) // has an Embroider stage
check(draft.embroidery?.opId == OpId("rank"))Properties
All DraftStage.Embroider nodes in this Draft, in topological order.
The single DraftStage.Embroider stage in this pipeline, or null if none was added. Equivalent to embroideries.singleOrNull().
true when every stage in this Draft is CoordinationKind.Free — no consensus step is present. A monotone pipeline converges without any Raft round.
Topological-order view of the stage types recorded in this Draft.