aub-workspace 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +23 -0
- package/bin/aub-workspace.mjs +246 -0
- package/package.json +32 -0
- package/vendor/aub/apps/editor/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js +1 -0
- package/vendor/aub/apps/editor/dist/assets/angular-importer.lib-dB_jK4mR.js +32 -0
- package/vendor/aub/apps/editor/dist/assets/canvas-tools-CuYC7cA2.js +364 -0
- package/vendor/aub/apps/editor/dist/assets/design-bridge.lib-DJvaK6AX.js +1 -0
- package/vendor/aub/apps/editor/dist/assets/export-agent-prompt.lib-BsP0KNqo.js +2 -0
- package/vendor/aub/apps/editor/dist/assets/export-md.lib-DdmdeWgO.js +3 -0
- package/vendor/aub/apps/editor/dist/assets/handoff-package.lib-DDYpcEma.js +20 -0
- package/vendor/aub/apps/editor/dist/assets/implementation-report.lib-CmsSB_8s.js +1 -0
- package/vendor/aub/apps/editor/dist/assets/index-BCH-ek3h.js +2 -0
- package/vendor/aub/apps/editor/dist/assets/index-lAnc928Q.css +1 -0
- package/vendor/aub/apps/editor/dist/assets/index-vt1nM1M4.js +507 -0
- package/vendor/aub/apps/editor/dist/assets/jszip.min-CRfXyL92.js +12 -0
- package/vendor/aub/apps/editor/dist/assets/react-vendor-ByX9Pqse.js +40 -0
- package/vendor/aub/apps/editor/dist/brand/android-chrome-192x192.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/android-chrome-512x512.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/app-icon-1024.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/app-icon-192.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/app-icon-512.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/apple-touch-icon.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/aub-logo-mark.svg +28 -0
- package/vendor/aub/apps/editor/dist/brand/favicon-16x16.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon-32x32.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon-48x48.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon.ico +0 -0
- package/vendor/aub/apps/editor/dist/brand/favicon.svg +9 -0
- package/vendor/aub/apps/editor/dist/brand/maskable-icon-512.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/mstile-150x150.png +0 -0
- package/vendor/aub/apps/editor/dist/brand/safari-pinned-tab.svg +8 -0
- package/vendor/aub/apps/editor/dist/browserconfig.xml +9 -0
- package/vendor/aub/apps/editor/dist/index.html +22 -0
- package/vendor/aub/apps/editor/dist/manifest.webmanifest +28 -0
- package/vendor/aub/apps/editor/dist/template-previews/admin-table.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/booking.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/calendar.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/catalog.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/chat.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/checkout.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/crm.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/dashboard.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/feed.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/files.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/kanban.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/landing.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/mail.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/onboarding.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/pricing.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/product-detail.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/settings.png +0 -0
- package/vendor/aub/apps/editor/dist/template-previews/wiki.png +0 -0
- package/vendor/aub/apps/mcp-server/dist/aub.js +15 -0
- package/vendor/aub/apps/mcp-server/dist/context.js +1 -0
- package/vendor/aub/apps/mcp-server/dist/http.js +123 -0
- package/vendor/aub/apps/mcp-server/dist/index.js +23 -0
- package/vendor/aub/apps/mcp-server/dist/repo.js +17 -0
- package/vendor/aub/apps/mcp-server/dist/schema.js +42 -0
- package/vendor/aub/apps/mcp-server/dist/server.js +80 -0
- package/vendor/aub/apps/mcp-server/dist/tools/approve-component-candidate.js +27 -0
- package/vendor/aub/apps/mcp-server/dist/tools/diff-blueprints.js +27 -0
- package/vendor/aub/apps/mcp-server/dist/tools/export-handoff.js +87 -0
- package/vendor/aub/apps/mcp-server/dist/tools/export-prompt.js +35 -0
- package/vendor/aub/apps/mcp-server/dist/tools/export-template-authoring-prompt.js +13 -0
- package/vendor/aub/apps/mcp-server/dist/tools/generate-template-from-source.js +25 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-aub-session.js +13 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-blueprint.js +28 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-project.js +45 -0
- package/vendor/aub/apps/mcp-server/dist/tools/get-workspace-status.js +10 -0
- package/vendor/aub/apps/mcp-server/dist/tools/import-design-bridge.js +62 -0
- package/vendor/aub/apps/mcp-server/dist/tools/list-blueprints.js +11 -0
- package/vendor/aub/apps/mcp-server/dist/tools/list-projects.js +11 -0
- package/vendor/aub/apps/mcp-server/dist/tools/lock-blueprint.js +33 -0
- package/vendor/aub/apps/mcp-server/dist/tools/migrate-blueprint.js +38 -0
- package/vendor/aub/apps/mcp-server/dist/tools/resolve-component.js +51 -0
- package/vendor/aub/apps/mcp-server/dist/tools/scaffold-blueprint.js +53 -0
- package/vendor/aub/apps/mcp-server/dist/tools/scan-project-ui.js +18 -0
- package/vendor/aub/apps/mcp-server/dist/tools/submit-report.js +48 -0
- package/vendor/aub/apps/mcp-server/dist/tools/update-aub-session.js +14 -0
- package/vendor/aub/apps/mcp-server/dist/tools/validate-blueprint.js +67 -0
- package/vendor/aub/apps/mcp-server/dist/tools/validate-project.js +74 -0
- package/vendor/aub/apps/mcp-server/dist/tools/write-blueprint.js +72 -0
- package/vendor/aub/apps/mcp-server/dist/workspace.js +138 -0
- package/vendor/aub/docs/agent-handoff.md +85 -0
- package/vendor/aub/docs/agent-handoff.zh-Hant.md +85 -0
- package/vendor/aub/docs/template-authoring-agent.md +86 -0
- package/vendor/aub/schema/aub-ci.schema.json +34 -0
- package/vendor/aub/schema/aub.registry.schema.json +118 -0
- package/vendor/aub/schema/design-bridge.schema.json +44 -0
- package/vendor/aub/schema/implementation-report.schema.json +93 -0
- package/vendor/aub/schema/project-types.ts +72 -0
- package/vendor/aub/schema/registry/components.json +118 -0
- package/vendor/aub/schema/types.js +13 -0
- package/vendor/aub/schema/types.ts +348 -0
- package/vendor/aub/schema/ui-blueprint-lock.schema.json +61 -0
- package/vendor/aub/schema/ui-blueprint.schema.json +1339 -0
- package/vendor/aub/schema/ui-project.schema.json +139 -0
- package/vendor/aub/scripts/agent-implementation-benchmark.lib.mjs +125 -0
- package/vendor/aub/scripts/angular-importer.lib.mjs +982 -0
- package/vendor/aub/scripts/check-editor-bundle-budget.mjs +36 -0
- package/vendor/aub/scripts/ci-verify.lib.mjs +256 -0
- package/vendor/aub/scripts/ci-verify.mjs +45 -0
- package/vendor/aub/scripts/create-authoring-kit.mjs +84 -0
- package/vendor/aub/scripts/create-implementation-report.mjs +24 -0
- package/vendor/aub/scripts/design-bridge.lib.d.mts +32 -0
- package/vendor/aub/scripts/design-bridge.lib.mjs +69 -0
- package/vendor/aub/scripts/diff-blueprint.lib.d.mts +18 -0
- package/vendor/aub/scripts/diff-blueprint.lib.mjs +148 -0
- package/vendor/aub/scripts/diff-blueprint.mjs +25 -0
- package/vendor/aub/scripts/export-agent-prompt.lib.d.mts +10 -0
- package/vendor/aub/scripts/export-agent-prompt.lib.mjs +160 -0
- package/vendor/aub/scripts/export-agent-prompt.mjs +79 -0
- package/vendor/aub/scripts/export-md.lib.d.mts +3 -0
- package/vendor/aub/scripts/export-md.lib.mjs +302 -0
- package/vendor/aub/scripts/export-md.mjs +43 -0
- package/vendor/aub/scripts/generate-registry-artifacts.lib.mjs +118 -0
- package/vendor/aub/scripts/generate-registry-artifacts.mjs +65 -0
- package/vendor/aub/scripts/generate-site-locales.mjs +545 -0
- package/vendor/aub/scripts/handoff-package.lib.d.mts +20 -0
- package/vendor/aub/scripts/handoff-package.lib.mjs +111 -0
- package/vendor/aub/scripts/implementation-report.lib.d.mts +21 -0
- package/vendor/aub/scripts/implementation-report.lib.mjs +97 -0
- package/vendor/aub/scripts/import-angular-component.mjs +72 -0
- package/vendor/aub/scripts/import-design-bridge.mjs +59 -0
- package/vendor/aub/scripts/lock-blueprint.lib.d.mts +23 -0
- package/vendor/aub/scripts/lock-blueprint.lib.mjs +58 -0
- package/vendor/aub/scripts/lock-blueprint.mjs +36 -0
- package/vendor/aub/scripts/migrate-blueprint-cli.mjs +28 -0
- package/vendor/aub/scripts/migrate-blueprint.d.mts +5 -0
- package/vendor/aub/scripts/migrate-blueprint.mjs +95 -0
- package/vendor/aub/scripts/package-workspace-cli.mjs +34 -0
- package/vendor/aub/scripts/project.lib.d.mts +44 -0
- package/vendor/aub/scripts/project.lib.mjs +175 -0
- package/vendor/aub/scripts/project.mjs +332 -0
- package/vendor/aub/scripts/registry.lib.d.mts +52 -0
- package/vendor/aub/scripts/registry.lib.mjs +222 -0
- package/vendor/aub/scripts/run-agent-implementation.mjs +423 -0
- package/vendor/aub/scripts/run-agent-readability.mjs +145 -0
- package/vendor/aub/scripts/run-ollama-prompt.mjs +30 -0
- package/vendor/aub/scripts/scaffold-blueprint.lib.d.mts +38 -0
- package/vendor/aub/scripts/scaffold-blueprint.lib.mjs +316 -0
- package/vendor/aub/scripts/scaffold-blueprint.mjs +86 -0
- package/vendor/aub/scripts/score-agent-implementation.mjs +27 -0
- package/vendor/aub/scripts/score-agent-readability.mjs +54 -0
- package/vendor/aub/scripts/sync-brand-assets.mjs +33 -0
- package/vendor/aub/scripts/validate-blueprint.lib.d.mts +14 -0
- package/vendor/aub/scripts/validate-blueprint.lib.mjs +136 -0
- package/vendor/aub/scripts/validate.mjs +128 -0
- package/vendor/aub/scripts/verify-implementation-report.mjs +36 -0
- package/vendor/aub/scripts/workspace-loop.lib.d.mts +17 -0
- package/vendor/aub/scripts/workspace-loop.lib.mjs +674 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/HenryLau1103/AUB/schema/0.1.0/ui-project.schema.json",
|
|
4
|
+
"title": "UI Blueprint Project",
|
|
5
|
+
"description": "A reference-based multi-screen project. Lists member single-screen Blueprint files by relative path, declares a navigation graph between them, names an entry screen, and optionally carries a project-level shared design system. Member .ui.json files remain fully valid standalone Blueprints.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"version",
|
|
10
|
+
"id",
|
|
11
|
+
"name",
|
|
12
|
+
"screens",
|
|
13
|
+
"entry_screen"
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"$schema": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Optional path or URL to this JSON Schema. Lets editors provide validation and autocomplete for standalone .aub.project.json files. Ignored by AUB tooling."
|
|
19
|
+
},
|
|
20
|
+
"version": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Semantic version of the project schema this document conforms to.",
|
|
23
|
+
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
|
|
24
|
+
"enum": ["0.1.0"],
|
|
25
|
+
"examples": ["0.1.0"]
|
|
26
|
+
},
|
|
27
|
+
"id": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Unique project identifier (kebab or dot notation, e.g. 'acme-app').",
|
|
30
|
+
"pattern": "^[a-z0-9][a-z0-9._-]*$",
|
|
31
|
+
"minLength": 1,
|
|
32
|
+
"maxLength": 128
|
|
33
|
+
},
|
|
34
|
+
"name": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "Human-readable project name shown in editors and exports.",
|
|
37
|
+
"minLength": 1,
|
|
38
|
+
"maxLength": 128
|
|
39
|
+
},
|
|
40
|
+
"description": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Optional one-paragraph summary of the product or flow this project describes.",
|
|
43
|
+
"maxLength": 1024
|
|
44
|
+
},
|
|
45
|
+
"screens": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"description": "Member screens. Each references a single-screen Blueprint file by relative path. At least one required.",
|
|
48
|
+
"minItems": 1,
|
|
49
|
+
"items": { "$ref": "#/$defs/screenRef" }
|
|
50
|
+
},
|
|
51
|
+
"entry_screen": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "Screen id (from screens[].id) where the flow starts. MUST match one of the declared screens.",
|
|
54
|
+
"pattern": "^[a-z0-9][a-z0-9._-]*$",
|
|
55
|
+
"minLength": 1,
|
|
56
|
+
"maxLength": 128
|
|
57
|
+
},
|
|
58
|
+
"navigation": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"description": "Directed navigation edges between screens. from/to MUST reference declared screen ids.",
|
|
61
|
+
"items": { "$ref": "#/$defs/navigationEdge" }
|
|
62
|
+
},
|
|
63
|
+
"design_system": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"description": "Optional project-level shared design tokens. Member screens may override these in their own design_system. Free-form object mirroring a Blueprint design_system; not validated field-for-field here.",
|
|
66
|
+
"additionalProperties": true
|
|
67
|
+
},
|
|
68
|
+
"provenance": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"description": "Optional metadata about how this project document was produced.",
|
|
71
|
+
"additionalProperties": true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"$defs": {
|
|
75
|
+
"screenRef": {
|
|
76
|
+
"type": "object",
|
|
77
|
+
"additionalProperties": false,
|
|
78
|
+
"required": ["id", "path"],
|
|
79
|
+
"properties": {
|
|
80
|
+
"id": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"description": "Screen identifier. MUST match the referenced Blueprint's screen.id.",
|
|
83
|
+
"pattern": "^[a-z0-9][a-z0-9._-]*$",
|
|
84
|
+
"minLength": 1,
|
|
85
|
+
"maxLength": 128
|
|
86
|
+
},
|
|
87
|
+
"name": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"description": "Optional display name. Defaults to the referenced Blueprint's screen.name.",
|
|
90
|
+
"minLength": 1,
|
|
91
|
+
"maxLength": 128
|
|
92
|
+
},
|
|
93
|
+
"path": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "Relative path (from the project file) to a single-screen .ui.json or .ui.yaml Blueprint.",
|
|
96
|
+
"minLength": 1,
|
|
97
|
+
"maxLength": 1024
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"navigationEdge": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"required": ["from", "to"],
|
|
105
|
+
"properties": {
|
|
106
|
+
"from": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"description": "Source screen id (must be a declared screen).",
|
|
109
|
+
"pattern": "^[a-z0-9][a-z0-9._-]*$",
|
|
110
|
+
"minLength": 1,
|
|
111
|
+
"maxLength": 128
|
|
112
|
+
},
|
|
113
|
+
"to": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"description": "Destination screen id (must be a declared screen).",
|
|
116
|
+
"pattern": "^[a-z0-9][a-z0-9._-]*$",
|
|
117
|
+
"minLength": 1,
|
|
118
|
+
"maxLength": 128
|
|
119
|
+
},
|
|
120
|
+
"trigger": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"description": "What causes the navigation.",
|
|
123
|
+
"enum": ["click", "submit", "change", "load", "system", "gesture"]
|
|
124
|
+
},
|
|
125
|
+
"interaction_id": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "Optional id of the interaction on the source screen that triggers this navigation.",
|
|
128
|
+
"minLength": 1,
|
|
129
|
+
"maxLength": 128
|
|
130
|
+
},
|
|
131
|
+
"label": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"description": "Optional human-readable label for the edge (e.g. 'Open settings').",
|
|
134
|
+
"maxLength": 280
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { verifyImplementationReport } from './implementation-report.lib.mjs';
|
|
2
|
+
|
|
3
|
+
const STYLE_KEYS = [
|
|
4
|
+
'position',
|
|
5
|
+
'marginTop',
|
|
6
|
+
'marginRight',
|
|
7
|
+
'marginBottom',
|
|
8
|
+
'marginLeft',
|
|
9
|
+
'backgroundColor',
|
|
10
|
+
'color',
|
|
11
|
+
'borderRadius',
|
|
12
|
+
'boxShadow',
|
|
13
|
+
'fontFamily',
|
|
14
|
+
'fontSize',
|
|
15
|
+
'fontWeight',
|
|
16
|
+
'lineHeight',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const AUTO_LAYOUT_STYLE_KEYS = [
|
|
20
|
+
'display',
|
|
21
|
+
'flexDirection',
|
|
22
|
+
'rowGap',
|
|
23
|
+
'columnGap',
|
|
24
|
+
'paddingTop',
|
|
25
|
+
'paddingRight',
|
|
26
|
+
'paddingBottom',
|
|
27
|
+
'paddingLeft',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export function scoreImplementationBenchmark(blueprint, candidate, reference, implementationReport) {
|
|
31
|
+
const checks = [];
|
|
32
|
+
const nodeIds = blueprint.nodes.map((node) => node.id);
|
|
33
|
+
const root = blueprint.nodes.find((node) => node.parent_id === null);
|
|
34
|
+
|
|
35
|
+
for (const viewport of blueprint.viewports) {
|
|
36
|
+
const candidateView = candidate.viewports[viewport.id];
|
|
37
|
+
const referenceView = reference.viewports[viewport.id];
|
|
38
|
+
add(checks, `${viewport.id}.screenshot`, Boolean(candidateView?.screenshot_bytes > 5000), '> 5000 bytes', candidateView?.screenshot_bytes ?? 0);
|
|
39
|
+
add(checks, `${viewport.id}.horizontal_overflow`, candidateView?.horizontal_overflow === false, false, candidateView?.horizontal_overflow);
|
|
40
|
+
add(checks, `${viewport.id}.root_children`, equal(candidateView?.root_children, root?.children ?? []), root?.children ?? [], candidateView?.root_children);
|
|
41
|
+
|
|
42
|
+
for (const nodeId of nodeIds) {
|
|
43
|
+
add(checks, `${viewport.id}.node.${nodeId}`, Boolean(candidateView?.nodes?.[nodeId]), true, Boolean(candidateView?.nodes?.[nodeId]));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const node of blueprint.nodes) {
|
|
47
|
+
const actualNode = candidateView?.nodes?.[node.id];
|
|
48
|
+
const referenceNode = referenceView?.nodes?.[node.id];
|
|
49
|
+
add(
|
|
50
|
+
checks,
|
|
51
|
+
`${viewport.id}.parent.${node.id}`,
|
|
52
|
+
actualNode?.parent_node_id === node.parent_id,
|
|
53
|
+
node.parent_id,
|
|
54
|
+
actualNode?.parent_node_id
|
|
55
|
+
);
|
|
56
|
+
const styleKeys = node.layout?.mode === 'auto'
|
|
57
|
+
? [...STYLE_KEYS, ...AUTO_LAYOUT_STYLE_KEYS]
|
|
58
|
+
: STYLE_KEYS;
|
|
59
|
+
for (const key of styleKeys) {
|
|
60
|
+
if (referenceNode?.styles?.[key] === undefined) continue;
|
|
61
|
+
add(
|
|
62
|
+
checks,
|
|
63
|
+
`${viewport.id}.style.${node.id}.${key}`,
|
|
64
|
+
actualNode?.styles?.[key] === referenceNode.styles[key],
|
|
65
|
+
referenceNode.styles[key],
|
|
66
|
+
actualNode?.styles?.[key]
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const placement = node.placements?.[viewport.id];
|
|
71
|
+
if (!placement) continue;
|
|
72
|
+
const actual = actualNode?.rect;
|
|
73
|
+
for (const key of ['x', 'y', 'width', 'height']) {
|
|
74
|
+
const pass = Number.isFinite(actual?.[key]) && Math.abs(actual[key] - placement[key]) <= 2;
|
|
75
|
+
add(checks, `${viewport.id}.geometry.${node.id}.${key}`, pass, placement[key], actual?.[key]);
|
|
76
|
+
}
|
|
77
|
+
add(checks, `${viewport.id}.geometry.${node.id}.z_index`, Number(actual?.z_index) === placement.z_index, placement.z_index, actual?.z_index);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const primary = candidateView?.nodes?.primary_cta?.rect;
|
|
81
|
+
const secondary = candidateView?.nodes?.secondary_cta?.rect;
|
|
82
|
+
add(checks, `${viewport.id}.cta_side_by_side`, Boolean(
|
|
83
|
+
primary && secondary && Math.abs(primary.y - secondary.y) <= 2 && primary.x + primary.width <= secondary.x
|
|
84
|
+
), true, { primary, secondary });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (const node of blueprint.nodes) {
|
|
88
|
+
const expectedText = node.content?.text ?? node.content?.label;
|
|
89
|
+
if (!expectedText) continue;
|
|
90
|
+
const actualText = candidate.viewports.desktop?.nodes?.[node.id]?.text?.trim();
|
|
91
|
+
add(checks, `content.${node.id}`, actualText === expectedText, expectedText, actualText);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const interaction of blueprint.interactions) {
|
|
95
|
+
add(
|
|
96
|
+
checks,
|
|
97
|
+
`interaction.${interaction.id}`,
|
|
98
|
+
candidate.interactions?.[interaction.source_node_id] === interaction.action,
|
|
99
|
+
interaction.action,
|
|
100
|
+
candidate.interactions?.[interaction.source_node_id]
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
add(checks, 'accessibility.focus_visible', candidate.has_focus_visible === true, true, candidate.has_focus_visible);
|
|
105
|
+
const reportVerification = verifyImplementationReport(blueprint, implementationReport);
|
|
106
|
+
add(checks, 'implementation_report.ready', reportVerification.ready, true, reportVerification);
|
|
107
|
+
|
|
108
|
+
const passed = checks.filter((check) => check.pass).length;
|
|
109
|
+
return {
|
|
110
|
+
score: Math.round((passed / checks.length) * 100),
|
|
111
|
+
passed,
|
|
112
|
+
total: checks.length,
|
|
113
|
+
ready: passed === checks.length,
|
|
114
|
+
checks,
|
|
115
|
+
report_verification: reportVerification,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function add(checks, path, pass, expected, actual) {
|
|
120
|
+
checks.push({ path, pass, expected, actual });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function equal(left, right) {
|
|
124
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
125
|
+
}
|