Files
XZBT-NGN/test-fixtures/reference-exhibits/museum-gallery/README.md
T

122 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Museum Gallery — Step 6.2 multi-surface reference exhibit
A deliberately small XZBT Contract 5.3 exhibit built to prove the
multi-surface presentation model from
`docs/architecture/XZBT-Multi-Surface-Model-Step6.1.md` (Revision 2) and
`docs/contract/XZBT-Exhibit-Contract-Specification-v5.3.md` Section 31 — not
to be visually elaborate. See
`docs/reference/Museum-Gallery-Step6.2-Verification.md` for the full
verification writeup; this file documents the exhibit's own structure and
its chosen internal attachment transport.
## Entry point
`control.html` is the primary surface (`surface.control`, `primary: true`)
and the exhibit's canonical entry point — open it directly for full
standalone operation, exactly like any other reference exhibit's
`index.html`. `index.html` in this directory is a plain redirect to
`control.html`, kept only for directory-listing consistency; it has no
behavior of its own.
## Surfaces
| id | label | primary | url | role |
| --- | --- | --- | --- | --- |
| `surface.control` | Control Room | `true` | `control.html` | control |
| `surface.artifact` | Artifact Display | `false` | `artifact.html` | ambient |
| `surface.info-wall` | Information Wall | `false` | `info-wall.html` | information |
## Exactly one Exhibit State Core
`control.html` is the only document that loads `contract-adapter.js` (and
therefore the only document that constructs an `XZBTContractCore.ContractCore`
instance). `artifact.html` and `info-wall.html` load only `surface-bus.js` —
they are structurally incapable of constructing a second Core; the shared
`tests/museum-gallery.test.js` suite asserts this directly (see "Exactly one
Exhibit State Core exists" in that file).
## Chosen internal attachment transport: `BroadcastChannel`
`surface-bus.js` implements the generic attachment sequence from Step 6.1
§7.2 using a same-origin `BroadcastChannel` named `xzbt-museum-gallery-core-v1`,
with `control.html` as the single, clearly identified authoritative owner
document (Contract 5.3 §31.7's "cross-document attachment" shape).
Why `BroadcastChannel` over the other two permitted shapes:
- it needs no window-handle bookkeeping (unlike `postMessage` to a specific
`window` reference, which breaks if the owner window reference is lost or
the surface was opened independently rather than via `window.open`);
- it needs no separate worker lifecycle (unlike `SharedWorker`, which is
unsupported in some embedding contexts and adds a process to reason
about for a reference fixture this small);
- every participant — owner or surface — only ever needs to know one
string (the channel name), which keeps `control.html`, `artifact.html`,
and `info-wall.html` fully decoupled from each other; none of them
reference the other documents by name or handle.
This transport is exhibit-internal. It carries no XZBT contract envelope, is
never observed by a host, and is not mentioned anywhere in Contract 5.3 —
per Step 6.1 §7.2 and Contract 5.3 §31.7/§31.9, the contract only needs to
know that surfaces exist and how a host opens one. A different exhibit is
free to choose `SharedWorker`, in-process attachment, or another same-origin
mechanism entirely.
### Message shapes (informal, exhibit-internal only)
- surface → owner: `{ type: 'attach', requestId }`
- owner → surface: `{ type: 'attach.snapshot', inReplyTo, snapshot, registryRevision }`
- owner → all: `{ type: 'core-event', event }` — one relayed copy of every
normalized event the Core already emits (`state.changed`,
`selection.changed`, `action.executed`, …)
- surface → owner: `{ type: 'mutate', kind: 'set'|'invoke', target, value|args }`
— routed straight into `core.applyMutation` / `core.invokeAction` with
`source: 'ui'`, the same chokepoint the primary UI's own controls use
- surface → owner: `{ type: 'detach' }` — bookkeeping only; never mutates
state
## Shared state
`artifact.selected` (selection), `lighting.level` (range 0–1),
`rotation.speed` (range 0–2), `labels.enabled` (state/boolean), plus one
impulse, `action.spotlight-flash`, to prove `action.executed` propagation
across surfaces.
## Native interactions proving the canonical mutation path
- Artifact Display's "Cycle artifact" button calls `link.mutate('set',
'artifact.selected', …)`.
- Information Wall's "Toggle labels" button calls `link.mutate('set',
'labels.enabled', …)`.
Both are relayed by the bus into `core.applyMutation` on the one Core that
`control.html` owns — the same call the Control Room's own controls and a
contract `set` from NGN would make. See the verification document for the
event-sequence and stateRevision proof.
## Running it directly (no test harness)
Serve this repository with `npm start` and open:
```
http://127.0.0.1:4173/test-fixtures/reference-exhibits/museum-gallery/control.html
```
Then open `artifact.html` and `info-wall.html` in separate tabs/windows from
the same origin. Changing state in any one window updates the other two.
Closing and reopening a non-primary surface reflects current state
immediately. Opening `artifact.html` or `info-wall.html` alone, with
`control.html` not open anywhere, shows a "Waiting for the Control Room
surface to be open…" state rather than inventing its own state.
## Known limitation: NGN attachment is not exercised in Step 6.2
`control.html` includes the optional `XZBTHostTransport`, matching every
other reference exhibit. Because Museum Gallery declares `xzbtVersion:
'5.3'` while the current (pre-6.3) NGN host always sends the envelope tag
`xzbt: '5.2'`, an actual attach attempt from today's NGN would be rejected
at the envelope-version check rather than negotiating a Contract-major-5
session. This is expected and intentional: NGN's generic surface discovery
and version negotiation are Phase 6.3+ work, explicitly out of scope for
Step 6.2. See the verification document's known-limitations section.