WallRiderLangWRL CORE 0.1.2 · FROZEN
REFERENCE

Every table, in one place.

This page is the lookup surface for WRL Core 0.1.2 — the exact vocabularies, signatures, bounds, codes and pinned ids that the canonicalizer enforces. Prose lives in the guide; the normative text lives in the spec.

Grammar

The complete core world surface. Whitespace outside tokens is insignificant. Comments start with ; and run to end of line.

document    ::= profile-line  ( declaration | edge | comment | blank )*

profile-line ::= "profile" WS profile-id
declaration  ::= "[" role ":" id "]" [ config ] [ ports ]
edge         ::= "[" [ role ":" ] id "]" "--" edge-tag "-->" "[" [ role ":" ] id "]"

config       ::= "(" [ config-item ( "," config-item )* ] ")"
ports        ::= "{" [ port ( "," port )* ] "}"
config-item  ::= key "=" value | clock-sugar | "configurable"

role         ::= "pulser" | "relay" | "door" | "spinner" | "orb"
edge-tag     ::= "sig" | "socket"
id           ::= WORD  ; [A-Za-z0-9_]+, and MUST NOT contain "__"
comment      ::= ";" ANY*
# is not a comment marker. In the core surface the only comment marker is ;. # belongs to the identity family and is preserved by the parser rather than discarded.
A double underscore is reserved. An id matching [A-Za-z0-9_]+ is still rejected if it contains __[relay:a__b] fails with WRL_UNSUPPORTED_FEATURE. The sequence is reserved for compiler-generated names, so that a lowered identifier can never collide with one you wrote.
Every group is a set, and a set has no repeats. A {ports} group naming the same port twice is a typed rejection (WRL_PORT_SIGNATURE), and a (config) group setting the same key twice is WRL_DUPLICATE_CONFIG_KEY. Neither is last-one-wins, because a repeated key is far more often a mistake than an intention, and silently keeping one of them would make the id depend on which.

Line regexes, as implemented

LinePattern
declaration^\[(\w+):(\w+)\]\s*(\([^)]*\))?\s*(\{[^}]*\})?$
edge^\[(?:\w+:)?(\w+)\]\s*--(\w+)-->\s*\[(?:\w+:)?(\w+)\]$
epoch claim scenario only^\[epoch:(\d+)\]\s*(.*)$

The role prefix is optional on an edge endpoint and, when present, is not part of the identity — [relay:r0] and [r0] refer to the same object on an edge line, and seal identically.

Optional is not unchecked. A role prefix you do write is a checked assertion. Writing [door:r0] when r0 was declared a relay is WRL_ROLE_PREFIX_MISMATCH, not a shrug. The prefix never affects the id; it exists so that a reader can see the shape of an edge without scrolling, and it would be worth nothing if it could lie.
The profile line is required, singular, and first. A world document must open with exactly profile <id> — comments and blank lines may precede it, nothing else may. Omitting it is WRL_MISSING_PROFILE, repeating it is WRL_DUPLICATE_PROFILE, and writing it with trailing tokens or no id at all is WRL_MALFORMED_PROFILE. A profile-only document is legal: it is the empty world, and it seals.

Role registry

Surface tokenCanonical roleState schema refSurface status
pulserPulserstate.pulser.v1grounded
relayRelaystate.relay.v1grounded
doorDoorstate.door.v1grounded
spinnerSpinnerstate.spinner.v1grounded
orbOrbstate.orb.v1grounded
— none —Mailboxstate.mailbox.v1IR-only
Mailbox has no surface spelling. It is IR/runtime-grounded — it exists in the canonical IR and the runtime honours it — but WRL source cannot declare it and the formatter cannot emit it. It is therefore not a sixth writable role, and its presence does not mean the async route texture was promoted.

The state schema reference is derived, never written: state.<role lowercased>.v1.

Port signatures

Frozen per role. The {…} group on a declaration is checked against this table, not defined by it.

Roleoutin
Pulsersig_out
Relaysig_outsig_in
Doorsig_in
Spinnersocketsig_in
Orbpose
Mailbox
Empty groups are omitted, not emptied. In the canonical artifact a Door carries {"in":["sig_in"]} with no "out" key. Emitting "out":[] produces different bytes and therefore a different sem- id.

Edge kinds

Surface tagCanonical kindSource portDestination port
--sig-->SignalWiresig_outsig_in
--socket-->SocketControlsocketpose

Legal source roles and destination roles fall out of the port table:

KindLegal sourcesLegal destinations
SignalWirePulser, RelayRelay, Door, Spinner
SocketControlSpinnerOrb
At most one edge may land on any input port. Fan-out is unrestricted; fan-in is WRL_CONTROLLER_CONFLICT.

Configuration schema

static_config is construction-time, not run-time. Everything in this section is read once, when the world is built, and is part of the SemanticArtifactID. It seeds runtime cells — a Spinner's declared rotor is the initial value of the cell the runtime later writes — but it is not those cells, and it does not track them. The name is exact: the configuration is static because a running world never writes back into its own document. Runtime values live in state (addressed by state_schema_ref, whose contents are outside the document) and are observable in the film; the two are related only at period zero, by seeding.
RoleSurface keysCanonical static_config keys
Pulsermode, period, phase, epochclock
Relay
Door
Spinnerw, n, rotor, configurablew, n, rotor, configurable
Orb
Mailbox IR-onlyw, cap

The Pulser is the one role whose surface keys and canonical keys differ: four surface fields collapse into a single typed clock tuple.

Spinner fields

FieldTypeMeaning
wintegertotal bit width of one rotor lane
ninteger, 0 ≤ n ≤ wfractional bits; unit = 1 << n
rotorexactly 4 integers, each 0 ≤ lane < 1<<wquaternion lanes, written a.b.c.d or a name
configurablebooleanwhether the rotor may be rewritten at run time
The bound on n is , not <. The validator accepts n = w, and this table said n < w until it was checked against the frozen implementation. The looser bound is worth understanding rather than tightening: at n = w the geometry is still well-formed, but the unit 1 << n equals 2w and so falls outside the legal lane range — every lane is representable, and the value one is not. Such a world seals fine and is arithmetically degenerate. If you want a rotor of unit magnitude you need n < w; the validator enforces well-formedness, not usefulness.

Rotor lanes are written with dots in the core surface (181.0.0.181). Because the dot is the lane separator, a rotor cannot carry a decimal fraction — rotor=181.5.0.0 is the four-lane rotor (181, 5, 0, 0), not a fractional value. The bootstrap surface used commas; that spelling is a legacy path.

Clock vocabulary

SugarExplicit surfaceCanonical clock
every Kmode=periodic, period=K, phase=0["periodic", K, 0]
every K, phase Pmode=periodic, period=K, phase=P["periodic", K, P]
once at Emode=once, epoch=E["once", E]

A clock outside its legal range is WRL_CLOCK_RANGE: period must be at least 1, phase must be less than period, and epoch must be non-negative.

Rotor vocabulary

Named rotors split into two classes, and the distinction is recorded in build provenance.

NameLanes at fractional width nClass
identity[u, 0, 0, 0]exact
reverse_x[0, u, 0, 0]exact
reverse_y[0, 0, u, 0]exact
reverse_z[0, 0, 0, u]exact
quarter_turn_z[q, 0, 0, q] where q = round(u/√2)rounded

where u = 1 << n. Any other name is WRL_UNSUPPORTED_FEATURE.

The exact-integer projection

No floating point is used anywhere. round(u/√2) is computed with integer arithmetic only:

u      = 1 << n
two_uu = 2 * u * u
q0     = isqrt(two_uu) / 2
q      = q0 + 1   when  two_uu > 4*q0*q0 + 4*q0 + 1
       = q0       otherwise
nunit uq
41611
8256181
166553646341

A rounded named rotor carries the provenance policy forge_named_rotor_rne_sym_v1. Exact named rotors carry none. Provenance never enters the artifact bytes — it records how a value was produced, not what the value is.

Sugar forms and bounds

Sugar version sugar.v2. A source-to-source pre-pass in front of the untouched canonical parser.

FormKindExpands to
every K / once at Evalueexplicit mode=… fields
rotor=<name>valuefour explicit integer lanes
[role:base*K]structuralbase0 … base(K-1), zero-based
base*K in an edge endpointstructuralpositional pairing across both sides
[src] --tag--> {a, b, c}structuralone edge per listed destination
BoundValueViolation
replication base index0
replication count max1024WRL_NUMERIC_RANGE
fan-out count max1024WRL_NUMERIC_RANGE
total expansion max65536 linesWRL_NUMERIC_RANGE
count literal digits max9WRL_NUMERIC_RANGE

Three decisions worth knowing: replication members are zero-based; replicated edges pair positionally and require equal counts on both sides; an inline comment on a replicated line attaches to the first emitted line.

The law is: no sugar-specific identity. A sugared spelling and its explicit twin produce the same canonical bytes and seal to the same sem- id. That is not the claim that editing sugar cannot move an id — sp*3sp*4 is a different program and moves it.

Canonical artifact

The canonicalizer produces this record, serializes it as JSON with sorted keys and separators "," / ":" and no whitespace, then takes SHA-256 of the UTF-8 bytes.

{
  "ir_version": "1.0",
  "profile_id": "forge.world.core.v1",
  "objects": [
    { "object_id", "role", "ports", "state_schema_ref", "static_config" }, …
  ],
  "edges": [ { "src", "dst", "kind" }, … ],
  "schemas": {
    "runtime_state_schema": "RuntimeStateV1",
    "epoch_input_schema":  "EpochInputV1",
    "observable_schema":   "EpochResultV1"
  },
  "semantic_policies": {
    "rulepack_id":       "forge.world.core.rules.v1",
    "admit_policy_id":   "admit_candidate_min_firstreceipt_v1",
    "film_schema_id":    "film.v0.7",
    "numeric_policy_ids": ["POLICY_FORGE"]
  }
}

Canonical ordering

CollectionSort key
objectsidentity-first: (object_id, role)
edgesnatural tuple order over (src, kind, dst)
JSON keyslexicographic, at every depth

Because objects sort identity-first, the order you declare things in is inert: shuffling declaration lines cannot move the sem- id.

Pinned policy ids

ConstantValue
IR version1.0  (mailbox profile: 1.1)
Profileforge.world.core.v1
Rulepackforge.world.core.rules.v1
Admit policyadmit_candidate_min_firstreceipt_v1
Admit policy (mailbox)admit_mailbox_deliver_all_v1
Film schemafilm.v0.7  (mailbox: film.v0.7.mailbox.v1)
Numeric policies["POLICY_FORGE"]
Sugar versionsugar.v2
Named-rotor rounding policyforge_named_rotor_rne_sym_v1
Mailbox width max32
A null or empty policy id is a hard error (WRL_UNSEALED_POLICY). Policies are part of the semantic artifact; an unset one would let two genuinely different worlds hash to the same value.

Identity ladder

PrefixNamesHash of
sem-SemanticArtifactIDcanonical IR + semantic policies
bknd-BackendArtifactIDthe semantic id + the lowering profile
scen-ScenarioDigestthe digest domain of the run inputs
replay-ReplayBundleIDworld + scenario together
bundle-ForgeBundleIDa self-contained exported project's canonical bytes
env-evaluation environmentits splits, canonicalized as sorted sets

Every id is <prefix>-<64 lowercase hex>, SHA-256 over the canonical bytes of the thing named. Nothing else may occupy those namespaces.

The two sem- values used across this site — both asserted by test/conformance.mjs, so a build that disagrees with either is a failing build:

WorldSemanticArtifactID
the starter world
pulser, relay, spinner, orb — the teaching example
sem-67e954cfe3115166b49388366df3f062a46572ba2baf53380f1520f4050b60ae
the pinned conformance fixture
six objects; what the test batteries assert against
sem-8ae91fe9cbc5fd086ce4356d587c403211e5c7b2b3ebdd316496367429ecfe4a

What moves an id, and what does not

Changesem-
comments, blank lines, indentation, alignmentinert
declaration orderinert
edge orderinert
sugared vs. explicit spelling of the same valueinert
presentation: x/y position, colour, curveinert
periods or [epoch:N] claimsinert — they are run inputs
renaming an objectmoves
adding or removing an object or edgemoves
reconnecting an edgemoves
any rotor, clock or width valuemoves
the profile or any pinned policy idmoves

Diagnostic codes

Every rejection is one of these typed codes. Downstream tools branch on the code; the detail string is for humans.

This is the full Forge toolchain catalog, not the list a single stage emits. The Browser column says whether the playground can raise the code at all: the browser spine stops at the seal, so codes belonging to backend lowering or to sealed-record round-tripping are listed for completeness and will never appear there. The subset is available programmatically as W.BROWSER_CODE_IDS, and test/conformance.mjs checks that every code in it has a description and that the two lists have not drifted apart.

CodeMeansBrowser
WRL_DUPLICATE_IDa second object claims an id already declaredyes
WRL_UNKNOWN_ENDPOINTan edge names an object that was never declaredyes
WRL_ILLEGAL_PORT_PAIRan edge asks for a port the role does not haveyes
WRL_CONTROLLER_CONFLICTtwo controllers reach the same input portyes
WRL_CLOCK_RANGEa pulser clock is outside its legal rangeyes
WRL_NUMERIC_RANGEa numeric field is outside its legal range, or is not a complete integer literalyes
WRL_EPOCH_RANGEan epoch index is outside the declared runyes
WRL_UNSUPPORTED_FEATUREthe construct is outside frozen Semantic IR v1yes
WRL_MALFORMED_ARTIFACTthe artifact record has the wrong shapeyes
WRL_PORT_SIGNATUREa {ports} group does not match the frozen signature, or repeats a portyes
WRL_WORLD_SOURCE_HAS_SCENARIOrun inputs appeared in world sourceyes
WRL_SUGAR_MALFORMEDa sugared spelling could not be expandedyes
WRL_MISSING_PROFILEworld source did not open with a profile lineyes
WRL_DUPLICATE_PROFILEworld source declares the profile more than onceyes
WRL_MALFORMED_PROFILEthe profile line is not exactly profile <id>yes
WRL_UNKNOWN_CONFIG_KEYa declaration carries a key the role does not defineyes
WRL_DUPLICATE_CONFIG_KEYa declaration sets the same key twiceyes
WRL_ROLE_PREFIX_MISMATCHan edge asserts a role the object does not haveyes
WRL_UNSEALED_POLICYa semantic policy id is null or emptyno — sealing wrapper
WRL_BAD_LOWERING_PROFILEa backend lowering profile is half-specifiedno — backend lowering
WRL_SEALED_IMMUTABLEsomething tried to write to a sealed objectno — sealed records
WRL_UNKNOWN_ARTIFACT_FIELDa sealed record carries an unknown fieldno — sealed records

A diagnostic carries a code, a human detail, and — where the failure is lexical — a line number in the authored source, mapped back through any sugar expansion so it refers to what you wrote rather than to generated text. When the fault lies inside an expansion, the diagnostic also reports which member of the expansion it was.

Lines, not spans. The origin sidecar that carries a generated line back to an authored one is line-granular. A diagnostic therefore locates a line; it does not carry a column range, and this site does not claim underlined spans. Column resolution would need the mapping to record token offsets, which it deliberately does not yet do.

Parser entry points

Entry pointAcceptsStatus
parse_wrl_core(text)world source only; rejects run inputs with WRL_WORLD_SOURCE_HAS_SCENARIOnormative
parse_wrl_legacy_document(text)a pre-boundary combined documentmigration bridge
split_legacy_document(text)a combined documentsplits it into world + scenario

Two forbidden tokens mark a world document as containing run inputs: a line beginning periods , and a line containing [epoch:.

Status: three axes, not one tier

An earlier revision of this site described every construct with a single "tier". That word was doing three unrelated jobs at once, and it hid the exact thing a reader most needs to know. Frozen meaning and writable syntax are independent. The period cycle is completely settled and you cannot type it; surface sugar is fully writable and deliberately not frozen. A single scale cannot say both, so this site uses three.

AxisQuestion it answersValues
Meaning status Is what this means settled, and may it change under me? settled frozen in Core 0.1.2 · drafted designed, may change shape · sketched named only
Grounding Is there something underneath that actually executes it? runtime lowers and runs · IR-only exists in the IR, no surface · none nothing lowers it
Writable now Can I type this into a world document today and have it parse? yes · no
Freezing a family means the set of members is closed and each member's meaning-role is settled. It does not freeze exact glyphs, argument grammars, sugar, or edge-case rules — those remain draft until a later revision promotes them. So settled on the meaning axis is a promise about semantics, never about spelling.
The one column to read. If you are deciding what you can build with this afternoon, read Writable now and ignore the other two. Exactly the rows marked yes are the language that exists as a thing you can type.

Where each construct sits today

ConstructMeaningGroundingWritable nowNote
Ten construct kinds (closed set)settled§1 — a taxonomy, not a syntax
Four reading lawssettled§2
Containers [ ] ( ) { }settledruntimeyes§3
# @ ?settledIR-onlyno§4 — meaning fixed, no world-source spelling
* replication-by-positiondraftedruntimeyesbounded surface sugar; expands before parsing
* wildcard matchsketchednonenoreserved; no lowering exists
Route texture -- solidsettledruntimeyesthe only surface-grounded texture: declarable, emittable, round-trips
Route texture ~~ asyncsettledIR-onlynoneeds a logical route declaration distinct from the structural edge
Route texture == verifiedsettledIR-onlynoacceptance machinery exists; the construct does not
Route texture !! faultsettledIR-onlynofault state exists; route and supervision do not
Periods and superdense timesettledruntimeno§6 — the model runs; you do not spell it
Five memory kindssettledruntimeno§7
Period cycle, six phasessettledruntimeno§8 — the clearest case of settled-but-unwritable
WorldFrame / EventLedgersettledruntimeno§8b
BuildFilmsketchednonenobuild provenance — draft §36
Fact unionsettledruntimenounion law only; settlement above it is sketched
//commitsettledruntimenothe COMMIT phase is real; the marker is not world syntax
///sealsettledIR-onlynosealing is grounded; the artifact registry is sketched
/gatedraftednonenono capability-gate node kind yet — draft §20
Canonicalization & content identitysettledruntimeyes§11 — you invoke it by writing any world
Document boundarysettledruntimeyes§15, new in 0.1.2 — enforced as a typed rejection
Five surface rolessettledruntimeyesPulser · Relay · Door · Spinner · Orb
Surface sugar (sugar.v2)draftedruntimeyesbattery green and identity-equivalent, deliberately not frozen
Mailbox rolesettledIR-onlynonot a sixth surface role; the formatter refuses to emit it
Expression notation, types, generics, numericsdraftednonenodesigned in full — draft §10–§17
Effects, capabilities, entropydraftednonenodraft §23
Supervision error ladderdraftednonenodraft §25
Streams and backpressuredraftednonenodraft §26
Actor behavior blocksdraftednonenoa projection, not a second semantics — draft §21
Evolution and migrationdraftednonenodraft §27
Podium / rankingdraftednonenodraft §20.7
Static-check catalogdraftednonenoeighteen rejections — draft §40
Execution profilesdraftednonenodraft §41
Fragments, stencils, derives, reflectionsketchednonenosettled as kinds only — draft §28–§34
Modules and buildssketchednonenodraft §35–§36
Foreign functionssketchednonenodraft §38
Distributed settlement above fact-unionsketchednonenoreceipts are recognized evidence, never blindly merged

Counting the yes rows is the honest summary of the language as a writable artifact: containers, five roles, two edge kinds, the solid route texture, the sugar layer, the document boundary and the canonicalization that gives you an id. Everything else on this site is meaning you can rely on and syntax you cannot yet write.

The rows that link out. Every drafted and sketched row above is specified somewhere — in the authored Complete Design Draft, which is published in full at Design draft. The section numbers in the Note column are its numbers. If you want to know what a row will mean once it exists, follow the link; if you want to know whether you can type it today, read the Writable now column and stop there.

Promotion capabilities

A capability is one named thing the toolchain does not do yet. It is the unit in which the future arrives.

This table is the registry, and it is machine-read. Every data-requires annotation in the published HTML must name a capability listed here; the conformance suite fails on an unknown name, on a capability missing either classification, and on a registry entry that nothing cites. A capability cannot be invented in a footnote, and it cannot be quietly abandoned.

Each row carries two independent classifications, and the difference between them is the difference between a design and a program:

AxisValuesAnswers
Meaningsettled drafted sketchedhow firm the definition is — whether it is frozen, written down in full, or argued for
Toolchainshipped partial unshippedhow much of it the implementation actually does. A partial row must name the pipeline stages the input completes, and the stage that refuses it, from desugar · parse · validate · canonicalize · serialize · seal · execute

The two textures below are why the second axis exists. Writing [p0] ~~sig~~> [r0] does not produce a syntax error. The parser recognizes the reserved texture — it does not fall through to "unrecognized notation" — so what comes back is located on line 4 and says why: these are transition classes, not IR v1 edges. That is more than "unshipped" and much less than "shipped".

Two corrections to this paragraph, both worth keeping visible. An earlier version said the texture was "refused at lowering". There is no route declaration and no lowering step for these textures, so that overstated it. The replacement said the line was "tokenized" and named tokenize as the stage completed — and that was also untrue, in the opposite direction: there is no tokenizer. parseWrlCore splits the source on newlines, strips comments, and dispatches on regular expressions. Naming a stage the implementation does not have is not a smaller error than naming one it has not reached.

The stage names below are now taken from functions that exist. The input completes desugardesugarCore runs, rewrites the surrounding sugar, and passes the texture line through untouched — and is refused by parseWrlCore. So the row reads desugar; refused at parse, and both halves name something you can call.
"Recognized" is a separate claim, and it is the one the suite proves. Where the refusal happens is a fact about pipeline position. How it is refused is a different fact: the parser identifies this construct by name rather than treating it as noise. The conformance suite demonstrates it rather than trusting it — it runs the texture through the real toolchain and runs a line of genuine nonsense, and requires that the nonsense say "unrecognized" while the texture does not. Both fail with the same code, so the code proves nothing; the discriminator is that one falls through to the catch-all and the other does not. If the texture ever degraded to being treated as garbage, that check would fail by name.
What promotion does and does not do automatically. An earlier version of this page said that when a capability ships, every snippet depending on it "becomes a test obligation" by itself. That was not true. Most draft snippets are fragments — they carry no profile line, so they do not seal today and would go on not sealing after the capability landed, for a reason having nothing to do with the capability. Nothing would have gone red.

What is mechanical is this: shipping a capability means editing its Toolchain cell to shipped, and the moment that cell changes the suite fails for every block still citing it, by file and block number. The trip-wire is on the row, where a person must act, not on the snippet, where nothing would have happened. Turning a fragment into a positive test additionally needs a fixture context to embed it in — that does not exist yet, and is named here rather than implied.
CapabilityMeaningToolchainWhat has to shipStepSpecified in
typed-portsdraftedunshippedports carry a type, messages carry a schema1draft §11
async-routesettledpartial desugar; refused at parse~~ as a logical route declaration, plus a writable mailbox2draft §21
profile-mechanismsketchedunshippedProfileSchemaV1 — the machinery a profile is written in: relation kinds, attribute types, units, bounded resources, finite resolution tables. Declarative only, so it needs no expression notation3Core Part II §D6.1
attributed-relationssketchedunshippedtyped attributes and units on a relation4Core Part II §D8
resolved-terminalssketchedunshippedmany drivers on one terminal, settled by a named resolution function4Core Part II §D8
behavioursdraftedunshippeduser-written behaviour blocks canonicalizing to drawn routes5draft §26
collectionsdraftedunshippedSet vs FactSet, the four symbol kinds5draft §16
expression-notationdraftedunshippedvalues, data types, functions, pattern matching5draft §10–§13
generics-traitsdraftedunshippedparametric generics, traits, hash-pinned coherence5draft §14
numericsdraftedunshippedthe numeric tower with determinism classes5draft §15
resourcesdraftedunshippedaffine handles, borrow and move5draft §17
merge-routesdraftedunshipped<~merge~> over a declared join-semilattice6draft §22
verified-routesettledpartial desugar; refused at parse== with checker identity, policy version and evidence6draft §23
supervisiondraftedunshippedthe supervision floor, caret ownership and !!7draft §25
dynamic-topologysketchedunshippedthe eight topology operations and their obligations8Core Part II §D9
acausal-relationssketchedunshippedundirected conserved-quantity connections settled by a solver wall9Core Part II §D8
effect-wallsdraftedunshippedcapability gates, effect rows, seeded entropy9draft §20, §24
migrationdraftedunshippedlive-state migration as a verified, evidence-carrying route9draft §27
podiumdraftedunshippedthe ranking boundary with a mandatory stable tie-breaker9draft §20.7
derivessketchedunshippedstratified monotone graph functions with checkers10draft §32
ffisketchedunshippedforeign functions admitted only through a boundary10draft §38
metaprogrammingsketchedunshippedphases, fragments, stencils and the six laws10draft §28–§31
modulessketchedunshippedcontent-addressed modules and the no-build property10draft §35–§36
reflectionsketchedunshippedcompile-time reflection free, runtime reflection gated10draft §34
testingsketchedunshippedtests and properties as first-class graph specifications10draft §37
domain-profilesdraftedunshippeda complete production package — mobility, electrical, logistics, robotics — pinning roles, ports, units, laws and film schemas, written using the step-3 mechanism11draft §41

The Step column is the position in the dependency ladder. Steps are a partial order, not a schedule: several capabilities share a step because nothing among them blocks the others.

How a snippet becomes a test. A code block on this site that cannot be written today carries data-not-current, which asserts only that the toolchain refuses it — deliberately not which diagnostic comes back first, because the first complaint about a future construct is usually a missing profile rather than the construct itself. Alongside it, data-requires names the capabilities the block is waiting on. The day one of them ships, the blocks that depend on it start parsing, data-not-current goes red, and the documentation has to be updated before the build is green again.

Browser API

wrl.js is an ES module: a faithful browser port of the identity spine, verified against the reference implementation's canonical bytes. It is what the playground runs, which is why the ids it shows are real.

import * as W from "./wrl.js";

const r = await W.sealWorld(source);
// { ok: true,  source, desugared, origins, graph, artifact, bytes,
//   semanticId: "sem-…", sugared }
// { ok: false, code, message, line, locator, fieldPath }
ExportDoes
sealWorld(src)the whole pipeline: desugar → parse → validate → canonicalize → serialize → hash
desugarCore(src)the source-to-source pre-pass alone
desugarCoreMapped(src)as above, plus authored-line origins for every emitted line
parseWrlCore(src)strict world parser; rejects run inputs
parseWrlLegacyDocument(src)combined-document migration bridge
splitLegacyDocument(src)splits a combined document into world + scenario
validateGraph(g)the structural laws, as typed codes
canonicalizeGraph(g)sorts and normalizes into canonical form
graphToIr(g)the canonical artifact record
serializeArtifact(a)canonical JSON bytes, sorted keys, no whitespace
semanticArtifactId(a)"sem-" + sha256(bytes)
formatCore(g)emits a canonical world document — no scenario syntax, ever
objectPorts(role)the frozen port projection, empty groups omitted
namedRotor(name, n)four exact integer lanes
namedRotorPolicy(name)the rounding provenance id, or null when exact
roundUOverSqrt2(n)the integer quarter-turn projection
selfCheck()re-seals the pinned demo world and asserts the frozen id

Errors are thrown as WrlError carrying code, detail, line, locator and fieldPath. sealWorld catches them and returns them as data.