openspec-playwright 0.3.14 → 0.3.16

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.
@@ -461,9 +461,9 @@ If Ollama with a vision model is available, analyze screenshots for layout anoma
461
461
 
462
462
  If Vision Check shows `⚠ disabled` or `⚠ not reachable` → skip this step entirely. Vision Check is optional and should not block exploration.
463
463
 
464
- **Configuration** (in order of priority):
465
- 1. Environment variables: `OLLAMA_URL`, `OLLAMA_VISION_MODEL`
466
- 2. `tests/playwright/app-knowledge.md` **Vision Check Config** section
464
+ **Configuration**:
465
+ - `.env` file in `tests/playwright/` (highest priority): `OLLAMA_URL`, `OLLAMA_VISION_MODEL`, `OLLAMA_VISION_ENABLED`
466
+ - Environment variables: `OLLAMA_URL`, `OLLAMA_VISION_MODEL`
467
467
 
468
468
  If no configuration is found, vision check is disabled.
469
469
 
package/README.md CHANGED
@@ -40,6 +40,7 @@ openspec-pw audit # Audit tests for orphaned specs and issues
40
40
  openspec-pw migrate # Migrate old test files to new structure
41
41
  openspec-pw explore # Explore routes in parallel with Playwright
42
42
  openspec-pw vision-check # Analyze screenshots for layout anomalies (Ollama VLM)
43
+ # Supports: multi-viewport, baseline diff, HTML report
43
44
  openspec-pw uninstall # Remove integration from the project
44
45
  ```
45
46
 
package/bin/openspec-pw CHANGED
@@ -2,6 +2,7 @@
2
2
  # Resolve symlinks to find real script location, then go up to package root
3
3
  REAL="$(readlink -f "$0" 2>/dev/null || echo "$0")"
4
4
  DIR="$(cd "$(dirname "$REAL")/.." && pwd)"
5
- # cd to the script's directory so Node's module resolution starts from global node_modules,
6
- # not from the caller's working directory (which may have a local node_modules shadowing it)
7
- cd "$DIR" && node dist/index.js "$@"
5
+ # Save caller's CWD before cd so init/git get the correct working directory
6
+ ORIG_CWD="$(pwd)"
7
+ cd "$DIR" && OPENSPE_PW_CWD="$ORIG_CWD" node dist/index.js "$@"
8
+ cd "$ORIG_CWD"
@@ -1,9 +1,12 @@
1
1
  /**
2
2
  * Vision check command: Analyze screenshots for layout anomalies using Ollama VLM.
3
3
  *
4
- * Usage:
5
- * openspec-pw vision-check --screenshots "__screenshots__/*.png"
6
- * openspec-pw vision-check --screenshots "shot1.png,shot2.png" --parallel 2
4
+ * Modes:
5
+ * --screenshots "..." Analyze existing files (single mode)
6
+ * --url ... --viewport ... Capture from URL at multiple viewports
7
+ * --baseline Save as baseline (with --screenshots or --url+viewport)
8
+ * --diff Compare against baseline
9
+ * --report <path> Generate HTML report
7
10
  *
8
11
  * Exit codes:
9
12
  * 0 = Check completed (with or without anomalies)
@@ -18,6 +21,11 @@ export interface VisionCheckOptions {
18
21
  dryRun?: boolean;
19
22
  severity?: string;
20
23
  json?: boolean;
24
+ viewport?: string;
25
+ url?: string;
26
+ baseline?: boolean;
27
+ diff?: boolean;
28
+ report?: string;
21
29
  }
22
30
  /**
23
31
  * Main vision check command.
@@ -1,20 +1,24 @@
1
1
  /**
2
2
  * Vision check command: Analyze screenshots for layout anomalies using Ollama VLM.
3
3
  *
4
- * Usage:
5
- * openspec-pw vision-check --screenshots "__screenshots__/*.png"
6
- * openspec-pw vision-check --screenshots "shot1.png,shot2.png" --parallel 2
4
+ * Modes:
5
+ * --screenshots "..." Analyze existing files (single mode)
6
+ * --url ... --viewport ... Capture from URL at multiple viewports
7
+ * --baseline Save as baseline (with --screenshots or --url+viewport)
8
+ * --diff Compare against baseline
9
+ * --report <path> Generate HTML report
7
10
  *
8
11
  * Exit codes:
9
12
  * 0 = Check completed (with or without anomalies)
10
13
  * 1 = Ollama not available (skipped)
11
14
  * 2 = Configuration missing or invalid (skipped)
12
15
  */
13
- import { existsSync, readFileSync, writeFileSync } from "fs";
16
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
14
17
  import { join, basename } from "path";
15
18
  import { glob } from "glob";
16
19
  import chalk from "chalk";
17
- import { loadOllamaConfig, checkOllamaHealth, batchAnalyzeScreenshots, } from "../utils/ollama.js";
20
+ import { chromium } from "playwright";
21
+ import { loadOllamaConfig, checkOllamaHealth, batchAnalyzeScreenshots, compareScreenshotDiff, generateHtmlReport, } from "../utils/ollama.js";
18
22
  /**
19
23
  * Extract route name from screenshot path.
20
24
  * e.g., "__screenshots__/dashboard.png" → "/dashboard"
@@ -53,62 +57,91 @@ function filterBySeverity(anomalies, severityFilter) {
53
57
  const levels = severityFilter.toLowerCase().split(",").map((s) => s.trim());
54
58
  return anomalies.filter((a) => levels.includes(a.severity));
55
59
  }
60
+ // ── Viewport presets ───────────────────────────────────────────────────────────
61
+ const VIEWPORT_PRESETS = {
62
+ mobile: { width: 375, height: 667 },
63
+ tablet: { width: 768, height: 1024 },
64
+ desktop: { width: 1280, height: 720 },
65
+ wide: { width: 1920, height: 1080 },
66
+ };
56
67
  /**
57
- * Append anomalies to app-exploration.md Visual Anomalies section.
68
+ * Parse viewport string: "mobile,desktop" or "375x667,1280x720"
58
69
  */
59
- function appendToExploration(projectRoot, anomalies) {
60
- const explorationPath = join(projectRoot, "tests", "playwright", "app-exploration.md");
61
- if (!existsSync(explorationPath)) {
62
- console.error(chalk.yellow(`Warning: ${explorationPath} not found, skipping write`));
63
- return;
64
- }
65
- let content = readFileSync(explorationPath, "utf-8");
66
- // Find or create Visual Anomalies section
67
- const sectionHeader = "## Visual Anomalies";
68
- const tableHeader = `| Route | Element | Type | Position | Severity | Description |
69
- | --- | --- | --- | --- | --- | --- |`;
70
- if (!content.includes(sectionHeader)) {
71
- // Add section before "## Next Steps" or at the end
72
- const nextStepsIndex = content.indexOf("## Next Steps");
73
- if (nextStepsIndex !== -1) {
74
- content =
75
- content.slice(0, nextStepsIndex) +
76
- `${sectionHeader}\n\n${tableHeader}\n\n` +
77
- content.slice(nextStepsIndex);
70
+ function parseViewports(input) {
71
+ return input.split(",").map((v) => {
72
+ const name = v.trim().toLowerCase();
73
+ if (VIEWPORT_PRESETS[name]) {
74
+ return { name, ...VIEWPORT_PRESETS[name] };
78
75
  }
79
- else {
80
- content += `\n\n${sectionHeader}\n\n${tableHeader}\n`;
76
+ const parts = name.split("x");
77
+ if (parts.length === 2) {
78
+ const w = parseInt(parts[0], 10);
79
+ const h = parseInt(parts[1], 10);
80
+ if (w > 0 && h > 0) {
81
+ return { name: `${w}x${h}`, width: w, height: h };
82
+ }
83
+ }
84
+ throw new Error(`Invalid viewport: "${v}". Use presets (mobile/tablet/desktop/wide) or WxH (e.g. 375x667)`);
85
+ });
86
+ }
87
+ // ── Baseline paths ───────────────────────────────────────────────────────────
88
+ const BASELINE_DIR = ".openspec-pw/vision-baseline";
89
+ const DIFF_DIR = ".openspec-pw/vision-diff";
90
+ /**
91
+ * Capture screenshots from a URL at multiple viewports using Playwright.
92
+ */
93
+ async function captureFromUrl(url, viewports, outputDir, concurrency = 2) {
94
+ const results = [];
95
+ mkdirSync(outputDir, { recursive: true });
96
+ let browser = null;
97
+ try {
98
+ browser = await chromium.launch({ headless: true });
99
+ for (let i = 0; i < viewports.length; i += concurrency) {
100
+ const batch = viewports.slice(i, i + concurrency);
101
+ const batchPromises = batch.map(async (vp) => {
102
+ // Each viewport gets its own context so viewport size doesn't affect other captures
103
+ const context = await browser.newContext({
104
+ viewport: { width: vp.width, height: vp.height },
105
+ });
106
+ const page = await context.newPage();
107
+ try {
108
+ await page.goto(url, { waitUntil: "networkidle", timeout: 30000 });
109
+ const filename = `${vp.name}.png`;
110
+ const filepath = join(outputDir, filename);
111
+ await page.screenshot({ path: filepath, fullPage: true });
112
+ return { path: filepath, route: `${vp.name}:${url}`, viewport: vp.name };
113
+ }
114
+ finally {
115
+ await context.close();
116
+ }
117
+ });
118
+ const batchResults = await Promise.all(batchPromises);
119
+ results.push(...batchResults);
81
120
  }
82
121
  }
83
- // Append new anomalies (de-duplicate by route + element + type)
84
- const existingRows = content.match(/\| [^|]+ \| [^|]+ \| [^|]+ \| [^|]+ \| [^|]+ \| [^|]+ \|/g) || [];
85
- const existingKeys = new Set(existingRows.map((row) => {
86
- const cells = row.split("|").map((c) => c.trim()).filter(Boolean);
87
- return `${cells[0]}:${cells[1]}:${cells[2]}`;
88
- }));
89
- const newRows = [];
90
- for (const a of anomalies) {
91
- const key = `${a.route}:${a.element}:${a.type}`;
92
- if (!existingKeys.has(key)) {
93
- newRows.push(`| ${a.route} | ${a.element} | ${a.type} | ${a.position} | ${a.severity} | ${a.description} |`);
94
- existingKeys.add(key);
95
- }
96
- }
97
- if (newRows.length > 0) {
98
- // Insert after table header
99
- const headerIndex = content.indexOf(tableHeader);
100
- if (headerIndex !== -1) {
101
- const insertPoint = headerIndex + tableHeader.length;
102
- content =
103
- content.slice(0, insertPoint) +
104
- "\n" +
105
- newRows.join("\n") +
106
- content.slice(insertPoint);
107
- }
108
- writeFileSync(explorationPath, content, "utf-8");
109
- console.log(chalk.green(` ✓ Appended ${newRows.length} anomalies to app-exploration.md`));
122
+ finally {
123
+ if (browser)
124
+ await browser.close();
110
125
  }
126
+ return results;
111
127
  }
128
+ /**
129
+ * Copy screenshots to baseline directory.
130
+ */
131
+ function saveBaseline(screenshots, projectRoot) {
132
+ const baselineDir = join(projectRoot, BASELINE_DIR);
133
+ mkdirSync(baselineDir, { recursive: true });
134
+ for (const s of screenshots) {
135
+ const name = s.viewport
136
+ ? `${basename(s.path, ".png")}-baseline.png`
137
+ : `${basename(s.path, ".png")}-baseline.png`;
138
+ const dest = join(baselineDir, name);
139
+ writeFileSync(dest, readFileSync(s.path));
140
+ console.log(chalk.green(` ✓ Baseline saved: ${dest}`));
141
+ }
142
+ return baselineDir;
143
+ }
144
+ // ── Main command ─────────────────────────────────────────────────────────────
112
145
  /**
113
146
  * Main vision check command.
114
147
  */
@@ -133,18 +166,53 @@ export async function visionCheck(options) {
133
166
  }
134
167
  process.exit(2);
135
168
  }
136
- // 2. Dry run: list files only
169
+ // 2. Parse viewports
170
+ let viewports = null;
171
+ if (options.viewport) {
172
+ viewports = parseViewports(options.viewport);
173
+ }
174
+ // 3. Gather screenshots
175
+ let screenshots = [];
176
+ if (options.viewport && options.url) {
177
+ // Multi-viewport capture mode
178
+ if (!options.json) {
179
+ console.log(chalk.blue(`\n📷 Capturing at ${viewports.length} viewport(s) from ${options.url}...\n`));
180
+ }
181
+ screenshots = await captureFromUrl(options.url, viewports, join(projectRoot, ".openspec-pw/vision-current"));
182
+ }
183
+ else {
184
+ // File-based mode
185
+ screenshots = await resolveScreenshots(options.screenshots);
186
+ }
187
+ if (screenshots.length === 0) {
188
+ if (options.viewport && !options.url) {
189
+ console.log(chalk.yellow("Error: --viewport requires --url"));
190
+ }
191
+ else {
192
+ console.log(chalk.yellow("No screenshots found. Provide --screenshots <pattern> or --url <url> --viewport <views>"));
193
+ }
194
+ process.exit(1);
195
+ }
196
+ // 4. Baseline mode: save and exit
197
+ if (options.baseline) {
198
+ const baselineDir = saveBaseline(screenshots, projectRoot);
199
+ if (!options.json) {
200
+ console.log(chalk.green(`\n✓ Baseline saved (${screenshots.length} screenshots) in ${baselineDir}`));
201
+ }
202
+ return;
203
+ }
204
+ // 5. Dry run
137
205
  if (options.dryRun) {
138
- const screenshots = await resolveScreenshots(options.screenshots);
139
- console.log(chalk.blue("\n📷 Screenshots to analyze (dry run):\n"));
206
+ console.log(chalk.blue("\n📷 Screenshots (dry run):\n"));
140
207
  for (const s of screenshots) {
141
- console.log(` ${s.route} ${s.path}`);
208
+ const vp = s.viewport ? ` [${s.viewport}]` : "";
209
+ console.log(` ${s.route}${vp} → ${s.path}`);
142
210
  }
143
211
  console.log(chalk.gray(`\nTotal: ${screenshots.length} files`));
144
212
  console.log(chalk.gray(`Ollama: ${config.url} (${config.model})`));
145
213
  return;
146
214
  }
147
- // 3. Health check
215
+ // 6. Health check
148
216
  const health = await checkOllamaHealth(config);
149
217
  if (!health.ok) {
150
218
  const result = {
@@ -163,29 +231,77 @@ export async function visionCheck(options) {
163
231
  }
164
232
  process.exit(1);
165
233
  }
166
- // 4. Resolve screenshots
167
- const screenshots = await resolveScreenshots(options.screenshots);
168
- if (screenshots.length === 0) {
169
- console.log(chalk.yellow("No screenshots found matching pattern"));
170
- process.exit(0);
171
- }
172
234
  if (!options.json) {
173
- console.log(chalk.blue(`\n🔍 Analyzing ${screenshots.length} screenshots...\n`));
235
+ const mode = options.diff ? "diff" : "analyze";
236
+ console.log(chalk.blue(`\n🔍 ${mode === "diff" ? "Pixel diff" : "Analyzing"} ${screenshots.length} screenshot(s)...\n`));
174
237
  }
175
- // 5. Batch analyze
176
- const concurrency = options.parallel || 4;
177
- const result = await batchAnalyzeScreenshots(config, screenshots, concurrency);
178
- // 6. Filter by severity if specified
238
+ // 7. Diff mode: compare with baseline
239
+ const result = {
240
+ processed: 0,
241
+ anomalies: [],
242
+ skipped: [],
243
+ ollamaUrl: config.url,
244
+ model: config.model,
245
+ baselineDir: join(projectRoot, BASELINE_DIR),
246
+ };
247
+ if (options.diff) {
248
+ const baselineDir = join(projectRoot, BASELINE_DIR);
249
+ const diffDir = join(projectRoot, DIFF_DIR);
250
+ mkdirSync(diffDir, { recursive: true });
251
+ for (const s of screenshots) {
252
+ const baseName = basename(s.path, ".png");
253
+ const baselinePath = join(baselineDir, `${baseName}-baseline.png`);
254
+ const diffPath = join(diffDir, `${baseName}-diff.png`);
255
+ if (!existsSync(baselinePath)) {
256
+ result.skipped.push(s.path);
257
+ if (!options.json) {
258
+ console.log(chalk.yellow(` ⚠ No baseline for ${s.route}, skipping diff`));
259
+ }
260
+ continue;
261
+ }
262
+ try {
263
+ const { changed, anomalies } = await compareScreenshotDiff(config, baselinePath, s.path, diffPath, s.route);
264
+ result.processed++;
265
+ result.anomalies.push(...anomalies.map((a) => ({ ...a, viewport: s.viewport })));
266
+ if (!options.json) {
267
+ if (changed) {
268
+ console.log(chalk.yellow(` ~ ${s.route}${s.viewport ? ` [${s.viewport}]` : ""}: ${anomalies.length} anomaly(ies)`));
269
+ }
270
+ else {
271
+ console.log(chalk.gray(` ✓ ${s.route}${s.viewport ? ` [${s.viewport}]` : ""}: no changes`));
272
+ }
273
+ }
274
+ }
275
+ catch (err) {
276
+ const error = err;
277
+ result.skipped.push(s.path);
278
+ if (!options.json) {
279
+ console.error(chalk.red(` ✗ ${s.route}: ${error.message}`));
280
+ }
281
+ }
282
+ }
283
+ }
284
+ else {
285
+ // Analyze mode: batch analyze screenshots
286
+ const concurrency = options.parallel || 4;
287
+ const batchResult = await batchAnalyzeScreenshots(config, screenshots.map((s) => ({ path: s.path, route: s.route })), concurrency);
288
+ result.processed = batchResult.processed;
289
+ result.anomalies = batchResult.anomalies.map((a) => ({
290
+ ...a,
291
+ viewport: screenshots.find((s) => s.path === a.screenshot)?.viewport,
292
+ }));
293
+ result.skipped = batchResult.skipped;
294
+ }
295
+ // 8. Filter by severity
179
296
  if (options.severity) {
180
297
  result.anomalies = filterBySeverity(result.anomalies, options.severity);
181
298
  }
182
- // 7. Output results
299
+ // 9. Output
183
300
  if (options.json) {
184
301
  console.log(JSON.stringify(result, null, 2));
185
302
  }
186
303
  else {
187
- // Text output
188
- console.log(chalk.blue("─── Vision Check Results ───\n"));
304
+ console.log(chalk.blue("─── Results ───\n"));
189
305
  console.log(` Processed: ${result.processed}/${screenshots.length}`);
190
306
  console.log(` Anomalies: ${result.anomalies.length}`);
191
307
  if (result.skipped.length > 0) {
@@ -199,7 +315,8 @@ export async function visionCheck(options) {
199
315
  : a.severity === "warning"
200
316
  ? chalk.yellow
201
317
  : chalk.gray;
202
- console.log(` ${severityColor(`[${a.severity}]`)} ${a.route}`);
318
+ const vp = a.viewport ? ` [${a.viewport}]` : "";
319
+ console.log(` ${severityColor(`[${a.severity}]`)} ${a.route}${vp}`);
203
320
  console.log(` Element: ${a.element}`);
204
321
  console.log(` Type: ${a.type} (${a.position})`);
205
322
  console.log(` ${a.description}\n`);
@@ -209,11 +326,14 @@ export async function visionCheck(options) {
209
326
  console.log(chalk.green("\n ✓ No layout anomalies detected\n"));
210
327
  }
211
328
  }
212
- // 8. Append to app-exploration.md if anomalies found
213
- if (result.anomalies.length > 0 && !options.json) {
214
- appendToExploration(projectRoot, result.anomalies);
329
+ // 10. HTML report
330
+ if (options.report) {
331
+ generateHtmlReport(result, screenshots.map((s) => ({ path: s.path, route: s.route })), options.report, options.diff ? join(projectRoot, DIFF_DIR) : undefined);
332
+ if (!options.json) {
333
+ console.log(chalk.green(` ✓ HTML report: ${options.report}`));
334
+ }
215
335
  }
216
- // 9. Write to output file if specified
336
+ // 11. JSON output file
217
337
  if (options.output) {
218
338
  writeFileSync(options.output, JSON.stringify(result, null, 2), "utf-8");
219
339
  if (!options.json) {
@@ -1 +1 @@
1
- {"version":3,"file":"visionCheck.js","sourceRoot":"","sources":["../../src/commands/visionCheck.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"visionCheck.js","sourceRoot":"","sources":["../../src/commands/visionCheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAW,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC;AAiB5B;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,cAAsB;IAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC9C,8CAA8C;IAC9C,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3D,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,kBAAkB,CAC/B,OAAe;IAEf,gCAAgC;IAChC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YACd,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACtC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,eAAe;IACf,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvB,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC;KAC/B,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,SAA0B,EAC1B,cAAsB;IAEtB,MAAM,MAAM,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,kFAAkF;AAElF,MAAM,gBAAgB,GAAsD;IAC1E,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACnC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IACpC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;CACpC,CAAC;AAEF;;GAEG;AACH,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACpC,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnB,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YACpD,CAAC;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,mEAAmE,CAAC,CAAC;IAC9G,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAEhF,MAAM,YAAY,GAAG,8BAA8B,CAAC;AACpD,MAAM,QAAQ,GAAG,0BAA0B,CAAC;AAE5C;;GAEG;AACH,KAAK,UAAU,cAAc,CAC3B,GAAW,EACX,SAAiE,EACjE,SAAiB,EACjB,cAAsB,CAAC;IAEvB,MAAM,OAAO,GAA6D,EAAE,CAAC;IAC7E,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1C,IAAI,OAAO,GAAmB,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;YAClD,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBAC3C,oFAAoF;gBACpF,MAAM,OAAO,GAAG,MAAM,OAAQ,CAAC,UAAU,CAAC;oBACxC,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;iBACjD,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrC,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;oBACnE,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC;oBAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;oBAC3C,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC1D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;gBAC3E,CAAC;wBAAS,CAAC;oBACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBACxB,CAAC;YACH,CAAC,CAAC,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAI,OAAO;YAAE,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACrC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,WAAsE,EACtE,WAAmB;IAEnB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACpD,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ;YACrB,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe;YAC5C,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACrC,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAElC,wBAAwB;IACxB,MAAM,MAAM,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAE7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAsB;YAChC,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC;QAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,IAAI,SAAS,GAAkE,IAAI,CAAC;IACpF,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,wBAAwB;IACxB,IAAI,WAAW,GAA8D,EAAE,CAAC;IAEhF,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACpC,8BAA8B;QAC9B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,SAAU,CAAC,MAAM,qBAAqB,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;QACzG,CAAC;QACD,WAAW,GAAG,MAAM,cAAc,CAChC,OAAO,CAAC,GAAG,EACX,SAAU,EACV,IAAI,CAAC,WAAW,EAAE,6BAA6B,CAAC,CACjD,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,kBAAkB;QAClB,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yFAAyF,CAAC,CAAC,CAAC;QACvH,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,WAAW,CAAC,MAAM,oBAAoB,WAAW,EAAE,CAAC,CAAC,CAAC;QACvG,CAAC;QACD,OAAO;IACT,CAAC;IAED,aAAa;IACb,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC;QACzD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,WAAW,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,kBAAkB;IAClB,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,MAAM,GAAsB;YAChC,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,MAAM,CAAC,OAAO;YAC1B,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC;QAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yBAAyB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,qBAAqB,CAAC,CAAC,CAAC;IAC3H,CAAC;IAED,sCAAsC;IACtC,MAAM,MAAM,GAAsB;QAChC,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,SAAS,EAAE,MAAM,CAAC,GAAG;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC;KAC7C,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC5C,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAExC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,QAAQ,eAAe,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,WAAW,CAAC,CAAC;YAEvD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;oBAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBAC7E,CAAC;gBACD,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,qBAAqB,CACxD,MAAM,EACN,YAAY,EACZ,CAAC,CAAC,IAAI,EACN,QAAQ,EACR,CAAC,CAAC,KAAK,CACR,CAAC;gBACF,MAAM,CAAC,SAAS,EAAE,CAAC;gBACnB,MAAM,CAAC,SAAS,CAAC,IAAI,CACnB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAC1D,CAAC;gBACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;oBAClB,IAAI,OAAO,EAAE,CAAC;wBACZ,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,MAAM,eAAe,CAAC,CACxG,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;oBAC/F,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,KAAK,GAAG,GAAY,CAAC;gBAC3B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,0CAA0C;QAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAC/C,MAAM,EACN,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAC1D,WAAW,CACZ,CAAC;QACF,MAAM,CAAC,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;QACzC,MAAM,CAAC,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnD,GAAG,CAAC;YACJ,QAAQ,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ;SACrE,CAAC,CAAC,CAAC;QACJ,MAAM,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;IACvC,CAAC;IAED,wBAAwB;IACxB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1E,CAAC;IAED,YAAY;IACZ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;YACjD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACjC,MAAM,aAAa,GACjB,CAAC,CAAC,QAAQ,KAAK,UAAU;oBACvB,CAAC,CAAC,KAAK,CAAC,GAAG;oBACX,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS;wBACxB,CAAC,CAAC,KAAK,CAAC,MAAM;wBACd,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBACnB,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChD,OAAO,CAAC,GAAG,CAAC,KAAK,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE,EAAE,CAAC,CAAC;gBACrE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACzC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACnD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,kBAAkB,CAChB,MAAM,EACN,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAC1D,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CACvD,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACxE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,8 @@
1
+ // Restore caller's working directory (passed from shell wrapper via env var).
2
+ // This ensures init/git/file operations use the user's directory, not the global package dir.
3
+ if (process.env.OPENSPE_PW_CWD) {
4
+ process.chdir(process.env.OPENSPE_PW_CWD);
5
+ }
1
6
  import { readFileSync } from "fs";
2
7
  import { join, dirname } from "path";
3
8
  import { fileURLToPath } from "url";
@@ -78,13 +83,18 @@ program
78
83
  program
79
84
  .command("vision-check")
80
85
  .description("Analyze screenshots for layout anomalies using Ollama VLM")
81
- .requiredOption("-s, --screenshots <pattern>", "Screenshot path(s): glob pattern or comma-separated list")
86
+ .option("-s, --screenshots <pattern>", "Screenshot path(s): glob pattern or comma-separated list")
82
87
  .option("-c, --config <path>", "Config file path (default: app-knowledge.md)")
83
88
  .option("-p, --parallel <n>", "Number of parallel requests to Ollama", (v) => parseInt(v, 10), 4)
84
89
  .option("-o, --output <path>", "Write JSON results to file")
85
90
  .option("--severity <levels>", "Filter by severity: blocking,warning,minor")
86
91
  .option("-n, --dry-run", "List screenshots without analyzing")
87
92
  .option("--json", "Output results as JSON")
93
+ .option("--viewport <views>", "Capture at multiple viewports: comma-separated presets (mobile,tablet,desktop,wide) or WxH (e.g. 375x667). Requires --url.")
94
+ .option("--url <url>", "URL to capture screenshots from (used with --viewport)")
95
+ .option("--baseline", "Save screenshots as baseline (used with --viewport or --screenshots)")
96
+ .option("--diff", "Compare current screenshots against baseline (requires prior --baseline run)")
97
+ .option("--report <path>", "Generate HTML report at the given path")
88
98
  .action(async (opts) => {
89
99
  await visionCheck(opts);
90
100
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,9 @@
1
1
  /**
2
2
  * Ollama API utilities for vision model integration.
3
3
  *
4
- * Configuration priority (highest to lowest):
5
- * 1. Function parameters
6
- * 2. Environment variables (OLLAMA_URL, OLLAMA_VISION_MODEL)
7
- * 3. app-knowledge.md Vision Check Config section
8
- *
9
- * If no configuration is found, vision check is disabled.
4
+ * Configuration: reads from `.env` in `tests/playwright/` (highest priority),
5
+ * then falls back to environment variables. If no URL or model is found,
6
+ * vision check is disabled.
10
7
  */
11
8
  export interface OllamaConfig {
12
9
  url: string;
@@ -17,10 +14,12 @@ export interface VisionAnomaly {
17
14
  route: string;
18
15
  screenshot: string;
19
16
  element: string;
20
- type: "obscured" | "crowded" | "overflowed";
17
+ type: "obscured" | "crowded" | "overflowed" | "missing" | "incorrect";
21
18
  position: string;
22
19
  severity: "blocking" | "warning" | "minor";
23
20
  description: string;
21
+ viewport?: string;
22
+ changed?: boolean;
24
23
  }
25
24
  export interface VisionCheckResult {
26
25
  processed: number;
@@ -29,17 +28,23 @@ export interface VisionCheckResult {
29
28
  skipReason?: string;
30
29
  ollamaUrl: string;
31
30
  model: string;
31
+ baselineDir?: string;
32
+ currentDir?: string;
32
33
  }
33
34
  export interface OllamaGenerateResponse {
34
35
  response: string;
35
36
  done: boolean;
36
37
  }
38
+ export interface PixelDiffRegion {
39
+ x: number;
40
+ y: number;
41
+ width: number;
42
+ height: number;
43
+ changedPixels: number;
44
+ }
37
45
  /**
38
- * Load Ollama config with priority:
39
- * 1. Environment variables (OLLAMA_URL, OLLAMA_VISION_MODEL)
40
- * 2. app-knowledge.md Vision Check Config section
41
- *
42
- * If no configuration is found, returns enabled=false.
46
+ * Load Ollama config from `.env` in `tests/playwright/` and environment variables.
47
+ * If no URL or model is configured, vision check is disabled.
43
48
  */
44
49
  export declare function loadOllamaConfig(projectRoot?: string): OllamaConfig;
45
50
  /**
@@ -61,3 +66,19 @@ export declare function batchAnalyzeScreenshots(config: OllamaConfig, screenshot
61
66
  path: string;
62
67
  route: string;
63
68
  }>, concurrency?: number): Promise<VisionCheckResult>;
69
+ /**
70
+ * Compare two screenshots with pixel diff.
71
+ * Returns changed regions and optionally saves a diff image.
72
+ */
73
+ export declare function compareScreenshotDiff(config: OllamaConfig, baselinePath: string, currentPath: string, diffPath: string, route: string): Promise<{
74
+ changed: boolean;
75
+ anomalies: VisionAnomaly[];
76
+ }>;
77
+ /**
78
+ * Generate a self-contained HTML report with embedded screenshots and results.
79
+ * If diffDir is provided, diff images are shown alongside current screenshots.
80
+ */
81
+ export declare function generateHtmlReport(result: VisionCheckResult, screenshots: Array<{
82
+ path: string;
83
+ route: string;
84
+ }>, outputPath: string, diffDir?: string): void;
@@ -1,70 +1,35 @@
1
1
  /**
2
2
  * Ollama API utilities for vision model integration.
3
3
  *
4
- * Configuration priority (highest to lowest):
5
- * 1. Function parameters
6
- * 2. Environment variables (OLLAMA_URL, OLLAMA_VISION_MODEL)
7
- * 3. app-knowledge.md Vision Check Config section
8
- *
9
- * If no configuration is found, vision check is disabled.
4
+ * Configuration: reads from `.env` in `tests/playwright/` (highest priority),
5
+ * then falls back to environment variables. If no URL or model is found,
6
+ * vision check is disabled.
10
7
  */
11
- import { existsSync, readFileSync } from "fs";
8
+ import { config as loadEnv } from "dotenv";
9
+ import { createRequire } from "module";
10
+ import { existsSync, readFileSync, writeFileSync } from "fs";
12
11
  import { join } from "path";
12
+ const _require = createRequire(import.meta.url);
13
13
  // ── Config loading ────────────────────────────────────────────────────────────
14
14
  /**
15
- * Load Ollama config from app-knowledge.md.
16
- * Parses the "## Vision Check Config" section.
17
- */
18
- function loadFromAppKnowledge(projectRoot) {
19
- const appKnowledgePath = join(projectRoot, "tests", "playwright", "app-knowledge.md");
20
- if (!existsSync(appKnowledgePath))
21
- return {};
22
- try {
23
- const content = readFileSync(appKnowledgePath, "utf-8");
24
- const match = content.match(/## Vision Check Config\s*\n([\s\S]*?)(?=\n##|\n---|\z)/);
25
- if (!match)
26
- return {};
27
- const section = match[1];
28
- const config = {};
29
- const urlMatch = section.match(/ollama_url:\s*(.+)/);
30
- if (urlMatch)
31
- config.url = urlMatch[1].trim();
32
- const modelMatch = section.match(/vision_model:\s*(.+)/);
33
- if (modelMatch)
34
- config.model = modelMatch[1].trim();
35
- const enabledMatch = section.match(/vision_enabled:\s*(.+)/);
36
- if (enabledMatch)
37
- config.enabled = enabledMatch[1].trim() === "true";
38
- return config;
39
- }
40
- catch {
41
- return {};
42
- }
43
- }
44
- /**
45
- * Load Ollama config with priority:
46
- * 1. Environment variables (OLLAMA_URL, OLLAMA_VISION_MODEL)
47
- * 2. app-knowledge.md Vision Check Config section
48
- *
49
- * If no configuration is found, returns enabled=false.
15
+ * Load Ollama config from `.env` in `tests/playwright/` and environment variables.
16
+ * If no URL or model is configured, vision check is disabled.
50
17
  */
51
18
  export function loadOllamaConfig(projectRoot = process.cwd()) {
52
- const appKnowledge = loadFromAppKnowledge(projectRoot);
53
- // Environment variables override app-knowledge.md
54
- const url = process.env.OLLAMA_URL || appKnowledge.url;
55
- const model = process.env.OLLAMA_VISION_MODEL || appKnowledge.model;
19
+ // Lazy load .env from tests/playwright/ (falls back gracefully if missing)
20
+ const envPath = join(projectRoot, "tests", "playwright", ".env");
21
+ if (existsSync(envPath)) {
22
+ loadEnv({ path: envPath });
23
+ }
24
+ const url = process.env.OLLAMA_URL;
25
+ const model = process.env.OLLAMA_VISION_MODEL;
56
26
  // If no url or model configured, disable vision check
57
27
  if (!url || !model) {
58
28
  return { url: "", model: "", enabled: false };
59
29
  }
60
30
  // Enabled: default true unless explicitly disabled
61
- let enabled = true;
62
- if (process.env.OLLAMA_VISION_ENABLED !== undefined) {
63
- enabled = process.env.OLLAMA_VISION_ENABLED === "true";
64
- }
65
- else if (appKnowledge.enabled !== undefined) {
66
- enabled = appKnowledge.enabled;
67
- }
31
+ const enabled = process.env.OLLAMA_VISION_ENABLED === undefined ||
32
+ process.env.OLLAMA_VISION_ENABLED === "true";
68
33
  return { url, model, enabled };
69
34
  }
70
35
  // ── Health check ──────────────────────────────────────────────────────────────
@@ -111,25 +76,34 @@ export async function checkOllamaHealth(config) {
111
76
  }
112
77
  }
113
78
  // ── Vision analysis ───────────────────────────────────────────────────────────
114
- const VISION_PROMPT = `你是一个专业的网页UI测试员。请分析这张截图,检测以下问题:
115
-
116
- 1. 遮挡:可交互元素(按钮、表单、链接)是否被其他元素遮挡、覆盖或压住,导致无法正常点击?
117
- 2. 拥挤:多个元素是否间距过窄、文字重叠、边界模糊,导致难以区分或误操作?
118
- 3. 溢出:内容是否被容器裁剪,导致关键信息不可见?
119
-
120
- 对于每个问题,请返回:
121
- - element: 元素名称/描述
122
- - type: 问题类型(obscured / crowded / overflowed)
123
- - position: 位置(用屏幕区域描述:左上/右上/中/左下/右下)
124
- - severity: 严重程度(blocking / warning / minor)
125
- - description: 问题描述
126
-
127
- 如果一切正常,返回空的 anomalies 数组。
128
-
129
- 请严格以JSON格式回答,不要包含任何其他文字:
130
- {
131
- "anomalies": []
132
- }`;
79
+ const VISION_PROMPT = [
80
+ "你是专业的UI测试工程师,以普通用户视角审视这张截图。",
81
+ "",
82
+ "【检测目标】用户可感知的功能性UI问题,不包括:",
83
+ "- 装饰性图标、logo的细微偏差",
84
+ "- CSS hover/transition动画状态",
85
+ "- 浏览器默认样式(滚动条、右键菜单)",
86
+ "- 动态广告/推荐内容(如能正常交互则不报错)",
87
+ "",
88
+ "【问题类型】",
89
+ "1. obscured 可交互元素被遮挡/覆盖,无法点击",
90
+ "2. crowded — 元素间距过窄、文字重叠、难以区分",
91
+ "3. overflowed — 内容被裁剪,关键信息不可见",
92
+ "4. missing — 明显应该存在的元素完全消失",
93
+ "5. incorrect — 文本内容明显错误、样式完全错误",
94
+ "",
95
+ "【严重程度】",
96
+ "- blocking:核心功能不可用(如提交按钮被遮挡)",
97
+ "- warning:影响使用体验(如重要文字被截断)",
98
+ "- minor:细微视觉问题(图标轻微偏移)",
99
+ "",
100
+ "【定位】用屏幕区域:左上/上/右上/左/中/右/左下/下/右下",
101
+ "",
102
+ '返回JSON格式,不要包含任何其他文字:',
103
+ '{"anomalies":[]}',
104
+ "",
105
+ '如果一切正常,返回:{"anomalies":[]}',
106
+ ].join("\n");
133
107
  /**
134
108
  * Analyze a single screenshot with the vision model.
135
109
  */
@@ -205,4 +179,282 @@ export async function batchAnalyzeScreenshots(config, screenshots, concurrency =
205
179
  }
206
180
  return result;
207
181
  }
182
+ // ── Pixel diff ───────────────────────────────────────────────────────────────
183
+ const DIFF_PROMPT = `你是专业的UI回归测试工程师。这张图是像素差异图,红色高亮区域表示与基准版不同。
184
+
185
+ 请分析红色高亮区域,检测:
186
+ 1. 哪些变化是真实的UI bug(如元素被遮挡、布局错乱、内容丢失)
187
+ 2. 哪些变化是正常的(如动态内容更新、动画状态变化)
188
+
189
+ 【忽略】动态广告/推荐内容、时间戳、数值变化、hover/focus状态、第三方嵌入内容的变化。
190
+
191
+ 【问题类型】
192
+ - obscured:可交互元素被遮挡,无法点击
193
+ - crowded:元素间距错乱、文字重叠
194
+ - overflowed:内容被裁剪,关键信息不可见
195
+ - missing:原有元素消失
196
+ - incorrect:样式/内容明显错误
197
+
198
+ 【严重程度】
199
+ - blocking:核心功能不可用
200
+ - warning:影响使用体验
201
+ - minor:细微视觉回归
202
+
203
+ 返回JSON(不要包含任何其他文字):
204
+ {"anomalies":[]}`;
205
+ /**
206
+ * Compare two screenshots with pixel diff.
207
+ * Returns changed regions and optionally saves a diff image.
208
+ */
209
+ export async function compareScreenshotDiff(config, baselinePath, currentPath, diffPath, route) {
210
+ const pixelmatch = _require("pixelmatch");
211
+ const { PNG } = _require("pngjs");
212
+ if (!existsSync(baselinePath)) {
213
+ throw new Error("Baseline screenshot not found: " + baselinePath);
214
+ }
215
+ if (!existsSync(currentPath)) {
216
+ throw new Error("Current screenshot not found: " + currentPath);
217
+ }
218
+ const img1 = PNG.sync.read(readFileSync(baselinePath));
219
+ const img2 = PNG.sync.read(readFileSync(currentPath));
220
+ if (img1.width !== img2.width || img1.height !== img2.height) {
221
+ throw new Error(`Screenshot dimensions mismatch: ${img1.width}x${img1.height} vs ${img2.width}x${img2.height}`);
222
+ }
223
+ const diff = new PNG(img1.width, img1.height);
224
+ const changedPixels = pixelmatch(img1.data, img2.data, diff.data, img1.width, img1.height, { threshold: 0.1 });
225
+ const changedRatio = changedPixels / (img1.width * img1.height);
226
+ // Save diff image
227
+ writeFileSync(diffPath, PNG.sync.write(diff));
228
+ // If no meaningful changes, skip VLM analysis
229
+ if (changedRatio < 0.001) {
230
+ return { changed: false, anomalies: [] };
231
+ }
232
+ // Analyze diff image with VLM (only diff image to avoid context overflow)
233
+ const diffB64 = readFileSync(diffPath).toString("base64");
234
+ const response = await fetch(`${config.url}/api/generate`, {
235
+ method: "POST",
236
+ headers: { "Content-Type": "application/json" },
237
+ body: JSON.stringify({
238
+ model: config.model,
239
+ prompt: DIFF_PROMPT,
240
+ images: [diffB64],
241
+ stream: false,
242
+ }),
243
+ });
244
+ if (!response.ok) {
245
+ throw new Error(`Ollama API error: ${response.status}`);
246
+ }
247
+ const data = (await response.json());
248
+ const responseText = data.response || "";
249
+ let jsonStr = responseText;
250
+ const jsonMatch = responseText.match(/```(?:json)?\s*([\s\S]*?)```/);
251
+ if (jsonMatch) {
252
+ jsonStr = jsonMatch[1];
253
+ }
254
+ try {
255
+ const parsed = JSON.parse(jsonStr.trim());
256
+ const anomalies = (parsed.anomalies || []).map((a) => ({
257
+ ...a,
258
+ route,
259
+ screenshot: currentPath,
260
+ changed: true,
261
+ }));
262
+ return { changed: true, anomalies };
263
+ }
264
+ catch {
265
+ console.error(`Warning: Could not parse diff response for ${route}`);
266
+ return { changed: true, anomalies: [] };
267
+ }
268
+ }
269
+ // ── HTML Report ─────────────────────────────────────────────────────────────
270
+ /**
271
+ * Generate a self-contained HTML report with embedded screenshots and results.
272
+ * If diffDir is provided, diff images are shown alongside current screenshots.
273
+ */
274
+ export function generateHtmlReport(result, screenshots, outputPath, diffDir) {
275
+ const timestamp = new Date().toISOString();
276
+ // Group anomalies by severity
277
+ const bySeverity = {
278
+ blocking: [],
279
+ warning: [],
280
+ minor: [],
281
+ };
282
+ for (const a of result.anomalies) {
283
+ const key = a.severity || "minor";
284
+ if (bySeverity[key])
285
+ bySeverity[key].push(a);
286
+ }
287
+ // Build screenshot cards with base64 images
288
+ const screenshotCards = screenshots
289
+ .map((s) => {
290
+ const base64 = readFileSync(s.path).toString("base64");
291
+ // Check for diff image
292
+ let diffBase64 = "";
293
+ let hasDiff = false;
294
+ if (diffDir) {
295
+ const baseName = s.path.split("/").pop().replace(".png", "");
296
+ const diffPath = join(diffDir, `${baseName}-diff.png`);
297
+ if (existsSync(diffPath)) {
298
+ diffBase64 = readFileSync(diffPath).toString("base64");
299
+ hasDiff = true;
300
+ }
301
+ }
302
+ const anomalies = result.anomalies.filter((a) => a.screenshot === s.path);
303
+ const badge = anomalies.length > 0
304
+ ? `<span class="badge badge-${anomalies[0].severity}">${anomalies.length} issue${anomalies.length > 1 ? "s" : ""}</span>`
305
+ : `<span class="badge badge-ok">OK</span>`;
306
+ const anomalyList = anomalies.length > 0
307
+ ? `<div class="anomaly-list">
308
+ ${anomalies
309
+ .map((a) => ` <div class="anomaly-item severity-${a.severity}">
310
+ <div class="anomaly-header">
311
+ <span class="type-badge">${a.type}</span>
312
+ <span class="severity-badge ${a.severity}">${a.severity}</span>
313
+ ${a.viewport ? `<span class="viewport-badge">${a.viewport}</span>` : ""}
314
+ ${a.changed ? `<span class="diff-badge">changed</span>` : ""}
315
+ </div>
316
+ <div class="anomaly-body">
317
+ <strong>${a.element}</strong>
318
+ <p>${a.description}</p>
319
+ <div class="anomaly-meta">${a.position}</div>
320
+ </div>
321
+ </div>`)
322
+ .join("\n")}
323
+ </div>`
324
+ : "";
325
+ const diffSection = hasDiff
326
+ ? `<div class="card-diff"><div class="diff-label">Diff</div><img src="data:image/png;base64,${diffBase64}" alt="diff" /></div>`
327
+ : "";
328
+ const currentSection = `<div class="card-img"><div class="img-label">Current</div><img src="data:image/png;base64,${base64}" alt="${s.route}" /></div>`;
329
+ const comparisonSection = hasDiff
330
+ ? `<div class="card-comparison">${currentSection}${diffSection}</div>`
331
+ : currentSection;
332
+ return ` <div class="screenshot-card ${anomalies.length > 0 ? "has-issues" : ""}">
333
+ <div class="card-header">
334
+ <span class="route">${s.route}</span>
335
+ ${badge}
336
+ </div>
337
+ <div class="card-body">${comparisonSection}</div>
338
+ ${anomalyList}
339
+ </div>`;
340
+ })
341
+ .join("\n");
342
+ const html = `<!DOCTYPE html>
343
+ <html lang="en">
344
+ <head>
345
+ <meta charset="UTF-8">
346
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
347
+ <title>Vision Check Report</title>
348
+ <style>
349
+ * { box-sizing: border-box; margin: 0; padding: 0; }
350
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f172a; color: #e2e8f0; padding: 24px; }
351
+ .header { margin-bottom: 24px; }
352
+ .header h1 { font-size: 24px; font-weight: 600; color: #f8fafc; }
353
+ .meta { font-size: 13px; color: #94a3b8; margin-top: 4px; }
354
+ .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 32px; }
355
+ .stat-card { background: #1e293b; border-radius: 12px; padding: 16px; }
356
+ .stat-value { font-size: 32px; font-weight: 700; }
357
+ .stat-label { font-size: 12px; color: #94a3b8; margin-top: 4px; }
358
+ .stat-blocking .stat-value { color: #ef4444; }
359
+ .stat-warning .stat-value { color: #f59e0b; }
360
+ .stat-minor .stat-value { color: #94a3b8; }
361
+ .stat-processed .stat-value { color: #22c55e; }
362
+ .section { margin-bottom: 32px; }
363
+ .section h2 { font-size: 18px; font-weight: 600; margin-bottom: 16px; color: #f8fafc; border-bottom: 1px solid #334155; padding-bottom: 8px; }
364
+ .screenshots-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); gap: 16px; }
365
+ .screenshot-card { background: #1e293b; border-radius: 12px; overflow: hidden; border: 1px solid #334155; }
366
+ .screenshot-card.has-issues { border-color: #475569; }
367
+ .card-header { padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #334155; }
368
+ .route { font-family: monospace; font-size: 14px; font-weight: 600; color: #f8fafc; }
369
+ .badge { font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 9999px; }
370
+ .badge-ok { background: #14532d; color: #4ade80; }
371
+ .badge-blocking { background: #7f1d1d; color: #fca5a5; }
372
+ .badge-warning { background: #78350f; color: #fcd34d; }
373
+ .badge-minor { background: #1e293b; color: #94a3b8; border: 1px solid #475569; }
374
+ .card-body { padding: 8px; }
375
+ .card-comparison { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
376
+ .card-img { position: relative; }
377
+ .img-label { position: absolute; top: 4px; left: 4px; font-size: 10px; background: rgba(0,0,0,0.6); color: #fff; padding: 2px 6px; border-radius: 4px; z-index: 1; }
378
+ .card-diff { position: relative; }
379
+ .diff-label { position: absolute; top: 4px; left: 4px; font-size: 10px; background: rgba(220,38,38,0.8); color: #fff; padding: 2px 6px; border-radius: 4px; z-index: 1; }
380
+ .card-body img { width: 100%; border-radius: 6px; display: block; }
381
+ .anomaly-list { padding: 12px 16px; border-top: 1px solid #334155; }
382
+ .anomaly-item { padding: 10px 12px; border-radius: 8px; margin-bottom: 8px; background: #0f172a; }
383
+ .anomaly-item:last-child { margin-bottom: 0; }
384
+ .anomaly-header { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
385
+ .type-badge { font-size: 11px; font-weight: 600; padding: 2px 6px; border-radius: 4px; background: #334155; color: #e2e8f0; font-family: monospace; }
386
+ .severity-badge { font-size: 11px; font-weight: 600; padding: 2px 6px; border-radius: 4px; }
387
+ .severity-badge.blocking { background: #7f1d1d; color: #fca5a5; }
388
+ .severity-badge.warning { background: #78350f; color: #fcd34d; }
389
+ .severity-badge.minor { background: #1e293b; color: #94a3b8; border: 1px solid #475569; }
390
+ .viewport-badge { font-size: 11px; padding: 2px 6px; border-radius: 4px; background: #312e81; color: #a5b4fc; }
391
+ .diff-badge { font-size: 11px; padding: 2px 6px; border-radius: 4px; background: #dc2626; color: #fff; font-family: monospace; }
392
+ .anomaly-body { }
393
+ .anomaly-body strong { font-size: 13px; color: #f8fafc; }
394
+ .anomaly-body p { font-size: 12px; color: #cbd5e1; margin-top: 4px; line-height: 1.5; }
395
+ .anomaly-meta { font-size: 11px; color: #64748b; margin-top: 4px; }
396
+ .empty-state { text-align: center; padding: 48px; color: #64748b; }
397
+ .empty-state h3 { font-size: 18px; color: #94a3b8; margin-bottom: 8px; }
398
+ .diff-indicator { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #f59e0b; margin-right: 4px; }
399
+ .diff-mode { font-size: 14px; background: #dc2626; color: #fff; padding: 2px 8px; border-radius: 6px; font-weight: normal; vertical-align: middle; }
400
+ </style>
401
+ </head>
402
+ <body>
403
+ <div class="header">
404
+ <h1>Vision Check Report${diffDir ? " <span class='diff-mode'>DIFF MODE</span>" : ""}</h1>
405
+ <div class="meta">Generated: ${timestamp} | Ollama: ${result.ollamaUrl} | Model: ${result.model}${diffDir ? " | Baseline: " + result.baselineDir : ""}</div>
406
+ </div>
407
+
408
+ <div class="summary">
409
+ <div class="stat-card stat-processed">
410
+ <div class="stat-value">${result.processed}</div>
411
+ <div class="stat-label">Processed</div>
412
+ </div>
413
+ <div class="stat-card stat-blocking">
414
+ <div class="stat-value">${bySeverity.blocking.length}</div>
415
+ <div class="stat-label">Blocking</div>
416
+ </div>
417
+ <div class="stat-card stat-warning">
418
+ <div class="stat-value">${bySeverity.warning.length}</div>
419
+ <div class="stat-label">Warning</div>
420
+ </div>
421
+ <div class="stat-card stat-minor">
422
+ <div class="stat-value">${bySeverity.minor.length}</div>
423
+ <div class="stat-label">Minor</div>
424
+ </div>
425
+ </div>
426
+
427
+ <div class="section">
428
+ <h2>Screenshots (${screenshots.length})</h2>
429
+ ${screenshotCards
430
+ ? `<div class="screenshots-grid">${screenshotCards}</div>`
431
+ : `<div class="empty-state"><h3>No screenshots analyzed</h3></div>`}
432
+ </div>
433
+
434
+ ${result.anomalies.length > 0
435
+ ? `<div class="section">
436
+ <h2>All Anomalies</h2>
437
+ <div class="anomaly-list" style="padding:0;border:none;background:transparent">
438
+ ${result.anomalies
439
+ .map((a) => ` <div class="anomaly-item severity-${a.severity}">
440
+ <div class="anomaly-header">
441
+ <span class="type-badge">${a.type}</span>
442
+ <span class="severity-badge ${a.severity}">${a.severity}</span>
443
+ ${a.viewport ? `<span class="viewport-badge">${a.viewport}</span>` : ""}
444
+ ${a.changed ? `<span class="diff-indicator" title="Pixel diff detected"></span>` : ""}
445
+ </div>
446
+ <div class="anomaly-body">
447
+ <strong>${a.element}</strong>
448
+ <p>${a.description}</p>
449
+ <div class="anomaly-meta">${a.route} · ${a.position}</div>
450
+ </div>
451
+ </div>`)
452
+ .join("\n")}
453
+ </div>
454
+ </div>`
455
+ : ""}
456
+ </body>
457
+ </html>`;
458
+ writeFileSync(outputPath, html, "utf-8");
459
+ }
208
460
  //# sourceMappingURL=ollama.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/utils/ollama.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAkC5B,iFAAiF;AAEjF;;;GAGG;AACH,SAAS,oBAAoB,CAAC,WAAmB;IAC/C,MAAM,gBAAgB,GAAG,IAAI,CAC3B,WAAW,EACX,OAAO,EACP,YAAY,EACZ,kBAAkB,CACnB,CAAC;IACF,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CACzB,wDAAwD,CACzD,CAAC;QACF,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QAEtB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,MAAM,GAA0B,EAAE,CAAC;QAEzC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACrD,IAAI,QAAQ;YAAE,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAE9C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACzD,IAAI,UAAU;YAAE,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEpD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC7D,IAAI,YAAY;YAAE,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;QAErE,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,cAAsB,OAAO,CAAC,GAAG,EAAE;IAClE,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAEvD,kDAAkD;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,YAAY,CAAC,GAAG,CAAC;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,YAAY,CAAC,KAAK,CAAC;IAEpE,sDAAsD;IACtD,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC;IAED,mDAAmD;IACnD,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,MAAM,CAAC;IACzD,CAAC;SAAM,IAAI,YAAY,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB;IAEpB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IACtD,CAAC;IAED,IAAI,CAAC;QACH,sBAAsB;QACtB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;QAE3D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,GAAG,WAAW,EAAE;YACrD,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,iBAAiB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QACpE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyC,CAAC;QAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAE7C,6DAA6D;QAC7D,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAC9B,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,KAAK,MAAM,CAAC,KAAK;YACrB,IAAI,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;YACnC,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,SAAS,CACpC,CAAC;QAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,UAAU,MAAM,CAAC,KAAK,2BAA2B,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;aAClG,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;IAClE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAAY,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;QACtD,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;IACnE,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;EAkBpB,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,cAAsB,EACtB,KAAa;IAEb,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,yBAAyB,cAAc,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,GAAG,eAAe,EAAE;QACzD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,aAAa;YACrB,MAAM,EAAE,CAAC,WAAW,CAAC;YACrB,MAAM,EAAE,KAAK;SACd,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA2B,CAAC;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAEzC,0DAA0D;IAC1D,IAAI,OAAO,GAAG,YAAY,CAAC;IAC3B,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACrE,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAoC,CAAC;QAC7E,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QAEzC,wCAAwC;QACxC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,GAAG,CAAC;YACJ,KAAK;YACL,UAAU,EAAE,cAAc;SAC3B,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;QAC3D,OAAO,CAAC,KAAK,CAAC,gDAAgD,KAAK,EAAE,CAAC,CAAC;QACvE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,MAAoB,EACpB,WAAmD,EACnD,cAAsB,CAAC;IAEvB,MAAM,MAAM,GAAsB;QAChC,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,SAAS,EAAE,MAAM,CAAC,GAAG;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC;IAEF,qBAAqB;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;YACnD,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC/D,MAAM,CAAC,SAAS,EAAE,CAAC;gBACnB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;YACtC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,KAAK,GAAG,GAAY,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,oBAAoB,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC7D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/utils/ollama.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openspec-playwright",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "description": "OpenSpec + Playwright E2E verification setup tool for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,12 +23,16 @@
23
23
  "@types/tar": "^6.1.13",
24
24
  "chalk": "^5.3.0",
25
25
  "commander": "^12.1.0",
26
+ "dotenv": "^17.4.2",
26
27
  "glob": "^13.0.6",
28
+ "pixelmatch": "^7.1.0",
27
29
  "playwright": "^1.50.0",
30
+ "pngjs": "^7.0.0",
28
31
  "tar": "^7.5.13"
29
32
  },
30
33
  "devDependencies": {
31
34
  "@types/node": "^22.0.0",
35
+ "@types/pixelmatch": "^5.2.6",
32
36
  "@typescript-eslint/eslint-plugin": "^8.58.0",
33
37
  "@typescript-eslint/parser": "^8.58.0",
34
38
  "@vitest/coverage-v8": "^4.1.2",
@@ -101,22 +101,6 @@ Persists assertion repairs (typos, spec drift) across sessions.
101
101
 
102
102
  ---
103
103
 
104
- ## Vision Check Config
105
-
106
- Ollama VLM configuration for layout anomaly detection. See `openspec-pw doctor` for status.
107
-
108
- ```
109
- ollama_url:
110
- vision_model:
111
- vision_enabled: false
112
- ```
113
-
114
- > **Note**: Vision check is disabled by default. Configure `ollama_url` and `vision_model` to enable.
115
- > Environment variables (`OLLAMA_URL`, `OLLAMA_VISION_MODEL`) override these values.
116
- > Run `openspec-pw vision-check --dry-run` to verify configuration.
117
-
118
- ---
119
-
120
104
  ## Changelog
121
105
 
122
106
  | Date | Change | By |