generated from Labyricorn/labyricorn-project-template
1448 lines
41 KiB
Markdown
1448 lines
41 KiB
Markdown
# XZBT Exhibit Contract Specification
|
||
## Version 5.3
|
||
|
||
**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
|
||
|
||
---
|
||
|
||
## 1. Purpose
|
||
|
||
The XZBT Exhibit Contract defines a stable, discoverable language through which an external host can inspect, observe, and control an XZBT-compatible exhibit.
|
||
|
||
The architecture is deliberately separated into three concerns:
|
||
|
||
- **Exhibit:** presentation, native controls, audio, visuals, simulation, and exhibit-specific behavior.
|
||
- **Contract:** the shared control and observation language.
|
||
- **Exhibit Engine:** orchestration, recording, integration, networking, authoring, packaging, and administration.
|
||
|
||
The contract does not require XZBT-NGN to exist for an exhibit to operate.
|
||
|
||
An exhibit implementing this contract remains a complete independently usable artifact.
|
||
|
||
---
|
||
|
||
## 2. Governing Architectural Rule
|
||
|
||
An XZBT-compatible exhibit MUST remain operable without XZBT-NGN.
|
||
|
||
Connection to XZBT-NGN is additive.
|
||
|
||
The exhibit exposes addressable capabilities and state.
|
||
|
||
XZBT-NGN decides how to coordinate, automate, integrate, record, schedule, and package those capabilities.
|
||
|
||
The contract MUST NOT be expanded merely to move Exhibit Engine responsibilities into the exhibit.
|
||
|
||
---
|
||
|
||
## 3. Roles
|
||
|
||
### 3.1 Exhibit responsibilities
|
||
|
||
An exhibit owns:
|
||
|
||
- visual presentation;
|
||
- audio presentation;
|
||
- simulation and ambience;
|
||
- native UI;
|
||
- local input handling;
|
||
- internal state;
|
||
- exhibit-specific actions;
|
||
- standalone behavior;
|
||
- exhibit-native speech rendering;
|
||
- exhibit-native sound rendering;
|
||
- exhibit-native visual effects.
|
||
|
||
### 3.2 Exhibit Engine responsibilities
|
||
|
||
XZBT-NGN may:
|
||
|
||
- discover an exhibit;
|
||
- inspect capabilities and targets;
|
||
- request state;
|
||
- invoke actions;
|
||
- set exposed values;
|
||
- observe normalized events;
|
||
- record operator activity;
|
||
- execute scenarios;
|
||
- author timelines;
|
||
- expose webhooks;
|
||
- manage authentication and authorization;
|
||
- connect external systems;
|
||
- map telemetry;
|
||
- package authored experiences;
|
||
- administer one or more exhibits.
|
||
|
||
---
|
||
|
||
## 4. Transport Independence
|
||
|
||
The contract defines semantics and normalized message envelopes, not one mandatory transport.
|
||
|
||
Permitted transports may include:
|
||
|
||
- same-origin `postMessage`;
|
||
- trusted wrapper bindings;
|
||
- local WebSocket transport;
|
||
- local application IPC;
|
||
- future host-specific bindings.
|
||
|
||
The exhibit MUST NOT need to know whether a request originated from a webhook, Streamer.bot, simulator, telemetry source, administrative UI, scenario engine, or other integration.
|
||
|
||
NGN translates external sources into contract operations.
|
||
|
||
---
|
||
|
||
## 5. Session and Handshake
|
||
|
||
A host MUST establish a contract session before sending control operations through a negotiated transport.
|
||
|
||
A standalone exhibit MUST NOT depend on this handshake for normal operation.
|
||
|
||
`hello` is the only contract message that MAY be sent without a `sessionId`.
|
||
|
||
Every other request MUST carry a valid `sessionId` issued by the exhibit. Missing or unknown session identifiers MUST be rejected with `INVALID_SESSION`.
|
||
|
||
### 5.1 Host hello
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "hello",
|
||
"requestId": "req-001",
|
||
"host": {
|
||
"name": "XZBT-NGN",
|
||
"version": "0.1.0"
|
||
},
|
||
"supportedContractMajors": [5]
|
||
}
|
||
```
|
||
|
||
### 5.2 Exhibit hello response
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "hello.result",
|
||
"requestId": "req-001",
|
||
"sessionId": "sess-7f2a",
|
||
"exhibit": {
|
||
"product": "scifi-xzbt",
|
||
"version": "implementation-defined",
|
||
"build": "implementation-defined"
|
||
},
|
||
"contract": {
|
||
"major": 5,
|
||
"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
|
||
|
||
Every request, response, and event transmitted through the contract MUST use a normalized envelope.
|
||
|
||
### 6.1 Request
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "invoke",
|
||
"requestId": "req-1042",
|
||
"sessionId": "sess-7f2a",
|
||
"target": "sfx.console-beep",
|
||
"args": {}
|
||
}
|
||
```
|
||
|
||
A `set` request MAY additionally contain an `options` object when the target explicitly declares supported options.
|
||
|
||
### 6.2 Response
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "invoke.result",
|
||
"requestId": "req-1042",
|
||
"sessionId": "sess-7f2a",
|
||
"ok": true
|
||
}
|
||
```
|
||
|
||
### 6.3 Error response
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "error",
|
||
"requestId": "req-1042",
|
||
"sessionId": "sess-7f2a",
|
||
"ok": false,
|
||
"error": {
|
||
"code": "UNKNOWN_TARGET",
|
||
"message": "The requested target is not registered."
|
||
}
|
||
}
|
||
```
|
||
|
||
When a malformed message cannot be parsed well enough to recover `requestId` or `sessionId`, either field MAY be `null`.
|
||
|
||
### 6.4 Correlation
|
||
|
||
`requestId` MUST be unique within a host session.
|
||
|
||
Responses MUST echo the corresponding `requestId`.
|
||
|
||
Events are asynchronous and do not require a `requestId`, but SHOULD include a `correlationId` when directly caused by a specific request.
|
||
|
||
### 6.5 Version field
|
||
|
||
The `xzbt` field is advisory metadata for diagnostics.
|
||
|
||
The negotiated session contract major/minor is authoritative after handshake.
|
||
|
||
---
|
||
|
||
## 7. Describe
|
||
|
||
The host MUST be able to request a complete machine-readable description.
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "describe",
|
||
"requestId": "req-010",
|
||
"sessionId": "sess-7f2a"
|
||
}
|
||
```
|
||
|
||
Response:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "describe.result",
|
||
"requestId": "req-010",
|
||
"sessionId": "sess-7f2a",
|
||
"exhibit": {
|
||
"product": "scifi-xzbt",
|
||
"version": "implementation-defined",
|
||
"build": "implementation-defined"
|
||
},
|
||
"contract": {
|
||
"major": 5,
|
||
"minor": 3
|
||
},
|
||
"registryRevision": 1,
|
||
"stateRevision": 27,
|
||
"capabilities": [],
|
||
"targets": [],
|
||
"surfaces": []
|
||
}
|
||
```
|
||
|
||
`describe` is authoritative for the current session.
|
||
|
||
The `capabilities` array is a snapshot of current capability states at the time of the response.
|
||
|
||
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
|
||
|
||
External contract target IDs use a canonical dotted namespace.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
transport.playing
|
||
transport.muted
|
||
mix.master
|
||
view.observation
|
||
view.viewport-frame
|
||
event.alert-red
|
||
alert.active
|
||
sfx.console-beep
|
||
speech.say
|
||
telemetry.engine.temperature
|
||
```
|
||
|
||
### 8.1 Grammar
|
||
|
||
A target ID MUST:
|
||
|
||
- use lowercase ASCII letters, digits, hyphens, and dots;
|
||
- begin with a lowercase letter;
|
||
- contain one or more dot-separated segments;
|
||
- not contain whitespace;
|
||
- not contain empty segments;
|
||
- not be interpreted as a JavaScript property path.
|
||
|
||
Recommended grammar:
|
||
|
||
```text
|
||
[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.
|
||
|
||
Target IDs SHOULD NOT be renamed casually.
|
||
|
||
Deprecated targets SHOULD remain discoverable long enough for hosts to migrate.
|
||
|
||
### 8.3 Internal mapping and normalization
|
||
|
||
An exhibit MAY map canonical external IDs to existing internal IDs.
|
||
|
||
Example:
|
||
|
||
```text
|
||
mix.master -> master-vol
|
||
```
|
||
|
||
Mapping is not always a rename.
|
||
|
||
Example:
|
||
|
||
```text
|
||
transport.playing -> absolute-state adapter around existing transport logic
|
||
```
|
||
|
||
An exhibit MUST NOT implement an externally visible persistent state target merely by blindly toggling an existing control.
|
||
|
||
A conforming exhibit may need to build a normalization layer before its existing internals can satisfy the contract.
|
||
|
||
---
|
||
|
||
## 9. Target Descriptor
|
||
|
||
Each target returned by `describe` MUST include enough metadata for a generic host to inspect and operate it.
|
||
|
||
Base descriptor:
|
||
|
||
```json
|
||
{
|
||
"id": "mix.master",
|
||
"label": "Master Volume",
|
||
"kind": "range",
|
||
"readable": true,
|
||
"writable": true,
|
||
"restorable": true,
|
||
"category": "mix",
|
||
"unit": null,
|
||
"requires": ["audio"]
|
||
}
|
||
```
|
||
|
||
`requires` references capability IDs from Section 17.
|
||
|
||
When a required capability is not usable, the target remains discoverable but MUST NOT be operated successfully. A generic host SHOULD present it as unavailable rather than removing it.
|
||
|
||
Additional fields depend on kind.
|
||
|
||
### 9.1 Range
|
||
|
||
```json
|
||
{
|
||
"id": "mix.master",
|
||
"kind": "range",
|
||
"min": 0,
|
||
"max": 1,
|
||
"step": 0.01
|
||
}
|
||
```
|
||
|
||
### 9.2 State
|
||
|
||
```json
|
||
{
|
||
"id": "view.observation",
|
||
"kind": "state",
|
||
"valueType": "boolean"
|
||
}
|
||
```
|
||
|
||
### 9.3 Selection
|
||
|
||
```json
|
||
{
|
||
"id": "universe.selected",
|
||
"kind": "selection",
|
||
"options": [
|
||
{"value": "starfleet", "label": "Starflight Command"},
|
||
{"value": "whataverse", "label": "Whataverse"}
|
||
]
|
||
}
|
||
```
|
||
|
||
Values in examples are illustrative except where a profile document explicitly declares them normative.
|
||
|
||
### 9.4 Impulse
|
||
|
||
```json
|
||
{
|
||
"id": "event.alert-red",
|
||
"kind": "impulse",
|
||
"readable": false,
|
||
"writable": false,
|
||
"restorable": false
|
||
}
|
||
```
|
||
|
||
A target with `kind: "impulse"` is invokable.
|
||
|
||
`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
|
||
clarifies Contract 5.2; it does not introduce Contract 5.3. Missing `arguments`
|
||
MUST be tolerated as an empty array for backward compatibility. New 5.2 exhibits
|
||
SHOULD explicitly emit `arguments: []` for argumentless impulses.
|
||
|
||
```json
|
||
{
|
||
"id": "speech.say",
|
||
"kind": "impulse",
|
||
"readable": false,
|
||
"writable": false,
|
||
"restorable": false,
|
||
"category": "speech",
|
||
"requires": ["speech"],
|
||
"arguments": [
|
||
{"name": "text", "type": "string", "required": true, "maxLength": 2000}
|
||
]
|
||
}
|
||
```
|
||
|
||
Each argument descriptor has:
|
||
|
||
| Field | Requirement |
|
||
| --- | --- |
|
||
| `name` | REQUIRED string, unique within the target |
|
||
| `type` | REQUIRED: `string`, `number`, `integer`, or `boolean` |
|
||
| `required` | REQUIRED boolean |
|
||
| `label` | OPTIONAL human-readable string |
|
||
| `description` | OPTIONAL human-readable string |
|
||
| `enum` | OPTIONAL array of allowed literal values |
|
||
| `min`, `max` | OPTIONAL number |
|
||
| `step` | OPTIONAL positive number |
|
||
| `minLength`, `maxLength` | OPTIONAL non-negative integer |
|
||
|
||
Invoke `args` MUST be an object. Every argument with `required: true` MUST be
|
||
present. Undeclared keys MUST be rejected with `INVALID_VALUE`. Values MUST match
|
||
the declared type, and all declared enum, bounds, step, and length constraints
|
||
MUST be enforced.
|
||
|
||
NGN MAY generate controls directly from this metadata and MUST NOT infer
|
||
undocumented arguments. NGN MUST still surface an impulse with an unsupported
|
||
future argument type and report its schema as unsupported rather than inventing
|
||
behavior.
|
||
|
||
Established examples: `speech.say` declares required string `text` with
|
||
`maxLength: 2000`; the established impulse form of `display.ticker` declares
|
||
required string `text` with `maxLength: 512`. Argumentless actions, including
|
||
`speech.generate-announcement` and argumentless event/sound impulses, declare
|
||
`arguments: []`. These examples do not establish a host target inventory.
|
||
|
||
---
|
||
|
||
## 10. Target Kinds
|
||
|
||
The base contract defines four kinds.
|
||
|
||
### 10.1 State
|
||
|
||
Persistent value such as boolean, string, or bounded scalar.
|
||
|
||
### 10.2 Range
|
||
|
||
Persistent bounded numeric state.
|
||
|
||
### 10.3 Selection
|
||
|
||
Persistent value selected from a declared set.
|
||
|
||
### 10.4 Impulse
|
||
|
||
Non-persistent action or event.
|
||
|
||
Impulse targets MUST NOT appear in a restorable state snapshot as current state.
|
||
|
||
---
|
||
|
||
## 11. Invoke
|
||
|
||
`invoke` performs an impulse.
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "invoke",
|
||
"requestId": "req-200",
|
||
"sessionId": "sess-7f2a",
|
||
"target": "sfx.console-beep",
|
||
"args": {}
|
||
}
|
||
```
|
||
|
||
The exhibit MUST validate the target and arguments before execution.
|
||
|
||
Arguments MUST be validated against the declared target schema where such a schema exists.
|
||
|
||
Unexpected argument keys SHOULD be rejected.
|
||
|
||
A successful `invoke` response means that the operation was accepted for execution, not necessarily that a long-running effect has completed.
|
||
|
||
---
|
||
|
||
## 12. Set
|
||
|
||
`set` changes writable persistent state.
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "set",
|
||
"requestId": "req-201",
|
||
"sessionId": "sess-7f2a",
|
||
"target": "mix.master",
|
||
"value": 0.75
|
||
}
|
||
```
|
||
|
||
A successful state-changing set MUST result in a normalized state update.
|
||
|
||
A successful no-op set MUST NOT increment `stateRevision`.
|
||
|
||
---
|
||
|
||
## 13. State Snapshot
|
||
|
||
The host MUST be able to request externally meaningful persistent state.
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "state.get",
|
||
"requestId": "req-300",
|
||
"sessionId": "sess-7f2a"
|
||
}
|
||
```
|
||
|
||
Response:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "state.result",
|
||
"requestId": "req-300",
|
||
"sessionId": "sess-7f2a",
|
||
"stateRevision": 28,
|
||
"values": {
|
||
"transport.playing": true,
|
||
"transport.muted": false,
|
||
"mix.master": 0.75,
|
||
"view.observation": true,
|
||
"universe.selected": "starfleet",
|
||
"preset.selected": "tng-bridge"
|
||
}
|
||
}
|
||
```
|
||
|
||
Only readable persistent targets belong in `values`.
|
||
|
||
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
|
||
|
||
The exhibit MUST maintain a monotonically increasing `stateRevision` for externally observable persistent state.
|
||
|
||
### 14.1 Mutation transaction
|
||
|
||
One top-level contract-visible mutation operation is one **mutation transaction**, unless the exhibit explicitly opens a larger transaction for a coherent multi-value operation.
|
||
|
||
Examples of one transaction may include:
|
||
|
||
- one host `set`;
|
||
- one UI slider change;
|
||
- one MIDI mutation;
|
||
- one universe change that also selects a default preset;
|
||
- one preset selection that updates several exposed values.
|
||
|
||
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:
|
||
|
||
1. compute and commit the transaction;
|
||
2. increment `stateRevision` exactly once if externally visible state changed;
|
||
3. emit resulting `state.changed` / `selection.changed` events carrying that revision.
|
||
|
||
### 14.3 No-op behavior
|
||
|
||
A transaction that produces no externally visible state change MUST NOT increment `stateRevision`.
|
||
|
||
### 14.4 Why both revision and sequence exist
|
||
|
||
`stateRevision` tracks committed persistent-state history.
|
||
|
||
Event `sequence` tracks delivery order of all emitted contract events, including impulses and errors.
|
||
|
||
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
|
||
|
||
Normalized events MUST identify the authoritative source of the action when known.
|
||
|
||
Base values:
|
||
|
||
```text
|
||
ui
|
||
midi
|
||
hotkey
|
||
host
|
||
scenario
|
||
internal
|
||
system
|
||
```
|
||
|
||
A `source` property supplied by a host command MUST be ignored.
|
||
|
||
The receiving bridge assigns the authoritative source.
|
||
|
||
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
|
||
|
||
A conforming XZBT 5.2 exhibit MUST publish normalized events for contract-visible operations.
|
||
|
||
Base event types include:
|
||
|
||
```text
|
||
state.changed
|
||
action.executed
|
||
selection.changed
|
||
capability.changed
|
||
registry.changed
|
||
error
|
||
```
|
||
|
||
Example:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "state.changed",
|
||
"sessionId": "sess-7f2a",
|
||
"sequence": 144,
|
||
"timestamp": 1799781200123,
|
||
"stateRevision": 29,
|
||
"target": "mix.master",
|
||
"value": 0.82,
|
||
"source": "midi"
|
||
}
|
||
```
|
||
|
||
Impulse example:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "action.executed",
|
||
"sessionId": "sess-7f2a",
|
||
"sequence": 145,
|
||
"timestamp": 1799781200234,
|
||
"target": "sfx.console-beep",
|
||
"args": {},
|
||
"source": "ui"
|
||
}
|
||
```
|
||
|
||
### 16.1 Sequence
|
||
|
||
Event `sequence` MUST increase monotonically within one session.
|
||
|
||
It is session-scoped and resets when a new `sessionId` is issued.
|
||
|
||
A host MUST reset its expected sequence after reconnect.
|
||
|
||
### 16.2 Correlation
|
||
|
||
When an event is caused directly by a host request, it SHOULD include the request's `requestId` as `correlationId`.
|
||
|
||
### 16.3 Selection events
|
||
|
||
A successful change to a Selection-kind target SHOULD emit `selection.changed`.
|
||
|
||
### 16.4 Errors
|
||
|
||
Request-scoped errors MUST be returned as responses.
|
||
|
||
An exhibit MAY additionally publish an `error` event for observability.
|
||
|
||
If published, it SHOULD carry the same source and `correlationId` as the rejected request.
|
||
|
||
### 16.5 Recorder behavior
|
||
|
||
NGN recording SHOULD normally record operator-originated events such as `ui`, `midi`, and `hotkey`.
|
||
|
||
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
|
||
|
||
Capabilities are discoverable and stateful.
|
||
|
||
Descriptor example:
|
||
|
||
```json
|
||
{
|
||
"id": "speech",
|
||
"state": "available"
|
||
}
|
||
```
|
||
|
||
Base states:
|
||
|
||
```text
|
||
unsupported
|
||
available
|
||
loading
|
||
ready
|
||
busy
|
||
error
|
||
```
|
||
|
||
Definitions:
|
||
|
||
- `unsupported`: the exhibit does not implement the capability.
|
||
- `available`: implemented, but not necessarily initialized.
|
||
- `loading`: initialization is in progress.
|
||
- `ready`: usable now.
|
||
- `busy`: currently occupied but still operational.
|
||
- `error`: initialization or operation failed.
|
||
|
||
A capability may change state during a session.
|
||
|
||
Capability changes MUST emit `capability.changed`.
|
||
|
||
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
|
||
|
||
An exhibit with speech support SHOULD expose:
|
||
|
||
```text
|
||
speech.say
|
||
```
|
||
|
||
Example:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "invoke",
|
||
"requestId": "req-410",
|
||
"sessionId": "sess-7f2a",
|
||
"target": "speech.say",
|
||
"args": {
|
||
"text": "Engineering reports reactor output at eighty-seven percent."
|
||
}
|
||
}
|
||
```
|
||
|
||
The exhibit controls synthesis and playback.
|
||
|
||
NGN supplies content.
|
||
|
||
The contract does not require a specific TTS engine or a speech queue.
|
||
|
||
If the exhibit has a usable fallback synthesis path while its preferred path is loading, it MAY accept `speech.say` through that fallback.
|
||
|
||
A successful `speech.say` response means accepted for playback, not playback completed.
|
||
|
||
---
|
||
|
||
## 19. Sound and Visual Events
|
||
|
||
Exhibit-native sound and visual actions SHOULD be exposed as impulse targets where useful.
|
||
|
||
Examples:
|
||
|
||
```text
|
||
sfx.console-beep
|
||
sfx.warning-tone
|
||
event.alert-red
|
||
event.ship-arrival
|
||
```
|
||
|
||
State and impulse semantics MUST remain distinct.
|
||
|
||
For example:
|
||
|
||
```text
|
||
event.alert-red
|
||
```
|
||
|
||
may be an impulse, while:
|
||
|
||
```text
|
||
alert.active
|
||
```
|
||
|
||
may represent current persistent alert state.
|
||
|
||
NGN requests the action.
|
||
|
||
The exhibit owns its implementation.
|
||
|
||
---
|
||
|
||
## 20. Safe Text Injection
|
||
|
||
An exhibit MAY expose safe text surfaces such as:
|
||
|
||
```text
|
||
display.ticker
|
||
```
|
||
|
||
Text MUST be handled as data.
|
||
|
||
The contract MUST NOT permit arbitrary:
|
||
|
||
- HTML;
|
||
- JavaScript;
|
||
- CSS;
|
||
- selectors;
|
||
- executable expressions.
|
||
|
||
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
|
||
|
||
Telemetry support is OPTIONAL.
|
||
|
||
The contract defines how telemetry is represented if an exhibit exposes structured telemetry. It does not require every exhibit to implement telemetry.
|
||
|
||
A telemetry target descriptor SHOULD declare:
|
||
|
||
- identifier;
|
||
- label;
|
||
- value type;
|
||
- unit;
|
||
- minimum and maximum where applicable;
|
||
- writable status;
|
||
- update expectations if useful.
|
||
|
||
Example:
|
||
|
||
```json
|
||
{
|
||
"id": "telemetry.engine.temperature",
|
||
"label": "Engine Temperature",
|
||
"kind": "range",
|
||
"valueType": "number",
|
||
"unit": "celsius",
|
||
"readable": true,
|
||
"writable": true,
|
||
"restorable": false
|
||
}
|
||
```
|
||
|
||
Existing SciFi-XZBT telemetry-like presentation is primarily audio activity and ticker text rather than a structured numeric telemetry model.
|
||
|
||
Therefore structured writable telemetry in SciFi-XZBT is a new exhibit feature, not merely exposure of an existing data object.
|
||
|
||
It may be implemented incrementally and is not required for the first contract-compatible milestone.
|
||
|
||
---
|
||
|
||
## 22. Telemetry Ownership
|
||
|
||
Writable telemetry MAY support source ownership.
|
||
|
||
Recommended modes:
|
||
|
||
```text
|
||
simulation
|
||
external
|
||
```
|
||
|
||
An external update MAY include a lease duration:
|
||
|
||
```json
|
||
{
|
||
"xzbt": "5.3",
|
||
"type": "set",
|
||
"requestId": "req-520",
|
||
"sessionId": "sess-7f2a",
|
||
"target": "telemetry.engine.temperature",
|
||
"value": 482.7,
|
||
"options": {
|
||
"ownership": "external",
|
||
"ttlMs": 5000
|
||
}
|
||
}
|
||
```
|
||
|
||
After lease expiration, the exhibit MAY return to simulated ownership.
|
||
|
||
The exact telemetry lease mechanism remains optional in 5.2, unchanged in 5.3.
|
||
|
||
A simple explicit release mechanism is also acceptable.
|
||
|
||
---
|
||
|
||
## 23. Registry Revision
|
||
|
||
`registryRevision` represents the current set and metadata of discoverable targets.
|
||
|
||
It SHOULD increment when targets or descriptor metadata actually change during a session.
|
||
|
||
A `registry.changed` event MUST notify the host when the revision changes.
|
||
|
||
The host then re-runs `describe`.
|
||
|
||
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
|
||
|
||
Implementations SHOULD use stable machine-readable error codes.
|
||
|
||
Recommended base codes include:
|
||
|
||
```text
|
||
UNSUPPORTED_VERSION
|
||
INVALID_MESSAGE
|
||
INVALID_SESSION
|
||
UNKNOWN_TARGET
|
||
INVALID_VALUE
|
||
INVALID_ARGUMENTS
|
||
CAPABILITY_UNAVAILABLE
|
||
TARGET_READ_ONLY
|
||
TARGET_NOT_INVOKABLE
|
||
TARGET_NOT_SETTABLE
|
||
INTERNAL_ERROR
|
||
```
|
||
|
||
Human-readable error text is advisory.
|
||
|
||
Hosts SHOULD branch on codes, not message strings.
|
||
|
||
---
|
||
|
||
## 25. Security Boundary
|
||
|
||
The contract MUST NOT provide arbitrary code execution.
|
||
|
||
Target IDs MUST NOT be interpreted as property traversal.
|
||
|
||
Contract payloads MUST NOT permit raw executable markup.
|
||
|
||
The exhibit contract MUST NOT provide a primitive for fetching arbitrary URLs.
|
||
|
||
External networking belongs to the host or to explicitly defined exhibit-native functionality.
|
||
|
||
Both host and exhibit MUST validate incoming messages.
|
||
|
||
Internet-facing authentication and authorization belong to XZBT-NGN, not the standalone exhibit.
|
||
|
||
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
|
||
|
||
The XZBT Exhibit Contract does not require a general-purpose scenario engine in the standalone exhibit.
|
||
|
||
A scenario is an orchestration concept.
|
||
|
||
XZBT-NGN may execute scenarios by issuing contract operations over time.
|
||
|
||
A separately packaged exhibit may contain:
|
||
|
||
- authored scenario data;
|
||
- a compact runtime;
|
||
- only the functionality necessary to execute that packaged scenario.
|
||
|
||
The ordinary standalone exhibit does not need to load arbitrary scenario files.
|
||
|
||
Scenario data MUST remain inert data and MUST NOT be interpreted as arbitrary executable code.
|
||
|
||
---
|
||
|
||
## 27. Extensibility
|
||
|
||
The base contract is exhibit-generic.
|
||
|
||
A castle exhibit could expose:
|
||
|
||
```text
|
||
weather.rain
|
||
fireplace.intensity
|
||
event.drawbridge
|
||
sfx.thunder
|
||
```
|
||
|
||
A train exhibit could expose:
|
||
|
||
```text
|
||
engine.throttle
|
||
brake.pressure
|
||
event.whistle
|
||
telemetry.speed
|
||
```
|
||
|
||
NGN discovers these targets dynamically.
|
||
|
||
---
|
||
|
||
## 28. Versioning
|
||
|
||
### 28.1 Contract major
|
||
|
||
Breaking protocol changes require a new contract major.
|
||
|
||
### 28.2 Contract minor
|
||
|
||
Backward-compatible additions may increase the minor version.
|
||
|
||
### 28.3 Exhibit version
|
||
|
||
Exhibit product version is independent from contract version.
|
||
|
||
### 28.4 Registry revision
|
||
|
||
Registry revision is runtime target metadata and does not imply a contract version change.
|
||
|
||
### 28.5 State revision
|
||
|
||
`stateRevision` is a runtime state-history counter and is not a protocol version.
|
||
|
||
### 28.6 Scenario format
|
||
|
||
Scenario format versioning is owned by XZBT-NGN and is outside the Exhibit Contract.
|
||
|
||
### 28.7 Additive targets
|
||
|
||
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
|
||
|
||
An exhibit is minimally XZBT Contract 5.2 compatible when it supports:
|
||
|
||
- compatible handshake;
|
||
- normalized message envelope;
|
||
- `describe`;
|
||
- at least one discoverable target;
|
||
- `state.get` for readable persistent targets;
|
||
- `stateRevision`;
|
||
- normalized responses;
|
||
- normalized event emission;
|
||
- session event sequencing;
|
||
- command validation;
|
||
- version reporting.
|
||
|
||
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
|
||
|
||
Version 5.2 keeps the Version 5 architecture intact while tightening implementation semantics.
|
||
|
||
The key rule remains:
|
||
|
||
**The exhibit exposes what it can do.**
|
||
|
||
**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.
|