Manifesto

OpenXP Experience Format Manifesto: Designer intent, declared

This manifesto sets out the principles that govern the design decisions for the OpenXP experience format: designer intent, declared. Every feature, keyword, rule, and constraint in the format traces to one or more of these principles.

This manifesto is the canonical single source of truth. Every rule, schema, fixture, test, tool, and implementation exists in service of these principles. Where any of them disagrees with a principle, the principle wins and the disagreeing artefact contains a defect. This holds for artefacts that already exist, not only for features being proposed.

It follows that an implementation's behaviour is never evidence of what a principle means. Where code and principle disagree, the code is wrong. Recording observed behaviour into the specification to settle such a disagreement converts a defect into the definition, and is precisely the outcome this precedence exists to prevent.

Where the manifesto is silent on a question, admits two readings that imply different behaviour, or contradicts itself, the question is escalated to the platform owner and settled before the work proceeds — never resolved by inference from the rules or the code. A claim that no principle applies must name the principles considered and why each does not; silence is a finding, not a default. The precedence hierarchy and the change obligations are Principle P507 (Manifesto Supremacy); R905 (Manifesto Change Review) binds their enforcement. The manifesto delegates enforcement downward, never meaning.

The principles are organised and prioritised into themed sections. When two principles appear to conflict, earlier sections take precedence (Safety over Composability, Privacy over Governance), but true conflicts should be resolved by design, not by override. Principles within a section are presented in a logical sequence but all carry equal weight unless explicitly stated.

Human-Centred Design

Experience Files Declare Intent

Public framing

OpenXP puts the designer in charge. The designer's creative vision and intent is written into a single “experience” file as structured data, not filed away as a brief no one reads. Every line of an OpenXP experience file is a commitment to what the experience will be — what the participant inhabits, what touchpoints exist, why specific actions fire. The runtime command (# openxp run my-experience.xp --venue my-venue.xpvenue) serves that commitment; sensors, agents, and environmental variation cannot silently override it. This is what separates the format from a runtime configuration language: the designer authors intent once, and the platform binds against that intent everywhere — at validation time, at execution time, at the verifier's static-analysis pass. A camera reading a room, an agent proposing a cue, an operator stepping in at the desk: all of them serve the declaration. None of them redefine it.

Technical framing

The format is a declarative language. Every primitive — every field, every block, every annotation — is a declaration of what the designer commits the experience to be. There are no observation primitives, no descriptive primitives, no inferred-from-runtime primitives in the format. Declaration is the only mode the language operates in.

This is the foundational principle. Every other principle, every primitive shape, every rule and verifier, every export to runtime is in service of this commitment.

Three levels of intent declaration

The format declares intent at three levels, each more specific than the last:

  1. Architectural Primitives declare the shape of the experience — what kind it is and what it commits to as a state of being: realm, domain, modality, synchronicity, senses, accessibility, processing. These are commitments, not constraints: the experience IS this shape from declaration onward; nothing toggles them at runtime. Together they answer "what kind of experience is this, what senses does it engage, who is it for, and how does it handle data?"
  2. Structural primitives declare the capability and boundary the designer commits to expose — what the experience can do and within what limits: touchpoints (the perceptual, output, sensor, and control surfaces — including all perception.X subtypes per Principle P002), journey and state (the state-machine spine), actors and agents (live human delivery + AI participants), policies (the active operational rules per Principles P103–P105), ensembles (bounded participant groupings), environments and zones (spatial regions), plus associated pipeline primitives (capture, deliver) and supporting structures (timelines, properties, safety, assets, schema). Each is exhaustively defined in the format specification (xp-spec-X.X.json); the list here is representative of the structural-intent surface, not exhaustive.
  3. Operational annotations declare the human purpose behind specific actions and transitions: the intent: field is mandatory at experience-body and journey-body, and inherits down the scope tree (per Principle P601). Declaring intent not only defines the specific mechanical operations, it also defines why that moment in the experience exists.

All three levels carry equal weight as declarations. They are not "primitives plus annotations" — they are intent declared at three different scales of the experience.

Commitment vs Constraint. Architectural primitives are commitments — they describe what the experience IS, durably and unconditionally. processing declares the experience's privacy posture; accessibility declares the experience's commitment to participant needs; realm declares where it lives. These are inviolable by design: the format has no construct that changes them mid-execution, and a conforming runtime MUST NOT alter them at runtime. Structural primitives include both capability surfaces (touchpoints, journeys, ensembles — things the experience HAS) and active rules (policies — things the experience ENFORCES). A designer who treats processing as a togglable rule rather than a foundational commitment has misread the level.

experience.xp
1 
2experience "Multi-Sensory Gallery Experience" {
3 intent: "A guided gallery walk that meets every sense without overwhelming any"
4 // Architectural — the shape of the experience
5 realm: physical // physical venue delivery
6 domain: cultural // experience industry context (R231)
7 modality: [guided, ambient] // composable delivery modes (R232)
8 synchronicity: synchronous // timeline-bound execution (R233)
9 senses: [sight, sound] // sensory composition (P601 inheritance)
10 
11 accessibility { // commitment to participant needs (R225-R230)
12 navigational { wheelchair: true, step.free: true }
13 perceptual { language.sign: [it, en], warning.photosensitive: false }
14 }
15 
16 processing { // privacy commitment (P201, R501-R508)
17 mode: transient
18 purpose: "adapt the experience to the guest in the moment"
19 lawful.basis: consent
20 classification {
21 confidentiality: internal
22 integrity: medium
23 availability: low
24 }
25 }
26 
27 // Structural — the capabilities and boundaries
28 touchpoints {
29 farewell_moment: perception.closure { // perception subtype (P002)
30 intent: "Give the guest a sense of completion and gratitude" // operational intent
31 mechanical: output.display
32 }
33 }
34 
35 journey "main" {
36 intent: "Hold the guest in the active scene until the session closes gracefully"
37 initial: active
38 state active {
39 on session_timer.expired -> farewell {
40 intent: "Transition gracefully rather than abruptly ending" // operational intent
41 do: output.scene(name: "farewell")
42 }
43 }
44 state farewell { }
45 }
46}

Declarations describe actual instances, not conceptual possibility

Every experience file declaration refers to the actual thing the experience commits to. A touchpoint's realm declares where that touchpoint instance actually exists; not where similar touchpoints could exist, not where a participant might perceive it as existing, not where a future implementation might place it. A modality declaration commits to which sense channels actually carry the experience; not which channels could conceivably carry it. A domain declaration commits to what the experience actually IS; not which conceptual categories it could be classified under.

The distinction matters because the format is executing an experience, not describing a possibility space. An output.lighting instance connected to DMX lighting hardware exists in the physical realm because the rendering happens in physical space. The same touchpoint type backed by AR rendering of light exists in the augmented realm because the rendering happens in augmented space. These are different instances of the same touchpoint type, with different realm declarations. Neither is a "conceptual" lighting touchpoint; both are actual lighting instances, differing only in where they actually render.

This is what eliminates ambiguity from the format. Without the actual-not-conceptual rule, every declaration becomes negotiable: "could a participant perceive this lighting as part of an AR experience? maybe? so should it be declared augmented?" — and the declaration carries no commitment. With the rule, the declaration is unambiguous: where does the actual lighting render? That is its realm. Whether a participant perceives it as part of an AR scene or not is a separate question, answered elsewhere in the experience definition (typically by the journey's state realm, not by the touchpoint's realm).

Rationale

A specification that conflates declaration with observation is a specification where designer commitment can be silently overridden — by runtime conditions, by sensor input, by agent inference, by environmental variation. The format exists to make designer commitment first-class and durable across all of these.

The format captures designer commitment. The runtime, the agents, the simulators, the actors, the sensors, and the accessibility systems serve that commitment — they make immersion felt, lighting warm, agent reasoning coherent, accessibility real. Participant experience is the whole point of the work.

Runtime input is integral to this. A camera detecting boredom in an experience whose intent is "excitement" does not redefine the intent — it informs the runtime that reality has diverged from the designer's commitment, so the runtime, the actors, and the agents can act to restore it. Sensors, AI agents, and human actors form a closed loop that tracks the declared intent as its set-point. Inputs drive and measure the objective; declared intent is the objective.

The principle is one of authority, not isolation. Observation flows up; declarations stay constant; runtime closes the gap.

Operational intent annotations are not comments; they are functional metadata. The same is true at the structural and architectural levels — fields are not configuration values, they are design commitments. When an AI agent needs to adapt an experience for a different venue, audience, or mood, it consults the declarations at every level: what kind of experience is this (architectural), what capabilities does it expose (structural), what human purpose drives this specific action (operational). The agent serves the declarations; it does not overrule them.

Intent Compounds Through Inheritance. Intent declarations inherit down the lexical scope tree from experience to journey to state to transition. At every level, the resolved intent is the chain of declared intents from experience root to the current block. The deliberative agent (and any consumer of the format) MUST receive the full resolved chain — not just the local declaration — to construct an accurate mental model of why this block exists. Override semantics are REPLACE-on-override (per Principle P601); the parent chain remains traversable. Intent is mandatory at experience-body (the experience's soul) and journey-body (the journey's spine); optional at lower scopes where inheritance applies. Where omitted, the block inherits the nearest enclosing intent.

Experiences Serve Perception

Public framing

OpenXP gives designers a vocabulary for what people actually feel. Six core perceptions — warmth, energy, tension, calm, wonder, and presence — are the design surface the format exposes. A designer working in OpenXP doesn't begin by wiring DMX channels or scripting cue lists; they begin by naming the perception the moment is built to produce. Warmth is the texture of welcome. Energy is the pulse of a room alive. Tension is the held breath before resolution. Calm is where thoughts settle. Wonder is the moment everything shifts. Presence is the feeling of being truly here, now. The runtime, the lighting rig, the spatial audio, the actor's read of the room — all of them serve those declarations. The compilation from "design for wonder" to "DMX universe 1, channels 1–24, warm amber at 70%" lives below the line; the designer stays above it.

P002 is the direct extension of P001 at the level of perception. P001 says every primitive in the format is a declaration of intent; P002 says that at the human level, intent is expressed in the language of feeling and perception. This is the language Shakespeare wrote into his stage directions, the language ritual, ceremony, and theatre have carried for thousands of years, the through-line that every memorable experience — from a play, to a museum gallery, to a theme park attraction, to a brand activation — is built on. The format is the first specification to make that language declarative, structured, and portable. It encodes a long inheritance of creative practice into a form a runtime can execute, a venue can carry forward, and another designer can read.

Technical framing

The fundamental unit of design is human perception — what someone sees, hears, feels, or senses — not a DMX channel, MIDI note, or API call. You describe what people experience, and what machines execute. The mechanical substrate (hardware protocols, sensor readings, actuator commands) exists to produce perceptions. The format provides a human layer above this mechanical layer: designers author in terms of perceptions and intents; the runtime compiles these down to mechanical operations.

P002 stands on its own terms. The declaration is valuable whether or not any sensor will later corroborate it. An actor reading the format knows what to deliver. A lighting designer knows what mood to compose. A producer knows the arc the audience will travel. The measurement of an experience is not a sensor reading; it is the way one guest describes the show to another, the photograph that gets shared, the memory that returns years later. The network that carries an experience is human connection, not wires.

experience.xp
1 
2touchpoints {
3 // Describes what the guest perceives
4 welcome_glow: perception.warmth {
5 intent: "Create a sense of arrival and belonging"
6 realm: physical
7 }
8}
9 
10// The runtime compiles this to mechanical operations:
11// → DMX universe 1, channels 1-24, warm amber at 70%
12// → LED strip zone "entrance", pattern "pulse", colour #F59E0B

The six core perceptions are the design vocabulary. Each names something the designer commits the experience to produce, expressed in terms a human reader recognises. They are authored intent, not telemetry. The runtime — actors, agents, and mechanical outputs together — works to deliver them.

Warmth

The emotional tone of welcome. How a space says hello before anyone speaks.

experience.xp
1 
2// Perception as authored intent
3perception.targets: { warmth: { min: 0.6, ramp: "gentle" } }

Energy

Collective vitality. The pulse of a room full of people alive to what's happening.

experience.xp
1 
2// Shape energy upward
3perception.targets: { energy: { max: 0.95, ramp: "burst" } }

Tension

The held breath of a moment that hasn't resolved. The shape of suspense.

experience.xp
1 
2// Hold a suspense window
3perception.targets: { tension: { min: 0.5, max: 0.8 } }

Calm

The peaceful quality of a contemplative space. Where thoughts settle.

experience.xp
1 
2// Design for sustained calm
3perception.targets: { calm: { min: 0.7, ramp: "sustained" } }

Wonder

Awe and discovery. The moment everything shifts.

experience.xp
1 
2// Design wonder as a peak
3perception.targets: { wonder: { min: 0.8, ramp: "burst" } }

Presence

Spatial awareness. The feeling of being truly here, now.

experience.xp
1 
2// Design presence upward
3perception.targets: { presence: { min: 0.6, ramp: "gentle" } }

Rationale

Donald Hoffman's Interface Theory of Perception demonstrates that our perceptions are not faithful representations of objective reality — they are adaptive interfaces shaped by evolution for fitness, not truth. A red warning light is not "really" red; redness is an interface our visual system constructs. The format takes this insight seriously: we design experiences at the interface level (perceptions, feelings, intents) because that is the level at which humans actually operate. The mechanical substrate is the hidden reality behind the interface. Hoffman's work informs this hierarchy but the format uses its own terminology — perception, intent, senses — rather than claiming to implement any other formal framework.

Feelings Are First-Class

Technical framing

Where P002 establishes the design language of perception and feeling, P003 establishes that the same affective qualities can also enter the runtime as signals, when the technology is available to support it. Emotions, comfort levels, excitement, and other affective states are not side effects — they are first-class inputs to the state machine, as legitimate as an NFC tap or a button press. The format treats feelings as typed data with units, ranges, and sensor mappings.

P003 augments P002; it does not validate it. An experience file expressed in P002 is complete on its own — an actor-led piece with no sensors is a fully valid experience, and many of the most memorable experiences ever staged were exactly that. What P003 adds is responsiveness in time: when a runtime can read affect, it can support the declared intent more attentively. Cues can adjust to the room. Actors can prompt changes, and be prompted. Deliberative agents can respond to intended perceptions, and reach for the next palette.

Mechanically, P003 inherits from P002. The same perception.warmth declaration that authors warmth as intent in P002 also exposes it as a channel the runtime can read when a source is bound. The declaration is not duplicated — same name, same range, now optionally readable. P003 does not introduce a parallel vocabulary; it activates the one P002 already established.

A biometric reading is a perception. A crowd energy level is a perception. A dwell time indicating boredom is a perception. These are not metadata — they are first-class inputs to the state machine. A sensor or an actor can trigger transitions on wonder, shape scenes with calm, and adapt entire journeys to the emotional arc of the room.

experience.xp
1 
2// Perception as runtime signal: warmth measured from a thermal/colour proxy
3on warmth.change -> deepen_welcome {
4 guard: warmth.reading < 0.4
5 do: lights.cue("amber_embrace")
6}
7 
8// Perception sourced from a biometric sensor and aggregated
9touchpoints {
10 crowd_mood: perception.energy {
11 source: sensor.biometric
12 range: [0.0, 1.0]
13 source.window: 30s
14 }
15}
16 
17journey "adaptive_show" {
18 state performing {
19 on crowd_mood.reading -> intensify {
20 guard: crowd_mood.value > 0.8
21 do: output.scene(name: "high_energy")
22 }
23 on crowd_mood.reading -> calm {
24 guard: crowd_mood.value < 0.3
25 do: output.scene(name: "gentle")
26 }
27 }
28}

The source of a perception reading is not fixed. An actor can declare a reading through an actor.* touchpoint (per Principle P005). A reactive agent can derive a value from a window of lower-level signals. A camera can yield a crowd-energy aggregate. Whatever the source, the reading enters the state machine through the same first-class channel.

P002 and P003 are separate principles because both halves stand alone in different ways. A designer can author a complete P002-compliant experience without any P003 measurement: actors and static cues deliver the declared targets, and the experience holds. A runtime can stream rich P003 readings without any P002 declarations, but those readings would be telemetry without creative meaning — numbers without an intent to serve. Together they form the cycle of authored intent and responsive delivery: P002 declares, the runtime executes, P003 listens, the runtime adapts, the declaration holds. Both halves are real on their own terms; together they close the cycle.

Rationale

Every experience produces emotional responses. P003 makes them legible to the runtime as structured signals — typed, ranged, sourced — rather than leaving them implicit in the room. When the runtime can read affect, it can support the designer's intent more responsively. The transmission of the experience itself is still human: guest to friend, photo to feed, memory across time. P003 is how the runtime listens in real time, in service of the intent declared in P002.

The Participant Completes the Experience

Public framing

An OpenXP experience is deliberately incomplete. The format file is not a script the participant performs; it is a set of conditions the participant inhabits and finishes in their own way. Shakespeare's plays endure across four centuries because they admit the audience as the final author of meaning, and remain different on every staging. Keats called this Negative Capability — the capacity to hold uncertainty without collapsing it into a fixed reading. OpenXP makes this architectural rather than incidental. Designers commit to conditions — moments, perceptions, materials, cues, actor judgment, agent attention — and trust the human in the room to inhabit them. An experience that tries to control how participants feel is brittle, because human response refuses control. An experience that encodes conditions and trusts the participant to complete them holds, because it admits human variation as the architecture rather than as the edge case.

Technical framing

The participant is the only first-class entity in an experience whose presence cannot be declared and whose behaviour cannot be specified. They arrive, inhabit, interpret, and depart, bringing with them their own perception, history, attention, and meaning. P001 declares the designer's intent. P002 expresses that intent in the language of perception. P003 lets the runtime listen for affective signals when the technology supports it. P004 names the asymmetry the other three depend on: the experience file encodes the conditions for the experience; the participant completes it.

This is not a limitation of the language. It is the architecture. An experience that tries to control participant response is brittle, because human response cannot be controlled. An experience that encodes conditions — moments, perceptions, materials, cues, actor judgment, agent attention — and trusts the participant to inhabit them is robust, because it admits human variation as foundational rather than as edge case. Shakespeare's plays endure across four centuries and every culture they have travelled to because they are deliberately incomplete; the audience completes them, and completes them differently every time. Keats called this quality Negative Capability — the capacity to be in uncertainties, mysteries, and doubts, without irritable reaching after fact and reason. The format is the first executable specification that names this quality as a design principle.

P004 makes the other three principles cohere by clarifying what they each claim and what they do not.

P001's declarations describe what the experience commits to be, not what each participant will feel. A realm: physical declaration commits the experience to physical delivery; it does not commit the participant to a physical experience of presence — some participants may feel dislocated, transported, or absent. The declaration is real; the response is not predicted.

P002's design vocabulary is for authoring conditions, not for engineering response. A perception.warmth { intent: "welcome" } declaration commits the experience to producing the conditions of welcome; whether a particular participant feels welcome on a particular day is the participant's completion, not the system's verification.

P003's measurement, where present, supports responsiveness, never validation. A camera reading low crowd energy does not mean the design failed; it means the runtime now has the information to adjust in service of the declared intent. Absence of measurement does not mean the experience failed either; it means the participant's completion is happening privately, as it does in every actor-led piece staged for millennia.

P005's actors are the principal vehicles of participant completion when sensors and agents are absent — an actor reading the room is the runtime's oldest measurement channel, predating every electronic sensor by thousands of years.

experience.xp
1 
2touchpoints {
3 // Authored, no measurement intended — common in theatre, ceremony, contemplative spaces
4 third_act_wonder: perception.wonder {
5 intent: "Guests feel the scale of what they have witnessed"
6 range: [0.0, 1.0]
7 source: authored
8 }
9 
10 // Measured, source bound — common in adaptive light/sound, biometric-driven work
11 crowd_mood: perception.energy {
12 intent: "Adapt scene pacing to room energy"
13 range: [0.0, 1.0]
14 source: sensor.biometric
15 source.window: 30s
16 }
17 
18 // Considered, not yet bound — common in multi-venue deployment
19 arrival_warmth: perception.warmth {
20 intent: "Create the feeling of welcome"
21 range: [0.0, 1.0]
22 source.consider: [actor.host, sensor.camera, agent.crowd_warmth]
23 // The format declares the design intent to measure where possible.
24 }
25}

The principle has a practical consequence the spec must honour. Where measurement of perception is possible, the design should consider whether to measure — not to validate the design, but to remain responsive to the participants who are completing it. Where measurement is not possible, the absence is not a defect; the participant completes the experience anyway, through actors, through designed cues, through their own attention. The format must accommodate both modes without privileging the measured one. This is what R308 enforces: every perception touchpoint declaration must record a source consideration — source: authored, a concrete source: binding, or source.consider: [...] — but the validator emits an advisory, not an error, when none are present. The principle prompts the designer to consider; it does not force them to bind.

Rationale

The most durable creative artefacts in human history — Shakespeare's plays, Greek tragedy, ritual, ceremony, the great novels, the great films — are durable because they are incomplete. They create conditions for human response without dictating it. They train interpretation rather than collapsing it. Donald Hoffman's Interface Theory, cited in P002, tells us that perception is an active construction, not a passive reception; the participant's completion of an experience is the same active construction at the level of meaning. An experience-orchestration language that aspires to the durability of Shakespeare's plays — to be carried across venues, across decades, across cultures, by readers who were not in the original room — must encode this asymmetry as a foundational principle, not as an afterthought.

The principle also speaks to a practical truth every experienced designer knows. Humans will find unexpected paths through any experience, often in the most surprising ways. They will misread, repurpose, ignore, redirect, transcend, and surprise. A logical approach to a mechanical problem is always upended by humans. An experience that does not account for this will fail at first contact with reality. An experience that admits it as the architecture — that encodes conditions and trusts the participant to inhabit them — will hold.

The Actor Is a First-Class Participant

Public framing

Live actors carry the most transformative immersive experiences, and OpenXP is designed around that fact rather than against it. The performer, the host, the guide, the musician, the puppeteer — these are the highest-bandwidth instruments in an immersive production, and the technology stack serves them rather than replacing them. The journey graph offers an actor cues; the actor reads the room and chooses the next moment. The AI agent proposes a lighting change; the actor's creative judgment overrides it without ceremony. This is not nostalgia for hand-crafted theatre amongst sensor-driven systems. It is a hierarchy: the technology serves the actor, the actor serves the audience, and the audience completes the experience. OpenXP encodes that hierarchy at the language level so a production team — designer, runtime, operator, performer — can rely on it.

Technical framing

The human actor — performer, stage manager, facilitator, guide, musician, puppeteer — is the most potent creative element in an immersive experience. The format recognises the actor as a distinct event source whose creative decisions in the moment carry higher authority than any AI agent tier (per the Event Authority Hierarchy, Principle P106).

An actor is not an operator. An operator intervenes against the system's intended behaviour — holding, resetting, overriding in response to technical or safety concerns. An actor works within the system's intended behaviour — advancing, selecting, improvising within the creative director's declared constraints.

An actor is not a sensor. A sensor fires when a physical condition is met. An actor fires when a creative judgment is made. The runtime distinguishes between these because they carry different authority, different audit semantics, and different verification requirements.

experience.xp
1touchpoints {
2 // A sensor fires on physical condition
3 reader: sensor.tap { }
4 
5 // An actor fires on creative judgment
6 host: actor.select {
7 role: "macbeth"
8 intent: "Select a visitor for an intimate one-on-one scene"
9 }
10}

Rationale

A language that treats a trained artist's creative decision identically to an MQTT message has failed to understand what makes immersive experiences work. The most transformative, memorable immersive experiences consistently rely on live actors — the highest-impact productions are actor-driven with minimal technology. The technology serves the actor. The actor serves the audience. This hierarchy is operational, not philosophical. When a deliberative agent proposes a lighting change and an actor triggers a scene transition, the actor's creative judgment — constrained by the creator's declared artistic policies — takes precedence.

Human-Readable Code

Technical framing

The format is a text format with a grammar designed for human authorship and review. It is not a serialisation format that happens to be readable. Designers should be able to read, write, and understand the format without specialised tooling.

experience.xp
1 
2// This is valid experience-file text. A designer can read it.
3experience "Immersive Gallery Walk" {
4 version: "1.0"
5 locale: "en-GB"
6 
7 touchpoints {
8 badge: sensor.tap { }
9 spotlight: output.lighting { universe: 1 }
10 }
11 
12 journey "visitor" {
13 initial: entrance
14 
15 state entrance {
16 on badge.tap -> gallery {
17 do: output.scene(name: "welcome_light")
18 }
19 }
20 
21 state gallery { }
22 }
23}

Rationale

Experience design is a collaborative discipline. Designers, producers, account managers, engineers, and operators all need to understand what an experience does. A format that requires a programmer to decode it excludes most of the team. The format's syntax — curly braces, colons, named blocks — is also deliberately familiar to anyone who has worked with human friendly formats such as CSS, JSON, or a configuration file.

One Spine: the Journey State Machine

Public framing

Every OpenXP experience stands on one backbone: the journey.

The journey is the experience written down as a map: its phases, moments, and states, joined by transitions, the cues that move a guest from one to the next. A state is simply where a guest is right now: queuing at the entrance, inside the reveal, lingering in the farewell room. Engineers call this shape a state machine, and the picture it makes, a graph: a fixed set of places a guest can be, with the rules for moving between them. Designers can read the same picture as a storyboard whose arrows are written into the script.

Everything else in the file attaches to that one spine: the sensors that listen, the lights and audio that respond, the actors and agents that read the room, the policies that govern what it may do. One spine means one place to look. A producer reading the journey knows the shape of the show. An operator tracing a fault finds the exact transition that fired. A reviewer deciding whether a construct belongs in the format asks one question: can it take part in the journey? The spine carries the experience; it does not command it. The designer's declared intent remains the authority the whole language serves.

Technical framing

Every experience has exactly one structural spine: the journey state machine. A journey declares the finite set of states a participant can occupy, organised as a phase ⊃ moment ⊃ state hierarchy (phases contain moments, which contain states), and the transitions that move a participant between states in response to events. A state is where a participant is in the experience at a given moment; a transition is the declared rule for what happens next. Together these declarations form a single directed graph, and every other construct in the file attaches to that graph.

That graph anchors three things:

  • Scope integrity. P505's litmus test asks one question of every construct: can it participate in this graph? badge: sensor.tap passes; its tap event drives a declared transition. A moodboard of reference imagery fails: not because creative material is unwelcome but because it is an artefact that shaped the experience yet takes no part in its execution. No guest encounters it, no transition fires on it, no output delivers it. What it carried has already crossed into the experience definition file as declarations: mood, palette, intent fields, perception targets, content for an LED wall. The artefact is retired; its intent persists.
  • Conformance. The spine's lifecycle has three stages, and an implementation's conformance level is how many of them it honours.
    • Validation: prove the graph holds before anything runs; it parses, it terminates, no state is unreachable.
    • Execution: drive the graph from live events, firing only declared transitions.
    • Adaptation: reshape the graph for a new venue, audience, or mood (P001); the result must still clear the first two stages.
  • Traceability. Every rule traces to a principle; every runtime behaviour traces to a declared transition on the spine. That contract is fundamental to how OpenXP operates. When an operator asks why the welcome lighting fired, the trace gives one answer in P402's source-mapped form: transition arrival → gallery, source gallery-night.xp:18, on badge.tap. No behaviour exists that cannot be walked back to a declaration.
experience.xp
1 
2experience "Gallery Night" {
3 spec: "openxp/1.0"
4 intent: "An evening walk through light and sound"
5 
6 touchpoints {
7 badge: sensor.tap { } // attaches to the spine: its events drive transitions
8 glow: perception.warmth {
9 intent: "Arrival feels like welcome"
10 mechanical: output.lighting
11 }
12 }
13 
14 journey "visitor" {
15 intent: "Guide each visitor from arrival into the gallery"
16 initial: arrival // the spine begins here
17 state arrival { // a state: where the participant is
18 on badge.tap -> gallery { // a transition: the declared rule for what happens next
19 do: output.scene(name: "welcome_glow")
20 }
21 }
22 
23 state gallery { }
24 }
25}

The spine is the root of structure, not the root of authority. That position belongs to P001: intent is the foundational principle, and the spine, like every other primitive, exists to carry declared intent into execution. P007 is subordinate to P001 by construction: it names and defines the load-bearing skeleton that execution requires.

The rest of the language meets the spine in four fixed ways:

  • safety { } vetoes first. The experience-root safety { } block checks every event before the state machine processes it. A vetoed event produces no transition; the journey holds its current state. When the fire system trips, no event reaches any journey; every guest holds where they stand until the all-clear.
  • Policies govern every action. Whatever a transition asks the experience to do is evaluated against the declared policies { } before it executes, under P103's four-tier priority; no action source is exempt. When a transition asks the LED wall for an AI-generated scene, the design-tier quality policy passes judgment before a pixel changes. Together these are P103's two safety mechanisms: safety { } screens events before the spine moves; policies screen actions when it does.
  • Perception, participant, and actor signals drive the spine. Perception readings (P002, P003), participant input (P004), and actor judgment (P005) arrive as first-class events. A falling calm reading can soften the lighting, a guest's vote can choose the next room, the host's cue can open the finale: each fires a transition exactly as a badge tap does.
  • Architectural commitments contain the spine. realm, processing, accessibility and their peers declare what the experience is (P001). Every transition runs inside them; none can alter them: the language has no construct that flips processing from transient to retained mid-journey, and no state exists where the wheelchair commitment lapses. A conforming runtime MUST carry these commitments into its storage and delivery paths — for processing, gating capture persistence on the resolved mode and declared retention:. That obligation is normative: the reference runtime enforces processing at authoring/validation time (R501–R508 static validation) and does not yet wire the resolved mode into its capture/store path (R507 records deletion semantics as a deferred runtime contract in the enforcement registry); the commitment binds every implementation that claims conformance.

One spine, not several. An experience may declare many journeys, but they are parts of one transition graph, not rivals to it. Every guarantee built on the spine is the answer to a question asked of the graph. Is the machine finite (P101)? Which transition fires on this event (P102)? Can this construct participate (P505)? One graph gives each question exactly one answer; a second spine would give every question two answers.

Rationale

A specification needs one answer to "what is the structure everything else attaches to?" Without it, scope decisions (P505), conformance definitions, and traceability fragment into per-construct judgment calls. Naming the journey state machine as that anchor settles the question without disturbing the hierarchy of authority: safety and privacy policies still outrank artistic transitions (P103), privacy commitments still bind every conforming implementation unconditionally (P201), and intent remains the root the whole language serves (P001).

The structure/authority distinction matters most under adaptation. When an AI agent reshapes an experience for a new venue or audience, it serves the declarations (P001): the spine tells it what may be restructured; the policy tiers (P103), the processing contracts (P201), and the architectural commitments themselves tell it what may not. Privacy and accessibility are never tunable parameters, even when relaxing them would make the graph reachable.

Art Direction Is First-Class

Public framing

Every immersive experience has a look, a sound, a temperature, a smell — a deliberate aesthetic the designer chose. P002 gives a vocabulary for what a moment should feel like; P008 gives one for how it is dressed to produce that feeling. Perception names the warmth; scenography fixes the candlelit chiaroscuro, the low amber key, the cathedral-scale reverb, the beeswax-and-cold-stone scent that is that warmth in this particular show. A creative director arrives with a palette, references, a mood — a brand. The format is where that art direction is written down and carried forward intact, instead of evaporating at the handoff and being reinvented downstream by whatever tool reaches the gap first.

Technical framing

An experience separates creative expression into three distinct layers, and the spec keeps them distinct:

  • perception names the target feeling — the WHAT (P002).
  • scenography fixes the aesthetic treatment — the HOW.
  • output.* dispatches that treatment to hardware — the execution.
experience.xp
1experience "The Emberline" {
2 intent: "Frozen art direction: candlelit chiaroscuro carried by the scenography blueprint"
3 assets {
4 mood_board: image @assets/mood.jpg@ // exemplar ground truth
5 }
6 scenography { // the HOW, frozen at authoring time
7 visual { treatment: "candlelit chiaroscuro", palette: ["#D96C32", "#1A1D21"], references: [mood_board] }
8 light { key: "low-key", temperature: "warm" }
9 sound { key: "minor", register: "low" }
10 scent { profile: "smoky-sweet", intensity: "subtle" }
11 provenance { brand.id: "openxp.studio", resolved.at: "2026-06-19T00:00:00Z", spec.hash: "…" }
12 }
13 touchpoints {
14 arrival_warmth: perception.warmth { intent: "the feeling of welcome" } // the WHAT
15 nave_light: output.pixels { intent: "carry the low-key warm key" } // the dispatch
16 }
17}

scenography { } is a first-class block declarable at experience / journey / phase / state, fixing creative direction across eight standalone axes — visual · light · sound · motion · materiality · scent · thermal · air — beside an inert provenance { } freeze record. It is a frozen blueprint: its content — palette, keys, profiles, exemplar references — is resolved once at authoring time from the designer's brand and stamped with provenance. Downstream it is read, never re-decided. A state may re-author an axis (replace-per-axis, P601), but every override is itself part of the frozen authored tree; the effective treatment at any state is the deterministic resolution of that tree, never a runtime recomputation modulated by telemetry.

The boundary is exact (P505). Only executable or resolvable ambient channels belong in scenography — palette, lighting keys, colour temperature, audio register, scent/thermal/air profiles, exemplar references. Qualitative, non-executable direction — brand voice, severity-rated constraints, narrative principles — is not scenography; it stays in authoring-time preferences, shaping enrichment but never entering the blueprint. If a field cannot be resolved to a treatment a consumer acts on, it does not belong here.

The blueprint travels. Because it is self-contained and frozen, the same authored intent renders identically across every preview, every venue, and every regeneration. Where a room lacks the hardware to realise an axis — no scent diffuser, no thermal rig — that axis is skipped, never forced and never fatal. Scenography is a portable contract between the creative vision and whatever room receives it.

Rationale

Art direction cannot be formally encoded into the .xp without the language to define it. A designer's palette and mood would only survive as far as the brief and then evaporate at the handoff. The renderer, given no aesthetic intent, risks filling the vacuum with a hardcoded default that at best poorly represents the brief, and at worst, inverts it. The defect is not in the renderer. If the spec has no place to carry the HOW, something downstream will be forced to guess — and a guess is not intent. A specification whose stated purpose is to declare intent (P001) cannot leave the most visible dimension of an experience undeclared. P008 closes that gap the way P002 closes it for feeling: a structured, portable, human-readable layer that the runtime, the renderer, and the next designer all read identically. It is frozen because art direction is a creative commitment, not a runtime variable — provenance stamps where it came from, and immutability guarantees that what the designer authored is what every room renders.

Accessibility Is a First-Class Axis

Public framing

An experience must be able to map against the full range of human bodies and senses, in order to consciously adapt for them. A path with no step-free route, a soundscape with no caption, a cue that assumes a hand others cannot raise — each is a door quietly closed before anyone arrives. Accessibility in the format is not a compliance checklist appended once the design is finished; it is declared in the same breath as the art direction, as a first-class axis of how the experience is navigated, how it is perceived, and how it is interacted with, for participants whose capacities differ. The designer commits — up front, in the file — that the experience reaches more than one kind of body, and that commitment travels with the experience to every venue.

Technical framing

accessibility { } is a first-class block, declarable at experience / journey / state / touchpoint, carrying exactly three sub-axes over a closed vocabulary:

  • navigational — how a participant moves through and orients within the experience.
  • perceptual — how the experience is sensed across sight, sound, and other channels (e.g. captions, audio description, alt text).
  • interactive — how a participant acts on the experience, and what alternatives exist.
experience.xp
1experience "The Emberline" {
2 intent: "Declare the experience's accessibility commitments as first-class structure"
3 accessibility {
4 navigational { step.free: true }
5 perceptual { captions: required, audio.description: available }
6 interactive { input.alternatives: ["gaze", "switch"] }
7 }
8}

Inheritance narrows, never widens (R226): a child scope may add or tighten a commitment, never silently drop one a parent declared. Unknown sub-axes or fields are rejected (closed vocabulary, R225/R228). Visual assets carry per-asset text.alt (R229), overridable per touchpoint (R230). The photosensitive-warning requirement (R227) is universal — a safety floor, not an option.

Rationale

Accessibility behaves exactly like art direction (P008): if the spec gives it no place to live, it survives only as far as the brief and then evaporates — reinvented, inconsistently, by whatever tool reaches the gap first, or omitted entirely. Making it a declared, inherited, validated axis means an experience cannot quietly forget who it excludes; the commitment is authored, carried, and checkable, the same way a palette or a key is.

Modality Declares the Mode of Engagement

Public framing

How does a participant meet the experience — led by the hand or free to wander, washed in ambience or called to perform, alone or shoulder to shoulder with others? This is not decoration on top of the experience; it is the shape of the participation itself. Modality is the experience declaring, first-class, the mode or modes of engagement it commits to produce. It is composable — a piece may be guided and collaborative at once — because real experiences rarely sit in a single mode. And where the mode is collaborative, the structural means of the grouping is the ensembles primitive: modality names the intent to engage participants together; ensembles is how that group is bounded and reasoned about.

Technical framing

modality: is a composable list at experience-body, drawn from a closed five-value enum (R232): guided · autonomous · ambient · performative · collaborative. The list form is mandatory even for a single value (modality: [guided]), order is not semantic, and the enum is vocab-pack-extensible for v1.1+ (R702).

experience.xp
1experience "The Emberline" {
2 modality: [guided, collaborative] // led, and experienced together
3 ensembles {
4 party: formation { size.max: 6 } // the structural realisation of "collaborative"
5 }
6}

Modality is the WHAT — the declared mode; ensembles (R220) is the HOW for its collaborative case — the bounded participant grouping over which guards aggregate. The two compose as distinct layers, the way perception and scenography do under P008; modality never duplicates the ensemble's structure, and the ensemble never re-declares the intent.

Rationale

The mode of engagement determines almost everything downstream — the interface a participant is given, how actors are directed, which sensors are wired, whether a moment waits for one person or for all of them. Left implicit, every tool must guess it, and the guesses diverge. Declaring modality first-class, and composably, makes the participation's shape an authored commitment rather than an emergent accident.

Synchronicity Declares the Experience's Relationship to Time

Public framing

Do all participants move through the experience together, breathing the same beat — or does each travel it at their own pace, the experience reshaping around them — or both at once? An experience's relationship to time is as foundational as its relationship to space, and just as consequential for what the runtime can promise. Synchronicity declares that relationship, first-class: synchronous, asynchronous, or hybrid. It is not a deployment detail discovered when the doors open; it is a commitment the experience makes about how time is shared.

Technical framing

synchronicity: is a closed three-value scalar at experience-body (R233): synchronous · asynchronous · hybrid. It is a runtime-binding field — the enum is frozen at v1.0 (no pack extension) because it imposes constraints on timeline determinism that the runtime must enforce, not merely record.

experience.xp
1experience "The Emberline" {
2 intent: "Declare the experience's relationship to time: a shared spine with self-paced passages"
3 synchronicity: hybrid // a shared spine, with self-paced passages
4}

Synchronicity binds how the runtime may schedule the timeline (P102 Deterministic Execution) and how an ensembles group coordinates in time — synchronous holding members to a shared beat, asynchronous letting each advance on its own thread, hybrid admitting both within one piece. The declaration is the contract the runtime's scheduling guarantees are written against.

Rationale

Temporal mode is a hard constraint, not a preference: a synchronous experience the runtime schedules as asynchronous is simply broken, and the failure surfaces late and expensively. Declaring synchronicity first-class lets the runtime bind its determinism guarantees at authoring time, where a contradiction is a parse-time error rather than an opening-night surprise.

The Sensorium Is Declared and Open

Public framing

Name your senses and you will probably stop at five. Yet close your eyes on a dark ride and the world does not vanish — it changes hands: the tilt of the floor is read by your sense of balance, the nearness of a flame effect by warmth on skin, the position of your own outstretched arm by the body's quiet map of itself. Humans carry more channels than they name. Other subjects carry channels humans lack entirely: a bat sounds out the dark, an elephant hears distant storms through its feet, a robin steers by the planet's magnetic field. Every subject lives inside its own perceptual world — a sliver of reality tuned to its needs — and no subject, human or otherwise, senses everything. An experience reaches its audience through these channels or not at all, so the sensorium is declared first-class: the experience states which of its subject's senses it engages, and because subjects differ, that vocabulary belongs to the world, not to the format.

Technical framing

senses: is a bracketed list, declarable at experience, state, and touchpoint body. Its eight core values are the human baselinesight · sound · touch · smell · taste · vestibular · thermal · proprioception — already three deeper than the folk five. The declaration is an engagement contract, consumed by coherence machinery — never a dispatch target, though adaptive systems may read it as input when substituting one channel for another; treatment belongs to scenography (P008), the felt outcome to perception (P002), delivery alternatives to accessibility (P009), and dispatch to output.*. The set is open and pack-extensible under strict namespacing (R224), because the sensorium of an experience is a property of the world and its subject — human, animal, machine, or simulated — not of the format: a value beyond the baseline is valid only in pack.value form with its namespace matching a use:-imported pack, and a bare unknown value is an error (E1118), so an invented channel can never pass as silent design intent. Inheritance is additive per P601 — a child scope unions with its parent; removing an inherited channel within a scope (sense suppression) is deferred to v2.x.

experience.xp
1experience "The Emberline" {
2 senses: [sight, sound, touch] // the human baseline this piece engages
3 
4 journey "emberline" {
5 initial: blackout_passage
6 
7 state blackout_passage {
8 senses: [vestibular, thermal] // additive: darkness hands the scene to balance and warmth
9 }
10 }
11}

A subject that is not human declares its own channels the same way — the language does not know the difference:

experience.xp
1experience "Low Thunder" {
2 use: "sanctuary/fauna"
3 senses: [sound, fauna.infrasound, fauna.seismic] // an elephant's evening, on the elephant's channels
4}

Compatibility between a declared sense and a touchpoint's mechanical type is advisory (R608): a tool cannot see a venue's real affordances — a bridged audio channel, a hidden haptic actuator — so it may inform the author and must not overrule them. The warning is suppressible per touchpoint, and a pack value carries advisory-only coverage until its pack ships compatibility cells.

Rationale

A closed human sensorium forces dishonest declarations wherever reality exceeds it. A breath-led journey whose spine is interoception must either omit its primary channel or mislabel it as touch — erasing exactly the signal that coherence and consent tooling most needs to see — and an experience designed for an animal cannot be described at all. Sensory biology's central lesson is that every creature perceives its own Umwelt, a thin slice of what there is (von Uexküll's term, retold for a general audience in Ed Yong's An Immense World); a format that hard-codes one species' slice mistakes its own baseline for the world. So the human baseline ships as vocabulary, not as law, and packs carry every other perceptual world. The compatibility check stays advisory for the same reason the set stays open: the format describes sensory worlds it cannot fully see, so it informs the author and never overrules them.

Determinism and Safety

Non-Turing-Complete by Design

Technical framing

The format is intentionally not a full programming language. It has no loops, no variables, no conditionals beyond guards, no recursion, no function definitions. It is a declaration language: you declare states, transitions, guards, and actions. The runtime executes them.

This is not a limitation — it is a safety guarantee. An experience file cannot contain an infinite loop, a stack overflow, a race condition, or an undecidable computation. Every experience file terminates. Every state machine is finite. Every guard is a pure boolean expression.

experience.xp
1// This is ALL you can do in a guard:
2guard: queue.position(profile) <= 5 && not rate.limited(profile, "tap", "3/min")
3 
4// You CANNOT do any of these:
5// guard: while(true) { } — no loops
6// guard: let x = 5; x + 1 — no variables
7// guard: if (a) then b else c — no conditionals (guards ARE the conditional)
8// guard: factorial(n) — no recursion

Rationale

experience files control physical environments where people are present. An infinite loop in a lighting controller is a safety hazard. An undecidable guard expression is an unpredictable experience. By restricting expressiveness, the format guarantees that every file can be fully analysed, simulated, and verified before deployment.

Deterministic Execution

Technical framing

Given the same experience file and the same sequence of events, the runtime MUST produce the same sequence of state transitions and actions. There is no hidden state, no randomness in the core execution model, no ordering ambiguity.

Declaration order is evaluation order. If two transitions could fire on the same event, the first one declared wins. If two policies conflict, priority tier resolves it; within the same tier, declaration order wins.

experience.xp
1state active {
2 // If both guards are true, the FIRST transition fires.
3 // This is deterministic, not random.
4 on sensor.tap -> path_a {
5 guard: queue.position(profile) < 10
6 }
7 on sensor.tap -> path_b {
8 guard: queue.position(profile) < 20
9 }
10}

Scope of the determinism invariant. Determinism governs the behaviour of a single journey instance. If Alice's journey is at state gallery and a proximity_sensor.detected event arrives, the runtime produces exactly the transition the format declares for that state and event. Replay the same sequence of events into the same starting state and you get the same outcome — Alice's journey entrance → gallery → finale → gift_shop is fully deterministic from the moment she begins until she leaves. This is the runtime's core promise to designers, verifiers, and operators.

Files read as a single linear narrative; execution is a graph. An experience file reads from top to bottom as a single, coherent declaration of intent — each phase, moment, and state written once, in place, in the order a designer would narrate it. The runtime executes that content as a graph of state transitions driven by live events, not as a sequence following the file's lexical order. Declaration order resolves guard conflicts within a state (see above) but does not imply that the runtime traverses states top-to-bottom. A participant's actual path through an experience is determined entirely by the events that arrive and the guards that evaluate, which may traverse states in any order the transition graph permits. Global interrupts (emergency stop, fire, venue-wide abort) live in experience-root safety {} and policies {}, evaluated on every event under the Safety > Operator > Artistic authority ordering (P106) — they are orthogonal to the narrative hierarchy (R134) and do not alter this guarantee.

Determinism does NOT govern the relative ordering of events that arrive from multiple participants or external sources at the same moment. Cross-instance arrival order is the concern of the underlying transport (DMX HTP/LTP, OSC ordering, media-server cue semantics) and the policy contention rules (Principle P103's four-tier priority). If Alice and Bob both reach gallery and both trigger proximity events within the same millisecond, the runtime resolves the contention deterministically per the priority tiers — but the specific arrival order is a property of the world, not of the format.

Rationale

Non-determinism in experience execution means unpredictable guest outcomes. A theme park ride that sometimes skips a cue, a retail display that occasionally shows the wrong content, a safety system that fires inconsistently — these are not acceptable. Determinism is the foundation on which operators build trust. A producer who walks through an experience file can predict what the runtime will do. A venue operator can reproduce a guest's reported issue by replaying their event log. A legal reviewer can audit a privacy-sensitive sequence without running the experience. None of this is possible if the runtime might skip a cue, reorder a transition, or branch on a condition outside the experience file.

Four-Tier Priority

Public framing

Every risk in OpenXP is a policy, and every policy carries one of four labels — safety, privacy, operational, design — that determine which wins when two of them collide. Safety is always at the top, and design is always at the bottom. Fire detection beats throughput. Consent beats schedule. Schedule beats aesthetic preference. The four labels are a total order: every policy belongs to exactly one of them, and the order does not move between experiences. A producer reading an experience file knows the chain of precedence without consulting the rule book. A safety reviewer can prove that nothing the language declares can quietly outrank the safety tier. A venue operator can build trust on a contract that is the same on every show. The tiers are public, named, and fixed by the language rather than by the deployment. Declared policies bind on every action source — AI agent decisions, journey-transition do: actions, and any other mechanism that dispatches work into the runtime — so no action category is exempt from the priority order.

Technical framing

Every policy in the format is declared at one of exactly four priority tiers — safety, privacy, operational, design — evaluated in strict order. Safety always wins. Declared policies { priority: ... } bind on every action source: journey-transition do: actions, AI-agent-produced actions, and any future action source. No action category receives an implicit exemption from the priority guarantee. The runtime evaluates the full transition batch against applicable policies before any action executes — if any action in the batch is blocked, no action in the batch executes and the policy's P104 response governs (see P104 — Graduated Response Model for the stop/halt/degrade/advisory vocabulary).

  1. safety — human wellbeing, physical limits, emergency stops
  2. privacy — data protection, consent, biometric handling
  3. operational — throughput, scheduling, resource management
  4. design — creative intent, aesthetic quality, content standards

A lower-tier policy can never override a higher-tier policy. The tiers are total-ordered: every policy belongs to exactly one tier, and tier priority is fixed across the spec — designers cannot re-rank tiers experience-by-experience.

experience.xp
1// Declared in the enclosing experience: properties occupancy, capacity_max,
2// consent, quality; touchpoints biometric_reader (sensor.biometric)
3// and scene_writer (agent.text).
4policies {
5 emergency_capacity {
6 when: property("occupancy") > property("capacity_max")
7 ensure: property("occupancy") <= property("capacity_max")
8 priority: safety
9 response: stop
10 }
11 
12 biometric_consent {
13 when: biometric_reader.sample
14 ensure: property("consent") == true
15 priority: privacy
16 response: halt
17 fallback: activity.log(type: "consent.missing", data: "sample dropped")
18 }
19 
20 queue_throughput {
21 when: queue.position(profile) > 40
22 ensure: queue.position(profile) <= 40
23 priority: operational
24 response: degrade
25 fallback: activity.log(type: "queue.degraded", data: "non-essential outputs skipped")
26 }
27 
28 content_quality {
29 when: scene_writer.complete
30 ensure: property("quality") >= 7
31 priority: design
32 response: advisory
33 }
34}

Distinguishing safety { } from policies { priority: safety }: The format provides two distinct safety mechanisms with different runtime scopes. The safety { } block gates journey transitions at event granularity — it runs before the state-machine tick and can prevent a transition from firing entirely. Declared policies { priority: safety } bind the four-tier priority guarantee on every action source dispatched within an accepted transition — they operate at action-dispatch granularity, one batch per transition. The two mechanisms are complementary: safety { } holds the journey at its current state before a potentially-unsafe transition advances; policies { priority: safety } ensures that any action dispatched during an accepted transition cannot bypass the safety tier. Designers may use both in the same experience.

Rationale

Three-tier priority (safety/operational/design) leaves privacy floating between safety and operations. In physical venues with biometric sensors, cameras, and tracking systems, privacy deserves its own tier — higher than operational convenience, lower than physical safety. The four-tier model makes the hierarchy explicit and unambiguous, and lets verifiers prove that safety-critical and privacy-critical effects always reach the runtime. Binding policies on every action source — not only AI-agent decisions — closes the gap where journey-driven do: actions could otherwise bypass declared constraints, making the priority guarantee verifiable end-to-end across all execution paths.

Graduated Response Model

Technical framing

Policy enforcement is not all-or-nothing. Each policy declares its response level — stop, halt, degrade, or advisory — which the runtime applies when the policy fires.

The four response levels:

  • stop — halt all actions; no fallback executes; the journey does not proceed until an operator intervenes. Default for safety-tier policies.
  • halt — stop the violating action, execute its declared fallback chain (or proceed without the action when the declared fallback is the explicit drop form), and notify the operator; the journey continues. Escalation to stop occurs only when the declared fallbacks fail. Default for privacy-tier policies.
  • degrade — skip non-essential actions and simplify outputs while maintaining the core flow. Default for operational-tier policies.
  • advisory — log and notify only; no automatic action is taken; the journey continues unchanged. Default for design-tier policies.

Each tier has a sensible default but designers can override the default per-policy when needed (e.g., a design-tier policy that fails closed via stop because the creator deemed the violation intolerable).

experience.xp
1// Declared in the enclosing experience: properties fire_detected and filter_passed;
2// touchpoints scene_writer (agent.text) and scene_wall (output.display).
3policies {
4 fire_alarm {
5 when: property("fire_detected") == true
6 ensure: property("fire_detected") == false
7 priority: safety
8 response: stop
9 // Everything stops. No fallback. Lights to emergency preset.
10 }
11 
12 content_filter {
13 when: scene_writer.complete
14 ensure: property("filter_passed") == true
15 priority: design
16 response: degrade
17 fallback: output.scene(name: "default_content")
18 // Swap in safe default content, continue the experience.
19 }
20}

Rationale

Not every violation is an emergency. A stop for a content quality issue would ruin the experience. An advisory for a fire alarm would endanger lives. The graduated model forces designers to think about proportionality and gives the runtime clear instructions for each scenario, while keeping the maximum-severity option (stop) available for the violations that need it.

Three-Stage Policy Lifecycle

Technical framing

Every policy in the format flows through three stages — Author, Validate, and Runtime — and is identified by name, tier, response level, and effect at every stage. Each stage has clear ownership: authors write policies; the validator proves them sound; the runtime executes them.

text
┌───────────┐ ┌──────────────┐ ┌──────────────┐
│ Author │ → │ Validate │ → │ Runtime │
│ (design) │ │ (spec time) │ │ (execute) │
├───────────┤ ├──────────────┤ ├──────────────┤
│ Name │ │ Type-check │ │ Match on │
│ Tier │ │ Tier valid │ │ event │
│ Response │ │ Effect │ │ Evaluate │
│ When │ │ reachable │ │ guard │
│ Effect │ │ No conflict │ │ Apply effect │
└───────────┘ └──────────────┘ └──────────────┘

Rationale

A policy that is only checked at runtime is a policy that surprises operators. A policy that is only checked at design time is a policy that may not behave as expected under real conditions. The three-stage lifecycle separates concerns: design-time intent (Author), pre-deployment proof (Validate), and execution-time enforcement (Runtime). Every policy has a clear contract at each stage and is auditable end to end.

Event Authority Hierarchy

Technical framing

The format declares a strict authority hierarchy that governs which event source wins when two or more sources attempt to influence the same journey state at the same moment. The hierarchy has eight levels, from highest authority to lowest:

  1. Safety Interlock — physical-safety hardware (e-stop, fire alarm, harness sensor) and runtime safety guards. Highest authority. Bypasses all other sources.
  2. Operator Intent — explicit operator command (hold, resume, skip, reset, override). The named human running the experience.
  3. Actor Intent — human-initiated event from an actor.* touchpoint. Live creative judgment.
  4. Artistic Policy — designer-declared policies in the design tier (Principle P103).
  5. Compositional Agentagent.compositional proposing journey-scale structural changes over minute-scale horizons.
  6. Deliberative Agentagent.deliberative proposing considered, multi-step adjustments. LLM-backed.
  7. Reactive Agentagent.reactive responding to immediate sensor input. Rule-based, sub-second.
  8. Format Journey — the declared journey graph itself.

When two sources fire on the same target at the same moment, the higher-authority source's effect wins; the lower-authority source's event is logged as "superseded" in the Decision Log and does not affect the journey state. Where a level holds standing authority (e.g. an operator places the journey in hold), all lower levels are blocked until that authority releases.

The three agent tiers — Reactive, Deliberative, Compositional — each have a fixed contract for latency class, model dependence, and runtime fallback. Reactive: sub-second, rule-based, no LLM. Deliberative: seconds-scale under the author-declared latency.sla (R414), LLM-backed creative decisions, mandatory fallback. Compositional: minute-scale pipelines (video compositing, artwork generation, souvenir production), no required LLM in the core contract but mandatory fallback. The binding deadline is always the author's declared latency.sla; the tier names a latency class, not a magnitude (P506).

Rationale

Without a hierarchy, a reactive agent firing on a participant's facial expression could overrule an actor’s creative judgment, or an operator's emergency hold could be undone by a journey-graph transition. The hierarchy gives every event a known place in the priority order and lets verifiers prove that human authority — the operator at the desk, the actor on the floor — is never silently overruled by an AI proposal or a journey-graph quirk. Hierarchy enforcement is the validator's job and the runtime's job (R409).

Simulation Precedes Production

Technical framing

This is the final gate of the readiness ladder (P109): the transition from simulated to live. An experience file is not cleared for production until the same bundle has produced a successful end-to-end simulation pass against the target venue. Production is the venue-bound live start — a start against a named venue that is not an explicit simulation — and a production runtime MUST refuse it without a passing simulated receipt for the same subject and the same venue: same experience file hash, same venue fingerprint, same touchpoint inventory (R1033). Where no matching receipt exists, the runtime MUST fail with a diagnostic naming the (xp_hash, venue_fingerprint) pair and the verification command that produces a receipt — an xpverify simulation run against the same venue.

The simulation requirement is a strict default, not a recommendation. A conforming production runtime embeds the receipt check and MUST refuse a live start that no receipt admits. That refusal is forgivable, and only by a human hand: an override is offered on the runtime's command-line surface alone, and MUST restate the evidence it waives — the rung whose receipt is absent, that rung's subject hash, and for a venue-bound rung the venue fingerprint — so that it goes stale on any edit of the work and cannot live durably in a launcher script. No environment variable and no configuration key admits an unevidenced start. Only absent evidence is waivable: evidence the runtime re-establishes for itself and finds defective refuses absolutely, because a defect the machine has found is not missing evidence. Every overridden start MUST be recorded in the run's own receipt and disclosed for the whole session, so that a run without evidence can never afterwards be read as a run with it — OpenXP can be overridden, but it can never be silenced. The gate is normative and binds every implementation that claims production readiness.

What the gate establishes is procedural, not physical. It shows that evidence exists for this experience at this venue; it does not inspect the room, and it is not a protective device. It prevents an experience being run as production without evidence. It cannot prevent someone running the venue-bound mode with a queue outside, an unsafe rig overhead, or an interlock defeated — those belong to the certified safety layer this platform coordinates with and never replaces. A conforming implementation MUST NOT present the gate, in a diagnostic or anywhere else, as a statement that the venue is safe.

Rationale

Live immersive experiences run with paying guests in physical venues. The cost of a journey graph that "almost works" is not a stack trace in a log; it is a guest stuck in a dark room, an actor delivering a cue to silence, a queue collapsing under load. Simulation against the target venue catches the categorical failures — unreachable states, dangling touchpoints, missing assets — before they reach guests. The pre-production gate enforces this discipline at the language level instead of trusting that operators will remember to run the simulator.

Producers Read Back What They Write

Technical framing

Every producer of experience-file text — a design tool, a canvas editor, a toolkit pipeline, any future emitter — MUST parse its emitted text back through the canonical parser (P402) before that text is persisted to storage or transmitted across any boundary. Any parse error in the read-back is an unrecoverable producer defect and MUST abort the emission immediately at the emit site: no warning-and-continue, no partial write, no fallback emission.

Emission MUST NOT silently drop, truncate, or reshape what the producer declared: a property intended for the file that cannot survive the canonical emit-then-parse round trip is a producer defect — or a property that does not belong in the file — and the failure MUST surface at emission, not downstream.

Because every producer gates its own output, downstream consumers assume strict validity and MUST NOT compensate: no forgiving parser, no quirks mode, no auto-repair heuristics, no silent workaround. A parse failure downstream is conclusive evidence of an upstream defect and MUST produce an immediate, loud rejection — regardless of who produced the document.

Rationale

An emitter that trusts its own output ships its bugs to every consumer at once, and the failure surfaces where it is most expensive — at load time in another tool, at deploy time in a venue, at run time in front of guests. The moment of emission is the cheapest place the defect will ever be caught: the producing tool still holds the model, the context, and the user who can act on the failure. Reading back through the one canonical parser turns every emission into a self-test of both the producer and the format, and it is what entitles every downstream consumer — including the runtime that drives physical hardware — to fail hard on bad input instead of carrying defensive repair layers or quirks modes. The enforcement rule is R3014.

Readiness Is Staged and Evidenced

Public framing

An experience does not become ready in one step. It is written, then checked, then wired to a particular building, then rehearsed, and only then run in front of guests. Each of those is a different kind of confidence, earned from different evidence, and the difference matters most when someone is deciding whether tonight's show can go ahead. A file that has been proof-read is not a file that has been rehearsed. So an experience carries its evidence with it: at any moment it can say how far along it is, what was checked to get there, and how much of itself was actually exercised. The ladder is short and the rungs are strict, so that "ready" means one thing to the designer who wrote it, the integrator who wired it, and the venue that runs it.

Technical framing

Readiness is a ladder of conditions, each named for what the artefact has acquired rather than for the tool that established it: authored · verified · bound · simulated · live. An artefact claims only conditions it holds evidence for, and a condition cannot be reached over a gap in the ones below it.

Every condition has an open path. Naming rungs for conditions rather than tools is half of tool-independence; the other half is that each condition MUST be establishable — and its receipt emittable — by open-source tooling alone. A tool outside the open pipeline MAY make a rung easier to climb; it MUST NOT be the only way to climb one. An experience's readiness is a property of the artefact and its evidence, never of which vendor's tool its author could obtain.

A check may be deferred only to a stage that can actually perform it. A declaration that no later stage reads MUST be checked at the last stage that reads it — deferring a check to a stage that never inspects the declaration defers it to nothing.

Every condition is evidenced by a receipt naming its subject by hash, the materials the stage consumed — spec, ruleset, enforcement posture, and for venue-bound stages the venue fingerprint — and the coverage achieved. A receipt recording only that a stage passed is not evidence: a stage that cannot state how much of the declared surface it exercised cannot be relied upon by the next. The ladder splits at binding: authored and verified are properties of the experience alone and survive a move to another venue; bound, simulated and live are properties of the experience and one venue together.

Everything an experience needs to be understood travels inside it; only the venue varies. Vocabulary packs are semantics and are embedded, and their absence is fatal. Assets are payload and MAY be referenced externally, their absence governed by the declared per-asset resolution policy. This is also what makes the evidence sound: because packs are covered by the subject hash, changing one invalidates every receipt.

A new condition is admitted to the ladder only where a new external authority enters, responsibility moves to a different party, and a new artefact is produced. A deeper question asked of the same artefact by the same party is a level within a condition, not a rung of its own.

The final gate — production requires a matching simulation receipt, or a human override that restates the missing evidence and is recorded in the run's own receipt — is P107. Enforcement rules: R1050 (stage receipts), R1033 (the production gate).

Rationale

Without a named ladder, "ready" is asserted rather than evidenced, and every party means something different by it: the designer means the file is finished, the integrator means the wiring resolves, the venue means it has seen it run. The words then travel further than the evidence behind them, and the gap is discovered in front of guests.

Naming the rungs is only half of it. The reason each carries coverage rather than a verdict is that a stage which reports only pass or fail can be satisfied vacuously — one guest walked along one happy path, every error branch and every ensemble join untouched, and the artefact emerges wearing a badge it did not earn. That failure is not hypothetical pessimism about tooling; it is what any gate degrades into once passing it becomes the objective. Recording what was exercised makes the badge mean something a later stage can rely on, and makes a thin pass visible as thin rather than indistinguishable from a thorough one.

The deferral clause exists because the tempting answer to any inconvenient check is "a later stage will catch it". That is sound only when a later stage looks. Declarative commitments — the sensory contract, the accessibility commitments — are read by people and downstream tools and never by the executing state machine, so no amount of simulation will ever examine them. For those, the checking stage is the last one that reads them, and there is nothing after it.

The open-path clause exists because the first half of tool-independence — naming conditions, not tools — can be honoured to the letter while a closed tool quietly becomes the only practical way to establish a rung. At that point a readiness claim is a licensing fact, and the platform's promise — that anyone can author, verify, and run an experience with open tools — has failed without any principle noticing. Requiring an open establishment path and an open receipt emitter for every condition makes the promise inspectable: a rung whose mechanics land only in a proprietary tool is a violation here, not a marketing regression.

Privacy by Design

Public framing

Privacy is written into the format next to the sensor that captures the data, not assembled later in a compliance document nobody reads. When a heart-rate monitor is declared in an OpenXP experience, the file states what mode the data lives in (transient, scoped, or retained), what purpose it serves, what lawful basis supports it, and how long it survives — all in a processing { } block attached to the touchpoint itself. The producer of the data sits inline with the contract that governs it. A privacy reviewer can audit the file directly without learning a separate compliance toolchain. An operator cannot deploy a biometric sensor without declaring its processing contract first. This is what privacy by design means at the language level: the contract travels with the capture, the language refuses to separate them, and the discipline becomes the default rather than the exception.

Technical framing

Privacy is not a configuration setting, an external compliance layer, or an afterthought. Privacy by Design is a core architectural posture: every touchpoint that captures data encodes its data-governance contract within the experience definition itself, not in a separate compliance document or runtime configuration. The format encodes this intent in the processing { } block — a language primitive that binds data mode (transient, scoped, or retained), purpose, lawful basis, and retention semantics directly to the touchpoint producing or consuming the data.

experience.xp
1touchpoints {
2 heart_monitor: sensor.biometric {
3 type: "heart_rate"
4 processing {
5 mode: transient
6 purpose: "real-time heart rate; not stored"
7 lawful.basis: interests.legitimate
8 classification {
9 confidentiality: confidential
10 integrity: high
11 availability: medium
12 }
13 }
14 }
15 
16 loyalty_reader: sensor.tap {
17 processing {
18 mode: retained
19 purpose: "loyalty programme tracking"
20 lawful.basis: consent
21 retention.period: "90d"
22 classification {
23 confidentiality: internal
24 integrity: medium
25 availability: low
26 }
27 }
28 }
29}

Rationale

When privacy is a separate configuration file, a deployment setting, or a compliance checkbox, it gets forgotten, misconfigured, or overridden. When the processing { } contract is written into the experience definition itself — right next to the sensor that captures the data — it is visible to every reviewer, auditable by every tool, and enforceable by the runtime. You cannot deploy a biometric sensor without declaring its processing contract. The block name processing aligns the spec with GDPR Article 4(2) ("processing of personal data") and ISO/IEC 27701 vocabulary; the architectural principle of "Privacy by Design" (GDPR Article 25; Cavoukian's 7 PbD foundational principles) is the strategic posture this language primitive implements.

Special Category Data Requires Explicit Declaration

Technical framing

When a touchpoint captures special category data as defined by GDPR Article 9 — biometric data used for identification, health data, racial or ethnic origin, political opinions, religious or philosophical beliefs, sex life, sexual orientation, genetic data, or trade union membership — the format must declare an explicit processing { } block on that touchpoint. The block carries the processing contract directly inline with the touchpoint that captures the data.

experience.xp
1touchpoints {
2 // Biometric data used for identification — special category.
3 // Special-category capture — processing block is mandatory (R509);
4 // the declared categories are named in category.special (R505).
5 identity_camera: sensor.biometric {
6 type: "face.identification"
7 processing {
8 purpose: "guest identification for personalised journey"
9 lawful.basis: consent
10 mode: scoped
11 retention.period: "session"
12 category.special: ["biometric"]
13 classification {
14 confidentiality: restricted
15 integrity: high
16 availability: medium
17 }
18 }
19 }
20}

R505 (Special Category Data Declaration) requires the block to name its categories in category.special; the category vocabulary and any lawful-basis constraint are regime-specific and live in downstream rule and vocabulary packs per P206 (Enable, Don't Embed) — core requires the declaration, never the legal characterisation. R509 (Processing Block Required on Special Category Touchpoints) enforces the principle's "explicit declaration" requirement: no implicit processing on biometric or other special-category touchpoints.

Rationale

GDPR Article 9 treats special category data as fundamentally riskier than ordinary personal data and demands an explicit lawful basis. Encoding the requirement at the language level — not in a separate compliance layer, not in deployment review, not in operator discretion — means every special-category capture surfaces its processing contract inline with the capture itself. Privacy regulators and ethics reviewers can audit the file directly; the requirement cannot be lost between layers. The spec stays as permissive as the law allows; downstream policy and jurisdiction-specific rules narrow as needed.

Ephemeral by Default

Technical framing

Data captured by experiences is ephemeral unless explicitly declared otherwise. The default value of mode is transient — biometric readings, facial recognition data, location tracking, and other sensitive signals exist only for the duration of the session. They are not persisted, not exported, not retained.

To retain data beyond the session, the designer must explicitly opt in with mode: retained and a declared retention.period.

experience.xp
1touchpoints {
2 // Biometric touchpoints require an explicit processing block (R509).
3 // The default mode `transient` honours Ephemeral by Default — the
4 // sensor reads in the moment and discards.
5 mood_sensor: sensor.biometric {
6 type: "gsr"
7 processing {
8 mode: transient
9 purpose: "ambient stress reading; not stored"
10 lawful.basis: interests.legitimate
11 classification {
12 confidentiality: confidential
13 integrity: medium
14 availability: low
15 }
16 }
17 }
18 
19 // Explicit retention — designer has consciously opted in,
20 // evaluated by privacy-priority policies on every event.
21 loyalty_scan: sensor.tap {
22 processing {
23 mode: retained
24 purpose: "loyalty programme tracking"
25 lawful.basis: consent
26 retention.period: "90d"
27 classification {
28 confidentiality: internal
29 integrity: medium
30 availability: low
31 }
32 }
33 }
34}

Rationale

The safest default is to keep nothing. In a world of GDPR, CCPA, and evolving privacy regulation, the default must be privacy-preserving. Designers who need to retain data must consciously choose to do so, and that choice is visible in the experience file for audit and review.

Scoped Data Visibility

Technical framing

Data flows in the format are scoped. A touchpoint's data is visible only within the lexical scope where its processing { } block sits — declared once at the level the designer intends (experience, journey, or state), inherited inward, and invisible outside (resolved per R209 container inheritance). There is no global data bus; visibility is declared, not assumed.

experience.xp
1touchpoints {
2 wristband: sensor.biometric {
3 type: "heart_rate"
4 lawful.basis: consent
5 }
6}
7 
8journey "wellness_walk" {
9 intent: "A wellness walk whose biometric readings stay scoped to this journey"
10 // Processing block at journey scope — wristband data is visible
11 // only within this journey's states (R209 lexical inheritance).
12 // A different journey in the same experience cannot read it.
13 processing {
14 mode: scoped
15 purpose: "journey-scoped wellness check"
16 lawful.basis: consent
17 classification {
18 confidentiality: confidential
19 integrity: high
20 availability: medium
21 }
22 }
23 
24 initial: walking
25 state walking {
26 on wristband.read -> calmed {
27 guard: wristband.value < 80
28 }
29 }
30 state calmed { }
31}

Rationale

In a physical venue with dozens of sensors and cameras, unrestricted data flow creates surveillance. Scoping ensures that a heart rate monitor in a wellness zone cannot be read by a marketing integration in the gift shop. Data goes where the designer sends it, nowhere else.

Adaptive Without Surveillance

Technical framing

The format enables experiences that adapt to participants in real time without building persistent profiles. Three primitives compose to make this possible: realm (Principle P301) declares the medium of presence the designer commits the experience to and constrains the signals available within it; perception captures or infers participant state in the moment; processing modes (Principles P203–P204) guarantee that captured state is used immediately and discarded.

The trade-off is explicit at the language level. A designer who wants higher-fidelity perception — gaze tracking, biometric depth, fine-grained gesture — must commit to stronger transient guarantees in the same block. The trade-off cannot be moved to deployment, to a separate configuration, or to operator discretion.

Rationale

The result is a posture: the participant is fully present, fully read, and fully forgotten. An experience can respond to an emotional peak without recording who felt it. A queue can balance throughput against fatigue without retaining a fatigue history. A wearable can drive an adaptive scene without the scene becoming a profile. This is what separates an adaptive experience from a surveillance system, and the format puts the boundary at the language level — not at the policy layer, not at the deployment review, not at the operator's discretion. By the time an experience file describes adaptive behaviour, the discard contract is already written.

Enable, Don't Embed

Technical framing

The format encodes mechanism, never mandate. Where an external framework — a privacy statute, an accessibility regulation, a safety code — imposes requirements on an experience, the core language provides the structural surface those requirements attach to: the processing { } contract, the declared floor fields, the open annotations { } seam. It does not encode the framework itself. lawful.basis is an open field, not a statute's closed enum; no jurisdiction's threshold lives in the validator; no regime's cross-check runs in core.

The line is descriptive taxonomy versus normative mandate. Core standardises the language of what is occurring: the categories of sensitive capture (category.special), the modes data can live in, the classification axes — neutral descriptors a downstream layer needs before it can judge anything at all, retained even where a legal instrument first named them. What is permissible — which basis a regime accepts, which fields it makes mandatory, which severities it applies — is narrowing, and narrowing belongs downstream: a rule pack may declare a regime's mandates, and a file that satisfies core remains valid everywhere. The statute mutates; the grammar does not.

The delegation is a seam, not a shipped mechanism, and the language says so honestly: core neither performs regulatory cross-checks nor claims another component does.

Rationale

A language whose semantics depend on international law changes meaning when a statute is amended or a case is decided. A regime's enum baked into the grammar makes every experience file carry one jurisdiction's legal vocabulary to venues its regulation never reaches, and demands a grammar change for every jurisdiction added — a compliance engine wearing a format's name, its validity shifting under authors who changed nothing. The format's purpose is to describe, simulate, and execute experiences identically everywhere; compliance is enabled and surfaced, never embedded.

What core guarantees is narrower and stronger: every capture carries its structural contract inline (P201), stated as permissively as the law allows (P202), so any downstream layer — present or future — has the declared facts it needs to judge.

Realm Fluidity

Experiences Flow Across Realms

Public framing

An OpenXP experience is not bound to one medium. A guest might begin in a physical queue, continue on a digital companion app, dive into a virtual reality world, and search for a hidden augmented souvenir — all within the same journey. The format treats realms as first-class declarations: each realm is the designer's commitment to a medium of presence, where the participant actually inhabits the experience at that moment. The four realms are a closed set — physical, digital, augmented, virtual — and the journey flows between them through explicit transitions written into the file. The runtime, the agents, and the touchpoints serve the realm declaration; sensor inference and runtime conditions cannot silently override what the designer has committed the participant to. Modern experiences are not single-channel; OpenXP models the full spectrum without collapsing it into the hardware layer.

Technical framing

The format declares the realm an experience is designed for — the medium of presence the designer commits the participant to inhabit. Realm is a designer commitment, not a perceptual observation: a state declared realm: physical is an experience the designer has committed to delivering through on-site venue hardware, regardless of what sensors might infer about the participant in the moment.

The four realms are a closed enum:

  • physical — on-site venue hardware, real-world installations, mobile-companion experiences anchored in physical space.
  • digital — screens and apps, software-only interfaces, no physical-world coupling required.
  • augmented — actual world layered with constructed elements (AR overlays, projection mapping, headset-augmented venue space).
  • virtual — wholly constructed environments (VR headsets, immersive 3D worlds, fully-rendered virtual spaces).

These are not categories of what the participant perceives — they are categories of what the designer commits the experience to be. An experience declared realm: augmented is a commitment to design for augmented presence; the runtime, agents, sensors, and actors then serve that commitment. This anchors the realm primitive in declaration semantics per Principle P001.

Realm is not confined to a single value across an experience. A guest might begin in a physical queue, continue on a digital companion app, enter a virtual pre-show, and return to physical for the main event — all within a single experience. Container inheritance (Principle P601) propagates realm down through journey, state, and touchpoint scopes; inner blocks can redeclare without affecting siblings (Principle P302). Participants inhabit exactly one realm at a time (Principle P303), with cross-realm content delivery handled by touchpoints declared in any realm (Principle P304). Lexical-scope resolution and transition emission live in R209; touchpoint-realm validation lives in R604; per-touchpoint compatibility is declared in the compatibility.realm table in xp-spec-1.0.json.

experience.xp
1experience "Museum Tour" {
2 intent: "Guide a visitor across physical and augmented exhibit realms"
3 version: "1.0"
4 realm: physical // experience-level commitment
5 
6 touchpoints {
7 exhibit_sensor: sensor.tap { realm: physical }
8 audio_guide: output.audio { realm: digital }
9 ar_overlay: output.display { realm: augmented }
10 }
11 
12 journey "visitor" {
13 intent: "Walk the visitor through the museum's realms without breaking presence"
14 initial: lobby
15 
16 state lobby {
17 on exhibit_sensor.tap -> viewing {
18 realm.transition: physical -> augmented
19 do: output.scene(name: "ar_exhibit_info")
20 }
21 }
22 
23 state viewing { }
24 }
25}

Realm portability is asymmetric. Physical-realm declarations generally embed into less-constrained realms — a digital companion experience can ship alongside a physical experience; augmented overlays can layer onto a physical state. Virtual-realm declarations cannot generally be transposed back to physical without redesign: a wholly-constructed environment loses the physical-anchored constraints (proximity, lighting, room scale) that physical experiences depend on. Designers committing to virtual-realm experiences are committing to a narrower portability profile. v1.0 surfaces the asymmetry as architectural truth, and as machine-readable spec metadata: the formal portability matrix exists as portability.realm in spec/xp-spec-1.0.json, a 4x4 directional matrix over the closed realm enum, with virtual -> physical declared incompatible.

Rationale

Modern experiences are not single-channel. A theme-park app extends the ride. An AR layer enhances a museum exhibit. A virtual pre-show prepares guests for a physical experience. The format must model the full spectrum, not just the hardware layer. By declaring realm as designer commitment rather than perceptual observation, the format keeps designer authority first-class and lets runtime systems serve that authority.

Layered Realm Defaults

Technical framing

The experience declares a default realm; individual journey states, touchpoints, and other inner blocks can override it. Overrides at inner levels do not leak to siblings — a single state declared realm: virtual does not change the realm of neighbouring states. The R209 lexical-scope walk resolves the effective realm for each block by walking outward until it finds a declaration.

experience.xp
1experience "Hybrid Event" {
2 intent: "One physical event carrying a digital stream beside the room"
3 realm: physical // Experience-level realm commitment
4 
5 touchpoints {
6 stage_lights: output.lighting { } // Inherits physical
7 live_stream: output.display { realm: digital } // Override: digital stream
8 vr_backstage: output.display { realm: virtual } // Override: VR environment
9 }
10}

Rationale

Most experiences are primarily in one realm with exceptions. A physical venue experience might have a digital companion app and a virtual preview. Declaring every component's realm individually would be tedious and error-prone. Layered defaults keep the common case simple and the exceptions explicit.

Sequential Realm Inhabitation

Technical framing

A participant is in exactly one realm at a time. The realm of the current state determines which realm — this is a designer commitment, not a phenomenological description of what the participant feels. A VR-coaster rider feels both G-force and a rendered environment simultaneously; the designer commits the state to realm: virtual and treats the physical motion as cross-realm content delivery into that virtual state.

Transitions between realms are first-class runtime events (per R209 and R603). The four-realm enum is closed: no implicit fifth realm, no tacit blending of two declared realms into a third. Where an experience feels hybrid, the designer must commit to one realm and treat the others as content delivered into it.

Rationale

Modern blended experiences — theme-park guest queueing in physical, donning AR glasses for a pre-show in augmented, entering a fully immersive room in virtual — pass through multiple realms on a single journey. Without strict singularity at the state level, the language would have to admit hybrid realms (physical+augmented, virtual+haptic, …) and the combinatorics would explode. By forcing the designer to commit to one realm per state, the format keeps the runtime contract finite, the verifier walk decidable, and the journey itself legible to anyone reading the file. The asymmetry between "what the participant is committed to" and "what touchpoints deliver" is what Principle P304 (Cross-Realm Content Delivery) handles.

Cross-Realm Content Delivery

Technical framing

The realm of a state declares where the participant is committed to being. The realm of a touchpoint declares where the touchpoint's mechanical operation lives. These are independent declarations: a touchpoint declared in one realm can deliver content into a state declared in another, and the runtime bridges them.

experience.xp
1journey "vr_coaster" {
2 state ride {
3 realm: virtual // participant is committed to the rendered environment
4 
5 // Physical motion is delivered into a virtual-realm state:
6 // the coaster mechanism is mechanically physical, but the
7 // participant experiences the G-force while immersed in VR.
8 on motion_sensor.peak -> climax {
9 do: haptic_seat.pulse(intensity: 0.9)
10 }
11 }
12}

The pattern has directional asymmetry. Physical-realm touchpoints can deliver into any state realm (a physical haptic device reaches a participant whose state-realm is virtual; physical room speakers reach a participant in an augmented state). Digital and augmented touchpoints can deliver into states of equal or greater immersion. Virtual-realm touchpoints can only deliver into virtual states — a rendering inside a headset cannot reach a participant who isn't in the headset. Designers commit to the most-immersive state realm an experience requires; physical touchpoints flex to serve it.

Realm is single-valued. The format does not support multi-valued realm declarations like realm: [virtual, physical]. Where an experience feels multi-realm — a VR coaster, an AR theatre, a haptic companion device for a physical ride — the designer declares the realm the participant is committed to, and uses cross-realm content delivery to model touchpoints from other realms. Multi-valued declarations would break inheritance resolution, transition events, verifier reachability, and the asymmetric portability of Principle P301.

Rationale

Modern experiences depend on this independence. A VR coaster's motion is mechanically physical but experientially virtual. A theme-park companion app's notifications are mechanically digital but contextually physical. A museum's room audio is mechanically physical but layered onto an augmented state. If touchpoint realm were forced to match state realm, every cross-realm pattern in immersive experience design would be unrepresentable in the format. Decoupling them lets the language describe what experiences actually are, not what a single-realm model can fit.

Composability and Extensibility

Universal Primitives, Optional Vocabulary Packs

Public framing

OpenXP is one open standard, with a small core of universal primitives that every experience uses and a set of optional vocabulary packs that extend the language for specific industries. The core covers touchpoints, actions, guards, and policies — the structural surface a designer needs whether the work is a theme park ride, a museum gallery, a retail flagship, a wellness journey, or a learning programme. Domain-specific vocabulary loads on top via the use: directive: a theme-park pack adds ride vehicles and queue management; a healthcare pack adds clinical roles and pathway primitives; a museum pack adds exhibit and dwell-time vocabulary. The author learns the core once, and the same language carries across every domain a venue might serve. Cross-domain experiences — a museum that hosts a learning programme and a retail flagship — compose without translation layers.

Technical framing

The format ships with a core set of universal primitives — the touchpoint categories, action types, guard functions, and policy constructs that every experience needs. Domain-specific vocabulary (theme park rides, retail stores, concert venues, museums) is loaded via optional vocabulary packs declared with the use: directive. Pack-defined subtypes use the dot-form category.subtype notation per R112.

experience.xp
1experience "Theme Park Ride" {
2 intent: "Drive a ride sequence with vocabulary loaded from the theme-parks pack"
3 spec: "openxp/1.0"
4 use: "openxp/theme-parks" // Loads ride-specific vocabulary
5 
6 touchpoints {
7 // ride.vehicle is defined in the theme-parks vocabulary pack
8 car: ride.vehicle { capacity: 4, track: "main" }
9 }
10}

Single declaration, no parallel enumeration. Every construct in the format is declared exactly once, in exactly one place. Design-time views — visual arc diagrams, storyboards, walkthrough previews, journey maps — are projections derived from the canonical source by tooling at authoring and display time. They are never authored separately and linked back by string key. A beat written once in its moment block is the only authoritative form; every other representation of that beat is generated from it, like a table of contents auto-built from chapter headings. This is the structural expression of P001 (Experience Files Declare Intent) at the journey level: intent is declared once, not duplicated. Governed by R134 (Single Journey Enumeration) for the phase ⊃ moment ⊃ state hierarchy.

Rationale

A language that tries to include every domain's vocabulary in its core spec becomes bloated and opinionated. A language that provides no vocabulary at all requires every project to reinvent the wheel. Vocabulary packs split the difference: the core is small and universal, domain packs add richness without bloating the base.

Adding new language primitives raises the bar. Top-level blocks, transition forms, action shapes, and guard expressions are the language's structural surface — distinct from vocabulary (subtypes), which lives in packs. A new primitive is justified only when an existing primitive demonstrably cannot express the use case through composition. Three things must be published with any proposal: at least one real use case (cross-industry preferred); a worked attempt to express it with existing primitives; a clear demonstration that composition fails or produces unmanageable cost. New primitives may not be added pre-emptively, "for symmetry," or to "round out the design." The language stays sparse by construction; richness is delivered via vocabulary packs (Principle P406).

The single-declaration discipline gives the same return on the narrative structure that vocabulary packs give on the vocabulary surface: a sparse, authoritative source with derived representations as needed. A parallel journey.map block re-stating the journey's moments is exactly the kind of design-time duplication this principle forbids — it doubles the authoring surface, creates a synchronisation obligation, and violates single-source-of-truth. The journey { phase ⊃ moment ⊃ state } hierarchy is the single canonical tree; tooling projects it into arc views on demand.

One Canonical Format

Technical framing

There is exactly one way to represent an experience. There is no "compact mode", no "binary format", no "alternative syntax". The text format is the canonical format. The runtime may optimise internally (pre-compiled state tables, indexed lookups, compressed assets) but the source of truth is always the human-readable text.

Source mapping connects runtime execution back to authoring-time line numbers, enabling debugging and audit trails.

text
Runtime execution trace:
State transition: idle → active
Source: experience.xp:42 (journey "main", state idle, on reader.tap)
Policy check: safety_first (experience.xp:18)
Action: profile.create (experience.xp:44)

Rationale

Multiple formats create translation bugs, versioning headaches, and tooling fragmentation. One format means one parser, one validator, one set of fixtures, one source of truth. The runtime's internal representation is an optimisation detail, not a format.

Self-Describing

Technical framing

The format should be capable of describing its own tools, processes, and governance. The language’s own evolution — how spec changes are proposed, validated, and released — can be expressed as an experience file.

This is not a theoretical curiosity. It is a concrete design goal: the OpenXP platform's governance process is itself an experience file (platform.xp) that defines the states, transitions, policies, and actions of spec evolution.

experience.xp
1// platform.xp — the platform describes its own governance
2experience "OpenXP Platform Governance" {
3 version: "1.0"
4 
5 touchpoints {
6 spec_change: integration.receive { }
7 test_runner: system.queue { mode: "fifo" }
8 human_review: system.notification { type: "approval" }
9 }
10 
11 policies {
12 backward_compat {
13 when: spec_change.received
14 ensure: xp.all.parses
15 priority: safety
16 }
17 }
18 
19 journey "spec-evolution" {
20 initial: watching
21 
22 state watching {
23 on spec_change.received -> validating {
24 do: test_runner.enqueue(change)
25 }
26 }
27 
28 state validating {
29 on test_runner.tests.passed -> reviewing {
30 do: human_review.send(summary)
31 }
32 }
33 
34 state reviewing {
35 on human_review.approved -> releasing
36 }
37 
38 state releasing {
39 on ci_pipeline.complete -> watching
40 }
41 }
42}

Rationale

A language that cannot describe its own tools is incomplete. Self-description validates that the format is expressive enough for real-world processes, provides a living example of the language, and enables the agentic evolution loop where AI agents propose spec changes governed by policies declared in the format.

Abstraction and Compartmentalisation

Technical framing

Complex experiences should compose from simpler building blocks. The format supports inclusion of sub-experiences, asset references, and modular journey definitions. Each component can be authored, tested, and validated independently.

experience.xp
1experience "Festival" {
2 intent: "Compose a festival from stage sub-experiences included as modules"
3 version: "1.0"
4 
5 // Include sub-experiences as modules
6 include: "stages/main-stage.xp"
7 include: "stages/food-court.xp"
8 include: "stages/vip-lounge.xp"
9 
10 // Shared assets referenced by path
11 assets {
12 brand_logo: @brand/logo-icon-dark.svg@
13 welcome_audio: @assets/welcome.mp3@
14 }
15}

Rationale

A 500-line monolithic experience file is as unmanageable as a 5000-line monolithic program. Composability enables teams to work in parallel, test components in isolation, and reuse proven building blocks across experiences. A theme park's queue management module should work identically whether it is used in a ride, a restaurant, or a retail store.

One Naming, Two Forms

Technical framing

Every named entity and operation in the format is identified by a category and a member: category.subtype for entities that exist, category.verb for operations that fire. The form follows the role. A touchpoint is declared as a block; an action is invoked as a call. The grammar makes the distinction visible to anyone reading a file. A category MAY additionally declare category-level operations in the specification catalogue (category.verb, e.g. actor.cue); a declared operation is valid in type position beside the category's subtypes — the catalogue declaration, not the word's grammatical class, is what admits it there.

When a designer writes actor.host, they are naming a thing — a host who participates in the journey, declared once and referenced by other constructs. When they write cue(), record(), or merge(), they are firing an operation — a runtime event with arguments and a return point. The block-versus-call distinction is not decorative. It mirrors the underlying semantics: entities are stable across a state's lifetime; operations are momentary, ordered, and traceable.

Rationale

This duality keeps the format legible at scale. A reader scanning a journey can distinguish "what exists" from "what happens" at a glance, without consulting the spec to decide whether cue is a touchpoint or an action. The naming rule and the parser cooperate: the parser rejects any form in a position the catalogue does not declare for it, so undeclared misuse fails early rather than producing surprising runtime behaviour.

One Catalogue, Many Domains

Technical framing

The format has one catalogue of categories and subtypes. There are no aliases, no domain dialects, no parallel namespaces. A clinical pathway, an immersive activation, and a learning experience all reach into the same vocabulary; they differ in which subtypes they emphasise, not in which language they speak.

Vocabulary packs extend the catalogue with domain-specific subtypes within the existing category structure. A medical pack adds actor.clinician under the same actor category that already houses actor.host and actor.guide. A retail pack adds wearable.watch.smart.acme under the same wearable.watch.smart family. New subtypes nest under existing categories; they do not invent new top-level vocabularies that compete with the base.

Rationale

This is the rationale that animates the catalogue naming convention. If two domains were free to fork the catalogue, the language would fragment into mutually unintelligible dialects within a year of release. By forcing every subtype into the same compositional shape — and by validating that shape at pack registration — the format stays one language across every domain that adopts it. Authors learn the catalogue once. Tools index it once. Cross-domain experiences (a museum that hosts a learning programme and a retail flagship) compose without translation layers.

Vocabulary packs are files: on disk under spec/vocab/ (cross-experience scope) or carried inside the .xp bundle under vocab/ (experience-local scope). Both flow through the same registration pipeline; both honour R112 and R116. An experience file never declares vocabulary inline.

No subtyping, leaf-typed. The format declares no subtype relation. Every type is its own primitive; relationships between types are advisory metadata, never substitutability. portability.realm documents which realms can flow content into which others — it describes flow direction, not partial order, and a value declared realm: virtual is never substitutable for realm: physical even if the portability matrix permits content flow between them. Type predicates evaluate by exact match against the catalogue. This forecloses an entire class of evolution traps: introducing subtyping additively in a future major release is permitted (R802-safe); declaring a partial order now and backtracking would re-classify existing programs (R802-breaking). The leaf-typed posture preserves the option without committing the cost. See spec/RULES.md R807 + R808 for stability tier mechanics; see Principle P701 (Warn-but-Preserve for Forward Compatibility) for handling of unknown metadata keys.

One declaration, derived projections. P406's "one catalogue" discipline extends to the narrative structure: there is one declaration of each journey beat, in exactly one place in the journey { phase ⊃ moment ⊃ state } tree. No parallel enumeration — no journey.map alongside the journey, no group re-listing states already declared in the transition graph. Design-time views (arc diagrams, storyboards, visual journey maps) are projections computed from the single canonical tree; they are generated by tooling, never retyped. This is the P406 "one catalogue" guarantee applied to authoring: the catalogue of beats is the journey hierarchy itself, not a separate arc-authoring surface that must be kept in sync. Cross-reference: P401 (single-declaration discipline), R134 (Single Journey Enumeration — governs the phase ⊃ moment ⊃ state hierarchy).

One Experience, Two Shapes

Technical framing

An experience travels in one of two shapes: the text alone, or a ZIP container holding that text together with the assets it names and every vocabulary pack it imports. Both are .xp. A reader decides which it has been handed by the bytes, never by the file name — the ZIP magic bytes identify an archive, and manifest.json at its root marks it as an experience container rather than an arbitrary ZIP — so the extension names the experience, not the packaging.

The container is an envelope, not a format. There is no container-only construct, no manifest field that overrides a declaration in the text, and no experience that behaves one way packaged and another way plain. Opening a container yields exactly what the standalone text would have given — plus the assets that text names and the packs it imports, and nothing else. The canonical form of an experience is always the human-readable text (P402); the container is how that text travels with what it references (P404).

A container may also carry evidence about its contents — readiness receipts (P109) — and tooling state that describes how the contents were viewed. Neither is experience content: neither is resolved when the container is opened, and neither may alter what the text declares. A reader that ignores them reads the same experience.

Because a reader must open a container before it reads a single word of the text, the envelope declares what lies inside: the manifest states the spec version its contents target, and a reader rejects any container that omits it (R3011). This is the discipline P504 demands of a runtime, applied at the package boundary — verify the declared version against what you embed, refuse what you cannot verify, never guess.

The two shapes flow through one pipeline. A reader handed plain text synthesises the same manifest in memory — one entry, computed checksum, current spec version — so there is no plain-text code path to drift from the packaged one. Plain text is valid input to every conforming tool. A publisher of a canonical artefact — a use-case template, a lens library, a production deployment — ships the container, so the artefact carries its assets, its checksums, and its declared version with it (R3013). Loose text is for what stays close to home: fixtures, documentation, working files.

Text that imports a vocabulary pack is not a complete artefact in loose form: the pack is its semantics and has nowhere to live outside a container. Such text remains valid parser input, and cannot be delivered or run.

text
welcome-gallery.xp ← one file to the file system; a container to a reader
├── mimetype ← first entry, uncompressed: application/vnd.openxp+zip
├── manifest.json ← spec version, entry point, per-file SHA-256
├── experience.xp ← the entry point the manifest names — unchanged by packaging
└── assets/
├── welcome.mp3
└── hero.png

The container's mechanics are specified in spec/xp-format-1.0.md and the manifest schema spec/xp-manifest-1.0.json.

Rationale

Containers grow semantics unless a principle forbids it. The pressure is constant and each instance is reasonable on its day: a manifest field that would save a parse, a default that applies only when bundled, a shorthand the packager understands and the parser does not. Each addition is small; together they make the envelope a second language wearing the first one's name, and every reader must then implement both. The mimetype-first convention is borrowed from EPUB and ODF deliberately — those formats prove a container can stay an envelope for decades, but only because their specifications say it must.

Declaring the version at the envelope costs one manifest field and removes the failure that is worst precisely when it matters most. A reader that parses a future version's text against today's grammar does not fail — it produces a confident, plausible, wrong result. An honest refusal at the manifest is cheaper than a plausible misreading at the parser.

Splitting the obligation between reader and publisher keeps both halves honest. If readers could demand containers, a fixture or a documentation snippet would need zipping to be read at all, and the format would stop being the approachable text P006 promises. If publishers could ship loose text as a finished artefact, a use-case would arrive without its assets, its checksums, or its declared version — the three promises the manifest exists to keep.

One Fact, One Authority

Technical framing

An experience file and a venue manifest describe the same room from two different authorities. The experience file carries the designer's intent — the spatial requirements the experience states it needs: dimensions, capacity, the commitments it makes to every venue that will ever host it. The venue manifest is the sole carrier of as-built reality: room bounds, footprint polygons, positions — the geometry a survey measured, not the geometry a designer wished. Room shape never enters the experience file. The two are different assertions about the same room — a requirement and a measurement — and each has exactly one home: intent is authoritative in the experience file, reality is authoritative in the venue manifest. Where a consumer needs the room as it is, deterministic venue data supersedes designer-stated requirements — the precedence is fixed, never a consumer's choice — and the stated requirement survives as what the venue is checked against.

Within the venue document, authority is singular too. A venue's spatial description is inline geometry or a reference to an external USD stage — never both (R1017). Whichever form the document carries is the authority; any other form is a projection derived from it. A document that declares two representations of one fact declares no fact at all — it states a conflict without a resolution, and leaves every consumer to invent its own answer.

A projection must survive the round trip. Inline geometry converted to USD and back yields the original, field for field, within a documented numeric tolerance; a USD stage that strictly conforms to the required tier converts to inline and back the same way (R1019). A conversion that loses information is not a projection but a second, poorer source — and re-importing it silently rewrites the fact it claimed to carry.

Rationale

The split follows from what each document can know. A designer authoring an experience for venues not yet chosen cannot know any venue's as-built geometry; a venue survey cannot know what a future experience will require. One document declaring intent and another resolving it against reality is the platform's own architecture — control planes declare desired state, the data plane resolves it — written into the artefacts. Collapse the two and one of them lies: the experience stops being portable, or the venue stops being real.

Two authorities for one room is how a walkthrough validates in the studio and collides at the venue: the diagram draws the designer's rectangle while the guests walk the surveyor's polygon. Naming a single winner — reality, deterministically — turns that disagreement from a silent divergence into a resolvable merge, and the losing value is still preserved where it belongs, as the stated requirement the venue can be checked against.

Interchange with the external world's geometry formats is not optional — venues are surveyed, modelled, and lit in tools that will never speak this platform's schemas, and USD is their lingua franca. What is optional is whether interchange erodes the original. Requiring the round trip to be lossless makes erosion detectable by a gate instead of discoverable at a venue; a projection that cannot come home intact was never a projection.

Touchpoints Declare Capabilities; Connectors Speak Protocols

Public framing

A designer declares that an experience needs a camera, a cue, a light, a tap — never that it needs OSC on port 8000. Which driver carries the cue, which protocol that driver speaks, and which address it goes to, are facts about the venue, and they are written where venue facts live. An experience file declares only the capability it requires; a venue that can provide that capability, by whatever means it has, can host the experience unchanged.

Technical framing

A touchpoint type names a capability — what is sensed, output, controlled or synchronised — never the wire protocol, transport, product or vendor ecosystem that delivers it. The facts about delivery — a host address, a port, a message broker, a credential, a DMX universe and address, a device identifier, a table mapping messages to events — are facts about a particular venue (P408). They belong in that venue's manifest, in the entry that binds this touchpoint; they are not fields of the experience format (P001, P505). The experience file has no construct in which a protocol, an address or a product can be named, so it cannot say one even by accident.

A capability is complete on its own terms: every event and command a type declares must be interpretable definitively by any real endpoint that provides that capability, without deriving meaning from the experience file, the venue file, or documentation held elsewhere. What an experience uses on a touchpoint — the events its journeys, policies and safety envelope listen for, the commands its actions and fallbacks call — is its capability commitment for that touchpoint; no second declaration exists to drift from it, and a venue may host the experience only where it can provide that commitment in full.

Three tests decide what belongs in the catalogue:

  1. The touring test. If a value would change when the same experience tours to a different venue, it is a venue fact.
  2. The naming test. If a name describes how data travels, or which product or vendor carries it, rather than what a participant or environment does, senses or perceives, it is a transport or product binding, not a capability.
  3. The interpretability test. If an endpoint providing the capability could not act on an event or command without consulting another source, the vocabulary is not yet a capability.

A type or field that fails any of the three is a defect in the catalogue and resolves upward under P507.

Three files meet at this boundary, and each has one job (the five artefact types are set out in STANDARDS.md):

  1. The experience file, in the .xp format, is the designer's declaration of intent (P001).
  2. The venue manifest, a .xpvenue file governed by the deployment-wiring rules (R10xx), is the venue's declaration of as-built reality (P408): what hardware exists, and one binding for every touchpoint the experience declares. A binding names a connector — a driver, shipped with the platform, that speaks one or more protocols and states which capabilities it can provide — together with that connector's settings and whether it is being simulated.
  3. The connector fabric is the platform layer between the runtime and the hardware, where the connectors themselves live.

The runtime reads the experience for what is required, the venue manifest for what is bound, and the fabric for what can run.

The experience declares a cue surface and a proximity zone, and nothing about wires:

experience.xp
1touchpoints {
2 house_cues: control.cue {
3 intent: "Fire the lighting and sound cues that frame each act"
4 role: master
5 slot: "stage-left-desk"
6 }
7 foyer_zone: sensor.proximity {
8 intent: "Know when a ticket-holder has arrived in the foyer"
9 slot: "foyer-arch"
10 }
11}
12 
13journey "evening" {
14 initial: doors
15 state doors {
16 on foyer_zone.enter -> seated {
17 do: mcp.call(connector: "#house_cues", args: { command: "go", cue: 1 })
18 }
19 }
20 state seated {}
21}

The venue manifest binds each touchpoint to a connector and carries every transport fact:

json
{
"bindings": {
"house_cues": {
"connector": "osc",
"settings": {
"host": "192.168.10.20",
"send_port": 53000,
"address_map": { "go": "/cue/{cue}/go" }
}
},
"foyer_zone": {
"connector": "ble",
"settings": { "uuid": "…", "enter_threshold": -70 }
}
}
}

A second venue binds house_cues to midi with an event_map and foyer_zone to a camera-based presence connector; the experience file is byte-identical at both. A venue that cannot provide go on a cue connector cannot bind house_cues at all, and says so before anything starts.

Neither block names a type the catalogue does not define, and no venue fact appears in the experience file. That is the whole principle, shown once.

Rationale

This is P001, P002 and P408 applied to the boundary between the experience and the hardware, stated once so it cannot be re-derived differently. P002 places the unit of design at perception, "not a DMX channel, MIDI note, or API call"; P408 places reality in the venue manifest; P505 excludes configuration from the format. Without this boundary a category defines itself by its transport or its vendor, and the experience stops being portable exactly as P408 predicts: a venue that can fulfil the identical intent over a different wire cannot host it without editing the file.

Sensing that describes a participant's action names a capability because it describes what happens at the touchpoint, not how the result travels: a tap, a presence in a zone, a position. Synchronisation to an external clock is a capability; the wire format that carries the clock is not. Cueing an external show system is a capability; the show-control protocol that carries the cue is not. A vendor's hub is a connector; the light, climate or scene it controls is the capability.

Making the experience's own usage its declaration is what keeps the boundary honest in both directions. A declaration the file could write but never exercise is a promise no venue can be checked against; a capability the file exercises but never declared is a hole no gate can see. One source, read from the graph, removes both.

Governance and Evolution

Immutable Released Versions

Technical framing

Once a spec version is released (e.g., openxp/1.0), it is frozen. No fields are added, removed, or changed. All evolution happens in the next version. The spec.hash in every experience file header creates a tamper-evident link between the file and the spec version it was authored against.

experience.xp
1experience "Versioned" {
2 intent: "Pin the authoring-time spec so drift is detectable at load"
3 spec: "openxp/1.0"
4 spec.hash: "a1b2c3d4e5f6" // SHA-256 prefix of the spec at authoring time
5 version: "1.0"
6}

Rationale

Mutable specs create a class of bugs where the same file parses differently depending on when you downloaded the spec. Immutable versions guarantee that a file that parses today will parse identically in ten years.

Additive Within Major, Breaking at Major

Technical framing

Within a major version (1.x), changes are strictly additive: new touchpoint types, new actions, new keywords. No existing construct is removed or changed in meaning. Breaking changes — removal of types, changed semantics, restructured blocks — require a new major version (2.0).

text
1.0 → 1.1: Add perception.temperature type ✓ Additive
1.1 → 1.2: Add "retention" keyword ✓ Additive
1.2 → 2.0: Remove "extend" block, replace with ✓ Breaking (new major)
"vocabulary" block

Rationale

Additive evolution means that every valid 1.0 file is also a valid 1.x file. Designers can adopt new features at their own pace. Parsers can be forward-compatible within a major version. This is the same contract used by semantic versioning, HTTP, and every successful protocol.

Self-Governing Evolution Loop

Public framing

OpenXP is designed to evolve openly, with proposals and human judgment working at different speeds. A proposal — a new touchpoint subtype, a new guard function, a new vocabulary pack — can come from a human contributor or from an AI agent; the loop does not care which hand drafted it. Either way it flows through the fixtures that validate it, the CI that propagates it across the platform, and the human gate that approves every normative change. The platform's own governance is itself an experience file — a journey of states and transitions the runtime executes. This is not a theoretical curiosity. It is the operational shape of how OpenXP gets better without losing the discipline that makes it trustworthy: AI speed paired with human approval, automated validation paired with manual review, continuous evolution paired with immutable releases.

Technical framing

The spec, fixtures, sync tooling, and CI drift checks form the foundation for a self-governing evolution loop: a change is proposed — by a human or by an AI agent — fixtures validate it, CI propagates it, and a human approves every normative change. The loop is governed by policies declared in the format (Principle P403) and protected by immutable versioning (Principle P501).

text
Change proposed (human or AI agent)
→ spec/fixtures/ validate it (parser conformance)
→ CI propagates it (sync-spec.sh + drift check)
→ Human approves it (policy: human_gate)
→ Version bumps
→ All modules sync

Rationale

A language that evolves only through human committee meetings evolves slowly. A language that evolves only through AI proposals evolves dangerously. The self-governing loop combines AI speed with human judgment, automated validation with manual review, continuous evolution with immutable releases.

Embedded Spec

Technical framing

Every runtime embeds its spec version at compile time. The runtime does not download, fetch, or discover its spec at startup. This guarantees that the runtime's behaviour is fully determined by its build, not by external state.

rust
// The spec is literally compiled into the binary
const SPEC: &str = include_str!("specs/xp-spec-1.0.json");
experience.xp
1// At parse time, the runtime verifies the file's spec.hash
2// against the embedded spec. Mismatch = warning.
3experience "Verified" {
4 spec: "openxp/1.0"
5 spec.hash: "a1b2c3d4e5f6"
6}

Rationale

External spec resolution introduces network dependencies, version confusion, and a class of "works on my machine" bugs. Embedding the spec makes the runtime self-contained: if you have the binary and the experience file, you have everything needed to execute the experience. No internet required. No configuration drift possible.

Experience Format Scope Integrity

Technical framing

The format's domain is experience execution. Its vocabulary — touchpoints, states, journeys, agents, policies, actions — forms a structural graph that the runtime traverses when executing an experience. Every construct in the format spec must participate in this graph: it must be reachable from, referenced by, or capable of affecting a touchpoint, state, or journey.

Authoring-time tools, creative thinking aids, design-phase annotations, and configuration formats that share no structural elements with the experience execution graph are not format constructs. Expressing them in the format syntax, extending the spec with their keywords, or including them in .xp files does not make them part of the format — it makes the spec incoherent.

The litmus test is direct: Can this construct appear inside an experience { } block and be meaningfully referenced by or participate in a journey? If the answer is no, it must not extend the format spec.

One surface is declared rather than tested: the meta block (R105) carries author and tool metadata — flat typed key-value pairs preserved verbatim through parse and emit and never interpreted by the runtime. It is an inert, preserved surface, not an execution construct; it extends no execution vocabulary, and declaring behaviour in it has no effect. The carve-out is singular and closed: meta is the one declared home for cataloguing metadata, it grants no precedent, and the litmus test continues to bind every other proposed construct.

This principle exists in productive tension with Principle P403 (Self-Describing). Self-description means that the platform's own evolution process can be expressed as an experience — with touchpoints, states, and journeys the runtime can execute. It does not mean that every tool the platform uses becomes format vocabulary. The self-describing property applies to processes that fit the execution model, not to every artefact in the platform's ecosystem.

Rationale

A spec that absorbs the vocabulary of every adjacent tool loses its identity. The format's execution model guarantees — determinism, safety, policy enforcement, source mapping — derive from its bounded scope. When non-executable constructs enter the spec, those guarantees become undefined at their boundaries. A spec-compliant parser given an unknown block name must produce an error (R105). Allowing authoring tools to extend the spec either forces the runtime to silently ignore those blocks or forces every parser implementer to distinguish "real" runtime blocks from "merely" authoring-time blocks. That distinction has no place in a spec document.

Bounded by Structure, Not by Magnitude

Technical framing

The language guarantees that every evaluation is finite — and it does so structurally, never by fixing a magnitude. Iteration exists only over sets whose bound the author declares or the spec defaults (size.max); deadlines exist only where the author declares them (latency.sla); the property space is finite because every property is written out in the file. The declared bound is the mechanism; no number in the language stands between an author and a legitimate design.

Where a number does appear in the specification tree, it is one of three things, each carrying a machine-readable classification (R904): a value forced by an encoding or a cited external standard (encoding.forced); a conformance floor — "a conformant implementation MUST support at least N" — which binds implementations and is the portability guarantee (support.floor); or a documented implementation cap with a defined error code, which belongs to an implementation, never to the language (implementation.limit). A file within the floors behaves identically on every conformant implementation. An implementation that cannot honour a declared bound rejects the file loudly with its documented diagnostic — truncation, clamping, and partial evaluation are forbidden.

The test for any proposed number is inherited from the strictest precedent available: does the value fall out of the encoding, or is it a guess about what is reasonable? Guesses do not enter the language. Capacity opinions — how many participants, how large a venue — are domain declarations owned by the experience and venue files.

Rationale

Surveyed total and terminating languages state their boundedness guarantee structurally and fix no program-binding magnitude in the specification; where numbers exist they are implementation floors, per-run declared bounds, or implementation caps kept out of the standard. The pattern holds because a magnitude in a language spec is wrong in both directions at once: too low, and it forbids authors legitimate designs while inviting an unanswerable "why not one more?"; too high, and it promises nothing an implementation can rely on. A floor has neither failure mode — raising it costs implementers only, and every file under it is portable everywhere. Fixing the number's role rather than the number itself also makes limits auditable: a classified number can be checked against its justification mechanically, while a bare number in prose drifts into consumer code and hardens into policy nobody chose.

Manifesto Supremacy

Public framing

This manifesto is where OpenXP's intent lives, and everything else — the specification, the rules, the schemas, the code, the CI — was built from it and answers to it. When the manifesto changes, the platform is reviewed against the change. When any other document is added, changed, or deleted, it is checked against the manifesto before the change lands. Where an artefact disagrees with a principle, the artefact is the defect — however established, whoever wrote it. And when the manifesto itself must move, that is a decision the platform owner takes deliberately — never a side effect of other work, never an inference from what the code happens to do. A contributor never has to guess which of two documents wins. The manifesto does, and the escalation path is written down.

Technical framing

The manifesto governs the entire OpenXP platform. The experience format is its first concern, but its authority does not stop at the language: the codebase, the specification, the rules, the governance documents, the standards, and the CI that gates them all exist in service of these principles and are measured against them. Precedence runs manifesto → rules → machine encodings → implementations → fixtures and documentation, and a conflict between any two layers resolves upward, never downward. This principle is complete in itself: nothing below this document defines any part of its meaning. Enforcement is delegated downward, as all enforcement is — R905 (Manifesto Change Review) binds the gates and the platform owner's approval to every change here, serving this principle exactly as every rule serves the principle it traces to.

Three obligations keep the hierarchy live rather than declared:

A change to the manifesto triggers a review of the platform. A changed principle silently re-classifies every artefact built on the old reading, so the change does not land alone: the platform — codebase, specification, rules, governance, standards, CI — is reviewed against the new text, and rules, governance, and standards are created or updated until nothing contradicts it.

A change to any other document is validated against the manifesto first. A document added, updated, or deleted — a rule, a schema, a standard, a workflow, a guide — is checked against the principles before it lands, not after it has been built upon.

Disagreement blocks, or escalates — there is no third path. Where the manifesto disagrees with a proposed change, the change is blocked, or the manifesto must itself be amended — and amending it is an immediate, unequivocal escalation to the platform owner. No document routes around a principle, and no principle is changed as a side effect.

The gates mechanise the structural half of this: every rule traces to a principle it names correctly, every principle is implemented by at least one rule, the supremacy statements stay intact, and the worked examples stay executable. Whether an artefact honours a principle's meaning is not decidable by a script. Reading the principle discharges that residue — prose binds where gates cannot compute.

Rationale

Without a single root, requirements accumulate wherever their writer happened to be standing: a rule citing a workflow document, a doctrine living in a contributor guide, a normative claim in an architecture note that no gate reads. Each placement is reasonable on its day; together they fragment authority until two documents disagree and nothing says which wins. A governance defect of that shape should never wait to be discovered — not by an audit, still less by a failure, the most expensive discovery of all. Conformance belongs at the source: a change validated against the manifesto before it lands never needs finding afterwards.

The review trigger exists because a principle change is never local. The platform was built from this document; changing a sentence here changes what counts as a defect everywhere downstream. Reviewing the platform at the moment of change propagates the decision deliberately. Skipping the review propagates it anyway — later, silently, discovered one contradiction at a time.

Deletion is validated for the same reason addition is. Removing the rule that implements a principle un-implements the principle, and doing so quietly is the easiest route around a constraint — which is why a principle left with no rule tracing to it fails the gate rather than fading out.

The escalation clause is what keeps supremacy honest in both directions. A manifesto that cannot be changed becomes a dead letter routed around by increasingly creative readings; a manifesto changed casually is not a source of truth but a mirror of the code. Requiring the platform owner's deliberate decision — for amendment, and only for amendment — makes the manifesto hard to move and impossible to ignore, which is precisely the combination a single source of truth requires. This matters most when contribution outgrows the founding team: the hierarchy a community inherits must be written where the community reads.

Machines Propose, Humans Decide

Public framing

OpenXP's code may come from a human hand or a machine one — AI agents may draft, gates verify every change, pipelines carry releases. No machine decides. Every decision that binds the platform — what a principle means, what conformance requires, what ships, what is overridden — is taken by a human being. The platform owner is a human, always, and explicitly never a machine. A gate saying no is a human's earlier decision executing; a machine saying yes is never, by itself, permission. This is the law the runtime already lives by — agents propose, policies constrain, operators override — applied to the platform that makes the rules. Wherever automation grows, the loop closes through a person.

Technical framing

The platform owner is a human being — always, and explicitly never a machine, an AI agent, or a quorum of them. The decisions this manifesto reserves are taken by humans and cannot be delegated to automation: amending the manifesto (P507); changing what conformance means — the rules, the grammar, the schemas; authorising a release or a seal (P501) — the machine turns the key, only a human orders the turn; resolving a governance escalation (P507); granting or revoking trust — a conformance certification, a signing key, a steward's appointment; and overriding a gate.

A change is normative when it changes what conforms. A formatting pass, a dependency bump, a regenerated projection that leaves conformance untouched needs gates, not ratification — the reservation binds meaning, not motion.

Machines may participate everywhere else: AI agents draft and propose, gates verify and block, pipelines build and publish. Participation is an option, never an obligation — a human writing every line is equally conformant. The line is authority, not activity, and the asymmetry is deliberate: a machine may always say no — a failed invariant blocks at machine speed, fail-closed — but it may never say yes to a normative change, and it may never forgive its own no. A gate that blocks a change enforces a decision a human already took, encoded as a rule; it exercises no judgement of its own. An escape hatch is a human's hand, or it is a hole. And the human's half must be real: an approval given without reading is a machine approval wearing a human name.

This is one law stated at every altitude. At runtime, agents propose and policies constrain; the operator's intervention outranks every agent tier (P103, P106), and the actor's in-the-moment judgement outranks the machine's (P005). At authoring time, the tool suggests and the author decides (P702). At governance time, automation prepares, validates, and propagates, and a human approves every normative change — the evolution loop (P503) is self-governing in exactly this sense: the platform's own declared policies validate proposals mechanically, and the approvals inside the loop are human.

Rationale

Authority follows accountability, and accountability cannot rest on something that cannot bear it. A human owner can answer for the platform's direction — to a community, a venue, a regulator, a guest who was harmed; a machine can answer for nothing. Reserving the deliberate decisions to the party who can be held responsible for them is not caution about what machines can do — it is precision about what responsibility is.

The deeper failure the reservation prevents is circular authority. Rule One's corollary holds that an implementation's behaviour is never evidence of what a principle means; the strongest form of that failure is automation quietly amending the principle to match the behaviour — a system approving its own homework, converging on whatever the system finds easy. A human decision at the boundary is the anchor that keeps the loop honest: proposals can come from anywhere at machine speed, but nothing becomes normative until a person, outside the automation, chooses it.

The cost is deliberate. A human in the loop is slower than automation, and at the moments this principle governs — an amendment, a seal, an override — slower is the feature: those are precisely the decisions that should not happen at machine speed. And the principle binds the kind of holder, not the number: how ownership is held among humans, delegated, or succeeded is governance mechanics (GOVERNANCE.md); that it is held by humans is constitutional, and does not change with scale.

Inheritance

Container Inheritance for Declarations

Technical framing

Block-scoped declarations — realm, senses, processing, intent, and other context-defining properties — inherit from the enclosing block unless explicitly overridden. A state inside a journey inherits the journey's realm and processing mode; a transition inside a state inherits the state's realm. Exiting an inner block restores the outer block's declaration; a child's override does not leak upward.

Container inheritance is type-correct: each field's merge behaviour matches its semantic type. For fields whose semantic type is one-of-many enum — realm (physical / digital / augmented / virtual), processing.mode (transient / scoped / retained), intent — inheritance applies replace semantics: the innermost declaration wins and the outer value is not consulted further. For fields whose semantic type is many-coexisting envelope — senses (sight + sound + touch can all be present simultaneously) — inheritance applies additive merge: child fields union with parent fields in declaration order, without duplicates.

experience.xp
1experience "Multi-Sense" {
2 intent: "Layer an additional tactile channel onto the experience-wide senses in one quiet zone"
3 senses: [sight, sound]
4 
5 journey "tour" {
6 intent: "A tour whose quiet zone adds a tactile channel"
7 initial: quiet_zone
8 state quiet_zone {
9 senses: [touch]
10 // Effective senses at this state: [sight, sound, touch]
11 }
12 }
13}

Per-field merge mode is declared in spec/xp-spec-1.0.json inheritable: blocks (merge: replace | additive). Sense Suppression — removing a specific inherited sense within a scoped block (e.g. senses { !sight } for a "dark zone inside a sighted realm") — is deferred to v2.x; v1.0 supports additive merge only.

The scenography block (the immutable art-direction blueprint) also joins this inheritable block set, declarable at experience/journey/phase/state. Its inheritable: declares merge: replace-per-axis — each of its eight axes (visual, light, sound, motion, materiality, scent, thermal, air) inherits independently and an inner block's axis supersedes the enclosing axis wholesale, never merging. This is the replace semantics applied at axis granularity, consistent with the realm/senses/processing replacement model above and with R209's unified inheritance walker. The principle-level treatment of the scenography blueprint is Principle P008 (Art Direction Is First-Class).

Rationale

Inheritance reduces repetition without hiding intent. A predominantly-physical experience declares realm: physical once at the experience level; only the scenes that step into augmented or virtual restate it. A reader scanning the file can rely on the rule mechanically — find the nearest enclosing declaration walking outward — without needing to track an accumulated state of merged values. The verifier resolves declarations the same way the human reader does, which keeps tooling and intuition aligned. Cross-reference: R209 (Container Inheritance Resolution).

Validation Discipline

Warn-but-Preserve for Forward Compatibility

Technical framing

experience files outlive the runtimes that first author them. A retail brand publishing an experience pack today expects every venue to play it tomorrow — including venues running last year's runtime, and venues that will update next year. Warn-but-Preserve is the rule that makes this work: when an older runtime encounters something in a file it does not recognise, it tells the operator about it and keeps the unfamiliar content intact. It does not crash and refuse the file. It does not silently delete what it did not understand. The unknown content survives, flagged, until a runtime that recognises it picks up the file.

The formal contract: when a validator or parser meets a key it does not recognise on a metadata field, it MUST emit a diagnostic warning that names the key and the spec version known to the runtime, AND it MUST preserve the unknown key intact through any round-trip. The unknown key is not silently dropped, not promoted to an error, and not mutated. This applies to metadata surfaces — compatibility.realm and the capture { } / deliver { } / schema { } block bodies (R125, R126, R127), and any additive metadata block introduced under R802. It does not apply to structural surfaces — touchpoint categories, journey/state/transition block shapes, action names — which remain hard errors under R105 (reject unknown top-level blocks) and R702 (catalogue uniqueness).

experience.xp
1// Future spec adds `compatibility.realm.bidirectional` metadata key:
2compatibility.realm {
3 physical → digital
4 digital → physical
5 physical ↔ augmented: { bidirectional: true } // ← new key in 1.2
6}

A v1.0 runtime parsing this file warns: "unknown compatibility.realm metadata key bidirectional on edge physical ↔ augmented (runtime knows spec 1.0; key may be defined in a later minor)" — and round-trips the value through emit unchanged. A v1.2 runtime accepts the key without warning. No code path branches on spec version; the warn-and-preserve behaviour is uniform.

Rationale

Warn-but-Preserve trades a verbose log line for forward-compatibility insurance. The trade is heavily worth it: the verbose log is fixable by updating the runtime; the lost data is not. Putting the principle at the language level — not in deployment review, not in a separate compatibility layer — means every runtime, validator, and tool that parses an experience file inherits the contract automatically. Forward compatibility is not a feature opt-in; it is the language's default posture.

Author Authority

Technical framing

The format validator enforces document structure and safety floors. It cannot inspect venue affordances, physical workarounds, staging bridges, or designer intent about physical reality. When a validation check touches the boundary between document structure — decidable from the format text and spec vocabulary alone — and the author's claim about physical reality — which requires venue knowledge the validator cannot have — the check is advisory. It informs the author but does not reject the document.

The validator hard-fails on two categories: safety violations (non-negotiable overrides of author intent due to legal liability or potential runtime harm) and structural well-formedness (the document is not valid experience-file text; downstream consumers cannot trust it). The validator warns on a third category: author-authority plausibility mismatches (the validator infers an inconsistency, but the author may have venue knowledge that resolves it). This three-bucket distinction is the organising axis for posture assignment across all L0-validate rules, formalised by R903.

Three-bucket posture assignment:

  • Safety and operational floor → ERROR. Non-negotiable; overrides author intent. Runtime-crashing or legally liable violations — photosensitive content warnings (R227), event-bus storm limits, recursion guards. The validator is the last mechanical defence before physical or legal harm.
  • Structural well-formedness → ERROR. The document is not valid experience-file text. Grammar violations, missing required fields, naming/format errors, namespace resolution failures, referential integrity breaks, closed-vocabulary membership checks, uniqueness and cardinality constraints. Downstream consumers assume these pass.
  • Author authority and plausibility → WARN. The validator cannot see venue affordances, undeclared physical passages, staging bridges, or the designer's representation of their physical installation. A realm mismatch between spec table and declared touchpoint, or a spatial reachability gap in the modelled topology, is advisory. The validator informs; it does not gatekeep venue knowledge.

Rationale

This principle grounds the platform's validation posture: safety and operational floors are errors, structural well-formedness is an error, and author domain intent warns — the three buckets R903 formalises, with the safety tier's precedence fixed by P103. The validator's authority stops precisely where the author's domain knowledge begins. A lighting designer declaring a DMX fixture as realm: virtual knows whether their installation uses a DMX-to-simulation bridge. A spatial designer declaring a zone transition the topology graph does not model may know of a physical passage not yet captured in the format environment block. Erroring on these cases would make the validator an obstacle rather than an assistant.

The canonical author-authority case is R604 realm-compatibility: virtual subsumes all touchpoint types (anything can be virtualised), and physically "impossible" effects are routinely achievable via undeclared affordances — trap doors, hidden panels, quick-change rigs, bridge adapters. The validator informs the author of the discrepancy; the author decides whether to suppress it (via suppress: [R604] on the touchpoint), update the format to match reality, or leave the advisory unresolved. Three outcomes, all legitimate. None require the validator to veto.

P702 and P701 (Warn-but-Preserve) form the two-pillar posture discipline for this section: P701 governs forward-compatibility — unknown future content is preserved rather than rejected; P702 governs author authority — venue-knowledge mismatches are advised rather than blocked.

Public framing

The format's validator is a structural referee, not a venue inspector. It hard-fails on broken documents and safety violations. It advises on physical plausibility — because the author knows their venue; the validator does not.

Origin & narrative voice

I love this industry. The people are extraordinary. The ambition is often audacious. But there is a technical challenge at the heart of everything we do:

We design for what people should feel, and then we build experiences with tools that only speak in what machines should do.

Somewhere between the original creative vision and the technical delivery, the human intent often gets watered down, or lost. The deeper the experience, the higher the risk — more systems, more vendors, more integration, more points of failure, and more cost. Often invisible until you are on-site at 3am asking “…whose responsibility is that?” — if the idea even made it that far to begin with.

The industry needs a common experience design language that starts with human perception, not hardware protocols.

Foundations that raise the floor, and the ceiling, so that everyone — from the kid in their bedroom to the team delivering something no one has ever built, in a place they have never been, to a deadline they did not set — is building on solid ground. A language that is open, accessible, and belongs to the industry, not locked into one vendor’s ecosystem.