--- /mnt/user-data/uploads/XZBT-NGN/docs/contract/XZBT-Exhibit-Contract-Specification-v5.2.md 2026-09-14 20:04:53.376627937 +0000 +++ /home/claude/XZBT-Exhibit-Contract-Specification-v5.3.md 2026-09-14 20:34:49.665940986 +0000 @@ -1,10 +1,14 @@ # XZBT Exhibit Contract Specification -## Version 5.2 +## Version 5.3 -**Status:** Proposed normative specification -**Document version:** 5.2 -**Contract family:** XZBT Exhibit Contract -**Compatibility major:** 5 +**Status:** Proposed normative specification +**Document version:** 5.3 +**Contract family:** XZBT Exhibit Contract +**Compatibility major:** 5 +**Supersedes:** Version 5.2, additively. No existing normative requirement +from 5.2 has been removed, weakened, or reinterpreted. Contract 5.3 adds +presentation-surface provisions and surface-related cross-references as +documented in Section 39. **Primary consumers:** XZBT-compatible exhibits and XZBT-NGN Exhibit Engine --- @@ -111,7 +115,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "hello", "requestId": "req-001", "host": { @@ -126,7 +130,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "hello.result", "requestId": "req-001", "sessionId": "sess-7f2a", @@ -137,13 +141,15 @@ }, "contract": { "major": 5, - "minor": 2 + "minor": 3 } } ``` If no compatible major version exists, the exhibit MUST respond with an `error` carrying code `UNSUPPORTED_VERSION`, MUST echo the `requestId` when recoverable, and MUST NOT create a session. +A 5.2-only exhibit reporting `{"major": 5, "minor": 2}` remains fully compatible with a 5.3-aware host under the ordinary contract-major compatibility rule (Section 28.1); nothing in this handshake requires either party to implement 5.3-specific behavior. + --- ## 6. Message Envelope @@ -154,7 +160,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "invoke", "requestId": "req-1042", "sessionId": "sess-7f2a", @@ -169,7 +175,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "invoke.result", "requestId": "req-1042", "sessionId": "sess-7f2a", @@ -181,7 +187,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "error", "requestId": "req-1042", "sessionId": "sess-7f2a", @@ -219,7 +225,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "describe", "requestId": "req-010", "sessionId": "sess-7f2a" @@ -230,7 +236,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "describe.result", "requestId": "req-010", "sessionId": "sess-7f2a", @@ -241,12 +247,13 @@ }, "contract": { "major": 5, - "minor": 2 + "minor": 3 }, "registryRevision": 1, "stateRevision": 27, "capabilities": [], - "targets": [] + "targets": [], + "surfaces": [] } ``` @@ -256,6 +263,14 @@ NGN MUST discover targets instead of assuming that an exhibit exposes a fixed science-fiction vocabulary. +**`surfaces` (introduced in Contract 5.3).** An OPTIONAL array of presentation +surface descriptors, normatively defined in Section 31. Its absence, or an +empty array, both mean the exhibit has not adopted multi-surface presentation +and is functionally equivalent to a Contract 5.2 `describe.result`, which +never contained this field. A 5.3-aware host MUST treat a `describe.result` +lacking `surfaces` identically to one where `surfaces` is present and empty +(Section 31.5). + --- ## 8. Canonical Target IDs @@ -294,6 +309,9 @@ [a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+ ``` +This grammar also governs presentation surface identifiers (Section 31.2); +no separate identifier grammar is defined for surfaces. + ### 8.2 Stability Once published as part of an exhibit's external contract, a canonical target ID becomes part of that exhibit's compatibility surface. @@ -405,6 +423,11 @@ `kind` is authoritative for invokability. No separate `invokable` field is defined. +Presentation surfaces (Section 31) are a structurally distinct descriptor +family from targets and are never expressed using any target `kind`, +including `impulse`. A host MUST NOT infer surface existence from any target +descriptor. + ### 9.5 Impulse arguments (authoritative Contract 5.2 clarification) Impulse descriptors use `arguments`, an array of argument descriptors. This @@ -489,7 +512,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "invoke", "requestId": "req-200", "sessionId": "sess-7f2a", @@ -514,7 +537,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "set", "requestId": "req-201", "sessionId": "sess-7f2a", @@ -537,7 +560,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "state.get", "requestId": "req-300", "sessionId": "sess-7f2a" @@ -548,7 +571,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "state.result", "requestId": "req-300", "sessionId": "sess-7f2a", @@ -568,6 +591,11 @@ A state snapshot MUST NOT imply that every internal exhibit variable is externally exposed. +State exposed through `values` is scoped to the one logical exhibit instance +and its one session, regardless of how many presentation surfaces (Section +31) are currently open. `state.get` MUST NOT be parameterized by surface, and +no surface-specific state view is defined by this contract. + --- ## 14. State Revision and Mutation Transactions @@ -588,6 +616,10 @@ All contract-visible state changes committed by one transaction share one resulting `stateRevision`. +A native interaction originating on any presentation surface (Section 31) is +one mutation transaction, subject to this same rule, regardless of which +surface it originated on. + ### 14.2 Ordering The exhibit MUST: @@ -608,6 +640,11 @@ The counters serve different purposes and MUST NOT be treated as interchangeable. +Multi-surface presentation does not introduce a second revision or sequence +counter of any kind. Every presentation surface of one exhibit instance +observes the same `stateRevision` history and the same event `sequence` +stream defined here. + --- ## 15. Source and Origin @@ -632,6 +669,12 @@ This distinction is required for recording and feedback-loop prevention. +An interaction originating on a presentation surface other than the primary +surface (Section 31.3) uses the same `source` vocabulary as an interaction on +the primary surface — typically `ui`. This contract does not define a +per-surface source value; which surface an interaction originated on is not +contract-visible. + --- ## 16. Events @@ -653,7 +696,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "state.changed", "sessionId": "sess-7f2a", "sequence": 144, @@ -669,7 +712,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "action.executed", "sessionId": "sess-7f2a", "sequence": 145, @@ -710,6 +753,13 @@ It SHOULD NOT automatically record its own `scenario` or host playback events back into the scenario being recorded unless explicitly configured. +### 16.6 `registry.changed` and surfaces (Contract 5.3) + +`registry.changed` (Section 23) covers changes to `surfaces` in addition to +`targets` and capability metadata. A single `registryRevision` governs both; +this contract does not define a separate surface-registry revision. See +Section 31.6. + --- ## 17. Capability Model @@ -751,6 +801,10 @@ A host MUST treat the current discovered state as authoritative. +A presentation surface (Section 31) MAY declare `requires` against +capability IDs defined here, using identical semantics to target `requires` +(Section 9). + --- ## 18. Speech @@ -765,7 +819,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "invoke", "requestId": "req-410", "sessionId": "sess-7f2a", @@ -843,6 +897,9 @@ Each text target SHOULD declare a maximum accepted length. +This restriction applies equally to any text rendered by a presentation +surface (Section 31); surfaces introduce no new text-injection surface area. + --- ## 21. Telemetry @@ -899,7 +956,7 @@ ```json { - "xzbt": "5.2", + "xzbt": "5.3", "type": "set", "requestId": "req-520", "sessionId": "sess-7f2a", @@ -914,7 +971,7 @@ After lease expiration, the exhibit MAY return to simulated ownership. -The exact telemetry lease mechanism remains optional in 5.2. +The exact telemetry lease mechanism remains optional in 5.2, unchanged in 5.3. A simple explicit release mechanism is also acceptable. @@ -932,6 +989,10 @@ Registry revision SHOULD NOT change merely because a fixed target becomes contextually unavailable. +As of Contract 5.3, `registryRevision` also governs the `surfaces` array +(Section 31.6). One counter covers both; this contract does not define an +independent surface-registry revision. + --- ## 24. Error Codes @@ -978,6 +1039,11 @@ Same-origin `postMessage` transports MUST validate both `event.origin` and `event.source` against the expected host relationship. +The same-origin requirement in this section extends to presentation surface +resolution and to any exhibit-internal attachment channel used between an +exhibit's own documents (Section 31.7). Neither introduces a new trust +boundary beyond the one already defined here. + --- ## 26. Scenario Independence @@ -1056,6 +1122,16 @@ An exhibit may add targets without changing the contract version, provided existing target semantics remain compatible. +### 28.8 Contract 5.3 (presentation surfaces) + +Contract 5.3 adds the optional `surfaces` field to `describe.result` +(Section 7) and the normative Presentation Surfaces model (Section 31), per +the rule in 28.2: this is a backward-compatible addition, not a breaking +change. Contract major remains 5. An exhibit reporting `{major: 5, minor: 2}` +is unaffected by this addition and remains fully conformant; a 5.3-aware host +MUST continue to interoperate with it exactly as under Contract 5.2 (Section +31.5). + --- ## 29. Conformance Minimum @@ -1076,6 +1152,11 @@ Speech, telemetry, MIDI, scenarios, Web3D, and any particular exhibit namespace are optional capabilities. +This conformance minimum is unchanged by Contract 5.3. Presentation surfaces +(Section 31) are an optional capability of the same kind: an exhibit that +implements none of Section 31 and never emits `surfaces` remains fully +conformant, at either contract minor. + --- ## 30. Architectural Summary @@ -1089,3 +1170,278 @@ **The contract defines how that capability is described, observed, and invoked.** **XZBT-NGN decides how to orchestrate and integrate it.** + +Version 5.3 preserves this architecture without modification and adds exactly +one optional capability class — presentation surfaces (Section 31) — built +entirely on the existing session, state-revision, event, and registry-revision +mechanisms defined above. + +--- + +## 31. Presentation Surfaces (introduced in Contract 5.3) + +This section is new in Contract 5.3. It formalizes the multi-surface +presentation model approved in XZBT-NGN's Step 6.1 architecture document +(`docs/architecture/XZBT-Multi-Surface-Model-Step6.1.md`, Revision 2). Its +scope is narrowly the discovery and identification of presentation surfaces +and the contract-visible guarantees around them; it does not define display +transport, casting, or remote endpoints (explicitly out of scope — see +Section 31.9). + +### 31.1 Definition + +A **presentation surface** is a renderable, full-screen-capable visual view +of one logical exhibit instance, addressable by a stable identifier, that an +exhibit advertises as independently viewable. Every presentation surface of +one exhibit instance is driven by that exhibit's one authoritative +`stateRevision` history and one event `sequence` stream (Sections 13, 14, +16); this contract defines no mechanism by which two surfaces of the same +exhibit instance could observe divergent state. + +A presentation surface is not a target (Section 9), not a capability +(Section 17), and not the host's own control/administration interface. It +MUST NOT be represented using any target `kind`. + +### 31.2 Surface descriptor + +When an exhibit advertises presentation surfaces, each entry in the +`surfaces` array (Section 7) MUST be an object with the following fields: + +| Field | Requirement | Notes | +| --- | --- | --- | +| `id` | REQUIRED string | MUST conform to the canonical target-ID grammar (Section 8.1). No separate identifier grammar is defined for surfaces. | +| `label` | REQUIRED string | Human-readable. | +| `kind` | REQUIRED, constant `"surface"` | Identifies the descriptor type. | +| `primary` | REQUIRED boolean | Governed by Section 31.3. | +| `url` | REQUIRED string | Governed by Section 31.4. | + +The following fields are OPTIONAL: + +| Field | Purpose | +| --- | --- | +| `description` | Longer human-readable text. | +| `role` | Advisory grouping hint (e.g. `"control"`, `"ambient"`, `"information"`). No contract behavior depends on this field's value in Contract 5.3. | +| `aspectRatio` | Advisory sizing hint (e.g. `"16:9"`). | +| `category` | Mirrors target `category` (Section 9) for consistent grouping. | +| `requires` | Array of capability IDs (Section 17), with identical semantics to target `requires`: the surface remains discoverable but SHOULD be presented as degraded or unavailable when a required capability is not `ready`. | + +No field of a surface descriptor MAY reference a display transport, casting +protocol, network endpoint, or device class (Section 31.9). + +### 31.3 The `primary` invariant and validation order + +`surfaces` (Section 7) has exactly three conformant top-level forms: + +1. **Absent.** The exhibit does not advertise multi-surface presentation. + Functionally equivalent to a Contract 5.2 `describe.result`. +2. **Present and empty (`[]`).** MUST be treated identically to form 1 by a + conformant host. +3. **Present and non-empty.** Evaluated using the deterministic validation + order below. + +A host MUST evaluate a non-empty `surfaces` array in the following order: + +1. Validate each individual surface descriptor against Section 31.2 and + Section 31.4. +2. Discard individually invalid entries (Section 31.5); retain only the + valid entries as the working set. +3. Evaluate the `primary` invariant against the working set, not against the + original array: + - If the working set is empty (every entry was individually invalid), + treat `surfaces` as if it were absent (form 1). + - If the working set contains exactly one entry with `primary: true`, + that entry is the primary surface and the working set is the + conformant surface catalog for this `describe.result`. + - If the working set contains zero entries with `primary: true`, or more + than one, the surface catalog as a whole is malformed: the host MUST + reject the entire working set (not just the offending entries), fall + back to treating `surfaces` as absent (form 1), and SHOULD report a + diagnostic. + +This order is intentional and normative: the `primary` invariant is always +evaluated after individually-invalid entries have already been discarded, so +that one malformed entry cannot be mistaken for a missing or duplicate +`primary` among otherwise-valid entries, and so that discarding a malformed +entry can deterministically change whether the invariant holds. + +The primary surface, once determined by this process, is the surface a +Section-31-aware host that provides no operator surface selection opens by +default, and is the surface whose standalone-use guarantee is unconditional +(Section 31.8). + +### 31.4 URL resolution + +`url` MUST be one of: + +- a path relative to the exhibit's own base document location — the same + base URL already used to establish the exhibit's session; +- such a relative path with an appended query string and/or fragment; +- a bare query string and/or fragment, resolving against the exhibit's own + base document, for a single-page exhibit whose surfaces are views within + one already-served document. + +A host resolving `url` MUST: + +1. resolve it against the exhibit's already-established base URL, not + against the host's own administrative interface location; +2. reject the entry (Section 31.5) if the resolved URL is not same-origin + with that base, per the same-origin requirement in Section 25; +3. apply the same path-containment validation the host already applies to + the exhibit's primary document, if any such validation exists in that + host implementation. + +Absolute, protocol-relative, or cross-origin `url` values MUST be rejected as +malformed individual entries; they do not invalidate the rest of the array. + +### 31.5 Individual entry validation + +A host MUST validate each surface entry independently, as step 1 of the +order defined in Section 31.3. An entry missing a required field, using an +invalid `id` (Section 8.1), or specifying a `url` that fails Section 31.4 is +individually invalid; the host SHOULD skip only that entry, log a +diagnostic, and continue evaluating the remainder of `surfaces`. Individual +entry validation never by itself invalidates the whole array — only the +structural `primary` evaluation performed afterward, against the surviving +valid entries (Section 31.3, steps 2–3), can do that. + +A host that does not implement any Section 31 behavior MAY safely ignore the +`surfaces` field entirely; doing so is fully conformant with the +`describe.result` schema, since the field is OPTIONAL (Section 7). + +An exhibit implementing only Contract 5.2 behavior is unaffected: it never +emits `surfaces`, and no 5.3-only requirement applies to it. + +### 31.6 Registry governance + +`surfaces` is governed by `registryRevision` (Section 23) exactly as +`targets` is. There is no independent surface-registry counter. A +`registry.changed` event (Section 16.6) requires the host to re-run +`describe` and re-read both `targets` and `surfaces`. + +### 31.7 State and interaction + +All presentation surfaces of one exhibit instance share that instance's one +session, one `stateRevision` history, and one event `sequence` stream +(Sections 13, 14, 16); this contract defines no per-surface state channel +and no per-surface session. How an exhibit internally propagates state to +each surface's rendering code is an exhibit implementation detail outside +this contract's normative scope. + +The normative requirement on interaction is narrower than "every native +interaction becomes a public target": any surface-originated interaction +that changes contract-visible persistent state or executes a contract-visible +action MUST obey the same mutation, revision, source, and event semantics +(Sections 14, 15, 16) as the equivalent operation originating from the +exhibit's primary UI or through a contract `set`/`invoke` (Section 14.1). A +surface-local interaction that does not change contract-visible state and +does not execute a contract-visible action — purely presentational +interaction confined to that surface — remains exhibit-internal and is +outside this contract's scope; this contract does not require it to have a +corresponding target. + +An exhibit's internal mechanism for connecting a surface's rendering code to +its own state, including any same-origin channel used between the exhibit's +own documents, is not part of the message envelope defined in Section 6 and +is never observed by the host. + +### 31.8 Standalone behavior + +Per the governing rule in Section 2, an exhibit's `primary` surface (Section +31.3) — or, when `surfaces` is absent or empty, the exhibit's ordinary entry +point — MUST remain fully and unconditionally usable standalone, with no +dependency on XZBT-NGN, on a contract session, or on any other surface. + +A non-primary surface SHOULD remain directly usable without XZBT-NGN. This +contract does not require every non-primary surface to be usable in complete +isolation from the exhibit's other documents; an exhibit MAY have a +non-primary surface depend on another of its own documents being present, as +an exhibit-internal implementation consequence of Section 31.7, provided that +dependency is never on XZBT-NGN itself. + +### 31.9 Non-goals + +This section defines discovery and identification of presentation surfaces +only. It does not define, and MUST NOT be extended by implementations to +imply: + +- casting or remote display protocols; +- network display endpoints or device classes; +- an assignment mechanism between a surface and a physical or logical + display; +- any change to session, state, revision, or event semantics beyond the + cross-references added in Sections 7, 9.4, 13, 14.1, 14.4, 15, 16.6, 17, + 20, 23, 25, and 29 of this document. + +Those concerns are reserved for future contract or XZBT-NGN work and are +explicitly out of scope for Contract 5.3. + +--- + +## 32. Version 5.3 Summary + +Contract 5.3 is Contract 5.2 plus one optional, additive capability: +presentation surfaces (Section 31). No existing normative requirement is +weakened, removed, or reinterpreted. An exhibit or host that implements +nothing in Section 31 is unaffected and remains conformant. The architectural +rule from Section 30 is unchanged: the exhibit exposes what it can do, the +contract defines how that is described and invoked, and XZBT-NGN decides how +to orchestrate it — now including, optionally, orchestrating which of an +exhibit's several presentation surfaces is currently shown. + +--- + +## 39. Changelog (5.2 → 5.3) + +This section exists only in 5.3 and has no 5.2 counterpart. + +**Added:** + +- `surfaces` OPTIONAL field on `describe.result` (Section 7). +- Section 31, Presentation Surfaces: definition, descriptor schema, the + `primary` invariant and its three conformant forms, URL resolution, + validation/backward-compatibility rules, registry governance, the + state/interaction guarantee, standalone-use requirements, and explicit + non-goals. +- Section 28.8, recording the versioning rationale for this addition. +- Cross-reference sentences in Sections 5.2 (hello response commentary), + 9.4, 13, 14.1, 14.4, 15, 16.6, 17, 20, 23, 25, 29, and 30, each noting how + the existing normative rule in that section extends to, or is unaffected + by, presentation surfaces. None of these cross-references change the + normative requirement already stated in 5.2 for that section. + +**Changed:** + +- Header metadata (document version, compatibility statement) — the + supersedes wording was tightened during the pre-6.2 cleanup pass to state + plainly that no existing 5.2 requirement was removed, weakened, or + reinterpreted, rather than characterizing which sections happened to + receive cross-references. +- Illustrative `"xzbt"` and `contract.minor` values in JSON examples updated + from `"5.2"` / `2` to `"5.3"` / `3` throughout, for internal consistency + within this document. This is cosmetic within the example payloads and + does not alter any example's normative meaning. +- Section 31.3 was restructured, during the same cleanup pass, into an + explicit, deterministic validation order (validate individual entries → + discard invalid ones → evaluate the `primary` invariant against the + surviving set) so that a discarded individually-invalid entry cannot leave + the `primary` determination ambiguous. Section 31.5 was narrowed to cover + only individual-entry validation and now cross-references 31.3 for the + structural `primary` evaluation, rather than restating it. This is a + clarification of Revision 2's intent, not a new rule. +- Section 31.7's interaction requirement was narrowed from "every successful + surface interaction behaves like `set`/`invoke`" to the intended scope: + this requirement applies only to interactions that change contract-visible + state or execute a contract-visible action. Purely surface-local, + non-contract-visible interaction is explicitly out of scope and is not + required to have a corresponding target. +- Section 31.3's reference to "a host with no surface-specific UI" was + reworded to "a Section-31-aware host that provides no operator surface + selection," to avoid it being read as covering a host that ignores Section + 31 entirely. + +**Removed:** nothing. No 5.2 requirement is weakened, deleted, or +reinterpreted by this document. + +**Not changed:** Sections 1–4, 6, 8.2–8.3, 10–12, 18–19, 21–22, 24, 26–27, +28.1–28.7 carry no 5.3-specific content and are reproduced from 5.2 +unmodified except for the cosmetic example-version updates noted above.