WallRiderLangWRL CORE 0.1.2 · FROZEN
DIRECTION · NON-NORMATIVE

A deterministic actor foundation for executable topology

Every other page on this site documents what WallRiderLang is. This page documents what it is for, what it is not, and the ordered list of things that do not exist yet. Nothing here is frozen, nothing here is implemented, and every code block on this page is verified by the test suite to be rejected by today's toolchain.

Three different things get called "WRL", and confusing them produces either an unfairly bad review or an unearned good one.
  1. WRL Core 0.1.2, the writable surface. Five roles, one texture, no behaviours. Its actor surface is narrow, and the frozen extract says so.
  2. The authored design. A serious actor model with mailboxes, behaviour blocks, capabilities, supervision, live-state migration and message compatibility — written down in full, tier-marked, and published at Design draft. It is designed, not built.
  3. The topology direction. This page. It goes past what conventional actor runtimes model, because it is about giving relationships domain meaning rather than giving processes better plumbing.

The order matters. (1) is what you can run, (2) is what the language is designed to be, (3) is what it is for. A review that scores (1) and concludes about (3) — or quotes (3) and implies (1) — is scoring the wrong artifact.

This page is argument, not specification. The normative document is Core 0.1.2, and its Part II carries the same argument in the spec's own language. If this page and the spec disagree about what is settled, the spec wins.
This is not the language's feature roadmap. Most of what WRL is designed to become was written down long before this page — the authored Complete Design Draft, forty-six sections covering the expression notation, boundaries, effects, supervision, metaprogramming and seven worked examples, each marked Core, Experimental or Proposed by its author. Go there to learn what the language has been designed to do. Come here for the narrower question of what it is for, how far along it actually is, and in what order the missing pieces have to be built.

The reframing

WRL has been graded, reasonably, against the conventional actor model: processes, mailboxes, behaviour loops, supervision trees. Against that ruler the writable surface scores badly, and the score is correct. There are no arbitrary behaviours, no writable asynchronous mailboxes, no supervision, no selective receive, no process lifecycle, and nothing resembling the operational tooling that Erlang/OTP has accumulated over three decades of running telephone switches.

Stated plainly, so it cannot be read as marketing: as a general actor runtime WRL is far behind Erlang/OTP, and it will not catch up by imitating Erlang/OTP. Anyone choosing a language today to keep a million lightweight processes alive should choose Erlang or Elixir, and this page is not an argument against that.

Two qualifications keep that from being the whole story, and neither is a softening of it.

First: the part that is built is the part actor systems find hardest. Deterministic replay, canonical event ordering, a within-period fixpoint, content-addressed identity, and a film that reconstructs a run exactly are not conveniences an actor runtime adds later — they are properties most actor runtimes gave up permanently in exchange for scheduling freedom, and cannot recover without redesigning from the bottom. WRL has a small actor surface sitting on an unusually strong deterministic foundation. That is a rarer position than a large actor surface on a nondeterministic one, and it is the reason the ceiling is high even though the floor is low.

Second: the actor model is designed, it is just not built. Mailboxes with declared capacity and overflow policy, behaviour blocks that canonicalize to the same bytes as the drawn form, capability walls, deterministic supervision, verified live-state migration and content-addressed message compatibility are all specified in the authored draft. That is a substantial design, and it is a different kind of gap from a blank page — but it would overstate it to call the remainder mere implementation. Several questions an actor operating system has already answered are still genuinely open here: placement (which host runs which identity, and who decides), partitions (what a period means when the fleet splits), fairness (what the scheduler owes a starved identity when order is canonical), lifecycle (spawn, hand-off and retirement under replay), and operations (upgrade, observation and intervention on a running system). Those are design questions, not typing exercises, and the answers may move the draft.

But the ruler still measures the wrong thing. Erlang is an actor operating system: it is superb at keeping large populations of processes alive, supervised and upgradable. It is deliberately indifferent to what those processes mean. A road network, a power grid or a robot fleet can be modelled in Erlang perfectly well — the topology lives in process state, ETS tables, maps, registries and external databases. What Erlang does not do is make that domain topology a native canonical language artifact: a thing the language names, seals, diffs and hands you as evidence. It is expressible; it is not first-class.

WRL's bet is the opposite one:

The topology is the program. The network of identities, the relations between them, the guarantees those relations carry, and the authority that governs them are the source text — not a data structure the source text builds at run time.

That is a different category of language, with different competitors, and it is the frame the rest of this site should be read in.

One identity, many networks

Many specialist tools privilege exactly one network. A traffic simulator knows roads and vehicles. A circuit simulator knows components and nets. An actor runtime knows processes and messages. A robotics middleware knows nodes and topics. Each is excellent inside its domain, and each was built by people who had no reason to model the others.

Heterogeneous tools do exist, and the claim here is not that nobody has ever combined two domains — co-simulation frameworks, Ptolemy's hierarchical directors [5] and Modelica's multi-physics libraries [2] all do. The claim is narrower: combining them over one durable identity, with a content-addressed name for the whole assembly and a replayable film of the run, is the part that is rare.

A real drone is simultaneously a participant in many networks:

LayerThe relation it contributes
Physical / spatialthe drone occupies an airway segment
Communicationsthe drone streams telemetry to a fleet controller
Commandthe controller dispatches the drone
Authorityan operator is permitted to reroute it
Faultits failure escalates to a supervisor
Energyit draws from a charger and depletes a battery
Economica delivery fulfils a contract and incurs cost
Evidencea signed observation is accepted under a policy

In practice that drone is often represented separately in each system that touches it — as a ROS node, a routing entity, a battery model, an authorization subject, a maintenance record, a process, a simulation object — with a different identifier in each. How many representations there are depends entirely on the deployment, so the number is not the point. The point is that every pair of them is a chance to disagree, and keeping them aligned is an integration cost paid continuously rather than a modelling problem anyone finished solving.

The thesis is that they should be one durable identity participating in several typed topologies, and that the whole assembly — world, policies, run, and outcome — should have a single content-addressed name.

Design-sketch notation, to make the shape concrete. This is not WRL Core 0.1.2 and the toolchain refuses it:

profile wrl.mobility.v1

[drone:d7](battery=82, payload=4kg){pose, telemetry, command}
[airway:a12](capacity=6, altitude=120){occupancy}
[fleet:west]{telemetry}
[operator:dispatch]{command}
[charger:c3]{power}
[supervisor:safety]{fault_in}

[d7] --occupies--> [a12]
[d7] ~~telemetry~~> [west]
[dispatch] ==command==> [d7]
[d7] !!fault!!> [safety]
[c3] --power--> [d7]

The spelling is not the point and will change. The point is that d7 appears once, and five different networks are declared over it — spatial, asynchronous-communications, authorization, fault, and energy — in a document that can be hashed, diffed, replayed and audited as a unit.

Where this actually is today

A single number here would be dishonest in both directions, because the five questions people actually mean when they ask "how good is it" have five different answers. Scored out of ten, generously enough that the low ones cannot be blamed on a harsh grader:

What is being scoredWhy
WRL Core's writable actor surface
what you can type today
3.5/10five fixed roles, one texture, no behaviours, no mailbox, no spawn. This is the number a hands-on reviewer will reach, and it is right
The implemented deterministic runtime foundation
what the small surface sits on
7.5/10content-addressed worlds, canonical ordering, within-period fixpoint, byte-exact replay, an independent oracle. Rare and hard — and frozen and demonstrated for the Core fixture, which is a smaller claim than "finished": it has not been shown at fleet scale, under partition, or across hosts of different architectures
The full authored actor-model design
what the language is designed to be
8.7/10mailboxes with capacity and overflow, behaviour blocks, capability walls, deterministic supervision, verified migration, message compatibility — all written, none running
Topology-native actor-system potential
the ceiling if the thesis is right
9.7/10few actor-oriented systems combine a first-class relation with canonical identity, replay evidence and capability topology — the pieces exist separately in graph databases, modelling languages and actor runtimes, and the combination is what is unoccupied. A ceiling, not a result
Production operations maturity vs OTP
running it in anger
2/10no distribution, no hot upgrade in production, no observer, no tracing, no thirty years of operators. This one is not close and will not be soon
Read the spread, not the average. Averaging 3.5 and 9.7 produces a number that describes nothing. The shape of the spread is the actual finding: a narrow surface on a strong foundation, with a designed middle and an unbuilt operational floor. That shape says the risk is in delivery, not in conception — and it says the fastest way to be wrong is to widen the surface before the foundation can carry it.

Feature by feature

The same judgement at higher resolution. A score here is how well the language handles the concern in principle, given what is designed and what is grounded — not whether you can type it today. The "writable" column is what you can type today, and the two disagree on purpose.

ConcernWritable nowNote
Stable identity9.5yesidentity is structural and content-addressed, not a runtime handle
Semantic replay9.5yesa film reconstructs a run byte-exactly; verified against an independent oracle
Immutable messages9.5partlyvalues are immutable by construction; the asynchronous carrier is not writable
Error / value / fault ladder9.5partlythree distinct outcome kinds, not exceptions; fault state exists, escalation does not
Owned state9yessingle-writer per cell is a static check, not a convention
Same-period vs later delivery9nothe distinction is frozen in the texture family; only -- is writable
Bounded mailboxes9nocapacity and overflow policy are part of the port type, not runtime configuration
Quiescence9yesdefined precisely, and distinguished from termination
Capability / effect walls9nono effect happens invisibly; every crossing is a named, recorded wall
Live-state migration9noa verified route with recorded evidence, not an improvised upgrade script
Explicit backpressure8.5nooverflow is a declared policy with an outcome, never a silent drop
Deterministic supervision8.5nodesigned to replay identically, which conventional supervision does not
Behaviour blocks8.5norequired to canonicalize to the same bytes as the drawn form — a testable law
Message compatibility8.5nocontent-addressed message types; an unknown hash is an outcome, not a crash
Dynamic process lifecycle6nothe hard case for sealed identity; §D9 now derives topology from immutable ledger facts and admits novel identities by sealed rule — placement and partition behaviour remain open
Selective receive5nono design; it interacts badly with canonical ordering and needs one
Distributed placement4nomerge laws exist; placement, partition and consensus do not
Scheduler implementation4n/athe reducer is correct and unoptimised; no preemption, no fairness work
Operational tooling2nothe honest floor. No observer, no tracing, no live introspection

Two patterns in that table are worth naming. Everything scoring 9 or above is a property of the identity and evidence machinery, which is the part that is built. Everything scoring below 6 is a property of a running distributed system, which is the part that is not. The language is strong exactly where meaning is decided and weak exactly where operations happen.

The gap, restated as a table

The claimWhat exists today
Many typed layers over one identityOne layer. Two edge kinds, both signal-ish.
Four route textures carrying guaranteesOne writable texture, --. The other three are frozen meanings with no surface.
Attributed, weighted relationsNone. An edge carries a kind and two endpoints.
Programmable behaviourNone. Five fixed roles with fixed reactions.
Dynamic topologyNone. The world is static for the length of a run.
SupervisionFault state exists. Supervision does not.
Domain profilesOne profile, forge.world.core.v1.
Content-addressed worlds and replayable filmsThis part is real, tested, and shipping.

So the honest summary is: the mechanism is built and the ambition is not. What exists is a small, complete, property-tested demonstration that a topology can be canonicalized, sealed, replayed and independently checked. Everything on this page is an argument about what that mechanism should be pointed at next.

Why the small part was built first. Identity and replay are the load-bearing claims — if a world's id is not stable and its run is not reproducible, then every layer added on top inherits an unfalsifiable foundation. Adding drones to a language whose worlds do not hash reliably would produce an impressive demo and a worthless artifact.

The six pillars

Six design decisions follow from the thesis. Each is stated in spec language in Core 0.1.2 Part II; here is the argument for each. The first five are about what a world means; the sixth is about what to build next, and is the one most likely to be argued with.

1 · The layers are node-aligned, because identity is not per-layer

Multilayer networks are a studied formalism, not an improvisation. In the standard treatment a multilayer network is a set of node-layer tuples plus intra-layer and inter-layer edges, where layers may be structured along several aspects — edge type, time, and so on — and inter-layer edges commonly get different semantics from intra-layer ones.1 A recurring cost in that literature is bookkeeping: the same entity appears once per layer as a replica, and the replicas have to be tied together by explicit coupling edges.

WRL's durable identity removes that cost by construction:

A WRL world is a node-aligned multilayer graph. An identity is not replicated per layer; the layers are aspects of one identity. There is therefore no such thing as an inter-layer coupling edge between d7-in-the-road-layer and d7-in-the-comms-layer, because there is one d7.

This is the single largest structural advantage available to the language, and it is a direct consequence of a decision already frozen in §4: identity is a first-class construct kind, not a per-graph label. It also constrains the design — see what would falsify this, because node-alignment is a real assumption and it can be wrong.

2 · Not every link is a directed route

WRL Core has exactly one connection concept: a directed edge from a source port to a destination port, with at most one edge landing on any input. That rule is correct for owned actor state — it is what makes "conflicts dissolve" true — and it is wrong as a universal wiring law. Two large domains break it immediately.

Electrical and hydraulic connections are not directed. In Modelica a connector distinguishes potential variables, which are set equal across a connection, from flow variables, which are constrained to sum to zero at the connection point — Kirchhoff's laws expressed as a connection semantics.2 Nothing in that is a message from a sender to a receiver. Voltage and current are solved together over the connected set.

Buses have many drivers on purpose. Hardware description languages solved this long ago and the solution is instructive: VHDL provides unresolved types, where more than one driver on a signal is a compile error, and resolved types, where a declared resolution function computes the signal's value from all its drivers — which is how three-state buses are modelled.3

The consequence for WRL is a relief, not a rewrite. Core's one-controller-per-input rule is the unresolved default. It should stay exactly as it is, and become a property of the port type rather than a global law:
  • owned port — at most one writer, statically enforced. Today's rule, unchanged.
  • resolved terminal — many drivers, one value, via a resolution function named by the profile.
  • acausal connector — no direction at all; potential variables equalized, flow variables summed to zero, solved as a system.
Three connection kinds, one of which already exists and is already frozen.

3 · Textures encode guarantees, and must not be asked to encode domains

There is an obvious-looking move here that would be a mistake: since --, ~~, == and !! are so readable, keep inventing textures — one for roads, one for power, one for money.

That collapses under its own weight, and the reason is visible in any mature messaging stack. ROS 2 exposes a channel's behaviour as a set of independent QoS policies — reliability, durability, history, depth, deadline, lifespan and liveliness — which can be combined to be as strict as TCP or as loose as UDP.4 Those are seven orthogonal axes on a single channel. No glyph vocabulary survives that, and a language that tried would need several thousand arrows.

So the frozen four stay four, and they keep the one job they are good at:

TextureAnswers exactly one question
--does it settle inside this period?
~~is it asynchronous — observable no earlier than the next period?
==does it require evidence accepted under a named policy?
!!is it a failure path that engages supervision?

Everything else — domain, direction, cardinality, capacity, cost, units, geometry, schema, reliability, policy — becomes named typed attributes on the relation, whose legality is pinned by the profile. A power connection is a solid relation in the power domain that happens to be acausal; those are three independent facts and the texture carries only the first.

4 · Walls are where the model of computation changes

If a world can contain roads, circuits and message queues, then it contains several models of computation — continuous time, discrete events, synchronous reaction, dataflow. That problem has a known good answer.

Ptolemy II makes the semantics of a model a component in the model: a director implements a model of computation, and a composite actor may be opaque, so its local director need not be the same as the director above it. That is what makes hierarchical heterogeneity work, with directors for process networks, discrete events, dataflow, synchronous/reactive and continuous time.5

WRL already has the construct this requires, and it is not an actor. It is a wall — the boundary family that gates, commits and seals (§10):

A wall may enclose a sub-world under a different profile. The wall, and only the wall, is where the model of computation changes; the enclosing world does not need to understand the enclosed one, only the wall's contract.

The outer world does not learn SPICE. It learns that a wall named amp3 accepts a stimulus, produces a signed result, and takes one period to do it. Whether the inside was solved by nonlinear transient analysis or by a lookup table is not the outer world's business — and that is precisely the property that makes composition survive contact with real solvers.

The pleasant surprise is the construct count. Adding "Road", "Wire", "Transistor" and "Drone" as fundamental construct kinds is unnecessary and would be a mistake — those are roles supplied by profiles. The ten frozen kinds (§1) already cover this design: identities are Actors, relations are Routes, the boundary between models is a Wall, the simulation step is a Period, the optimizer is a Derive, and the record is a Film. The multilayer thesis needs no new construct kind. It needs profiles, and it needs the surface for the kinds that already exist.

5 · Derives seal the answer, not the search

This is the pillar that decides whether "auditable" is true or decorative, and it turns on an asymmetry between two kinds of external engine.

Simulators can be re-run. SUMO fixes its random sequence from a seed and is deterministic by default, so the same configuration produces the same behaviour; the seed is an option and the default is a fixed value.6 An engine like that can be sealed the ordinary WRL way: hash the inputs, the engine profile and the seed, and verify by replaying.

Optimizers frequently cannot. The OR-Tools routing solver is sensitive to the order in which variables and constraints are created — non-deterministic map iteration in the caller has been enough to produce non-deterministic results and run times — users report substantial run-to-run variability in solution quality on identical problems, and the solver does not honour a time limit while it is still inside its first-solution heuristic.7 None of that is a defect; it is what heuristic search is like. But it means a route plan cannot be verified by re-running the search.

The rule. A derive over a search engine seals its inputs, its solver profile, and its result — and ships the result with a deterministic checker. Verification re-checks the plan against the declared constraints and recomputes its objective value. It does not re-run the solver. The solver is an untrusted oracle; the checker is the trusted part.

One consequence has to be stated because it is the most tempting thing to overclaim. Feasibility is checkable in roughly the cost of reading the plan. Optimality is not checkable at all without redoing the search. So a sealed plan may honestly carry:

feasible under constraints C; objective value 412; produced by solver profile S

and it may never carry optimal. A film that says "this plan satisfies every capacity and time window, and here is the arithmetic" is a smaller claim than "this is the best plan", and it is the one that can be independently checked by a party who does not trust you.

6 · The next primitive is a relation, not another actor feature

Everything above converges on one conclusion about sequencing, and it is the least intuitive claim on this page: the next thing to build is not a better actor.

The pull towards actor features is strong and it is the wrong pull. Spawn, selective receive, a supervision tree and a distribution layer would each close a visible gap against Erlang, and each would leave the language competing on Erlang's ground with thirty fewer years of work. Meanwhile the thing few actor-oriented systems offer — a relation that is itself a typed, attributed, checkable, sealed object — would still not exist here.

The claim. An actor language whose connections are untyped arrows is a worse Erlang. An actor language whose connections carry domains, units, capacities, resolution rules and conservation laws — over identities that hash and runs that replay — is not a worse anything. Relations are the differentiator; actors are the substrate.

Concretely, the near-term work is the shape argued in Core Part II §D8: broaden the runtime's third entity from a binary directed Edge to a general Relation, with today's route as its simplest specialisation.

RelationAllocation =
    AuthoredAllocation { world_id, authored_name }        ; present at period 0
  | LeasedAllocation   { lease_id, local_counter }        ; attached at runtime

RelationRevision   { domain, kind, endpoints, orientation,
                     texture?, attributes, policy }

Endpoint { terminal, role }

relation_id      = H("WRL_RELATION" ‖ "authored" ‖ world_id ‖ authored_name)
relation_id      = H("WRL_RELATION" ‖ "leased"   ‖ lease_id ‖ local_counter)
current_revision = fold over the ledger prefix — derived, never stored

The split into a stable relation_id and a content-addressed revision is §D8.1, and it is what lets two physically distinct but identical relations — parallel cables, a redundant link, two lanes of one segment — be told apart, revised and failed independently. The name comes from an allocation rather than from the event that creates the relation, because deriving it from the event is circular: the event id is a hash over its arguments, and the id would be one of them. The revision carries no back-pointer to its predecessor, so lifecycle history has exactly one home — the ledger — and two relations that reach the same value by different routes share one revision id. provenance is gone from the value for the same reason and moves onto the event (§D8.3) — it is how a value was produced, which is the question a content address is not answering. texture? is optional because an acausal relation has none.

The allocation is two variants rather than one flat record because the two cases get their uniqueness from different places: an authored name is unique by parse, checked when the world seals, while a runtime counter is unique only within a lease — a content-addressed value naming a range that no two live allocators can hold at once (§D8.4). Why a lease was granted stays on its grant event and its acceptance receipt, never in the lease, which is §D8.3 applied one level down. An allocation is also spent by being seen: once it appears in any observed proposal it is bound to that proposal's transition and can never name a second relation, whether the proposal was accepted, refused, or abandoned (§D8.6) — the identity equivalent of never reusing a nonce.

Relation identity is therefore world-scoped, and it is worth naming here rather than leaving to be discovered at the first upgrade. A relation keeps its name across every runtime attach, revision and retirement — that is the point of D8.1 — but not across a re-seal, because a re-sealed world is a different sem- id by construction. That is the same scope object ids already have, so it is consistency rather than a new restriction; what it costs is that carrying a relation across a redeploy becomes a migration claim, with an explicit map a checker can verify, and it is filed against that capability at step 9.

Three unusual capabilities fall out of that one change, and none of them is reachable by improving actors:

Falls outBecauseRare elsewhere because
Multi-participant relations — a bus, a net, a shared segmentendpoints is a set, not a pair, and each one carries a role — the tail-and-head structure of a directed hyperarc. This is also the link graph of a bigraph,9 where a link joins any number of portsactor runtimes model connection as addressing, and an address has one target
Acausal relations — potentials equal, flows sum to zeroorientation admits a value that names no source, which is what a physical connection actually is2message passing presupposes a sender; a wire does not have one
Domain-checked attributes — capacity, cost, impedance, unitsattributes are typed by the world's profile, so capacity=3 has a unit and a range and can be checked before the rungraph databases got here first for storage10 — but they do not seal, check, or replay

And the reason to do it before the actor features rather than after is ordering, not preference. Typed ports, supervision, effect walls and domain profiles all need to know what a connection is. Building them against a binary directed arrow means rebuilding each of them when the arrow generalises — which is the same argument §D3 makes for why attributed relations must precede any domain profile.

What it costs, stated where it cannot be skipped. The broadening is only affordable if a plain --sig--> route still serialises to byte-identical canonical output. If it does not, every published sem- id on this site moves, and the change stops being an extension and becomes a version break. That constraint is §D8's central obligation and the first thing an implementation should test.

Consequences

Expressing a graph is not implementing its laws

The distinction that keeps this project honest:

WRL can become excellent at declaring that a resistor connects to a transistor. That gives it exactly none of Kirchhoff's laws, nonlinear device models, transient analysis, or a convergent numerical solver. Declaring roads and vehicles likewise solves no routing problem. Notation is not physics and it is not optimization.

Read the following as two separate questions per domain — can WRL describe this network, and can it compute what the network does — because the answers are very different:

DomainDescribable todayWhat computing it needs
Generic directed graphmostly — no weights or attributesattributed relations
Digital logicnetlist shape onlybit vectors, clock domains, delays, tri-state resolution, unknown/high-Z values
Analog circuitno — connections are acausalmulti-terminal nets, units, continuous time, DAEs, a nonlinear solver
Road networktopology onlyweights, capacity, geometry, lanes, continuous position between vertices
Vehicle / drone fleettopology onlybehaviours, async telemetry, dynamic membership, tasks, reservations, an external router
Electric gridtopology onlyphases, power flow, protection models, an analysis engine
Logistics networktopology onlyattributes, time windows, an optimizer and its checker
Organizational / authority networkpartly — the shape suits it== and the permission/instance split (§16.2)
Auditable cyber-physical twinthe evidence half is realeverything above, plus effect adapters

What four domains actually demand

The previous table names what each domain needs in prose. This one crosses the four domains that matter most against the thirteen capabilities they draw on, because the useful information is in the overlap: a capability demanded by all four is infrastructure, and a capability demanded by one is a profile's business.

required · needed for realistic use · · not essential.

CapabilityFleetCircuitGridRoboticsStatus
Attributed relations§D8 — sketched
Typed quantities and unitsdrafted, ungrounded
Safety invariantsstatic checks exist; runtime invariants do not
Discrete-event timebuilt — this is the period cycle
Dynamic topology·§D9 — sketched
Geometry and coordinate frames··nothing. Not even a frame concept
Reservations and resources·affine resources are drafted
External solver interfacepillar 5 — derives, sketched
Topology deltas·needs §D9 first
Uncertainty·nothing, and it fights determinism — see below
Resolved terminals··§D8 — sketched
Acausal connectors··§D8 — sketched
Continuous time·nothing. Needs a solver wall (pillar 4)

Three readings of that table, in decreasing order of comfort.

The top four rows are unanimous, and only one of them is built. That is a clean answer to "what next": attributed relations, units, invariants. Nothing domain-specific competes with a row that every domain needs.

The split is real and it is diagonal. Fleet and robotics want dynamic topology, geometry and reservations; circuit and grid want resolved terminals, acausal connectors and continuous time. Almost nothing in the bottom half is shared. This is the strongest argument for profiles rather than construct kinds — a language that put all thirteen in the core would be a language nobody could learn, and one that picked a side would be a single-domain tool.

Uncertainty is the row that does not fit, and it should not be smoothed over. Real robots have noisy sensors and probabilistic beliefs. A language whose central promise is byte-exact replay cannot host sampling without either recording every draw as an observed fact — which makes the film enormous but keeps replay exact — or admitting nondeterminism, which ends the promise. The first is probably right and is untested. Until it is tested, "WRL for robotics" is an aspiration with a known unresolved obstruction.

The specialists, and what not to rebuild

Each of these is the right answer to a question WRL should not be trying to answer:

QuestionRight answerWRL's role
What does this transistor circuit do?ngspice / the SPICE familyseal the netlist, the model IDs, the solver profile and the result
How does this multi-physics system behave?Modelicasupply the acausal connector semantics; own the surrounding authority and evidence
What happens to this distribution feeder?OpenDSSunify the electrical model with the comms, fault, crew and market models
How does traffic actually flow?SUMOseal the scenario and seed; replay the film
What is a good vehicle route?OR-Tools or a specialist solverbe the derive boundary and the checker (pillar 5)
How do robot components interoperate?ROS 2 / DDSdeclare why a message is permitted, what it may affect, and what proves it happened
How do I keep a million processes alive?Erlang/OTPnothing — use Erlang
How do I mix models of computation?Ptolemy IIborrow the director idea; add identity, policy and replay (pillar 4)

The target is not to beat any of them at their own question. It is to be the language in which their answers compose into one verifiable world: same identities, one canonical topology, one authority model, one replayable record.

The closest neighbour is not an actor language. Unison content-addresses code — every definition is identified by a hash of its syntax tree, names are metadata pointing at immutable hashes.8 WRL applies that idea one level out: it content-addresses the topology and its policies rather than the function body. That is the useful comparison, and it is a better guide to what WRL is than any comparison to Erlang.

Four demonstrations

Arguments about a language are cheap. These four are the specific things that, if they worked, would demonstrate the thesis — and if they cannot be made to work, would refute it. They are written in design-sketch notation. None of them parses; each names the capabilities it is waiting on, and the test suite checks on every run that today's toolchain still refuses it.

These are later work and are recorded here on purpose. The authored draft carries seven worked examples of its own — a criterium race, a supervised worker pool, a replicated fact lattice, a world fabricator, cell signalling, a proof-carrying patch, a versioned ingest. The four below are not in it. They belong to the topology extrapolation, so they live on this page rather than being back-dated into a document that did not contain them.

A · Autonomous delivery fleet

The flagship, because it is the only one that exercises every layer at once. One drone participates simultaneously in spatial occupancy, communications, command authority, energy, fault, evidence and economic fulfilment — and the whole assembly has one name.

profile wrl.mobility.v1

[drone:d7](battery=82%, payload=4kg, frame=wgs84)
  {pose, telemetry, command, fault_out, power_in}
[airway:a12](capacity=6, altitude=120m){occupancy}
[fleet:west]{telemetry_in, dispatch}
[operator:kim](role=dispatcher){command_out}
[charger:c3](watts=400){supply}
[supervisor:safety](on_fault=land_now){fault_in}
[contract:ord991](due=14:30, penalty=12.00usd){fulfilment}

; spatial — an attributed relation against a finite capacity
[d7] --occupies(cost=1, until=lease(6))--> [a12]
; communications — does not settle this period
[d7] ~~telemetry(rate=4hz, loss=ok)~~> [west]
; authority — a command carries evidence that it was permitted
[kim] ==command(cap=reroute.v1)==> [d7]
; energy — acausal: the charger does not "send" watts
relation electrical acausal {c3.supply, d7.power_in}
; fault — escalation, not an exception
[d7] !!fault(class=gps_loss)!!> [safety]
; economic — the delivery discharges an obligation
[d7] --fulfils(units=1)--> [ord991]

The demonstration is not that this can be drawn. It is that d7 is written once, and the seven statements about it are checked together, sealed together, and replayed together.

The question it answersWhat passing would prove
Can a static check catch cross-layer nonsense?that a12 is at capacity while d7 is still committed to ord991 is a contradiction between the spatial and economic layers. No single-domain tool can see it, because no single-domain tool holds both
Does one identity really cost less than seven?the integration bug class disappears rather than moving. If the layers still need reconciliation, node-alignment bought nothing
Is the film evidence?an operator can hand a regulator one file that reconstructs the flight, the authorisation, the energy draw and the contract state — with no trusted runtime in between

B · A resolved digital bus

The smallest demonstration, and the sharpest, because it is entirely falsifiable. A single-writer signal, a multi-driver resolved bus, high impedance, contention, a deterministic resolution function, and verified timing — with a right answer that hardware engineers already know.

profile wrl.digital.v1

; an OWNED terminal: exactly one writer, today's frozen rule
[reg:r0](width=8){q: owned<bits8>}
[gate:g0]{a: in<bits8>, y: owned<bits8>}
[r0] --sig--> [g0].a

; a RESOLVED terminal: many drivers, one named function.
; the resolution table is part of the sealed document —
; a bus whose resolver came from the runtime would break §11.
[bus:b0](width=8, resolve=std_logic){d: resolved<logic8>}
[driver:u1](oe=true) {y}
[driver:u2](oe=false){y}  ; drives Z, high impedance
[driver:u3](oe=true) {y}

[u1] --drive--> [b0].d
[u2] --drive--> [b0].d
[u3] --drive--> [b0].d
CaseRequired outcome
Two drivers on an owned terminalstatic error before the seal — the rule frozen in §0, unchanged
Three drivers on a resolved terminal, one enabledlegal. The value is the enabled driver's; the two Z contributions are absorbed by the resolution function
Two enabled drivers disagreeinglegal to write, and resolves to X — contention is a value, not a crash, exactly as in std_logic3
The same world sealed on two machinesidentical sem- id, because the resolution table is in the document
REACT settling a resolved terminalone pass, because the resolution is a pure, total, deterministic function of one canonically ordered driver map, with a declared value for the empty map. It needs no algebraic laws at all: §D2.1 keeps idempotence for §9's join, where it makes redelivery harmless, and keeps associativity and commutativity only for a profile that opts into folding the driver set. Demanding any of them here would forbid "two enabled drivers is a fault" and "the strongest driver wins", which are ordinary bus rules
Why this one is the right first build. It needs no solver, no continuous time, and no new phase in the period cycle. It is §D8's resolved-terminal half and nothing else, and it has a known-correct answer for every case — so it can be wrong, which the fleet demonstration cannot be for years yet.

C · A microgrid

The hardest of the four, because it needs an acausal electrical network solved inside a wall while five other layers proceed on the ordinary period cycle around it.

profile wrl.power.v1

; inside this wall the model of computation is not message
; passing — it is a system of equations (pillar 4)
wall electrical solver=power_flow.v1, tolerance=1e-6 {
  [bus:b1](nominal=400V){pin}
  [pv:solar](rated=50kW){pin}
  [battery:bess](soc=61%, rated=120kWh){pin}
  [feeder:f4](length=1.8km, r=0.31ohm){pin_a, pin_b}

  ; no writer, no direction: potentials equal, flows sum to zero
  relation electrical acausal {b1.pin, solar.pin, bess.pin, f4.pin_a}
}

; outside the wall, ordinary WRL, ordinary periods
[scada:ops]{telemetry_in, dispatch}
[relay:p22](trip=overcurrent(1.2pu, 200ms)){fault_out}
[crew:team3](skills=hv){assignment}
[market:da](interval=1h){commitment}

[f4] ~~telemetry(rate=1hz)~~> [ops]
[ops] ==dispatch(cap=setpoint.v1)==> [bess]
[p22] !!fault(class=overcurrent)!!> [ops]
[ops] --assigns(eta=40min)--> [team3]
[bess] --commits(mwh=0.4, price=?p)--> [da]

What makes this a genuine test rather than a bigger picture: the electrical layer does not settle by passing values. Everything else does. A single world therefore contains two models of computation, and the wall is the only place they meet.

The question it answersWhy it is hard
Can a solver live inside a period without infecting it?the solve must be a deterministic function of the sealed inputs. A tolerance, an iteration order or a starting guess that varies makes the film unreproducible
Can a protection trip cross from the solved layer to the discrete one?the relay reads a solved quantity and produces a discrete event, so the wall must define a crossing direction and a settlement order
Do the crew and market layers stay honest?an assignment and a market commitment are obligations over the same identities as the physics. Today they live in three unrelated systems

D · A road-network derive

The complete pillar 5 loop, end to end, and the one that decides whether "auditable optimisation" is a real category. A sealed road world, a fleet, a set of orders and a set of constraints go in; an untrusted external solver proposes; a deterministic checker accepts or refuses; the accepted plan is dispatched; execution produces a film.

profile wrl.logistics.v1

; inputs are sealed BEFORE the solver is asked anything
[roadnet:metro](source=#osm.metro.v3, edges=88214){graph}
[fleet:north](vehicles=12, capacity=1400kg){assignment}
[orders:batch7](count=340, windows=hard){demand}
[rules:law](max_shift=9h, rest=45min){constraint}

; the solver is an ORACLE. Its output is a claim, not a result.
derive plan by=solver(or_tools.routing.v9, seed=7, limit=30s)
  from {[metro], [north], [batch7], [law]}
  check feasibility.v1 {
    ; each of these is cheap to verify and expensive to find
    every order served exactly once
    every vehicle within capacity
    every window respected
    every shift within law.max_shift
    objective recomputed from [metro].edge_costs
  }

; only a CHECKED plan may be dispatched
[plan] ==dispatch(cap=fleet.command.v1)==> [north]
The one claim this demonstration must refuse to make. The sealed plan may say feasible under these constraints, objective value 4 812, produced by solver profile or_tools.routing.v9 seed 7. It may never say optimal. Feasibility is checkable in about the cost of reading the plan; optimality is not checkable without redoing the search. A language that let a derive stamp "optimal" on an unverifiable result would be laundering a heuristic into evidence, which is worse than having no derives at all.
The question it answersWhat passing would prove
Can an untrusted engine participate in a sealed world?a solver that is non-deterministic run to run7 can still contribute to a byte-exact film, because the film records the answer and the check, not the search
Is the checker actually cheaper than the search?if it is not, derives collapse — either they seal unverifiable claims, or verification costs as much as solving and nobody runs it. This is falsification condition 2
Does a third party need to trust the operator?a regulator re-runs the checker against the sealed inputs and reaches the same verdict without the solver, the operator, or the runtime

The dependency ladder

The spec insists its promotion order is "steered, not merely preferred" (§16) because each step supplies something the next one needs. The same discipline applies to everything on this page. Here is the ordering, with the reason each step cannot move earlier:

This table is checked against the capability registry, and the check had to be repaired. Each row carries data-step and data-capabilities, and the conformance suite requires that every registered capability be delivered by exactly one rung and that the rung number match the step the registry prints. An earlier version of that check read only the printed numbers, and a reviewer demonstrated it was decorative: swapping the steps of supervision and dynamic-topology in the registry and re-sorting the rows left the suite entirely green. That is precisely the dependency error this ladder exists to prevent — promoting the fault route before the supervision floor it requires — so the check was passing over the one bug it was written to catch. It now fails by name. A commit message in this repository claimed the earlier version was "the check that would have caught this commit's own bug"; it would not have, and the overstatement is recorded here rather than quietly corrected.
#StepWhy it cannot come sooner
1Typed ports and message schemasevery later feature has to say what flows; without this, attributes and behaviours are untyped strings
2~~ async route + mailbox surfacealready §16 step 2. Telemetry is asynchronous; a fleet without it is a diagram
3Profile mechanismProfileSchemaV1: relation kinds, attribute types, units, bounded resources and finite resolution tablesneeds the type system from step 1, and nothing later. An earlier version of this row said "resolution functions", which need the expression notation from step 5 — a cycle in a ladder whose entire claim is that it is a dependency order. §D6.1 restricts the kernel to declarations, so the step is deliverable where it stands
4Attributed relations (weight, capacity, units) and resolved terminalsneeds step 3 to say what capacity=3 means, or "cost" is a name with no arithmetic and no unit
5Behavioursneeds the expression notation, which §13 still lists as Experimental in its entirety
6== verified route§16.1: needs claimant, target, operation family and named policy all enforced — nothing less is a verified route
7Supervision floor + !!§16 step 6 is explicit: the fault route may only follow a supervision floor that actually exists
8Dynamic topologyidentities joining and leaving is meaningless without a lifecycle, and a lifecycle without supervision leaks. It also needs step 4's bounded resources before an escrowed attach can be safe under partition
9Effect adapters (walls to ROS, devices, APIs) and the solver walla command that leaves the world needs step 6 to authorize it and a film to record it. Acausal relations settle here, because they settle in a solver
10Derive boundary + checkersneeds attributes (4) to state constraints and effects (9) to matter
11Production domain profiles — mobility, electrical, logistics, roboticsa profile pins roles, ports, units, laws and film schemas — it can only pin things that exist
Two corrections to an earlier version of this table. It had dynamic topology at 6 and supervision at 7, while the same row said "a lifecycle without supervision leaks" — the justification named a dependency the ordering violated, and the machine-readable annotation on §D9's sketch named supervision too. The ordering was wrong, not the reason.

It also had a cycle. Attributed relations were step 3 and domain profiles step 10, but §D8 says relation attributes are validated by a profile — so step 3 depended on step 10. The fix is that these were always two capabilities wearing one name: the mechanism for declaring kinds, types and units, and the production packages written with it. The mechanism is early because everything typed needs it. The packages are late because they can only pin things that already exist. The resolved bus can then be built against a small conformance profile without freezing the digital-circuit domain to get there.
The mobility profile is step 11, and it is the one everybody will want to build first. It demonstrates beautifully and it would be a mistake. A profile invented before typed ports and behaviours exist would have to smuggle in a role system by example — which is exactly the failure §16.2 already refuses for [worker:w1]: freezing a decision about principals as a side effect of shipping a demo. If a fleet profile is written before step 1, its choices become precedent regardless of whether they were ever sanctioned.

What would falsify this

An honest direction document names the observations that would sink it. These are the five that would.

This section is a non-normative summary. Core Part II §D7 is the normative statement of the falsification conditions; what follows expands five of its eight at argument length. Where the two differ, the spec is right and this page is stale. That is a real hazard rather than a formality — Direction once carried a condition §D9 had already retired, and every link on the page resolved correctly the whole time, because a link checker proves that citations resolve and not that two pages agree. So each heading below links to its normative row by a stable id, the conformance suite requires that link to be present, and it requires this page's set of conditions to be a subset of the spec's. None of that can diff prose; what it can do is make sure a reader who suspects drift is one click from the authority, and that a condition cannot be invented, resurrected or silently orphaned here.

1 · If identity turns out to be per-layer after all normative statement

Node-alignment (pillar 1) assumes one identity is the right granularity across every layer. That assumption fails if layers need to version independently — if a drone's communications identity can be replaced (new radio, new certificate, new address) while its physical and contractual identity persist. If that turns out to be the common case rather than the exception, WRL needs per-layer replicas and explicit coupling edges, and the largest claimed advantage over conventional multilayer tooling evaporates.

2 · If checking is not cheaper than solving normative statement

Pillar 5 assumes a plan's feasibility can be verified far more cheaply than the plan can be found. That is true for routing with capacity and time-window constraints. It is not obviously true for every interesting derive — constraint systems exist whose solutions are no easier to check than to compute. Wherever that holds, the derive boundary provides paperwork rather than verification, and should say so instead of implying otherwise.

3 · If profiles cannot compose without a central registry normative statement

Pillar 4 assumes a wall can join two profiles knowing only their contracts. If in practice every cross-profile wall needs global knowledge — shared units, shared time bases, shared numeric conventions negotiated in one place — then "one world, many domains" degrades into a monolith with a plugin directory, and the composition claim was never real.

4 · If broadening the relation moves every published id normative statement

Pillar 6 assumes a general Relation can serialise a plain directed route to the same canonical bytes today's edge produces. Eliding defaulted fields is not enough to achieve that, and §D8 now says so: the frozen form names objects where the general form names terminals, and calls the container edges rather than relations, neither of which is a default that can be omitted. The compatibility mechanism is therefore a normative legacy projection — relations of exactly the frozen shape are encoded in the old form — and the condition is whether that projection is total over the published corpus. If some pinned world contains a route the projection cannot cover, every sem- id ever published moves, the change is a version break rather than an extension, and the ordering of the entire ladder has to be reconsidered. This is still the cheapest condition on the list to test, and it should still be tested first.

5 · If admission cannot be decided from sealed rules and recorded evidence normative statement

§D9 admits identities the document never enumerated by sealing an admission rule — trust roots, identity scheme, schema, checker, quota policy — rather than a roster of participants. A vehicle belonging to another operator can therefore join a sealed world mid-run, because what was sealed was the test it has to pass, not the list it has to be on. That construction fails if real federation requires consulting live external state at admission time — a revocation service, a broker's current view, a quota held somewhere else — which cannot be captured as evidence a replay can re-read. Then admission is not a function of the seal and the ledger, the film stops being self-contained, and the guarantee degrades to "it was true when we looked".

None of these are settled. They are stated here so that the answers, when they arrive, are recognizable as answers rather than as surprises — and so that a reader can tell which parts of this page are engineering and which are a bet.
A retired condition, kept visible. An earlier version of this list argued that sealed identity and open topology were in "genuine conflict, and one of them has to be given up", on the assumption that the set of possible participants had to be bounded by the document. §D9 retired that assumption — a trust domain admits by attested rule, not by prior enumeration, which is how SPIFFE federates — so the dilemma was a false one and the condition above replaces it with the narrower question that survives. Retired conditions are struck here rather than deleted, because a falsification list that quietly loses entries is a list you cannot audit.

The first real test

Two different things get called "the first test", and separating them is the last piece of honesty this page owes.

The demonstration that would validate the thesis is demonstration A: a single world in which one identity participates in road, communications, dispatch, energy and fault topologies at once; executed across a multi-machine TRVM run; calling an external route solver through a derive; producing a film a third party can check without trusting the machine that produced it. That demonstration needs a production mobility profile, which is step 11 — the last rung — and the work between here and there is steps 1 through 10: typed ports, an async surface, the profile mechanism, attributes on relations, behaviours, a verified route, a supervision floor, dynamic topology, an effects boundary and the derive wall. None of it is glamorous and none of it can be skipped.

The demonstration that should be built first is demonstration B, the resolved digital bus. It is the smallest thing that is not already true: no solver, no continuous time, no new phase in the period cycle, and no new profile machinery beyond one resolution table. It exercises exactly one half of §D8 — many drivers meeting at one terminal — and every case in it has an answer that hardware engineers settled decades ago. That is what makes it valuable: it can fail in a recognisable way, which demonstration A cannot do for years.

The rule the two together imply. Build the smallest thing that can be wrong, before the largest thing that would be impressive. The fleet profile is step 11 for the reason given above; the bus is not a step on the ladder at all, it is a test of whether steps 1, 3 and 4 — typed ports, the profile mechanism, and attributed relations with resolved terminals — have the right shape between them. A resolution table is written in the profile mechanism, over ports that step 1 typed, to govern attributes step 4 introduced; the bus is the smallest world that needs all three at once, which is exactly why it is worth building before anything larger.
The strongest version of WRL is not Erlang with prettier arrows. It is a language for living networks — where identities persist, topology has meaning, routes declare guarantees, walls declare authority, derives compute plans, periods order change, and films let someone else check the whole thing.

The last clause is the one that is already true. The rest is the roadmap.


References

  1. Kivelä, Arenas, Barthelemy, Gleeson, Moreno & Porter, “Multilayer networks”, Journal of Complex Networks 2(3), 2014 — node-layer tuples, aspects, and the intra-layer / inter-layer edge distinction.
  2. Modelica Language Specification, ch. 9 “Connectors and Connections”, and Modelica.UsersGuide.Connectors — potential variables equalized, flow variables summed to zero.
  3. VHDL std_logic / std_ulogic and resolution functions — resolved vs unresolved types and multiple drivers.
  4. ROS 2 documentation, “Quality of Service settings” — reliability, durability, history, depth, deadline, lifespan and liveliness as independent policies.
  5. Ptolemy II: Heterogeneous Concurrent Modeling and Design in Java — directors as models of computation, opaque composite actors, hierarchical heterogeneity.
  6. Eclipse SUMO documentation, “Randomness” — deterministic by default from a fixed seed; --seed and --random.
  7. google/or-tools issue #1331, “Highly variable, non-deterministic results in VRP”; #2212, time limit not respected inside the first-solution heuristic; and or-tools-discuss, “Deterministic solvers” — model ordering affects results.
  8. Unison, “The big idea” — definitions identified by a hash of their syntax tree; names as metadata over immutable hashes.
  9. R. Milner, The Space and Motion of Communicating Agents, Cambridge University Press, 2009 — a bigraph is a place graph and a link graph over one node set; links are hyperedges; reaction rules reconfigure structure and may create or destroy nodes.
  10. ISO/IEC 39075:2024, Information technology — Database languages — GQL — the first new ISO database language since SQL; standardises the property graph as a directed, labelled, attributed multigraph in which nodes and edges both carry properties.