Files
XZBT-NGN/test-fixtures/reference-exhibits/planetarium/contract-adapter.js
T
Labyricorn 745912e451 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.
2026-09-14 19:45:27 -07:00

216 lines
6.7 KiB
JavaScript

/*
* Planetarium — XZBT Exhibit Contract 5.3 adapter.
*
* Declares the catalog, binds targets to real exhibit services, and routes
* the native UI through the canonical mutation path. No state of its own.
*/
(function () {
'use strict';
var Core = window.XZBTContractCore;
var IDENTITY = {
product: 'Planetarium',
version: '1.0.0',
build: 'reference-exhibit'
};
var DESCRIPTORS = [
{
id: 'sky.constellation',
kind: 'selection',
label: 'Constellation',
description: 'Constellation currently tracked and drawn.',
options: [
{ value: 'orion', label: 'Orion' },
{ value: 'cygnus', label: 'Cygnus' },
{ value: 'scorpius', label: 'Scorpius' },
{ value: 'ursa-major', label: 'Ursa Major' },
{ value: 'cassiopeia', label: 'Cassiopeia' },
{ value: 'lyra', label: 'Lyra' }
],
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.magnitude-limit',
kind: 'range',
label: 'Magnitude limit',
description: 'Faintest stellar magnitude rendered. Higher values show more stars.',
min: 1, max: 6, step: 0.1, unit: 'mag',
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.azimuth',
kind: 'range',
label: 'Azimuth',
description: 'Compass bearing of the view, 0 to 1 of a full turn.',
min: 0, max: 1, step: 0.01,
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.altitude',
kind: 'range',
label: 'Altitude',
description: 'Elevation of the view above the horizon, 0 to 1.',
min: 0, max: 1, step: 0.01,
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.time-scale',
kind: 'range',
label: 'Time scale',
description: 'Rate at which sky time advances.',
min: 0, max: 4, step: 0.05, unit: 'x',
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.filter',
kind: 'selection',
label: 'Filter',
description: 'Optical filter applied to the view.',
options: [
{ value: 'none', label: 'None' },
{ value: 'light-pollution', label: 'Light pollution' },
{ value: 'h-alpha', label: 'H-alpha' },
{ value: 'oxygen-iii', label: 'Oxygen III' }
],
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.tracking',
kind: 'state',
valueType: 'boolean',
label: 'Tracking',
description: 'Whether the mount is tracking the selected constellation.',
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'sky.paused',
kind: 'state',
valueType: 'boolean',
label: 'Sky frozen',
description: 'Whether sky time is frozen.',
readable: true, writable: true, restorable: true,
category: 'sky', requires: []
},
{
id: 'action.advance-time',
kind: 'impulse',
label: 'Advance time',
description: 'Advance sky time. Optional argument: minutes (1 to 240).',
arguments: [
{ name: 'minutes', type: 'number', required: false, min: 1, max: 240, default: 10 }
],
readable: false, writable: false, restorable: false,
category: 'action', requires: []
},
{
id: 'action.reset-sky',
kind: 'impulse',
label: 'Reset sky',
description: 'Return sky time to epoch.',
readable: false, writable: false, restorable: false,
category: 'action', requires: []
},
{
id: 'action.toggle-tracking',
kind: 'impulse',
label: 'Toggle tracking',
description: 'Engage or disengage the mount.',
readable: false, writable: false, restorable: false,
category: 'action', requires: []
},
{
id: 'telemetry.visible-stars',
kind: 'state',
valueType: 'number',
label: 'Visible stars',
description: 'Stars currently above the magnitude limit.',
readable: true, writable: false, restorable: false,
category: 'telemetry', requires: []
},
{
id: 'telemetry.sky-time',
kind: 'state',
valueType: 'number',
unit: 'h',
label: 'Sky time',
description: 'Elapsed sky time in hours.',
readable: true, writable: false, restorable: false,
category: 'telemetry', requires: []
},
{
id: 'telemetry.moon-phase',
kind: 'state',
valueType: 'number',
label: 'Moon phase',
description: 'Lunar phase as a fraction of the cycle.',
readable: true, writable: false, restorable: false,
category: 'telemetry', requires: []
}
];
function createPlanetariumContract(exhibit, ui) {
var catalog = new Core.Catalog(DESCRIPTORS);
var capabilities = new Core.CapabilityRegistry();
capabilities.declare('render', 'ready');
var setters = {
'sky.constellation': function (v) { return exhibit.setConstellation(v); },
'sky.magnitude-limit': function (v) { return exhibit.setMagnitudeLimit(v); },
'sky.azimuth': function (v) { return exhibit.setAzimuth(v); },
'sky.altitude': function (v) { return exhibit.setAltitude(v); },
'sky.time-scale': function (v) { return exhibit.setTimeScale(v); },
'sky.filter': function (v) { return exhibit.setFilter(v); },
'sky.tracking': function (v) { return exhibit.setTracking(v); },
'sky.paused': function (v) { return exhibit.setPaused(v); }
};
var readers = {};
var ids = catalog.ids();
for (var i = 0; i < ids.length; i++) {
(function (id) {
readers[id] = function () { return exhibit.read(id); };
})(ids[i]);
}
var actions = {
'action.advance-time': function (args) { return exhibit.advanceTime(args); },
'action.reset-sky': function () { return exhibit.resetSky(); },
'action.toggle-tracking': function () { return exhibit.toggleTracking(); }
};
var core = new Core.ContractCore({
identity: IDENTITY,
catalog: catalog,
capabilities: capabilities,
setters: setters,
readers: readers,
actions: actions
});
ui.dispatchOverride = function (targetId, value) {
core.applyMutation(targetId, value, 'ui');
ui.sync();
};
ui.invokeOverride = function (targetId, args) {
core.invokeAction(targetId, args || {}, 'ui');
ui.sync();
};
exhibit.onChange = function () { ui.sync(); };
return core;
}
window.PlanetariumContract = { create: createPlanetariumContract, IDENTITY: IDENTITY };
})();