foundry-design 0.2.0-beta.22 → 0.2.0-beta.23
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/README.md +6 -4
- package/dist/delivery-capture.d.ts +8 -0
- package/dist/delivery-capture.d.ts.map +1 -0
- package/dist/delivery-capture.js +234 -0
- package/dist/delivery-capture.js.map +1 -0
- package/dist/delivery-export.d.ts +3 -1
- package/dist/delivery-export.d.ts.map +1 -1
- package/dist/delivery-export.js +172 -8
- package/dist/delivery-export.js.map +1 -1
- package/dist/doctor.d.ts +8 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +110 -13
- package/dist/doctor.js.map +1 -1
- package/dist/index.js +51 -27
- package/dist/index.js.map +1 -1
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +9 -0
- package/dist/indexer.js.map +1 -1
- package/dist/installer.d.ts +2 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +2 -1
- package/dist/installer.js.map +1 -1
- package/dist/release.d.ts +3 -3
- package/dist/release.js +1 -1
- package/dist/session-resume.d.ts +16 -0
- package/dist/session-resume.d.ts.map +1 -0
- package/dist/session-resume.js +30 -0
- package/dist/session-resume.js.map +1 -0
- package/dist/source-anchor.d.ts +8 -0
- package/dist/source-anchor.d.ts.map +1 -0
- package/dist/source-anchor.js +40 -0
- package/dist/source-anchor.js.map +1 -0
- package/dist/visual-check-capture.d.ts +8 -0
- package/dist/visual-check-capture.d.ts.map +1 -0
- package/dist/visual-check-capture.js +331 -0
- package/dist/visual-check-capture.js.map +1 -0
- package/dist/visual-check.d.ts +10 -0
- package/dist/visual-check.d.ts.map +1 -0
- package/dist/visual-check.js +411 -0
- package/dist/visual-check.js.map +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { access, copyFile, lstat, mkdir, readFile, readdir, rename, rmdir, writeFile, } from 'node:fs/promises';
|
|
3
|
+
import { constants } from 'node:fs';
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
5
|
+
import { chromium } from 'playwright';
|
|
6
|
+
import sharp from 'sharp';
|
|
7
|
+
import { visualCaptureSchema, visualCheckReportSchema, visualScreenSchema, } from 'foundry-design-protocol';
|
|
8
|
+
import { captureVisualScreen, screenConfigurationHash, UnsupportedVisualContextError, validateVisualUrl, } from './visual-check-capture.js';
|
|
9
|
+
const identifier = /^[a-z0-9][a-z0-9_-]{0,79}$/i;
|
|
10
|
+
const hash = (content) => createHash('sha256').update(content).digest('hex');
|
|
11
|
+
const exists = (path) => access(path).then(() => true, () => false);
|
|
12
|
+
const rootFor = (projectRoot) => resolve(projectRoot, '.foundry/visual-checks');
|
|
13
|
+
const safeId = (id) => {
|
|
14
|
+
if (!identifier.test(id))
|
|
15
|
+
throw new Error('Invalid visual-check identifier.');
|
|
16
|
+
return id;
|
|
17
|
+
};
|
|
18
|
+
async function safePath(root, child) {
|
|
19
|
+
const target = resolve(root, child);
|
|
20
|
+
const path = relative(root, target);
|
|
21
|
+
if (!path || path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path))
|
|
22
|
+
throw new Error('Visual-check artifact path escapes its managed directory.');
|
|
23
|
+
let current = root;
|
|
24
|
+
const parents = [
|
|
25
|
+
root,
|
|
26
|
+
...path.split(sep).map((part) => {
|
|
27
|
+
current = join(current, part);
|
|
28
|
+
return current;
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
31
|
+
// Also reject .foundry as a symlink, so managed writes never leave the project.
|
|
32
|
+
parents.unshift(dirname(root));
|
|
33
|
+
for (const part of parents) {
|
|
34
|
+
try {
|
|
35
|
+
if ((await lstat(part)).isSymbolicLink())
|
|
36
|
+
throw new Error('Visual checks refuse symbolic-link storage paths.');
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error.code !== 'ENOENT')
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return target;
|
|
44
|
+
}
|
|
45
|
+
async function configuration(root) {
|
|
46
|
+
const path = await safePath(root, 'screens.json');
|
|
47
|
+
if (!(await exists(path)))
|
|
48
|
+
return { version: 1, screens: [], baselines: {} };
|
|
49
|
+
const input = JSON.parse(await readFile(path, 'utf8'));
|
|
50
|
+
if (input.version !== 1 ||
|
|
51
|
+
!Array.isArray(input.screens) ||
|
|
52
|
+
!input.baselines ||
|
|
53
|
+
typeof input.baselines !== 'object')
|
|
54
|
+
throw new Error('Unsupported visual-check configuration.');
|
|
55
|
+
const screens = input.screens.map((screen) => visualScreenSchema.parse(screen));
|
|
56
|
+
if (new Set(screens.map((screen) => screen.name)).size !== screens.length)
|
|
57
|
+
throw new Error('Duplicate registered screen names.');
|
|
58
|
+
const baselines = Object.fromEntries(Object.entries(input.baselines).map(([name, value]) => [safeId(name), safeId(String(value))]));
|
|
59
|
+
return { version: 1, screens, baselines };
|
|
60
|
+
}
|
|
61
|
+
async function saveConfiguration(root, config) {
|
|
62
|
+
const path = await safePath(root, 'screens.json');
|
|
63
|
+
const temp = await safePath(root, `screens-${randomUUID()}.tmp`);
|
|
64
|
+
await writeFile(temp, `${JSON.stringify(config, null, 2)}\n`, { flag: 'wx' });
|
|
65
|
+
await rename(temp, path);
|
|
66
|
+
}
|
|
67
|
+
async function withLock(root, work) {
|
|
68
|
+
const lock = await safePath(root, 'operation.lock');
|
|
69
|
+
await mkdir(root, { recursive: true });
|
|
70
|
+
try {
|
|
71
|
+
await mkdir(lock);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (error.code === 'EEXIST')
|
|
75
|
+
throw new Error('Another visual-check operation is running. If a process was interrupted, remove .foundry/visual-checks/operation.lock after confirming it has stopped.');
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
return await work();
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
await rmdir(lock);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function registerVisualScreen(projectRoot, input) {
|
|
86
|
+
const screen = visualScreenSchema.parse(input);
|
|
87
|
+
validateVisualUrl(screen.url);
|
|
88
|
+
const root = rootFor(projectRoot);
|
|
89
|
+
return withLock(root, async () => {
|
|
90
|
+
const config = await configuration(root);
|
|
91
|
+
const previous = config.screens.find((item) => item.name === screen.name);
|
|
92
|
+
config.screens = [...config.screens.filter((item) => item.name !== screen.name), screen];
|
|
93
|
+
// Keep immutable baseline evidence. Changed config needs a fresh explicit approval.
|
|
94
|
+
if (previous && screenConfigurationHash(previous) !== screenConfigurationHash(screen))
|
|
95
|
+
delete config.baselines[screen.name];
|
|
96
|
+
await saveConfiguration(root, config);
|
|
97
|
+
return screen;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
export function visualCheckExitCode(results) {
|
|
101
|
+
if (!results.length ||
|
|
102
|
+
results.some((result) => ['failed', 'unsupported'].includes(result.status)))
|
|
103
|
+
return 2;
|
|
104
|
+
if (results.some((result) => result.status === 'different'))
|
|
105
|
+
return 1;
|
|
106
|
+
if (results.some((result) => result.status === 'unbaselined'))
|
|
107
|
+
return 3;
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
function findingKey(finding) {
|
|
111
|
+
return `${finding.kind}:${finding.selector}`;
|
|
112
|
+
}
|
|
113
|
+
export async function compareVisualCaptures(baseline, current, baselineImage, currentImage, diffImage) {
|
|
114
|
+
const empty = { geometryChanges: [], newFindings: [] };
|
|
115
|
+
if (baseline.configurationHash !== screenConfigurationHash(baseline.screen) ||
|
|
116
|
+
current.configurationHash !== screenConfigurationHash(current.screen))
|
|
117
|
+
throw new Error('Recorded capture configuration was modified after capture.');
|
|
118
|
+
if (baseline.configurationHash !== current.configurationHash)
|
|
119
|
+
return {
|
|
120
|
+
status: 'unsupported',
|
|
121
|
+
reason: 'Capture configuration differs from the approved baseline. Capture and approve the new context explicitly.',
|
|
122
|
+
...empty,
|
|
123
|
+
};
|
|
124
|
+
if (baseline.browser !== current.browser || baseline.platform !== current.platform)
|
|
125
|
+
return {
|
|
126
|
+
status: 'unsupported',
|
|
127
|
+
reason: 'Browser version or operating system differs from the baseline. Use the same capture environment or explicitly approve a baseline here.',
|
|
128
|
+
...empty,
|
|
129
|
+
};
|
|
130
|
+
const [before, after] = await Promise.all([readFile(baselineImage), readFile(currentImage)]);
|
|
131
|
+
if (hash(before) !== baseline.screenshotHash || hash(after) !== current.screenshotHash)
|
|
132
|
+
throw new Error('Screenshot hash differs from the recorded capture. Evidence may have been modified.');
|
|
133
|
+
const [a, b] = await Promise.all([
|
|
134
|
+
sharp(before).ensureAlpha().raw().toBuffer({ resolveWithObject: true }),
|
|
135
|
+
sharp(after).ensureAlpha().raw().toBuffer({ resolveWithObject: true }),
|
|
136
|
+
]);
|
|
137
|
+
if (a.info.width !== b.info.width || a.info.height !== b.info.height)
|
|
138
|
+
return {
|
|
139
|
+
status: 'unsupported',
|
|
140
|
+
reason: 'Screenshot dimensions do not match the approved context.',
|
|
141
|
+
...empty,
|
|
142
|
+
};
|
|
143
|
+
const diff = Buffer.alloc(b.data.length);
|
|
144
|
+
let changedPixels = 0;
|
|
145
|
+
for (let offset = 0; offset < b.data.length; offset += 4) {
|
|
146
|
+
const changed = [0, 1, 2, 3].some((channel) => Math.abs(a.data[offset + channel] - b.data[offset + channel]) >
|
|
147
|
+
current.screen.pixelThreshold);
|
|
148
|
+
if (changed)
|
|
149
|
+
changedPixels++;
|
|
150
|
+
diff[offset] = changed ? 255 : Math.round(b.data[offset] * 0.25 + 190);
|
|
151
|
+
diff[offset + 1] = changed ? 64 : Math.round(b.data[offset + 1] * 0.25 + 190);
|
|
152
|
+
diff[offset + 2] = changed ? 112 : Math.round(b.data[offset + 2] * 0.25 + 190);
|
|
153
|
+
diff[offset + 3] = 255;
|
|
154
|
+
}
|
|
155
|
+
await sharp(diff, { raw: { width: b.info.width, height: b.info.height, channels: 4 } })
|
|
156
|
+
.png()
|
|
157
|
+
.toFile(diffImage);
|
|
158
|
+
const oldGeometry = new Map(baseline.geometry.map((item) => [item.selector, item]));
|
|
159
|
+
const geometryChanges = [];
|
|
160
|
+
for (const item of current.geometry) {
|
|
161
|
+
const old = oldGeometry.get(item.selector);
|
|
162
|
+
if (!old)
|
|
163
|
+
geometryChanges.push({
|
|
164
|
+
selector: item.selector,
|
|
165
|
+
description: 'Element appeared in measured geometry.',
|
|
166
|
+
});
|
|
167
|
+
else {
|
|
168
|
+
const properties = ['x', 'y', 'width', 'height'].filter((key) => Math.abs(item[key] - old[key]) > current.screen.geometryTolerance);
|
|
169
|
+
if (properties.length)
|
|
170
|
+
geometryChanges.push({
|
|
171
|
+
selector: item.selector,
|
|
172
|
+
description: properties.map((key) => `${key}: ${old[key]} → ${item[key]}px`).join('; '),
|
|
173
|
+
});
|
|
174
|
+
oldGeometry.delete(item.selector);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const selector of oldGeometry.keys())
|
|
178
|
+
geometryChanges.push({ selector, description: 'Element disappeared from measured geometry.' });
|
|
179
|
+
const oldFindings = new Set(baseline.findings.map(findingKey));
|
|
180
|
+
const newFindings = current.findings.filter((finding) => !oldFindings.has(findingKey(finding)));
|
|
181
|
+
const totalPixels = b.info.width * b.info.height;
|
|
182
|
+
const changedRatio = changedPixels / totalPixels;
|
|
183
|
+
const different = changedRatio > current.screen.changedPixelRatio ||
|
|
184
|
+
geometryChanges.length > 0 ||
|
|
185
|
+
newFindings.length > 0;
|
|
186
|
+
return {
|
|
187
|
+
status: different ? 'different' : 'passed',
|
|
188
|
+
changedPixels,
|
|
189
|
+
totalPixels,
|
|
190
|
+
changedRatio,
|
|
191
|
+
geometryChanges,
|
|
192
|
+
newFindings,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function escapeHtml(value) {
|
|
196
|
+
return value.replace(/[&<>"']/g, (character) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[character]);
|
|
197
|
+
}
|
|
198
|
+
export function renderVisualCheckHtml(report) {
|
|
199
|
+
const esc = escapeHtml;
|
|
200
|
+
const image = (path, label) => path
|
|
201
|
+
? `<figure><figcaption>${label}</figcaption><img alt="${label}" src="../../${esc(path)}"></figure>`
|
|
202
|
+
: '';
|
|
203
|
+
return `<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Foundry visual check ${esc(report.id)}</title><style>body{font:16px/1.5 system-ui,sans-serif;margin:0;background:#f4f4f5;color:#171719}main{max-width:1440px;margin:auto;padding:32px}h1{font-size:28px}section{background:white;border:1px solid #ddd;border-radius:8px;padding:24px;margin:24px 0}.images{display:flex;gap:16px;flex-wrap:wrap}figure{margin:0;flex:1;min-width:260px}img{width:100%;border:1px solid #ddd}code{overflow-wrap:anywhere}li{margin:8px 0}.status{font-weight:600}small{color:#626267}</style><main><h1>Foundry visual checks</h1><p>${esc(report.createdAt)} · ${esc(report.id)}</p><p>Differences are evidence to review, not an automatic judgment of design quality. Baselines change only through explicit approval.</p>${report.results.map((result) => `<section><h2>${esc(result.name)} <span class="status">· ${result.status}</span></h2>${result.reason ? `<p>${esc(result.reason)}</p>` : ''}${result.capture ? `<small>${result.capture.screen.viewport.width} × ${result.capture.screen.viewport.height} · ${esc(result.capture.screen.theme)} · ${esc(result.capture.screen.state)} · Browser ${esc(result.capture.browser)} · ${esc(result.capture.platform)} · Revision ${esc(result.capture.sourceRevision || 'unavailable')}${result.capture.sourceDirty ? ' (uncommitted source changes)' : ''}</small>` : ''}${result.changedRatio !== undefined ? `<p>${(result.changedRatio * 100).toFixed(3)}% changed pixels · ${result.geometryChanges.length} geometry changes · ${result.newFindings.length} new findings</p>` : ''}<div class="images">${image(result.baselineScreenshot, 'Approved baseline')}${image(result.capture?.screenshot, 'Current capture')}${image(result.diffScreenshot, 'Pixel differences')}</div><ul>${result.geometryChanges.map((item) => `<li><code>${esc(item.selector)}</code>: ${esc(item.description)}</li>`).join('')}${result.newFindings.map((item) => `<li><code>${esc(item.selector)}</code>: ${esc(item.message)}</li>`).join('')}</ul>${result.capture ? `<details><summary>Capture evidence and existing findings</summary><ul>${result.capture.evidence.map((item) => `<li>${esc(item)}</li>`).join('')}${result.capture.findings.map((item) => `<li><code>${esc(item.selector)}</code>: ${esc(item.message)}</li>`).join('')}</ul></details>` : ''}</section>`).join('')}</main></html>`;
|
|
204
|
+
}
|
|
205
|
+
export async function runVisualChecks(projectRoot, name) {
|
|
206
|
+
const root = rootFor(projectRoot);
|
|
207
|
+
return withLock(root, async () => {
|
|
208
|
+
const config = await configuration(root);
|
|
209
|
+
const screens = name
|
|
210
|
+
? config.screens.filter((screen) => screen.name === safeId(name))
|
|
211
|
+
: config.screens;
|
|
212
|
+
if (!screens.length)
|
|
213
|
+
throw new Error('No matching screen is registered. Run visual-check register first.');
|
|
214
|
+
const id = `check_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
215
|
+
const runRoot = await safePath(root, `runs/${id}`);
|
|
216
|
+
await mkdir(runRoot, { recursive: true });
|
|
217
|
+
const results = [];
|
|
218
|
+
let browser;
|
|
219
|
+
try {
|
|
220
|
+
browser = await chromium.launch({ headless: true });
|
|
221
|
+
for (const screen of screens) {
|
|
222
|
+
try {
|
|
223
|
+
const imagePath = await safePath(root, `runs/${id}/${screen.name}.png`);
|
|
224
|
+
const capture = await captureVisualScreen(browser, screen, projectRoot, imagePath);
|
|
225
|
+
capture.screenshot = relative(root, imagePath).split(sep).join('/');
|
|
226
|
+
const baselineId = config.baselines[screen.name];
|
|
227
|
+
if (!baselineId) {
|
|
228
|
+
results.push({
|
|
229
|
+
name: screen.name,
|
|
230
|
+
status: 'unbaselined',
|
|
231
|
+
capture,
|
|
232
|
+
reason: 'No approved baseline. Review this capture, then approve this run explicitly.',
|
|
233
|
+
geometryChanges: [],
|
|
234
|
+
newFindings: [],
|
|
235
|
+
});
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const baseline = visualCaptureSchema.parse(JSON.parse(await readFile(await safePath(root, `baselines/${safeId(baselineId)}/capture.json`), 'utf8')));
|
|
239
|
+
const baselineImage = await safePath(root, baseline.screenshot);
|
|
240
|
+
const diff = await safePath(root, `runs/${id}/${screen.name}-diff.png`);
|
|
241
|
+
const comparison = await compareVisualCaptures(baseline, capture, baselineImage, imagePath, diff);
|
|
242
|
+
results.push({
|
|
243
|
+
name: screen.name,
|
|
244
|
+
capture,
|
|
245
|
+
baselineId,
|
|
246
|
+
baselineScreenshot: baseline.screenshot,
|
|
247
|
+
...comparison,
|
|
248
|
+
...((await exists(diff))
|
|
249
|
+
? { diffScreenshot: relative(root, diff).split(sep).join('/') }
|
|
250
|
+
: {}),
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
results.push({
|
|
255
|
+
name: screen.name,
|
|
256
|
+
status: error instanceof UnsupportedVisualContextError ? 'unsupported' : 'failed',
|
|
257
|
+
reason: String(error.message),
|
|
258
|
+
geometryChanges: [],
|
|
259
|
+
newFindings: [],
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
for (const screen of screens)
|
|
266
|
+
results.push({
|
|
267
|
+
name: screen.name,
|
|
268
|
+
status: 'failed',
|
|
269
|
+
reason: `Browser could not start. Install Chromium explicitly with “npx playwright install chromium”. ${String(error.message)}`,
|
|
270
|
+
geometryChanges: [],
|
|
271
|
+
newFindings: [],
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
finally {
|
|
275
|
+
await browser?.close();
|
|
276
|
+
}
|
|
277
|
+
const report = {
|
|
278
|
+
format: 'foundry.visual-check',
|
|
279
|
+
version: 1,
|
|
280
|
+
id,
|
|
281
|
+
createdAt: new Date().toISOString(),
|
|
282
|
+
results,
|
|
283
|
+
exitCode: visualCheckExitCode(results),
|
|
284
|
+
};
|
|
285
|
+
await writeFile(join(runRoot, 'report.html'), renderVisualCheckHtml(report), { flag: 'wx' });
|
|
286
|
+
await writeFile(join(runRoot, 'report.tmp'), `${JSON.stringify(report, null, 2)}\n`, {
|
|
287
|
+
flag: 'wx',
|
|
288
|
+
});
|
|
289
|
+
await rename(join(runRoot, 'report.tmp'), join(runRoot, 'report.json'));
|
|
290
|
+
return report;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
export async function approveVisualBaseline(projectRoot, runId, name) {
|
|
294
|
+
const root = rootFor(projectRoot);
|
|
295
|
+
return withLock(root, async () => {
|
|
296
|
+
const report = visualCheckReportSchema.parse(JSON.parse(await readFile(await safePath(root, `runs/${safeId(runId)}/report.json`), 'utf8')));
|
|
297
|
+
if (report.id !== runId)
|
|
298
|
+
throw new Error('Report identity does not match the requested run.');
|
|
299
|
+
const result = report.results.find((item) => item.name === safeId(name));
|
|
300
|
+
if (!result?.capture || ['failed', 'unsupported'].includes(result.status))
|
|
301
|
+
throw new Error('Only a successful, supported capture can become a baseline.');
|
|
302
|
+
const config = await configuration(root);
|
|
303
|
+
const screen = config.screens.find((item) => item.name === name);
|
|
304
|
+
if (!screen ||
|
|
305
|
+
result.capture.screen.name !== name ||
|
|
306
|
+
screenConfigurationHash(screen) !== result.capture.configurationHash ||
|
|
307
|
+
result.capture.configurationHash !== screenConfigurationHash(result.capture.screen))
|
|
308
|
+
throw new Error('Screen configuration has changed since capture. Run a new check before approval.');
|
|
309
|
+
const source = await safePath(root, result.capture.screenshot);
|
|
310
|
+
if (hash(await readFile(source)) !== result.capture.screenshotHash)
|
|
311
|
+
throw new Error('Capture image was modified after the run. Baseline approval refused.');
|
|
312
|
+
const id = `baseline_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
313
|
+
const destination = await safePath(root, `baselines/${id}`);
|
|
314
|
+
await mkdir(destination, { recursive: true });
|
|
315
|
+
await copyFile(source, join(destination, 'capture.png'), constants.COPYFILE_EXCL);
|
|
316
|
+
await writeFile(join(destination, 'capture.json'), `${JSON.stringify({ ...result.capture, screenshot: `baselines/${id}/capture.png` }, null, 2)}\n`, { flag: 'wx' });
|
|
317
|
+
await writeFile(join(destination, 'approval.json'), `${JSON.stringify({ version: 1, runId, name, approvedAt: new Date().toISOString(), method: 'explicit-cli-approval' }, null, 2)}\n`, { flag: 'wx' });
|
|
318
|
+
config.baselines[name] = id;
|
|
319
|
+
await saveConfiguration(root, config);
|
|
320
|
+
return id;
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
export async function listVisualCheckReports(projectRoot) {
|
|
324
|
+
const root = rootFor(projectRoot);
|
|
325
|
+
const runs = await safePath(root, 'runs');
|
|
326
|
+
if (!(await exists(runs)))
|
|
327
|
+
return [];
|
|
328
|
+
const ids = (await readdir(runs))
|
|
329
|
+
.filter((id) => identifier.test(id))
|
|
330
|
+
.sort()
|
|
331
|
+
.reverse()
|
|
332
|
+
.slice(0, 20);
|
|
333
|
+
const reports = [];
|
|
334
|
+
for (const id of ids) {
|
|
335
|
+
const file = await safePath(root, `runs/${id}/report.json`);
|
|
336
|
+
if (!(await exists(file)))
|
|
337
|
+
continue; // A running check has not committed a report yet.
|
|
338
|
+
const report = visualCheckReportSchema.parse(JSON.parse(await readFile(file, 'utf8')));
|
|
339
|
+
if (report.id !== id)
|
|
340
|
+
throw new Error('Visual-check report identity does not match its directory.');
|
|
341
|
+
reports.push(report);
|
|
342
|
+
}
|
|
343
|
+
return reports;
|
|
344
|
+
}
|
|
345
|
+
export async function runVisualCheckCli(args, projectRoot) {
|
|
346
|
+
const option = (name) => {
|
|
347
|
+
const index = args.indexOf(name);
|
|
348
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
349
|
+
};
|
|
350
|
+
const repeated = (name) => args.flatMap((item, index) => (item === name && args[index + 1] ? [args[index + 1]] : []));
|
|
351
|
+
const required = (name) => {
|
|
352
|
+
const value = option(name);
|
|
353
|
+
if (!value || value.startsWith('--'))
|
|
354
|
+
throw new Error(`${name} is required.`);
|
|
355
|
+
return value;
|
|
356
|
+
};
|
|
357
|
+
const print = (value, message) => console.log(args.includes('--json') ? JSON.stringify(value, null, 2) : message);
|
|
358
|
+
try {
|
|
359
|
+
if (args[0] === 'register') {
|
|
360
|
+
const hook = (axis, value) => option(`--${axis}-attribute`)
|
|
361
|
+
? {
|
|
362
|
+
selector: option(`--${axis}-selector`) ?? 'html',
|
|
363
|
+
attribute: required(`--${axis}-attribute`),
|
|
364
|
+
value,
|
|
365
|
+
}
|
|
366
|
+
: undefined;
|
|
367
|
+
const theme = option('--theme') ?? 'current';
|
|
368
|
+
const state = option('--state') ?? 'current';
|
|
369
|
+
const screen = await registerVisualScreen(projectRoot, {
|
|
370
|
+
version: 1,
|
|
371
|
+
name: required('--name'),
|
|
372
|
+
url: required('--url'),
|
|
373
|
+
viewport: {
|
|
374
|
+
width: Number(option('--width') ?? 1440),
|
|
375
|
+
height: Number(option('--height') ?? 900),
|
|
376
|
+
},
|
|
377
|
+
theme,
|
|
378
|
+
state,
|
|
379
|
+
themeHook: hook('theme', theme),
|
|
380
|
+
stateHook: hook('state', state),
|
|
381
|
+
masks: repeated('--mask'),
|
|
382
|
+
targets: repeated('--target'),
|
|
383
|
+
});
|
|
384
|
+
print(screen, `Registered ${screen.name}. Run visual-check run, review the report, then approve a baseline explicitly.`);
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
if (args[0] === 'run') {
|
|
388
|
+
const report = await runVisualChecks(projectRoot, option('--name'));
|
|
389
|
+
print(report, `${report.results.map((result) => `${result.name}: ${result.status}${result.reason ? ` — ${result.reason}` : ''}`).join('\n')}\nReport: ${join(rootFor(projectRoot), 'runs', report.id, 'report.html')}`);
|
|
390
|
+
return report.exitCode;
|
|
391
|
+
}
|
|
392
|
+
if (args[0] === 'approve') {
|
|
393
|
+
const id = await approveVisualBaseline(projectRoot, required('--run'), required('--name'));
|
|
394
|
+
print({ baselineId: id }, `Approved ${id}. Prior baseline evidence has been retained.`);
|
|
395
|
+
return 0;
|
|
396
|
+
}
|
|
397
|
+
if (args[0] === 'list') {
|
|
398
|
+
const config = await configuration(rootFor(projectRoot));
|
|
399
|
+
print(config, config.screens
|
|
400
|
+
.map((screen) => `${screen.name}: ${screen.viewport.width}×${screen.viewport.height} ${screen.theme}/${screen.state} — ${config.baselines[screen.name] ? 'baseline approved' : 'needs baseline'}`)
|
|
401
|
+
.join('\n') || 'No registered screens.');
|
|
402
|
+
return 0;
|
|
403
|
+
}
|
|
404
|
+
throw new Error('Use visual-check register, run, approve or list.');
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
print({ error: String(error.message), exitCode: 2 }, `Visual check: ${String(error.message)}`);
|
|
408
|
+
return 2;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=visual-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-check.js","sourceRoot":"","sources":["../src/visual-check.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foundry-design",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.23",
|
|
4
4
|
"description": "Install and run the local-first Foundry visual design control plane",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"foundry-design": "dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"engines": {
|
|
15
|
-
"node": ">=20"
|
|
15
|
+
"node": ">=20.9.0"
|
|
16
16
|
},
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"homepage": "https://github.com/seanx24x/foundry-design-control#readme",
|
|
@@ -34,8 +34,10 @@
|
|
|
34
34
|
"inspector"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"foundry-design-protocol": "0.2.0-beta.
|
|
38
|
-
"foundry-design-runtime": "0.2.0-beta.
|
|
37
|
+
"foundry-design-protocol": "0.2.0-beta.23",
|
|
38
|
+
"foundry-design-runtime": "0.2.0-beta.23",
|
|
39
|
+
"playwright": "1.62.1",
|
|
40
|
+
"sharp": "0.35.4"
|
|
39
41
|
},
|
|
40
42
|
"scripts": {
|
|
41
43
|
"build": "tsc -p tsconfig.json && node ../../scripts/copy-cli-skill.mjs",
|