generated from Labyricorn/labyricorn-project-template
Steps 6.4-6.7B — Local surfaces, reference-exhibit validation, SciFi Observation surface
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.
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user