← back to Agent Cabinet
proof(live-ux-canary): gate marker against the bundle hash computed at startup, not a literal
56486bdc53a09bdf2fdc59a7d84c4a814d7b5515 · 2026-09-23 13:47:31 -0700 · Steve
Compute the expected marker the way redeploy-ux-delta.sh does (sha256[:12] of the canonical bundle) so a routine rebuild no longer reds the whole fleet, while a site left on a stale bundle is still caught. Unreadable bundle -> markerCanonical false with a surfaced reason, never a silent pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzbjT22E2Q7Q64Wy8xMeH5
Files touched
M front-page-audit/proof/live-ux-canary.mjs
Diff
commit 56486bdc53a09bdf2fdc59a7d84c4a814d7b5515
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Sep 23 13:47:31 2026 -0700
proof(live-ux-canary): gate marker against the bundle hash computed at startup, not a literal
Compute the expected marker the way redeploy-ux-delta.sh does (sha256[:12] of the canonical bundle) so a routine rebuild no longer reds the whole fleet, while a site left on a stale bundle is still caught. Unreadable bundle -> markerCanonical false with a surfaced reason, never a silent pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzbjT22E2Q7Q64Wy8xMeH5
---
front-page-audit/proof/live-ux-canary.mjs | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/front-page-audit/proof/live-ux-canary.mjs b/front-page-audit/proof/live-ux-canary.mjs
index 756f917..f99e059 100644
--- a/front-page-audit/proof/live-ux-canary.mjs
+++ b/front-page-audit/proof/live-ux-canary.mjs
@@ -9,14 +9,30 @@ process.env.NODE_PATH = '/Users/macstudio3/.npm-global/lib/node_modules';
require('module').Module._initPaths();
const { chromium, webkit } = require('playwright');
import fs from 'fs';
+import crypto from 'crypto';
const [,, sitesFile, engineName='chromium', outFile=`live-canary-${new Date().toISOString().replace(/[:.]/g,'-')}.json`] = process.argv;
const sites = fs.readFileSync(sitesFile,'utf8').split('\n').map(s=>s.trim()).filter(Boolean);
const BUNDLE_RX = /ux-primitives|UXGrid|ModalRig|Bento|CommandPalette|Toast|Skeleton|EmptyState|copyToClipboard/i;
-// Expected bundle marker. Set UX_MARKER to pin a specific build (mirror the deploy script's $CANON as the
-// single source of truth) when you want exact-match; otherwise accept any well-formed marker so a routine
-// rebuild — which rotates the content hash — doesn't red the whole fleet with a perfectly healthy bundle.
-const EXPECT_MARKER = process.env.UX_MARKER || null;
-const MARKER_RX = /^ux-primitives\.bundle v\d+\.\d+\.\d+#[0-9a-f]{6,}$/;
+// The deploy script (_shared/scripts/redeploy-ux-delta.sh) computes CANON=$(shasum -a 256
+// ux-primitives.bundle.js | cut -c1-12) and injects `ux-primitives.bundle v1.1.1#$CANON`. That hash is
+// content-derived, so any rebuild rotates it — a hardcoded literal reds the whole fleet after a routine
+// rebuild even though every site is correctly updated. Compute the expected marker the SAME way the deployer
+// does, from the canonical bundle, at startup, and gate against it so a site left on a STALE bundle (wrong
+// hash) is still caught. A caller may pin an exact marker via EXPECTED_MARKER (UX_MARKER kept for back-compat).
+// If the bundle can't be read we do NOT silently pass: markerCanonical goes false with a surfaced reason.
+const CANON_BUNDLE = process.env.UX_BUNDLE || '/Users/macstudio3/Projects/_shared/ux-primitives.bundle.js';
+const UX_VERSION = process.env.UX_VERSION || '1.1.1';
+let EXPECT_MARKER = process.env.EXPECTED_MARKER || process.env.UX_MARKER || null;
+let markerReason = null;
+if (!EXPECT_MARKER) {
+ try {
+ const h = crypto.createHash('sha256').update(fs.readFileSync(CANON_BUNDLE)).digest('hex').slice(0,12);
+ EXPECT_MARKER = `ux-primitives.bundle v${UX_VERSION}#${h}`;
+ } catch (e) {
+ markerReason = `bundle unreadable at ${CANON_BUNDLE}: ${String(e.message||e).slice(0,120)}`;
+ }
+}
+console.log(`expected marker: ${EXPECT_MARKER || '(UNRESOLVED — '+markerReason+')'}`);
const engine = engineName==='webkit'?webkit:chromium;
const browser = await engine.launch({ headless:true });
const out=[];
@@ -52,7 +68,8 @@ for (const site of sites){
rec.bundleErrors=[...consoleErr,...pageErr].filter(x=>BUNDLE_RX.test(x));
rec.otherErrors=[...consoleErr,...pageErr].filter(x=>!BUNDLE_RX.test(x)).length;
rec.pageErrorsAll=pageErr.length;
- rec.criteria={ uxInit: st.ux==='object', markerCanonical: EXPECT_MARKER ? (st.marker===EXPECT_MARKER) : (typeof st.marker==='string' && MARKER_RX.test(st.marker)), gridWired: st.hasGrid,
+ rec.markerExpected=EXPECT_MARKER; if(markerReason) rec.markerReason=markerReason;
+ rec.criteria={ uxInit: st.ux==='object', markerCanonical: EXPECT_MARKER ? (st.marker===EXPECT_MARKER) : false, gridWired: st.hasGrid,
skeletonSeen: maxSkel>0, skeletonCleared: st.skel===0, productsRender: st.products>0, noEmptyWhenProducts: st.empty===0,
controls: st.sort && st.density, noBundleErr: rec.bundleErrors.length===0 };
// skeletonSeen is INFORMATIONAL on live (a fast CDN load can legitimately beat the 50ms sampler); it does not gate pass
← 65c6777 proof(front-page): harden ux-primitives activation gate + de
·
back to Agent Cabinet
·
proof(prove-activation): kill every spawned server on any th 5b74e92 →