generated from Labyricorn/labyricorn-project-template
One commit for the work accumulated in the working tree since Step 6.3, which had never been split into per-step commits: - src/local-surfaces.js + src/surface-url.js (new); src/ui.js, src/validation.js, src/connection.js and public/index.html updated for local-surface hosting and generic surface rendering - tests: local-surfaces (20), scifi-surfaces (24) and postmessage-interop (7) new; connection/museum-gallery/surface-validation suites updated - reference exhibits: shared/contract-core.js defaults to Contract 5.3 (major 5, minor 3, xzbt 5.3); museum-gallery advertises its surface catalog; aquarium/haunted-house/planetarium adapters updated - SciFi-XZBT (Step 6.7A/6.7B): surface-mode.js + surface-bus.js, Observation-surface boot branch, local-change hooks, view.pillars / view.warp-flight targets; fixture byte-identical to G:/.vibe/SciFi-XZBT - SciFi-XZBT contract adapter handshake fix: the inbound bridge filter no longer gates on an exact advisory xzbt value (Contract 5.3 §6.5), only on its presence/type, matching the host's own envelope validation; the adapter now advertises contract minor 3 / version 5.3.0, which it already implemented via the 5.3 surfaces field. Root cause of the five failing postmessage-interop tests (host hello was silently dropped). - docs: architecture 6.4 and 6.7A, reference 6.6 and 6.7; evidence logs; test-fixtures/PROVENANCE.md resync record Test results: NGN 154/154 (was 149/154); postmessage-interop 7/7 (was 2/7); SciFi contract harness 21/21, real-adapter suite 32/32. git diff --check clean for changed files; two pre-existing trailing-whitespace lines remain in test-fixtures/reference-exhibits/scifi/index.html, copied verbatim from the authoritative SciFi source. Step 6.7 live verification (browser Observation, packaged standalone) is still pending and is not claimed here.
144 lines
7.5 KiB
Markdown
144 lines
7.5 KiB
Markdown
# XZBT-NGN Exhibit Engine
|
||
|
||
A single-exhibit host for XZBT Exhibit Contract 5.3 (current; see
|
||
[Canonical documentation](#canonical-documentation)). It negotiates sessions,
|
||
discovers descriptor-driven controls, inspects reported state, sends set/invoke
|
||
operations, and displays capabilities, events, revisions, and protocol errors.
|
||
|
||
Step 5 implementation and verification are recorded in
|
||
[the completion report](STEP5-MVP-COMPLETION-REPORT.md). The SciFi-XZBT argument
|
||
descriptors are corrected and both text invocations pass through the operator UI.
|
||
Step 5 is complete: 27 automated tests and all three browser reference checks
|
||
pass. Haunted House reports conformant values, and publishing validation passes.
|
||
Steps 6.1–6.3 established Contract 5.3 surface discovery and interoperability.
|
||
Step 6.4 adds local presentation panes; see the
|
||
[Step 6.4 report](docs/architecture/XZBT-NGN-Step6.4-Local-Surfaces.md).
|
||
|
||
## Run locally
|
||
|
||
Requires Node.js 22 or later. No npm dependencies or build step.
|
||
|
||
```powershell
|
||
npm start
|
||
```
|
||
|
||
Open `http://127.0.0.1:4173`. Enter a same-origin exhibit path and select
|
||
**Load exhibit**. The host sends `hello`, `describe`, and `state.get` and renders
|
||
the discovered controls. Enter another path and select **Load exhibit** to switch.
|
||
|
||
- **Reconnect** negotiates a new session with the current frame, preserving the
|
||
exhibit instance. After **Disconnect**, it reloads the remembered URL; the new
|
||
exhibit instance starts with its own initial state.
|
||
- **Disconnect** removes the frame and clears session, catalog, state and events.
|
||
- **Refresh state** reads a new authoritative snapshot.
|
||
- **Presentation surfaces** provides Open, Reload and Close for each local view,
|
||
with its label, primary status and lifecycle state. URLs resolve against the
|
||
supplying exhibit's document URL, and must remain same-origin. NGN closes its
|
||
surface panes when disconnecting, reconnecting the session or switching exhibits.
|
||
A primary surface already represented by the control frame is marked as open;
|
||
its lifecycle remains under the Connection controls.
|
||
- Controls are grouped by the exhibit's category (or Other when omitted).
|
||
Reported values and draft inputs are distinct; select **Set** or **Invoke**
|
||
to submit. Rediscovery resets drafts.
|
||
- Expand **Capabilities**, **State and metadata**, or **Protocol diagnostics**
|
||
details to inspect engineering information. The latest diagnostic is also
|
||
shown near the connection panel. **Clear log** dismisses historical diagnostics.
|
||
|
||
Included reference fixture paths:
|
||
|
||
```text
|
||
/test-fixtures/reference-exhibits/aquarium/index.html
|
||
/test-fixtures/reference-exhibits/planetarium/index.html
|
||
/test-fixtures/reference-exhibits/haunted-house/index.html
|
||
/test-fixtures/reference-exhibits/museum-gallery/control.html
|
||
/test-fixtures/reference-exhibits/scifi/index.html
|
||
```
|
||
|
||
These are locally corrected test/reference fixtures, not NGN product code or
|
||
pristine upstream conformance evidence. See [provenance](test-fixtures/PROVENANCE.md).
|
||
Place additional trusted HTML exhibits and their relative assets under `public/`
|
||
and enter their served URL. A filesystem path or a different server origin cannot
|
||
be attached directly. The server exposes only `public/`, `src/`, and
|
||
`test-fixtures/`, binds to `127.0.0.1`, and denies paths escaping those directories.
|
||
For a port conflict, set `$env:PORT='4175'` before `npm start` and use that origin.
|
||
|
||
## Verification
|
||
|
||
```powershell
|
||
npm test
|
||
python devlog_editor.py --validate
|
||
git diff --check
|
||
```
|
||
|
||
Run the browser suite at `/test-fixtures/host-verification.html`; its timestamped
|
||
results appear on the page and in the browser console. The normal operator UI
|
||
checks and external SciFi-XZBT preparation are documented in
|
||
[Step 5 verification](test-fixtures/STEP5-VERIFICATION.md). Saved browser evidence
|
||
is under `test-fixtures/evidence/`. No source edits or dedicated harness are
|
||
needed for ordinary operation.
|
||
|
||
## Canonical documentation
|
||
|
||
This repository is the canonical home for the shared
|
||
[XZBT Exhibit Contract Specification 5.3](docs/contract/XZBT-Exhibit-Contract-Specification-v5.3.md) --
|
||
the current maintained contract, which additively supersedes
|
||
[Contract Specification 5.2](docs/contract/XZBT-Exhibit-Contract-Specification-v5.2.md)
|
||
(retained as a historical predecessor; no 5.2 normative requirement was
|
||
removed, weakened, or reinterpreted) -- and for the
|
||
[XZBT Exhibit Authoring Guide 5.2](docs/authoring/XZBT-Exhibit-Authoring-Guide-v5.2-Step3.7.md).
|
||
The [NGN Implementation Plan 5.2](docs/architecture/XZBT-NGN-Exhibit-Engine-Implementation-Plan-v5.2.md)
|
||
also belongs here. Its historical phase numbering describes the longer roadmap;
|
||
the current Step 5 completion pass does not authorize those later features.
|
||
SciFi-XZBT is an external exhibit implementation, not the NGN architecture.
|
||
`docs/reference/` contains external implementation context, not host requirements.
|
||
|
||
NGN and its maintained reference exhibits (Museum Gallery, SciFi-XZBT, Haunted
|
||
House, Aquarium, Planetarium) move forward with the contract: there is no
|
||
requirement to keep a currently maintained exhibit, or its test coverage,
|
||
frozen on an old minor version. The `xzbt` envelope field is advisory metadata
|
||
only (Contract §6.5) and is never used as an exact-string compatibility gate;
|
||
real compatibility is negotiated by the handshake and contract fields. A
|
||
genuine, unmaintained Contract 5.2 exhibit remains protocol-compatible with
|
||
this host (Contract §28.2) -- that guarantee is unrelated to which minor
|
||
version the exhibits maintained in *this* repository currently declare.
|
||
|
||
## Implementation and MVP boundary
|
||
|
||
- `src/host.js`: negotiation, requests, discovery, state cache, events and recovery.
|
||
- `src/connection.js`: URL validation and frame load/disconnect/reconnect lifecycle.
|
||
- `src/surface-url.js`, `src/local-surfaces.js`: canonical surface URL resolution
|
||
and local presentation frame lifecycle, without additional contract sessions.
|
||
- `src/validation.js`: descriptor, state value and argument validation.
|
||
- `src/transport/post-message.js`: same-origin frame transport.
|
||
- `src/ui.js`, `public/`: generic operator interface.
|
||
- `server/serve.js`: loopback static server.
|
||
- `tests/`, `test-fixtures/`: automated checks, reference fixtures and browser evidence.
|
||
|
||
The MVP supports one exhibit, Contract 5.3 discovery, generic target rendering,
|
||
state inspection, set/invoke, capabilities, events, session/revision/sequence
|
||
tracking, reconnect and synchronization recovery. It has in-memory state only;
|
||
logs retain 200 entries. Idle polling is not enabled. The last connection URL is
|
||
remembered only until the page is reloaded. Contract 5.3 presentation-surface
|
||
discovery and local rendering (Section 31) are implemented and exercised by the
|
||
Museum Gallery reference exhibit; other maintained exhibits do not declare
|
||
multiple surfaces. Surface errors stay within the affected pane. Remote/cast
|
||
display assignment remains deferred. Shared-state synchronization proof remains
|
||
Step 6.5; this step adds no host-side surface communication.
|
||
|
||
Not implemented: casting/display endpoints, MIDI, MCP/webhooks,
|
||
scenarios/recording, telemetry acquisition, multi-exhibit orchestration,
|
||
persisted operator configurations, remote deployment, accounts, databases,
|
||
cloud services, plugins, commercial licensing or production branding.
|
||
|
||
## Publishing records
|
||
|
||
`.labyricorn/` holds this project's Lektor exhibition and development records.
|
||
See [publishing guidance](.labyricorn/README.md) and scoped `AGENTS.md` files.
|
||
`python devlog_editor.py` opens the standalone publishing editor;
|
||
`python devlog_editor.py --validate` validates records without opening the GUI.
|
||
Application code lives outside `.labyricorn/`.
|
||
|
||
## License
|
||
|
||
See [LICENSE](LICENSE).
|