Step 5 Complete

This commit is contained in:
2026-09-14 13:01:45 -07:00
parent 76928f7870
commit 961919e017
34 changed files with 3309 additions and 273 deletions
+5
View File
@@ -20,6 +20,11 @@ Local compatibility corrections:
- Planetarium's magnitude reader and native dispatch still used the old
camelCase ID. They now match its existing canonical `sky.magnitude-limit`
descriptor, fixing a null snapshot value and failed native writes.
- Final Step 5 closure: Haunted House's haunt-level reader now clamps to 0–1
and rounds to integer hundredths, matching its unchanged 0.01 descriptor step.
The internal drifting simulation and Manifest behavior remain continuous;
snapshots and mutation events share this normalized reader. Previously the
reader rounded to thousandths and could report off-step values.
NGN has no fixture-specific target logic. These corrections apply only to
the local fixture copies. No upstream fixes or independent conformance
+147
View File
@@ -0,0 +1,147 @@
# Step 5 repeatable verification
Latest rerun (2026-09-14): the corrected SciFi text targets pass through the normal
UI; NGN tests pass 25/25. The browser gate currently fails at 2/3 on Haunted House's
haunt-level step, and publishing validation still fails. See completion report Q.
Run from the NGN repository root with Node.js 22+. Use `npm start` and the normal
UI at `http://127.0.0.1:4173/`. No npm install, build, source edit, external mount,
or test harness is required for operator use. Use the same origin/port for every
exhibit. `npm test` runs the automated tests.
## External SciFi-XZBT preparation
SciFi-XZBT is supplied separately. The run recorded here used the actual working
copy at `G:/.vibe/SciFi-XZBT`, whose HEAD was
`179b9db715aaa92999c5bfef451b6877f30079fe` with local changes and untracked contract
files. This is NOT evidence for that commit alone or for a released dist build.
The original SHA-256 manifest `evidence/step5-scifi-files.json` identifies the
initial 12 files tested. The authorized follow-up corrected the external adapter's
two argument descriptors and matching validator. Its fresh copy is identified by
`evidence/step5-scifi-arguments-files.json`; all 12 source/copy hashes match.
For this source layout, copy the runtime entry point and its relative assets
without modifying them. Use a fresh destination name when repeating with a newer
copy, to avoid mixing versions:
```powershell
$exhibitSource = 'G:/.vibe/SciFi-XZBT'
$exhibitDestination = 'test-fixtures/local/scifi-arguments'
New-Item -ItemType Directory -Path $exhibitDestination
Copy-Item -LiteralPath (Join-Path $exhibitSource 'index.html') -Destination $exhibitDestination
Copy-Item -LiteralPath (Join-Path $exhibitSource 'js') -Destination $exhibitDestination -Recurse
Copy-Item -LiteralPath (Join-Path $exhibitSource 'css') -Destination $exhibitDestination -Recurse
```
`test-fixtures/local/` is ignored by Git. Do not copy the external repository's
credentials, .git, or development tooling into a served directory. A future
self-contained distributable can instead be placed under `public/` unchanged.
The tested source copy uses only index.html, js/ and css/ for this workflow.
Enter `/test-fixtures/local/scifi-arguments/index.html` in the **normal NGN UI**, then
select **Load exhibit**. Expected identity: SciFi-XZBT 5.2.0, Contract 5.2,
61 discovered targets. Inspect Session and exhibit metadata and Current
persistent state. Controls below refer to labels discovered from this copy;
they are test instructions, not product configuration.
1. Set Master Volume to 0.42; verify reported value and state.changed.
2. Set Master Mute true; verify reported value.
3. Set Observation Viewport Active true, then false; verify reported values
and native exhibit behavior within its single frame.
4. Select Active Audio Preset / Interprise-G: Main Engineering; verify
preset.selected and related changes share one resulting revision.
5. Invoke Comm Badge Chime; verify action.executed (acceptance, not audio fidelity).
6. Invoke Demat Cycle Impulse while in Starfleet; expect CAPABILITY_UNAVAILABLE.
7. Select Active Sci-Fi Universe / Whataverse / Tardix, then invoke Demat Cycle
Impulse; verify action.executed in that context.
8. Inspect Speak Text Line and Display Ticker Message descriptors. A conformant
version declares an `arguments` array and NGN shows its text field. Enter text
and invoke; verify acceptance/event. **The corrected copy passes this check:**
both fields appear and action.executed contains the exact submitted args.text.
Speech declares maxLength 2000, ticker 512, both required strings. Correct the
external source before copying; do not add a host workaround or patch only the
served copy. The original copy's legacy args.text failure remains in old evidence.
9. Inspect Incoming events: source, correlationId, monotonically increasing
sequence and stateRevision. Reconnect while attached: new session, cleared
event log/sequence baseline, same exhibit state and revision.
10. Disconnect: no frame/catalog/cache remains. Reconnect: URL reloads, a new
instance and session are discovered. Initial state/revision may differ from
the removed instance. No source changes required.
Classify failures before changing NGN: host defect, external exhibit contract
defect, conformant but awkward behavior, or environment limitation. Sound
acceptance/events are covered; audible output and optional AI downloads are not
certified. Text-argument failure blocks Step 5 acceptance.
## Reference regression through the normal UI
Use these paths, changing only the URL field:
| Exhibit | URL | Representative operations |
| --- | --- | --- |
| Aquarium | /test-fixtures/reference-exhibits/aquarium/index.html | Population 16, Paused true, Species Blue Tang, Feed |
| Planetarium | /test-fixtures/reference-exhibits/planetarium/index.html | Azimuth 0.75, Sky frozen true, Constellation Cygnus, Advance time with Include minutes checked and minutes 30 |
| Haunted House | /test-fixtures/reference-exhibits/haunted-house/index.html | Haunt level 0.5, Held true, Room Library, Manifest |
Inspect reports and events, reconnect and confirm a new session. Disconnect and
reload the remembered URL. Aquarium and Planetarium pass the representative
flows. Haunted House emits Manifest's action event, but during the effect a
snapshot can contain a haunt-level value off its declared 0.01 step; NGN reports
INVALID_MESSAGE and preserves its previous cache. This is a pre-existing fixture
limitation, not a new host regression. No fixture repair was made in Step 5.
The existing transport suite at `/test-fixtures/host-verification.html` remains a
separate regression check: select Run verification, expect 3/3, and save the
visible timestamped text or browser console output. The latest rerun produced
2/3, failing Haunted House's step validation. Its first impulse with no capability
requirements is Manifest, and the fixture's continuous drift can also produce
off-step snapshots. The earlier statement that this suite avoids Manifest was
incorrect. Do not reinterpret a historical 3/3 as the current result or as complete
fixture conformance certification.
## Failure and cancellation checks
- Start with no URL: useful disconnected controls/empty catalog.
- Enter an off-origin URL: reject and preserve the current exhibit.
- Enter a missing local URL: document-load timeout (15 seconds in the checked
browser), or hello timeout (5 seconds if an error page finishes loading).
Enter a valid path to recover.
- Disconnect during loading or switch rapidly: old frame load callbacks must
not attach to the new exhibit. Focused automated lifecycle tests cover this.
- Refresh state reads current values. Logs can be cleared; prior diagnostics
are timestamped and do not imply the current connection is failed.
## Evidence and repeatability limits
`evidence/step5-reference-suite.txt` is the actual timestamped browser suite output.
`step5-scifi-session.json` contains the actual discovered catalog, session metadata,
events and failures. The three reference JSON files contain DOM-rendered runtime
metadata/events; Haunted House also includes its errors. `step5-operator.jpg`
shows the operator panel. Evidence was captured in local Chromium on 2026-09-14.
A fresh `npm start` succeeded on port 4175 because an existing service occupied
4173; the final browser transport suite ran on that fresh process. The normal UI
ran on 4173. No separate pristine checkout was created; tests/startup use the
current source tree without build products. SciFi repeatability requires the
external files described above. Repository publishing validation has an existing
malformed trailing record block in the Post Step 4 Completion devlog; see report.
Follow-up evidence is separate from those historical artifacts:
`step5-scifi-arguments-ui.json` captures the corrected descriptors, text fields,
and successful events; `step5-scifi-arguments-files.json` identifies the tested
working copy; `step5-acceptance-rerun-browser.txt` records the current 2/3 failure.
`step5-scifi-arguments-ui-final.json` records the repeated checks after line-ending
cleanup, including a draft reset on speech capability rediscovery and successful
ticker resubmission with the exact intended text.
The follow-up started a fresh server on 4173 and performed the requested narrow
SciFi checks, rather than repeating every earlier operator case above.
The optional external validator regression check is:
```powershell
node test-fixtures/check-scifi-arguments.cjs G:/.vibe/SciFi-XZBT/js/contract-adapter.js
```
It checks descriptor arrays, required/type/unknown-key/length rejection before
execution, maximum-length acceptance, and unchanged argumentless behavior. It
supplements the real operator UI checks; it does not replace them.
+38
View File
@@ -0,0 +1,38 @@
// Optional external-exhibit regression check; not NGN product configuration.
// Usage: node test-fixtures/check-scifi-arguments.cjs <contract-adapter.js>
const fs = require('node:fs');
const vm = require('node:vm');
const assert = require('node:assert/strict');
async function main() {
const context = { window: {}, console };
vm.createContext(context);
vm.runInContext(fs.readFileSync(process.argv[2], 'utf8'), context);
const calls = [];
const adapter = new context.window.XZBTContractAdapter({ bindings: { invokers: {
'speech.say': args => calls.push(args),
'display.ticker': args => calls.push(args),
'speech.generate-announcement': args => calls.push(args)
} } });
for (const [id, maxLength] of [['speech.say', 2000], ['display.ticker', 512]]) {
const descriptor = adapter.targets.get(id);
assert.equal(Object.hasOwn(descriptor, 'args'), false);
assert.deepEqual(JSON.parse(JSON.stringify(descriptor.arguments)), [
{ name: 'text', type: 'string', required: true, maxLength }
]);
for (const args of [{}, { text: null }, { text: 42 }, { text: 'x', extra: true }, { text: 'x'.repeat(maxLength + 1) }]) {
const before = calls.length;
const result = await adapter.invokeAction(id, args);
assert.equal(result.code, 'INVALID_VALUE');
assert.equal(calls.length, before, 'invalid arguments must not execute');
}
const text = 'x'.repeat(maxLength);
assert.equal((await adapter.invokeAction(id, { text })).ok, true);
assert.equal(calls.at(-1).text, text);
console.log(`PASS ${id}: arguments metadata, required/type/unknown/length rejection, exact length accepted`);
}
assert.equal((await adapter.invokeAction('speech.generate-announcement', {})).ok, true);
assert.equal((await adapter.invokeAction('speech.generate-announcement', { text: 'x' })).code, 'INVALID_VALUE');
console.log('PASS argumentless impulse: empty args accepted, unknown key rejected');
}
main().catch(error => { console.error(error); process.exitCode = 1; });
@@ -0,0 +1,7 @@
Started: 2026-09-14T19:41:45.445Z
PASS aquarium: 12 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
PASS planetarium: 14 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
FAIL haunted-house: room.haunt-level: Value must follow step 0.01.
2/3 real exhibits passed.
Finished: 2026-09-14T19:41:45.575Z
@@ -0,0 +1,66 @@
{
"events": [
{
"correlationId": "ngn-2-4",
"sequence": 1,
"sessionId": "sess-1a192",
"source": "host",
"stateRevision": 1,
"target": "tank.population",
"timestamp": 1789398588359,
"type": "state.changed",
"value": 16,
"xzbt": "5.2"
},
{
"correlationId": "ngn-2-6",
"sequence": 2,
"sessionId": "sess-1a192",
"source": "host",
"stateRevision": 2,
"target": "tank.paused",
"timestamp": 1789398588908,
"type": "state.changed",
"value": true,
"xzbt": "5.2"
},
{
"correlationId": "ngn-2-8",
"sequence": 3,
"sessionId": "sess-1a192",
"source": "host",
"stateRevision": 3,
"target": "tank.species",
"timestamp": 1789398589178,
"type": "selection.changed",
"value": "blue-tang",
"xzbt": "5.2"
},
{
"args": {},
"correlationId": "ngn-2-10",
"sequence": 4,
"sessionId": "sess-1a192",
"source": "host",
"target": "action.feed",
"timestamp": 1789398589436,
"type": "action.executed",
"xzbt": "5.2"
}
],
"metadata": {
"contract": {
"major": 5,
"minor": 2
},
"exhibit": {
"build": "reference-exhibit",
"product": "Aquarium",
"version": "1.0.0"
},
"registryRevision": 1,
"sequence": 4,
"sessionId": "sess-1a192",
"stateRevision": 3
}
}
@@ -0,0 +1,7 @@
Started: 2026-09-14T19:55:22.193Z
PASS aquarium: 12 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
PASS planetarium: 14 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
PASS haunted-house: 13 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
3/3 real exhibits passed.
Finished: 2026-09-14T19:55:22.342Z
@@ -0,0 +1,25 @@
{
"capturedAt": "2026-09-14T19:56:36.172Z",
"checks": [
{
"status": "fulfilled",
"value": {
"chunk_id": "82977d",
"wall_time_seconds": 1.3615515999999999,
"exit_code": 0,
"original_token_count": 585,
"output": "\n> [email protected] test\n> node --test\n\n✔ connection accepts served paths and same-origin URLs, rejects unsupported locations (1.7406ms)\n✔ switch and disconnect cancel old frame loads; invalid URL preserves active frame (1.1493ms)\n✔ reconnect negotiates existing frame and reloads remembered URL after disconnect (0.4236ms)\n✔ stalled document load ends with recoverable error (20.0644ms)\n✔ optional descriptor metadata is permissive when omitted and typed when supplied (1.4027ms)\n✔ Haunted House reports bounded hundredths while preserving continuous drift (28.2601ms)\n✔ Haunted House snapshots and mutation events stay valid through Manifest, drift and Calm (11.0154ms)\n✔ negotiates, discovers and reads real session fields (4.696ms)\n✔ sets all persistent kinds, invokes arguments, preserves no-op revisions (1.6233ms)\n✔ invalid values and required/unknown arguments never reach transport (1.4478ms)\n✔ argument type/enum/bounds/step/length rules and unsupported future types (0.5322ms)\n✔ surfaces exhibit errors and invalid session requires reconnect (0.9883ms)\n✔ unsupported version and timeout are explicit failures (11.4367ms)\n✔ native events update cache; shared revision is not a gap (0.8535ms)\n✔ sequence and revision gaps resync and remain visible (26.0243ms)\n✔ capability and registry changes debounce discovery; normal state does not (52.8678ms)\n✔ events arriving during snapshot are replayed without lost updates (0.6791ms)\n✔ old session traffic does not mutate new cache (0.4186ms)\n✔ malformed persistent events trigger recovery (25.6604ms)\n✔ postMessage verifies origin and source and cleans up (0.4321ms)\n✔ local server serves host and denies repository/private paths (41.9438ms)\n✔ invalid reported types do not contaminate the cache (26.2967ms)\n✔ invalid snapshot values preserve previous cache and mark uncertainty (0.6139ms)\n✔ snapshot revision cannot roll back a previously observed transaction (0.322ms)\n✔ registry rediscovery adds descriptors and removes obsolete cached targets (25.7427ms)\n✔ unsupported future impulse arguments do not hide the catalog (0.7149ms)\n✔ capability requirements block unusable services without deleting targets (0.4759ms)\nℹ tests 27\nℹ suites 0\nℹ pass 27\nℹ fail 0\nℹ cancelled 0\nℹ skipped 0\nℹ todo 0\nℹ duration_ms 388.0334\n"
}
},
{
"status": "fulfilled",
"value": {
"chunk_id": "9c0253",
"wall_time_seconds": 31.5457821,
"exit_code": 0,
"original_token_count": 8,
"output": "devlog-editor: devlog is valid\r\n"
}
}
]
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,128 @@
{
"events": [
{
"correlationId": "ngn-11-35",
"sequence": 1,
"sessionId": "sess-1ce04",
"source": "host",
"stateRevision": 1,
"target": "room.haunt-level",
"timestamp": 1789398645709,
"type": "state.changed",
"value": 0.5,
"xzbt": "5.2"
},
{
"correlationId": "ngn-11-37",
"sequence": 2,
"sessionId": "sess-1ce04",
"source": "host",
"stateRevision": 2,
"target": "room.paused",
"timestamp": 1789398646251,
"type": "state.changed",
"value": true,
"xzbt": "5.2"
},
{
"correlationId": "ngn-11-39",
"sequence": 3,
"sessionId": "sess-1ce04",
"source": "host",
"stateRevision": 3,
"target": "room.current",
"timestamp": 1789398646528,
"type": "selection.changed",
"value": "library",
"xzbt": "5.2"
},
{
"args": {},
"correlationId": "ngn-11-41",
"sequence": 4,
"sessionId": "sess-1ce04",
"source": "host",
"target": "action.manifest",
"timestamp": 1789398646792,
"type": "action.executed",
"xzbt": "5.2"
}
],
"logs": [
{
"code": "SESSION",
"detail": {
"sessionId": "sess-1a192"
},
"message": "Exhibit session established.",
"time": "2026-09-14T15:09:20.864Z"
},
{
"code": "SESSION",
"detail": {
"sessionId": "sess-21bcb"
},
"message": "Exhibit session established.",
"time": "2026-09-14T15:09:49.720Z"
},
{
"code": "SESSION",
"detail": {
"sessionId": "sess-14131"
},
"message": "Exhibit session established.",
"time": "2026-09-14T15:09:50.283Z"
},
{
"code": "SESSION",
"detail": {
"sessionId": "sess-194b7"
},
"message": "Exhibit session established.",
"time": "2026-09-14T15:10:00.111Z"
},
{
"code": "SESSION",
"detail": {
"sessionId": "sess-22e"
},
"message": "Exhibit session established.",
"time": "2026-09-14T15:10:24.934Z"
},
{
"code": "SESSION",
"detail": {
"sessionId": "sess-1ce04"
},
"message": "Exhibit session established.",
"time": "2026-09-14T15:10:25.249Z"
},
{
"code": "INVALID_MESSAGE",
"detail": null,
"message": "room.haunt-level: Value must follow step 0.01.",
"time": "2026-09-14T15:10:46.252Z"
},
{
"code": "INVALID_MESSAGE",
"detail": null,
"message": "room.haunt-level: Value must follow step 0.01.",
"time": "2026-09-14T15:10:46.530Z"
}
],
"metadata": {
"contract": {
"major": 5,
"minor": 2
},
"exhibit": {
"build": "reference-exhibit",
"product": "Haunted House",
"version": "1.0.0"
},
"registryRevision": 1,
"sequence": 4,
"sessionId": "sess-1ce04",
"stateRevision": 3
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

@@ -0,0 +1,68 @@
{
"events": [
{
"correlationId": "ngn-8-21",
"sequence": 1,
"sessionId": "sess-194b7",
"source": "host",
"stateRevision": 1,
"target": "sky.azimuth",
"timestamp": 1789398623275,
"type": "state.changed",
"value": 0.75,
"xzbt": "5.2"
},
{
"correlationId": "ngn-8-23",
"sequence": 2,
"sessionId": "sess-194b7",
"source": "host",
"stateRevision": 2,
"target": "sky.paused",
"timestamp": 1789398623816,
"type": "state.changed",
"value": true,
"xzbt": "5.2"
},
{
"correlationId": "ngn-8-25",
"sequence": 3,
"sessionId": "sess-194b7",
"source": "host",
"stateRevision": 3,
"target": "sky.constellation",
"timestamp": 1789398624094,
"type": "selection.changed",
"value": "cygnus",
"xzbt": "5.2"
},
{
"args": {
"minutes": 30
},
"correlationId": "ngn-8-27",
"sequence": 4,
"sessionId": "sess-194b7",
"source": "host",
"target": "action.advance-time",
"timestamp": 1789398624643,
"type": "action.executed",
"xzbt": "5.2"
}
],
"metadata": {
"contract": {
"major": 5,
"minor": 2
},
"exhibit": {
"build": "reference-exhibit",
"product": "Planetarium",
"version": "1.0.0"
},
"registryRevision": 1,
"sequence": 4,
"sessionId": "sess-194b7",
"stateRevision": 3
}
}
@@ -0,0 +1,6 @@
Started: 2026-09-14T15:11:53.141Z
PASS aquarium: 12 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
PASS planetarium: 14 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
PASS haunted-house: 13 targets; negotiation, discovery, state/range/selection, invoke, errors, events, no-op, reconnect, session invalidation/recovery.
3/3 real exhibits passed.
Finished: 2026-09-14T15:11:53.273Z
@@ -0,0 +1,68 @@
{
"capturedAt": "2026-09-14T19:45:18.3670019Z",
"source": "G:\\.vibe\\SciFi-XZBT",
"sourceCommit": "179b9db715aaa92999c5bfef451b6877f30079fe",
"destination": "G:\\.vibe\\XZBT-NGN\\test-fixtures\\local\\scifi-arguments",
"files": [
{
"path": "index.html",
"sourceSha256": "9A851185BB5CB78AD034E25709253222BB35CE061716F611750CB758A55BC44C",
"copySha256": "9A851185BB5CB78AD034E25709253222BB35CE061716F611750CB758A55BC44C"
},
{
"path": "css\\style.css",
"sourceSha256": "93032672388E757EFB6A52C5059344C378A7CED9F738D2C907EF4D969BB87CEE",
"copySha256": "93032672388E757EFB6A52C5059344C378A7CED9F738D2C907EF4D969BB87CEE"
},
{
"path": "js\\app.js",
"sourceSha256": "499280FE19BAF4D4429AD915958C2BB54247018CDAC1195EB17E906DDC6370FE",
"copySha256": "499280FE19BAF4D4429AD915958C2BB54247018CDAC1195EB17E906DDC6370FE"
},
{
"path": "js\\audio.js",
"sourceSha256": "0E8C4D8C09B7C53F0C2F402C259AACE95656AA4181709CB9F4D8F30F0D451A64",
"copySha256": "0E8C4D8C09B7C53F0C2F402C259AACE95656AA4181709CB9F4D8F30F0D451A64"
},
{
"path": "js\\config.js",
"sourceSha256": "8ED99BDABD688C5D738DF6515BADCED90CD2EC73C81CAFC07376E62BFCF15CE5",
"copySha256": "8ED99BDABD688C5D738DF6515BADCED90CD2EC73C81CAFC07376E62BFCF15CE5"
},
{
"path": "js\\contract-adapter.js",
"sourceSha256": "71C74BECA55046D7899653C0C8FA420A169BB6A68BAA43E1D02443AA6AAE7747",
"copySha256": "71C74BECA55046D7899653C0C8FA420A169BB6A68BAA43E1D02443AA6AAE7747"
},
{
"path": "js\\control-bus.js",
"sourceSha256": "47160558AF54F8F7E6408B6E2E52E726568EBA02058C4518CC221B86AC8F2234",
"copySha256": "47160558AF54F8F7E6408B6E2E52E726568EBA02058C4518CC221B86AC8F2234"
},
{
"path": "js\\core-animations.js",
"sourceSha256": "0CA430E307090F2D391FD92C074B00B7193259DD82FC656612DBF7397D945E7D",
"copySha256": "0CA430E307090F2D391FD92C074B00B7193259DD82FC656612DBF7397D945E7D"
},
{
"path": "js\\generative-experience.js",
"sourceSha256": "371FF099E9529DA9D93F20B943F46A40466248AAEF91955D11BF005DC29817DB",
"copySha256": "371FF099E9529DA9D93F20B943F46A40466248AAEF91955D11BF005DC29817DB"
},
{
"path": "js\\observation-bezels.js",
"sourceSha256": "18B853477F66C39CA6BCC7FE08C9C2BF868E2A909D3E18C38681D589205108FA",
"copySha256": "18B853477F66C39CA6BCC7FE08C9C2BF868E2A909D3E18C38681D589205108FA"
},
{
"path": "js\\observation-engine.js",
"sourceSha256": "A5FEE90BDE61F733D28FD9F5EA58A81BCA911F9B3D0BBE41AE65CB06C5188376",
"copySha256": "A5FEE90BDE61F733D28FD9F5EA58A81BCA911F9B3D0BBE41AE65CB06C5188376"
},
{
"path": "js\\visualizer.js",
"sourceSha256": "ED33A96E62674D0F7F30DDDC9FE83E94CA488BFCA45F32585E7AE51F0B35B89A",
"copySha256": "ED33A96E62674D0F7F30DDDC9FE83E94CA488BFCA45F32585E7AE51F0B35B89A"
}
]
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,50 @@
[
{
"path": "index.html",
"sha256": "9A851185BB5CB78AD034E25709253222BB35CE061716F611750CB758A55BC44C"
},
{
"path": "css\\style.css",
"sha256": "93032672388E757EFB6A52C5059344C378A7CED9F738D2C907EF4D969BB87CEE"
},
{
"path": "js\\app.js",
"sha256": "499280FE19BAF4D4429AD915958C2BB54247018CDAC1195EB17E906DDC6370FE"
},
{
"path": "js\\audio.js",
"sha256": "0E8C4D8C09B7C53F0C2F402C259AACE95656AA4181709CB9F4D8F30F0D451A64"
},
{
"path": "js\\config.js",
"sha256": "8ED99BDABD688C5D738DF6515BADCED90CD2EC73C81CAFC07376E62BFCF15CE5"
},
{
"path": "js\\contract-adapter.js",
"sha256": "0ED3234477EE21C50F1E872313B6259DF37E269D06C523DA60E41B484DA5236F"
},
{
"path": "js\\control-bus.js",
"sha256": "47160558AF54F8F7E6408B6E2E52E726568EBA02058C4518CC221B86AC8F2234"
},
{
"path": "js\\core-animations.js",
"sha256": "0CA430E307090F2D391FD92C074B00B7193259DD82FC656612DBF7397D945E7D"
},
{
"path": "js\\generative-experience.js",
"sha256": "371FF099E9529DA9D93F20B943F46A40466248AAEF91955D11BF005DC29817DB"
},
{
"path": "js\\observation-bezels.js",
"sha256": "18B853477F66C39CA6BCC7FE08C9C2BF868E2A909D3E18C38681D589205108FA"
},
{
"path": "js\\observation-engine.js",
"sha256": "A5FEE90BDE61F733D28FD9F5EA58A81BCA911F9B3D0BBE41AE65CB06C5188376"
},
{
"path": "js\\visualizer.js",
"sha256": "ED33A96E62674D0F7F30DDDC9FE83E94CA488BFCA45F32585E7AE51F0B35B89A"
}
]
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -19,7 +19,7 @@ async function raw(transport, message) {
});
}
run.addEventListener('click', async () => {
run.disabled = true; results.textContent = ''; document.querySelector('#fixtures').replaceChildren();
run.disabled = true; results.textContent = `Started: ${new Date().toISOString()}\n`; document.querySelector('#fixtures').replaceChildren();
let passed = 0;
for (const name of ['aquarium', 'planetarium', 'haunted-house']) {
const host = new ExhibitHost();
@@ -74,5 +74,6 @@ run.addEventListener('click', async () => {
} catch (error) { results.textContent += `FAIL ${name}: ${error.message}\n`; }
finally { host.disconnect(); frame.remove(); }
}
results.textContent += `${passed}/3 real exhibits passed.\n`; run.disabled = false;
results.textContent += `${passed}/3 real exhibits passed.\nFinished: ${new Date().toISOString()}\n`; run.disabled = false;
console.info(results.textContent);
});
@@ -582,7 +582,8 @@
switch (targetId) {
case 'room.current': return h.room;
case 'room.spirit': return h.spirit;
case 'room.haunt-level': return Math.round(h.hauntLevel * 1000) / 1000;
// Keep the simulation continuous; report bounded, integer hundredths.
case 'room.haunt-level': return Math.round(clamp(h.hauntLevel, 0, 1) * 100) / 100;
case 'room.fog-density': return h.fogDensity;
case 'room.candlelight': return h.candlelight;
case 'room.audio-enabled': return h.audioEnabled;