The Build Plan
The build plan is a JSON document the OQL kernel emits from a workbook's source. It describes the complete set of WASM worlds, components, inputs, outputs, and edges — everything the runtime needs to compile and wire the workbook's code. It is the interface between the Org source and the WASM execution layer.
Structure
{
"worlds": [
{
"id": "my-workbook/score-items",
"lang": "javascript",
"src": "export function score_items(items) { ... }",
"args": {"in": ["items"], "out": ["scores"]}
}
],
"components": [
{
"id": "my-workbook/score-items",
"world": "my-workbook/score-items",
"in": ["items"],
"out": ["scores"],
"deps": []
}
],
"edges": [],
"imports": ["items"],
"exports": ["scores"]
}
| Key | Type | Description |
worlds | array | One entry per compilable source block. Contains the source text and language. |
components | array | One entry per wired component (heading with :in:, :out:, or :deps:). |
edges | array | Directed edges connecting component outputs to inputs. |
imports | array | Names the workbook consumes from outside (unresolved inputs). |
exports | array | Names the workbook produces (resolved outputs). |
How OQL builds it
The Rust kernel (kernel/src/lib.rs) uses the orgize parser to walk the
heading tree. For each heading it collects:
:PROPERTIES:→ reads:in:,:out:,:deps:,:sig:Child source blocks → reads language, source text, and block header args
Heading title → derives the component ID (lowercased, hyphenated)
A World is created for each source block that has a compilable language. A
Comp is created for each heading that declares :in:, :out:, or :deps:.
Args holds the parsed property values. A Sig holds the optional explicit WIT
signature.
Edges are computed by matching: for each component with :deps: entries, find the
upstream component(s) and create directed edges from their :out: names to this
component's matching :in: names.
Inspecting the plan
wb tangle my.org # prints the full plan as JSON
wb tangle my.org | jq . # pretty-print with jq
Or in iex:
org = File.read!("my.org")
plan = Workbooks.OQL.tangle_plan(org)
plan["worlds"] # list of worlds
plan["components"] # list of components
plan["edges"] # list of edges
plan["imports"] # top-level inputs
plan["exports"] # top-level outputs
Worlds vs components
A world is a compilable unit: source code + language. It maps directly to a WASM module. A component is the wired unit: it references a world and declares how its inputs and outputs connect to the rest of the graph.
One world can back multiple components (the same code reused with different wiring), though this is uncommon in practice. The more common case is 1:1.
The edge map
Each edge in edges is:
{
"from": {"component": "parse-input", "port": "parsed"},
"to": {"component": "process", "port": "parsed"}
}
The runtime walks edges topologically to determine execution order. Components with no incoming edges run first; components with unsatisfied imports wait until their upstream completes.
Validation
wb lint my.org (or Workbooks.OQL.lint/1) checks the build plan for common
errors:
Declared
:deps:that reference non-existent components:in:names with no upstream edge and no workbook-level import:out:names that nothing downstream consumes (warnings, not errors)Source blocks with unsupported languages (if
:out:is declared)
The current lint implementation is a stub that returns an empty issues list —
full static analysis is a planned addition.
WIT component model
The runtime uses the WASM Component Model (WIT) to type-check component
interfaces at link time. Each world in the build plan is compiled to a WIT
component; the engine verifies that the types declared in :sig: (or inferred
from :in: / :out:) are satisfied before execution. Type mismatches are caught
at link time, not at runtime.