@rolepod/uiproof 0.4.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.
@@ -0,0 +1,918 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import { Page } from 'playwright';
4
+
5
+ /**
6
+ * Writes artifacts under `./.rolepod-uiproof/artifacts/{run_id}/` (D-026).
7
+ *
8
+ * v0.1 emits two formats: PNG screenshots and a JSON replay bundle. Future
9
+ * milestones extend the format set (HAR, console log, a11y tree, video).
10
+ */
11
+ type ReplayStep = Record<string, unknown>;
12
+ type ReplayBundle = {
13
+ version: 1;
14
+ run_id: string;
15
+ recorded_at: string;
16
+ open: Record<string, unknown>;
17
+ steps: ReplayStep[];
18
+ expect: ReplayStep[];
19
+ };
20
+ declare class ArtifactStore {
21
+ readonly rootDir: string;
22
+ constructor(opts?: {
23
+ rootDir?: string;
24
+ });
25
+ /** Allocate a fresh run id and ensure its directory exists. */
26
+ startRun(prefix?: string): Promise<{
27
+ runId: string;
28
+ runDir: string;
29
+ }>;
30
+ writeScreenshot(runDir: string, buf: Buffer, name: string): Promise<string>;
31
+ writeReplayBundle(runDir: string, bundle: ReplayBundle, name?: string): Promise<string>;
32
+ writeReport(runDir: string, name: string, body: string): Promise<string>;
33
+ writeBytes(runDir: string, name: string, buf: Buffer): Promise<string>;
34
+ ensureDir(absDir: string): Promise<string>;
35
+ /** Root for stored visual baselines: `./.rolepod-uiproof/baselines/`. */
36
+ get baselineDir(): string;
37
+ private timestampSlug;
38
+ }
39
+
40
+ declare const bboxSchema: z.ZodObject<{
41
+ x: z.ZodNumber;
42
+ y: z.ZodNumber;
43
+ w: z.ZodNumber;
44
+ h: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ declare const a11yStateSchema: z.ZodObject<{
47
+ focused: z.ZodOptional<z.ZodBoolean>;
48
+ selected: z.ZodOptional<z.ZodBoolean>;
49
+ expanded: z.ZodOptional<z.ZodBoolean>;
50
+ disabled: z.ZodOptional<z.ZodBoolean>;
51
+ }, z.core.$strip>;
52
+ type A11yNode = {
53
+ ref: string;
54
+ role: string;
55
+ name?: string;
56
+ value?: string;
57
+ state?: z.infer<typeof a11yStateSchema>;
58
+ bbox?: z.infer<typeof bboxSchema>;
59
+ children?: A11yNode[];
60
+ };
61
+ declare const browserOpenShape: {
62
+ readonly platform: z.ZodDefault<z.ZodEnum<{
63
+ web: "web";
64
+ ios: "ios";
65
+ android: "android";
66
+ }>>;
67
+ readonly url: z.ZodOptional<z.ZodString>;
68
+ readonly browser: z.ZodOptional<z.ZodEnum<{
69
+ chromium: "chromium";
70
+ firefox: "firefox";
71
+ webkit: "webkit";
72
+ }>>;
73
+ readonly viewport: z.ZodOptional<z.ZodObject<{
74
+ width: z.ZodNumber;
75
+ height: z.ZodNumber;
76
+ }, z.core.$strip>>;
77
+ readonly bundle_id: z.ZodOptional<z.ZodString>;
78
+ readonly device: z.ZodOptional<z.ZodString>;
79
+ readonly app_package: z.ZodOptional<z.ZodString>;
80
+ readonly app_activity: z.ZodOptional<z.ZodString>;
81
+ readonly emulator: z.ZodOptional<z.ZodString>;
82
+ readonly headless: z.ZodOptional<z.ZodBoolean>;
83
+ readonly user_agent: z.ZodOptional<z.ZodString>;
84
+ readonly locale: z.ZodOptional<z.ZodString>;
85
+ };
86
+ declare const browserOpenSchema: z.ZodObject<{
87
+ platform: z.ZodDefault<z.ZodEnum<{
88
+ web: "web";
89
+ ios: "ios";
90
+ android: "android";
91
+ }>>;
92
+ url: z.ZodOptional<z.ZodString>;
93
+ browser: z.ZodOptional<z.ZodEnum<{
94
+ chromium: "chromium";
95
+ firefox: "firefox";
96
+ webkit: "webkit";
97
+ }>>;
98
+ viewport: z.ZodOptional<z.ZodObject<{
99
+ width: z.ZodNumber;
100
+ height: z.ZodNumber;
101
+ }, z.core.$strip>>;
102
+ bundle_id: z.ZodOptional<z.ZodString>;
103
+ device: z.ZodOptional<z.ZodString>;
104
+ app_package: z.ZodOptional<z.ZodString>;
105
+ app_activity: z.ZodOptional<z.ZodString>;
106
+ emulator: z.ZodOptional<z.ZodString>;
107
+ headless: z.ZodOptional<z.ZodBoolean>;
108
+ user_agent: z.ZodOptional<z.ZodString>;
109
+ locale: z.ZodOptional<z.ZodString>;
110
+ }, z.core.$strip>;
111
+ declare const browserCloseShape: {
112
+ readonly session_id: z.ZodString;
113
+ };
114
+ declare const browserCloseSchema: z.ZodObject<{
115
+ session_id: z.ZodString;
116
+ }, z.core.$strip>;
117
+ declare const browserSnapshotShape: {
118
+ readonly session_id: z.ZodString;
119
+ readonly mode: z.ZodOptional<z.ZodEnum<{
120
+ visible: "visible";
121
+ full: "full";
122
+ }>>;
123
+ };
124
+ declare const browserSnapshotSchema: z.ZodObject<{
125
+ session_id: z.ZodString;
126
+ mode: z.ZodOptional<z.ZodEnum<{
127
+ visible: "visible";
128
+ full: "full";
129
+ }>>;
130
+ }, z.core.$strip>;
131
+ declare const browserClickShape: {
132
+ readonly session_id: z.ZodString;
133
+ readonly ref: z.ZodString;
134
+ readonly button: z.ZodOptional<z.ZodEnum<{
135
+ left: "left";
136
+ right: "right";
137
+ middle: "middle";
138
+ }>>;
139
+ };
140
+ declare const browserClickSchema: z.ZodObject<{
141
+ session_id: z.ZodString;
142
+ ref: z.ZodString;
143
+ button: z.ZodOptional<z.ZodEnum<{
144
+ left: "left";
145
+ right: "right";
146
+ middle: "middle";
147
+ }>>;
148
+ }, z.core.$strip>;
149
+ declare const browserTypeShape: {
150
+ readonly session_id: z.ZodString;
151
+ readonly ref: z.ZodString;
152
+ readonly text: z.ZodString;
153
+ readonly clear_first: z.ZodOptional<z.ZodBoolean>;
154
+ };
155
+ declare const browserTypeSchema: z.ZodObject<{
156
+ session_id: z.ZodString;
157
+ ref: z.ZodString;
158
+ text: z.ZodString;
159
+ clear_first: z.ZodOptional<z.ZodBoolean>;
160
+ }, z.core.$strip>;
161
+ declare const browserKeyShape: {
162
+ readonly session_id: z.ZodString;
163
+ readonly key: z.ZodString;
164
+ };
165
+ declare const browserKeySchema: z.ZodObject<{
166
+ session_id: z.ZodString;
167
+ key: z.ZodString;
168
+ }, z.core.$strip>;
169
+ declare const browserScrollShape: {
170
+ readonly session_id: z.ZodString;
171
+ readonly direction: z.ZodEnum<{
172
+ left: "left";
173
+ right: "right";
174
+ up: "up";
175
+ down: "down";
176
+ }>;
177
+ readonly amount: z.ZodOptional<z.ZodNumber>;
178
+ readonly ref: z.ZodOptional<z.ZodString>;
179
+ };
180
+ declare const browserScrollSchema: z.ZodObject<{
181
+ session_id: z.ZodString;
182
+ direction: z.ZodEnum<{
183
+ left: "left";
184
+ right: "right";
185
+ up: "up";
186
+ down: "down";
187
+ }>;
188
+ amount: z.ZodOptional<z.ZodNumber>;
189
+ ref: z.ZodOptional<z.ZodString>;
190
+ }, z.core.$strip>;
191
+ declare const browserWaitForShape: {
192
+ readonly session_id: z.ZodString;
193
+ readonly condition: z.ZodDiscriminatedUnion<[z.ZodObject<{
194
+ kind: z.ZodLiteral<"text_visible">;
195
+ text: z.ZodString;
196
+ }, z.core.$strip>, z.ZodObject<{
197
+ kind: z.ZodLiteral<"ref_exists">;
198
+ query: z.ZodString;
199
+ }, z.core.$strip>, z.ZodObject<{
200
+ kind: z.ZodLiteral<"url_matches">;
201
+ pattern: z.ZodString;
202
+ }, z.core.$strip>, z.ZodObject<{
203
+ kind: z.ZodLiteral<"idle">;
204
+ ms: z.ZodNumber;
205
+ }, z.core.$strip>], "kind">;
206
+ readonly timeout_ms: z.ZodOptional<z.ZodNumber>;
207
+ };
208
+ declare const browserWaitForSchema: z.ZodObject<{
209
+ session_id: z.ZodString;
210
+ condition: z.ZodDiscriminatedUnion<[z.ZodObject<{
211
+ kind: z.ZodLiteral<"text_visible">;
212
+ text: z.ZodString;
213
+ }, z.core.$strip>, z.ZodObject<{
214
+ kind: z.ZodLiteral<"ref_exists">;
215
+ query: z.ZodString;
216
+ }, z.core.$strip>, z.ZodObject<{
217
+ kind: z.ZodLiteral<"url_matches">;
218
+ pattern: z.ZodString;
219
+ }, z.core.$strip>, z.ZodObject<{
220
+ kind: z.ZodLiteral<"idle">;
221
+ ms: z.ZodNumber;
222
+ }, z.core.$strip>], "kind">;
223
+ timeout_ms: z.ZodOptional<z.ZodNumber>;
224
+ }, z.core.$strip>;
225
+ declare const browserScreenshotShape: {
226
+ readonly session_id: z.ZodString;
227
+ readonly full_page: z.ZodOptional<z.ZodBoolean>;
228
+ };
229
+ declare const browserScreenshotSchema: z.ZodObject<{
230
+ session_id: z.ZodString;
231
+ full_page: z.ZodOptional<z.ZodBoolean>;
232
+ }, z.core.$strip>;
233
+ declare const browserNavigateShape: {
234
+ readonly session_id: z.ZodString;
235
+ readonly url: z.ZodString;
236
+ };
237
+ declare const browserNavigateSchema: z.ZodObject<{
238
+ session_id: z.ZodString;
239
+ url: z.ZodString;
240
+ }, z.core.$strip>;
241
+ declare const verifyUiFlowShape: {
242
+ readonly mode: z.ZodDefault<z.ZodEnum<{
243
+ assert: "assert";
244
+ reproduce: "reproduce";
245
+ }>>;
246
+ readonly open: z.ZodObject<{
247
+ platform: z.ZodDefault<z.ZodEnum<{
248
+ web: "web";
249
+ ios: "ios";
250
+ android: "android";
251
+ }>>;
252
+ url: z.ZodOptional<z.ZodString>;
253
+ browser: z.ZodOptional<z.ZodEnum<{
254
+ chromium: "chromium";
255
+ firefox: "firefox";
256
+ webkit: "webkit";
257
+ }>>;
258
+ viewport: z.ZodOptional<z.ZodObject<{
259
+ width: z.ZodNumber;
260
+ height: z.ZodNumber;
261
+ }, z.core.$strip>>;
262
+ bundle_id: z.ZodOptional<z.ZodString>;
263
+ device: z.ZodOptional<z.ZodString>;
264
+ app_package: z.ZodOptional<z.ZodString>;
265
+ app_activity: z.ZodOptional<z.ZodString>;
266
+ emulator: z.ZodOptional<z.ZodString>;
267
+ headless: z.ZodOptional<z.ZodBoolean>;
268
+ user_agent: z.ZodOptional<z.ZodString>;
269
+ locale: z.ZodOptional<z.ZodString>;
270
+ }, z.core.$strip>;
271
+ readonly steps: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
272
+ kind: z.ZodLiteral<"click">;
273
+ query: z.ZodString;
274
+ }, z.core.$strip>, z.ZodObject<{
275
+ kind: z.ZodLiteral<"type">;
276
+ query: z.ZodString;
277
+ text: z.ZodString;
278
+ clear_first: z.ZodOptional<z.ZodBoolean>;
279
+ }, z.core.$strip>, z.ZodObject<{
280
+ kind: z.ZodLiteral<"key">;
281
+ key: z.ZodString;
282
+ }, z.core.$strip>, z.ZodObject<{
283
+ kind: z.ZodLiteral<"wait_for">;
284
+ condition: z.ZodDiscriminatedUnion<[z.ZodObject<{
285
+ kind: z.ZodLiteral<"text_visible">;
286
+ text: z.ZodString;
287
+ }, z.core.$strip>, z.ZodObject<{
288
+ kind: z.ZodLiteral<"ref_exists">;
289
+ query: z.ZodString;
290
+ }, z.core.$strip>, z.ZodObject<{
291
+ kind: z.ZodLiteral<"url_matches">;
292
+ pattern: z.ZodString;
293
+ }, z.core.$strip>, z.ZodObject<{
294
+ kind: z.ZodLiteral<"idle">;
295
+ ms: z.ZodNumber;
296
+ }, z.core.$strip>], "kind">;
297
+ }, z.core.$strip>, z.ZodObject<{
298
+ kind: z.ZodLiteral<"navigate">;
299
+ url: z.ZodString;
300
+ }, z.core.$strip>], "kind">>>;
301
+ readonly expect: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
302
+ kind: z.ZodLiteral<"text_visible">;
303
+ text: z.ZodString;
304
+ }, z.core.$strip>, z.ZodObject<{
305
+ kind: z.ZodLiteral<"text_absent">;
306
+ text: z.ZodString;
307
+ }, z.core.$strip>, z.ZodObject<{
308
+ kind: z.ZodLiteral<"url_matches">;
309
+ pattern: z.ZodString;
310
+ }, z.core.$strip>, z.ZodObject<{
311
+ kind: z.ZodLiteral<"ref_in_state">;
312
+ query: z.ZodString;
313
+ state: z.ZodEnum<{
314
+ focused: "focused";
315
+ visible: "visible";
316
+ enabled: "enabled";
317
+ }>;
318
+ }, z.core.$strip>], "kind">>>;
319
+ readonly capture: z.ZodOptional<z.ZodArray<z.ZodEnum<{
320
+ screenshot: "screenshot";
321
+ har: "har";
322
+ console: "console";
323
+ a11y_tree: "a11y_tree";
324
+ video: "video";
325
+ }>>>;
326
+ readonly close_on_finish: z.ZodDefault<z.ZodBoolean>;
327
+ /**
328
+ * Only consulted when `mode='reproduce'`. When true (default) and the
329
+ * initial run reproduces the bug, the composite tries to remove each
330
+ * step in turn and re-runs to find a smaller reproducer.
331
+ */
332
+ readonly minimize: z.ZodDefault<z.ZodBoolean>;
333
+ };
334
+ declare const verifyUiFlowSchema: z.ZodObject<{
335
+ mode: z.ZodDefault<z.ZodEnum<{
336
+ assert: "assert";
337
+ reproduce: "reproduce";
338
+ }>>;
339
+ open: z.ZodObject<{
340
+ platform: z.ZodDefault<z.ZodEnum<{
341
+ web: "web";
342
+ ios: "ios";
343
+ android: "android";
344
+ }>>;
345
+ url: z.ZodOptional<z.ZodString>;
346
+ browser: z.ZodOptional<z.ZodEnum<{
347
+ chromium: "chromium";
348
+ firefox: "firefox";
349
+ webkit: "webkit";
350
+ }>>;
351
+ viewport: z.ZodOptional<z.ZodObject<{
352
+ width: z.ZodNumber;
353
+ height: z.ZodNumber;
354
+ }, z.core.$strip>>;
355
+ bundle_id: z.ZodOptional<z.ZodString>;
356
+ device: z.ZodOptional<z.ZodString>;
357
+ app_package: z.ZodOptional<z.ZodString>;
358
+ app_activity: z.ZodOptional<z.ZodString>;
359
+ emulator: z.ZodOptional<z.ZodString>;
360
+ headless: z.ZodOptional<z.ZodBoolean>;
361
+ user_agent: z.ZodOptional<z.ZodString>;
362
+ locale: z.ZodOptional<z.ZodString>;
363
+ }, z.core.$strip>;
364
+ steps: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
365
+ kind: z.ZodLiteral<"click">;
366
+ query: z.ZodString;
367
+ }, z.core.$strip>, z.ZodObject<{
368
+ kind: z.ZodLiteral<"type">;
369
+ query: z.ZodString;
370
+ text: z.ZodString;
371
+ clear_first: z.ZodOptional<z.ZodBoolean>;
372
+ }, z.core.$strip>, z.ZodObject<{
373
+ kind: z.ZodLiteral<"key">;
374
+ key: z.ZodString;
375
+ }, z.core.$strip>, z.ZodObject<{
376
+ kind: z.ZodLiteral<"wait_for">;
377
+ condition: z.ZodDiscriminatedUnion<[z.ZodObject<{
378
+ kind: z.ZodLiteral<"text_visible">;
379
+ text: z.ZodString;
380
+ }, z.core.$strip>, z.ZodObject<{
381
+ kind: z.ZodLiteral<"ref_exists">;
382
+ query: z.ZodString;
383
+ }, z.core.$strip>, z.ZodObject<{
384
+ kind: z.ZodLiteral<"url_matches">;
385
+ pattern: z.ZodString;
386
+ }, z.core.$strip>, z.ZodObject<{
387
+ kind: z.ZodLiteral<"idle">;
388
+ ms: z.ZodNumber;
389
+ }, z.core.$strip>], "kind">;
390
+ }, z.core.$strip>, z.ZodObject<{
391
+ kind: z.ZodLiteral<"navigate">;
392
+ url: z.ZodString;
393
+ }, z.core.$strip>], "kind">>>;
394
+ expect: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
395
+ kind: z.ZodLiteral<"text_visible">;
396
+ text: z.ZodString;
397
+ }, z.core.$strip>, z.ZodObject<{
398
+ kind: z.ZodLiteral<"text_absent">;
399
+ text: z.ZodString;
400
+ }, z.core.$strip>, z.ZodObject<{
401
+ kind: z.ZodLiteral<"url_matches">;
402
+ pattern: z.ZodString;
403
+ }, z.core.$strip>, z.ZodObject<{
404
+ kind: z.ZodLiteral<"ref_in_state">;
405
+ query: z.ZodString;
406
+ state: z.ZodEnum<{
407
+ focused: "focused";
408
+ visible: "visible";
409
+ enabled: "enabled";
410
+ }>;
411
+ }, z.core.$strip>], "kind">>>;
412
+ capture: z.ZodOptional<z.ZodArray<z.ZodEnum<{
413
+ screenshot: "screenshot";
414
+ har: "har";
415
+ console: "console";
416
+ a11y_tree: "a11y_tree";
417
+ video: "video";
418
+ }>>>;
419
+ close_on_finish: z.ZodDefault<z.ZodBoolean>;
420
+ minimize: z.ZodDefault<z.ZodBoolean>;
421
+ }, z.core.$strip>;
422
+ declare const auditA11yShape: {
423
+ readonly open: z.ZodObject<{
424
+ platform: z.ZodDefault<z.ZodEnum<{
425
+ web: "web";
426
+ ios: "ios";
427
+ android: "android";
428
+ }>>;
429
+ url: z.ZodOptional<z.ZodString>;
430
+ browser: z.ZodOptional<z.ZodEnum<{
431
+ chromium: "chromium";
432
+ firefox: "firefox";
433
+ webkit: "webkit";
434
+ }>>;
435
+ viewport: z.ZodOptional<z.ZodObject<{
436
+ width: z.ZodNumber;
437
+ height: z.ZodNumber;
438
+ }, z.core.$strip>>;
439
+ bundle_id: z.ZodOptional<z.ZodString>;
440
+ device: z.ZodOptional<z.ZodString>;
441
+ app_package: z.ZodOptional<z.ZodString>;
442
+ app_activity: z.ZodOptional<z.ZodString>;
443
+ emulator: z.ZodOptional<z.ZodString>;
444
+ headless: z.ZodOptional<z.ZodBoolean>;
445
+ user_agent: z.ZodOptional<z.ZodString>;
446
+ locale: z.ZodOptional<z.ZodString>;
447
+ }, z.core.$strip>;
448
+ readonly level: z.ZodDefault<z.ZodEnum<{
449
+ "wcag-a": "wcag-a";
450
+ "wcag-aa": "wcag-aa";
451
+ "wcag-aaa": "wcag-aaa";
452
+ }>>;
453
+ readonly scope: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"page">, z.ZodObject<{
454
+ ref: z.ZodString;
455
+ }, z.core.$strip>]>>;
456
+ readonly report_format: z.ZodDefault<z.ZodEnum<{
457
+ json: "json";
458
+ markdown: "markdown";
459
+ }>>;
460
+ readonly close_on_finish: z.ZodDefault<z.ZodBoolean>;
461
+ };
462
+ declare const auditA11ySchema: z.ZodObject<{
463
+ open: z.ZodObject<{
464
+ platform: z.ZodDefault<z.ZodEnum<{
465
+ web: "web";
466
+ ios: "ios";
467
+ android: "android";
468
+ }>>;
469
+ url: z.ZodOptional<z.ZodString>;
470
+ browser: z.ZodOptional<z.ZodEnum<{
471
+ chromium: "chromium";
472
+ firefox: "firefox";
473
+ webkit: "webkit";
474
+ }>>;
475
+ viewport: z.ZodOptional<z.ZodObject<{
476
+ width: z.ZodNumber;
477
+ height: z.ZodNumber;
478
+ }, z.core.$strip>>;
479
+ bundle_id: z.ZodOptional<z.ZodString>;
480
+ device: z.ZodOptional<z.ZodString>;
481
+ app_package: z.ZodOptional<z.ZodString>;
482
+ app_activity: z.ZodOptional<z.ZodString>;
483
+ emulator: z.ZodOptional<z.ZodString>;
484
+ headless: z.ZodOptional<z.ZodBoolean>;
485
+ user_agent: z.ZodOptional<z.ZodString>;
486
+ locale: z.ZodOptional<z.ZodString>;
487
+ }, z.core.$strip>;
488
+ level: z.ZodDefault<z.ZodEnum<{
489
+ "wcag-a": "wcag-a";
490
+ "wcag-aa": "wcag-aa";
491
+ "wcag-aaa": "wcag-aaa";
492
+ }>>;
493
+ scope: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"page">, z.ZodObject<{
494
+ ref: z.ZodString;
495
+ }, z.core.$strip>]>>;
496
+ report_format: z.ZodDefault<z.ZodEnum<{
497
+ json: "json";
498
+ markdown: "markdown";
499
+ }>>;
500
+ close_on_finish: z.ZodDefault<z.ZodBoolean>;
501
+ }, z.core.$strip>;
502
+ declare const visualDiffShape: {
503
+ readonly open: z.ZodObject<{
504
+ platform: z.ZodDefault<z.ZodEnum<{
505
+ web: "web";
506
+ ios: "ios";
507
+ android: "android";
508
+ }>>;
509
+ url: z.ZodOptional<z.ZodString>;
510
+ browser: z.ZodOptional<z.ZodEnum<{
511
+ chromium: "chromium";
512
+ firefox: "firefox";
513
+ webkit: "webkit";
514
+ }>>;
515
+ viewport: z.ZodOptional<z.ZodObject<{
516
+ width: z.ZodNumber;
517
+ height: z.ZodNumber;
518
+ }, z.core.$strip>>;
519
+ bundle_id: z.ZodOptional<z.ZodString>;
520
+ device: z.ZodOptional<z.ZodString>;
521
+ app_package: z.ZodOptional<z.ZodString>;
522
+ app_activity: z.ZodOptional<z.ZodString>;
523
+ emulator: z.ZodOptional<z.ZodString>;
524
+ headless: z.ZodOptional<z.ZodBoolean>;
525
+ user_agent: z.ZodOptional<z.ZodString>;
526
+ locale: z.ZodOptional<z.ZodString>;
527
+ }, z.core.$strip>;
528
+ readonly baseline_id: z.ZodString;
529
+ readonly viewport: z.ZodOptional<z.ZodObject<{
530
+ width: z.ZodNumber;
531
+ height: z.ZodNumber;
532
+ }, z.core.$strip>>;
533
+ readonly threshold_pct: z.ZodDefault<z.ZodNumber>;
534
+ readonly close_on_finish: z.ZodDefault<z.ZodBoolean>;
535
+ /** Pixel sensitivity for pixelmatch (0 = strict, 1 = lax). Default 0.1. */
536
+ readonly pixel_threshold: z.ZodDefault<z.ZodNumber>;
537
+ };
538
+ declare const visualDiffSchema: z.ZodObject<{
539
+ open: z.ZodObject<{
540
+ platform: z.ZodDefault<z.ZodEnum<{
541
+ web: "web";
542
+ ios: "ios";
543
+ android: "android";
544
+ }>>;
545
+ url: z.ZodOptional<z.ZodString>;
546
+ browser: z.ZodOptional<z.ZodEnum<{
547
+ chromium: "chromium";
548
+ firefox: "firefox";
549
+ webkit: "webkit";
550
+ }>>;
551
+ viewport: z.ZodOptional<z.ZodObject<{
552
+ width: z.ZodNumber;
553
+ height: z.ZodNumber;
554
+ }, z.core.$strip>>;
555
+ bundle_id: z.ZodOptional<z.ZodString>;
556
+ device: z.ZodOptional<z.ZodString>;
557
+ app_package: z.ZodOptional<z.ZodString>;
558
+ app_activity: z.ZodOptional<z.ZodString>;
559
+ emulator: z.ZodOptional<z.ZodString>;
560
+ headless: z.ZodOptional<z.ZodBoolean>;
561
+ user_agent: z.ZodOptional<z.ZodString>;
562
+ locale: z.ZodOptional<z.ZodString>;
563
+ }, z.core.$strip>;
564
+ baseline_id: z.ZodString;
565
+ viewport: z.ZodOptional<z.ZodObject<{
566
+ width: z.ZodNumber;
567
+ height: z.ZodNumber;
568
+ }, z.core.$strip>>;
569
+ threshold_pct: z.ZodDefault<z.ZodNumber>;
570
+ close_on_finish: z.ZodDefault<z.ZodBoolean>;
571
+ pixel_threshold: z.ZodDefault<z.ZodNumber>;
572
+ }, z.core.$strip>;
573
+ declare const scaffoldE2eShape: {
574
+ readonly framework: z.ZodEnum<{
575
+ "playwright-test": "playwright-test";
576
+ "vitest+playwright": "vitest+playwright";
577
+ "pytest+selenium": "pytest+selenium";
578
+ }>;
579
+ readonly scenario_nl: z.ZodString;
580
+ readonly url: z.ZodString;
581
+ readonly recorded_bundle: z.ZodOptional<z.ZodString>;
582
+ /** Override the generated test file name. */
583
+ readonly filename: z.ZodOptional<z.ZodString>;
584
+ };
585
+ declare const scaffoldE2eSchema: z.ZodObject<{
586
+ framework: z.ZodEnum<{
587
+ "playwright-test": "playwright-test";
588
+ "vitest+playwright": "vitest+playwright";
589
+ "pytest+selenium": "pytest+selenium";
590
+ }>;
591
+ scenario_nl: z.ZodString;
592
+ url: z.ZodString;
593
+ recorded_bundle: z.ZodOptional<z.ZodString>;
594
+ filename: z.ZodOptional<z.ZodString>;
595
+ }, z.core.$strip>;
596
+ declare const extractUiStateShape: {
597
+ readonly session_id: z.ZodOptional<z.ZodString>;
598
+ readonly open: z.ZodOptional<z.ZodObject<{
599
+ platform: z.ZodDefault<z.ZodEnum<{
600
+ web: "web";
601
+ ios: "ios";
602
+ android: "android";
603
+ }>>;
604
+ url: z.ZodOptional<z.ZodString>;
605
+ browser: z.ZodOptional<z.ZodEnum<{
606
+ chromium: "chromium";
607
+ firefox: "firefox";
608
+ webkit: "webkit";
609
+ }>>;
610
+ viewport: z.ZodOptional<z.ZodObject<{
611
+ width: z.ZodNumber;
612
+ height: z.ZodNumber;
613
+ }, z.core.$strip>>;
614
+ bundle_id: z.ZodOptional<z.ZodString>;
615
+ device: z.ZodOptional<z.ZodString>;
616
+ app_package: z.ZodOptional<z.ZodString>;
617
+ app_activity: z.ZodOptional<z.ZodString>;
618
+ emulator: z.ZodOptional<z.ZodString>;
619
+ headless: z.ZodOptional<z.ZodBoolean>;
620
+ user_agent: z.ZodOptional<z.ZodString>;
621
+ locale: z.ZodOptional<z.ZodString>;
622
+ }, z.core.$strip>>;
623
+ readonly question_nl: z.ZodString;
624
+ readonly close_on_finish: z.ZodDefault<z.ZodBoolean>;
625
+ };
626
+ declare const extractUiStateSchema: z.ZodObject<{
627
+ session_id: z.ZodOptional<z.ZodString>;
628
+ open: z.ZodOptional<z.ZodObject<{
629
+ platform: z.ZodDefault<z.ZodEnum<{
630
+ web: "web";
631
+ ios: "ios";
632
+ android: "android";
633
+ }>>;
634
+ url: z.ZodOptional<z.ZodString>;
635
+ browser: z.ZodOptional<z.ZodEnum<{
636
+ chromium: "chromium";
637
+ firefox: "firefox";
638
+ webkit: "webkit";
639
+ }>>;
640
+ viewport: z.ZodOptional<z.ZodObject<{
641
+ width: z.ZodNumber;
642
+ height: z.ZodNumber;
643
+ }, z.core.$strip>>;
644
+ bundle_id: z.ZodOptional<z.ZodString>;
645
+ device: z.ZodOptional<z.ZodString>;
646
+ app_package: z.ZodOptional<z.ZodString>;
647
+ app_activity: z.ZodOptional<z.ZodString>;
648
+ emulator: z.ZodOptional<z.ZodString>;
649
+ headless: z.ZodOptional<z.ZodBoolean>;
650
+ user_agent: z.ZodOptional<z.ZodString>;
651
+ locale: z.ZodOptional<z.ZodString>;
652
+ }, z.core.$strip>>;
653
+ question_nl: z.ZodString;
654
+ close_on_finish: z.ZodDefault<z.ZodBoolean>;
655
+ }, z.core.$strip>;
656
+ declare const ToolNames: {
657
+ readonly browserOpen: "rolepod_browser_open";
658
+ readonly browserClose: "rolepod_browser_close";
659
+ readonly browserSnapshot: "rolepod_browser_snapshot";
660
+ readonly browserClick: "rolepod_browser_click";
661
+ readonly browserType: "rolepod_browser_type";
662
+ readonly browserKey: "rolepod_browser_key";
663
+ readonly browserScroll: "rolepod_browser_scroll";
664
+ readonly browserWaitFor: "rolepod_browser_wait_for";
665
+ readonly browserScreenshot: "rolepod_browser_screenshot";
666
+ readonly browserNavigate: "rolepod_browser_navigate";
667
+ readonly verifyUiFlow: "rolepod_verify_ui_flow";
668
+ readonly auditA11y: "rolepod_audit_a11y";
669
+ readonly visualDiff: "rolepod_visual_diff";
670
+ readonly scaffoldE2e: "rolepod_scaffold_e2e";
671
+ readonly extractUiState: "rolepod_extract_ui_state";
672
+ };
673
+ type ToolName = (typeof ToolNames)[keyof typeof ToolNames];
674
+
675
+ /**
676
+ * The single seam between rolepod-uiproof's tool layer and any
677
+ * browser/mobile automation backend.
678
+ *
679
+ * Implementations: PlaywrightEngine (web), AppiumEngine (iOS + Android),
680
+ * optional SeleniumEngine (legacy grid, not yet implemented).
681
+ */
682
+ type Platform = "web" | "ios" | "android";
683
+ type Direction = "up" | "down" | "left" | "right";
684
+ type WaitCondition = {
685
+ kind: "text_visible";
686
+ text: string;
687
+ } | {
688
+ kind: "ref_exists";
689
+ query: string;
690
+ } | {
691
+ kind: "url_matches";
692
+ pattern: string;
693
+ } | {
694
+ kind: "idle";
695
+ ms: number;
696
+ };
697
+ type OpenOptions = {
698
+ platform: Platform;
699
+ url?: string;
700
+ browser?: "chromium" | "firefox" | "webkit";
701
+ viewport?: {
702
+ width: number;
703
+ height: number;
704
+ };
705
+ headless?: boolean;
706
+ user_agent?: string;
707
+ locale?: string;
708
+ bundle_id?: string;
709
+ device?: string;
710
+ app_package?: string;
711
+ app_activity?: string;
712
+ emulator?: string;
713
+ };
714
+ /** Opaque session handle returned by `Engine.open`. */
715
+ interface Session {
716
+ readonly id: string;
717
+ readonly platform: Platform;
718
+ }
719
+ type A11ySnapshot = {
720
+ session_id: string;
721
+ platform: Platform;
722
+ url_or_screen: string;
723
+ taken_at: string;
724
+ tree: A11yNode;
725
+ /** Screenshot buffer captured alongside the snapshot, if requested. */
726
+ screenshot?: Buffer;
727
+ };
728
+ interface Engine {
729
+ readonly id: "playwright" | "appium" | "selenium";
730
+ open(opts: OpenOptions): Promise<Session>;
731
+ close(session: Session): Promise<void>;
732
+ snapshot(session: Session, mode?: "visible" | "full"): Promise<A11ySnapshot>;
733
+ click(session: Session, ref: string, opts?: {
734
+ button?: "left" | "right" | "middle";
735
+ }): Promise<void>;
736
+ type(session: Session, ref: string, text: string, opts?: {
737
+ clearFirst?: boolean;
738
+ }): Promise<void>;
739
+ key(session: Session, key: string): Promise<void>;
740
+ scroll(session: Session, dir: Direction, amount?: number, ref?: string): Promise<void>;
741
+ waitFor(session: Session, cond: WaitCondition, timeoutMs?: number): Promise<void>;
742
+ screenshot(session: Session, fullPage?: boolean): Promise<Buffer>;
743
+ /** Web-only. Throws `unsupported_platform` on mobile sessions. */
744
+ navigate(session: Session, url: string): Promise<void>;
745
+ }
746
+
747
+ /**
748
+ * Routes sessions to the correct engine and enforces idle-timeout cleanup.
749
+ *
750
+ * v0.1: only PlaywrightEngine is wired up, so every `platform: 'web'`
751
+ * request goes there. AppiumEngine (v0.3) will register against the
752
+ * `ios`/`android` platform keys without touching tool code.
753
+ */
754
+ declare class SessionRegistry {
755
+ private readonly enginesByPlatform;
756
+ private readonly engineBySession;
757
+ private readonly platformBySession;
758
+ private readonly lastActivity;
759
+ private readonly idleTimeoutMs;
760
+ private idleTimer;
761
+ constructor(opts?: {
762
+ idleTimeoutMs?: number;
763
+ });
764
+ /** Register an engine as the handler for a given platform. */
765
+ register(platform: Platform, engine: Engine): void;
766
+ open(opts: OpenOptions): Promise<Session>;
767
+ engineFor(sessionId: string): Engine;
768
+ close(session: Session): Promise<void>;
769
+ /** Look up the platform recorded for an open session. */
770
+ platformOf(sessionId: string): Platform;
771
+ shutdown(): Promise<void>;
772
+ private touch;
773
+ private platformFor;
774
+ private ensureIdleSweep;
775
+ }
776
+
777
+ declare const SERVER_NAME = "rolepod-uiproof";
778
+ declare const SERVER_VERSION = "0.4.0";
779
+ type ServerHandle = {
780
+ mcp: McpServer;
781
+ registry: SessionRegistry;
782
+ store: ArtifactStore;
783
+ shutdown(): Promise<void>;
784
+ };
785
+ /**
786
+ * Build the MCP server with every v0.1 tool registered. Caller is
787
+ * responsible for choosing a transport (stdio for production, in-memory
788
+ * for tests) and invoking `mcp.connect(transport)`.
789
+ */
790
+ declare function buildServer(opts?: {
791
+ artifactRoot?: string;
792
+ idleTimeoutMs?: number;
793
+ }): ServerHandle;
794
+
795
+ /**
796
+ * PlaywrightEngine — v0.1 web-only implementation backed by Playwright's
797
+ * Chromium / Firefox / WebKit drivers and the built-in
798
+ * `page.accessibility.snapshot()` API.
799
+ *
800
+ * The interface contract (Engine.ts) is shared with AppiumEngine and the
801
+ * optional SeleniumEngine.
802
+ */
803
+ declare class PlaywrightEngine implements Engine {
804
+ readonly id: "playwright";
805
+ private readonly sessions;
806
+ open(opts: OpenOptions): Promise<Session>;
807
+ close(session: Session): Promise<void>;
808
+ snapshot(session: Session, mode?: "visible" | "full"): Promise<A11ySnapshot>;
809
+ click(session: Session, ref: string, opts?: {
810
+ button?: "left" | "right" | "middle";
811
+ }): Promise<void>;
812
+ type(session: Session, ref: string, text: string, opts?: {
813
+ clearFirst?: boolean;
814
+ }): Promise<void>;
815
+ key(session: Session, key: string): Promise<void>;
816
+ scroll(session: Session, dir: Direction, amount?: number, ref?: string): Promise<void>;
817
+ waitFor(session: Session, cond: WaitCondition, timeoutMs?: number): Promise<void>;
818
+ screenshot(session: Session, fullPage?: boolean): Promise<Buffer>;
819
+ navigate(session: Session, url: string): Promise<void>;
820
+ /**
821
+ * Composite-only escape hatch — exposes the raw Playwright Page so a
822
+ * composite tool that genuinely needs page-level APIs (axe-core,
823
+ * `getByText`, etc.) can use them without bloating the Engine interface
824
+ * with web-specific verbs. Throws if the session is not web.
825
+ */
826
+ getPageForSession(sessionId: string): Page;
827
+ /** Increment generation; the next ref-using call will see them as stale. */
828
+ bumpGeneration(sessionId: string): void;
829
+ private requireSession;
830
+ private resolveLocator;
831
+ private invalidateRefs;
832
+ /**
833
+ * Test / shutdown helper. Closes every open session.
834
+ */
835
+ shutdown(): Promise<void>;
836
+ }
837
+
838
+ /**
839
+ * AppiumEngine — v0.3 mobile support via Appium 2.x + webdriverio.
840
+ *
841
+ * webdriverio is an `optionalDependency` (brief D-020). The engine
842
+ * lazy-imports it; if missing, every public method throws a structured
843
+ * `engine_error` with installation guidance.
844
+ *
845
+ * Smoke tests run against a real simulator only when one is reachable;
846
+ * unit tests for AT normalization use fixture XML strings (see
847
+ * `tests/unit/`).
848
+ */
849
+ declare class AppiumEngine implements Engine {
850
+ readonly id: "appium";
851
+ private readonly sessions;
852
+ private wdioCache;
853
+ open(opts: OpenOptions): Promise<Session>;
854
+ close(session: Session): Promise<void>;
855
+ snapshot(session: Session, _mode?: "visible" | "full"): Promise<A11ySnapshot>;
856
+ click(session: Session, ref: string): Promise<void>;
857
+ type(session: Session, ref: string, text: string, opts?: {
858
+ clearFirst?: boolean;
859
+ }): Promise<void>;
860
+ key(session: Session, key: string): Promise<void>;
861
+ scroll(session: Session, dir: Direction, amount?: number, _ref?: string): Promise<void>;
862
+ waitFor(session: Session, cond: WaitCondition, timeoutMs?: number): Promise<void>;
863
+ screenshot(session: Session, _fullPage?: boolean): Promise<Buffer>;
864
+ navigate(_session: Session, _url: string): Promise<void>;
865
+ private loadWdio;
866
+ private buildCapabilities;
867
+ private screenIdentifier;
868
+ private requireSession;
869
+ private resolveElement;
870
+ private toSelector;
871
+ private invalidateRefs;
872
+ }
873
+
874
+ /**
875
+ * Engine selection happens once at server startup. v0.3 wires
876
+ * Playwright for `web` and Appium for `ios`/`android`. The
877
+ * `ROLEPOD_MCP_WEB_ENGINE` env var (D-012) only governs the *web*
878
+ * engine; mobile always routes to Appium.
879
+ */
880
+ declare function createWebEngine(): Engine;
881
+ declare function createMobileEngine(): Engine;
882
+ /** Back-compat alias for v0.1 callers. */
883
+ declare function createEngine(): Engine;
884
+
885
+ /**
886
+ * Structured error types surfaced to MCP clients. Each carries enough
887
+ * context for the Lead agent to recover (typically: re-snapshot, then retry).
888
+ *
889
+ * Snapshot freshness rule: any state-changing call invalidates the current
890
+ * ref index; a stale ref returns `stale_ref` with the last valid snapshot
891
+ * timestamp so the Lead can re-snapshot and retry.
892
+ */
893
+ type ErrorCode = "stale_ref" | "unknown_ref" | "unknown_session" | "unsupported_platform" | "unsupported_engine" | "not_implemented_in_v01" | "not_implemented_in_v02" | "invalid_input" | "engine_error";
894
+ declare class RolepodMcpError extends Error {
895
+ readonly code: ErrorCode;
896
+ readonly detail?: Record<string, unknown> | undefined;
897
+ readonly name = "RolepodMcpError";
898
+ constructor(code: ErrorCode, message: string, detail?: Record<string, unknown> | undefined);
899
+ toJSON(): {
900
+ code: ErrorCode;
901
+ message: string;
902
+ detail?: Record<string, unknown>;
903
+ };
904
+ }
905
+ declare class StaleRefError extends RolepodMcpError {
906
+ constructor(sessionId: string, ref: string, lastValidSnapshotAt: string | null);
907
+ }
908
+ declare class UnknownRefError extends RolepodMcpError {
909
+ constructor(sessionId: string, ref: string);
910
+ }
911
+ declare class UnknownSessionError extends RolepodMcpError {
912
+ constructor(sessionId: string);
913
+ }
914
+ declare class UnsupportedPlatformError extends RolepodMcpError {
915
+ constructor(platform: string);
916
+ }
917
+
918
+ export { type A11yNode, type A11ySnapshot, AppiumEngine, ArtifactStore, type Engine, type OpenOptions, type Platform, PlaywrightEngine, RolepodMcpError, SERVER_NAME, SERVER_VERSION, type ServerHandle, type Session, SessionRegistry, StaleRefError, type ToolName, ToolNames, UnknownRefError, UnknownSessionError, UnsupportedPlatformError, type WaitCondition, auditA11ySchema, auditA11yShape, browserClickSchema, browserClickShape, browserCloseSchema, browserCloseShape, browserKeySchema, browserKeyShape, browserNavigateSchema, browserNavigateShape, browserOpenSchema, browserOpenShape, browserScreenshotSchema, browserScreenshotShape, browserScrollSchema, browserScrollShape, browserSnapshotSchema, browserSnapshotShape, browserTypeSchema, browserTypeShape, browserWaitForSchema, browserWaitForShape, buildServer, createEngine, createMobileEngine, createWebEngine, extractUiStateSchema, extractUiStateShape, scaffoldE2eSchema, scaffoldE2eShape, verifyUiFlowSchema, verifyUiFlowShape, visualDiffSchema, visualDiffShape };