@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 @@
1
+ {"version":3,"sources":["../../bin/rolepod-uiproof.ts","../../src/cli/doctor.ts","../../src/cli/install_mobile.ts","../../src/cli/replay.ts","../../src/artifact/ArtifactStore.ts","../../src/util/log.ts","../../src/util/errors.ts","../../src/engine/AppiumEngine.ts","../../src/engine/a11y/uiautomator2.ts","../../src/engine/a11y/xcuitest.ts","../../src/engine/PlaywrightEngine.ts","../../src/engine/a11y/normalize.ts","../../src/engine/factory.ts","../../src/session/SessionRegistry.ts","../../src/schema/tools.ts","../../src/replay/minimize.ts","../../src/tools/result.ts","../../src/tools/composite/verify_ui_flow.ts","../../src/server.ts","../../src/tools/atomic/browser_click.ts","../../src/tools/atomic/browser_close.ts","../../src/tools/atomic/browser_key.ts","../../src/tools/atomic/browser_navigate.ts","../../src/tools/atomic/browser_open.ts","../../src/tools/atomic/browser_screenshot.ts","../../src/tools/atomic/browser_scroll.ts","../../src/tools/atomic/browser_snapshot.ts","../../src/tools/atomic/browser_type.ts","../../src/tools/atomic/browser_wait_for.ts","../../src/tools/composite/audit_a11y.ts","../../src/tools/composite/extract_ui_state.ts","../../src/tools/composite/scaffold_e2e.ts","../../src/tools/composite/visual_diff.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { runDoctor } from \"../src/cli/doctor.js\";\nimport { runInstallMobile } from \"../src/cli/install_mobile.js\";\nimport { runReplay } from \"../src/cli/replay.js\";\nimport { buildServer, SERVER_VERSION } from \"../src/server.js\";\nimport { log } from \"../src/util/log.js\";\n\nconst HELP = `rolepod-uiproof ${SERVER_VERSION}\n\nUsage:\n rolepod-uiproof Start the MCP server on stdio (default)\n rolepod-uiproof doctor Health check (Node, Playwright, Appium, SDKs)\n rolepod-uiproof install:mobile Print mobile setup checklist (iOS / Android)\n rolepod-uiproof replay <file> Re-run a verify_ui_flow replay bundle\n rolepod-uiproof --version Print version\n rolepod-uiproof --help This help\n`;\n\nasync function main(): Promise<void> {\n const [, , sub, ...rest] = process.argv;\n\n switch (sub) {\n case undefined:\n case \"serve\":\n return startServer();\n case \"doctor\":\n process.exit(await runDoctor());\n return;\n case \"install:mobile\":\n case \"install\":\n process.exit(runInstallMobile());\n return;\n case \"replay\": {\n const target = rest[0];\n if (!target) {\n process.stderr.write(\"Usage: rolepod-uiproof replay <bundle.json>\\n\");\n process.exit(2);\n }\n process.exit(await runReplay(target));\n return;\n }\n case \"--version\":\n case \"-v\":\n process.stdout.write(`${SERVER_VERSION}\\n`);\n return;\n case \"--help\":\n case \"-h\":\n case \"help\":\n process.stdout.write(HELP);\n return;\n default:\n process.stderr.write(`Unknown subcommand: ${sub}\\n${HELP}`);\n process.exit(2);\n }\n}\n\nasync function startServer(): Promise<void> {\n const server = buildServer();\n const transport = new StdioServerTransport();\n\n const shutdown = async (signal: NodeJS.Signals) => {\n log.info(\"shutting down\", { signal });\n await server.shutdown().catch((err: unknown) =>\n log.error(\"shutdown failed\", { err: String(err) }),\n );\n process.exit(0);\n };\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"));\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"));\n\n await server.mcp.connect(transport);\n log.info(\"rolepod-uiproof connected on stdio\");\n}\n\nmain().catch((err: unknown) => {\n log.error(\"fatal startup error\", {\n err: err instanceof Error ? err.stack : String(err),\n });\n process.exit(1);\n});\n","import { existsSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { homedir, platform as osPlatform } from \"node:os\";\n\ntype Check = {\n name: string;\n status: \"ok\" | \"warn\" | \"fail\";\n detail: string;\n};\n\n/**\n * `rolepod-uiproof doctor` — diagnose local environment readiness. Exits\n * with code 0 if every check is `ok` or `warn`, 1 if any `fail`.\n */\nexport async function runDoctor(): Promise<number> {\n const checks: Check[] = [];\n\n // Node version\n const major = Number(process.versions.node.split(\".\")[0]);\n checks.push({\n name: \"Node ≥20\",\n status: major >= 20 ? \"ok\" : \"fail\",\n detail: process.versions.node,\n });\n\n // Playwright Chromium install (looks under the default cache directory)\n checks.push(checkPlaywrightChromium());\n\n // webdriverio (optional)\n checks.push(await checkWebdriverIO());\n\n // Appium server reachable\n checks.push(await checkAppiumServer());\n\n // Xcode (macOS only, for iOS testing — roadmap v0.3)\n if (osPlatform() === \"darwin\") {\n checks.push(checkXcode());\n }\n\n // Android SDK (roadmap v0.3)\n checks.push(checkAndroidSdk());\n\n // SeleniumEngine status — explicitly roadmap v0.4\n checks.push({\n name: \"SeleniumEngine (roadmap v0.4)\",\n status: \"warn\",\n detail:\n \"Not implemented — deferred to v0.4 (legacy Selenium grid support, opt-in via ROLEPOD_MCP_WEB_ENGINE=selenium).\",\n });\n\n // Artifact dir writable\n checks.push(checkArtifactDir());\n\n print(checks);\n const failed = checks.some((c) => c.status === \"fail\");\n return failed ? 1 : 0;\n}\n\nfunction checkPlaywrightChromium(): Check {\n const candidates = [\n join(homedir(), \"Library\", \"Caches\", \"ms-playwright\"),\n join(homedir(), \".cache\", \"ms-playwright\"),\n process.env.PLAYWRIGHT_BROWSERS_PATH,\n ].filter((x): x is string => typeof x === \"string\");\n for (const base of candidates) {\n if (existsSync(base)) {\n return {\n name: \"Playwright Chromium installed\",\n status: \"ok\",\n detail: base,\n };\n }\n }\n return {\n name: \"Playwright Chromium installed\",\n status: \"fail\",\n detail: \"Run: npx playwright install chromium\",\n };\n}\n\nasync function checkWebdriverIO(): Promise<Check> {\n try {\n const url = await import.meta.resolve?.(\"webdriverio\");\n return {\n name: \"webdriverio (mobile client, v0.3)\",\n status: \"ok\",\n detail: url ?? \"resolved\",\n };\n } catch {\n return {\n name: \"webdriverio (mobile client, v0.3)\",\n status: \"warn\",\n detail:\n \"Not installed — web works fine without it. Mobile is roadmap v0.3. For mobile: npm i webdriverio\",\n };\n }\n}\n\nasync function checkAppiumServer(): Promise<Check> {\n const host = process.env.APPIUM_HOST ?? \"127.0.0.1\";\n const port = Number(process.env.APPIUM_PORT ?? 4723);\n const path = process.env.APPIUM_BASE_PATH ?? \"/\";\n const url = `http://${host}:${port}${path.endsWith(\"/\") ? path : path + \"/\"}status`;\n try {\n const ctrl = new AbortController();\n const timeout = setTimeout(() => ctrl.abort(), 1500);\n const res = await fetch(url, { signal: ctrl.signal });\n clearTimeout(timeout);\n return {\n name: \"Appium server (roadmap v0.3)\",\n status: res.ok ? \"ok\" : \"warn\",\n detail: `${url} → HTTP ${res.status}`,\n };\n } catch {\n return {\n name: \"Appium server (roadmap v0.3)\",\n status: \"warn\",\n detail: `Not reachable at ${url} — mobile sessions need a running Appium daemon. Web sessions are unaffected.`,\n };\n }\n}\n\nfunction checkXcode(): Check {\n const path = \"/Applications/Xcode.app\";\n if (existsSync(path)) {\n return { name: \"Xcode (iOS, roadmap v0.3)\", status: \"ok\", detail: path };\n }\n return {\n name: \"Xcode (iOS, roadmap v0.3)\",\n status: \"warn\",\n detail:\n \"Install Xcode via the App Store; required for iOS simulators. Not needed for web targets.\",\n };\n}\n\nfunction checkAndroidSdk(): Check {\n const candidates = [\n process.env.ANDROID_HOME,\n process.env.ANDROID_SDK_ROOT,\n join(homedir(), \"Library\", \"Android\", \"sdk\"),\n join(homedir(), \"Android\", \"Sdk\"),\n ].filter((x): x is string => typeof x === \"string\");\n for (const path of candidates) {\n if (existsSync(path)) {\n return { name: \"Android SDK (roadmap v0.3)\", status: \"ok\", detail: path };\n }\n }\n return {\n name: \"Android SDK (roadmap v0.3)\",\n status: \"warn\",\n detail:\n \"Set ANDROID_HOME — needed only for Android testing. Not needed for web or iOS targets.\",\n };\n}\n\nfunction checkArtifactDir(): Check {\n const dir = resolve(process.cwd(), \".rolepod-uiproof\");\n // Directory does not need to exist yet; only the parent does.\n return {\n name: \"Artifact root writable\",\n status: \"ok\",\n detail: `Will be created at: ${dir}/artifacts/{run_id}/`,\n };\n}\n\nfunction print(checks: Check[]): void {\n const icon = (s: Check[\"status\"]) => (s === \"ok\" ? \"✓\" : s === \"warn\" ? \"•\" : \"✗\");\n for (const c of checks) {\n // Doctor output is user-facing CLI; stdout is appropriate here\n // because this subcommand never speaks MCP on the same channel.\n process.stdout.write(` ${icon(c.status)} ${c.name.padEnd(30)} ${c.detail}\\n`);\n }\n}\n","import { platform as osPlatform } from \"node:os\";\n\nexport function runInstallMobile(): number {\n const os = osPlatform();\n const lines: string[] = [];\n\n lines.push(\"rolepod-uiproof install:mobile — setup checklist\\n\");\n lines.push(\"Mobile support is OPTIONAL. Skip if you only target the web.\\n\");\n\n lines.push(\"1. Install the Node client:\");\n lines.push(\" npm install webdriverio\\n\");\n\n lines.push(\"2. Install the Appium server (2.x):\");\n lines.push(\" npm install -g appium\");\n lines.push(\" appium driver install xcuitest # iOS\");\n lines.push(\" appium driver install uiautomator2 # Android\");\n lines.push(\" appium # leave running\\n\");\n\n if (os === \"darwin\") {\n lines.push(\"3. iOS — macOS host required:\");\n lines.push(\" • Install Xcode + Command Line Tools\");\n lines.push(\" • Open Xcode → Settings → Platforms → install an iOS Simulator\");\n lines.push(\" • `xcrun simctl list devices` confirms a device is available\\n\");\n } else {\n lines.push(\"3. iOS: not supported on this OS (macOS host required).\\n\");\n }\n\n lines.push(\"4. Android — any host:\");\n lines.push(\" • Install Android Studio OR command-line tools\");\n lines.push(\" • Set ANDROID_HOME to the SDK location\");\n lines.push(\" • `adb devices` confirms an emulator or device is reachable\\n\");\n\n lines.push(\"5. Verify:\");\n lines.push(\" npx rolepod-uiproof doctor\\n\");\n\n lines.push(\"Environment overrides (optional):\");\n lines.push(\" APPIUM_HOST default: 127.0.0.1\");\n lines.push(\" APPIUM_PORT default: 4723\");\n lines.push(\" APPIUM_BASE_PATH default: /\");\n\n for (const l of lines) process.stdout.write(l + \"\\n\");\n return 0;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { ArtifactStore } from \"../artifact/ArtifactStore.js\";\nimport { createMobileEngine, createWebEngine } from \"../engine/factory.js\";\nimport { SessionRegistry } from \"../session/SessionRegistry.js\";\nimport { verifyUiFlowTool } from \"../tools/composite/verify_ui_flow.js\";\nimport type { ToolContext } from \"../tools/types.js\";\n\n/**\n * `rolepod-uiproof replay <bundle.json>` — re-runs a verify_ui_flow\n * replay bundle deterministically, with no agent in the loop. Exit\n * code 0 = passed, 1 = failed or error.\n */\nexport async function runReplay(bundlePath: string): Promise<number> {\n const abs = resolve(bundlePath);\n const raw = await readFile(abs, \"utf8\");\n const bundle = JSON.parse(raw) as Record<string, unknown>;\n if (bundle.version !== 1) {\n process.stderr.write(`Unsupported replay bundle version: ${bundle.version}\\n`);\n return 1;\n }\n\n const webEngine = createWebEngine();\n const registry = new SessionRegistry({ idleTimeoutMs: 0 });\n registry.register(\"web\", webEngine);\n const mobileEngine = createMobileEngine();\n registry.register(\"ios\", mobileEngine);\n registry.register(\"android\", mobileEngine);\n const store = new ArtifactStore();\n const ctx: ToolContext = { registry, store };\n\n try {\n const handler = verifyUiFlowTool.build(ctx);\n const result = await handler({\n mode: \"assert\",\n open: (bundle.open as Record<string, unknown>) ?? {},\n steps:\n (bundle.steps as Array<{ kind: string }> | undefined) ?? [],\n expect:\n (bundle.expect as Array<{ kind: string }> | undefined) ?? [],\n capture: [\"screenshot\"],\n close_on_finish: true,\n minimize: false,\n } as Parameters<ReturnType<typeof verifyUiFlowTool.build>>[0]);\n const body = result.structuredContent as Record<string, unknown>;\n process.stdout.write(JSON.stringify(body, null, 2) + \"\\n\");\n return body.passed === true ? 0 : 1;\n } finally {\n await registry.shutdown().catch(() => undefined);\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { log } from \"../util/log.js\";\n\n/**\n * Writes artifacts under `./.rolepod-uiproof/artifacts/{run_id}/` (D-026).\n *\n * v0.1 emits two formats: PNG screenshots and a JSON replay bundle. Future\n * milestones extend the format set (HAR, console log, a11y tree, video).\n */\nexport type ReplayStep = Record<string, unknown>;\n\nexport type ReplayBundle = {\n version: 1;\n run_id: string;\n recorded_at: string;\n open: Record<string, unknown>;\n steps: ReplayStep[];\n expect: ReplayStep[];\n};\n\nexport type ArtifactPaths = {\n screenshots: string[];\n replay_bundle?: string;\n};\n\nexport class ArtifactStore {\n readonly rootDir: string;\n\n constructor(opts: { rootDir?: string } = {}) {\n this.rootDir = opts.rootDir ?? resolve(process.cwd(), \".rolepod-uiproof\", \"artifacts\");\n }\n\n /** Allocate a fresh run id and ensure its directory exists. */\n async startRun(prefix = \"run\"): Promise<{ runId: string; runDir: string }> {\n const runId = `${prefix}_${this.timestampSlug()}_${randomUUID().slice(0, 8)}`;\n const runDir = resolve(this.rootDir, runId);\n await mkdir(runDir, { recursive: true });\n log.debug(\"artifact run started\", { run_id: runId, dir: runDir });\n return { runId, runDir };\n }\n\n async writeScreenshot(\n runDir: string,\n buf: Buffer,\n name: string,\n ): Promise<string> {\n const path = resolve(runDir, `${name}.png`);\n await writeFile(path, buf);\n return path;\n }\n\n async writeReplayBundle(\n runDir: string,\n bundle: ReplayBundle,\n name = \"replay.json\",\n ): Promise<string> {\n const path = resolve(runDir, name);\n await writeFile(path, JSON.stringify(bundle, null, 2), \"utf8\");\n return path;\n }\n\n async writeReport(runDir: string, name: string, body: string): Promise<string> {\n const path = resolve(runDir, name);\n await writeFile(path, body, \"utf8\");\n return path;\n }\n\n async writeBytes(runDir: string, name: string, buf: Buffer): Promise<string> {\n const path = resolve(runDir, name);\n await writeFile(path, buf);\n return path;\n }\n\n async ensureDir(absDir: string): Promise<string> {\n await mkdir(absDir, { recursive: true });\n return absDir;\n }\n\n /** Root for stored visual baselines: `./.rolepod-uiproof/baselines/`. */\n get baselineDir(): string {\n return resolve(this.rootDir, \"..\", \"baselines\");\n }\n\n private timestampSlug(): string {\n const d = new Date();\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return (\n `${d.getUTCFullYear()}` +\n pad(d.getUTCMonth() + 1) +\n pad(d.getUTCDate()) +\n \"T\" +\n pad(d.getUTCHours()) +\n pad(d.getUTCMinutes()) +\n pad(d.getUTCSeconds())\n );\n }\n}\n","/**\n * Stdio MCP servers MUST NOT write logs to stdout — stdout carries\n * JSON-RPC. All diagnostic output goes to stderr.\n *\n * Reference: MCP TypeScript SDK README, \"Logging on stdio servers\".\n */\n\nfunction emit(level: \"info\" | \"warn\" | \"error\" | \"debug\", msg: string, extra?: unknown): void {\n const line = JSON.stringify({\n ts: new Date().toISOString(),\n level,\n msg,\n ...(extra !== undefined ? { extra } : {}),\n });\n process.stderr.write(line + \"\\n\");\n}\n\nexport const log = {\n info: (msg: string, extra?: unknown) => emit(\"info\", msg, extra),\n warn: (msg: string, extra?: unknown) => emit(\"warn\", msg, extra),\n error: (msg: string, extra?: unknown) => emit(\"error\", msg, extra),\n debug: (msg: string, extra?: unknown) => {\n if (process.env.ROLEPOD_MCP_DEBUG) emit(\"debug\", msg, extra);\n },\n};\n","/**\n * Structured error types surfaced to MCP clients. Each carries enough\n * context for the Lead agent to recover (typically: re-snapshot, then retry).\n *\n * Snapshot freshness rule: any state-changing call invalidates the current\n * ref index; a stale ref returns `stale_ref` with the last valid snapshot\n * timestamp so the Lead can re-snapshot and retry.\n */\n\nexport type ErrorCode =\n | \"stale_ref\"\n | \"unknown_ref\"\n | \"unknown_session\"\n | \"unsupported_platform\"\n | \"unsupported_engine\"\n | \"not_implemented_in_v01\"\n | \"not_implemented_in_v02\"\n | \"invalid_input\"\n | \"engine_error\";\n\nexport class RolepodMcpError extends Error {\n override readonly name = \"RolepodMcpError\";\n constructor(\n readonly code: ErrorCode,\n message: string,\n readonly detail?: Record<string, unknown>,\n ) {\n super(message);\n }\n\n toJSON(): { code: ErrorCode; message: string; detail?: Record<string, unknown> } {\n return {\n code: this.code,\n message: this.message,\n ...(this.detail ? { detail: this.detail } : {}),\n };\n }\n}\n\nexport class StaleRefError extends RolepodMcpError {\n constructor(sessionId: string, ref: string, lastValidSnapshotAt: string | null) {\n super(\"stale_ref\", `Ref \"${ref}\" is stale — re-snapshot before retrying.`, {\n session_id: sessionId,\n ref,\n last_valid_snapshot_at: lastValidSnapshotAt,\n });\n }\n}\n\nexport class UnknownRefError extends RolepodMcpError {\n constructor(sessionId: string, ref: string) {\n super(\"unknown_ref\", `Ref \"${ref}\" was not found in the current snapshot.`, {\n session_id: sessionId,\n ref,\n });\n }\n}\n\nexport class UnknownSessionError extends RolepodMcpError {\n constructor(sessionId: string) {\n super(\"unknown_session\", `No open session with id \"${sessionId}\".`, {\n session_id: sessionId,\n });\n }\n}\n\nexport class UnsupportedPlatformError extends RolepodMcpError {\n constructor(platform: string) {\n super(\n \"unsupported_platform\",\n `Platform \"${platform}\" is not supported in v0.1 — only \"web\" is implemented. Mobile (ios/android) ships in v0.3.`,\n { platform },\n );\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n RolepodMcpError,\n UnknownRefError,\n UnknownSessionError,\n UnsupportedPlatformError,\n} from \"../util/errors.js\";\nimport { log } from \"../util/log.js\";\nimport {\n parseUiAutomator2Tree,\n type AndroidRefMeta,\n} from \"./a11y/uiautomator2.js\";\nimport { parseXcuiTestTree, type IosRefMeta } from \"./a11y/xcuitest.js\";\nimport type {\n A11ySnapshot,\n Direction,\n Engine,\n OpenOptions,\n Platform,\n Session,\n WaitCondition,\n} from \"./Engine.js\";\n\ntype MobileRefMeta = IosRefMeta | AndroidRefMeta;\n\n/**\n * Minimal subset of the webdriverio `Browser` surface that AppiumEngine\n * relies on. We type only what we use so that consumers without\n * `webdriverio` installed still typecheck.\n */\ntype WdioElement = {\n click(): Promise<void>;\n clearValue(): Promise<void>;\n setValue(value: string): Promise<void>;\n isEnabled(): Promise<boolean>;\n};\n\ntype WdioBrowser = {\n sessionId: string;\n capabilities: Record<string, unknown>;\n getPageSource(): Promise<string>;\n saveScreenshot(filepath?: string): Promise<Buffer>;\n takeScreenshot(): Promise<string>; // base64\n pressKeyCode?: (code: number) => Promise<void>;\n $(selector: string): Promise<WdioElement> & WdioElement;\n execute<T = unknown>(script: string, ...args: unknown[]): Promise<T>;\n deleteSession(): Promise<void>;\n pause(ms: number): Promise<void>;\n};\n\ntype WdioRemote = (\n opts: Record<string, unknown>,\n) => Promise<WdioBrowser>;\n\ntype MobileSession = {\n readonly id: string;\n readonly platform: \"ios\" | \"android\";\n readonly driver: WdioBrowser;\n};\n\ntype SessionInternals = {\n session: MobileSession;\n refIndex: Map<string, MobileRefMeta>;\n snapshotGeneration: number;\n refGeneration: number;\n lastSnapshotAt: string | null;\n};\n\n/**\n * AppiumEngine — v0.3 mobile support via Appium 2.x + webdriverio.\n *\n * webdriverio is an `optionalDependency` (brief D-020). The engine\n * lazy-imports it; if missing, every public method throws a structured\n * `engine_error` with installation guidance.\n *\n * Smoke tests run against a real simulator only when one is reachable;\n * unit tests for AT normalization use fixture XML strings (see\n * `tests/unit/`).\n */\nexport class AppiumEngine implements Engine {\n readonly id = \"appium\" as const;\n\n private readonly sessions = new Map<string, SessionInternals>();\n private wdioCache: WdioRemote | null = null;\n\n async open(opts: OpenOptions): Promise<Session> {\n if (opts.platform !== \"ios\" && opts.platform !== \"android\") {\n throw new UnsupportedPlatformError(opts.platform);\n }\n const remote = await this.loadWdio();\n const caps = this.buildCapabilities(opts);\n const driver = await remote({\n hostname: process.env.APPIUM_HOST ?? \"127.0.0.1\",\n port: Number(process.env.APPIUM_PORT ?? 4723),\n path: process.env.APPIUM_BASE_PATH ?? \"/\",\n capabilities: caps,\n });\n\n const sessionId = randomUUID();\n const session: MobileSession = { id: sessionId, platform: opts.platform, driver };\n this.sessions.set(sessionId, {\n session,\n refIndex: new Map(),\n snapshotGeneration: 0,\n refGeneration: -1,\n lastSnapshotAt: null,\n });\n log.info(\"mobile session opened\", {\n session_id: sessionId,\n platform: opts.platform,\n remote_session: driver.sessionId,\n });\n return { id: sessionId, platform: opts.platform };\n }\n\n async close(session: Session): Promise<void> {\n const s = this.requireSession(session.id);\n await s.session.driver.deleteSession().catch((err: unknown) =>\n log.warn(\"appium deleteSession failed\", { session_id: session.id, err: String(err) }),\n );\n this.sessions.delete(session.id);\n log.info(\"mobile session closed\", { session_id: session.id });\n }\n\n async snapshot(session: Session, _mode?: \"visible\" | \"full\"): Promise<A11ySnapshot> {\n void _mode;\n const s = this.requireSession(session.id);\n const xml = await s.session.driver.getPageSource();\n const normalized =\n s.session.platform === \"ios\"\n ? parseXcuiTestTree(xml)\n : parseUiAutomator2Tree(xml);\n\n s.snapshotGeneration += 1;\n s.refGeneration = s.snapshotGeneration;\n s.refIndex = normalized.refIndex as Map<string, MobileRefMeta>;\n s.lastSnapshotAt = new Date().toISOString();\n\n return {\n session_id: session.id,\n platform: s.session.platform,\n url_or_screen: this.screenIdentifier(s),\n taken_at: s.lastSnapshotAt,\n tree: normalized.tree,\n };\n }\n\n async click(session: Session, ref: string): Promise<void> {\n const s = this.requireSession(session.id);\n const el = await this.resolveElement(s, ref);\n await el.click();\n this.invalidateRefs(s);\n }\n\n async type(\n session: Session,\n ref: string,\n text: string,\n opts?: { clearFirst?: boolean },\n ): Promise<void> {\n const s = this.requireSession(session.id);\n const el = await this.resolveElement(s, ref);\n if (opts?.clearFirst) await el.clearValue();\n await el.setValue(text);\n this.invalidateRefs(s);\n }\n\n async key(session: Session, key: string): Promise<void> {\n const s = this.requireSession(session.id);\n if (s.session.platform === \"android\" && s.session.driver.pressKeyCode) {\n const code = ANDROID_KEY_CODES[key];\n if (code !== undefined) {\n await s.session.driver.pressKeyCode(code);\n this.invalidateRefs(s);\n return;\n }\n }\n throw new RolepodMcpError(\n \"not_implemented_in_v02\",\n `Mobile key(\"${key}\") is partially supported in v0.3 — only well-known Android keycodes are mapped. iOS hardware keys land later.`,\n { platform: s.session.platform, key },\n );\n }\n\n async scroll(\n session: Session,\n dir: Direction,\n amount = 400,\n _ref?: string,\n ): Promise<void> {\n void _ref;\n const s = this.requireSession(session.id);\n // Mobile scroll is fiddly across drivers — fall back to a touch\n // gesture via execute(). Most consumers will prefer a `wait_for`\n // followed by a `click` on a ref that scrolls into view.\n const action =\n s.session.platform === \"ios\"\n ? \"mobile: swipe\"\n : \"mobile: scrollGesture\";\n const params =\n s.session.platform === \"ios\"\n ? { direction: dir }\n : { left: 100, top: 200, width: 400, height: 600, direction: dir, percent: amount / 1000 };\n await s.session.driver\n .execute(action, params)\n .catch((err: unknown) => log.warn(\"scroll gesture failed\", { err: String(err) }));\n this.invalidateRefs(s);\n }\n\n async waitFor(\n session: Session,\n cond: WaitCondition,\n timeoutMs = 10_000,\n ): Promise<void> {\n const s = this.requireSession(session.id);\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (cond.kind === \"idle\") {\n await s.session.driver.pause(cond.ms);\n this.invalidateRefs(s);\n return;\n }\n const snap = await this.snapshot(session);\n const matched =\n cond.kind === \"text_visible\"\n ? treeIncludesText(snap.tree, cond.text)\n : cond.kind === \"ref_exists\"\n ? treeIncludesText(snap.tree, cond.query)\n : false;\n if (matched) return;\n await s.session.driver.pause(250);\n }\n throw new RolepodMcpError(\n \"engine_error\",\n `wait_for ${cond.kind} timed out after ${timeoutMs}ms`,\n { condition: cond, timeout_ms: timeoutMs },\n );\n }\n\n async screenshot(session: Session, _fullPage?: boolean): Promise<Buffer> {\n void _fullPage;\n const s = this.requireSession(session.id);\n const b64 = await s.session.driver.takeScreenshot();\n return Buffer.from(b64, \"base64\");\n }\n\n async navigate(_session: Session, _url: string): Promise<void> {\n throw new UnsupportedPlatformError(_session.platform);\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async loadWdio(): Promise<WdioRemote> {\n if (this.wdioCache) return this.wdioCache;\n try {\n // Avoid TypeScript pulling the (optional) module into static types.\n const mod = (await import(/* @vite-ignore */ \"webdriverio\")) as unknown as {\n remote: WdioRemote;\n };\n this.wdioCache = mod.remote;\n return mod.remote;\n } catch {\n throw new RolepodMcpError(\n \"engine_error\",\n \"Mobile support needs webdriverio (and a running Appium server). Run `npx rolepod-uiproof install:mobile` for the setup checklist.\",\n );\n }\n }\n\n private buildCapabilities(opts: OpenOptions): Record<string, unknown> {\n const caps: Record<string, unknown> = {};\n if (opts.platform === \"ios\") {\n caps.platformName = \"iOS\";\n caps[\"appium:automationName\"] = \"XCUITest\";\n if (opts.device) caps[\"appium:deviceName\"] = opts.device;\n if (opts.bundle_id) caps[\"appium:bundleId\"] = opts.bundle_id;\n } else {\n caps.platformName = \"Android\";\n caps[\"appium:automationName\"] = \"UiAutomator2\";\n if (opts.emulator) caps[\"appium:avd\"] = opts.emulator;\n if (opts.app_package) caps[\"appium:appPackage\"] = opts.app_package;\n if (opts.app_activity) caps[\"appium:appActivity\"] = opts.app_activity;\n }\n if (opts.locale) caps[\"appium:language\"] = opts.locale;\n return caps;\n }\n\n private screenIdentifier(s: SessionInternals): string {\n const caps = s.session.driver.capabilities as Record<string, unknown>;\n return String(\n caps[\"appium:bundleId\"] ??\n caps[\"appium:appPackage\"] ??\n caps.platformName ??\n s.session.platform,\n );\n }\n\n private requireSession(sessionId: string): SessionInternals {\n const s = this.sessions.get(sessionId);\n if (!s) throw new UnknownSessionError(sessionId);\n return s;\n }\n\n private async resolveElement(s: SessionInternals, ref: string): Promise<WdioElement> {\n if (s.refGeneration !== s.snapshotGeneration) {\n throw new RolepodMcpError(\n \"stale_ref\",\n `Ref \"${ref}\" is stale — re-snapshot before retrying.`,\n {\n session_id: s.session.id,\n ref,\n last_valid_snapshot_at: s.lastSnapshotAt,\n },\n );\n }\n const meta = s.refIndex.get(ref);\n if (!meta) throw new UnknownRefError(s.session.id, ref);\n const selector = this.toSelector(meta);\n return s.session.driver.$(selector);\n }\n\n private toSelector(meta: MobileRefMeta): string {\n if (meta.kind === \"ios\") {\n if (meta.accessibilityId) return `~${meta.accessibilityId}`;\n const chain = `**/${meta.type}[${meta.classChainIndex}]`;\n return `-ios class chain:${chain}`;\n }\n if (meta.resourceId) {\n return `-android uiautomator:new UiSelector().resourceId(\"${escape(meta.resourceId)}\")`;\n }\n if (meta.contentDesc) return `~${meta.contentDesc}`;\n if (meta.text) {\n return `-android uiautomator:new UiSelector().text(\"${escape(meta.text)}\")`;\n }\n return `-android uiautomator:new UiSelector().className(\"${meta.androidClass}\").instance(${meta.classIndex - 1})`;\n }\n\n private invalidateRefs(s: SessionInternals): void {\n s.snapshotGeneration += 1;\n }\n}\n\nconst ANDROID_KEY_CODES: Record<string, number> = {\n Enter: 66,\n Tab: 61,\n Escape: 111,\n Back: 4,\n Home: 3,\n Menu: 82,\n Search: 84,\n Backspace: 67,\n ArrowUp: 19,\n ArrowDown: 20,\n ArrowLeft: 21,\n ArrowRight: 22,\n};\n\nfunction escape(s: string): string {\n return s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction treeIncludesText(node: { name?: string; value?: string; children?: unknown[] }, text: string): boolean {\n const target = text.toLowerCase();\n const visit = (n: { name?: string; value?: string; children?: unknown[] }): boolean => {\n if ((n.name && n.name.toLowerCase().includes(target)) ||\n (n.value && n.value.toLowerCase().includes(target))) return true;\n if (!n.children) return false;\n for (const c of n.children as Array<{ name?: string; value?: string; children?: unknown[] }>) {\n if (visit(c)) return true;\n }\n return false;\n };\n return visit(node);\n}\n\n// Helper so we don't accidentally export this typo'd internal name.\nfunction _platformGuard(p: Platform): void {\n void p;\n}\nvoid _platformGuard;\n","/**\n * UIAutomator2 (Android via Appium) accessibility-tree normalizer.\n *\n * Parses the Appium XML page source returned by\n * `driver.getPageSource()`. UIAutomator2 markup is rooted at\n * `<hierarchy>` and uses Android class names as tag names\n * (e.g. `android.widget.Button`), with attributes such as\n * `resource-id`, `content-desc`, `text`, `bounds`, `enabled`, etc.\n *\n * Inspired by alumnium-hq/alumnium's UIAutomator2AccessibilityTree\n * (MIT) — see UPSTREAM_TRACKING.md. Original implementation; no\n * verbatim copy.\n */\nimport { XMLParser } from \"fast-xml-parser\";\nimport type { A11yNode } from \"../../schema/tools.js\";\n\nexport type AndroidRefMeta = {\n kind: \"android\";\n resourceId?: string;\n contentDesc?: string;\n text?: string;\n androidClass: string;\n /** 1-based index among siblings of the same android class. */\n classIndex: number;\n};\n\nexport type AndroidNormalizedSnapshot = {\n tree: A11yNode;\n refIndex: Map<string, AndroidRefMeta>;\n};\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@\",\n alwaysCreateTextNode: false,\n preserveOrder: true,\n});\n\ntype RawNode = Record<string, RawNode[] | undefined> & { \":@\"?: Record<string, string> };\n\nexport function parseUiAutomator2Tree(xmlString: string): AndroidNormalizedSnapshot {\n const refIndex = new Map<string, AndroidRefMeta>();\n let counter = 0;\n const nextRef = (): string => `e${++counter}`;\n\n let raw: RawNode[] = [];\n try {\n raw = parser.parse(xmlString) as RawNode[];\n } catch {\n raw = [];\n }\n\n const visit = (node: RawNode, siblingOcc: Map<string, number>): A11yNode | null => {\n const tagName = firstTagName(node);\n if (!tagName) return null;\n const attrs = node[\":@\"] ?? {};\n const childrenRaw = (node[tagName] as RawNode[]) ?? [];\n\n const idx = (siblingOcc.get(tagName) ?? 0) + 1;\n siblingOcc.set(tagName, idx);\n\n const ref = nextRef();\n refIndex.set(ref, {\n kind: \"android\",\n resourceId: attrs[\"@resource-id\"],\n contentDesc: attrs[\"@content-desc\"],\n text: attrs[\"@text\"],\n androidClass: tagName,\n classIndex: idx,\n });\n\n const role = simplifyAndroidClass(tagName);\n\n const a11y: A11yNode = { ref, role };\n const name = attrs[\"@content-desc\"] ?? attrs[\"@text\"];\n if (name) a11y.name = name;\n if (attrs[\"@text\"] && attrs[\"@text\"] !== name) a11y.value = attrs[\"@text\"];\n\n const state: A11yNode[\"state\"] = {};\n if (attrs[\"@enabled\"] === \"false\") state.disabled = true;\n if (attrs[\"@focused\"] === \"true\") state.focused = true;\n if (attrs[\"@selected\"] === \"true\") state.selected = true;\n if (Object.keys(state).length > 0) a11y.state = state;\n\n if (childrenRaw.length > 0) {\n const siblings = new Map<string, number>();\n const children: A11yNode[] = [];\n for (const child of childrenRaw) {\n const built = visit(child, siblings);\n if (built) children.push(built);\n }\n if (children.length > 0) a11y.children = children;\n }\n return a11y;\n };\n\n const hierarchy =\n raw.find((n) => Object.keys(n).some((k) => k === \"hierarchy\")) ?? raw[0];\n if (!hierarchy) {\n return {\n tree: { ref: \"e0\", role: \"RootWebArea\" },\n refIndex,\n };\n }\n const top = visit(hierarchy, new Map());\n if (top) return { tree: top, refIndex };\n return { tree: { ref: \"e0\", role: \"RootWebArea\" }, refIndex };\n}\n\nfunction firstTagName(node: RawNode): string | null {\n for (const key of Object.keys(node)) {\n if (key === \":@\") continue;\n // skip XML declarations (`<?xml ... ?>`) and processing instructions\n if (key.startsWith(\"?\")) continue;\n return key;\n }\n return null;\n}\n\n/** Map `android.widget.Button` → `Button`, fall back to the full class. */\nfunction simplifyAndroidClass(cls: string): string {\n const last = cls.split(\".\").pop();\n return last ?? cls;\n}\n","/**\n * XCUITest (iOS via Appium) accessibility-tree normalizer.\n *\n * Parses the Appium XML page source returned by\n * `driver.getPageSource()` and produces a unified `A11yNode` tree plus\n * a `refIndex` whose entries carry enough information for the engine to\n * resolve `ref → element` later (via accessibility id, name, or class\n * chain).\n *\n * Inspired by alumnium-hq/alumnium's XCUITestAccessibilityTree (MIT) —\n * see UPSTREAM_TRACKING.md. Original implementation; no verbatim copy.\n */\nimport { XMLParser } from \"fast-xml-parser\";\nimport type { A11yNode } from \"../../schema/tools.js\";\n\nexport type IosRefMeta = {\n kind: \"ios\";\n /** Accessibility id when present — primary locator. */\n accessibilityId?: string;\n name?: string;\n label?: string;\n type: string;\n /** 1-based class-chain index among siblings of the same `type`. */\n classChainIndex: number;\n};\n\nexport type IosNormalizedSnapshot = {\n tree: A11yNode;\n refIndex: Map<string, IosRefMeta>;\n};\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@\",\n alwaysCreateTextNode: false,\n preserveOrder: true,\n});\n\ntype RawNode = Record<string, RawNode[] | undefined> & { \":@\"?: Record<string, string> };\n\nexport function parseXcuiTestTree(xmlString: string): IosNormalizedSnapshot {\n const refIndex = new Map<string, IosRefMeta>();\n let counter = 0;\n const nextRef = (): string => `e${++counter}`;\n\n let raw: RawNode[] = [];\n try {\n raw = parser.parse(xmlString) as RawNode[];\n } catch {\n raw = [];\n }\n\n const visit = (node: RawNode, classChainOcc: Map<string, number>): A11yNode | null => {\n const tagName = firstTagName(node);\n if (!tagName) return null;\n const attrs = node[\":@\"] ?? {};\n const childrenRaw = (node[tagName] as RawNode[]) ?? [];\n\n const idx = (classChainOcc.get(tagName) ?? 0) + 1;\n classChainOcc.set(tagName, idx);\n\n const ref = nextRef();\n refIndex.set(ref, {\n kind: \"ios\",\n accessibilityId: attrs[\"@name\"],\n name: attrs[\"@name\"],\n label: attrs[\"@label\"],\n type: tagName,\n classChainIndex: idx,\n });\n\n const role = tagName.startsWith(\"XCUIElementType\")\n ? tagName.slice(\"XCUIElementType\".length).toLowerCase()\n : tagName;\n\n const a11y: A11yNode = { ref, role };\n const name = attrs[\"@label\"] ?? attrs[\"@name\"];\n if (name) a11y.name = name;\n if (attrs[\"@value\"]) a11y.value = attrs[\"@value\"];\n\n const state: A11yNode[\"state\"] = {};\n if (attrs[\"@enabled\"] === \"false\") state.disabled = true;\n if (attrs[\"@selected\"] === \"true\") state.selected = true;\n if (Object.keys(state).length > 0) a11y.state = state;\n\n if (childrenRaw.length > 0) {\n const siblings = new Map<string, number>();\n const children: A11yNode[] = [];\n for (const child of childrenRaw) {\n const built = visit(child, siblings);\n if (built) children.push(built);\n }\n if (children.length > 0) a11y.children = children;\n }\n return a11y;\n };\n\n const topLevel: A11yNode[] = [];\n const rootOcc = new Map<string, number>();\n for (const node of raw) {\n const built = visit(node, rootOcc);\n if (built) topLevel.push(built);\n }\n\n if (topLevel.length === 1) {\n return { tree: topLevel[0]!, refIndex };\n }\n const rootRef = nextRef();\n refIndex.set(rootRef, {\n kind: \"ios\",\n type: \"XCUIElementTypeApplication\",\n classChainIndex: 1,\n });\n const root: A11yNode = { ref: rootRef, role: \"application\" };\n if (topLevel.length > 0) root.children = topLevel;\n return { tree: root, refIndex };\n}\n\nfunction firstTagName(node: RawNode): string | null {\n for (const key of Object.keys(node)) {\n if (key === \":@\") continue;\n // skip XML declarations (`<?xml ... ?>`) and processing instructions\n if (key.startsWith(\"?\")) continue;\n return key;\n }\n return null;\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n chromium,\n firefox,\n webkit,\n type Browser,\n type BrowserContext,\n type Page,\n type Locator,\n} from \"playwright\";\nimport {\n RolepodMcpError,\n UnknownRefError,\n UnsupportedPlatformError,\n} from \"../util/errors.js\";\nimport { log } from \"../util/log.js\";\nimport {\n parseAriaSnapshot,\n type RefMeta,\n} from \"./a11y/normalize.js\";\nimport type {\n A11ySnapshot,\n Direction,\n Engine,\n OpenOptions,\n Session,\n WaitCondition,\n} from \"./Engine.js\";\n\ntype WebSession = Session & {\n readonly platform: \"web\";\n readonly browser: Browser;\n readonly context: BrowserContext;\n readonly page: Page;\n};\n\ntype SessionInternals = {\n session: WebSession;\n refIndex: Map<string, RefMeta>;\n /**\n * Monotonic generation number. Snapshot resets refs; any state-changing\n * call bumps the generation, invalidating prior refs per D-010.\n */\n snapshotGeneration: number;\n /** Generation at which the current refIndex was issued. */\n refGeneration: number;\n lastSnapshotAt: string | null;\n};\n\n/**\n * PlaywrightEngine — v0.1 web-only implementation backed by Playwright's\n * Chromium / Firefox / WebKit drivers and the built-in\n * `page.accessibility.snapshot()` API.\n *\n * The interface contract (Engine.ts) is shared with AppiumEngine and the\n * optional SeleniumEngine.\n */\nexport class PlaywrightEngine implements Engine {\n readonly id = \"playwright\" as const;\n\n private readonly sessions = new Map<string, SessionInternals>();\n\n async open(opts: OpenOptions): Promise<Session> {\n if (opts.platform !== \"web\") {\n throw new UnsupportedPlatformError(opts.platform);\n }\n\n const browserName = opts.browser ?? \"chromium\";\n const launcher =\n browserName === \"firefox\"\n ? firefox\n : browserName === \"webkit\"\n ? webkit\n : chromium;\n\n const headless = opts.headless ?? (process.env.CI ? true : false);\n const browser = await launcher.launch({ headless });\n\n const contextOptions: Parameters<typeof browser.newContext>[0] = {};\n if (opts.viewport) contextOptions.viewport = opts.viewport;\n if (opts.user_agent) contextOptions.userAgent = opts.user_agent;\n if (opts.locale) contextOptions.locale = opts.locale;\n\n const context = await browser.newContext(contextOptions);\n const page = await context.newPage();\n if (opts.url) {\n await page.goto(opts.url, { waitUntil: \"domcontentloaded\" });\n }\n\n const sessionId = randomUUID();\n const session: WebSession = {\n id: sessionId,\n platform: \"web\",\n browser,\n context,\n page,\n };\n this.sessions.set(sessionId, {\n session,\n refIndex: new Map(),\n snapshotGeneration: 0,\n refGeneration: -1,\n lastSnapshotAt: null,\n });\n log.info(\"session opened\", {\n session_id: sessionId,\n browser: browserName,\n url: opts.url ?? null,\n });\n return { id: sessionId, platform: \"web\" };\n }\n\n async close(session: Session): Promise<void> {\n const s = this.requireSession(session.id);\n await s.session.context.close().catch((err: unknown) => {\n log.warn(\"context close failed\", { session_id: session.id, err: String(err) });\n });\n await s.session.browser.close().catch((err: unknown) => {\n log.warn(\"browser close failed\", { session_id: session.id, err: String(err) });\n });\n this.sessions.delete(session.id);\n log.info(\"session closed\", { session_id: session.id });\n }\n\n async snapshot(\n session: Session,\n mode: \"visible\" | \"full\" = \"visible\",\n ): Promise<A11ySnapshot> {\n const s = this.requireSession(session.id);\n // Playwright 1.60 removed `page.accessibility`. The ai-mode aria\n // snapshot is the supported successor — it carries `[ref=eN]` markers\n // that the `aria-ref=` locator can resolve back to elements.\n const ariaYaml = await s.session.page.ariaSnapshot({ mode: \"ai\" });\n const { tree, refIndex } = parseAriaSnapshot(ariaYaml);\n void mode; // depth control will route here once we expose `depth` to callers.\n\n s.snapshotGeneration += 1;\n s.refGeneration = s.snapshotGeneration;\n s.refIndex = refIndex;\n s.lastSnapshotAt = new Date().toISOString();\n\n return {\n session_id: session.id,\n platform: \"web\",\n url_or_screen: s.session.page.url(),\n taken_at: s.lastSnapshotAt,\n tree,\n };\n }\n\n async click(\n session: Session,\n ref: string,\n opts?: { button?: \"left\" | \"right\" | \"middle\" },\n ): Promise<void> {\n const s = this.requireSession(session.id);\n const locator = this.resolveLocator(s, ref);\n await locator.click(opts?.button ? { button: opts.button } : undefined);\n this.invalidateRefs(s);\n }\n\n async type(\n session: Session,\n ref: string,\n text: string,\n opts?: { clearFirst?: boolean },\n ): Promise<void> {\n const s = this.requireSession(session.id);\n const locator = this.resolveLocator(s, ref);\n if (opts?.clearFirst) await locator.fill(\"\");\n await locator.fill(text);\n this.invalidateRefs(s);\n }\n\n async key(session: Session, key: string): Promise<void> {\n const s = this.requireSession(session.id);\n await s.session.page.keyboard.press(key);\n this.invalidateRefs(s);\n }\n\n async scroll(\n session: Session,\n dir: Direction,\n amount = 400,\n ref?: string,\n ): Promise<void> {\n const s = this.requireSession(session.id);\n const dx = dir === \"left\" ? -amount : dir === \"right\" ? amount : 0;\n const dy = dir === \"up\" ? -amount : dir === \"down\" ? amount : 0;\n if (ref) {\n const locator = this.resolveLocator(s, ref);\n await locator.evaluate(\n (el, [x, y]) => el.scrollBy(x as number, y as number),\n [dx, dy],\n );\n } else {\n await s.session.page.mouse.wheel(dx, dy);\n }\n this.invalidateRefs(s);\n }\n\n async waitFor(\n session: Session,\n cond: WaitCondition,\n timeoutMs = 10_000,\n ): Promise<void> {\n const s = this.requireSession(session.id);\n const page = s.session.page;\n switch (cond.kind) {\n case \"text_visible\":\n await page\n .getByText(cond.text, { exact: false })\n .first()\n .waitFor({ state: \"visible\", timeout: timeoutMs });\n break;\n case \"ref_exists\":\n await page\n .getByRole(\"button\", { name: cond.query })\n .first()\n .waitFor({ state: \"attached\", timeout: timeoutMs });\n break;\n case \"url_matches\":\n await page.waitForURL(new RegExp(cond.pattern), { timeout: timeoutMs });\n break;\n case \"idle\":\n await page.waitForLoadState(\"networkidle\", { timeout: timeoutMs });\n await page.waitForTimeout(cond.ms);\n break;\n }\n this.invalidateRefs(s);\n }\n\n async screenshot(session: Session, fullPage = false): Promise<Buffer> {\n const s = this.requireSession(session.id);\n return s.session.page.screenshot({ fullPage });\n }\n\n async navigate(session: Session, url: string): Promise<void> {\n const s = this.requireSession(session.id);\n if (s.session.platform !== \"web\") {\n throw new UnsupportedPlatformError(s.session.platform);\n }\n await s.session.page.goto(url, { waitUntil: \"domcontentloaded\" });\n this.invalidateRefs(s);\n }\n\n /**\n * Composite-only escape hatch — exposes the raw Playwright Page so a\n * composite tool that genuinely needs page-level APIs (axe-core,\n * `getByText`, etc.) can use them without bloating the Engine interface\n * with web-specific verbs. Throws if the session is not web.\n */\n getPageForSession(sessionId: string): Page {\n const s = this.requireSession(sessionId);\n if (s.session.platform !== \"web\") {\n throw new UnsupportedPlatformError(s.session.platform);\n }\n return s.session.page;\n }\n\n /** Increment generation; the next ref-using call will see them as stale. */\n bumpGeneration(sessionId: string): void {\n const s = this.requireSession(sessionId);\n this.invalidateRefs(s);\n }\n\n // -------------------------------------------------------------------------\n // Internal helpers\n // -------------------------------------------------------------------------\n\n private requireSession(sessionId: string): SessionInternals {\n const s = this.sessions.get(sessionId);\n if (!s) {\n throw new RolepodMcpError(\n \"unknown_session\",\n `No open session with id \"${sessionId}\".`,\n { session_id: sessionId },\n );\n }\n return s;\n }\n\n private resolveLocator(s: SessionInternals, ref: string): Locator {\n if (s.refGeneration !== s.snapshotGeneration) {\n throw new RolepodMcpError(\n \"stale_ref\",\n `Ref \"${ref}\" is stale — re-snapshot before retrying.`,\n {\n session_id: s.session.id,\n ref,\n last_valid_snapshot_at: s.lastSnapshotAt,\n },\n );\n }\n const meta = s.refIndex.get(ref);\n if (!meta) throw new UnknownRefError(s.session.id, ref);\n // The synthetic refs (`s1`, `s2`, ...) we issue for the wrapper root\n // are not real elements; the Lead should never click them.\n if (meta.ref.startsWith(\"s\")) {\n throw new UnknownRefError(s.session.id, ref);\n }\n return s.session.page.locator(`aria-ref=${meta.ref}`);\n }\n\n private invalidateRefs(s: SessionInternals): void {\n s.snapshotGeneration += 1;\n }\n\n /**\n * Test / shutdown helper. Closes every open session.\n */\n async shutdown(): Promise<void> {\n const ids = [...this.sessions.keys()];\n await Promise.all(\n ids.map((id) => this.close({ id, platform: \"web\" }).catch(() => undefined)),\n );\n }\n}\n","import yaml from \"js-yaml\";\nimport type { A11yNode } from \"../../schema/tools.js\";\n\n/**\n * Unified accessibility-tree normalization.\n *\n * Implements the Chromium path by parsing Playwright 1.60's\n * `page.ariaSnapshot({ mode: \"ai\" })` YAML output. Each leaf carries a\n * stable `[ref=eN]` marker that Playwright resolves back to a real\n * locator via `page.locator(\"aria-ref=eN\")`.\n *\n * Mobile A11y normalizers (XCUITest / UIAutomator2) are alumnium-inspired\n * — see THIRD_PARTY.md + UPSTREAM_TRACKING.md.\n */\n\n/** Locator metadata for ref → driver resolution. Never sent to the Lead. */\nexport type WebRefMeta = {\n kind: \"web\";\n /** The `eN` ref string. Used as `page.locator(\"aria-ref=\" + ref)`. */\n ref: string;\n};\n\nexport type RefMeta = WebRefMeta;\n\nexport type NormalizedSnapshot = {\n tree: A11yNode;\n refIndex: Map<string, RefMeta>;\n};\n\ntype YamlValue = string | YamlArray | YamlObject;\ntype YamlArray = YamlValue[];\ntype YamlObject = { [key: string]: YamlValue | null };\n\nconst KEY_RE = /^(?<role>\\S+?)(?:\\s+\"(?<name>(?:[^\"\\\\]|\\\\.)*)\")?(?<rest>(?:\\s+\\[[^\\]]+\\])*)\\s*$/;\nconst ATTR_RE = /\\[([^=\\]]+)(?:=([^\\]]+))?\\]/g;\n\ntype ParsedKey = {\n role: string;\n name?: string;\n attrs: Record<string, string>;\n};\n\nfunction parseKey(key: string): ParsedKey {\n const trimmed = key.trim();\n const m = KEY_RE.exec(trimmed);\n if (!m) {\n return { role: trimmed, attrs: {} };\n }\n const groups = m.groups!;\n const out: ParsedKey = { role: groups.role!, attrs: {} };\n if (groups.name !== undefined) out.name = unescapeQuoted(groups.name);\n const rest = groups.rest ?? \"\";\n for (const attrMatch of rest.matchAll(ATTR_RE)) {\n const [, k, v] = attrMatch;\n if (k) out.attrs[k] = v ?? \"true\";\n }\n return out;\n}\n\nfunction unescapeQuoted(s: string): string {\n return s.replace(/\\\\(.)/g, \"$1\");\n}\n\n/**\n * Parse a Playwright ai-mode aria snapshot string and produce the unified\n * A11yNode tree plus a refIndex for locator resolution.\n */\nexport function parseAriaSnapshot(snapshotYaml: string): NormalizedSnapshot {\n const refIndex = new Map<string, RefMeta>();\n let synthCounter = 0;\n const nextSynthRef = (): string => `s${++synthCounter}`;\n\n const consumeNode = (value: YamlValue): A11yNode | null => {\n // Object with one key like { 'link \"Home\" [ref=e3]': [...] | \"text\" }\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const keys = Object.keys(value);\n if (keys.length !== 1) return null;\n const key = keys[0]!;\n // Pseudo-keys like `/url` carry hyperlink metadata, not real nodes.\n if (key.startsWith(\"/\")) return null;\n const inner = value[key];\n if (typeof inner === \"string\") return buildNode(key, null, inner);\n if (Array.isArray(inner)) return buildNode(key, inner, undefined);\n return buildNode(key, null, undefined);\n }\n // Bare string like `link \"Home\" [ref=e3]` or `text \"hello\"`\n if (typeof value === \"string\") {\n return buildNode(value, null, undefined);\n }\n return null;\n };\n\n const buildNode = (\n key: string,\n rawChildren: YamlValue | null | undefined,\n inlineText: string | undefined,\n ): A11yNode => {\n const parsed = parseKey(key);\n const ref = parsed.attrs.ref ?? nextSynthRef();\n refIndex.set(ref, { kind: \"web\", ref });\n\n const node: A11yNode = {\n ref,\n role: parsed.role,\n };\n if (parsed.name !== undefined) node.name = parsed.name;\n if (inlineText !== undefined) {\n node.value = inlineText;\n } else if (parsed.attrs.level) {\n node.value = parsed.attrs.level;\n }\n\n const state: A11yNode[\"state\"] = {};\n if (\"disabled\" in parsed.attrs) state.disabled = parsed.attrs.disabled !== \"false\";\n if (\"focused\" in parsed.attrs) state.focused = parsed.attrs.focused !== \"false\";\n if (\"selected\" in parsed.attrs) state.selected = parsed.attrs.selected !== \"false\";\n if (\"expanded\" in parsed.attrs) state.expanded = parsed.attrs.expanded !== \"false\";\n if (Object.keys(state).length > 0) node.state = state;\n\n if (Array.isArray(rawChildren)) {\n const children: A11yNode[] = [];\n for (const child of rawChildren) {\n const built = consumeNode(child);\n if (built) children.push(built);\n }\n if (children.length > 0) node.children = children;\n }\n return node;\n };\n\n let loaded: YamlValue;\n try {\n loaded = (yaml.load(snapshotYaml) as YamlValue) ?? [];\n } catch {\n loaded = [];\n }\n\n const topLevel: A11yNode[] = [];\n if (Array.isArray(loaded)) {\n for (const entry of loaded) {\n const node = consumeNode(entry);\n if (node) topLevel.push(node);\n }\n } else if (loaded && typeof loaded === \"object\") {\n const node = consumeNode(loaded);\n if (node) topLevel.push(node);\n } else if (typeof loaded === \"string\" && loaded.length > 0) {\n const node = consumeNode(loaded);\n if (node) topLevel.push(node);\n }\n\n // The composite needs a single root. Wrap when there are 0 or >1 entries.\n if (topLevel.length === 1) {\n return { tree: topLevel[0]!, refIndex };\n }\n const rootRef = nextSynthRef();\n refIndex.set(rootRef, { kind: \"web\", ref: rootRef });\n const root: A11yNode = { ref: rootRef, role: \"RootWebArea\" };\n if (topLevel.length > 0) root.children = topLevel;\n return { tree: root, refIndex };\n}\n","import { RolepodMcpError } from \"../util/errors.js\";\nimport { AppiumEngine } from \"./AppiumEngine.js\";\nimport { PlaywrightEngine } from \"./PlaywrightEngine.js\";\nimport type { Engine } from \"./Engine.js\";\n\n/**\n * Engine selection happens once at server startup. v0.3 wires\n * Playwright for `web` and Appium for `ios`/`android`. The\n * `ROLEPOD_MCP_WEB_ENGINE` env var (D-012) only governs the *web*\n * engine; mobile always routes to Appium.\n */\nexport function createWebEngine(): Engine {\n const choice = (process.env.ROLEPOD_MCP_WEB_ENGINE ?? \"playwright\").toLowerCase();\n switch (choice) {\n case \"playwright\":\n return new PlaywrightEngine();\n case \"selenium\":\n throw new RolepodMcpError(\n \"unsupported_engine\",\n \"SeleniumEngine ships in v0.4 — set ROLEPOD_MCP_WEB_ENGINE=playwright until then.\",\n { requested: choice },\n );\n default:\n throw new RolepodMcpError(\n \"unsupported_engine\",\n `Unknown web engine \"${choice}\" — supported: playwright.`,\n { requested: choice },\n );\n }\n}\n\nexport function createMobileEngine(): Engine {\n return new AppiumEngine();\n}\n\n/** Back-compat alias for v0.1 callers. */\nexport function createEngine(): Engine {\n return createWebEngine();\n}\n","import { UnknownSessionError, UnsupportedPlatformError } from \"../util/errors.js\";\nimport { log } from \"../util/log.js\";\nimport type { Engine, OpenOptions, Platform, Session } from \"../engine/Engine.js\";\n\n/**\n * Routes sessions to the correct engine and enforces idle-timeout cleanup.\n *\n * v0.1: only PlaywrightEngine is wired up, so every `platform: 'web'`\n * request goes there. AppiumEngine (v0.3) will register against the\n * `ios`/`android` platform keys without touching tool code.\n */\nexport class SessionRegistry {\n private readonly enginesByPlatform = new Map<Platform, Engine>();\n private readonly engineBySession = new Map<string, Engine>();\n private readonly platformBySession = new Map<string, Platform>();\n private readonly lastActivity = new Map<string, number>();\n private readonly idleTimeoutMs: number;\n private idleTimer: NodeJS.Timeout | null = null;\n\n constructor(opts: { idleTimeoutMs?: number } = {}) {\n this.idleTimeoutMs = opts.idleTimeoutMs ?? 5 * 60 * 1000;\n }\n\n /** Register an engine as the handler for a given platform. */\n register(platform: Platform, engine: Engine): void {\n this.enginesByPlatform.set(platform, engine);\n }\n\n async open(opts: OpenOptions): Promise<Session> {\n const engine = this.enginesByPlatform.get(opts.platform);\n if (!engine) throw new UnsupportedPlatformError(opts.platform);\n const session = await engine.open(opts);\n this.engineBySession.set(session.id, engine);\n this.platformBySession.set(session.id, session.platform);\n this.touch(session.id);\n this.ensureIdleSweep();\n return session;\n }\n\n engineFor(sessionId: string): Engine {\n const engine = this.engineBySession.get(sessionId);\n if (!engine) throw new UnknownSessionError(sessionId);\n this.touch(sessionId);\n return engine;\n }\n\n async close(session: Session): Promise<void> {\n const engine = this.engineBySession.get(session.id);\n if (!engine) throw new UnknownSessionError(session.id);\n await engine.close(session);\n this.engineBySession.delete(session.id);\n this.platformBySession.delete(session.id);\n this.lastActivity.delete(session.id);\n }\n\n /** Look up the platform recorded for an open session. */\n platformOf(sessionId: string): Platform {\n const platform = this.platformBySession.get(sessionId);\n if (!platform) throw new UnknownSessionError(sessionId);\n return platform;\n }\n\n async shutdown(): Promise<void> {\n if (this.idleTimer) {\n clearInterval(this.idleTimer);\n this.idleTimer = null;\n }\n const closes: Array<Promise<void>> = [];\n for (const [sessionId, engine] of this.engineBySession) {\n const platform = this.platformFor(sessionId);\n closes.push(\n engine\n .close({ id: sessionId, platform })\n .catch((err: unknown) =>\n log.warn(\"shutdown close failed\", { sessionId, err: String(err) }),\n ),\n );\n }\n await Promise.all(closes);\n this.engineBySession.clear();\n this.platformBySession.clear();\n this.lastActivity.clear();\n }\n\n private touch(sessionId: string): void {\n this.lastActivity.set(sessionId, Date.now());\n }\n\n private platformFor(sessionId: string): Platform {\n return this.platformBySession.get(sessionId) ?? \"web\";\n }\n\n private ensureIdleSweep(): void {\n if (this.idleTimer || this.idleTimeoutMs <= 0) return;\n const interval = Math.max(30_000, Math.floor(this.idleTimeoutMs / 4));\n this.idleTimer = setInterval(() => {\n const cutoff = Date.now() - this.idleTimeoutMs;\n for (const [sessionId, lastSeen] of this.lastActivity) {\n if (lastSeen < cutoff) {\n const engine = this.engineBySession.get(sessionId);\n if (!engine) {\n this.lastActivity.delete(sessionId);\n continue;\n }\n log.info(\"idle session sweep — closing\", { sessionId });\n engine\n .close({ id: sessionId, platform: this.platformFor(sessionId) })\n .catch((err: unknown) =>\n log.warn(\"idle close failed\", { sessionId, err: String(err) }),\n )\n .finally(() => {\n this.engineBySession.delete(sessionId);\n this.lastActivity.delete(sessionId);\n });\n }\n }\n }, interval);\n this.idleTimer.unref();\n }\n}\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Shared building blocks\n// ---------------------------------------------------------------------------\n\nexport const platformSchema = z.enum([\"web\", \"ios\", \"android\"]);\nexport const browserSchema = z.enum([\"chromium\", \"firefox\", \"webkit\"]);\n\nexport const viewportSchema = z.object({\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n});\n\nexport const bboxSchema = z.object({\n x: z.number(),\n y: z.number(),\n w: z.number(),\n h: z.number(),\n});\n\nexport const a11yStateSchema = z.object({\n focused: z.boolean().optional(),\n selected: z.boolean().optional(),\n expanded: z.boolean().optional(),\n disabled: z.boolean().optional(),\n});\n\nexport type A11yNode = {\n ref: string;\n role: string;\n name?: string;\n value?: string;\n state?: z.infer<typeof a11yStateSchema>;\n bbox?: z.infer<typeof bboxSchema>;\n children?: A11yNode[];\n};\n\nexport const a11yNodeSchema: z.ZodType<A11yNode> = z.lazy(() =>\n z.object({\n ref: z.string(),\n role: z.string(),\n name: z.string().optional(),\n value: z.string().optional(),\n state: a11yStateSchema.optional(),\n bbox: bboxSchema.optional(),\n children: z.array(a11yNodeSchema).optional(),\n }),\n);\n\nexport const waitConditionSchema = z.discriminatedUnion(\"kind\", [\n z.object({ kind: z.literal(\"text_visible\"), text: z.string() }),\n z.object({ kind: z.literal(\"ref_exists\"), query: z.string() }),\n z.object({ kind: z.literal(\"url_matches\"), pattern: z.string() }),\n z.object({ kind: z.literal(\"idle\"), ms: z.number().int().positive() }),\n]);\n\n// ---------------------------------------------------------------------------\n// Atomic tools — input shapes\n//\n// NOTE: MCP SDK's `registerTool({ inputSchema })` expects a Zod *raw shape*\n// (a plain object whose values are Zod schemas), NOT a `z.object(...)`. We\n// export both the raw shape (for the SDK) and a derived `z.object` (for\n// internal parsing / type inference).\n// ---------------------------------------------------------------------------\n\nexport const browserOpenShape = {\n platform: platformSchema.default(\"web\"),\n url: z.string().url().optional(),\n browser: browserSchema.optional(),\n viewport: viewportSchema.optional(),\n // mobile fields kept for forward compat; v0.1 only handles platform='web'\n bundle_id: z.string().optional(),\n device: z.string().optional(),\n app_package: z.string().optional(),\n app_activity: z.string().optional(),\n emulator: z.string().optional(),\n headless: z.boolean().optional(),\n user_agent: z.string().optional(),\n locale: z.string().optional(),\n} as const;\nexport const browserOpenSchema = z.object(browserOpenShape);\nexport type BrowserOpenInput = z.infer<typeof browserOpenSchema>;\n\nexport const browserCloseShape = {\n session_id: z.string().min(1),\n} as const;\nexport const browserCloseSchema = z.object(browserCloseShape);\nexport type BrowserCloseInput = z.infer<typeof browserCloseSchema>;\n\nexport const browserSnapshotShape = {\n session_id: z.string().min(1),\n mode: z.enum([\"visible\", \"full\"]).optional(),\n} as const;\nexport const browserSnapshotSchema = z.object(browserSnapshotShape);\nexport type BrowserSnapshotInput = z.infer<typeof browserSnapshotSchema>;\n\nexport const browserClickShape = {\n session_id: z.string().min(1),\n ref: z.string().min(1),\n button: z.enum([\"left\", \"right\", \"middle\"]).optional(),\n} as const;\nexport const browserClickSchema = z.object(browserClickShape);\nexport type BrowserClickInput = z.infer<typeof browserClickSchema>;\n\nexport const browserTypeShape = {\n session_id: z.string().min(1),\n ref: z.string().min(1),\n text: z.string(),\n clear_first: z.boolean().optional(),\n} as const;\nexport const browserTypeSchema = z.object(browserTypeShape);\nexport type BrowserTypeInput = z.infer<typeof browserTypeSchema>;\n\nexport const browserKeyShape = {\n session_id: z.string().min(1),\n key: z.string().min(1),\n} as const;\nexport const browserKeySchema = z.object(browserKeyShape);\nexport type BrowserKeyInput = z.infer<typeof browserKeySchema>;\n\nexport const browserScrollShape = {\n session_id: z.string().min(1),\n direction: z.enum([\"up\", \"down\", \"left\", \"right\"]),\n amount: z.number().int().positive().optional(),\n ref: z.string().min(1).optional(),\n} as const;\nexport const browserScrollSchema = z.object(browserScrollShape);\nexport type BrowserScrollInput = z.infer<typeof browserScrollSchema>;\n\nexport const browserWaitForShape = {\n session_id: z.string().min(1),\n condition: waitConditionSchema,\n timeout_ms: z.number().int().positive().optional(),\n} as const;\nexport const browserWaitForSchema = z.object(browserWaitForShape);\nexport type BrowserWaitForInput = z.infer<typeof browserWaitForSchema>;\n\nexport const browserScreenshotShape = {\n session_id: z.string().min(1),\n full_page: z.boolean().optional(),\n} as const;\nexport const browserScreenshotSchema = z.object(browserScreenshotShape);\nexport type BrowserScreenshotInput = z.infer<typeof browserScreenshotSchema>;\n\nexport const browserNavigateShape = {\n session_id: z.string().min(1),\n url: z.string().url(),\n} as const;\nexport const browserNavigateSchema = z.object(browserNavigateShape);\nexport type BrowserNavigateInput = z.infer<typeof browserNavigateSchema>;\n\n// ---------------------------------------------------------------------------\n// Composite verify_ui_flow\n//\n// Both `mode: 'assert'` and `mode: 'reproduce'` are implemented (D-025).\n// When mode='reproduce' && passed && minimize, the composite runs a\n// classic ddmin pass over `steps` and adds a `minimized` block to the\n// output carrying the surviving step list and a `replay-minimized.json`\n// artifact path.\n// ---------------------------------------------------------------------------\n\nexport const verifyStepSchema = z.discriminatedUnion(\"kind\", [\n z.object({ kind: z.literal(\"click\"), query: z.string() }),\n z.object({\n kind: z.literal(\"type\"),\n query: z.string(),\n text: z.string(),\n clear_first: z.boolean().optional(),\n }),\n z.object({ kind: z.literal(\"key\"), key: z.string() }),\n z.object({ kind: z.literal(\"wait_for\"), condition: waitConditionSchema }),\n z.object({ kind: z.literal(\"navigate\"), url: z.string().url() }),\n]);\n\nexport const verifyExpectSchema = z.discriminatedUnion(\"kind\", [\n z.object({ kind: z.literal(\"text_visible\"), text: z.string() }),\n z.object({ kind: z.literal(\"text_absent\"), text: z.string() }),\n z.object({ kind: z.literal(\"url_matches\"), pattern: z.string() }),\n z.object({\n kind: z.literal(\"ref_in_state\"),\n query: z.string(),\n state: z.enum([\"visible\", \"enabled\", \"focused\"]),\n }),\n]);\n\nexport const captureKindSchema = z.enum([\n \"screenshot\",\n \"har\",\n \"console\",\n \"a11y_tree\",\n \"video\",\n]);\n\nexport const verifyUiFlowShape = {\n mode: z.enum([\"assert\", \"reproduce\"]).default(\"assert\"),\n open: browserOpenSchema,\n steps: z.array(verifyStepSchema).default([]),\n expect: z.array(verifyExpectSchema).default([]),\n capture: z.array(captureKindSchema).optional(),\n close_on_finish: z.boolean().default(true),\n /**\n * Only consulted when `mode='reproduce'`. When true (default) and the\n * initial run reproduces the bug, the composite tries to remove each\n * step in turn and re-runs to find a smaller reproducer.\n */\n minimize: z.boolean().default(true),\n} as const;\nexport const verifyUiFlowSchema = z.object(verifyUiFlowShape);\nexport type VerifyUiFlowInput = z.infer<typeof verifyUiFlowSchema>;\n\n// ---------------------------------------------------------------------------\n// audit_a11y\n// ---------------------------------------------------------------------------\n\nexport const wcagLevelSchema = z.enum([\"wcag-a\", \"wcag-aa\", \"wcag-aaa\"]);\nexport const a11ySeveritySchema = z.enum([\n \"critical\",\n \"serious\",\n \"moderate\",\n \"minor\",\n]);\nexport const auditScopeSchema = z.union([\n z.literal(\"page\"),\n z.object({ ref: z.string().min(1) }),\n]);\n\nexport const auditA11yShape = {\n open: browserOpenSchema,\n level: wcagLevelSchema.default(\"wcag-aa\"),\n scope: auditScopeSchema.default(\"page\"),\n report_format: z.enum([\"json\", \"markdown\"]).default(\"json\"),\n close_on_finish: z.boolean().default(true),\n} as const;\nexport const auditA11ySchema = z.object(auditA11yShape);\nexport type AuditA11yInput = z.infer<typeof auditA11ySchema>;\n\n// ---------------------------------------------------------------------------\n// visual_diff\n// ---------------------------------------------------------------------------\n\nexport const visualDiffShape = {\n open: browserOpenSchema,\n baseline_id: z.string().min(1),\n viewport: viewportSchema.optional(),\n threshold_pct: z.number().min(0).max(1).default(0.1),\n close_on_finish: z.boolean().default(true),\n /** Pixel sensitivity for pixelmatch (0 = strict, 1 = lax). Default 0.1. */\n pixel_threshold: z.number().min(0).max(1).default(0.1),\n} as const;\nexport const visualDiffSchema = z.object(visualDiffShape);\nexport type VisualDiffInput = z.infer<typeof visualDiffSchema>;\n\n// ---------------------------------------------------------------------------\n// scaffold_e2e\n// ---------------------------------------------------------------------------\n\nexport const e2eFrameworkSchema = z.enum([\n \"playwright-test\",\n \"vitest+playwright\",\n \"pytest+selenium\",\n]);\n\nexport const scaffoldE2eShape = {\n framework: e2eFrameworkSchema,\n scenario_nl: z.string().min(1),\n url: z.string().url(),\n recorded_bundle: z.string().min(1).optional(),\n /** Override the generated test file name. */\n filename: z.string().min(1).optional(),\n} as const;\nexport const scaffoldE2eSchema = z.object(scaffoldE2eShape);\nexport type ScaffoldE2eInput = z.infer<typeof scaffoldE2eSchema>;\n\n// ---------------------------------------------------------------------------\n// extract_ui_state — used internally by other shipped skills (not user-facing).\n// ---------------------------------------------------------------------------\n\nexport const extractUiStateShape = {\n session_id: z.string().min(1).optional(),\n open: browserOpenSchema.optional(),\n question_nl: z.string().min(1),\n close_on_finish: z.boolean().default(false),\n} as const;\nexport const extractUiStateSchema = z.object(extractUiStateShape);\nexport type ExtractUiStateInput = z.infer<typeof extractUiStateSchema>;\n\n// ---------------------------------------------------------------------------\n// Tool name registry — single source of truth for tool naming.\n// All names are prefixed `rolepod_*` per brief 03-tool-surface.md.\n// ---------------------------------------------------------------------------\n\nexport const ToolNames = {\n browserOpen: \"rolepod_browser_open\",\n browserClose: \"rolepod_browser_close\",\n browserSnapshot: \"rolepod_browser_snapshot\",\n browserClick: \"rolepod_browser_click\",\n browserType: \"rolepod_browser_type\",\n browserKey: \"rolepod_browser_key\",\n browserScroll: \"rolepod_browser_scroll\",\n browserWaitFor: \"rolepod_browser_wait_for\",\n browserScreenshot: \"rolepod_browser_screenshot\",\n browserNavigate: \"rolepod_browser_navigate\",\n verifyUiFlow: \"rolepod_verify_ui_flow\",\n auditA11y: \"rolepod_audit_a11y\",\n visualDiff: \"rolepod_visual_diff\",\n scaffoldE2e: \"rolepod_scaffold_e2e\",\n extractUiState: \"rolepod_extract_ui_state\",\n} as const;\n\nexport type ToolName = (typeof ToolNames)[keyof typeof ToolNames];\n","/**\n * Classic delta-debugging minimization (`ddmin`) — Zeller & Hildebrandt,\n * 2002. Given a sequence `input` and a predicate `reproduces(subset)`\n * that returns true when the subset still triggers the target outcome,\n * returns a 1-minimal subset.\n *\n * The algorithm is bounded by `O(N log N)` predicate calls in the\n * common case and `O(N²)` in the worst case — but each call is an\n * expensive browser run, so the caller is encouraged to cap the run\n * count separately if needed.\n */\nexport type DdminPredicate<T> = (subset: T[]) => Promise<boolean>;\n\nexport async function ddmin<T>(input: T[], reproduces: DdminPredicate<T>): Promise<T[]> {\n let current = [...input];\n let n = 2;\n while (current.length >= 2) {\n const chunkSize = Math.max(1, Math.floor(current.length / n));\n let reduced = false;\n\n // Try removing each chunk (delta) one at a time.\n for (let i = 0; i < current.length; i += chunkSize) {\n const complement = [\n ...current.slice(0, i),\n ...current.slice(i + chunkSize),\n ];\n if (complement.length === 0) continue;\n if (await reproduces(complement)) {\n current = complement;\n n = Math.max(n - 1, 2);\n reduced = true;\n break;\n }\n }\n if (reduced) continue;\n\n // No single delta worked — increase granularity.\n if (n >= current.length) break;\n n = Math.min(n * 2, current.length);\n }\n return current;\n}\n","import type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { RolepodMcpError } from \"../util/errors.js\";\n\n/**\n * Pack a successful tool result into the MCP wire format. The same value\n * is emitted both as a text content block (for the Lead to read) and as\n * `structuredContent` (for any client that prefers typed JSON).\n */\nexport function ok(value: unknown): CallToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify(value, null, 2) }],\n structuredContent: value as Record<string, unknown>,\n };\n}\n\n/**\n * Pack a structured error. RolepodMcpError surfaces a stable error code +\n * detail bag; anything else degrades to \"engine_error\" with the message.\n */\nexport function failure(err: unknown): CallToolResult {\n if (err instanceof RolepodMcpError) {\n const payload = err.toJSON();\n return {\n isError: true,\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n structuredContent: payload as unknown as Record<string, unknown>,\n };\n }\n const message = err instanceof Error ? err.message : String(err);\n const payload = { code: \"engine_error\" as const, message };\n return {\n isError: true,\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n structuredContent: payload as unknown as Record<string, unknown>,\n };\n}\n\n/** Wrap a handler so any thrown error is converted to a structured failure. */\nexport function safeHandler<Args>(\n fn: (args: Args) => Promise<CallToolResult>,\n): (args: Args) => Promise<CallToolResult> {\n return async (args: Args) => {\n try {\n return await fn(args);\n } catch (err) {\n return failure(err);\n }\n };\n}\n","import {\n ToolNames,\n verifyUiFlowShape,\n type A11yNode,\n type VerifyUiFlowInput,\n} from \"../../schema/tools.js\";\nimport type { A11ySnapshot, Engine, Session } from \"../../engine/Engine.js\";\nimport { ddmin } from \"../../replay/minimize.js\";\nimport { RolepodMcpError } from \"../../util/errors.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolContext, ToolModule } from \"../types.js\";\n\n/**\n * Composite `verify_ui_flow` — drive a session through steps and evaluate\n * expectations against the resulting state.\n *\n * - `mode: 'assert'` (default): pass = \"expected feature works\".\n * - `mode: 'reproduce'`: pass = \"expected bug surfaced\". When `minimize`\n * is true (default) and the initial run reproduces, the composite\n * performs a linear delta-removal pass over `steps` to find a smaller\n * sequence that still reproduces. See D-025.\n */\nexport const verifyUiFlowTool: ToolModule<typeof verifyUiFlowShape> = {\n name: ToolNames.verifyUiFlow,\n description:\n \"Open a session, run UI steps, evaluate assertions, and save evidence. Set mode='reproduce' for bug reproduction with optional step minimization.\",\n inputShape: verifyUiFlowShape,\n build(ctx) {\n return safeHandler(async (args: VerifyUiFlowInput) => {\n const { runId, runDir } = await ctx.store.startRun(\"verify\");\n\n const initial = await runFlow(ctx, args, args.steps, runDir, {\n captureEvidence: true,\n bundleName: \"replay.json\",\n });\n\n const result: Record<string, unknown> = {\n run_id: runId,\n mode: args.mode,\n passed: initial.passed,\n evidence_paths: initial.evidence,\n };\n if (initial.failedAtStep !== undefined) result.failed_at_step = initial.failedAtStep;\n if (initial.failureReason !== undefined) result.failure_reason = initial.failureReason;\n if (initial.finalUrl !== undefined) result.final_url_or_screen = initial.finalUrl;\n\n if (args.mode === \"reproduce\" && initial.passed && args.minimize) {\n const min = await minimize(ctx, args, args.steps, runDir);\n result.minimized = {\n original_step_count: args.steps.length,\n minimized_step_count: min.steps.length,\n minimal_steps: min.steps,\n steps_removed: min.removed,\n replay_bundle: min.replayPath,\n attempts: min.attempts,\n };\n }\n\n return ok(result);\n });\n },\n};\n\n// ---------------------------------------------------------------------------\n// Core single-run logic — shared by the initial run and every minimization\n// attempt.\n// ---------------------------------------------------------------------------\n\ntype RunOutcome = {\n passed: boolean;\n failedAtStep?: number;\n failureReason?: string;\n finalUrl?: string;\n evidence: { screenshots: string[]; replay_bundle?: string };\n};\n\nasync function runFlow(\n ctx: ToolContext,\n args: VerifyUiFlowInput,\n steps: VerifyUiFlowInput[\"steps\"],\n runDir: string,\n opts: { captureEvidence: boolean; bundleName: string },\n): Promise<RunOutcome> {\n const evidence: { screenshots: string[]; replay_bundle?: string } = { screenshots: [] };\n let passed = false;\n let failedAtStep: number | undefined;\n let failureReason: string | undefined;\n let finalSnapshot: A11ySnapshot | undefined;\n\n const session = await ctx.registry.open(args.open);\n const engine = ctx.registry.engineFor(session.id);\n const sessionHandle: Session = { id: session.id, platform: session.platform };\n\n try {\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]!;\n const beforeSnap = await engine.snapshot(sessionHandle);\n try {\n await runStep(engine, sessionHandle, step, beforeSnap);\n } catch (err) {\n failedAtStep = i;\n failureReason = `Step ${i} (${step.kind}) failed: ${describeError(err)}`;\n throw err;\n }\n }\n\n finalSnapshot = await engine.snapshot(sessionHandle);\n const failures: string[] = [];\n for (let i = 0; i < args.expect.length; i++) {\n const expectation = args.expect[i]!;\n if (!evaluateExpect(expectation, finalSnapshot)) {\n failures.push(`expect[${i}] ${describeExpect(expectation)}`);\n }\n }\n if (failures.length === 0) {\n passed = true;\n } else {\n failureReason = `Expectations failed: ${failures.join(\"; \")}`;\n }\n } catch (err) {\n if (!failureReason) failureReason = describeError(err);\n passed = false;\n } finally {\n if (opts.captureEvidence) {\n const wantScreenshot = !args.capture || args.capture.includes(\"screenshot\");\n if (wantScreenshot) {\n try {\n const buf = await engine.screenshot(sessionHandle, true);\n const p = await ctx.store.writeScreenshot(runDir, buf, \"final\");\n evidence.screenshots.push(p);\n } catch (err) {\n failureReason ??= `screenshot capture failed: ${describeError(err)}`;\n }\n }\n try {\n evidence.replay_bundle = await ctx.store.writeReplayBundle(\n runDir,\n {\n version: 1,\n run_id: runDir.split(\"/\").pop() ?? \"run\",\n recorded_at: new Date().toISOString(),\n open: args.open as unknown as Record<string, unknown>,\n steps: steps as unknown as Record<string, unknown>[],\n expect: args.expect as unknown as Record<string, unknown>[],\n },\n opts.bundleName,\n );\n } catch {\n /* swallow — replay bundle is best-effort */\n }\n }\n if (args.close_on_finish) {\n await ctx.registry.close(sessionHandle).catch(() => undefined);\n }\n }\n\n const out: RunOutcome = { passed, evidence };\n if (failedAtStep !== undefined) out.failedAtStep = failedAtStep;\n if (failureReason !== undefined) out.failureReason = failureReason;\n if (finalSnapshot) out.finalUrl = finalSnapshot.url_or_screen;\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Linear delta-removal — naive but bounded by the step count.\n// ---------------------------------------------------------------------------\n\ntype MinimizeResult = {\n steps: VerifyUiFlowInput[\"steps\"];\n removed: number[];\n attempts: number;\n replayPath: string | undefined;\n};\n\nasync function minimize(\n ctx: ToolContext,\n args: VerifyUiFlowInput,\n initialSteps: VerifyUiFlowInput[\"steps\"],\n runDir: string,\n): Promise<MinimizeResult> {\n // Tag each step with its original index so we can report what was removed.\n type Tagged = { step: VerifyUiFlowInput[\"steps\"][number]; origIndex: number };\n const tagged: Tagged[] = initialSteps.map((step, origIndex) => ({ step, origIndex }));\n let attempts = 0;\n\n const predicate = async (subset: Tagged[]): Promise<boolean> => {\n attempts += 1;\n const outcome = await runFlow(\n ctx,\n args,\n subset.map((t) => t.step),\n runDir,\n { captureEvidence: false, bundleName: \"minimize-tmp.json\" },\n );\n return outcome.passed;\n };\n\n const minimal = await ddmin(tagged, predicate);\n const remainingIdx = new Set(minimal.map((t) => t.origIndex));\n const removed = tagged\n .map((t) => t.origIndex)\n .filter((i) => !remainingIdx.has(i));\n\n // One final capture run with the minimized sequence to anchor evidence.\n let replayPath: string | undefined;\n if (minimal.length !== initialSteps.length) {\n const finalRun = await runFlow(\n ctx,\n args,\n minimal.map((t) => t.step),\n runDir,\n { captureEvidence: true, bundleName: \"replay-minimized.json\" },\n );\n replayPath = finalRun.evidence.replay_bundle;\n }\n return {\n steps: minimal.map((t) => t.step),\n removed: removed.sort((a, b) => a - b),\n attempts,\n replayPath,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Step + expect evaluation helpers (shared with mode='assert').\n// ---------------------------------------------------------------------------\n\nasync function runStep(\n engine: Engine,\n session: Session,\n step: VerifyUiFlowInput[\"steps\"][number],\n snap: A11ySnapshot,\n): Promise<void> {\n switch (step.kind) {\n case \"click\": {\n const ref = findRefByQuery(snap.tree, step.query);\n if (!ref) throw missingQuery(step.query);\n await engine.click(session, ref);\n return;\n }\n case \"type\": {\n const ref = findRefByQuery(snap.tree, step.query);\n if (!ref) throw missingQuery(step.query);\n await engine.type(\n session,\n ref,\n step.text,\n step.clear_first ? { clearFirst: true } : undefined,\n );\n return;\n }\n case \"key\":\n await engine.key(session, step.key);\n return;\n case \"wait_for\":\n await engine.waitFor(session, step.condition);\n return;\n case \"navigate\":\n await engine.navigate(session, step.url);\n return;\n }\n}\n\nfunction evaluateExpect(\n exp: VerifyUiFlowInput[\"expect\"][number],\n snap: A11ySnapshot,\n): boolean {\n switch (exp.kind) {\n case \"text_visible\":\n return treeHasText(snap.tree, exp.text);\n case \"text_absent\":\n return !treeHasText(snap.tree, exp.text);\n case \"url_matches\":\n return new RegExp(exp.pattern).test(snap.url_or_screen);\n case \"ref_in_state\": {\n const node = findNodeByQuery(snap.tree, exp.query);\n if (!node) return false;\n switch (exp.state) {\n case \"visible\":\n return true;\n case \"enabled\":\n return node.state?.disabled !== true;\n case \"focused\":\n return node.state?.focused === true;\n }\n }\n }\n}\n\nfunction describeExpect(exp: VerifyUiFlowInput[\"expect\"][number]): string {\n switch (exp.kind) {\n case \"text_visible\":\n return `text_visible \"${exp.text}\"`;\n case \"text_absent\":\n return `text_absent \"${exp.text}\"`;\n case \"url_matches\":\n return `url_matches /${exp.pattern}/`;\n case \"ref_in_state\":\n return `ref_in_state \"${exp.query}\" → ${exp.state}`;\n }\n}\n\nfunction missingQuery(query: string): RolepodMcpError {\n return new RolepodMcpError(\n \"invalid_input\",\n `No element matched query \"${query}\" in the current snapshot.`,\n { query },\n );\n}\n\nfunction describeError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction findRefByQuery(tree: A11yNode, query: string): string | null {\n const node = findNodeByQuery(tree, query);\n return node ? node.ref : null;\n}\n\nfunction findNodeByQuery(tree: A11yNode, query: string): A11yNode | null {\n const target = query.toLowerCase();\n const visit = (node: A11yNode): A11yNode | null => {\n if (\n (node.name && node.name.toLowerCase().includes(target)) ||\n (node.value && node.value.toLowerCase().includes(target))\n ) {\n return node;\n }\n if (node.children) {\n for (const c of node.children) {\n const hit = visit(c);\n if (hit) return hit;\n }\n }\n return null;\n };\n return visit(tree);\n}\n\nfunction treeHasText(tree: A11yNode, text: string): boolean {\n const target = text.toLowerCase();\n const visit = (node: A11yNode): boolean => {\n if (\n (node.name && node.name.toLowerCase().includes(target)) ||\n (node.value && node.value.toLowerCase().includes(target))\n ) {\n return true;\n }\n return node.children?.some(visit) ?? false;\n };\n return visit(tree);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { ArtifactStore } from \"./artifact/ArtifactStore.js\";\nimport { createMobileEngine, createWebEngine } from \"./engine/factory.js\";\nimport { SessionRegistry } from \"./session/SessionRegistry.js\";\nimport { browserClickTool } from \"./tools/atomic/browser_click.js\";\nimport { browserCloseTool } from \"./tools/atomic/browser_close.js\";\nimport { browserKeyTool } from \"./tools/atomic/browser_key.js\";\nimport { browserNavigateTool } from \"./tools/atomic/browser_navigate.js\";\nimport { browserOpenTool } from \"./tools/atomic/browser_open.js\";\nimport { browserScreenshotTool } from \"./tools/atomic/browser_screenshot.js\";\nimport { browserScrollTool } from \"./tools/atomic/browser_scroll.js\";\nimport { browserSnapshotTool } from \"./tools/atomic/browser_snapshot.js\";\nimport { browserTypeTool } from \"./tools/atomic/browser_type.js\";\nimport { browserWaitForTool } from \"./tools/atomic/browser_wait_for.js\";\nimport { auditA11yTool } from \"./tools/composite/audit_a11y.js\";\nimport { extractUiStateTool } from \"./tools/composite/extract_ui_state.js\";\nimport { scaffoldE2eTool } from \"./tools/composite/scaffold_e2e.js\";\nimport { verifyUiFlowTool } from \"./tools/composite/verify_ui_flow.js\";\nimport { visualDiffTool } from \"./tools/composite/visual_diff.js\";\nimport type { ToolContext } from \"./tools/types.js\";\nimport { log } from \"./util/log.js\";\n\nexport const SERVER_NAME = \"rolepod-uiproof\";\nexport const SERVER_VERSION = \"0.4.0\";\n\nexport type ServerHandle = {\n mcp: McpServer;\n registry: SessionRegistry;\n store: ArtifactStore;\n shutdown(): Promise<void>;\n};\n\n/**\n * Build the MCP server with every v0.1 tool registered. Caller is\n * responsible for choosing a transport (stdio for production, in-memory\n * for tests) and invoking `mcp.connect(transport)`.\n */\nexport function buildServer(\n opts: { artifactRoot?: string; idleTimeoutMs?: number } = {},\n): ServerHandle {\n const webEngine = createWebEngine();\n const registry = new SessionRegistry({ idleTimeoutMs: opts.idleTimeoutMs });\n registry.register(\"web\", webEngine);\n // Mobile engines are lazy — the webdriverio import only fires when an\n // `ios`/`android` session is actually opened. So registering Appium\n // unconditionally is safe for web-only installs.\n const mobileEngine = createMobileEngine();\n registry.register(\"ios\", mobileEngine);\n registry.register(\"android\", mobileEngine);\n\n const storeOpts: ConstructorParameters<typeof ArtifactStore>[0] = {};\n if (opts.artifactRoot !== undefined) storeOpts.rootDir = opts.artifactRoot;\n const store = new ArtifactStore(storeOpts);\n\n const ctx: ToolContext = { registry, store };\n\n const mcp = new McpServer({\n name: SERVER_NAME,\n version: SERVER_VERSION,\n });\n\n const tools = [\n // atomic\n browserOpenTool,\n browserCloseTool,\n browserSnapshotTool,\n browserClickTool,\n browserTypeTool,\n browserKeyTool,\n browserScrollTool,\n browserWaitForTool,\n browserScreenshotTool,\n browserNavigateTool,\n // composite\n verifyUiFlowTool,\n auditA11yTool,\n visualDiffTool,\n scaffoldE2eTool,\n extractUiStateTool,\n ] as const;\n\n for (const t of tools) {\n mcp.registerTool(\n t.name,\n { description: t.description, inputSchema: t.inputShape },\n t.build(ctx) as Parameters<typeof mcp.registerTool>[2],\n );\n }\n\n log.info(\"rolepod-uiproof server built\", {\n version: SERVER_VERSION,\n tools: tools.map((t) => t.name),\n });\n\n return {\n mcp,\n registry,\n store,\n async shutdown() {\n await registry.shutdown();\n await mcp.close().catch(() => undefined);\n },\n };\n}\n","import { browserClickShape, ToolNames, type BrowserClickInput } from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserClickTool: ToolModule<typeof browserClickShape> = {\n name: ToolNames.browserClick,\n description:\n \"Click the element identified by `ref` from the most recent snapshot. Invalidates all refs on success.\",\n inputShape: browserClickShape,\n build(ctx) {\n return safeHandler(async (args: BrowserClickInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n await engine.click(\n { id: args.session_id, platform: ctx.registry.platformOf(args.session_id) },\n args.ref,\n args.button ? { button: args.button } : undefined,\n );\n return ok({ clicked: true });\n });\n },\n};\n","import { browserCloseShape, ToolNames, type BrowserCloseInput } from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserCloseTool: ToolModule<typeof browserCloseShape> = {\n name: ToolNames.browserClose,\n description: \"Close an open session and free its browser / driver resources.\",\n inputShape: browserCloseShape,\n build(ctx) {\n return safeHandler(async (args: BrowserCloseInput) => {\n const platform = ctx.registry.platformOf(args.session_id);\n await ctx.registry.close({ id: args.session_id, platform });\n return ok({ closed: true });\n });\n },\n};\n","import { browserKeyShape, ToolNames, type BrowserKeyInput } from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserKeyTool: ToolModule<typeof browserKeyShape> = {\n name: ToolNames.browserKey,\n description:\n \"Press a single key (e.g. 'Enter', 'Tab', 'Escape'). Invalidates all refs on success.\",\n inputShape: browserKeyShape,\n build(ctx) {\n return safeHandler(async (args: BrowserKeyInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n await engine.key({ id: args.session_id, platform: ctx.registry.platformOf(args.session_id) }, args.key);\n return ok({ pressed: true });\n });\n },\n};\n","import {\n browserNavigateShape,\n ToolNames,\n type BrowserNavigateInput,\n} from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserNavigateTool: ToolModule<typeof browserNavigateShape> = {\n name: ToolNames.browserNavigate,\n description:\n \"Navigate the session to a new URL (web only). Invalidates all refs on success.\",\n inputShape: browserNavigateShape,\n build(ctx) {\n return safeHandler(async (args: BrowserNavigateInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n await engine.navigate({ id: args.session_id, platform: ctx.registry.platformOf(args.session_id) }, args.url);\n return ok({ navigated: true, url: args.url });\n });\n },\n};\n","import { browserOpenShape, ToolNames, type BrowserOpenInput } from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserOpenTool: ToolModule<typeof browserOpenShape> = {\n name: ToolNames.browserOpen,\n description:\n \"Open a new browser or mobile session against a target. v0.1 supports platform='web' only; mobile lands in v0.3.\",\n inputShape: browserOpenShape,\n build(ctx) {\n return safeHandler(async (args: BrowserOpenInput) => {\n const session = await ctx.registry.open(args);\n return ok({ session_id: session.id, platform: session.platform });\n });\n },\n};\n","import {\n browserScreenshotShape,\n ToolNames,\n type BrowserScreenshotInput,\n} from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserScreenshotTool: ToolModule<typeof browserScreenshotShape> = {\n name: ToolNames.browserScreenshot,\n description:\n \"Capture a screenshot and save under ./.rolepod-uiproof/artifacts/{run_id}/. Set `full_page: true` for full-page capture; default is viewport only. Read-only (does NOT invalidate refs).\",\n inputShape: browserScreenshotShape,\n build(ctx) {\n return safeHandler(async (args: BrowserScreenshotInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n const { runId, runDir } = await ctx.store.startRun(\"snap\");\n const buf = await engine.screenshot(\n { id: args.session_id, platform: ctx.registry.platformOf(args.session_id) },\n args.full_page ?? false,\n );\n const path = await ctx.store.writeScreenshot(runDir, buf, \"shot\");\n return ok({\n run_id: runId,\n path,\n width: undefined,\n height: undefined,\n bytes: buf.byteLength,\n });\n });\n },\n};\n","import { browserScrollShape, ToolNames, type BrowserScrollInput } from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserScrollTool: ToolModule<typeof browserScrollShape> = {\n name: ToolNames.browserScroll,\n description:\n \"Scroll the page (or a specific scrollable element when `ref` is set) by `amount` pixels in `direction`. Invalidates all refs on success.\",\n inputShape: browserScrollShape,\n build(ctx) {\n return safeHandler(async (args: BrowserScrollInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n await engine.scroll(\n { id: args.session_id, platform: ctx.registry.platformOf(args.session_id) },\n args.direction,\n args.amount,\n args.ref,\n );\n return ok({ scrolled: true });\n });\n },\n};\n","import {\n browserSnapshotShape,\n ToolNames,\n type BrowserSnapshotInput,\n} from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserSnapshotTool: ToolModule<typeof browserSnapshotShape> = {\n name: ToolNames.browserSnapshot,\n description:\n \"Return the current accessibility tree with stable refs (e1, e2, …). Refs are valid only until the next state-changing call (D-010).\",\n inputShape: browserSnapshotShape,\n build(ctx) {\n return safeHandler(async (args: BrowserSnapshotInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n const snap = await engine.snapshot(\n { id: args.session_id, platform: ctx.registry.platformOf(args.session_id) },\n args.mode,\n );\n return ok({\n session_id: snap.session_id,\n url_or_screen: snap.url_or_screen,\n tree: snap.tree,\n taken_at: snap.taken_at,\n });\n });\n },\n};\n","import { browserTypeShape, ToolNames, type BrowserTypeInput } from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserTypeTool: ToolModule<typeof browserTypeShape> = {\n name: ToolNames.browserType,\n description:\n \"Type `text` into the element identified by `ref`. Set `clear_first: true` to replace the existing value. Invalidates all refs on success.\",\n inputShape: browserTypeShape,\n build(ctx) {\n return safeHandler(async (args: BrowserTypeInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n await engine.type(\n { id: args.session_id, platform: ctx.registry.platformOf(args.session_id) },\n args.ref,\n args.text,\n args.clear_first ? { clearFirst: true } : undefined,\n );\n return ok({ typed: true });\n });\n },\n};\n","import {\n browserWaitForShape,\n ToolNames,\n type BrowserWaitForInput,\n} from \"../../schema/tools.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const browserWaitForTool: ToolModule<typeof browserWaitForShape> = {\n name: ToolNames.browserWaitFor,\n description:\n \"Wait until a condition holds: text_visible, ref_exists, url_matches, or idle. Defaults to a 10s timeout. Invalidates all refs on success.\",\n inputShape: browserWaitForShape,\n build(ctx) {\n return safeHandler(async (args: BrowserWaitForInput) => {\n const engine = ctx.registry.engineFor(args.session_id);\n const start = Date.now();\n await engine.waitFor(\n { id: args.session_id, platform: ctx.registry.platformOf(args.session_id) },\n args.condition,\n args.timeout_ms,\n );\n return ok({ matched: true, waited_ms: Date.now() - start });\n });\n },\n};\n","import AxeBuilder from \"@axe-core/playwright\";\nimport { PlaywrightEngine } from \"../../engine/PlaywrightEngine.js\";\nimport {\n auditA11yShape,\n ToolNames,\n type AuditA11yInput,\n} from \"../../schema/tools.js\";\nimport { RolepodMcpError } from \"../../util/errors.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nconst TAGS_BY_LEVEL: Record<AuditA11yInput[\"level\"], string[]> = {\n \"wcag-a\": [\"wcag2a\", \"wcag21a\"],\n \"wcag-aa\": [\"wcag2a\", \"wcag2aa\", \"wcag21a\", \"wcag21aa\"],\n \"wcag-aaa\": [\n \"wcag2a\",\n \"wcag2aa\",\n \"wcag2aaa\",\n \"wcag21a\",\n \"wcag21aa\",\n \"wcag21aaa\",\n ],\n};\n\nconst AXE_TO_SEVERITY: Record<string, \"critical\" | \"serious\" | \"moderate\" | \"minor\"> = {\n critical: \"critical\",\n serious: \"serious\",\n moderate: \"moderate\",\n minor: \"minor\",\n};\n\nexport const auditA11yTool: ToolModule<typeof auditA11yShape> = {\n name: ToolNames.auditA11y,\n description:\n \"Run an accessibility audit on the page using axe-core. Returns issues grouped by severity with WCAG references and fix suggestions. v0.2: scope='page' only.\",\n inputShape: auditA11yShape,\n build(ctx) {\n return safeHandler(async (args: AuditA11yInput) => {\n const { runId, runDir } = await ctx.store.startRun(\"audit\");\n const session = await ctx.registry.open(args.open);\n const engine = ctx.registry.engineFor(session.id);\n if (!(engine instanceof PlaywrightEngine)) {\n throw new RolepodMcpError(\n \"unsupported_engine\",\n \"audit_a11y currently requires PlaywrightEngine (mobile a11y audit lands later).\",\n );\n }\n const page = engine.getPageForSession(session.id);\n\n let reportPath: string | undefined;\n let issues: Array<Record<string, unknown>> = [];\n let scopeTagged = false;\n try {\n // Tag the scope element so axe-core can include it via CSS.\n if (args.scope !== \"page\") {\n // refresh refIndex so the supplied ref is meaningful\n await engine.snapshot({ id: session.id, platform: \"web\" });\n const ref = args.scope.ref;\n const locator = page.locator(`aria-ref=${ref}`);\n if ((await locator.count()) === 0) {\n throw new RolepodMcpError(\n \"unknown_ref\",\n `Ref \"${ref}\" not found in the current snapshot.`,\n { session_id: session.id, ref },\n );\n }\n await locator\n .first()\n .evaluate((el) => el.setAttribute(\"data-rolepod-axe-scope\", \"true\"));\n scopeTagged = true;\n }\n\n const builder = new AxeBuilder({ page }).withTags(TAGS_BY_LEVEL[args.level]);\n if (scopeTagged) builder.include(\"[data-rolepod-axe-scope]\");\n const results = await builder.analyze();\n issues = results.violations.flatMap((v) =>\n v.nodes.map((n, idx) => ({\n wcag_ref: pickWcagRef(v.tags) ?? v.id,\n severity: AXE_TO_SEVERITY[v.impact ?? \"minor\"] ?? \"minor\",\n ref: `${v.id}#${idx}`,\n description: v.help,\n fix_suggestion: v.helpUrl,\n target: n.target.join(\" \"),\n })),\n );\n\n const payload = {\n run_id: runId,\n level: args.level,\n counts: countBySeverity(issues),\n issues,\n };\n if (args.report_format === \"markdown\") {\n reportPath = await ctx.store.writeReport(\n runDir,\n \"report.md\",\n renderMarkdown(payload),\n );\n } else {\n reportPath = await ctx.store.writeReport(\n runDir,\n \"report.json\",\n JSON.stringify(payload, null, 2),\n );\n }\n } finally {\n if (scopeTagged) {\n await page\n .locator(\"[data-rolepod-axe-scope]\")\n .first()\n .evaluate((el) => el.removeAttribute(\"data-rolepod-axe-scope\"))\n .catch(() => undefined);\n }\n if (args.close_on_finish) {\n await ctx.registry.close(session).catch(() => undefined);\n }\n }\n\n return ok({\n run_id: runId,\n counts: countBySeverity(issues),\n issues,\n report_path: reportPath,\n });\n });\n },\n};\n\nfunction pickWcagRef(tags: string[]): string | undefined {\n return tags.find((t) => /^wcag\\d/.test(t));\n}\n\nfunction countBySeverity(\n issues: Array<Record<string, unknown>>,\n): Record<string, number> {\n const out: Record<string, number> = {\n critical: 0,\n serious: 0,\n moderate: 0,\n minor: 0,\n };\n for (const i of issues) {\n const s = String(i.severity);\n out[s] = (out[s] ?? 0) + 1;\n }\n return out;\n}\n\nfunction renderMarkdown(p: {\n run_id: string;\n level: string;\n counts: Record<string, number>;\n issues: Array<Record<string, unknown>>;\n}): string {\n const header = `# A11y audit — ${p.run_id}\\n\\nLevel: \\`${p.level}\\`\\n\\n## Counts\\n\\n- critical: ${p.counts.critical}\\n- serious: ${p.counts.serious}\\n- moderate: ${p.counts.moderate}\\n- minor: ${p.counts.minor}\\n\\n## Issues\\n\\n`;\n const body = p.issues\n .map(\n (i) =>\n `### ${i.severity} — ${i.description}\\n\\n- WCAG: ${i.wcag_ref}\\n- Target: \\`${i.target}\\`\\n- Fix: ${i.fix_suggestion}\\n`,\n )\n .join(\"\\n\");\n return header + body;\n}\n","import {\n extractUiStateShape,\n ToolNames,\n type A11yNode,\n type ExtractUiStateInput,\n} from \"../../schema/tools.js\";\nimport type { Session } from \"../../engine/Engine.js\";\nimport { RolepodMcpError } from \"../../util/errors.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\n/**\n * Returns the most-relevant accessibility-tree subtree plus the refs\n * matched by the question. **No LLM is invoked** — the Lead interprets\n * the returned subtree.\n */\nexport const extractUiStateTool: ToolModule<typeof extractUiStateShape> = {\n name: ToolNames.extractUiState,\n description:\n \"Return the AT-tree subtree most likely to answer a natural-language question, plus matched refs. No LLM is called — the Lead does the interpretation.\",\n inputShape: extractUiStateShape,\n build(ctx) {\n return safeHandler(async (args: ExtractUiStateInput) => {\n let session: Session;\n let openedHere = false;\n if (args.session_id) {\n const platform = ctx.registry.platformOf(args.session_id);\n session = { id: args.session_id, platform };\n } else if (args.open) {\n session = await ctx.registry.open(args.open);\n openedHere = true;\n } else {\n throw new RolepodMcpError(\n \"invalid_input\",\n \"Provide either `session_id` (existing session) or `open` (to start one).\",\n );\n }\n\n try {\n const engine = ctx.registry.engineFor(session.id);\n const snap = await engine.snapshot(session);\n const tokens = tokenize(args.question_nl);\n const matches = scoreTree(snap.tree, tokens);\n const top = matches[0];\n const subtree = top\n ? (top.subtree as A11yNode)\n : snap.tree;\n const matchedRefs = matches.slice(0, 8).map((m) => m.ref);\n\n let confidence: \"high\" | \"medium\" | \"low\" = \"low\";\n if (top) {\n if (top.score >= tokens.length && tokens.length > 0) confidence = \"high\";\n else if (top.score >= Math.max(1, Math.ceil(tokens.length / 2)))\n confidence = \"medium\";\n }\n\n return ok({\n snapshot_ref: snap.taken_at,\n confidence,\n matched_refs: matchedRefs,\n value: subtree,\n url_or_screen: snap.url_or_screen,\n });\n } finally {\n if (openedHere && args.close_on_finish) {\n await ctx.registry.close(session).catch(() => undefined);\n }\n }\n });\n },\n};\n\nfunction tokenize(q: string): string[] {\n return q\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((t) => t.length >= 2);\n}\n\ntype ScoredMatch = {\n ref: string;\n score: number;\n subtree: A11yNode;\n};\n\nfunction scoreTree(root: A11yNode, tokens: string[]): ScoredMatch[] {\n const matches: ScoredMatch[] = [];\n const visit = (node: A11yNode, ancestors: A11yNode[]): void => {\n const hay = `${node.name ?? \"\"} ${node.value ?? \"\"}`.toLowerCase();\n let score = 0;\n for (const t of tokens) if (hay.includes(t)) score += 1;\n if (score > 0) {\n // surface the matching node plus one ancestor for context\n const subtree = ancestors.length > 0 ? ancestors[ancestors.length - 1]! : node;\n matches.push({ ref: node.ref, score, subtree });\n }\n if (node.children) {\n for (const c of node.children) visit(c, [...ancestors, node]);\n }\n };\n visit(root, []);\n matches.sort((a, b) => b.score - a.score);\n return matches;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport {\n scaffoldE2eShape,\n ToolNames,\n type ScaffoldE2eInput,\n} from \"../../schema/tools.js\";\nimport { RolepodMcpError } from \"../../util/errors.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\ntype Step = { kind: string; [k: string]: unknown };\ntype Expect = { kind: string; [k: string]: unknown };\ntype ReplayShape = {\n version: number;\n open?: { url?: string };\n steps?: Step[];\n expect?: Expect[];\n};\n\nexport const scaffoldE2eTool: ToolModule<typeof scaffoldE2eShape> = {\n name: ToolNames.scaffoldE2e,\n description:\n \"Generate a runnable e2e test file (playwright-test, vitest+playwright, or pytest+selenium) from a scenario description and optional replay bundle from a prior verify_ui_flow run.\",\n inputShape: scaffoldE2eShape,\n build(ctx) {\n return safeHandler(async (args: ScaffoldE2eInput) => {\n const { runId, runDir } = await ctx.store.startRun(\"scaffold\");\n const slug = slugify(args.scenario_nl);\n const bundle = args.recorded_bundle\n ? await loadReplay(args.recorded_bundle)\n : null;\n const ctxObj = { args, slug, bundle };\n\n let body: string;\n let language: \"typescript\" | \"python\";\n let filename: string;\n let dependencies: string[];\n let setupNotes: string;\n\n switch (args.framework) {\n case \"playwright-test\":\n body = renderPlaywrightTest(ctxObj);\n language = \"typescript\";\n filename = args.filename ?? `${slug}.spec.ts`;\n dependencies = [\"@playwright/test\"];\n setupNotes =\n \"Install: `npm i -D @playwright/test && npx playwright install`. Run: `npx playwright test`.\";\n break;\n case \"vitest+playwright\":\n body = renderVitestPlaywright(ctxObj);\n language = \"typescript\";\n filename = args.filename ?? `${slug}.test.ts`;\n dependencies = [\"vitest\", \"playwright\"];\n setupNotes =\n \"Install: `npm i -D vitest playwright && npx playwright install chromium`. Run: `npx vitest`.\";\n break;\n case \"pytest+selenium\":\n body = renderPytestSelenium(ctxObj);\n language = \"python\";\n filename = args.filename ?? `test_${slug}.py`;\n dependencies = [\"pytest\", \"selenium\"];\n setupNotes =\n \"Install: `pip install pytest selenium`. Ensure a Chrome driver is on PATH. Run: `pytest`.\";\n break;\n default:\n throw new RolepodMcpError(\n \"invalid_input\",\n `Unknown framework \"${args.framework}\".`,\n );\n }\n\n const path = await ctx.store.writeReport(runDir, filename, body);\n\n return ok({\n run_id: runId,\n test_file_path: path,\n language,\n dependencies,\n setup_notes: setupNotes,\n from_replay_bundle: Boolean(bundle),\n });\n });\n },\n};\n\nasync function loadReplay(bundlePath: string): Promise<ReplayShape> {\n const raw = await readFile(resolve(bundlePath), \"utf8\");\n return JSON.parse(raw) as ReplayShape;\n}\n\nfunction slugify(s: string): string {\n return (\n s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 40) || \"scenario\"\n );\n}\n\ntype RenderCtx = {\n args: ScaffoldE2eInput;\n slug: string;\n bundle: ReplayShape | null;\n};\n\nfunction renderPlaywrightTest(c: RenderCtx): string {\n const url = c.bundle?.open?.url ?? c.args.url;\n const stepLines = c.bundle?.steps?.length\n ? c.bundle.steps.map(playwrightStepLine).join(\"\\n\")\n : ` // TODO: implement steps for: ${c.args.scenario_nl}`;\n const expectLines = c.bundle?.expect?.length\n ? c.bundle.expect.map(playwrightExpectLine).join(\"\\n\")\n : ` // TODO: add expectations`;\n return [\n `import { test, expect } from \"@playwright/test\";`,\n ``,\n `test(${JSON.stringify(c.args.scenario_nl)}, async ({ page }) => {`,\n ` await page.goto(${JSON.stringify(url)});`,\n stepLines,\n expectLines,\n `});`,\n ``,\n ].join(\"\\n\");\n}\n\nfunction renderVitestPlaywright(c: RenderCtx): string {\n const url = c.bundle?.open?.url ?? c.args.url;\n const stepLines = c.bundle?.steps?.length\n ? c.bundle.steps.map(playwrightStepLine).join(\"\\n\")\n : ` // TODO: implement steps for: ${c.args.scenario_nl}`;\n const expectLines = c.bundle?.expect?.length\n ? c.bundle.expect.map(playwrightExpectLine).join(\"\\n\")\n : ` // TODO: add expectations`;\n return [\n `import { test } from \"vitest\";`,\n `import { chromium, expect } from \"playwright/test\";`,\n ``,\n `test(${JSON.stringify(c.args.scenario_nl)}, async () => {`,\n ` const browser = await chromium.launch();`,\n ` const page = await browser.newPage();`,\n ` try {`,\n ` await page.goto(${JSON.stringify(url)});`,\n indent(stepLines, 2),\n indent(expectLines, 2),\n ` } finally {`,\n ` await browser.close();`,\n ` }`,\n `});`,\n ``,\n ].join(\"\\n\");\n}\n\nfunction renderPytestSelenium(c: RenderCtx): string {\n const url = c.bundle?.open?.url ?? c.args.url;\n const stepLines = c.bundle?.steps?.length\n ? c.bundle.steps.map(seleniumStepLine).join(\"\\n\")\n : ` # TODO: implement steps for: ${c.args.scenario_nl}`;\n const expectLines = c.bundle?.expect?.length\n ? c.bundle.expect.map(seleniumExpectLine).join(\"\\n\")\n : ` # TODO: add expectations`;\n return [\n `import pytest`,\n `from selenium import webdriver`,\n `from selenium.webdriver.common.by import By`,\n `from selenium.webdriver.common.keys import Keys`,\n ``,\n `def test_${slugifyPy(c.args.scenario_nl)}():`,\n ` \"\"\"${c.args.scenario_nl}\"\"\"`,\n ` driver = webdriver.Chrome()`,\n ` try:`,\n ` driver.get(${JSON.stringify(url)})`,\n indent(stepLines, 2),\n indent(expectLines, 2),\n ` finally:`,\n ` driver.quit()`,\n ``,\n ].join(\"\\n\");\n}\n\nfunction playwrightStepLine(step: Step): string {\n switch (step.kind) {\n case \"click\":\n return ` await page.getByText(${JSON.stringify(step.query)}, { exact: false }).first().click();`;\n case \"type\":\n return ` await page.getByRole(\"textbox\", { name: ${JSON.stringify(step.query)} }).fill(${JSON.stringify(step.text)});`;\n case \"key\":\n return ` await page.keyboard.press(${JSON.stringify(step.key)});`;\n case \"navigate\":\n return ` await page.goto(${JSON.stringify(step.url)});`;\n case \"wait_for\":\n return ` // wait_for: ${JSON.stringify(step.condition)} — translate to page.waitForXxx()`;\n default:\n return ` // unsupported step kind: ${step.kind}`;\n }\n}\n\nfunction playwrightExpectLine(exp: Expect): string {\n switch (exp.kind) {\n case \"text_visible\":\n return ` await expect(page.getByText(${JSON.stringify(exp.text)}, { exact: false }).first()).toBeVisible();`;\n case \"text_absent\":\n return ` await expect(page.getByText(${JSON.stringify(exp.text)}, { exact: false }).first()).toHaveCount(0);`;\n case \"url_matches\":\n return ` await expect(page).toHaveURL(new RegExp(${JSON.stringify(exp.pattern)}));`;\n case \"ref_in_state\":\n return ` // ref_in_state ${JSON.stringify(exp.query)} → ${String(exp.state)} — translate as needed`;\n default:\n return ` // unsupported expect kind: ${exp.kind}`;\n }\n}\n\nfunction seleniumStepLine(step: Step): string {\n switch (step.kind) {\n case \"click\":\n return ` driver.find_element(By.XPATH, f\"//*[contains(text(), \\\\\"${escapePy(String(step.query))}\\\\\")]\").click()`;\n case \"type\":\n return ` driver.find_element(By.XPATH, f\"//*[@aria-label=\\\\\"${escapePy(String(step.query))}\\\\\" or @placeholder=\\\\\"${escapePy(String(step.query))}\\\\\"]\").send_keys(${JSON.stringify(step.text)})`;\n case \"key\":\n return ` driver.switch_to.active_element.send_keys(Keys.${pyKeyName(String(step.key))})`;\n case \"navigate\":\n return ` driver.get(${JSON.stringify(step.url)})`;\n case \"wait_for\":\n return ` # wait_for: ${JSON.stringify(step.condition)} — translate to WebDriverWait`;\n default:\n return ` # unsupported step kind: ${step.kind}`;\n }\n}\n\nfunction seleniumExpectLine(exp: Expect): string {\n switch (exp.kind) {\n case \"text_visible\":\n return ` assert ${JSON.stringify(exp.text)} in driver.page_source`;\n case \"text_absent\":\n return ` assert ${JSON.stringify(exp.text)} not in driver.page_source`;\n case \"url_matches\":\n return ` import re; assert re.search(${JSON.stringify(exp.pattern)}, driver.current_url)`;\n case \"ref_in_state\":\n return ` # ref_in_state ${JSON.stringify(exp.query)} → ${String(exp.state)}`;\n default:\n return ` # unsupported expect kind: ${exp.kind}`;\n }\n}\n\nfunction slugifyPy(s: string): string {\n return (\n s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 40) || \"scenario\"\n );\n}\n\nfunction escapePy(s: string): string {\n return s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction pyKeyName(k: string): string {\n const map: Record<string, string> = {\n Enter: \"ENTER\",\n Tab: \"TAB\",\n Escape: \"ESCAPE\",\n Backspace: \"BACK_SPACE\",\n ArrowUp: \"ARROW_UP\",\n ArrowDown: \"ARROW_DOWN\",\n ArrowLeft: \"ARROW_LEFT\",\n ArrowRight: \"ARROW_RIGHT\",\n };\n return map[k] ?? `RETURN # unknown key: ${k}`;\n}\n\nfunction indent(block: string, n: number): string {\n const pad = \" \".repeat(n);\n return block\n .split(\"\\n\")\n .map((l) => (l.length > 0 ? pad + l : l))\n .join(\"\\n\");\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport pixelmatch from \"pixelmatch\";\nimport { PNG } from \"pngjs\";\nimport { PlaywrightEngine } from \"../../engine/PlaywrightEngine.js\";\nimport {\n ToolNames,\n visualDiffShape,\n type VisualDiffInput,\n} from \"../../schema/tools.js\";\nimport { RolepodMcpError } from \"../../util/errors.js\";\nimport { ok, safeHandler } from \"../result.js\";\nimport type { ToolModule } from \"../types.js\";\n\nexport const visualDiffTool: ToolModule<typeof visualDiffShape> = {\n name: ToolNames.visualDiff,\n description:\n \"Capture a screenshot and compare against a named baseline under ./.rolepod-uiproof/baselines/. First call for a baseline_id seeds the baseline (passed=true, diff_pct=0). Subsequent calls return the diff percentage and an annotated diff image.\",\n inputShape: visualDiffShape,\n build(ctx) {\n return safeHandler(async (args: VisualDiffInput) => {\n const { runId, runDir } = await ctx.store.startRun(\"vdiff\");\n const session = await ctx.registry.open({\n ...args.open,\n ...(args.viewport ? { viewport: args.viewport } : {}),\n });\n const engine = ctx.registry.engineFor(session.id);\n if (!(engine instanceof PlaywrightEngine)) {\n throw new RolepodMcpError(\n \"unsupported_engine\",\n \"visual_diff currently requires PlaywrightEngine.\",\n );\n }\n\n try {\n const buf = await engine.screenshot(\n { id: session.id, platform: session.platform },\n true,\n );\n const currentPath = await ctx.store.writeScreenshot(runDir, buf, \"current\");\n\n await ctx.store.ensureDir(ctx.store.baselineDir);\n const baselinePath = resolve(\n ctx.store.baselineDir,\n `${args.baseline_id}.png`,\n );\n\n if (!existsSync(baselinePath)) {\n await ctx.store.writeBytes(\n ctx.store.baselineDir,\n `${args.baseline_id}.png`,\n buf,\n );\n return ok({\n run_id: runId,\n baseline_id: args.baseline_id,\n diff_pct: 0,\n passed: true,\n baseline_path: baselinePath,\n current_path: currentPath,\n note: \"Baseline did not exist — current capture saved as the new baseline.\",\n });\n }\n\n const [baselineRaw, currentRaw] = await Promise.all([\n readFile(baselinePath),\n readFile(currentPath),\n ]);\n const baseline = PNG.sync.read(baselineRaw);\n const current = PNG.sync.read(currentRaw);\n\n if (baseline.width !== current.width || baseline.height !== current.height) {\n throw new RolepodMcpError(\n \"engine_error\",\n `Dimension mismatch for baseline \"${args.baseline_id}\" — baseline ${baseline.width}x${baseline.height}, current ${current.width}x${current.height}. Delete the baseline or pass a matching viewport.`,\n {\n baseline: { w: baseline.width, h: baseline.height },\n current: { w: current.width, h: current.height },\n },\n );\n }\n\n const diff = new PNG({ width: baseline.width, height: baseline.height });\n const diffPixels = pixelmatch(\n baseline.data,\n current.data,\n diff.data,\n baseline.width,\n baseline.height,\n { threshold: args.pixel_threshold, includeAA: true },\n );\n const total = baseline.width * baseline.height;\n const diffPct = diffPixels / total;\n\n const diffImagePath = await ctx.store.writeBytes(\n runDir,\n \"diff.png\",\n PNG.sync.write(diff),\n );\n\n return ok({\n run_id: runId,\n baseline_id: args.baseline_id,\n diff_pct: Number(diffPct.toFixed(6)),\n diff_pixels: diffPixels,\n total_pixels: total,\n passed: diffPct <= args.threshold_pct,\n baseline_path: baselinePath,\n current_path: currentPath,\n diff_image_path: diffImagePath,\n });\n } finally {\n if (args.close_on_finish) {\n await ctx.registry.close(session).catch(() => undefined);\n }\n }\n });\n },\n};\n"],"mappings":"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","names":["osPlatform","resolve","resolve","resolve","randomUUID","XMLParser","parser","firstTagName","randomUUID","randomUUID","randomUUID","payload","resolve","readFile","resolve","readFile","resolve","existsSync","readFile","resolve","resolve","existsSync","readFile"]}