Step 6.6 — Museum Gallery end-to-end validation through the NGN operator UI Server: pre-existing `npm start` server (node server/serve.js) on http://127.0.0.1:4173, started before this session and left running. A second instance started for validation failed with EADDRINUSE and exited; the served state was unchanged. NGN UI: http://127.0.0.1:4173/ Exhibit: http://127.0.0.1:4173/test-fixtures/reference-exhibits/museum-gallery/control.html Replacement exhibit: http://127.0.0.1:4173/test-fixtures/reference-exhibits/scifi/index.html Method: live browser session against the served page; values read from the live DOM, the exhibit frames, and NGN's own diagnostics panes. No test doubles. -------------------------------------------------------------------- 1. Initial connection (Load exhibit) -------------------------------------------------------------------- status: connected · synchronized identity: Museum Gallery · 0.1.0 · Contract 5.3 metadata: { sessionId: "sess-1f54f", contract: { major: 5, minor: 3 }, exhibit: { product: "Museum Gallery", version: "0.1.0", build: "reference-exhibit" }, registryRevision: 1, stateRevision: 0, sequence: null } capabilities: render: ready targets (5): artifact.selected (selection, r/w), lighting.level (range, r/w), rotation.speed (range, r/w), labels.enabled (state, r/w), action.spotlight-flash (impulse, not readable, not writable) state: { "artifact.selected": "the-orrery", "lighting.level": 0.6, "rotation.speed": 0.4, "labels.enabled": true } error log: one SESSION entry, no errors -------------------------------------------------------------------- 2. Surface discovery and primary handling -------------------------------------------------------------------- Presentation surfaces (3): surface.control Control Room Primary Role: control URL: control.html surface.artifact Artifact Display Non-primary Role: ambient URL: artifact.html surface.info-wall Information Wall Non-primary Role: information URL: info-wall.html Primary card buttons: Open disabled, Reload disabled, Close disabled Primary card status: "Open in the authoritative control frame. Use Connection controls to reload or disconnect." Non-primary panes rendered and each reported: "Attached to Control Room." Control Room readout "Attached non-primary surfaces": 2 -------------------------------------------------------------------- 3. Lifecycle (participant count in the authoritative Control Room) -------------------------------------------------------------------- open both -> 2 reload -> 2 reload again -> 2 close one -> 1 reopen -> 2 Reload freshness probe: a marker written to the secondary frame contentWindow was absent after reload (fresh document), and the document re-attached and re-rendered current state. -------------------------------------------------------------------- 4. Shared-state synchronization -------------------------------------------------------------------- Control -> secondaries Control Room combobox -> "star-map": event { type: "selection.changed", sequence: 1, stateRevision: 1, target: "artifact.selected", value: "star-map", source: "ui" } Control Room "Star Map"; Artifact Display "Star Map"; Information Wall "Star Map" Control Room lighting range -> 0.25: event { type: "state.changed", sequence: 2, stateRevision: 2, target: "lighting.level", value: 0.25, source: "ui" } Control Room "25%"; Artifact Display "Lighting: 25%" Secondary -> primary -> secondaries Real mouse click on Artifact Display "Cycle artifact" (authoritative value "star-map"): Control Room combobox became "meteorite"; Control Room label "Meteorite Fragment" event { type: "selection.changed", sequence: 3, stateRevision: 3, target: "artifact.selected", value: "meteorite", source: "ui" } Information Wall -> "Meteorite Fragment"; Artifact Display re-rendered authoritative result Sustained convergence (both secondaries open, alternating origins) step 1 control select the-orrery -> all views "The Orrery" revision 7 count 2 step 2 info-wall toggle labels -> labels.enabled true revision 8 count 2 step 3 control rotation 0.6 -> rotation.speed 0.6 revision 9 count 2 step 4 artifact-display cycle -> artifact.selected star-map revision 10 count 2 Control Room, Artifact Display, Information Wall and NGN reported state all agreed after every step. Late join close Information Wall -> count 1 mutate: rotation 1.7, labels OFF -> stateRevision 5 reopen Information Wall -> immediately rendered "Meteorite Fragment" / "Labels: OFF", count back to 2 Reload recovery mutate: lighting 0.9 -> stateRevision 6 reload Artifact Display -> fresh document returned with "Meteorite Fragment", "Lighting: 90%", "Rotation: 1.7x" (current state, not defaults); count still 2 -------------------------------------------------------------------- 5. NGN host commands -------------------------------------------------------------------- Refresh state (state.get): succeeded; stateRevision 10, status connected · synchronized, no error set lighting.level = 0.35: succeeded; Control Room "35%" (range 0.35), Artifact Display "Lighting: 35%"; event { type: "state.changed", sequence: 11, stateRevision: 11, target: "lighting.level", value: 0.35, source: "host", correlationId: "ngn-2-4" } set artifact.selected = meteorite: succeeded; Control Room / Artifact Display / Information Wall all "Meteorite Fragment"; event { type: "selection.changed", sequence: 12, stateRevision: 12, target: "artifact.selected", value: "meteorite", source: "host", correlationId: "ngn-2-6" } invoke action.spotlight-flash: succeeded; event { type: "action.executed", sequence: 13, target: "action.spotlight-flash", args: {}, source: "host", correlationId: "ngn-2-8" }; exhibit gallery.spotlightFlashCount incremented; Control Room and both secondaries announcement nodes flashed "Spotlight flashed." (captured by a DOM mutation observer on the Artifact Display announcement node: seen transitions ["Spotlight flashed.", "Waiting for shared state."]) -------------------------------------------------------------------- 6. Reconnect and exhibit replacement -------------------------------------------------------------------- Disconnect: status: disconnected · not synchronized catalog: "Connect an exhibit to discover its controls." surfaces: "No presentation surfaces advertised."; surface cards 0; surface iframes 0 control frame removed; state {}; metadata all null; no error entries Reconnect: status: connected · synchronized; session sess-15cf1; contract { major: 5, minor: 3 } targets (5); surfaces (3) with surface.control primary; participant count 0 no stale panes; both secondaries reopened -> "Attached to Control Room.", count 2 Switch to SciFi: identity: SciFi-XZBT · 5.2.0 · Contract 5.3 metadata: sessionId "sess-2akzu3a7", contract { major: 5, minor: 3 }, registryRevision 1, stateRevision 0 status: connected · synchronized; targets (61); surfaces: none advertised iframes referencing museum-gallery: 0 Switch back to Museum Gallery: session sess-126c6; contract { major: 5, minor: 3 }; targets (5); surfaces (3) with correct primary; participant count 0; iframes referencing scifi: 0 state: fresh exhibit defaults, stateRevision 0 -------------------------------------------------------------------- 7. Failure isolation (live) -------------------------------------------------------------------- Artifact Display document globals: XZBTContractCore: undefined MuseumGalleryContract: undefined MuseumGalleryExhibit: undefined XZBTHostTransport: undefined MuseumGallerySurfaceBus: present __museumGalleryDebug.core: absent Forged protocol messages posted directly to the secondary window: { xzbt: "5.3", type: "hello", requestId: "probe-secondary", supportedContractMajors: [5] } { xzbt: "5.3", type: "set", requestId: "probe-set", sessionId: "x", target: "artifact.selected", value: "meteorite" } -> responses received: none; authoritative selection unchanged ("The Orrery") Surface-local failure: Artifact Display frame navigated to /test-fixtures/reference-exhibits/museum-gallery/does-not-exist.html (served "Not found") -> NGN status stayed "connected · synchronized" on session sess-126c6; control frame still control.html; registry/state unaffected; no error entry; participant count 2 -> 0 with no stale entry NGN per-surface Reload on the failed pane: -> frame back at artifact.html, "Attached to Control Room.", participant count 1, session still synchronized, no error entry Automated-only isolation evidence (not re-injected live): malformed/invalid descriptor catalogs, isolated HTTP/frame/reload failures, external frame removal detection, stalled surface resource, redirect refusal on resource check, presentation-window impersonation refusal, transport source/origin validation. -------------------------------------------------------------------- 8. Automated verification -------------------------------------------------------------------- Focused: node --test tests/museum-gallery.test.js tests/local-surfaces.test.js tests/surface-validation.test.js tests/postmessage-interop.test.js tests/connection.test.js tests 107 / pass 107 / fail 0 Full: node --test tests 129 / pass 129 / fail 0 git diff --check -> clean (exit 0) python devlog_editor.py --validate -> devlog-editor: devlog is valid (exit 0)