mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-06 18:06:11 +00:00
Ouroboros advised a desktop-app owner to reload 'the browser tab' because the
runtime had no fact about the client UI: the launcher never exported the
retired OUROBOROS_DESKTOP_MODE flag, and messages carried no sending-surface
provenance at all.
Two additive facts, no device taxonomy (the model classifies raw observables):
- launcher.py exports OUROBOROS_PRESENTATION (desktop_window|browser_fallback;
absent=web) — the process posture, rendered as runtime_env.presentation.
- The SPA measures raw observables AT SEND TIME (pywebview bridge, ua,
viewport, matchMedia booleans, captured_at) and attaches client_surface to
each chat frame; the gateway normalizes it through the closed-key bounded
ouroboros/client_surface.py SSOT, stamps received_at, carries it in
task_metadata, persists it as an optional chat.jsonl column, and renders it
as the owner_client context fact. Non-web ingress gets a host-stamped
{channel: <source>} fallback; promotion/steering/mailbox carry it, and the
loop notes a mid-task surface change only when the surface IDENTITY differs
(viewport resize is not a device change), with a neutral note for the first
observed fact. SYSTEM.md documents the semantics and the pywebview product
facts (no Cmd+R, SHA auto-reload).
Adversarial waves 1-2 are folded in: Infinity viewport crash at ws ingress,
strict booleans, no-identity facts never mint change notes, provenance-honest
prompt wording, behavioral producer tests, send-site and received_at pins.
client_surface helpers live in their own module (message_bus/loop/chat.js stay
inside their ratchet sizes).
56 lines
2.4 KiB
JavaScript
56 lines
2.4 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
// Executable coverage for the send-time snapshot module (PLAN §9.7.26): the
|
|
// Python-side substring pins cannot catch a broken wire SHAPE — this runs the
|
|
// real code under a mocked browser environment.
|
|
|
|
function mockWindow({ pywebviewApi = undefined, narrow = false, coarse = false } = {}) {
|
|
globalThis.window = {
|
|
pywebview: pywebviewApi === undefined ? undefined : { api: pywebviewApi },
|
|
innerWidth: 1234,
|
|
innerHeight: 777,
|
|
matchMedia: (query) => ({
|
|
matches: query.includes('max-width') ? narrow : coarse,
|
|
}),
|
|
};
|
|
}
|
|
|
|
if (typeof navigator === 'undefined') {
|
|
globalThis.navigator = { userAgent: 'node-test/1.0' };
|
|
}
|
|
|
|
test('snapshot measures raw observables at call time', async () => {
|
|
mockWindow({ narrow: true, coarse: false });
|
|
const { clientSurfaceSnapshot } = await import('../modules/client_surface.js');
|
|
const snap = clientSurfaceSnapshot();
|
|
assert.equal(snap.pywebview, false);
|
|
assert.equal(typeof snap.ua, 'string');
|
|
assert.deepEqual(snap.viewport, { w: 1234, h: 777 });
|
|
assert.equal(snap.narrow_layout, true);
|
|
assert.equal(snap.coarse_pointer, false);
|
|
assert.ok(!Number.isNaN(Date.parse(snap.captured_at)), 'captured_at must be a parseable timestamp');
|
|
assert.deepEqual(
|
|
Object.keys(snap).sort(),
|
|
['captured_at', 'coarse_pointer', 'narrow_layout', 'pywebview', 'ua', 'viewport'],
|
|
'the wire shape is a closed set — a renamed/added key breaks the backend contract silently',
|
|
);
|
|
});
|
|
|
|
test('pywebview bridge presence flips the fact', async () => {
|
|
mockWindow({ pywebviewApi: {} });
|
|
const { clientSurfaceSnapshot } = await import('../modules/client_surface.js');
|
|
assert.equal(clientSurfaceSnapshot().pywebview, true);
|
|
});
|
|
|
|
test('field helper wraps the snapshot and stays honest on breakage', async () => {
|
|
mockWindow({});
|
|
const { clientSurfaceField, clientSurfaceSnapshot } = await import('../modules/client_surface.js');
|
|
const field = clientSurfaceField();
|
|
assert.ok(field.client_surface, 'field must wrap a live snapshot');
|
|
assert.deepEqual(Object.keys(field), ['client_surface']);
|
|
// A broken environment yields an honest null / empty spread, never a guess.
|
|
globalThis.window = undefined;
|
|
assert.equal(clientSurfaceSnapshot(), null);
|
|
assert.deepEqual(clientSurfaceField(), {});
|
|
});
|