Packages

A real-browser external-app verifier for patch-safe Phoenix LiveView interactions, with secondary unstyled reference components.

Current section

Files

Jump to
live_interaction_contracts priv harness ci-assert.mjs
Raw

priv/harness/ci-assert.mjs

// CI fuse assertion. Reads harness/results.json and enforces the FROZEN
// classification: green machines must be green on all engines; red fixtures must be
// red. Exits non-zero on any violation. Amber/unknown are reported, never gating.
// Usage: node ci-assert.mjs [path-to-results.json]
import { readFileSync } from 'node:fs';
const path = process.argv[2] || 'results.json';
const r = JSON.parse(readFileSync(path));
const engines = Object.keys(r.engines);
const NONDESTRUCTIVE = ['siblingPatch', 'contentPatch', 'attributePatch', 'reorderNearby', 'streamNearby', 'pushPatch', 'reconnect'];
const survived = (m, after) => {
if (!after) return false;
switch (m) {
case 'pop': return after.open === true;
case 'dlg': case 'det': return after.open === true;
case 'sel': return after.value === 'b';
case 'inp': return after.value === 'typed-value' && after.focused === true;
case 'scr': return after.scrollTop === 500;
}
};
// FROZEN expectations (see DELEGATION_LEDGER.md / RED_FIXTURES.md).
const GREEN = ['pop', 'sel', 'inp', 'scr']; // must survive all non-destructive patches, all engines
const RED = ['dlg', 'det']; // must fail all non-destructive patches (expected failure)
const violations = [];
const note = [];
for (const e of engines) {
for (const [runIndex, run] of r.engines[e].runs.entries()) {
const where = `${e} run ${runIndex + 1}`;
if (run.FATAL) {
violations.push(`FATAL: ${where}${run.FATAL}`);
continue;
}
const aha = run.aha;
if (!aha) {
violations.push(`AHA EVIDENCE MISSING: ${where}`);
} else {
const pop = aha.popover;
const raw = aha.rawDialog;
const protectedDialog = aha.protectedDialog;
const patched = (x) => x?.before?.rev === 0 && x?.after?.rev === 1 && x?.after?.sameNode === true;
if (!patched(pop) || pop.before?.popoverOpen !== true || pop.after?.popoverOpen !== true) {
violations.push(`AHA POPOVER REGRESSION: ${where} — acknowledged patch must preserve same-node :popover-open state`);
}
if (!patched(raw) || raw.before?.open !== true || raw.before?.openAttr !== true || raw.before?.modal !== true ||
raw.after?.open !== false || raw.after?.openAttr !== false || raw.after?.modal !== true || raw.events?.length !== 0) {
violations.push(`AHA RAW DIALOG CHANGED: ${where} — expected observed torn vector open=false/openAttr=false/:modal=true with no lifecycle event`);
}
if (!patched(protectedDialog) || protectedDialog.before?.open !== true || protectedDialog.before?.openAttr !== true || protectedDialog.before?.modal !== true ||
protectedDialog.after?.open !== true || protectedDialog.after?.openAttr !== true || protectedDialog.after?.modal !== true) {
violations.push(`AHA PROTECTED DIALOG REGRESSION: ${where} — open/openAttr/:modal must remain coherent while content patches`);
}
}
for (const m of GREEN) {
const patches = run[m].patches;
for (const p of NONDESTRUCTIVE) {
if (!survived(m, patches[p].after)) violations.push(`GREEN REGRESSION: ${m}.${p} on ${where} — delegated state did not survive`);
}
}
for (const m of RED) {
const patches = run[m].patches;
const anySurvived = NONDESTRUCTIVE.some((p) => survived(m, patches[p].after));
if (anySurvived) violations.push(`RED FIXTURE TURNED GREEN: ${m} on ${where} — expected failure no longer fails; reconcile ledger & kernel`);
}
}
}
// determinism: both runs identical per engine
for (const e of engines) {
if (JSON.stringify(r.engines[e].runs[0]) !== JSON.stringify(r.engines[e].runs[1])) violations.push(`NON-DETERMINISTIC: ${e} run1 != run2`);
}
note.push(`versions: ${JSON.stringify(r.versions)}`);
note.push(`engines: ${engines.map((e) => e + ' ' + r.engines[e].version).join(', ')}`);
note.push(`amber/unknown (reported, non-gating): select-popup, IME`);
console.log(note.join('\n'));
if (violations.length) {
console.error('\nFUSE TRIPPED:\n' + violations.map((v) => ' ✗ ' + v).join('\n'));
process.exit(1);
}
console.log('\n✓ conformance fuse OK — green machines green, red fixtures red, deterministic');