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,256 @@
|
||||
# XZBT-NGN Step 6.6 — Reference Exhibit End-to-End Validation
|
||||
|
||||
Status: PASS — no implementation changes were required.
|
||||
|
||||
Step 6.6 validates Museum Gallery end-to-end as a complete Contract 5.3 reference
|
||||
exhibit operating through the normal NGN operator UI. It is a validation task: no
|
||||
architecture was redesigned, no features were added, and no source file was modified.
|
||||
|
||||
## A. Environment
|
||||
|
||||
| Item | Value |
|
||||
| --- | --- |
|
||||
| NGN UI | `http://127.0.0.1:4173/` |
|
||||
| Server | The already-running `npm start` server on port 4173 (started at 16:43, before this session). A second instance started for validation failed to bind with `EADDRINUSE` and exited, so the served state was unchanged and the running server was left untouched. |
|
||||
| Exhibit under test | `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` |
|
||||
| Working tree | Step 6.3/6.4/6.5 uncommitted work preserved as found; HEAD `ed76cf6` |
|
||||
| Method | Real NGN UI in a browser, driven through the served page (no test doubles) |
|
||||
|
||||
## B. Initial connection
|
||||
|
||||
Observed through the served NGN page after `Load exhibit`:
|
||||
|
||||
- Status: `connected · synchronized`
|
||||
- Session: `sess-1f54f`
|
||||
- Negotiated contract: `{ major: 5, minor: 3 }`
|
||||
- Exhibit metadata: `Museum Gallery · 0.1.0 · build reference-exhibit`
|
||||
- `registryRevision` 1, `stateRevision` 0
|
||||
- Capabilities: `render: ready`
|
||||
- Target registry discovered (5):
|
||||
|
||||
| Target | Kind | Access |
|
||||
| --- | --- | --- |
|
||||
| `artifact.selected` | selection | readable · writable |
|
||||
| `lighting.level` | range | readable · writable |
|
||||
| `rotation.speed` | range | readable · writable |
|
||||
| `labels.enabled` | state | readable · writable |
|
||||
| `action.spotlight-flash` | impulse | not readable · not writable |
|
||||
|
||||
- State snapshot received: `artifact.selected="the-orrery"`, `lighting.level=0.6`,
|
||||
`rotation.speed=0.4`, `labels.enabled=true`
|
||||
- Protocol/error log: one `SESSION` entry, no errors
|
||||
|
||||
## C. Surface discovery and primary handling
|
||||
|
||||
`Presentation surfaces (3)` discovered, exactly the three the exhibit advertises:
|
||||
|
||||
| id | Label | Primary | Role | URL |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `surface.control` | Control Room | yes | control | `control.html` |
|
||||
| `surface.artifact` | Artifact Display | no | ambient | `artifact.html` |
|
||||
| `surface.info-wall` | Information Wall | no | information | `info-wall.html` |
|
||||
|
||||
Primary handling: the primary is not duplicated as a local pane. Its card carries the
|
||||
`Primary` badge, shows `Open in the authoritative control frame. Use Connection controls
|
||||
to reload or disconnect.`, and its Open/Reload/Close buttons are disabled. The two
|
||||
non-primary surfaces open as local panes and each renders and reports
|
||||
`Attached to Control Room.`
|
||||
|
||||
The Control Room's own `Attached non-primary surfaces` readout (the exhibit's participant
|
||||
count) became `2` when both panes were open.
|
||||
|
||||
## D. Lifecycle validation
|
||||
|
||||
Measured participant count in the authoritative Control Room:
|
||||
|
||||
```text
|
||||
open both: 2
|
||||
reload: 2
|
||||
reload again: 2
|
||||
close one: 1
|
||||
reopen: 2
|
||||
```
|
||||
|
||||
Each reload produced a fresh secondary document (verified by a marker placed on the
|
||||
frame's `contentWindow` disappearing after reload), which then re-attached and rendered
|
||||
the current authoritative state. No ratcheting and no stale participant entries were
|
||||
observed at any point.
|
||||
|
||||
## E. Shared-state validation
|
||||
|
||||
### Control -> secondaries
|
||||
|
||||
| Change made in Control Room | Observed propagation |
|
||||
| --- | --- |
|
||||
| Selected artifact -> Star Map | `selection.changed`, sequence 1, `stateRevision` 1, `source: "ui"`; both secondaries rendered `Star Map` |
|
||||
| Lighting level -> 25% | `state.changed`, sequence 2, `stateRevision` 2, `source: "ui"`; Artifact Display rendered `Lighting: 25%` |
|
||||
|
||||
Control Room, Artifact Display, Information Wall and NGN's reported state all agreed
|
||||
after each change.
|
||||
|
||||
### Secondary -> primary -> secondaries
|
||||
|
||||
A real mouse click on the Artifact Display's native `Cycle artifact` control while the
|
||||
authoritative selection was `star-map`:
|
||||
|
||||
- Control Room's authoritative selection became `meteorite` (its combobox followed)
|
||||
- `selection.changed`, sequence 3, `stateRevision` 3, `source: "ui"`
|
||||
- Information Wall updated to `Meteorite Fragment`
|
||||
- Artifact Display re-rendered from the authoritative result
|
||||
|
||||
The secondary remained a mirror: it holds no Core (see section H) and only routes
|
||||
mutations back through the owner's canonical path.
|
||||
|
||||
### Late join
|
||||
|
||||
Information Wall closed (count 1) -> authoritative state mutated (rotation 1.7,
|
||||
labels OFF, `stateRevision` 5) -> Information Wall reopened: it immediately rendered
|
||||
`Meteorite Fragment` and `Labels: OFF`, and the count returned to 2.
|
||||
|
||||
### Reload recovery
|
||||
|
||||
Lighting mutated to 90% (`stateRevision` 6) -> Artifact Display reloaded: a fresh
|
||||
document (marker gone) returned showing `Meteorite Fragment`, `Lighting: 90%`,
|
||||
`Rotation: 1.7x` — current state, not exhibit defaults — with the count still 2.
|
||||
|
||||
### Sustained convergence
|
||||
|
||||
Four consecutive normal changes alternating between the primary and both secondaries
|
||||
(control selection, Information Wall toggle, control rotation, Artifact Display cycle)
|
||||
left Control Room, Artifact Display, Information Wall and NGN all in agreement at every
|
||||
step, with revisions advancing 7 -> 8 -> 9 -> 10 and the count steady at 2.
|
||||
|
||||
## F. Host-command validation (NGN UI)
|
||||
|
||||
| Operation | NGN control used | Result |
|
||||
| --- | --- | --- |
|
||||
| Readable state query | `Refresh state` (`state.get`) | Succeeded; snapshot matched, `stateRevision` 10, status `connected · synchronized`, no error |
|
||||
| `set` (range) | `lighting.level` -> `0.35` + `Set` | Succeeded; Control Room 35%, Artifact Display `Lighting: 35%`, `state.changed` revision 11, `source: "host"`, `correlationId: ngn-2-4` |
|
||||
| `set` (selection) | `artifact.selected` -> Meteorite Fragment + `Set` | Succeeded; all surfaces `Meteorite Fragment`, `selection.changed` revision 12, `source: "host"`, `correlationId: ngn-2-6` |
|
||||
| `invoke` (impulse) | `action.spotlight-flash` + `Invoke` | Succeeded; `action.executed` sequence 13, `source: "host"`, `correlationId: ngn-2-8`; exhibit `spotlightFlashCount` incremented; Control Room and both secondaries flashed `Spotlight flashed.` |
|
||||
|
||||
Each command left NGN's own state synchronized and produced no error entry. Instrumenting
|
||||
the Artifact Display's announcement node with a DOM observer confirmed the host-initiated
|
||||
`action.executed` event actually reached the secondary (it flashed, then returned to idle
|
||||
after the announcer's 2.6 s window).
|
||||
|
||||
## G. Reconnect and replacement
|
||||
|
||||
### Disconnect / reconnect
|
||||
|
||||
- `Disconnect`: status `disconnected · not synchronized`; catalog reset to
|
||||
`Connect an exhibit to discover its controls.`; surfaces reset to
|
||||
`No presentation surfaces advertised.`; both local panes removed (0 surface iframes
|
||||
remaining); control frame removed; reported state `{}`; no error entries.
|
||||
- `Reconnect`: new session `sess-15cf1`, Contract 5.3, all three surfaces rediscovered
|
||||
with correct primary handling, control frame re-established, participant count `0`
|
||||
(fresh authoritative document), no stale panes or counts.
|
||||
- Both secondaries reopened and attached to the new session (count 2), each rendering the
|
||||
new session's current state.
|
||||
|
||||
### Exhibit replacement
|
||||
|
||||
- Museum -> SciFi (`scifi/index.html`): no Museum pane survived (0 iframes referencing
|
||||
the Museum exhibit), the surface catalog became `No presentation surfaces advertised.`
|
||||
(SciFi advertises none), and SciFi negotiated Contract 5.3 as
|
||||
`SciFi-XZBT · 5.2.0 · build production`, session `sess-2akzu3a7`,
|
||||
`connected · synchronized`, 61 targets, state snapshot received.
|
||||
- SciFi -> Museum (`museum-gallery/control.html`): new session `sess-126c6`, Contract 5.3,
|
||||
5 targets, 3 surfaces rediscovered with the correct primary, participant count `0`,
|
||||
0 SciFi frames left, 0 stale Museum panes.
|
||||
|
||||
## H. Failure isolation
|
||||
|
||||
Live-tested through the served UI:
|
||||
|
||||
- **A non-primary surface holds no authority.** Inside the Artifact Display document:
|
||||
`XZBTContractCore` undefined, `MuseumGalleryContract` undefined,
|
||||
`MuseumGalleryExhibit` undefined, `XZBTHostTransport` undefined; only the surface bus is
|
||||
present, and `__museumGalleryDebug` exposes a `link` but no core.
|
||||
- **A secondary cannot act as a protocol peer.** A forged `hello` and a forged `set`
|
||||
posted directly to the Artifact Display's window produced zero responses, and the
|
||||
authoritative selection was unchanged.
|
||||
- **One broken presentation surface does not harm the control session.** The Artifact
|
||||
Display frame was navigated to a missing page (`does-not-exist.html`, served as
|
||||
`Not found`): the authoritative session stayed `connected · synchronized` on
|
||||
`sess-126c6`, the Control Room kept rendering, the registry/state were unaffected, and
|
||||
the surface's participant slot was released (count 2 -> 0) with no stale entry.
|
||||
- **Reload failure is surface-local and recoverable.** NGN's per-surface `Reload` brought
|
||||
the pane back to `artifact.html`; it re-attached and the count returned to 1 while the
|
||||
session remained synchronized. No error was raised against the session.
|
||||
|
||||
Automated-only (covered by the suites below, not re-injected live):
|
||||
|
||||
- malformed / individually-invalid surface descriptors and catalog-level rejection
|
||||
(`surface-validation.test.js`, `museum-gallery.test.js` — 50 validation cases)
|
||||
- isolated HTTP, frame and reload failures, external frame removal detection, and a
|
||||
stalled surface resource (`local-surfaces.test.js`)
|
||||
- resource-check refusal of redirects before frame navigation (`local-surfaces.test.js`)
|
||||
- presentation window cannot impersonate the authoritative peer over the production
|
||||
transport (`local-surfaces.test.js`)
|
||||
- source/origin validation on the real postMessage transport
|
||||
(`postmessage-interop.test.js`)
|
||||
|
||||
## I. Automated verification
|
||||
|
||||
Focused run (Museum Gallery, local surfaces, surface validation, postMessage interop,
|
||||
connection lifecycle):
|
||||
|
||||
```text
|
||||
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 suite (run once):
|
||||
|
||||
```text
|
||||
node --test
|
||||
# tests 129
|
||||
# pass 129
|
||||
# fail 0
|
||||
```
|
||||
|
||||
Other validation:
|
||||
|
||||
```text
|
||||
git diff --check -> clean (exit 0)
|
||||
python devlog_editor.py --validate -> devlog-editor: devlog is valid (exit 0)
|
||||
```
|
||||
|
||||
## J. Files changed
|
||||
|
||||
None. Validation found no defect, so per the Step 6.6 fix policy no implementation file
|
||||
was modified. The only additions are this report and its raw evidence record
|
||||
(`test-fixtures/evidence/step6.6-museum-gallery-validation.txt`).
|
||||
|
||||
## K. Limitations
|
||||
|
||||
1. Failure isolation was live-tested only for the three cases in section H; malformed
|
||||
descriptor catalogs, redirect refusal, stalled resources and peer impersonation remain
|
||||
automated-only, and no risky manual failure injection was performed for them.
|
||||
2. The `Spotlight flashed.` announcement on secondaries is transient (2.6 s idle timeout).
|
||||
It was confirmed with a DOM mutation observer rather than by a raw text read after the
|
||||
event, so the recorded evidence is the observer transition sequence.
|
||||
3. All live checks were same-origin over `http://127.0.0.1:4173`. Cross-origin exhibits,
|
||||
`file://` documents, and non-`http` schemes were not exercised live.
|
||||
4. The exhibit instance is recreated by `Disconnect`/`Reconnect` and by exhibit switching,
|
||||
so post-reconnect state is the exhibit's documented default state (`stateRevision` 0).
|
||||
No cross-session state persistence exists in the reference exhibit; this is expected
|
||||
standalone behavior, not a regression.
|
||||
5. Local surfaces were exercised in one browser window; casting/remote displays remain
|
||||
out of scope for Step 6.6 and were not tested.
|
||||
|
||||
## L. Verdict
|
||||
|
||||
PASS. Museum Gallery behaves as a complete Contract 5.3 reference exhibit through the
|
||||
normal NGN operator UI: connection and synchronization succeed, Contract 5.3 is
|
||||
negotiated, the surface catalog and primary handling are correct, both secondaries render
|
||||
locally and report attachment, participant counts stay correct across reload/close/reopen,
|
||||
Control -> secondary and secondary -> primary -> secondaries synchronization are both
|
||||
proven, late join and reload recovery return current state, representative host commands
|
||||
work, disconnect/reconnect and exhibit switching clean up completely, SciFi still connects
|
||||
and synchronizes, and the focused and full automated suites pass.
|
||||
@@ -0,0 +1,206 @@
|
||||
# XZBT-NGN Step 6.7B — SciFi Observation Surface Implementation
|
||||
|
||||
Status: PARTIAL PASS. Implementation, focused tests, and full NGN test suite are
|
||||
complete against a pre-existing, out-of-scope defect. Live browser verification
|
||||
(report §15) and the standalone packaged-build check were not performed in this
|
||||
session.
|
||||
|
||||
Step 6.7B implements the architecture selected by Step 6.7A (design-only, no
|
||||
code changes) — Candidate A, narrow form: SciFi-XZBT remains one document, one
|
||||
script set, with two boot modes, and advertises a Contract 5.3 Observation
|
||||
presentation surface as a query-mode view of its own `index.html`.
|
||||
|
||||
## A. Chosen architecture (confirmed as implemented)
|
||||
|
||||
- One document, two boot modes, resolved by `js/surface-mode.js` from
|
||||
`window.location` before heavy subsystem construction.
|
||||
- Primary surface: `index.html` (unchanged console), `primary: true`.
|
||||
- Observation surface: `index.html?surface=observation&xi=<instanceId>`, per
|
||||
Contract 5.3 §31.4's query-string surface form.
|
||||
- One authoritative SciFi state, one Contract 5.3 host session (console mode
|
||||
only), no NGN changes (`src/**` untouched — verified by mtime check against
|
||||
this session's own edits).
|
||||
- Presentation synchronization is exhibit-owned via an instance-scoped
|
||||
`BroadcastChannel` (`js/surface-bus.js`), never observed by NGN.
|
||||
- Opening the Observation surface does not set `view.observation = true`; the
|
||||
console's own full-screen overlay is unaffected by pane lifecycle.
|
||||
|
||||
## B. Files changed — SciFi-XZBT (`G:\.vibe\SciFi-XZBT`)
|
||||
|
||||
| File | Change |
|
||||
| --- | --- |
|
||||
| `js/surface-mode.js` | **New**, 108 lines. Pure mode resolver (`resolve`, `newInstanceId`, `SURFACES`, `channelName`). No DOM, no imports. |
|
||||
| `js/surface-bus.js` | **New**, 254 lines. Instance-scoped `BroadcastChannel` owner/attach sides (`createOwner`, `attach`), adapted from Museum Gallery's proven attach/snapshot/mutate/detach shape with a Set-based participant count. |
|
||||
| `js/contract-adapter.js` | 1006 → 1060 lines (+54). Additive: `surfaces`/`instanceId` constructor options; `describe()` emits `surfaces` only when non-empty; `view.pillars` / `view.warp-flight` targets registered (state/boolean/readable/writable/restorable, `category: observation`, `requires: [observation]`); `onLocalChange`/`onLocalAction` hooks fired from `_commitChanges`/`_invokeAction`, independent of `sessionActive`; version bumped `5.2.0` → `5.3.0`. Handshake, envelope, `xzbt` gating, and the `_emitEvent` session gate are unchanged. |
|
||||
| `js/app.js` | 4703 → 4921 lines (+218). Boot-mode resolution; `isConsoleMode`-guarded construction of `StarshipVisualizer`, `XZBTGenerativeExperience`, `XZBTControlBus`, `XZBTContractAdapter`, the keydown hotkey listener, and the sleep timer; `enterObservation()`'s `prepareExperience()` call now runs only in console mode; surface-bus owner wiring (console) / attach wiring (presentation); `applyPresentationState()` renderer; `observationAudienceActive()` decoupling the ambient scheduler from local overlay visibility; `view.pillars`/`view.warp-flight` added to `bindings.setters` and `getContractStateSnapshot()`; `togglePillars()`/`toggleWarpFlight()` now route through `applyMutation`/bus `mutate` instead of local engine mutation; `window.__xzbtSurfaceDispose` + `beforeunload` detach. |
|
||||
| `js/observation-engine.js` | 3595 → 3602 lines (+7). Only change: the WARP and PILLARS dock buttons now route through `onMutation`, matching the pre-existing VIEWPORT/RED ALERT/PRESET pattern, instead of mutating engine state directly. |
|
||||
| `css/style.css` | 2430 → 2457 lines (+27, additive). `body.surface-observation` rules hide `header`/`main`, hide `#obs-btn-exit` / `#observation-return-pill`; overlay renders full-bleed. |
|
||||
| `index.html` | +2 `<script src="...">` tags, exact `package.ps1`-compatible form, positioned after `control-bus.js`, before `generative-experience.js`. |
|
||||
| `agents.md`, `README.md` | Documented the two-mode rule, the two new files, the surface-bus mechanism, and the no-duplicate-authority invariant. |
|
||||
|
||||
`js/audio.js`, `js/config.js`, `js/visualizer.js`, `js/core-animations.js`,
|
||||
`js/generative-experience.js`, `js/control-bus.js`, `js/observation-bezels.js`,
|
||||
and `tools/package.ps1` are unchanged, per the report's "deliberately
|
||||
unchanged" list.
|
||||
|
||||
## C. Files changed — XZBT-NGN
|
||||
|
||||
| File | Change |
|
||||
| --- | --- |
|
||||
| `test-fixtures/reference-exhibits/scifi/{index.html, js/app.js, js/contract-adapter.js, js/observation-engine.js, css/style.css}` | Byte-for-byte resync from SciFi-XZBT source. |
|
||||
| `test-fixtures/reference-exhibits/scifi/js/{surface-mode.js, surface-bus.js}` | **New**, copied verbatim from SciFi-XZBT source. |
|
||||
| `test-fixtures/PROVENANCE.md` | Appended resync note (source path, files copied, no fixture-local corrections). |
|
||||
| `tests/scifi-surfaces.test.js` | **New**, 533 lines, 24 tests: surface catalog / contract validation, mode resolution, bus late-join/propagation/mutation-routing/no-second-authority/reload/detach/session-independence, duplicate-subsystem construction spies, app.js source-structure guards, ambient-timer test, one-contract-session test. |
|
||||
| `tests/local-surfaces.test.js` | +1 test using SciFi's real descriptors (19 → 20 tests), confirming the primary resolves to `control` and opens no second frame. |
|
||||
| `src/**` | **Unchanged.** No NGN core changes were needed or made. |
|
||||
|
||||
## D. State synchronization
|
||||
|
||||
- Mechanism: `BroadcastChannel` named `xzbt-scifi-surface-v1:<instanceId>`, owned
|
||||
by the console document; the presentation document reads `instanceId` from its
|
||||
own `?xi=` query parameter.
|
||||
- Message shapes match report §5.3 verbatim (`attach` / `attach.snapshot` /
|
||||
`state` / `action` / `presentation` / `mutate` / `detach`), carry no XZBT
|
||||
envelope, and are never observed by NGN.
|
||||
- Late join / reload: `attach` always receives the live
|
||||
`contractAdapter.getContractState()` snapshot plus `stateRevision` and
|
||||
`registryRevision`; a reload is a fresh `attach` with a fresh `participantId`.
|
||||
- Presentation mutations (`view.pillars`, `view.warp-flight`, `view.viewport-frame`,
|
||||
`alert.active`, `preset.selected`) are sent as `mutate` requests and applied by
|
||||
the owner exclusively through `contractAdapter.applyMutation(...)` with source
|
||||
`'ui'` — the same chokepoint NGN's own `set` uses. The presentation side never
|
||||
writes local state.
|
||||
- Participant bookkeeping is a `Set`, so duplicate attach and late/duplicate
|
||||
detach are harmless and cannot ratchet the count.
|
||||
|
||||
## E. Heavy-subsystem ownership (confirmed)
|
||||
|
||||
Presentation mode does **not** construct: `XZBTGenerativeExperience` (WebLLM +
|
||||
Kokoro — `prepareExperience()` is now called only inside the console-mode
|
||||
branch of `enterObservation()`), `XZBTContractAdapter` (no second Contract
|
||||
session), `XZBTControlBus`, `StarshipVisualizer`, or `CoreAnimations` (its
|
||||
render loop is only reachable from `StarshipVisualizer`, which is never
|
||||
constructed). The keydown hotkey listener and the sleep timer are also
|
||||
console-only. This is enforced by `isConsoleMode` guards at each construction
|
||||
site and asserted by source-structure tests in `scifi-surfaces.test.js`, plus
|
||||
construction-spy tests that fail if `AudioContext`/`fetch`/`import` are ever
|
||||
touched from the surface side.
|
||||
|
||||
`AudioManager` and the synth subsystems are still constructed on the
|
||||
presentation side (needed only to satisfy `ObservationEngine`'s constructor
|
||||
arity, per the 6.7A report) but never `init()`/`resume()`d, so no
|
||||
`AudioContext` or audio node is ever created there.
|
||||
|
||||
## F. New absolute state targets
|
||||
|
||||
- `view.pillars` — state/boolean, readable, writable, restorable,
|
||||
`category: observation`, `requires: [observation]`. Wired into
|
||||
`bindings.setters`, `getContractStateSnapshot()`, and dock routing on both
|
||||
surfaces.
|
||||
- `view.warp-flight` — same shape. Implemented as a compare-and-toggle against
|
||||
the engine's existing flight-mode field in `app.js`'s setter rather than
|
||||
adding a new `observationEngine.setWarpFlight()` method (the report's
|
||||
suggested name doesn't exist in `observation-engine.js`), keeping that file's
|
||||
change to the two dock-routing lines only.
|
||||
|
||||
Both targets are covered end-to-end (registration, snapshot inclusion, mutation
|
||||
routing, cross-surface convergence) by tests in `scifi-surfaces.test.js`.
|
||||
|
||||
## G. Observation audience behavior
|
||||
|
||||
`observationAudienceActive()` = `observationActive || surfaceOwner.attachedCount() > 0`.
|
||||
The ambient-activity scheduler and `triggerObservationActivity` now gate on this
|
||||
predicate instead of `observationActive` alone, so a presentation-only audience
|
||||
(console in normal mode, one or more Observation panes attached) keeps
|
||||
procedural activity running. `observationActive` itself is unchanged and still
|
||||
gates the console's own local overlay rendering. Activity *decisions* are made
|
||||
once by the authority and broadcast; each surface renders its own visual
|
||||
realization of "an event fired now" rather than a byte-identical copy (see
|
||||
Deviations, below) — narrative timing is shared, exact pixel content is not.
|
||||
|
||||
## H. Standalone verification
|
||||
|
||||
Not run live in this session (see §K). By construction: `index.html` with no
|
||||
query string resolves to console mode via `js/surface-mode.js`'s `resolve()`,
|
||||
which is unchanged from today's single-mode behavior for that input, and no
|
||||
code path in the console branch was removed — only guarded with `isConsoleMode`,
|
||||
which is `true` for that input. This is asserted structurally by
|
||||
`scifi-surfaces.test.js`'s mode-resolution tests, but not confirmed by opening
|
||||
a real browser.
|
||||
|
||||
## I. Fixture synchronization
|
||||
|
||||
`test-fixtures/reference-exhibits/scifi/` was resynced by copying the seven
|
||||
changed/new files verbatim from `G:\.vibe\SciFi-XZBT` after the source was
|
||||
syntax-checked and its own focused tests passed. `test-fixtures/PROVENANCE.md`
|
||||
records the resync. No fixture-local corrections were introduced — drift
|
||||
prevention relies on this being a discrete, documented, one-directional copy
|
||||
step (source → fixture), matching the procedure Step 5 used.
|
||||
|
||||
## J. Tests
|
||||
|
||||
| Suite | Result |
|
||||
| --- | --- |
|
||||
| `tests/scifi-surfaces.test.js` (new) | 24/24 pass |
|
||||
| `tests/local-surfaces.test.js` | 20/20 pass |
|
||||
| Full NGN suite (`npm test`) | 149/154 pass |
|
||||
|
||||
The 5 failures are all in `tests/postmessage-interop.test.js` (`hello timed
|
||||
out` ×4, one regex check), and are **not** caused by this step's changes.
|
||||
Root cause: `contract-adapter.js`'s `_setupWindowBridge` gates inbound
|
||||
messages on exact string equality against `xzbt: '5.2'`, while NGN's
|
||||
`src/host.js` — modified independently, before this session, and outside this
|
||||
step's scope — now stamps outgoing envelopes `xzbt: '5.3'`. Fixing this
|
||||
requires editing the handshake/envelope gating logic that the 6.7A report
|
||||
explicitly marks "must not change" for Step 6.7B. This is flagged as a
|
||||
pre-existing cross-repo integration gap for separate resolution, not silently
|
||||
worked around.
|
||||
|
||||
## K. Live verification
|
||||
|
||||
**Not performed in this session.** The implementation was delegated to and
|
||||
completed by an agent operating via local shell access on the SciFi-XZBT and
|
||||
XZBT-NGN working trees; it did not drive a real browser against a running
|
||||
`npm start` server. The following report §15 acceptance-procedure steps
|
||||
remain to be run manually:
|
||||
|
||||
1. Connect NGN to `http://127.0.0.1:4173/test-fixtures/reference-exhibits/scifi/index.html`; confirm `connected · synchronized`, Contract 5/3, target catalog.
|
||||
2. Confirm the Surfaces panel shows exactly two entries — `surface.console` (Primary, no Open button) and `surface.observation` (`?surface=observation&xi=…`).
|
||||
3. Open the Observation pane; confirm it renders the current universe/preset within ~1s, shows no RETURN ✕ / return pill, and background click does nothing.
|
||||
4. Confirm the console pane does **not** black out — `view.observation` stays `false`.
|
||||
5. From NGN, `set` `universe.selected`, `preset.selected`, `alert.active`, `view.viewport-frame`, `view.activity`, `view.pillars`, `view.warp-flight` and confirm both console and pane converge, with `stateRevision` advancing.
|
||||
6. Reload the pane; confirm it returns to current (not default) state. Close/reopen; confirm the participant count does not ratchet.
|
||||
7. Press WATCH EXPERIENCE on the console; confirm the pane is unaffected and `view.observation` toggles only the console overlay.
|
||||
8. DevTools checks on the pane's frame: no WebLLM/Kokoro network activity, `window.generativeExperience === undefined`, no `AudioContext`.
|
||||
9. Confirm transient activity events and AI announcements appear on console and pane at the same moment.
|
||||
10. Disconnect/reconnect NGN; confirm clean pane release and rediscovery.
|
||||
11. Standalone: open `index.html` directly (no NGN) — full console, WATCH EXPERIENCE, hotkeys, audio.
|
||||
12. Standalone two-window: open `index.html?surface=observation&xi=<real id>` in a second window with no NGN present; confirm it attaches and mirrors.
|
||||
13. Open `?surface=observation&xi=nonexistent` alone; confirm a waiting state, no invented authority.
|
||||
14. Run `tools/package.ps1` (requires PowerShell — unavailable in this session's Linux shell) and open the packaged `dist/` file offline; confirm the two new scripts were inlined (report risk R7 — inlining failure is silent) and standalone behavior is unchanged.
|
||||
|
||||
## L. Deviations from the 6.7A report
|
||||
|
||||
- **Warp-flight setter name.** The report's suggested `observationEngine.setWarpFlight(...)` does not exist; implemented as a compare-and-toggle in `app.js`'s setter instead, touching only the two dock-routing lines in `observation-engine.js`.
|
||||
- **No single `bootConsole()` function.** The guarded constructions/listeners remain in their existing positions in `app.js` (each wrapped in an `isConsoleMode` check) rather than being physically lifted into one named function, to respect `agents.md`'s "surgical, scoped edits" rule on a ~4,900-line file. Source-structure tests instead assert `isConsoleMode` appears immediately before each construction site. Functionally equivalent to the report's suggestion; less textually tidy.
|
||||
- **Activity-event visuals are decision-synchronized, not pixel-identical.** Byte-identical rendering across documents would require refactoring the ten universe generator functions to take explicit random parameters instead of calling `Math.random()` internally — judged out of proportion to this step. The *decision* to fire an event, and its narrative timing, is shared; each surface renders its own visual instance of it. Documented as an extension of the already-accepted instrumentation-digit divergence (report §6).
|
||||
|
||||
## M. Remaining limitations
|
||||
|
||||
- **Audio-reactive waveform is flat on the Observation surface**, as explicitly scoped out of 6.7B. No audio graph exists there; `observation-engine.js`'s pre-existing `am.analyser`-null guards degrade it gracefully. Deferred, not solved, per the governing report.
|
||||
- **`postmessage-interop.test.js`'s 5 failures** (see §J) are a pre-existing `5.2`/`5.3` handshake-gating mismatch between this SciFi-XZBT change and an independent, prior `src/host.js` change, outside this step's edit scope. Needs separate resolution — likely a version-gating fix in `contract-adapter.js`'s `_setupWindowBridge`, but that edit was withheld here because the report marks it must-not-change for 6.7B.
|
||||
- **Live browser verification and the packaged single-file build were not exercised** in this session (§K) — recommended before treating 6.7B as fully accepted.
|
||||
|
||||
## Step 6.7 verdict
|
||||
|
||||
Step 6.7B implementation is **substantively complete against the 6.7A
|
||||
architecture**: correct surface catalog, single authority, session-independent
|
||||
local synchronization, both new canonical targets, all heavy-subsystem guards,
|
||||
audience-activity decoupling, and standalone-preserving structure, all
|
||||
supported by 44 passing focused/regression tests. Step 6.7 as a whole should
|
||||
**not yet be marked complete**: the pre-existing handshake mismatch surfaced by
|
||||
the full suite run needs a decision (fix now vs. track separately), and the
|
||||
live NGN/browser and standalone/packaged-build verification in report §15
|
||||
has not been performed. Recommend resolving the handshake mismatch and running
|
||||
live verification before closing Step 6.7B, and explicitly deferring Step 6.8
|
||||
until then, per this task's instructions.
|
||||
Reference in New Issue
Block a user