test: добавить Stage 6 в golden-матрицу (#673)

Issue: #673
User-Visible: no
This commit is contained in:
Sergey Matyunin
2026-09-27 07:51:54 +00:00
committed by claude[bot]
parent 2f857a0f6b
commit 15207dbacd
5 changed files with 97 additions and 54 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
// #649 AC12: product frames for docs/design/649-25d-stage6/ACCEPTANCE.md.
// Diagnostic, not golden (#455): run on a built bundle, compare by eye with the
// lab frames of sketch 07.
// These scenarios are canonical golden entries (#673). This focused command
// remains a diagnostic helper for rebuilding the side-by-side design document;
// baseline capture and acceptance still use the complete golden matrix (#455).
//
// npm run build && npm run bundle:sync
// node demo/capture_stage6_acceptance_649.mjs [out-dir]
+44 -45
View File
@@ -1,7 +1,7 @@
import { fixtureWallKey } from '../fixtures/visual-matrix.mjs';
/** Data-only HP-QA-01 capture matrix. Bump when framing or scenarios change. */
export const GOLDEN_MATRIX_VERSION = 65;
export const GOLDEN_MATRIX_VERSION = 66;
const stage = { capture: 'stage', threshold: { maxChannelDelta: 10, maxDiffRatio: 0.0005 } };
const page = { capture: 'page', threshold: { maxChannelDelta: 10, maxDiffRatio: 0.0008 } };
@@ -218,7 +218,50 @@ const stairLayerFixture = [
target_space_id: 'golden-lighting' },
];
/**
* #649/#673 Stage 6 acceptance scenes
* (docs/design/649-25d-stage6/ACCEPTANCE.md): tiles, floor shadows, soft sun
* wash and theme-free walls in the four theme × floor combinations of the
* approved sketch 07 (attachments 09, 10, 12, 13) plus the lifted hover frame
* (attachment 11); sun as the lab default 10:00. These exact objects are part
* of GOLDEN_SCENARIOS below; the separate export keeps the focused diagnostic
* side-by-side capture script useful without defining a second matrix.
*/
export const STAGE6_ACCEPTANCE_SCENARIOS = Object.freeze([
...[['light', 'light'], ['light', 'dark'], ['dark', 'dark'], ['dark', 'light']].map(([theme, floor]) => ({
id: `isometric-stage6-${theme}-${floor}floor`, fixture: 'visual',
space: 'golden-lighting', mode: 'view', projection: 'iso',
stage3Fixture: { roomMetrics: true, lockOpening: 'light-door', lockState: 'locked' },
stage3Golden: { requiredKinds: stage3RequiredOverlays },
markerOverrides: stage3DenseMarkers,
layoutOverrides: stage3DenseLayout,
stateOverrides: {
'light.golden_light_one': { attributes: { lqi: 40 } },
'light.golden_light_two': { attributes: { lqi: 120 } },
'sensor.golden_right_linkquality': { state: '210' },
'sun.sun': { attributes: { azimuth: 150, elevation: 52 } },
},
fillMode: 'custom', customFill: { c: floor === 'light' ? '#eee8de' : '#737777', a: 1 },
glowEnabled: false, sunRays: true, northDeg: 180,
// The lab's walls are the default white; the colour is the user's either way.
wallFill: { c: '#ffffff', a: 1 },
theme, viewport: { width: 1000, height: 900 }, ...stage,
})),
{ id: 'isometric-stage6-hover-light', fixture: 'visual',
space: 'golden-lighting', mode: 'view', projection: 'iso',
stage3Fixture: { roomMetrics: true, lockOpening: 'light-door', lockState: 'locked' },
stage3Golden: { requiredKinds: stage3RequiredOverlays },
markerOverrides: stage3DenseMarkers,
layoutOverrides: stage3DenseLayout,
fillMode: 'custom', customFill: { c: '#eee8de', a: 1 },
glowEnabled: false, sunRays: false,
hoverDevice: 'golden-light-two',
theme: 'light', viewport: { width: 1000, height: 900 }, ...stage,
},
]);
export const GOLDEN_SCENARIOS = Object.freeze([
...STAGE6_ACCEPTANCE_SCENARIOS,
// #663 AC3/AC10/AC12: both stair geometries, both rise directions and
// small/large footprints across themes, flat/2.5D and interaction states.
{ id: 'stairs-flat-normal-light', fixture: 'visual', space: 'golden-geometry', mode: 'view',
@@ -1224,47 +1267,3 @@ export const GOLDEN_SCENARIOS = Object.freeze([
cardEditorInvalidDefaultFloor: 'removed-floor', language: 'ru', theme: 'dark',
viewport: { width: 900, height: 760 }, ...page },
]);
/**
* #649 Stage 6 acceptance scenes (docs/design/649-25d-stage6/ACCEPTANCE.md):
* tiles, floor shadows, soft sun wash and theme-free walls in the four
* theme × floor combinations of the approved sketch 07 (attachments 09, 10,
* 12, 13) plus the lifted hover frame (attachment 11); sun as the lab default
* 10:00. They join GOLDEN_SCENARIOS in the same class D commit as their
* baselines captured on Linux CI (#455): every matrix scene needs a reviewed
* baseline (test/golden-wsl-artifact.test.mjs, #641), and a baseline cannot be
* captured before the scene exists. Until then they drive the diagnostic
* side-by-side frames only.
*/
export const STAGE6_ACCEPTANCE_SCENARIOS = Object.freeze([
...[['light', 'light'], ['light', 'dark'], ['dark', 'dark'], ['dark', 'light']].map(([theme, floor]) => ({
id: `isometric-stage6-${theme}-${floor}floor`, fixture: 'visual',
space: 'golden-lighting', mode: 'view', projection: 'iso',
stage3Fixture: { roomMetrics: true, lockOpening: 'light-door', lockState: 'locked' },
stage3Golden: { requiredKinds: stage3RequiredOverlays },
markerOverrides: stage3DenseMarkers,
layoutOverrides: stage3DenseLayout,
stateOverrides: {
'light.golden_light_one': { attributes: { lqi: 40 } },
'light.golden_light_two': { attributes: { lqi: 120 } },
'sensor.golden_right_linkquality': { state: '210' },
'sun.sun': { attributes: { azimuth: 150, elevation: 52 } },
},
fillMode: 'custom', customFill: { c: floor === 'light' ? '#eee8de' : '#737777', a: 1 },
glowEnabled: false, sunRays: true, northDeg: 180,
// The lab's walls are the default white; the colour is the user's either way.
wallFill: { c: '#ffffff', a: 1 },
theme, viewport: { width: 1000, height: 900 }, ...stage,
})),
{ id: 'isometric-stage6-hover-light', fixture: 'visual',
space: 'golden-lighting', mode: 'view', projection: 'iso',
stage3Fixture: { roomMetrics: true, lockOpening: 'light-door', lockState: 'locked' },
stage3Golden: { requiredKinds: stage3RequiredOverlays },
markerOverrides: stage3DenseMarkers,
layoutOverrides: stage3DenseLayout,
fillMode: 'custom', customFill: { c: '#eee8de', a: 1 },
glowEnabled: false, sunRays: false,
hoverDevice: 'golden-light-two',
theme: 'light', viewport: { width: 1000, height: 900 }, ...stage,
},
]);
+5 -6
View File
@@ -21,12 +21,11 @@ issue body; implementation notes: `docs/ISOMETRIC.md` § Stage 6, `docs/SUN.md`
`node demo/capture_stage6_acceptance_649.mjs` on a built bundle. The
furniture and settings frames come from the demo fixture.
These are **diagnostic** frames, not golden baselines. The five scenes join
`GOLDEN_SCENARIOS` together with their baselines captured and accepted on
Linux CI (#455) — a matrix scene without a reviewed baseline turns
`test/golden-wsl-artifact.test.mjs` (#641) red, and a baseline cannot exist
before its scene. PNGs are
reduced to a 256-colour palette; that is enough to compare layout and tone.
The five product scenes are canonical entries of `GOLDEN_SCENARIOS` (#673),
with reviewed baselines captured and accepted through the Linux/WSL contract
(#455, #641). The side-by-side PNGs in this document remain diagnostic copies:
they are reduced to a 256-colour palette, which is enough to compare layout and
tone, while the golden baselines retain their canonical bytes.
The two plans differ (the lab is its own SVG snapshot of a first floor; the
product frame is the golden lighting fixture), so the comparison is of the
+10
View File
@@ -10792,6 +10792,16 @@ const MUTANT_DEFINITIONS = [
replace: ' rotDeg: 4,\n',
}],
},
{
id: 'stage6-acceptance-left-diagnostic-only',
guard: 'node --test --test-name-pattern="#673" test/golden-matrix.test.mjs',
because: '#673: the five approved Stage 6 frames must be in the canonical matrix, not only the diagnostic exporter',
patches: [{
file: 'demo/golden/matrix.mjs',
find: ' ...STAGE6_ACCEPTANCE_SCENARIOS,\n // #663 AC3/AC10/AC12:',
replace: ' // mutant: Stage 6 acceptance remains diagnostic-only\n // #663 AC3/AC10/AC12:',
}],
},
{
id: 'stage3-w2-room-label-left-on-floor',
guard: 'node --test --test-name-pattern="exact Stage 4 overlay matrix" test/iso-overlays.test.mjs',
+35 -1
View File
@@ -4,6 +4,7 @@ import test from 'node:test';
import { prepareGoldenFixture } from '../demo/golden/harness.mjs';
import {
GOLDEN_MATRIX_VERSION, GOLDEN_SCENARIOS, OPENING_SYMBOL_EXISTING_GOLDEN_IMPACT,
STAGE6_ACCEPTANCE_SCENARIOS,
} from '../demo/golden/matrix.mjs';
import { fixtureWallKey } from '../demo/fixtures/visual-matrix.mjs';
import { readHouseplanProductionSource } from './houseplan-source.mjs';
@@ -445,7 +446,7 @@ test('sun-ray golden requires browser-painted light from a state-only sun entity
assert.ok(scenario);
const fixture = prepareGoldenFixture(scenario);
const space = fixture.config.spaces.find((item) => item.id === scenario.space);
assert.equal(GOLDEN_MATRIX_VERSION, 65);
assert.equal(GOLDEN_MATRIX_VERSION, 66);
assert.equal(space.settings.sun_rays, true);
assert.equal(scenario.northDeg, 90,
'the sign-sensitive golden must keep a non-zero north direction');
@@ -941,6 +942,39 @@ test('issue 570 Stage 4 reuses the historical iso goldens for visual handoff cov
'combined live-layer preflight must run after the async vacuum fixture settles');
});
test('#673 Stage 6 designer acceptance scenes are canonical golden entries', () => {
const ids = STAGE6_ACCEPTANCE_SCENARIOS.map((scenario) => scenario.id);
assert.equal(GOLDEN_MATRIX_VERSION, 66);
assert.deepEqual(ids, [
'isometric-stage6-light-lightfloor',
'isometric-stage6-light-darkfloor',
'isometric-stage6-dark-darkfloor',
'isometric-stage6-dark-lightfloor',
'isometric-stage6-hover-light',
]);
for (const scenario of STAGE6_ACCEPTANCE_SCENARIOS) {
assert.strictEqual(GOLDEN_SCENARIOS.find((item) => item.id === scenario.id), scenario,
`${scenario.id} must be the exact reviewed matrix object, not a drifting copy`);
assert.equal(scenario.projection, 'iso');
assert.equal(scenario.mode, 'view');
assert.equal(scenario.capture, 'stage');
assert.deepEqual(scenario.stage3Golden.requiredKinds,
['device', 'room-label', 'opening-lock']);
}
const themeFloor = STAGE6_ACCEPTANCE_SCENARIOS.slice(0, 4);
assert.deepEqual(themeFloor.map((scenario) => [scenario.theme, scenario.customFill.c]), [
['light', '#eee8de'], ['light', '#737777'],
['dark', '#737777'], ['dark', '#eee8de'],
]);
assert.equal(themeFloor.every((scenario) => scenario.sunRays === true
&& scenario.northDeg === 180
&& scenario.stateOverrides['sun.sun'].attributes.azimuth === 150
&& scenario.stateOverrides['sun.sun'].attributes.elevation === 52), true);
const hover = STAGE6_ACCEPTANCE_SCENARIOS[4];
assert.equal(hover.hoverDevice, 'golden-light-two');
assert.equal(hover.sunRays, false);
});
test('golden harness applies doorway, state and layout overrides to a cloned fixture', () => {
const scenario = GOLDEN_SCENARIOS.find((item) => item.id === 'lighting-opaque-glow-two-doorways-dark');
const fixture = prepareGoldenFixture(scenario);