@miller-tech/uap 1.138.1 → 1.140.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +12 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/fidelity.d.ts +5 -0
- package/dist/cli/fidelity.d.ts.map +1 -0
- package/dist/cli/fidelity.js +54 -0
- package/dist/cli/fidelity.js.map +1 -0
- package/dist/cli/guided-setup.d.ts.map +1 -1
- package/dist/cli/guided-setup.js +10 -0
- package/dist/cli/guided-setup.js.map +1 -1
- package/dist/cli/verify.d.ts +5 -0
- package/dist/cli/verify.d.ts.map +1 -1
- package/dist/cli/verify.js +79 -14
- package/dist/cli/verify.js.map +1 -1
- package/dist/cli/wizard-config.d.ts +9 -0
- package/dist/cli/wizard-config.d.ts.map +1 -1
- package/dist/cli/wizard-config.js +21 -0
- package/dist/cli/wizard-config.js.map +1 -1
- package/dist/config/settings-registry.d.ts.map +1 -1
- package/dist/config/settings-registry.js +32 -0
- package/dist/config/settings-registry.js.map +1 -1
- package/dist/delivery/fidelity.d.ts +24 -0
- package/dist/delivery/fidelity.d.ts.map +1 -0
- package/dist/delivery/fidelity.js +58 -0
- package/dist/delivery/fidelity.js.map +1 -0
- package/dist/delivery/vision-judge.d.ts +12 -2
- package/dist/delivery/vision-judge.d.ts.map +1 -1
- package/dist/delivery/vision-judge.js +56 -6
- package/dist/delivery/vision-judge.js.map +1 -1
- package/dist/delivery/visual-baseline.d.ts +45 -0
- package/dist/delivery/visual-baseline.d.ts.map +1 -0
- package/dist/delivery/visual-baseline.js +285 -0
- package/dist/delivery/visual-baseline.js.map +1 -0
- package/dist/delivery/visual-gate.d.ts +7 -1
- package/dist/delivery/visual-gate.d.ts.map +1 -1
- package/dist/delivery/visual-gate.js +25 -5
- package/dist/delivery/visual-gate.js.map +1 -1
- package/dist/types/config.d.ts +60 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +19 -0
- package/dist/types/config.js.map +1 -1
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/visual_verification.py +127 -0
- package/src/policies/schemas/policies/visual-verification.md +18 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* ADVISORY context. Unset config or any failure returns null — this seam is
|
|
10
10
|
* fail-soft by contract and never blocks a delivery on its own.
|
|
11
11
|
*/
|
|
12
|
-
import { readFileSync } from 'fs';
|
|
12
|
+
import { existsSync, readFileSync } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
13
14
|
import { fetchModelWithRetry } from '../models/long-fetch.js';
|
|
14
15
|
const MAX_IMAGES = 4;
|
|
15
16
|
const MAX_FINDINGS = 8;
|
|
@@ -35,11 +36,55 @@ export function parseVisionVerdict(text) {
|
|
|
35
36
|
return null;
|
|
36
37
|
}
|
|
37
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* The project's design system as review context — the DESIGN.md token allow-list
|
|
41
|
+
* (`.uap/design-tokens.json`, generated by `uap design`) plus the DESIGN.md
|
|
42
|
+
* intent prose. Lets the vision reviewer score adherence to the *actual* design
|
|
43
|
+
* system (palette, spacing, fonts, voice) instead of a generic "looks polished"
|
|
44
|
+
* bar. Returns '' when the project has no design system (fail-soft).
|
|
45
|
+
*/
|
|
46
|
+
export function readDesignContext(projectRoot) {
|
|
47
|
+
const parts = [];
|
|
48
|
+
try {
|
|
49
|
+
const allowPath = join(projectRoot, '.uap', 'design-tokens.json');
|
|
50
|
+
if (existsSync(allowPath)) {
|
|
51
|
+
const a = JSON.parse(readFileSync(allowPath, 'utf-8'));
|
|
52
|
+
if (a.name)
|
|
53
|
+
parts.push(`Design system: "${a.name}".`);
|
|
54
|
+
if (a.colors?.length)
|
|
55
|
+
parts.push(`Approved palette (the UI must use ONLY these colours): ${a.colors.slice(0, 14).join(', ')}.`);
|
|
56
|
+
if (a.spacing?.length)
|
|
57
|
+
parts.push(`Spacing scale: ${a.spacing.slice(0, 12).join(', ')}.`);
|
|
58
|
+
if (a.fontFamilies?.length)
|
|
59
|
+
parts.push(`Font families: ${a.fontFamilies.slice(0, 4).join(', ')}.`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
/* allow-list is optional */
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
for (const name of ['DESIGN.md', 'design.md', 'Design.md']) {
|
|
67
|
+
const p = join(projectRoot, name);
|
|
68
|
+
if (existsSync(p)) {
|
|
69
|
+
const md = readFileSync(p, 'utf-8').replace(/^---[\s\S]*?---\s*/, '').trim();
|
|
70
|
+
if (md)
|
|
71
|
+
parts.push(`Design intent (from ${name}):\n${md.slice(0, 1400)}`);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* DESIGN.md is optional */
|
|
78
|
+
}
|
|
79
|
+
return parts.join('\n');
|
|
80
|
+
}
|
|
38
81
|
/**
|
|
39
82
|
* Score screenshots against the spec with the configured vision model.
|
|
40
|
-
*
|
|
83
|
+
* `designContext` (see readDesignContext) makes the review judge adherence to
|
|
84
|
+
* the project's design system, not just generic polish. Returns null when
|
|
85
|
+
* unconfigured or on any failure.
|
|
41
86
|
*/
|
|
42
|
-
export async function judgeScreenshots(screenshotPaths, spec, fetchImpl) {
|
|
87
|
+
export async function judgeScreenshots(screenshotPaths, spec, designContext = '', fetchImpl) {
|
|
43
88
|
if (!visionJudgeConfigured() || screenshotPaths.length === 0)
|
|
44
89
|
return null;
|
|
45
90
|
const endpoint = process.env.UAP_VISION_ENDPOINT.replace(/\/$/, '');
|
|
@@ -59,10 +104,15 @@ export async function judgeScreenshots(screenshotPaths, spec, fetchImpl) {
|
|
|
59
104
|
{
|
|
60
105
|
type: 'text',
|
|
61
106
|
text: 'You are a strict visual reviewer. These are frames of a rendered application. ' +
|
|
62
|
-
'Judge (a) design/aesthetic quality (composition, color, readability, polish)
|
|
63
|
-
'(b) whether the visible behavior matches the spec below
|
|
107
|
+
'Judge (a) design/aesthetic quality (composition, color, readability, polish), ' +
|
|
108
|
+
'(b) whether the visible behavior matches the spec below, and ' +
|
|
109
|
+
(designContext
|
|
110
|
+
? '(c) ADHERENCE TO THE DESIGN SYSTEM below — penalize off-palette colours, off-scale spacing, wrong fonts, and anything that violates the stated design intent. '
|
|
111
|
+
: '') +
|
|
112
|
+
'Respond with ONLY JSON: ' +
|
|
64
113
|
'{"score": <0-10>, "findings": ["<specific, actionable issue>", ...]}\n\nSPEC:\n' +
|
|
65
|
-
spec.slice(0, 4000)
|
|
114
|
+
spec.slice(0, 4000) +
|
|
115
|
+
(designContext ? `\n\nDESIGN SYSTEM (score adherence to this):\n${designContext.slice(0, 2500)}` : ''),
|
|
66
116
|
},
|
|
67
117
|
...images,
|
|
68
118
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vision-judge.js","sourceRoot":"","sources":["../../src/delivery/vision-judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"vision-judge.js","sourceRoot":"","sources":["../../src/delivery/vision-judge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Fraction of changed cells above which a page has drifted. */
|
|
2
|
+
export declare const DEFAULT_DRIFT_THRESHOLD = 0.12;
|
|
3
|
+
export interface PageDrift {
|
|
4
|
+
/** Baseline PNG basename (page identity). */
|
|
5
|
+
name: string;
|
|
6
|
+
/** True when a baseline existed to compare against. */
|
|
7
|
+
hasBaseline: boolean;
|
|
8
|
+
/** Overall drift = max(colour, structural) (0–1); 0 when no baseline. */
|
|
9
|
+
drift: number;
|
|
10
|
+
/** Colour-grid drift component (0–1). */
|
|
11
|
+
colorDrift?: number;
|
|
12
|
+
/** Structural (layout/edge) drift component from the dHash (0–1). */
|
|
13
|
+
structuralDrift?: number;
|
|
14
|
+
/** True when drift exceeded the threshold. */
|
|
15
|
+
drifted: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Decode a PNG into an N×N grid of average [r,g,b]. Returns null for any format
|
|
19
|
+
* we do not handle (never throws).
|
|
20
|
+
*/
|
|
21
|
+
export declare function pngToGrid(path: string, n?: number): number[][] | null;
|
|
22
|
+
/**
|
|
23
|
+
* Perceptual difference-hash (dHash) on luminance: compares each cell to its
|
|
24
|
+
* right neighbour, yielding a structural bit-map that is invariant to global
|
|
25
|
+
* brightness/colour shifts but sensitive to LAYOUT and edges — the thing an
|
|
26
|
+
* average-colour grid is blind to. Returns null for undecodable input.
|
|
27
|
+
*/
|
|
28
|
+
export declare function pngToDHash(path: string, n?: number): boolean[] | null;
|
|
29
|
+
/** Fraction of differing bits between two dHashes (0–1). */
|
|
30
|
+
export declare function hammingDrift(a: boolean[], b: boolean[]): number;
|
|
31
|
+
/** Fraction of grid cells whose colour distance exceeds the tolerance (0–1). */
|
|
32
|
+
export declare function gridDrift(a: number[][], b: number[][]): number;
|
|
33
|
+
/** The latest screenshot per page (max one per `<page>` prefix) in `.uap/visual/`. */
|
|
34
|
+
export declare function latestScreenshots(projectRoot: string): string[];
|
|
35
|
+
/** Copy each page's latest screenshot into the baseline dir (accept the look). */
|
|
36
|
+
export declare function approveVisualBaseline(projectRoot: string): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Compare the current run's latest screenshots against approved baselines.
|
|
39
|
+
* Returns one entry per current page. Fail-soft: undecodable pairs report
|
|
40
|
+
* hasBaseline=false so they never spuriously block.
|
|
41
|
+
*/
|
|
42
|
+
export declare function compareVisualBaseline(projectRoot: string, threshold?: number): PageDrift[];
|
|
43
|
+
/** Human-readable one-liner for a set of drifts (empty string when nothing to say). */
|
|
44
|
+
export declare function driftSummary(drifts: PageDrift[]): string;
|
|
45
|
+
//# sourceMappingURL=visual-baseline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-baseline.d.ts","sourceRoot":"","sources":["../../src/delivery/visual-baseline.ts"],"names":[],"mappings":"AAuBA,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;CAClB;AA4GD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,SAAO,GAAG,MAAM,EAAE,EAAE,GAAG,IAAI,CAcnE;AAKD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,SAAU,GAAG,OAAO,EAAE,GAAG,IAAI,CAwBtE;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,CAM/D;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAS9D;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAW/D;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBnE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,SAAS,SAA0B,GAClC,SAAS,EAAE,CA2Bb;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAYxD"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual regression baselines — pin an accepted UI's rendered appearance and
|
|
3
|
+
* fail later runs that drift from it.
|
|
4
|
+
*
|
|
5
|
+
* The visual gate saves per-page screenshots under `.uap/visual/`. Approving a
|
|
6
|
+
* baseline copies each page's latest screenshot to `.uap/visual/baseline/`.
|
|
7
|
+
* Subsequent runs decode both PNGs into a coarse average-colour grid
|
|
8
|
+
* (dependency-free — Node `zlib` only) and report the fraction of grid cells
|
|
9
|
+
* whose colour moved beyond a per-cell tolerance. Under max fidelity with
|
|
10
|
+
* baselines enabled, drift past the threshold blocks like a broken gate.
|
|
11
|
+
*
|
|
12
|
+
* The decoder supports the format Playwright/Chromium emits: 8-bit,
|
|
13
|
+
* non-interlaced, colour-type 2 (RGB) or 6 (RGBA). Anything else fingerprints
|
|
14
|
+
* to null and is treated as "no comparable baseline" (fail-soft, never throws).
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, copyFileSync } from 'fs';
|
|
17
|
+
import { basename, join } from 'path';
|
|
18
|
+
import { inflateSync } from 'zlib';
|
|
19
|
+
/** Coarse grid resolution for the fingerprint (N×N average-colour cells). */
|
|
20
|
+
const GRID = 32;
|
|
21
|
+
/** Per-cell colour distance (0–255 per channel, summed) above which a cell "changed". */
|
|
22
|
+
const CELL_TOLERANCE = 60;
|
|
23
|
+
/** Fraction of changed cells above which a page has drifted. */
|
|
24
|
+
export const DEFAULT_DRIFT_THRESHOLD = 0.12;
|
|
25
|
+
function baselineDir(projectRoot) {
|
|
26
|
+
return join(projectRoot, '.uap', 'visual', 'baseline');
|
|
27
|
+
}
|
|
28
|
+
function visualDir(projectRoot) {
|
|
29
|
+
return join(projectRoot, '.uap', 'visual');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Decode a PNG to raw RGB(A) pixels. Returns null for any format we do not
|
|
33
|
+
* handle (never throws). Pure Node (`zlib.inflateSync`). Supports the format
|
|
34
|
+
* Playwright/Chromium emits: 8-bit, non-interlaced, colour-type 2/6.
|
|
35
|
+
*/
|
|
36
|
+
function decodePng(path) {
|
|
37
|
+
try {
|
|
38
|
+
const buf = readFileSync(path);
|
|
39
|
+
if (buf.length < 8 || buf.readUInt32BE(0) !== 0x89504e47)
|
|
40
|
+
return null; // PNG magic
|
|
41
|
+
let off = 8;
|
|
42
|
+
let width = 0;
|
|
43
|
+
let height = 0;
|
|
44
|
+
let bitDepth = 0;
|
|
45
|
+
let colorType = 0;
|
|
46
|
+
let interlace = 0;
|
|
47
|
+
const idat = [];
|
|
48
|
+
while (off + 8 <= buf.length) {
|
|
49
|
+
const len = buf.readUInt32BE(off);
|
|
50
|
+
const type = buf.toString('ascii', off + 4, off + 8);
|
|
51
|
+
const dataStart = off + 8;
|
|
52
|
+
if (type === 'IHDR') {
|
|
53
|
+
width = buf.readUInt32BE(dataStart);
|
|
54
|
+
height = buf.readUInt32BE(dataStart + 4);
|
|
55
|
+
bitDepth = buf[dataStart + 8];
|
|
56
|
+
colorType = buf[dataStart + 9];
|
|
57
|
+
interlace = buf[dataStart + 12];
|
|
58
|
+
}
|
|
59
|
+
else if (type === 'IDAT') {
|
|
60
|
+
idat.push(buf.subarray(dataStart, dataStart + len));
|
|
61
|
+
}
|
|
62
|
+
else if (type === 'IEND') {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
off = dataStart + len + 4; // skip data + CRC
|
|
66
|
+
}
|
|
67
|
+
if (!width || !height || bitDepth !== 8 || interlace !== 0)
|
|
68
|
+
return null;
|
|
69
|
+
const channels = colorType === 2 ? 3 : colorType === 6 ? 4 : 0;
|
|
70
|
+
if (!channels)
|
|
71
|
+
return null;
|
|
72
|
+
const raw = inflateSync(Buffer.concat(idat));
|
|
73
|
+
const stride = width * channels;
|
|
74
|
+
if (raw.length < (stride + 1) * height)
|
|
75
|
+
return null;
|
|
76
|
+
// Un-filter scanlines in place into an RGB(A) buffer.
|
|
77
|
+
const px = Buffer.alloc(stride * height);
|
|
78
|
+
let rp = 0;
|
|
79
|
+
for (let y = 0; y < height; y++) {
|
|
80
|
+
const filter = raw[rp++];
|
|
81
|
+
const rowStart = y * stride;
|
|
82
|
+
for (let x = 0; x < stride; x++) {
|
|
83
|
+
const rawByte = raw[rp++];
|
|
84
|
+
const a = x >= channels ? px[rowStart + x - channels] : 0; // left
|
|
85
|
+
const b = y > 0 ? px[rowStart - stride + x] : 0; // up
|
|
86
|
+
const c = x >= channels && y > 0 ? px[rowStart - stride + x - channels] : 0; // up-left
|
|
87
|
+
let val = rawByte;
|
|
88
|
+
if (filter === 1)
|
|
89
|
+
val = rawByte + a;
|
|
90
|
+
else if (filter === 2)
|
|
91
|
+
val = rawByte + b;
|
|
92
|
+
else if (filter === 3)
|
|
93
|
+
val = rawByte + ((a + b) >> 1);
|
|
94
|
+
else if (filter === 4) {
|
|
95
|
+
const p = a + b - c;
|
|
96
|
+
const pa = Math.abs(p - a);
|
|
97
|
+
const pb = Math.abs(p - b);
|
|
98
|
+
const pc = Math.abs(p - c);
|
|
99
|
+
val = rawByte + (pa <= pb && pa <= pc ? a : pb <= pc ? b : c);
|
|
100
|
+
}
|
|
101
|
+
px[rowStart + x] = val & 0xff;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { width, height, channels, stride, px };
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Average colour of image cell [x0,x1)×[y0,y1) as [r,g,b]. */
|
|
111
|
+
function cellAvg(img, x0, x1, y0, y1) {
|
|
112
|
+
let r = 0;
|
|
113
|
+
let g = 0;
|
|
114
|
+
let bl = 0;
|
|
115
|
+
let count = 0;
|
|
116
|
+
for (let y = y0; y < y1; y++) {
|
|
117
|
+
for (let x = x0; x < x1; x++) {
|
|
118
|
+
const i = y * img.stride + x * img.channels;
|
|
119
|
+
r += img.px[i];
|
|
120
|
+
g += img.px[i + 1];
|
|
121
|
+
bl += img.px[i + 2];
|
|
122
|
+
count++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
count = count || 1;
|
|
126
|
+
return [Math.round(r / count), Math.round(g / count), Math.round(bl / count)];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Decode a PNG into an N×N grid of average [r,g,b]. Returns null for any format
|
|
130
|
+
* we do not handle (never throws).
|
|
131
|
+
*/
|
|
132
|
+
export function pngToGrid(path, n = GRID) {
|
|
133
|
+
const img = decodePng(path);
|
|
134
|
+
if (!img)
|
|
135
|
+
return null;
|
|
136
|
+
const grid = [];
|
|
137
|
+
for (let gy = 0; gy < n; gy++) {
|
|
138
|
+
for (let gx = 0; gx < n; gx++) {
|
|
139
|
+
const x0 = Math.floor((gx * img.width) / n);
|
|
140
|
+
const x1 = Math.max(x0 + 1, Math.floor(((gx + 1) * img.width) / n));
|
|
141
|
+
const y0 = Math.floor((gy * img.height) / n);
|
|
142
|
+
const y1 = Math.max(y0 + 1, Math.floor(((gy + 1) * img.height) / n));
|
|
143
|
+
grid.push(cellAvg(img, x0, x1, y0, y1));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return grid;
|
|
147
|
+
}
|
|
148
|
+
/** Structural difference-hash resolution (produces DHASH_N×DHASH_N bits). */
|
|
149
|
+
const DHASH_N = 16;
|
|
150
|
+
/**
|
|
151
|
+
* Perceptual difference-hash (dHash) on luminance: compares each cell to its
|
|
152
|
+
* right neighbour, yielding a structural bit-map that is invariant to global
|
|
153
|
+
* brightness/colour shifts but sensitive to LAYOUT and edges — the thing an
|
|
154
|
+
* average-colour grid is blind to. Returns null for undecodable input.
|
|
155
|
+
*/
|
|
156
|
+
export function pngToDHash(path, n = DHASH_N) {
|
|
157
|
+
const img = decodePng(path);
|
|
158
|
+
if (!img)
|
|
159
|
+
return null;
|
|
160
|
+
// (n) rows × (n+1) columns of luminance, then compare horizontally.
|
|
161
|
+
const cols = n + 1;
|
|
162
|
+
const luma = [];
|
|
163
|
+
for (let gy = 0; gy < n; gy++) {
|
|
164
|
+
for (let gx = 0; gx < cols; gx++) {
|
|
165
|
+
const x0 = Math.floor((gx * img.width) / cols);
|
|
166
|
+
const x1 = Math.max(x0 + 1, Math.floor(((gx + 1) * img.width) / cols));
|
|
167
|
+
const y0 = Math.floor((gy * img.height) / n);
|
|
168
|
+
const y1 = Math.max(y0 + 1, Math.floor(((gy + 1) * img.height) / n));
|
|
169
|
+
const [r, g, b] = cellAvg(img, x0, x1, y0, y1);
|
|
170
|
+
luma.push(0.299 * r + 0.587 * g + 0.114 * b);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const bits = [];
|
|
174
|
+
for (let gy = 0; gy < n; gy++) {
|
|
175
|
+
for (let gx = 0; gx < n; gx++) {
|
|
176
|
+
const i = gy * cols + gx;
|
|
177
|
+
bits.push(luma[i] < luma[i + 1]); // brighter to the right?
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return bits;
|
|
181
|
+
}
|
|
182
|
+
/** Fraction of differing bits between two dHashes (0–1). */
|
|
183
|
+
export function hammingDrift(a, b) {
|
|
184
|
+
const n = Math.min(a.length, b.length);
|
|
185
|
+
if (n === 0)
|
|
186
|
+
return 0;
|
|
187
|
+
let diff = 0;
|
|
188
|
+
for (let i = 0; i < n; i++)
|
|
189
|
+
if (a[i] !== b[i])
|
|
190
|
+
diff++;
|
|
191
|
+
return diff / n;
|
|
192
|
+
}
|
|
193
|
+
/** Fraction of grid cells whose colour distance exceeds the tolerance (0–1). */
|
|
194
|
+
export function gridDrift(a, b) {
|
|
195
|
+
const n = Math.min(a.length, b.length);
|
|
196
|
+
if (n === 0)
|
|
197
|
+
return 0;
|
|
198
|
+
let changed = 0;
|
|
199
|
+
for (let i = 0; i < n; i++) {
|
|
200
|
+
const d = Math.abs(a[i][0] - b[i][0]) + Math.abs(a[i][1] - b[i][1]) + Math.abs(a[i][2] - b[i][2]);
|
|
201
|
+
if (d > CELL_TOLERANCE)
|
|
202
|
+
changed++;
|
|
203
|
+
}
|
|
204
|
+
return changed / n;
|
|
205
|
+
}
|
|
206
|
+
/** The latest screenshot per page (max one per `<page>` prefix) in `.uap/visual/`. */
|
|
207
|
+
export function latestScreenshots(projectRoot) {
|
|
208
|
+
const dir = visualDir(projectRoot);
|
|
209
|
+
if (!existsSync(dir))
|
|
210
|
+
return [];
|
|
211
|
+
const shots = readdirSync(dir).filter((f) => f.toLowerCase().endsWith('.png'));
|
|
212
|
+
// Names look like `<page>-t<i>.png`; keep the highest t per page.
|
|
213
|
+
const byPage = new Map();
|
|
214
|
+
for (const f of shots.sort()) {
|
|
215
|
+
const page = f.replace(/-t\d+\.png$/i, '');
|
|
216
|
+
byPage.set(page, f); // later (higher t) wins due to sort
|
|
217
|
+
}
|
|
218
|
+
return [...byPage.values()].map((f) => join(dir, f));
|
|
219
|
+
}
|
|
220
|
+
/** Copy each page's latest screenshot into the baseline dir (accept the look). */
|
|
221
|
+
export function approveVisualBaseline(projectRoot) {
|
|
222
|
+
const dir = baselineDir(projectRoot);
|
|
223
|
+
mkdirSync(dir, { recursive: true });
|
|
224
|
+
const approved = [];
|
|
225
|
+
for (const shot of latestScreenshots(projectRoot)) {
|
|
226
|
+
// Normalise `<page>-t<i>.png` → `<page>.png` so the baseline is stable across runs.
|
|
227
|
+
const name = basename(shot).replace(/-t\d+\.png$/i, '.png');
|
|
228
|
+
const dest = join(dir, name);
|
|
229
|
+
try {
|
|
230
|
+
copyFileSync(shot, dest);
|
|
231
|
+
approved.push(dest);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// best-effort per file
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return approved;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Compare the current run's latest screenshots against approved baselines.
|
|
241
|
+
* Returns one entry per current page. Fail-soft: undecodable pairs report
|
|
242
|
+
* hasBaseline=false so they never spuriously block.
|
|
243
|
+
*/
|
|
244
|
+
export function compareVisualBaseline(projectRoot, threshold = DEFAULT_DRIFT_THRESHOLD) {
|
|
245
|
+
const bDir = baselineDir(projectRoot);
|
|
246
|
+
const out = [];
|
|
247
|
+
for (const shot of latestScreenshots(projectRoot)) {
|
|
248
|
+
const name = basename(shot).replace(/-t\d+\.png$/i, '.png');
|
|
249
|
+
const basePath = join(bDir, name);
|
|
250
|
+
if (!existsSync(basePath)) {
|
|
251
|
+
out.push({ name, hasBaseline: false, drift: 0, drifted: false });
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const cur = pngToGrid(shot);
|
|
255
|
+
const base = pngToGrid(basePath);
|
|
256
|
+
if (!cur || !base) {
|
|
257
|
+
out.push({ name, hasBaseline: false, drift: 0, drifted: false });
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const colorDrift = gridDrift(cur, base);
|
|
261
|
+
// Structural component: dHash captures layout/edge changes that a same-
|
|
262
|
+
// average-colour render would hide. Overall drift is the STRICTER of the
|
|
263
|
+
// two, so either a colour shift or a structural change trips the gate.
|
|
264
|
+
const curHash = pngToDHash(shot);
|
|
265
|
+
const baseHash = pngToDHash(basePath);
|
|
266
|
+
const structuralDrift = curHash && baseHash ? hammingDrift(curHash, baseHash) : 0;
|
|
267
|
+
const drift = Math.max(colorDrift, structuralDrift);
|
|
268
|
+
out.push({ name, hasBaseline: true, drift, colorDrift, structuralDrift, drifted: drift > threshold });
|
|
269
|
+
}
|
|
270
|
+
return out;
|
|
271
|
+
}
|
|
272
|
+
/** Human-readable one-liner for a set of drifts (empty string when nothing to say). */
|
|
273
|
+
export function driftSummary(drifts) {
|
|
274
|
+
const compared = drifts.filter((d) => d.hasBaseline);
|
|
275
|
+
if (compared.length === 0)
|
|
276
|
+
return '';
|
|
277
|
+
const drifted = compared.filter((d) => d.drifted);
|
|
278
|
+
if (drifted.length === 0) {
|
|
279
|
+
return `visual baseline: ${compared.length} page(s) within tolerance`;
|
|
280
|
+
}
|
|
281
|
+
return (`VISUAL REGRESSION — ${drifted.length}/${compared.length} page(s) drifted from baseline:\n` +
|
|
282
|
+
drifted.map((d) => ` - ${d.name}: ${(d.drift * 100).toFixed(1)}% of cells changed`).join('\n') +
|
|
283
|
+
'\n (approve the new look with `uap verify --approve-visual` if intended)');
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=visual-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-baseline.js","sourceRoot":"","sources":["../../src/delivery/visual-baseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,7 +91,13 @@ export interface VisualTargets {
|
|
|
91
91
|
}>;
|
|
92
92
|
}
|
|
93
93
|
export declare function readVisualTargets(projectRoot: string): VisualTargets;
|
|
94
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* Entry pages to render. Root-level `.html` first (index first); if the project
|
|
96
|
+
* has none — the shape of a React/Vue/Svelte app that only produces HTML after a
|
|
97
|
+
* build — fall back to the built `index.html` under dist/build/out so framework
|
|
98
|
+
* UIs are covered, not silently skipped. The static server serves projectRoot,
|
|
99
|
+
* so a nested entry like `dist/index.html` navigates fine.
|
|
100
|
+
*/
|
|
95
101
|
export declare function discoverEntryPages(projectRoot: string): string[];
|
|
96
102
|
/** Fraction of grid cells that differ between two samples. */
|
|
97
103
|
export declare function motionBetween(a: string[] | undefined, b: string[] | undefined): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-gate.d.ts","sourceRoot":"","sources":["../../src/delivery/visual-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACxC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,SAAS,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,iGAAiG;IACjG,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,mBAAmB,CAAC;CAC5C;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5G;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CASpE;
|
|
1
|
+
{"version":3,"file":"visual-gate.d.ts","sourceRoot":"","sources":["../../src/delivery/visual-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -83,12 +83,29 @@ const PIXEL_PROBE = `(function () {
|
|
|
83
83
|
function delay(ms) {
|
|
84
84
|
return new Promise((r) => setTimeout(r, ms));
|
|
85
85
|
}
|
|
86
|
-
/**
|
|
86
|
+
/** Common build-output dirs a framework project renders into (served from root). */
|
|
87
|
+
const BUILD_OUTPUT_DIRS = ['dist', 'build', 'out'];
|
|
88
|
+
/**
|
|
89
|
+
* Entry pages to render. Root-level `.html` first (index first); if the project
|
|
90
|
+
* has none — the shape of a React/Vue/Svelte app that only produces HTML after a
|
|
91
|
+
* build — fall back to the built `index.html` under dist/build/out so framework
|
|
92
|
+
* UIs are covered, not silently skipped. The static server serves projectRoot,
|
|
93
|
+
* so a nested entry like `dist/index.html` navigates fine.
|
|
94
|
+
*/
|
|
87
95
|
export function discoverEntryPages(projectRoot) {
|
|
88
96
|
try {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
const root = readdirSync(projectRoot).filter((f) => f.toLowerCase().endsWith('.html'));
|
|
98
|
+
if (root.length > 0) {
|
|
99
|
+
root.sort((a, b) => (a === 'index.html' ? -1 : b === 'index.html' ? 1 : a.localeCompare(b)));
|
|
100
|
+
return root.slice(0, MAX_PAGES);
|
|
101
|
+
}
|
|
102
|
+
// Framework fallback: a freshly built entry under a common output dir.
|
|
103
|
+
for (const d of BUILD_OUTPUT_DIRS) {
|
|
104
|
+
const entry = join(d, 'index.html');
|
|
105
|
+
if (existsSync(join(projectRoot, entry)))
|
|
106
|
+
return [entry];
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
92
109
|
}
|
|
93
110
|
catch {
|
|
94
111
|
return [];
|
|
@@ -207,7 +224,10 @@ export async function runVisualGate(projectRoot, options = {}) {
|
|
|
207
224
|
catch {
|
|
208
225
|
probes.push({ canvas: false });
|
|
209
226
|
}
|
|
210
|
-
|
|
227
|
+
// Flatten nested entry paths (dist/index.html) into a single
|
|
228
|
+
// screenshot-safe basename so no missing subdir defeats the write.
|
|
229
|
+
const shotBase = file.replace(/\.html$/i, '').replace(/[/\\]+/g, '_');
|
|
230
|
+
const shot = join(screenshotDir, `${shotBase}-t${i}.png`);
|
|
211
231
|
try {
|
|
212
232
|
await browser.screenshot(shot);
|
|
213
233
|
shots.push(shot);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-gate.js","sourceRoot":"","sources":["../../src/delivery/visual-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAoExD,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC;QAC9D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAkB,CAAC;QACxE,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG,EAAE,CAAC;AAChB,MAAM,eAAe,GAAG,CAAC,CAAC;AAC1B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,iFAAiF;AACjF,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,0EAA0E;AAC1E,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,+EAA+E;AAC/E,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B;;+EAE+E;AAC/E,MAAM,WAAW,GAAG;;;;;;;;;;YAUR,IAAI;;;;;;;;;;;;;;;;;;GAkBb,CAAC;AAUJ,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"visual-gate.js","sourceRoot":"","sources":["../../src/delivery/visual-gate.ts"],"names":[],"mappings":"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"}
|