@neonwatty/limner 0.1.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.
Files changed (82) hide show
  1. package/README.md +161 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +26 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/capture.d.ts +12 -0
  6. package/dist/commands/capture.js +66 -0
  7. package/dist/commands/capture.js.map +1 -0
  8. package/dist/commands/compare-image-app.d.ts +12 -0
  9. package/dist/commands/compare-image-app.js +45 -0
  10. package/dist/commands/compare-image-app.js.map +1 -0
  11. package/dist/commands/compare-image-reference.d.ts +28 -0
  12. package/dist/commands/compare-image-reference.js +82 -0
  13. package/dist/commands/compare-image-reference.js.map +1 -0
  14. package/dist/commands/compare.d.ts +15 -0
  15. package/dist/commands/compare.js +168 -0
  16. package/dist/commands/compare.js.map +1 -0
  17. package/dist/commands/init.d.ts +12 -0
  18. package/dist/commands/init.js +65 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/preview.d.ts +2 -0
  21. package/dist/commands/preview.js +27 -0
  22. package/dist/commands/preview.js.map +1 -0
  23. package/dist/commands/report.d.ts +2 -0
  24. package/dist/commands/report.js +14 -0
  25. package/dist/commands/report.js.map +1 -0
  26. package/dist/commands/runs.d.ts +2 -0
  27. package/dist/commands/runs.js +63 -0
  28. package/dist/commands/runs.js.map +1 -0
  29. package/dist/core/dom-metrics.d.ts +18 -0
  30. package/dist/core/dom-metrics.js +54 -0
  31. package/dist/core/dom-metrics.js.map +1 -0
  32. package/dist/core/playwright-capture.d.ts +27 -0
  33. package/dist/core/playwright-capture.js +46 -0
  34. package/dist/core/playwright-capture.js.map +1 -0
  35. package/dist/core/playwright-dom.d.ts +16 -0
  36. package/dist/core/playwright-dom.js +64 -0
  37. package/dist/core/playwright-dom.js.map +1 -0
  38. package/dist/core/reference-dom-facts.d.ts +65 -0
  39. package/dist/core/reference-dom-facts.js +71 -0
  40. package/dist/core/reference-dom-facts.js.map +1 -0
  41. package/dist/core/report-writer.d.ts +43 -0
  42. package/dist/core/report-writer.js +181 -0
  43. package/dist/core/report-writer.js.map +1 -0
  44. package/dist/core/run-logger.d.ts +22 -0
  45. package/dist/core/run-logger.js +67 -0
  46. package/dist/core/run-logger.js.map +1 -0
  47. package/dist/core/side-by-side.d.ts +8 -0
  48. package/dist/core/side-by-side.js +33 -0
  49. package/dist/core/side-by-side.js.map +1 -0
  50. package/dist/core/static-server.d.ts +6 -0
  51. package/dist/core/static-server.js +73 -0
  52. package/dist/core/static-server.js.map +1 -0
  53. package/dist/core/visual-spec-agent-pack.d.ts +27 -0
  54. package/dist/core/visual-spec-agent-pack.js +143 -0
  55. package/dist/core/visual-spec-agent-pack.js.map +1 -0
  56. package/dist/core/visual-spec-prompts.d.ts +32 -0
  57. package/dist/core/visual-spec-prompts.js +129 -0
  58. package/dist/core/visual-spec-prompts.js.map +1 -0
  59. package/dist/core/workspace.d.ts +31 -0
  60. package/dist/core/workspace.js +97 -0
  61. package/dist/core/workspace.js.map +1 -0
  62. package/dist/index.d.ts +14 -0
  63. package/dist/index.js +12 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/schemas/contract.d.ts +43 -0
  66. package/dist/schemas/contract.js +19 -0
  67. package/dist/schemas/contract.js.map +1 -0
  68. package/dist/schemas/events.d.ts +34 -0
  69. package/dist/schemas/events.js +29 -0
  70. package/dist/schemas/events.js.map +1 -0
  71. package/dist/schemas/visual-spec.d.ts +410 -0
  72. package/dist/schemas/visual-spec.js +201 -0
  73. package/dist/schemas/visual-spec.js.map +1 -0
  74. package/docs/agent-workflow.md +45 -0
  75. package/package.json +64 -0
  76. package/skills/limner/SKILL.md +51 -0
  77. package/templates/target/AGENT_GUIDE.md +24 -0
  78. package/templates/target/contract/acceptance.md +23 -0
  79. package/templates/target/contract/regions.json +11 -0
  80. package/templates/target/contract/tokens.json +21 -0
  81. package/templates/target/reference/index.html +22 -0
  82. package/templates/target/reference/styles.css +53 -0
@@ -0,0 +1,410 @@
1
+ import { z } from 'zod';
2
+ export declare const visualSpecSchema: z.ZodObject<{
3
+ version: z.ZodLiteral<1>;
4
+ source: z.ZodEnum<{
5
+ "ideal-image": "ideal-image";
6
+ "reference-html": "reference-html";
7
+ }>;
8
+ summary: z.ZodString;
9
+ viewport: z.ZodObject<{
10
+ kind: z.ZodEnum<{
11
+ desktop: "desktop";
12
+ mobile: "mobile";
13
+ }>;
14
+ widthHint: z.ZodOptional<z.ZodNumber>;
15
+ heightHint: z.ZodOptional<z.ZodNumber>;
16
+ }, z.core.$strip>;
17
+ layout: z.ZodObject<{
18
+ flow: z.ZodEnum<{
19
+ unknown: "unknown";
20
+ split: "split";
21
+ "single-column": "single-column";
22
+ "multi-column": "multi-column";
23
+ stacked: "stacked";
24
+ }>;
25
+ alignment: z.ZodEnum<{
26
+ unknown: "unknown";
27
+ left: "left";
28
+ centered: "centered";
29
+ mixed: "mixed";
30
+ }>;
31
+ density: z.ZodEnum<{
32
+ unknown: "unknown";
33
+ airy: "airy";
34
+ balanced: "balanced";
35
+ dense: "dense";
36
+ }>;
37
+ regions: z.ZodArray<z.ZodObject<{
38
+ id: z.ZodString;
39
+ label: z.ZodString;
40
+ role: z.ZodEnum<{
41
+ unknown: "unknown";
42
+ status: "status";
43
+ header: "header";
44
+ hero: "hero";
45
+ content: "content";
46
+ panel: "panel";
47
+ footer: "footer";
48
+ control: "control";
49
+ }>;
50
+ description: z.ZodString;
51
+ relativeBounds: z.ZodOptional<z.ZodObject<{
52
+ x: z.ZodNumber;
53
+ y: z.ZodNumber;
54
+ width: z.ZodNumber;
55
+ height: z.ZodNumber;
56
+ }, z.core.$strip>>;
57
+ evidence: z.ZodArray<z.ZodString>;
58
+ }, z.core.$strip>>;
59
+ navigation: z.ZodObject<{
60
+ header: z.ZodBoolean;
61
+ footer: z.ZodBoolean;
62
+ progressIndicator: z.ZodOptional<z.ZodString>;
63
+ }, z.core.$strip>;
64
+ }, z.core.$strip>;
65
+ typography: z.ZodObject<{
66
+ families: z.ZodArray<z.ZodString>;
67
+ scales: z.ZodArray<z.ZodObject<{
68
+ label: z.ZodEnum<{
69
+ body: "body";
70
+ eyebrow: "eyebrow";
71
+ heading: "heading";
72
+ subheading: "subheading";
73
+ caption: "caption";
74
+ cta: "cta";
75
+ meta: "meta";
76
+ }>;
77
+ size: z.ZodEnum<{
78
+ xs: "xs";
79
+ sm: "sm";
80
+ md: "md";
81
+ lg: "lg";
82
+ xl: "xl";
83
+ xxl: "xxl";
84
+ }>;
85
+ weight: z.ZodEnum<{
86
+ bold: "bold";
87
+ regular: "regular";
88
+ medium: "medium";
89
+ semibold: "semibold";
90
+ }>;
91
+ usage: z.ZodString;
92
+ }, z.core.$strip>>;
93
+ hierarchyNotes: z.ZodArray<z.ZodString>;
94
+ }, z.core.$strip>;
95
+ color: z.ZodObject<{
96
+ tone: z.ZodEnum<{
97
+ unknown: "unknown";
98
+ mixed: "mixed";
99
+ dark: "dark";
100
+ light: "light";
101
+ }>;
102
+ tokens: z.ZodArray<z.ZodObject<{
103
+ name: z.ZodString;
104
+ value: z.ZodString;
105
+ usage: z.ZodString;
106
+ }, z.core.$strip>>;
107
+ accents: z.ZodArray<z.ZodString>;
108
+ }, z.core.$strip>;
109
+ hierarchy: z.ZodObject<{
110
+ primaryFocus: z.ZodString;
111
+ primaryActions: z.ZodArray<z.ZodString>;
112
+ secondaryActions: z.ZodArray<z.ZodString>;
113
+ warningStates: z.ZodArray<z.ZodString>;
114
+ }, z.core.$strip>;
115
+ semantics: z.ZodObject<{
116
+ states: z.ZodArray<z.ZodObject<{
117
+ element: z.ZodString;
118
+ state: z.ZodString;
119
+ evidence: z.ZodString;
120
+ }, z.core.$strip>>;
121
+ mobileBehavior: z.ZodArray<z.ZodString>;
122
+ risks: z.ZodArray<z.ZodString>;
123
+ }, z.core.$strip>;
124
+ evidence: z.ZodArray<z.ZodString>;
125
+ }, z.core.$strip>;
126
+ export declare const visualSpecDiffSchema: z.ZodObject<{
127
+ summary: z.ZodString;
128
+ matches: z.ZodArray<z.ZodString>;
129
+ mismatches: z.ZodArray<z.ZodObject<{
130
+ area: z.ZodString;
131
+ ideal: z.ZodString;
132
+ reference: z.ZodString;
133
+ impact: z.ZodString;
134
+ severity: z.ZodEnum<{
135
+ medium: "medium";
136
+ high: "high";
137
+ low: "low";
138
+ }>;
139
+ }, z.core.$strip>>;
140
+ openQuestions: z.ZodArray<z.ZodString>;
141
+ nextFixes: z.ZodArray<z.ZodString>;
142
+ }, z.core.$strip>;
143
+ export declare const visualSpecBundleSchema: z.ZodObject<{
144
+ version: z.ZodLiteral<1>;
145
+ generatedBy: z.ZodLiteral<"agent">;
146
+ idealSpec: z.ZodObject<{
147
+ version: z.ZodLiteral<1>;
148
+ summary: z.ZodString;
149
+ viewport: z.ZodObject<{
150
+ kind: z.ZodEnum<{
151
+ desktop: "desktop";
152
+ mobile: "mobile";
153
+ }>;
154
+ widthHint: z.ZodOptional<z.ZodNumber>;
155
+ heightHint: z.ZodOptional<z.ZodNumber>;
156
+ }, z.core.$strip>;
157
+ layout: z.ZodObject<{
158
+ flow: z.ZodEnum<{
159
+ unknown: "unknown";
160
+ split: "split";
161
+ "single-column": "single-column";
162
+ "multi-column": "multi-column";
163
+ stacked: "stacked";
164
+ }>;
165
+ alignment: z.ZodEnum<{
166
+ unknown: "unknown";
167
+ left: "left";
168
+ centered: "centered";
169
+ mixed: "mixed";
170
+ }>;
171
+ density: z.ZodEnum<{
172
+ unknown: "unknown";
173
+ airy: "airy";
174
+ balanced: "balanced";
175
+ dense: "dense";
176
+ }>;
177
+ regions: z.ZodArray<z.ZodObject<{
178
+ id: z.ZodString;
179
+ label: z.ZodString;
180
+ role: z.ZodEnum<{
181
+ unknown: "unknown";
182
+ status: "status";
183
+ header: "header";
184
+ hero: "hero";
185
+ content: "content";
186
+ panel: "panel";
187
+ footer: "footer";
188
+ control: "control";
189
+ }>;
190
+ description: z.ZodString;
191
+ relativeBounds: z.ZodOptional<z.ZodObject<{
192
+ x: z.ZodNumber;
193
+ y: z.ZodNumber;
194
+ width: z.ZodNumber;
195
+ height: z.ZodNumber;
196
+ }, z.core.$strip>>;
197
+ evidence: z.ZodArray<z.ZodString>;
198
+ }, z.core.$strip>>;
199
+ navigation: z.ZodObject<{
200
+ header: z.ZodBoolean;
201
+ footer: z.ZodBoolean;
202
+ progressIndicator: z.ZodOptional<z.ZodString>;
203
+ }, z.core.$strip>;
204
+ }, z.core.$strip>;
205
+ typography: z.ZodObject<{
206
+ families: z.ZodArray<z.ZodString>;
207
+ scales: z.ZodArray<z.ZodObject<{
208
+ label: z.ZodEnum<{
209
+ body: "body";
210
+ eyebrow: "eyebrow";
211
+ heading: "heading";
212
+ subheading: "subheading";
213
+ caption: "caption";
214
+ cta: "cta";
215
+ meta: "meta";
216
+ }>;
217
+ size: z.ZodEnum<{
218
+ xs: "xs";
219
+ sm: "sm";
220
+ md: "md";
221
+ lg: "lg";
222
+ xl: "xl";
223
+ xxl: "xxl";
224
+ }>;
225
+ weight: z.ZodEnum<{
226
+ bold: "bold";
227
+ regular: "regular";
228
+ medium: "medium";
229
+ semibold: "semibold";
230
+ }>;
231
+ usage: z.ZodString;
232
+ }, z.core.$strip>>;
233
+ hierarchyNotes: z.ZodArray<z.ZodString>;
234
+ }, z.core.$strip>;
235
+ color: z.ZodObject<{
236
+ tone: z.ZodEnum<{
237
+ unknown: "unknown";
238
+ mixed: "mixed";
239
+ dark: "dark";
240
+ light: "light";
241
+ }>;
242
+ tokens: z.ZodArray<z.ZodObject<{
243
+ name: z.ZodString;
244
+ value: z.ZodString;
245
+ usage: z.ZodString;
246
+ }, z.core.$strip>>;
247
+ accents: z.ZodArray<z.ZodString>;
248
+ }, z.core.$strip>;
249
+ hierarchy: z.ZodObject<{
250
+ primaryFocus: z.ZodString;
251
+ primaryActions: z.ZodArray<z.ZodString>;
252
+ secondaryActions: z.ZodArray<z.ZodString>;
253
+ warningStates: z.ZodArray<z.ZodString>;
254
+ }, z.core.$strip>;
255
+ semantics: z.ZodObject<{
256
+ states: z.ZodArray<z.ZodObject<{
257
+ element: z.ZodString;
258
+ state: z.ZodString;
259
+ evidence: z.ZodString;
260
+ }, z.core.$strip>>;
261
+ mobileBehavior: z.ZodArray<z.ZodString>;
262
+ risks: z.ZodArray<z.ZodString>;
263
+ }, z.core.$strip>;
264
+ evidence: z.ZodArray<z.ZodString>;
265
+ source: z.ZodLiteral<"ideal-image">;
266
+ }, z.core.$strip>;
267
+ referenceSpec: z.ZodObject<{
268
+ version: z.ZodLiteral<1>;
269
+ summary: z.ZodString;
270
+ viewport: z.ZodObject<{
271
+ kind: z.ZodEnum<{
272
+ desktop: "desktop";
273
+ mobile: "mobile";
274
+ }>;
275
+ widthHint: z.ZodOptional<z.ZodNumber>;
276
+ heightHint: z.ZodOptional<z.ZodNumber>;
277
+ }, z.core.$strip>;
278
+ layout: z.ZodObject<{
279
+ flow: z.ZodEnum<{
280
+ unknown: "unknown";
281
+ split: "split";
282
+ "single-column": "single-column";
283
+ "multi-column": "multi-column";
284
+ stacked: "stacked";
285
+ }>;
286
+ alignment: z.ZodEnum<{
287
+ unknown: "unknown";
288
+ left: "left";
289
+ centered: "centered";
290
+ mixed: "mixed";
291
+ }>;
292
+ density: z.ZodEnum<{
293
+ unknown: "unknown";
294
+ airy: "airy";
295
+ balanced: "balanced";
296
+ dense: "dense";
297
+ }>;
298
+ regions: z.ZodArray<z.ZodObject<{
299
+ id: z.ZodString;
300
+ label: z.ZodString;
301
+ role: z.ZodEnum<{
302
+ unknown: "unknown";
303
+ status: "status";
304
+ header: "header";
305
+ hero: "hero";
306
+ content: "content";
307
+ panel: "panel";
308
+ footer: "footer";
309
+ control: "control";
310
+ }>;
311
+ description: z.ZodString;
312
+ relativeBounds: z.ZodOptional<z.ZodObject<{
313
+ x: z.ZodNumber;
314
+ y: z.ZodNumber;
315
+ width: z.ZodNumber;
316
+ height: z.ZodNumber;
317
+ }, z.core.$strip>>;
318
+ evidence: z.ZodArray<z.ZodString>;
319
+ }, z.core.$strip>>;
320
+ navigation: z.ZodObject<{
321
+ header: z.ZodBoolean;
322
+ footer: z.ZodBoolean;
323
+ progressIndicator: z.ZodOptional<z.ZodString>;
324
+ }, z.core.$strip>;
325
+ }, z.core.$strip>;
326
+ typography: z.ZodObject<{
327
+ families: z.ZodArray<z.ZodString>;
328
+ scales: z.ZodArray<z.ZodObject<{
329
+ label: z.ZodEnum<{
330
+ body: "body";
331
+ eyebrow: "eyebrow";
332
+ heading: "heading";
333
+ subheading: "subheading";
334
+ caption: "caption";
335
+ cta: "cta";
336
+ meta: "meta";
337
+ }>;
338
+ size: z.ZodEnum<{
339
+ xs: "xs";
340
+ sm: "sm";
341
+ md: "md";
342
+ lg: "lg";
343
+ xl: "xl";
344
+ xxl: "xxl";
345
+ }>;
346
+ weight: z.ZodEnum<{
347
+ bold: "bold";
348
+ regular: "regular";
349
+ medium: "medium";
350
+ semibold: "semibold";
351
+ }>;
352
+ usage: z.ZodString;
353
+ }, z.core.$strip>>;
354
+ hierarchyNotes: z.ZodArray<z.ZodString>;
355
+ }, z.core.$strip>;
356
+ color: z.ZodObject<{
357
+ tone: z.ZodEnum<{
358
+ unknown: "unknown";
359
+ mixed: "mixed";
360
+ dark: "dark";
361
+ light: "light";
362
+ }>;
363
+ tokens: z.ZodArray<z.ZodObject<{
364
+ name: z.ZodString;
365
+ value: z.ZodString;
366
+ usage: z.ZodString;
367
+ }, z.core.$strip>>;
368
+ accents: z.ZodArray<z.ZodString>;
369
+ }, z.core.$strip>;
370
+ hierarchy: z.ZodObject<{
371
+ primaryFocus: z.ZodString;
372
+ primaryActions: z.ZodArray<z.ZodString>;
373
+ secondaryActions: z.ZodArray<z.ZodString>;
374
+ warningStates: z.ZodArray<z.ZodString>;
375
+ }, z.core.$strip>;
376
+ semantics: z.ZodObject<{
377
+ states: z.ZodArray<z.ZodObject<{
378
+ element: z.ZodString;
379
+ state: z.ZodString;
380
+ evidence: z.ZodString;
381
+ }, z.core.$strip>>;
382
+ mobileBehavior: z.ZodArray<z.ZodString>;
383
+ risks: z.ZodArray<z.ZodString>;
384
+ }, z.core.$strip>;
385
+ evidence: z.ZodArray<z.ZodString>;
386
+ source: z.ZodLiteral<"reference-html">;
387
+ }, z.core.$strip>;
388
+ diff: z.ZodObject<{
389
+ summary: z.ZodString;
390
+ matches: z.ZodArray<z.ZodString>;
391
+ mismatches: z.ZodArray<z.ZodObject<{
392
+ area: z.ZodString;
393
+ ideal: z.ZodString;
394
+ reference: z.ZodString;
395
+ impact: z.ZodString;
396
+ severity: z.ZodEnum<{
397
+ medium: "medium";
398
+ high: "high";
399
+ low: "low";
400
+ }>;
401
+ }, z.core.$strip>>;
402
+ openQuestions: z.ZodArray<z.ZodString>;
403
+ nextFixes: z.ZodArray<z.ZodString>;
404
+ }, z.core.$strip>;
405
+ }, z.core.$strip>;
406
+ export type VisualSpec = z.infer<typeof visualSpecSchema>;
407
+ export type VisualSpecDiff = z.infer<typeof visualSpecDiffSchema>;
408
+ export type VisualSpecBundle = z.infer<typeof visualSpecBundleSchema>;
409
+ export declare function createVisualSpecJsonSchema(): unknown;
410
+ export declare function createVisualSpecBundleExample(): VisualSpecBundle;
@@ -0,0 +1,201 @@
1
+ import { z } from 'zod';
2
+ const relativeBoundsSchema = z.object({
3
+ x: z.number().min(0).max(1),
4
+ y: z.number().min(0).max(1),
5
+ width: z.number().min(0).max(1),
6
+ height: z.number().min(0).max(1),
7
+ });
8
+ const regionSchema = z.object({
9
+ id: z.string().min(1),
10
+ label: z.string().min(1),
11
+ role: z.enum(['header', 'hero', 'content', 'panel', 'footer', 'control', 'status', 'unknown']),
12
+ description: z.string().min(1),
13
+ relativeBounds: relativeBoundsSchema.optional(),
14
+ evidence: z.array(z.string()).min(1),
15
+ });
16
+ const scaleSchema = z.object({
17
+ label: z.enum(['eyebrow', 'heading', 'subheading', 'body', 'caption', 'cta', 'meta']),
18
+ size: z.enum(['xs', 'sm', 'md', 'lg', 'xl', 'xxl']),
19
+ weight: z.enum(['regular', 'medium', 'semibold', 'bold']),
20
+ usage: z.string().min(1),
21
+ });
22
+ const colorTokenSchema = z.object({
23
+ name: z.string().min(1),
24
+ value: z.string().min(1),
25
+ usage: z.string().min(1),
26
+ });
27
+ const stateSchema = z.object({
28
+ element: z.string().min(1),
29
+ state: z.string().min(1),
30
+ evidence: z.string().min(1),
31
+ });
32
+ export const visualSpecSchema = z.object({
33
+ version: z.literal(1),
34
+ source: z.enum(['ideal-image', 'reference-html']),
35
+ summary: z.string().min(1),
36
+ viewport: z.object({
37
+ kind: z.enum(['desktop', 'mobile']),
38
+ widthHint: z.number().int().positive().optional(),
39
+ heightHint: z.number().int().positive().optional(),
40
+ }),
41
+ layout: z.object({
42
+ flow: z.enum(['single-column', 'multi-column', 'split', 'stacked', 'unknown']),
43
+ alignment: z.enum(['left', 'centered', 'mixed', 'unknown']),
44
+ density: z.enum(['airy', 'balanced', 'dense', 'unknown']),
45
+ regions: z.array(regionSchema).min(1),
46
+ navigation: z.object({
47
+ header: z.boolean(),
48
+ footer: z.boolean(),
49
+ progressIndicator: z.string().optional(),
50
+ }),
51
+ }),
52
+ typography: z.object({
53
+ families: z.array(z.string()).min(1),
54
+ scales: z.array(scaleSchema).min(1),
55
+ hierarchyNotes: z.array(z.string()).min(1),
56
+ }),
57
+ color: z.object({
58
+ tone: z.enum(['dark', 'light', 'mixed', 'unknown']),
59
+ tokens: z.array(colorTokenSchema).min(1),
60
+ accents: z.array(z.string()).min(1),
61
+ }),
62
+ hierarchy: z.object({
63
+ primaryFocus: z.string().min(1),
64
+ primaryActions: z.array(z.string()),
65
+ secondaryActions: z.array(z.string()),
66
+ warningStates: z.array(z.string()),
67
+ }),
68
+ semantics: z.object({
69
+ states: z.array(stateSchema),
70
+ mobileBehavior: z.array(z.string()),
71
+ risks: z.array(z.string()).min(1),
72
+ }),
73
+ evidence: z.array(z.string()).min(1),
74
+ });
75
+ export const visualSpecDiffSchema = z.object({
76
+ summary: z.string().min(1),
77
+ matches: z.array(z.string()),
78
+ mismatches: z.array(z.object({
79
+ area: z.string().min(1),
80
+ ideal: z.string().min(1),
81
+ reference: z.string().min(1),
82
+ impact: z.string().min(1),
83
+ severity: z.enum(['high', 'medium', 'low']),
84
+ })).min(1),
85
+ openQuestions: z.array(z.string()),
86
+ nextFixes: z.array(z.string()).min(1),
87
+ });
88
+ export const visualSpecBundleSchema = z.object({
89
+ version: z.literal(1),
90
+ generatedBy: z.literal('agent'),
91
+ idealSpec: visualSpecSchema.extend({ source: z.literal('ideal-image') }),
92
+ referenceSpec: visualSpecSchema.extend({ source: z.literal('reference-html') }),
93
+ diff: visualSpecDiffSchema,
94
+ });
95
+ export function createVisualSpecJsonSchema() {
96
+ return z.toJSONSchema(visualSpecBundleSchema);
97
+ }
98
+ export function createVisualSpecBundleExample() {
99
+ return {
100
+ version: 1,
101
+ generatedBy: 'agent',
102
+ idealSpec: {
103
+ version: 1,
104
+ source: 'ideal-image',
105
+ summary: 'Replace with a concise summary of the ideal image.',
106
+ viewport: { kind: 'desktop', widthHint: 1440, heightHint: 900 },
107
+ layout: {
108
+ flow: 'single-column',
109
+ alignment: 'centered',
110
+ density: 'balanced',
111
+ regions: [{
112
+ id: 'hero',
113
+ label: 'Hero section',
114
+ role: 'hero',
115
+ description: 'Primary heading and explanatory copy.',
116
+ relativeBounds: { x: 0.2, y: 0.15, width: 0.6, height: 0.18 },
117
+ evidence: ['Large centered heading near the top of the screen.'],
118
+ }],
119
+ navigation: { header: true, footer: true, progressIndicator: 'Three-step progress header.' },
120
+ },
121
+ typography: {
122
+ families: ['Serif display for the main heading', 'Sans-serif for body and controls'],
123
+ scales: [{ label: 'heading', size: 'xxl', weight: 'bold', usage: 'Main page title' }],
124
+ hierarchyNotes: ['Heading is clearly dominant over surrounding body copy.'],
125
+ },
126
+ color: {
127
+ tone: 'dark',
128
+ tokens: [{ name: 'accent', value: 'warm gold', usage: 'Primary CTA and status emphasis' }],
129
+ accents: ['warm gold', 'orange warning'],
130
+ },
131
+ hierarchy: {
132
+ primaryFocus: 'Readiness-blocking seat warning and the add-seats CTA.',
133
+ primaryActions: ['Add 5 tables of 8 seats'],
134
+ secondaryActions: ['Back to previous step'],
135
+ warningStates: ['Need 40 more seats before readiness'],
136
+ },
137
+ semantics: {
138
+ states: [{ element: 'Continue action', state: 'disabled', evidence: 'Copy indicates seats must be added first.' }],
139
+ mobileBehavior: [],
140
+ risks: ['Heading, warning, and CTA ordering must remain intact.'],
141
+ },
142
+ evidence: ['Observed in ideal image.', 'Cross-checked against side-by-side capture.'],
143
+ },
144
+ referenceSpec: {
145
+ version: 1,
146
+ source: 'reference-html',
147
+ summary: 'Replace with a concise summary of the rendered reference.',
148
+ viewport: { kind: 'desktop', widthHint: 1440, heightHint: 900 },
149
+ layout: {
150
+ flow: 'single-column',
151
+ alignment: 'centered',
152
+ density: 'balanced',
153
+ regions: [{
154
+ id: 'hero',
155
+ label: 'Hero section',
156
+ role: 'hero',
157
+ description: 'Primary heading and explanatory copy.',
158
+ relativeBounds: { x: 0.2, y: 0.15, width: 0.6, height: 0.18 },
159
+ evidence: ['Seen in rendered reference screenshot.', 'Supported by reference DOM facts.'],
160
+ }],
161
+ navigation: { header: true, footer: true, progressIndicator: 'Three-step progress header.' },
162
+ },
163
+ typography: {
164
+ families: ['Serif display for the main heading', 'Sans-serif for body and controls'],
165
+ scales: [{ label: 'heading', size: 'xl', weight: 'medium', usage: 'Main page title in rendered reference' }],
166
+ hierarchyNotes: ['Heading is slightly lighter than the ideal.'],
167
+ },
168
+ color: {
169
+ tone: 'dark',
170
+ tokens: [{ name: 'accent', value: '#f2bd6d', usage: 'Primary CTA and status emphasis' }],
171
+ accents: ['#f2bd6d', '#ff784f'],
172
+ },
173
+ hierarchy: {
174
+ primaryFocus: 'Readiness warning and CTA remain the main focus.',
175
+ primaryActions: ['Add 5 tables of 8 seats', 'Add one table'],
176
+ secondaryActions: ['Back to previous step'],
177
+ warningStates: ['Need 40 more seats before readiness'],
178
+ },
179
+ semantics: {
180
+ states: [{ element: 'Continue action', state: 'disabled', evidence: 'Rendered disabled button copy is present.' }],
181
+ mobileBehavior: [],
182
+ risks: ['Heading weight may be too soft compared with the ideal.'],
183
+ },
184
+ evidence: ['Observed in rendered reference screenshot.', 'Cross-checked with DOM facts.'],
185
+ },
186
+ diff: {
187
+ summary: 'Replace with the highest-signal summary of the differences.',
188
+ matches: ['Dark tonal palette matches.', 'Primary warning plus CTA structure is preserved.'],
189
+ mismatches: [{
190
+ area: 'Heading weight',
191
+ ideal: 'Heavy, high-contrast serif heading.',
192
+ reference: 'Softer serif heading with less visual pull.',
193
+ impact: 'The hero loses urgency and visual authority.',
194
+ severity: 'medium',
195
+ }],
196
+ openQuestions: ['Is the softer heading weight intentional or an implementation drift?'],
197
+ nextFixes: ['Increase hero heading weight and contrast before tuning smaller controls.'],
198
+ },
199
+ };
200
+ }
201
+ //# sourceMappingURL=visual-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-spec.js","sourceRoot":"","sources":["../../src/schemas/visual-spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ # Agent Workflow
2
+
3
+ Limner is designed for agent-in-the-loop visual fidelity work.
4
+
5
+ ## Phase 1: Image To Reference
6
+
7
+ 1. Run `limn init <image> --target <name>`.
8
+ 2. Inspect `targets/<name>/source/`.
9
+ 3. Edit `contract/regions.json`, `contract/tokens.json`, and `contract/acceptance.md`.
10
+ 4. Rebuild `reference/index.html` and `reference/styles.css` as a faithful HTML facsimile.
11
+ 5. Run `limn compare image-reference --target <name>`.
12
+ 6. Optional: run `limn compare image-reference --target <name> --spec` to generate an agent-required visual spec prompt pack.
13
+ 7. Edit `contract/visual-spec-instructions.md` for target-specific prompt guidance, or pass `--spec-instructions <path>` for a shared prompt policy.
14
+ 8. If using Codex, start from `captures/image-reference/spec/agent-prompt.codex.md`.
15
+ 9. If using Claude, start from `captures/image-reference/spec/agent-prompt.claude.md` and attach the images it references.
16
+ 10. Have the agent write `captures/image-reference/spec/agent-response.json`, then rerun the command to validate and split the structured output.
17
+ 11. Instruct the agent to inspect the ideal image and reference screenshot separately; use the side-by-side only as comparison context.
18
+ 12. Open `captures/image-reference/side-by-side.png`.
19
+ 13. Record concrete mismatches in `reports/image-reference.md`.
20
+ 14. Iterate until the reference is approved.
21
+
22
+ ## Phase 2: Reference To App
23
+
24
+ 1. Add app selectors to `contract/regions.json`.
25
+ 2. Run `limn compare reference-app --target <name> --url <app-url>`.
26
+ 3. Open `captures/reference-app/side-by-side.png`.
27
+ 4. Inspect `captures/reference-app/dom-metrics.json`.
28
+ 5. Record app repair steps in `reports/reference-app.md`.
29
+ 6. Fix the app and rerun until the app matches the approved reference.
30
+
31
+ ## Optional Grounding: Image To App
32
+
33
+ Use this when you need to confirm that the app URL, authentication state, and viewport are correct before building the HTML reference.
34
+
35
+ ```bash
36
+ limn compare image-app --target <name> --url <app-url> --storage-state ./e2e/.auth/user.json
37
+ ```
38
+
39
+ This is not a replacement for Phase 1. For design reconstruction work, first recreate the generated image in `reference/index.html` and compare with `image-reference`.
40
+
41
+ Capture defaults to viewport-only. Add `--full-page` only when the generated image is meant to represent the full scrollable page.
42
+
43
+ ## Agent Rule
44
+
45
+ Do not treat side-by-side generation as success. It is evidence. The agent still needs to compare regions, name mismatches, and decide the next scoped fix.