-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-patterns.ts
More file actions
50 lines (45 loc) · 2.25 KB
/
Copy pathtest-patterns.ts
File metadata and controls
50 lines (45 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import './test-env.js';
/**
* Phase 20 Slice A — pattern library quality gate (FR-D1). Every page structure,
* stamped onto an empty canvas, must score > 95 with ZERO cliché tells across
* multiple themes. A pattern that ships a tell would *teach* slop, so this is the
* backstop that keeps the library honest. Pure + fast (no Chrome).
* Run with: npx tsx test-patterns.ts
*/
import { createCanvas } from './src/scene-graph.js';
import { listStructures, applyStructure } from './src/structures.js';
import { getPreset } from './src/presets.js';
import { evaluateCanvas } from './src/evaluate.js';
const BAR = 95; // every pattern must score STRICTLY above this (> 95)
// Neutral default (applyStructure's seeded defaults) + every bundled preset.
// All presets now use designed off-white/off-black (no pure #ffffff/#000000),
// so a pattern must hold up under each without tripping a tell.
const THEMES = ['default', 'dark', 'light', 'material', 'minimal'] as const;
let passed = 0;
let failed = 0;
function assert(condition: boolean, label: string) {
if (condition) { console.log(` ✓ ${label}`); passed++; }
else { console.log(` ✗ ${label}`); failed++; }
}
async function main() {
const pages = listStructures().filter((s) => s.kind === 'page');
console.log(`\nPattern quality gate — ${pages.length} page structures × ${THEMES.length} themes (bar: > ${BAR}, zero tells)\n`);
for (const s of pages) {
for (const theme of THEMES) {
const canvas = createCanvas(`gate-${s.name}-${theme}`);
applyStructure(canvas, s.name, { replace: true });
if (theme !== 'default') {
const preset = getPreset(theme);
if (preset) canvas.variables = structuredClone(preset.variables);
}
const ev = await evaluateCanvas(canvas, { mode: 'fast', genre: theme === 'default' ? undefined : theme });
const tells = ev.issues.filter((i) => i.category === 'cliche');
const ok = ev.overallScore > BAR && tells.length === 0;
const detail = ok ? `${ev.overallScore}` : `${ev.overallScore}${tells.length ? ' · tells: ' + tells.map((t) => t.tell).join(', ') : ''}`;
assert(ok, `${s.name} @ ${theme} — ${detail}`);
}
}
console.log(`\n${passed} passed, ${failed} failed`);
process.exit(failed > 0 ? 1 : 0);
}
main();