diff --git a/demo/benchmark_large_house.mjs b/demo/benchmark_large_house.mjs index ba7dc3c1..9c329fe0 100644 --- a/demo/benchmark_large_house.mjs +++ b/demo/benchmark_large_house.mjs @@ -175,6 +175,13 @@ try { const loadLongTasks = startLongTaskWindow(); const loadStarted = performance.now(); host.replaceChildren(card); + if (requiresIsometric) { + if (typeof card._onLabsSnapshot !== 'function') + throw new Error('large-house-isometric-v1 candidate has no Labs fixture hook'); + // The product flag expires at 1.65.0. Performance keeps exercising + // the dormant renderer without changing the public registry contract. + card._onLabsSnapshot({ active: Object.freeze(['iso']), space: '' }); + } card.hass = hassFor(fixture.states); window.__hpAssertCardContract(card, cardContract); if (requiresIsometric && (typeof card._setProjection !== 'function' diff --git a/demo/performance/README.md b/demo/performance/README.md index 1729ef8a..d3c0fd6a 100644 --- a/demo/performance/README.md +++ b/demo/performance/README.md @@ -4,10 +4,11 @@ fixture. The fixture has 60 rooms, 200 devices, 100 openings, 60 partitions, 40 columns and 500 decor objects on three floors. -Issue #89 adds `large-house-isometric-v1` through the same runner. It enables -`hp-labs=iso`, selects iso per fixture space, measures the View toggle and -records the capped `isoGeometry` cache. A comparison SHA predating #89 remains -flat while reporting the same profile. The dedicated +Issue #89 adds `large-house-isometric-v1` through the same runner. Because the +product flag expires at 1.65.0, the runner injects an explicit test-only Labs +snapshot, selects iso per fixture space, measures the View toggle and records +the capped `isoGeometry` cache. A comparison SHA predating #89 remains flat +while reporting the same profile. The dedicated `budgets-large-house-isometric.json` applies the reviewed 20% relative allowance plus absolute noise/ceiling checks. Only the exact-SHA Linux workflow is gate evidence; a local report is diagnostic. diff --git a/demo/performance/card-contract.mjs b/demo/performance/card-contract.mjs index 03c918ba..40c1c270 100644 --- a/demo/performance/card-contract.mjs +++ b/demo/performance/card-contract.mjs @@ -40,8 +40,10 @@ export const LARGE_HOUSE_CARD_CONTRACT = Object.freeze({ '_tool', ]), // A comparison SHA before #89 is intentionally flat; the isometric runner - // checks these two members only when the target source tree supports Stage 1. - optionalFields: Object.freeze(['_isoGeometryCache', '_planSnapGeometryCache', '_setProjection']), + // checks these members only when the target source tree supports Stage 1. + optionalFields: Object.freeze([ + '_isoGeometryCache', '_onLabsSnapshot', '_planSnapGeometryCache', '_setProjection', + ]), fieldTypes: Object.freeze({ _booting: 'boolean', _cleanFloorCache: 'map', @@ -50,6 +52,7 @@ export const LARGE_HOUSE_CARD_CONTRACT = Object.freeze({ _gridPitch: 'number', _loadOk: 'boolean', _model: 'array', + _onLabsSnapshot: 'function', _path: 'array', _isoGeometryCache: 'map', _planSnapGeometryCache: 'object', diff --git a/demo/smoke_isometric_contract.mjs b/demo/smoke_isometric_contract.mjs index bcdcbe02..d5bfc03f 100644 --- a/demo/smoke_isometric_contract.mjs +++ b/demo/smoke_isometric_contract.mjs @@ -13,6 +13,12 @@ const out = await page.evaluate(async () => { const enable = async () => { history.replaceState(null, '', '#space=f1&hp-labs=iso'); dispatchEvent(new HashChangeEvent('hashchange')); + if (typeof card._onLabsSnapshot !== 'function') throw new Error('missing Labs fixture hook'); + const active = Object.freeze(['iso']); + // The product flag expires at 1.65.0. Keep this renderer/lifecycle smoke + // explicit without extending the public Labs registry contract. + card._onLabsSnapshot({ active, space: '' }); + window.__hpLabs = active; await card.updateComplete; await frame(); }; diff --git a/demo/smoke_isometric_live_touch.mjs b/demo/smoke_isometric_live_touch.mjs index 5435249a..f09a538d 100644 --- a/demo/smoke_isometric_live_touch.mjs +++ b/demo/smoke_isometric_live_touch.mjs @@ -11,6 +11,12 @@ const out = await page.evaluate(async () => { const frame = () => new Promise((done) => requestAnimationFrame(() => requestAnimationFrame(done))); history.replaceState(null, '', '?hp-labs=iso#space=f1'); dispatchEvent(new HashChangeEvent('hashchange')); + if (typeof original._onLabsSnapshot !== 'function') throw new Error('missing Labs fixture hook'); + const testOnlyIso = Object.freeze(['iso']); + // The product registry remains expired; this direct snapshot exercises the + // dormant Stage 2 renderer and is removed by the real -iso path below. + original._onLabsSnapshot({ active: testOnlyIso, space: '' }); + window.__hpLabs = testOnlyIso; await original.updateComplete; const configSpace = original._serverCfg.spaces.find((space) => space.id === 'f1'); configSpace.settings = { @@ -293,6 +299,7 @@ const out = await page.evaluate(async () => { const card = document.createElement('houseplan-card'); card.setConfig({ type: 'custom:houseplan-card', kiosk }); host.replaceChildren(card); + card._onLabsSnapshot({ active: Object.freeze(['iso']), space: '' }); card.hass = window.__mkHass(); const started = performance.now(); while ((!card._loadOk || card._booting) && performance.now() - started < 9000) await wait(30); diff --git a/demo/smoke_split_corner_wall.mjs b/demo/smoke_split_corner_wall.mjs index 8f5992e5..84e99131 100644 --- a/demo/smoke_split_corner_wall.mjs +++ b/demo/smoke_split_corner_wall.mjs @@ -112,6 +112,8 @@ const res = await page.evaluate(async () => { history.replaceState(null, '', `?hp-labs=iso#space=${encodeURIComponent(c._space)}`); dispatchEvent(new HashChangeEvent('hashchange')); + if (typeof c._onLabsSnapshot !== 'function') throw new Error('missing Labs fixture hook'); + c._onLabsSnapshot({ active: Object.freeze(['iso']), space: '' }); await c.updateComplete; c._setProjection('iso'); await update(); diff --git a/demo/smoke_wall_junctions.mjs b/demo/smoke_wall_junctions.mjs index 3fa84d98..bce10e32 100644 --- a/demo/smoke_wall_junctions.mjs +++ b/demo/smoke_wall_junctions.mjs @@ -120,6 +120,8 @@ const out = await page.evaluate(async () => { history.replaceState(null, '', '?hp-labs=iso#space=junctions'); dispatchEvent(new HashChangeEvent('hashchange')); + if (typeof card._onLabsSnapshot !== 'function') throw new Error('missing Labs fixture hook'); + card._onLabsSnapshot({ active: Object.freeze(['iso']), space: '' }); await card.updateComplete; card._setProjection('iso'); await update();