driftx 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -667,6 +667,13 @@ async function withRetry(fn, policy, signal) {
667
667
  import { select } from "@inquirer/prompts";
668
668
  async function pickDevice(booted) {
669
669
  if (booted.length === 1) return booted[0];
670
+ if (!process.stdout.isTTY) {
671
+ const list = booted.map((d) => ` - "${d.name}" (${d.platform}, ${d.id})`).join("\n");
672
+ throw new Error(
673
+ `Multiple booted devices found. Use --device to specify one:
674
+ ${list}`
675
+ );
676
+ }
670
677
  const selected = await select({
671
678
  message: "Select a device",
672
679
  choices: booted.map((d) => ({
@@ -924,9 +931,7 @@ async function discoverTargets(metroPort) {
924
931
  });
925
932
  }
926
933
  function findRuntimeTarget(targets, deviceName) {
927
- const rnTargets = targets.filter(
928
- (t) => t.reactNative && t.description.includes("React Native")
929
- );
934
+ const rnTargets = targets.filter((t) => !!t.reactNative);
930
935
  if (deviceName) {
931
936
  return rnTargets.find(
932
937
  (t) => t.deviceName?.toLowerCase().includes(deviceName.toLowerCase())
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/shell.ts","../src/config.ts","../src/types.ts","../src/logger.ts","../src/prerequisites.ts","../src/exit-codes.ts","../src/commands/doctor.ts","../src/commands/init.ts","../src/devices/android-discovery.ts","../src/devices/ios-discovery.ts","../src/devices/discovery.ts","../src/commands/capture.ts","../src/capture/android-capture.ts","../src/capture/ios-capture.ts","../src/capture/capture.ts","../src/run-store.ts","../src/retry.ts","../src/commands/device-picker.ts","../src/inspect/uiautomator.ts","../src/inspect/ios-accessibility.ts","../src/inspect/cdp-client.ts","../src/inspect/strategy-cache.ts","../src/inspect/tree-inspector.ts","../src/formatters/compare.ts","../src/analyses/context.ts","../src/analyses/registry.ts","../src/diff/image-loader.ts","../src/diff/alignment.ts","../src/diff/pixel-diff.ts","../src/diff/region-extractor.ts","../src/diff/ignore-rules.ts","../src/diff/mask-generator.ts","../src/diff/viewport.ts","../src/diff/compare.ts","../src/inspect/component-matcher.ts","../src/inspect/finding-generator.ts","../src/analyses/plugins/pixel.ts","../src/analyses/plugins/a11y.ts","../src/analyses/plugins/regression.ts","../src/analyses/default-registry.ts","../src/analyses/orchestrator.ts","../src/commands/compare.ts","../src/formatters/clipboard.ts","../src/formatters/format.ts","../src/formatters/devices.ts","../src/formatters/doctor.ts","../src/formatters/inspect.ts","../src/interact/android.ts","../src/interact/ios.ts","../src/interact/backend.ts","../src/interact/resolver.ts","../src/interact/gestures.ts","../src/bin.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createRequire } from 'module';\nimport { existsSync, mkdirSync, readFileSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { homedir } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { RealShell } from './shell.js';\nimport { loadConfig } from './config.js';\nimport { createLogger, setLogger } from './logger.js';\nimport { checkPrerequisites } from './prerequisites.js';\nimport { computeDoctorExitCode } from './commands/doctor.js';\nimport { detectFramework, generateConfig } from './commands/init.js';\nimport { DeviceDiscovery } from './devices/discovery.js';\nimport { runCapture } from './commands/capture.js';\nimport { runCompare } from './commands/compare.js';\nimport { TreeInspector } from './inspect/tree-inspector.js';\nimport { pickDevice } from './commands/device-picker.js';\nimport { formatOutput } from './formatters/format.js';\nimport { devicesFormatter } from './formatters/devices.js';\nimport { doctorFormatter } from './formatters/doctor.js';\nimport { inspectFormatter } from './formatters/inspect.js';\nimport { compareFormatter } from './formatters/compare.js';\nimport type { FormatterContext } from './formatters/types.js';\nimport { createBackend } from './interact/backend.js';\nimport { GestureExecutor } from './interact/gestures.js';\n\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json');\n\nfunction getFormatterContext(opts: Record<string, unknown>): FormatterContext {\n return {\n format: (opts.format as FormatterContext['format']) ?? 'terminal',\n copy: !!opts.copy,\n quiet: !!opts.quiet,\n };\n}\n\nexport function createProgram(): Command {\n const program = new Command();\n program\n .name('driftx')\n .description('Visual diff tool for React Native and Android development')\n .version(pkg.version)\n .option('--verbose', 'enable debug logging')\n .option('--quiet', 'suppress all output except errors')\n .option('--format <type>', 'output format: terminal, markdown, json', 'terminal')\n .option('--copy', 'copy output to clipboard');\n\n program.hook('preAction', (_thisCommand, actionCommand) => {\n const opts = actionCommand.optsWithGlobals();\n const level = opts.verbose ? 'debug' : opts.quiet ? 'silent' : 'info';\n setLogger(createLogger(level));\n });\n\n program\n .command('doctor')\n .description('Check system prerequisites for driftx')\n .action(async function(this: Command) {\n const shell = new RealShell();\n const config = await loadConfig();\n const checks = await checkPrerequisites(shell, config.metroPort);\n const ctx = getFormatterContext(this.optsWithGlobals());\n await formatOutput(doctorFormatter, checks, ctx);\n process.exitCode = computeDoctorExitCode(checks);\n });\n\n program\n .command('init')\n .description('Initialize driftx configuration for this project')\n .action(async () => {\n const cwd = process.cwd();\n const files = readdirSync(cwd);\n let packageJson: Record<string, unknown> | undefined;\n try {\n packageJson = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf-8'));\n } catch {\n // no package.json\n }\n const framework = detectFramework(files, packageJson);\n const config = generateConfig(framework);\n const configPath = join(cwd, '.driftxrc.json');\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n');\n console.log(`Created ${configPath} (framework: ${framework})`);\n });\n\n program\n .command('devices')\n .description('List connected devices and simulators')\n .action(async function(this: Command) {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const ctx = getFormatterContext(this.optsWithGlobals());\n await formatOutput(devicesFormatter, devices, ctx);\n });\n\n program\n .command('capture')\n .description('Capture a screenshot from a device')\n .option('-d, --device <id>', 'device ID or name')\n .option('-o, --output <path>', 'output file path')\n .option('--settle', 'enable settle-time check')\n .option('--no-settle', 'disable settle-time check')\n .action(async (opts) => {\n const shell = new RealShell();\n const config = await loadConfig();\n const result = await runCapture(shell, config, {\n device: opts.device,\n output: opts.output,\n settleCheck: opts.settle,\n });\n console.log(`Screenshot saved: ${result.path}`);\n if (result.runId) {\n console.log(`Run ID: ${result.runId}`);\n }\n });\n\n program\n .command('compare')\n .description('Compare a screenshot against a design')\n .option('--design <path>', 'path to design image')\n .option('-d, --device <id>', 'device ID or name')\n .option('--threshold <n>', 'diff percentage threshold', parseFloat)\n .option('--screenshot <path>', 'use existing screenshot instead of capturing')\n .option('--with <analyses>', 'comma-separated analyses to run')\n .option('--without <analyses>', 'exclude specific analyses')\n .option('--baseline', 'compare against previous run screenshot')\n .action(async function(this: Command, opts: Record<string, unknown>) {\n if (!opts.design && !opts.baseline) {\n throw new Error('Either --design or --baseline must be provided');\n }\n const shell = new RealShell();\n const config = await loadConfig();\n const { exitCode, formatData } = await runCompare(shell, config, {\n design: opts.design as string | undefined,\n device: opts.device as string | undefined,\n threshold: opts.threshold as number | undefined,\n screenshot: opts.screenshot as string | undefined,\n with: opts.with as string | undefined,\n without: opts.without as string | undefined,\n baseline: !!opts.baseline,\n });\n const ctx = getFormatterContext(this.optsWithGlobals());\n await formatOutput(compareFormatter, formatData, ctx);\n process.exitCode = exitCode;\n });\n\n program\n .command('inspect')\n .description('Inspect component tree on device')\n .option('-d, --device <id>', 'device ID or name')\n .option('--json', 'output as JSON (alias for --format json)')\n .option('--capabilities', 'show inspection capabilities only')\n .action(async function(this: Command, opts: Record<string, unknown>) {\n const shell = new RealShell();\n const config = await loadConfig();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const inspector = new TreeInspector(shell, process.cwd());\n const result = await inspector.inspect(device, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n\n const globalOpts = this.optsWithGlobals();\n if (opts.json) globalOpts.format = 'json';\n const ctx = getFormatterContext(globalOpts);\n await formatOutput(inspectFormatter, result, ctx);\n });\n\n program\n .command('tap <target>')\n .description('Tap a component by testID, name, or text')\n .option('-d, --device <id>', 'device ID or name')\n .option('--xy', 'treat target as x,y coordinates')\n .action(async (target: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const config = await loadConfig();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n\n let result;\n if (opts.xy) {\n const [x, y] = target.split(',').map(Number);\n result = await executor.tapXY(device, x, y);\n } else {\n const inspector = new TreeInspector(shell, process.cwd());\n const inspectResult = await inspector.inspect(device, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n result = await executor.tap(device, inspectResult.tree, target);\n }\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('type <target> <text>')\n .description('Tap a component then type text into it')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (target: string, text: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const config = await loadConfig();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const inspector = new TreeInspector(shell, process.cwd());\n const inspectResult = await inspector.inspect(device, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.typeInto(device, inspectResult.tree, target, text);\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('swipe <direction>')\n .description('Swipe up, down, left, or right')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (direction: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.swipe(device, direction as 'up' | 'down' | 'left' | 'right');\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('go-back')\n .description('Press the back button')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.goBack(device);\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('open-url <url>')\n .description('Open a deep link or URL on the device')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (url: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.openUrl(device, url);\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('setup-claude')\n .description('Register driftx as a Claude Code plugin')\n .action(() => {\n const claudeDir = join(homedir(), '.claude');\n const pluginsDir = join(claudeDir, 'plugins');\n const driftxPluginDir = join(pluginsDir, 'driftx');\n const registryPath = join(pluginsDir, 'installed_plugins.json');\n\n const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\n const skillSource = join(packageRoot, 'driftx-plugin');\n\n if (!existsSync(skillSource)) {\n console.error(`driftx-plugin directory not found at ${skillSource}`);\n process.exitCode = 1;\n return;\n }\n\n mkdirSync(pluginsDir, { recursive: true });\n\n if (existsSync(driftxPluginDir)) {\n try { unlinkSync(driftxPluginDir); } catch {\n console.error(`Could not remove existing ${driftxPluginDir}. Remove it manually and retry.`);\n process.exitCode = 1;\n return;\n }\n }\n symlinkSync(skillSource, driftxPluginDir);\n\n let registry: { version: number; plugins: Record<string, unknown[]> } = { version: 2, plugins: {} };\n try {\n registry = JSON.parse(readFileSync(registryPath, 'utf-8'));\n } catch {}\n\n registry.plugins['driftx@local'] = [{\n scope: 'user',\n installPath: driftxPluginDir,\n version: pkg.version,\n installedAt: new Date().toISOString(),\n lastUpdated: new Date().toISOString(),\n }];\n\n writeFileSync(registryPath, JSON.stringify(registry, null, 2));\n console.log('driftx registered as Claude Code plugin.');\n console.log(` Symlink: ${driftxPluginDir} -> ${skillSource}`);\n console.log(` Registry: ${registryPath}`);\n console.log('\\nRestart Claude Code to pick up the driftx skill.');\n });\n\n return program;\n}\n\nexport function run(argv: string[]): void {\n const program = createProgram();\n program.parseAsync(argv);\n}\n","import { execFile } from 'node:child_process';\nimport type { Shell } from './types.js';\n\nexport class RealShell implements Shell {\n async exec(\n cmd: string,\n args: string[],\n options?: { timeout?: number },\n ): Promise<{ stdout: string; stderr: string }> {\n const controller = new AbortController();\n const timeout = options?.timeout;\n\n return new Promise((resolve, reject) => {\n const child = execFile(\n cmd,\n args,\n {\n signal: controller.signal,\n maxBuffer: 10 * 1024 * 1024,\n encoding: 'utf-8',\n },\n (error, stdout, stderr) => {\n if (error) {\n reject(error);\n } else {\n resolve({ stdout, stderr });\n }\n },\n );\n\n if (timeout) {\n setTimeout(() => {\n controller.abort();\n child.kill();\n }, timeout);\n }\n });\n }\n}\n\nexport function createShell(): Shell {\n return new RealShell();\n}\n","import { z } from 'zod';\nimport { cosmiconfig } from 'cosmiconfig';\nimport { DEFAULT_TIMEOUT_CONFIG, DEFAULT_RETRY_POLICY } from './types.js';\n\nconst timeoutSchema = z.object({\n deviceDiscoveryMs: z.number().int().positive().optional(),\n screenshotCaptureMs: z.number().int().positive().optional(),\n treeInspectionMs: z.number().int().positive().optional(),\n devToolsConnectMs: z.number().int().positive().optional(),\n});\n\nconst retrySchema = z.object({\n maxAttempts: z.number().int().positive().optional(),\n baseDelayMs: z.number().int().positive().optional(),\n maxDelayMs: z.number().int().positive().optional(),\n backoffMultiplier: z.number().positive().optional(),\n retryableErrors: z.array(z.string()).optional(),\n});\n\nconst boundingBoxSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number().positive(),\n height: z.number().positive(),\n});\n\nconst colorRangeSchema = z.object({\n r: z.tuple([z.number(), z.number()]),\n g: z.tuple([z.number(), z.number()]),\n b: z.tuple([z.number(), z.number()]),\n a: z.tuple([z.number(), z.number()]).optional(),\n});\n\nconst ignoreRuleSchema = z.object({\n type: z.enum(['testID', 'componentName', 'textPattern', 'boundingBox', 'sourceFile', 'colorRange']),\n value: z.union([z.string(), boundingBoxSchema, colorRangeSchema]),\n reason: z.string().optional(),\n});\n\nconst viewportSchema = z.object({\n cropStatusBar: z.boolean().optional(),\n cropNavigationBar: z.boolean().optional(),\n statusBarHeight: z.number().int().nonnegative().optional(),\n navigationBarHeight: z.number().int().nonnegative().optional(),\n});\n\nconst analysesSchema = z.object({\n default: z.array(z.string()).optional(),\n disabled: z.array(z.string()).optional(),\n options: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),\n}).optional();\n\nexport const configSchema = z.object({\n threshold: z.number().min(0).max(1).optional(),\n diffThreshold: z.number().min(0).max(1).optional(),\n settleTimeMs: z.number().int().positive().optional(),\n settleCheckEnabled: z.boolean().optional(),\n settleMaxDelta: z.number().min(0).max(1).optional(),\n primaryDevice: z.string().optional(),\n groups: z.record(z.string(), z.array(z.string())).optional(),\n platform: z.enum(['android', 'ios']).optional(),\n metroPort: z.number().int().positive().optional(),\n devToolsPort: z.number().int().positive().optional(),\n ignoreRules: z.array(ignoreRuleSchema).optional(),\n viewport: viewportSchema.optional(),\n timeouts: timeoutSchema.optional(),\n retry: retrySchema.optional(),\n regionMergeGap: z.number().int().nonnegative().optional(),\n regionMinArea: z.number().int().nonnegative().optional(),\n diffMaskColor: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional(),\n analyses: analysesSchema,\n});\n\nexport type DriftxConfig = {\n threshold: number;\n diffThreshold: number;\n settleTimeMs: number;\n settleCheckEnabled: boolean;\n settleMaxDelta: number;\n primaryDevice?: string;\n groups: Record<string, string[]>;\n platform: 'android' | 'ios';\n metroPort: number;\n devToolsPort: number;\n ignoreRules: z.infer<typeof ignoreRuleSchema>[];\n viewport: {\n cropStatusBar: boolean;\n cropNavigationBar: boolean;\n statusBarHeight: number;\n navigationBarHeight: number;\n };\n timeouts: typeof DEFAULT_TIMEOUT_CONFIG;\n retry: typeof DEFAULT_RETRY_POLICY;\n regionMergeGap: number;\n regionMinArea: number;\n diffMaskColor: [number, number, number, number];\n analyses: {\n default: string[];\n disabled: string[];\n options: Record<string, Record<string, unknown>>;\n };\n};\n\nconst DEFAULTS: DriftxConfig = {\n threshold: 0.1,\n diffThreshold: 0.01,\n settleTimeMs: 300,\n settleCheckEnabled: true,\n settleMaxDelta: 0.001,\n primaryDevice: undefined,\n groups: {},\n platform: 'android',\n metroPort: 8081,\n devToolsPort: 8097,\n ignoreRules: [],\n viewport: {\n cropStatusBar: true,\n cropNavigationBar: true,\n statusBarHeight: 24,\n navigationBarHeight: 48,\n },\n timeouts: { ...DEFAULT_TIMEOUT_CONFIG },\n retry: { ...DEFAULT_RETRY_POLICY },\n regionMergeGap: 8,\n regionMinArea: 100,\n diffMaskColor: [255, 0, 0, 128],\n analyses: {\n default: [],\n disabled: [],\n options: {},\n },\n};\n\nexport function getDefaultConfig(): DriftxConfig {\n return structuredClone(DEFAULTS);\n}\n\nexport function parseConfig(raw: unknown): DriftxConfig {\n const parsed = configSchema.parse(raw);\n const defaults = getDefaultConfig();\n\n return {\n ...defaults,\n ...parsed,\n viewport: { ...defaults.viewport, ...parsed.viewport },\n timeouts: { ...defaults.timeouts, ...parsed.timeouts },\n retry: { ...defaults.retry, ...parsed.retry },\n analyses: {\n default: parsed.analyses?.default ?? DEFAULTS.analyses.default,\n disabled: parsed.analyses?.disabled ?? DEFAULTS.analyses.disabled,\n options: { ...DEFAULTS.analyses.options, ...parsed.analyses?.options },\n },\n };\n}\n\nconst explorer = cosmiconfig('driftx');\n\nexport async function loadConfig(searchFrom?: string): Promise<DriftxConfig> {\n const result = await explorer.search(searchFrom);\n if (!result || result.isEmpty) {\n return getDefaultConfig();\n }\n return parseConfig(result.config);\n}\n","export interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface InspectionCapabilities {\n tree: 'none' | 'basic' | 'detailed';\n sourceMapping: 'none' | 'partial' | 'precise';\n styles: 'none' | 'partial' | 'detailed';\n protocol: string;\n}\n\nexport interface ScrollCaptureSupport {\n supported: boolean;\n reason: string;\n mode: 'none' | 'experimental' | 'stable';\n}\n\nexport interface SourceResolution {\n fileName: string;\n lineNumber?: number;\n columnNumber?: number;\n method: 'inspectElement' | 'sourceMap' | 'filesystem' | 'resourceId';\n confidence: number;\n}\n\nexport interface ExpectedValue {\n value: string | number;\n source: 'heuristic' | 'design-metadata' | 'unknown';\n confidence: number;\n label?: string;\n}\n\nexport interface DiffEvidence {\n type: 'pixel' | 'tree' | 'accessibility' | 'semantic' | 'token' | 'regression';\n score: number;\n note: string;\n}\n\nexport interface ComponentMatch {\n name: string;\n testID?: string;\n source?: SourceResolution;\n bounds: BoundingBox;\n depth: number;\n}\n\nexport interface DiffFinding {\n id: string;\n category:\n | 'spacing'\n | 'color'\n | 'font'\n | 'alignment'\n | 'size'\n | 'content'\n | 'missing'\n | 'extra'\n | 'unknown'\n | 'accessibility'\n | 'text-mismatch'\n | 'hierarchy'\n | 'regression'\n | 'design-token';\n severity: 'critical' | 'major' | 'minor' | 'info';\n confidence: number;\n region: BoundingBox;\n component?: ComponentMatch;\n expected?: ExpectedValue;\n actual?: ExpectedValue;\n evidence: DiffEvidence[];\n description?: string;\n}\n\nexport interface RunMetadata {\n runId: string;\n startedAt: string;\n completedAt?: string;\n projectRoot: string;\n gitCommit?: string;\n gitBranch?: string;\n deviceId: string;\n platform: 'android' | 'ios';\n framework: 'react-native' | 'native-android' | 'native-ios' | 'unknown';\n orientation: 'portrait' | 'landscape';\n appId?: string;\n configHash: string;\n driftxVersion: string;\n}\n\nexport interface PrerequisiteCheck {\n name: string;\n required: boolean;\n available: boolean;\n version?: string;\n path?: string;\n error?: string;\n fix?: string;\n}\n\nexport interface CapabilityReport {\n inspection: InspectionCapabilities;\n scrollCapture: ScrollCaptureSupport;\n sourceMapping: boolean;\n prerequisites: PrerequisiteCheck[];\n}\n\nexport interface RetryPolicy {\n maxAttempts: number;\n baseDelayMs: number;\n maxDelayMs: number;\n backoffMultiplier: number;\n retryableErrors: string[];\n}\n\nexport interface TimeoutConfig {\n deviceDiscoveryMs: number;\n screenshotCaptureMs: number;\n treeInspectionMs: number;\n devToolsConnectMs: number;\n}\n\nexport interface DeviceInfo {\n id: string;\n name: string;\n platform: 'android' | 'ios';\n osVersion: string;\n screenSize?: { width: number; height: number; density: number };\n state: 'booted' | 'offline' | 'unauthorized';\n transport?: string;\n}\n\nexport interface DiffRegion {\n id: string;\n bounds: BoundingBox;\n pixelCount: number;\n percentage: number;\n cropped?: string;\n}\n\nexport interface DiffResult {\n runId: string;\n metadata: RunMetadata;\n totalPixels: number;\n diffPixels: number;\n diffPercentage: number;\n regions: DiffRegion[];\n findings: DiffFinding[];\n capabilities: CapabilityReport;\n durationMs: number;\n}\n\nexport interface ColorRange {\n r: [number, number];\n g: [number, number];\n b: [number, number];\n a?: [number, number];\n}\n\nexport interface IgnoreRule {\n type:\n | 'testID'\n | 'componentName'\n | 'textPattern'\n | 'boundingBox'\n | 'sourceFile'\n | 'colorRange';\n value: string | BoundingBox | ColorRange;\n reason?: string;\n}\n\nexport interface ComponentNode {\n id: string;\n name: string;\n nativeName?: string;\n reactName?: string;\n testID?: string;\n bounds: BoundingBox;\n text?: string;\n children: ComponentNode[];\n source?: SourceResolution;\n styles?: Record<string, string | number>;\n inspectionTier: 'basic' | 'detailed';\n}\n\nexport interface Shell {\n exec(\n cmd: string,\n args: string[],\n options?: { timeout?: number },\n ): Promise<{ stdout: string; stderr: string }>;\n}\n\nexport const DEFAULT_RETRY_POLICY: RetryPolicy = {\n maxAttempts: 3,\n baseDelayMs: 500,\n maxDelayMs: 5000,\n backoffMultiplier: 2,\n retryableErrors: ['device busy', 'transport error', 'ECONNRESET'],\n};\n\nexport const DEFAULT_TIMEOUT_CONFIG: TimeoutConfig = {\n deviceDiscoveryMs: 5000,\n screenshotCaptureMs: 10000,\n treeInspectionMs: 15000,\n devToolsConnectMs: 3000,\n};\n","import pino from 'pino';\n\nexport type LogLevel = 'debug' | 'info' | 'error' | 'silent';\n\nexport function createLogger(level: LogLevel = 'info'): pino.Logger {\n return pino({\n level: level === 'silent' ? 'silent' : level,\n transport:\n process.env.NODE_ENV !== 'test'\n ? { target: 'pino-pretty', options: { colorize: true } }\n : undefined,\n });\n}\n\nlet _logger: pino.Logger | undefined;\n\nexport function getLogger(): pino.Logger {\n if (!_logger) {\n _logger = createLogger();\n }\n return _logger;\n}\n\nexport function setLogger(logger: pino.Logger): void {\n _logger = logger;\n}\n","import type { Shell, PrerequisiteCheck } from './types.js';\n\ninterface PrerequisiteSpec {\n name: string;\n cmd: string;\n args: string[];\n required: boolean;\n versionParser: (stdout: string) => string;\n fix: string;\n}\n\nconst CLI_PREREQUISITES: PrerequisiteSpec[] = [\n {\n name: 'node',\n cmd: 'node',\n args: ['--version'],\n required: true,\n versionParser: (stdout) => stdout.trim().replace(/^v/, ''),\n fix: 'Install Node.js >= 18 from https://nodejs.org',\n },\n {\n name: 'adb',\n cmd: 'adb',\n args: ['--version'],\n required: false,\n versionParser: (stdout) => {\n const match = stdout.match(/(\\d+\\.\\d+\\.\\d+)/);\n return match?.[1] ?? 'unknown';\n },\n fix: 'Install Android SDK Platform-Tools: https://developer.android.com/studio',\n },\n {\n name: 'xcrun',\n cmd: 'xcrun',\n args: ['--version'],\n required: false,\n versionParser: (stdout) => stdout.trim(),\n fix: 'Install Xcode Command Line Tools: xcode-select --install',\n },\n];\n\nasync function checkOne(spec: PrerequisiteSpec, shell: Shell): Promise<PrerequisiteCheck> {\n try {\n const { stdout } = await shell.exec(spec.cmd, spec.args, { timeout: 5000 });\n return {\n name: spec.name,\n required: spec.required,\n available: true,\n version: spec.versionParser(stdout),\n };\n } catch (err) {\n return {\n name: spec.name,\n required: spec.required,\n available: false,\n error: err instanceof Error ? err.message : String(err),\n fix: spec.fix,\n };\n }\n}\n\nasync function checkMetro(port: number): Promise<PrerequisiteCheck> {\n try {\n const { default: http } = await import('node:http');\n const status = await new Promise<string>((resolve, reject) => {\n const req = http.get(`http://localhost:${port}/status`, { timeout: 2000 }, (res) => {\n let data = '';\n res.on('data', (chunk: Buffer) => { data += chunk; });\n res.on('end', () => resolve(data));\n });\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });\n });\n return {\n name: 'metro',\n required: false,\n available: true,\n version: `running on :${port}`,\n };\n } catch {\n return {\n name: 'metro',\n required: false,\n available: false,\n fix: 'Start Metro bundler: npx react-native start',\n };\n }\n}\n\nexport async function checkPrerequisites(shell: Shell, metroPort = 8081): Promise<PrerequisiteCheck[]> {\n const cliChecks = CLI_PREREQUISITES.map((spec) => checkOne(spec, shell));\n const metro = checkMetro(metroPort);\n return Promise.all([...cliChecks, metro]);\n}\n","export const ExitCode = {\n Success: 0,\n DiffFound: 1,\n ConfigError: 2,\n RuntimeError: 3,\n PrerequisiteMissing: 4,\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n","import type { PrerequisiteCheck } from '../types.js';\nimport { ExitCode } from '../exit-codes.js';\n\nexport function computeDoctorExitCode(checks: PrerequisiteCheck[]): number {\n return checks.some((c) => c.required && !c.available)\n ? ExitCode.PrerequisiteMissing\n : ExitCode.Success;\n}\n","import type { RunMetadata } from '../types.js';\n\ntype Framework = RunMetadata['framework'];\n\nexport function detectFramework(files: string[], packageJson?: Record<string, unknown>): Framework {\n if (packageJson) {\n const deps = {\n ...(packageJson.dependencies as Record<string, string> | undefined),\n ...(packageJson.devDependencies as Record<string, string> | undefined),\n };\n if (deps['react-native']) {\n return 'react-native';\n }\n }\n\n const hasGradle = files.some((f) => f.endsWith('.gradle') || f.endsWith('.gradle.kts'));\n if (hasGradle) return 'native-android';\n\n const hasXcode = files.some((f) => f.endsWith('.xcodeproj') || f.endsWith('.xcworkspace'));\n if (hasXcode) return 'native-ios';\n\n return 'unknown';\n}\n\ninterface InitConfig {\n framework: Framework;\n threshold: number;\n diffThreshold: number;\n settleTimeMs: number;\n platform: 'android' | 'ios';\n metroPort?: number;\n viewport: {\n cropStatusBar: boolean;\n cropNavigationBar: boolean;\n };\n}\n\nexport function generateConfig(framework: Framework): InitConfig {\n const base = {\n threshold: 0.1,\n diffThreshold: 0.01,\n settleTimeMs: 300,\n viewport: {\n cropStatusBar: true,\n cropNavigationBar: true,\n },\n };\n\n switch (framework) {\n case 'react-native':\n return { ...base, framework, platform: 'android', metroPort: 8081 };\n case 'native-android':\n return { ...base, framework, platform: 'android' };\n case 'native-ios':\n return { ...base, framework, platform: 'ios' };\n default:\n return { ...base, framework, platform: 'android' };\n }\n}\n","import type { DeviceInfo, Shell } from '../types.js';\n\nexport function parseAdbDevices(output: string): DeviceInfo[] {\n const devices: DeviceInfo[] = [];\n const lines = output.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('List of devices') || line.trim() === '') continue;\n\n const match = line.match(/^(\\S+)\\s+(device|offline|unauthorized)(.*)$/);\n if (!match) continue;\n\n const [, id, rawState, rest] = match;\n\n const modelMatch = rest.match(/model:(\\S+)/);\n const transportMatch = rest.match(/transport_id:(\\S+)/);\n\n const state: DeviceInfo['state'] =\n rawState === 'device' ? 'booted' :\n rawState === 'offline' ? 'offline' : 'unauthorized';\n\n devices.push({\n id,\n name: modelMatch?.[1] ?? id,\n platform: 'android',\n osVersion: '',\n state,\n transport: transportMatch?.[1],\n });\n }\n\n return devices;\n}\n\nasync function fetchApiLevel(shell: Shell, deviceId: string): Promise<string> {\n try {\n const { stdout } = await shell.exec('adb', ['-s', deviceId, 'shell', 'getprop', 'ro.build.version.sdk']);\n return stdout.trim();\n } catch {\n return '';\n }\n}\n\nexport async function discoverAndroidDevices(shell: Shell): Promise<DeviceInfo[]> {\n const { stdout } = await shell.exec('adb', ['devices', '-l']);\n const devices = parseAdbDevices(stdout);\n\n for (const device of devices) {\n if (device.state === 'booted') {\n device.osVersion = await fetchApiLevel(shell, device.id);\n }\n }\n\n return devices;\n}\n","import type { DeviceInfo, Shell } from '../types.js';\n\ninterface SimctlDevice {\n udid: string;\n name: string;\n state: string;\n isAvailable: boolean;\n}\n\ninterface SimctlOutput {\n devices: Record<string, SimctlDevice[]>;\n}\n\nfunction parseOsVersion(runtime: string): string {\n const match = runtime.match(/iOS-(\\d+)-(\\d+)/);\n return match ? `${match[1]}.${match[2]}` : '';\n}\n\nexport function parseSimctlDevices(output: string): DeviceInfo[] {\n let parsed: SimctlOutput;\n try {\n parsed = JSON.parse(output);\n } catch {\n return [];\n }\n\n const devices: DeviceInfo[] = [];\n\n for (const [runtime, sims] of Object.entries(parsed.devices)) {\n const osVersion = parseOsVersion(runtime);\n\n for (const sim of sims) {\n if (!sim.isAvailable) continue;\n\n const state: DeviceInfo['state'] =\n sim.state === 'Booted' ? 'booted' : 'offline';\n\n devices.push({\n id: sim.udid,\n name: sim.name,\n platform: 'ios',\n osVersion,\n state,\n });\n }\n }\n\n return devices;\n}\n\nexport async function discoverIosDevices(shell: Shell): Promise<DeviceInfo[]> {\n const { stdout } = await shell.exec('xcrun', ['simctl', 'list', 'devices', '--json']);\n return parseSimctlDevices(stdout);\n}\n","import type { DeviceInfo, Shell } from '../types.js';\nimport { discoverAndroidDevices } from './android-discovery.js';\nimport { discoverIosDevices } from './ios-discovery.js';\nimport { getLogger } from '../logger.js';\n\ninterface DiscoveryOptions {\n cacheTtlMs?: number;\n}\n\nexport class DeviceDiscovery {\n private shell: Shell;\n private cacheTtlMs: number;\n private cache: DeviceInfo[] | null = null;\n private cacheTime = 0;\n\n constructor(shell: Shell, options?: DiscoveryOptions) {\n this.shell = shell;\n this.cacheTtlMs = options?.cacheTtlMs ?? 30000;\n }\n\n async list(): Promise<DeviceInfo[]> {\n if (this.cache && Date.now() - this.cacheTime < this.cacheTtlMs) {\n return this.cache;\n }\n\n const results: DeviceInfo[] = [];\n const logger = getLogger();\n\n try {\n const android = await discoverAndroidDevices(this.shell);\n results.push(...android);\n } catch (err) {\n logger.debug({ err }, 'Android discovery failed');\n }\n\n try {\n const ios = await discoverIosDevices(this.shell);\n results.push(...ios);\n } catch (err) {\n logger.debug({ err }, 'iOS discovery failed');\n }\n\n this.cache = results;\n this.cacheTime = Date.now();\n return results;\n }\n\n async findById(id: string): Promise<DeviceInfo | undefined> {\n const devices = await this.list();\n return devices.find((d) => d.id === id);\n }\n\n invalidateCache(): void {\n this.cache = null;\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { Shell, DeviceInfo } from '../types.js';\nimport { DEFAULT_RETRY_POLICY } from '../types.js';\nimport type { DriftxConfig } from '../config.js';\nimport { DeviceDiscovery } from '../devices/discovery.js';\nimport { captureScreenshot } from '../capture/capture.js';\nimport { RunStore } from '../run-store.js';\nimport { withRetry } from '../retry.js';\nimport { pickDevice } from './device-picker.js';\n\nexport interface CaptureCommandOptions {\n device?: string;\n output?: string;\n settleCheck?: boolean;\n}\n\nexport async function runCapture(\n shell: Shell,\n config: DriftxConfig,\n options: CaptureCommandOptions,\n): Promise<{ path: string; runId: string }> {\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n\n if (booted.length === 0) {\n throw new Error('No booted devices found. Start an emulator or boot a simulator.');\n }\n\n let device: DeviceInfo;\n if (options.device) {\n const found = booted.find((d) => d.id === options.device || d.name === options.device);\n if (!found) throw new Error(`Device not found: ${options.device}`);\n device = found;\n } else if (config.primaryDevice) {\n const found = booted.find((d) => d.id === config.primaryDevice || d.name === config.primaryDevice);\n if (!found) throw new Error(`Primary device not found: ${config.primaryDevice}`);\n device = found;\n } else {\n device = await pickDevice(booted);\n }\n\n const buffer = await withRetry(\n () => captureScreenshot(shell, device, {\n settleCheck: options.settleCheck ?? config.settleCheckEnabled,\n settleMaxDelta: config.settleMaxDelta,\n settleDelayMs: config.settleTimeMs,\n }),\n config.retry ?? DEFAULT_RETRY_POLICY,\n );\n\n const projectRoot = process.cwd();\n\n if (options.output) {\n fs.mkdirSync(path.dirname(options.output), { recursive: true });\n fs.writeFileSync(options.output, buffer);\n return { path: options.output, runId: '' };\n }\n\n const store = new RunStore(projectRoot);\n const run = store.createRun();\n await store.writeArtifact(run.runId, 'screenshot.png', buffer);\n await store.writeMetadata(run.runId, {\n runId: run.runId,\n startedAt: new Date().toISOString(),\n completedAt: new Date().toISOString(),\n deviceId: device.id,\n platform: device.platform,\n orientation: 'portrait',\n framework: 'unknown',\n projectRoot,\n driftxVersion: '0.1.0',\n });\n\n return { path: store.getRunPath(run.runId, 'screenshot.png'), runId: run.runId };\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { Shell } from '../types.js';\n\nconst DEVICE_TMP_PATH = '/sdcard/driftx-tmp.png';\n\nexport async function captureAndroidScreenshot(\n shell: Shell,\n deviceId: string,\n timeout?: number,\n): Promise<Buffer> {\n const localTmp = path.join(os.tmpdir(), `driftx-android-${Date.now()}-${deviceId}.png`);\n\n try {\n await shell.exec(\n 'adb',\n ['-s', deviceId, 'shell', 'screencap', '-p', DEVICE_TMP_PATH],\n timeout ? { timeout } : undefined,\n );\n await shell.exec('adb', ['-s', deviceId, 'pull', DEVICE_TMP_PATH, localTmp]);\n\n if (!fs.existsSync(localTmp)) {\n throw new Error('Screenshot capture returned empty buffer — pull did not create local file');\n }\n const buffer = fs.readFileSync(localTmp);\n if (buffer.length === 0) {\n throw new Error('Screenshot capture returned empty buffer');\n }\n return buffer;\n } finally {\n try {\n await shell.exec('adb', ['-s', deviceId, 'shell', 'rm', DEVICE_TMP_PATH]);\n } catch {}\n try {\n if (fs.existsSync(localTmp)) fs.unlinkSync(localTmp);\n } catch {}\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { Shell } from '../types.js';\n\nexport async function captureIosScreenshot(\n shell: Shell,\n deviceId: string,\n tmpPath?: string,\n): Promise<Buffer> {\n const screenshotPath = tmpPath ?? path.join(os.tmpdir(), `driftx-ios-${Date.now()}.png`);\n await shell.exec('xcrun', ['simctl', 'io', deviceId, 'screenshot', screenshotPath]);\n\n if (!fs.existsSync(screenshotPath)) {\n throw new Error(`iOS screenshot not created at ${screenshotPath}`);\n }\n const buffer = fs.readFileSync(screenshotPath);\n if (!tmpPath) fs.unlinkSync(screenshotPath);\n if (buffer.length === 0) throw new Error('iOS screenshot capture returned empty file');\n return buffer;\n}\n","import type { DeviceInfo, Shell } from '../types.js';\nimport { captureAndroidScreenshot } from './android-capture.js';\nimport { captureIosScreenshot } from './ios-capture.js';\nimport { getLogger } from '../logger.js';\nimport pixelmatch from 'pixelmatch';\nimport { PNG } from 'pngjs';\n\nexport function isScreenSettled(buf1: Buffer, buf2: Buffer, maxDelta: number): boolean {\n const img1 = PNG.sync.read(buf1);\n const img2 = PNG.sync.read(buf2);\n if (img1.width !== img2.width || img1.height !== img2.height) return false;\n const diffPixels = pixelmatch(img1.data, img2.data, undefined, img1.width, img1.height, {\n threshold: 0.1,\n });\n const totalPixels = img1.width * img1.height;\n return diffPixels / totalPixels <= maxDelta;\n}\n\nexport interface CaptureOptions {\n settleCheck?: boolean;\n settleMaxDelta?: number;\n settleDelayMs?: number;\n settleMaxAttempts?: number;\n timeout?: number;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function captureScreenshot(\n shell: Shell,\n device: DeviceInfo,\n options?: CaptureOptions,\n): Promise<Buffer> {\n const logger = getLogger();\n const captureOnce = async (): Promise<Buffer> => {\n if (device.platform === 'android') {\n return captureAndroidScreenshot(shell, device.id, options?.timeout);\n }\n return captureIosScreenshot(shell, device.id);\n };\n\n let buffer = await captureOnce();\n\n if (options?.settleCheck) {\n const maxDelta = options.settleMaxDelta ?? 0.001;\n const delayMs = options.settleDelayMs ?? 300;\n const maxAttempts = options.settleMaxAttempts ?? 5;\n\n for (let i = 0; i < maxAttempts; i++) {\n await delay(delayMs);\n const next = await captureOnce();\n if (isScreenSettled(buffer, next, maxDelta)) {\n logger.debug(`Screen settled after ${i + 1} check(s)`);\n return next;\n }\n buffer = next;\n }\n logger.warn('Screen did not settle within max attempts, using last capture');\n }\n\n return buffer;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { nanoid } from 'nanoid';\n\nexport interface RunHandle {\n runId: string;\n dir: string;\n}\n\nexport class RunStore {\n private baseDir: string;\n\n constructor(projectRoot: string) {\n this.baseDir = path.join(projectRoot, '.driftx', 'runs');\n }\n\n createRun(): RunHandle {\n const runId = nanoid(12);\n const dir = path.join(this.baseDir, runId);\n fs.mkdirSync(dir, { recursive: true });\n return { runId, dir };\n }\n\n private getRunDir(runId: string): string {\n return path.join(this.baseDir, runId);\n }\n\n async writeMetadata(runId: string, metadata: Record<string, unknown>): Promise<void> {\n const filePath = path.join(this.getRunDir(runId), 'metadata.json');\n fs.writeFileSync(filePath, JSON.stringify(metadata, null, 2));\n }\n\n async writeArtifact(runId: string, relativePath: string, data: Buffer): Promise<void> {\n const filePath = path.join(this.getRunDir(runId), relativePath);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, data);\n }\n\n listRuns(): string[] {\n if (!fs.existsSync(this.baseDir)) return [];\n return fs.readdirSync(this.baseDir).filter((f) => {\n return fs.statSync(path.join(this.baseDir, f)).isDirectory();\n });\n }\n\n getRunPath(runId: string, relativePath?: string): string {\n const dir = this.getRunDir(runId);\n return relativePath ? path.join(dir, relativePath) : dir;\n }\n\n readArtifact(runId: string, relativePath: string): Buffer | null {\n const fullPath = path.join(this.getRunDir(runId), relativePath);\n try {\n return fs.readFileSync(fullPath);\n } catch {\n return null;\n }\n }\n\n getLatestRun(): string | undefined {\n const runs = this.listRuns();\n if (runs.length === 0) return undefined;\n let latest: string | undefined;\n let latestTime = 0;\n for (const runId of runs) {\n try {\n const stat = fs.statSync(this.getRunDir(runId));\n if (stat.mtimeMs > latestTime) {\n latestTime = stat.mtimeMs;\n latest = runId;\n }\n } catch {\n continue;\n }\n }\n return latest;\n }\n}\n","import type { RetryPolicy } from './types.js';\n\nfunction isRetryable(error: Error, policy: RetryPolicy): boolean {\n return policy.retryableErrors.some((pattern) => error.message.includes(pattern));\n}\n\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error('Aborted'));\n return;\n }\n\n const timer = setTimeout(resolve, ms);\n\n signal?.addEventListener('abort', () => {\n clearTimeout(timer);\n reject(new Error('Aborted'));\n }, { once: true });\n });\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n policy: RetryPolicy,\n signal?: AbortSignal,\n): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < policy.maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n if (!isRetryable(lastError, policy)) {\n throw lastError;\n }\n\n if (signal?.aborted) {\n throw lastError;\n }\n\n if (attempt < policy.maxAttempts - 1) {\n const backoff = Math.min(\n policy.baseDelayMs * Math.pow(policy.backoffMultiplier, attempt),\n policy.maxDelayMs,\n );\n\n try {\n await delay(backoff, signal);\n } catch {\n throw lastError;\n }\n }\n }\n }\n\n throw lastError;\n}\n","import { select } from '@inquirer/prompts';\nimport type { DeviceInfo } from '../types.js';\n\nexport async function pickDevice(booted: DeviceInfo[]): Promise<DeviceInfo> {\n if (booted.length === 1) return booted[0];\n\n const selected = await select({\n message: 'Select a device',\n choices: booted.map((d) => ({\n name: `${d.name} (${d.platform}, ${d.osVersion || 'unknown'})`,\n value: d.id,\n })),\n });\n\n return booted.find((d) => d.id === selected)!;\n}\n","import type { ComponentNode, BoundingBox, Shell } from '../types.js';\n\nfunction parseBounds(boundsStr: string): BoundingBox {\n const match = boundsStr.match(/\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]/);\n if (!match) return { x: 0, y: 0, width: 0, height: 0 };\n const [, x1, y1, x2, y2] = match.map(Number);\n return { x: x1, y: y1, width: x2 - x1, height: y2 - y1 };\n}\n\nfunction parseNode(nodeStr: string, idCounter: { n: number }): { node: ComponentNode; remaining: string } | null {\n const attrMatch = nodeStr.match(/^<node\\s+([^>]*?)(\\/?>)/);\n if (!attrMatch) return null;\n\n const attrs = attrMatch[1];\n const selfClosing = attrMatch[2] === '/>';\n const afterTag = nodeStr.slice(attrMatch[0].length);\n\n const get = (name: string): string => {\n const m = attrs.match(new RegExp(`${name}=\"([^\"]*)\"`));\n return m ? m[1] : '';\n };\n\n const id = String(idCounter.n++);\n const resourceId = get('resource-id');\n const className = get('class');\n\n const node: ComponentNode = {\n id,\n name: className || 'unknown',\n nativeName: className || undefined,\n testID: resourceId || undefined,\n bounds: parseBounds(get('bounds')),\n text: get('text') || undefined,\n children: [],\n inspectionTier: 'basic',\n };\n\n if (selfClosing) {\n return { node, remaining: afterTag };\n }\n\n let rest = afterTag;\n while (true) {\n rest = rest.replace(/^\\s+/, '');\n if (rest.startsWith('</node>')) {\n rest = rest.slice('</node>'.length);\n break;\n }\n const child = parseNode(rest, idCounter);\n if (!child) break;\n node.children.push(child.node);\n rest = child.remaining;\n }\n\n return { node, remaining: rest };\n}\n\nexport function parseUiAutomatorXml(xml: string): ComponentNode[] {\n if (!xml.includes('<hierarchy')) {\n throw new Error('Invalid UIAutomator XML: missing <hierarchy> element');\n }\n\n const hierarchyMatch = xml.match(/<hierarchy[^>]*>([\\s\\S]*)<\\/hierarchy>/);\n if (!hierarchyMatch) return [];\n\n const content = hierarchyMatch[1].trim();\n if (!content) return [];\n\n const nodes: ComponentNode[] = [];\n const idCounter = { n: 0 };\n let remaining = content;\n\n while (remaining.trim()) {\n remaining = remaining.replace(/^\\s+/, '');\n if (!remaining.startsWith('<node')) break;\n const result = parseNode(remaining, idCounter);\n if (!result) break;\n nodes.push(result.node);\n remaining = result.remaining;\n }\n\n return nodes;\n}\n\nexport async function dumpUiAutomator(shell: Shell, deviceId: string, timeout?: number): Promise<ComponentNode[]> {\n const { stdout } = await shell.exec('adb', ['-s', deviceId, 'exec-out', 'uiautomator', 'dump', '/dev/tty'], timeout ? { timeout } : undefined);\n return parseUiAutomatorXml(stdout);\n}\n","import type { ComponentNode, Shell } from '../types.js';\nimport { getLogger } from '../logger.js';\n\ninterface AXElement {\n frame?: { x: number; y: number; width: number; height: number };\n role?: string;\n label?: string;\n identifier?: string;\n children?: AXElement[];\n}\n\nfunction parseElement(el: AXElement, idCounter: { n: number }): ComponentNode {\n const id = String(idCounter.n++);\n return {\n id,\n name: el.role ?? 'unknown',\n nativeName: el.role,\n testID: el.identifier || undefined,\n bounds: el.frame\n ? { x: el.frame.x, y: el.frame.y, width: el.frame.width, height: el.frame.height }\n : { x: 0, y: 0, width: 0, height: 0 },\n text: el.label || undefined,\n children: (el.children ?? []).map((c) => parseElement(c, idCounter)),\n inspectionTier: 'basic',\n };\n}\n\nexport function parseIosAccessibility(json: string): ComponentNode[] {\n const data = JSON.parse(json);\n const elements: AXElement[] = data.AXElements ?? [];\n const idCounter = { n: 0 };\n return elements.map((el) => parseElement(el, idCounter));\n}\n\nexport async function dumpIosAccessibility(shell: Shell, deviceId: string, timeout?: number): Promise<ComponentNode[]> {\n const logger = getLogger();\n const opts = timeout ? { timeout } : undefined;\n\n // Try idb (Facebook's iOS Development Bridge) if available\n try {\n const { stdout } = await shell.exec('idb', ['ui', 'describe-all', '--udid', deviceId], opts);\n return parseIosAccessibility(stdout);\n } catch {\n logger.debug('idb not available, skipping iOS accessibility tree');\n }\n\n throw new Error('iOS accessibility inspection requires idb (brew install idb-companion && pip install fb-idb) or React DevTools');\n}\n","import WebSocket from 'ws';\nimport http from 'node:http';\nimport type { ComponentNode, InspectionCapabilities } from '../types.js';\nimport { getLogger } from '../logger.js';\n\nexport interface CdpTarget {\n id: string;\n title: string;\n description: string;\n appId?: string;\n webSocketDebuggerUrl: string;\n deviceName?: string;\n reactNative?: {\n logicalDeviceId: string;\n };\n}\n\ninterface CdpResponse {\n id: number;\n result?: {\n result?: {\n type: string;\n value?: unknown;\n };\n exceptionDetails?: unknown;\n };\n error?: { message: string };\n}\n\nconst FIBER_WALK_SCRIPT = `(function() {\n try {\n var hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n if (!hook || !hook.renderers || hook.renderers.size === 0) return JSON.stringify(null);\n\n var flat = [];\n hook.renderers.forEach(function(renderer, id) {\n var roots = hook.getFiberRoots(id);\n if (!roots) return;\n roots.forEach(function(root) {\n if (root.current) flattenFiber(root.current, 0);\n });\n });\n\n return flat.length > 0 ? JSON.stringify(flat) : JSON.stringify(null);\n } catch(e) {\n return JSON.stringify(null);\n }\n\n function getName(fiber) {\n if (typeof fiber.type === 'string') return fiber.type;\n if (fiber.type && fiber.type.displayName) return fiber.type.displayName;\n if (fiber.type && fiber.type.name) return fiber.type.name;\n if (fiber.tag === 3) return null;\n return null;\n }\n\n function isNoise(name, fiber) {\n if (!name) return true;\n if (fiber.tag === 6) return true;\n var props = fiber.memoizedProps || {};\n var hasSignal = props.testID || props.nativeID || typeof props.children === 'string';\n if (hasSignal) return false;\n if (name === 'Unknown') return true;\n if (fiber.tag === 5) return true;\n if (name.substring(0, 3) === 'RCT' || name.substring(0, 5) === 'RNSVG') return true;\n if (name.indexOf('ViewManagerAdapter_') === 0) return true;\n var len = name.length;\n if (len > 7 && name.indexOf('Context', len - 7) === len - 7) return true;\n if (len > 8 && name.indexOf('Provider', len - 8) === len - 8) return true;\n if (len > 8 && name.indexOf('Consumer', len - 8) === len - 8) return true;\n var c = name.charCodeAt(0);\n if (c >= 97 && c <= 122) return true;\n if (name.indexOf('Animated(') === 0) return true;\n return false;\n }\n\n function flattenFiber(fiber, depth) {\n if (!fiber) return;\n var name = getName(fiber);\n var noise = isNoise(name, fiber);\n\n if (!noise) {\n var props = fiber.memoizedProps || {};\n var testID = props.testID || props.nativeID || undefined;\n var text = typeof props.children === 'string' ? props.children : undefined;\n flat.push({ n: name, d: depth, t: testID, x: text });\n var child = fiber.child;\n while (child) { flattenFiber(child, depth + 1); child = child.sibling; }\n } else {\n var child = fiber.child;\n while (child) { flattenFiber(child, depth); child = child.sibling; }\n }\n }\n})()`;\n\nexport async function discoverTargets(metroPort: number): Promise<CdpTarget[]> {\n return new Promise((resolve, reject) => {\n const req = http.get(`http://localhost:${metroPort}/json/list`, { timeout: 2000 }, (res) => {\n let data = '';\n res.on('data', (chunk: Buffer) => { data += chunk; });\n res.on('end', () => {\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve([]);\n }\n });\n });\n req.on('error', () => resolve([]));\n req.on('timeout', () => { req.destroy(); resolve([]); });\n });\n}\n\nexport function findRuntimeTarget(targets: CdpTarget[], deviceName?: string): CdpTarget | undefined {\n const rnTargets = targets.filter((t) =>\n t.reactNative && t.description.includes('React Native'),\n );\n\n if (deviceName) {\n return rnTargets.find((t) =>\n t.deviceName?.toLowerCase().includes(deviceName.toLowerCase()),\n );\n }\n\n return rnTargets[0];\n}\n\nexport class CdpClient {\n private ws: WebSocket | null = null;\n private connected = false;\n private msgId = 0;\n private pending = new Map<number, { resolve: (v: CdpResponse) => void; reject: (e: Error) => void }>();\n\n async connectAndGetTree(metroPort: number, timeoutMs: number, deviceName?: string): Promise<ComponentNode[]> {\n const logger = getLogger();\n\n const targets = await discoverTargets(metroPort);\n const target = findRuntimeTarget(targets, deviceName);\n if (!target) {\n logger.debug('No React Native debug target found via Metro');\n return [];\n }\n\n logger.debug(`Found CDP target: ${target.title} (${target.description})`);\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.cleanup();\n resolve([]);\n }, timeoutMs);\n\n try {\n this.ws = new WebSocket(target.webSocketDebuggerUrl);\n } catch {\n clearTimeout(timer);\n resolve([]);\n return;\n }\n\n this.ws.on('open', async () => {\n this.connected = true;\n try {\n const result = await this.evaluate(FIBER_WALK_SCRIPT);\n clearTimeout(timer);\n resolve(this.parseResult(result));\n } catch {\n clearTimeout(timer);\n resolve([]);\n }\n });\n\n this.ws.on('message', (data: Buffer) => {\n try {\n const msg: CdpResponse = JSON.parse(data.toString());\n if (msg.id !== undefined) {\n const p = this.pending.get(msg.id);\n if (p) {\n this.pending.delete(msg.id);\n p.resolve(msg);\n }\n }\n } catch {}\n });\n\n this.ws.on('error', () => {\n clearTimeout(timer);\n resolve([]);\n });\n\n this.ws.on('close', () => {\n this.connected = false;\n });\n });\n }\n\n private evaluate(expression: string): Promise<CdpResponse> {\n const id = ++this.msgId;\n return new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n this.ws!.send(JSON.stringify({\n id,\n method: 'Runtime.evaluate',\n params: { expression, returnByValue: true },\n }));\n });\n }\n\n private parseResult(response: CdpResponse): ComponentNode[] {\n const value = response.result?.result?.value;\n if (!value || typeof value !== 'string') return [];\n\n const parsed = JSON.parse(value);\n if (!Array.isArray(parsed)) return [];\n\n return this.optimize(this.rebuildTree(parsed));\n }\n\n private optimize(roots: ComponentNode[]): ComponentNode[] {\n let tree = roots;\n let prevCount = -1;\n for (let i = 0; i < 10; i++) {\n tree = this.dedup(tree);\n tree = this.pruneLeaves(tree);\n const count = this.countNodes(tree);\n if (count === prevCount) break;\n prevCount = count;\n }\n return tree;\n }\n\n private countNodes(nodes: ComponentNode[]): number {\n let c = 0;\n for (const n of nodes) c += 1 + this.countNodes(n.children);\n return c;\n }\n\n private pruneLeaves(nodes: ComponentNode[]): ComponentNode[] {\n return nodes.reduce<ComponentNode[]>((acc, node) => {\n node.children = this.pruneLeaves(node.children);\n if (node.children.length === 0 && !node.testID && !node.text) return acc;\n acc.push(node);\n return acc;\n }, []);\n }\n\n private rebuildTree(flat: Array<{ n: string; d: number; t?: string; x?: string }>): ComponentNode[] {\n const roots: ComponentNode[] = [];\n const stack: ComponentNode[] = [];\n let id = 0;\n\n for (const entry of flat) {\n const node: ComponentNode = {\n id: String(id++),\n name: entry.n,\n reactName: entry.n,\n testID: entry.t || undefined,\n bounds: { x: 0, y: 0, width: 0, height: 0 },\n text: entry.x || undefined,\n children: [],\n inspectionTier: 'detailed',\n };\n\n while (stack.length > entry.d) stack.pop();\n\n if (stack.length === 0) {\n roots.push(node);\n } else {\n stack[stack.length - 1].children.push(node);\n }\n stack.push(node);\n }\n\n return roots;\n }\n\n private dedup(nodes: ComponentNode[]): ComponentNode[] {\n return nodes.map((node) => this.dedupNode(node)).filter(Boolean) as ComponentNode[];\n }\n\n private dedupNode(node: ComponentNode): ComponentNode | null {\n node.children = this.dedup(node.children);\n if (node.children.length === 1) {\n const child = node.children[0];\n const sameText = node.text && child.text && node.text === child.text;\n const sameTestID = node.testID && child.testID && node.testID === child.testID;\n if (sameText || sameTestID) {\n child.children = [...child.children];\n return child;\n }\n const nodeHasSignal = node.testID || node.text;\n if (!nodeHasSignal) {\n child.children = [...child.children];\n return child;\n }\n }\n return node;\n }\n\n getCapabilities(): InspectionCapabilities {\n return {\n tree: this.connected ? 'detailed' : 'none',\n sourceMapping: this.connected ? 'partial' : 'none',\n styles: this.connected ? 'partial' : 'none',\n protocol: 'cdp',\n };\n }\n\n async disconnect(): Promise<void> {\n this.cleanup();\n }\n\n private cleanup(): void {\n if (this.ws) {\n try { this.ws.close(); } catch {}\n this.ws = null;\n }\n this.connected = false;\n for (const [, p] of this.pending) {\n p.reject(new Error('disconnected'));\n }\n this.pending.clear();\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { StrategyMethod } from './tree-inspector.js';\n\nexport interface CachedEntry {\n method: StrategyMethod;\n reason: string;\n appId?: string;\n timestamp: number;\n}\n\nexport class StrategyCache {\n private filePath: string;\n private ttlMs: number;\n private entries: Map<string, CachedEntry>;\n\n constructor(projectRoot: string, ttlMs: number = 60_000) {\n this.filePath = path.join(projectRoot, '.driftx', 'strategy-cache.json');\n this.ttlMs = ttlMs;\n this.entries = this.load();\n }\n\n get(deviceId: string): CachedEntry | undefined {\n const entry = this.entries.get(deviceId);\n if (!entry) return undefined;\n if (Date.now() - entry.timestamp > this.ttlMs) {\n this.entries.delete(deviceId);\n this.persist();\n return undefined;\n }\n return entry;\n }\n\n set(deviceId: string, method: StrategyMethod, reason: string, appId?: string): void {\n this.entries.set(deviceId, { method, reason, appId, timestamp: Date.now() });\n this.persist();\n }\n\n delete(deviceId: string): void {\n this.entries.delete(deviceId);\n this.persist();\n }\n\n clear(): void {\n this.entries.clear();\n this.persist();\n }\n\n private load(): Map<string, CachedEntry> {\n try {\n const raw = fs.readFileSync(this.filePath, 'utf-8');\n const data: Record<string, CachedEntry> = JSON.parse(raw);\n return new Map(Object.entries(data));\n } catch {\n return new Map();\n }\n }\n\n private persist(): void {\n try {\n const dir = path.dirname(this.filePath);\n fs.mkdirSync(dir, { recursive: true });\n const obj: Record<string, CachedEntry> = Object.fromEntries(this.entries);\n fs.writeFileSync(this.filePath, JSON.stringify(obj, null, 2));\n } catch {\n // best-effort — don't break inspection if cache write fails\n }\n }\n}\n","import type { Shell, DeviceInfo, ComponentNode, InspectionCapabilities } from '../types.js';\nimport { dumpUiAutomator } from './uiautomator.js';\nimport { dumpIosAccessibility } from './ios-accessibility.js';\nimport { CdpClient, discoverTargets, findRuntimeTarget } from './cdp-client.js';\nimport type { CdpTarget } from './cdp-client.js';\nimport { StrategyCache } from './strategy-cache.js';\nimport { getLogger } from '../logger.js';\n\nexport interface InspectOptions {\n metroPort: number;\n devToolsPort: number;\n timeoutMs: number;\n}\n\nexport type StrategyMethod = 'cdp' | 'uiautomator' | 'idb' | 'none';\n\nexport interface InspectionStrategy {\n method: StrategyMethod;\n reason: string;\n appId?: string;\n cdpTarget?: CdpTarget;\n}\n\nexport interface InspectResult {\n tree: ComponentNode[];\n capabilities: InspectionCapabilities;\n strategy: InspectionStrategy;\n device: { name: string; platform: 'android' | 'ios' };\n hints: string[];\n}\n\nexport class TreeInspector {\n private shell: Shell;\n private fileCache: StrategyCache | null;\n\n constructor(shell: Shell, projectRoot?: string) {\n this.shell = shell;\n this.fileCache = projectRoot ? new StrategyCache(projectRoot) : null;\n }\n\n invalidateCache(deviceId?: string): void {\n if (!this.fileCache) return;\n if (deviceId) {\n this.fileCache.delete(deviceId);\n } else {\n this.fileCache.clear();\n }\n }\n\n async resolveStrategy(device: DeviceInfo, options: InspectOptions): Promise<InspectionStrategy> {\n if (options.metroPort > 0) {\n const targets = await discoverTargets(options.metroPort);\n const target = findRuntimeTarget(targets, device.name);\n if (target) {\n return {\n method: 'cdp',\n reason: 'React Native app connected via Metro',\n appId: target.appId,\n cdpTarget: target,\n };\n }\n }\n\n if (device.platform === 'android') {\n return { method: 'uiautomator', reason: 'Android native inspection' };\n }\n\n return { method: 'idb', reason: 'iOS native inspection via idb' };\n }\n\n async inspect(device: DeviceInfo, options: InspectOptions): Promise<InspectResult> {\n const logger = getLogger();\n const hints: string[] = [];\n let usedCache = false;\n\n const cachedEntry = this.fileCache?.get(device.id);\n let strategy: InspectionStrategy;\n\n if (cachedEntry && cachedEntry.method !== 'none') {\n logger.debug(`Using cached strategy for ${device.name}: ${cachedEntry.method}`);\n usedCache = true;\n if (cachedEntry.method === 'cdp' && options.metroPort > 0) {\n const targets = await discoverTargets(options.metroPort);\n const target = findRuntimeTarget(targets, device.name);\n strategy = target\n ? { method: 'cdp', reason: cachedEntry.reason, appId: target.appId, cdpTarget: target }\n : await this.resolveStrategy(device, options);\n } else {\n strategy = { method: cachedEntry.method, reason: cachedEntry.reason, appId: cachedEntry.appId };\n }\n } else {\n strategy = await this.resolveStrategy(device, options);\n }\n\n this.fileCache?.set(device.id, strategy.method, strategy.reason, strategy.appId);\n\n const base = { device: { name: device.name, platform: device.platform }, strategy };\n\n if (strategy.method === 'cdp' && strategy.cdpTarget) {\n try {\n const cdp = new CdpClient();\n const tree = await cdp.connectAndGetTree(\n options.metroPort, options.timeoutMs, device.name,\n );\n const caps = cdp.getCapabilities();\n await cdp.disconnect();\n if (tree.length > 0) {\n logger.debug(`CDP: got ${tree.length} root nodes for ${device.name}`);\n return { ...base, tree, capabilities: caps, hints };\n }\n } catch (err) {\n logger.debug(`CDP failed: ${err instanceof Error ? err.message : err}`);\n }\n logger.debug('CDP strategy resolved but returned no tree, falling back to native');\n }\n\n if (strategy.method === 'uiautomator' || (strategy.method === 'cdp' && device.platform === 'android')) {\n try {\n const tree = await dumpUiAutomator(this.shell, device.id, options.timeoutMs);\n logger.debug(`UIAutomator: got ${tree.length} root nodes for ${device.name}`);\n return {\n ...base,\n strategy: { method: 'uiautomator', reason: strategy.method === 'cdp' ? 'CDP fallback to native' : strategy.reason },\n tree,\n capabilities: { tree: 'basic', sourceMapping: 'none', styles: 'none', protocol: 'uiautomator' },\n hints,\n };\n } catch (err) {\n logger.debug(`UIAutomator failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n if (strategy.method === 'idb' || (strategy.method === 'cdp' && device.platform === 'ios')) {\n try {\n const tree = await dumpIosAccessibility(this.shell, device.id, options.timeoutMs);\n logger.debug(`idb: got ${tree.length} root nodes for ${device.name}`);\n return {\n ...base,\n strategy: { method: 'idb', reason: strategy.method === 'cdp' ? 'CDP fallback to native' : strategy.reason },\n tree,\n capabilities: { tree: 'basic', sourceMapping: 'none', styles: 'none', protocol: 'idb' },\n hints,\n };\n } catch (err) {\n logger.debug(`iOS accessibility failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n if (device.platform === 'ios') {\n hints.push('Install idb for native iOS tree inspection: brew install idb-companion && pip install fb-idb');\n }\n\n if (usedCache) {\n this.fileCache?.delete(device.id);\n logger.debug(`Invalidated cached strategy for ${device.name} after complete failure`);\n }\n\n return {\n ...base,\n strategy: { method: 'none', reason: 'No inspection method available' },\n tree: [],\n capabilities: { tree: 'none', sourceMapping: 'none', styles: 'none', protocol: 'none' },\n hints,\n };\n }\n}\n","import pc from 'picocolors';\nimport type { DiffFinding, DiffRegion, ComponentNode } from '../types.js';\nimport type { OutputFormatter, CompareFormatData } from './types.js';\nimport type { AnalysisResult } from '../analyses/types.js';\n\nfunction confidenceLabel(confidence: number): string {\n if (confidence >= 0.8) return 'high';\n if (confidence >= 0.5) return 'probable';\n return 'approximate';\n}\n\nfunction severityColor(severity: DiffFinding['severity'], text: string): string {\n if (severity === 'critical') return pc.red(pc.bold(text));\n if (severity === 'major') return pc.yellow(text);\n if (severity === 'minor') return pc.cyan(text);\n return pc.dim(text);\n}\n\nfunction severityCounts(findings: DiffFinding[]): string {\n const counts: Record<string, number> = {};\n for (const f of findings) {\n counts[f.severity] = (counts[f.severity] ?? 0) + 1;\n }\n const parts: string[] = [];\n for (const sev of ['critical', 'major', 'minor', 'info'] as const) {\n if (counts[sev]) parts.push(`${counts[sev]} ${sev}`);\n }\n return parts.join(', ');\n}\n\nfunction formatTreePlain(nodes: ComponentNode[], indent: number = 0): string {\n const lines: string[] = [];\n for (const node of nodes) {\n const prefix = ' '.repeat(indent);\n const name = node.reactName ?? node.name;\n const testId = node.testID ? ` [${node.testID}]` : '';\n const text = node.text ? ` \"${node.text}\"` : '';\n const b = node.bounds;\n const bounds = b.width > 0 ? ` (${b.x},${b.y} ${b.width}x${b.height})` : '';\n lines.push(`${prefix}${name}${testId}${text}${bounds}`);\n const childStr = formatTreePlain(node.children, indent + 1);\n if (childStr) lines.push(childStr);\n }\n return lines.join('\\n');\n}\n\nfunction getPixelMeta(analyses: AnalysisResult[]): {\n diffPercentage: number;\n diffPixels: number;\n totalPixels: number;\n regions: DiffRegion[];\n} {\n const pixel = analyses.find((a) => a.analysisName === 'pixel');\n const meta = pixel?.metadata as Record<string, unknown> | undefined;\n return {\n diffPercentage: (meta?.diffPercentage as number) ?? 0,\n diffPixels: (meta?.diffPixels as number) ?? 0,\n totalPixels: (meta?.totalPixels as number) ?? 0,\n regions: (meta?.regions as DiffRegion[]) ?? [],\n };\n}\n\nexport const compareFormatter: OutputFormatter<CompareFormatData> = {\n terminal(data) {\n const { report } = data;\n const pm = getPixelMeta(report.analyses);\n const lines: string[] = [];\n lines.push('');\n lines.push(` Diff: ${pm.diffPercentage.toFixed(2)}% (${pm.diffPixels.toLocaleString()}/${pm.totalPixels.toLocaleString()} pixels)`);\n if (pm.regions.length > 0) lines.push(` Regions: ${pm.regions.length}`);\n lines.push(` Duration: ${report.durationMs}ms`);\n\n for (const a of report.analyses) {\n lines.push(` [${a.analysisName}] ${a.summary}`);\n }\n\n if (report.findings.length === 0) {\n lines.push('');\n lines.push(pc.green(' No differences found.'));\n lines.push('');\n lines.push(` Run: ${report.runId}`);\n lines.push('');\n return lines.join('\\n');\n }\n\n lines.push('');\n lines.push(' Findings');\n lines.push(' ' + '─'.repeat(70));\n\n for (const f of report.findings) {\n const tag = severityColor(f.severity, `[${f.severity.toUpperCase()}]`);\n const comp = f.component\n ? `${f.component.name}${f.component.testID ? ` [${f.component.testID}]` : ''}`\n : pc.dim('(unmatched)');\n const region = `(${f.region.x},${f.region.y} ${f.region.width}x${f.region.height})`;\n const conf = `(${confidenceLabel(f.confidence)})`;\n lines.push(` ${tag} ${f.id} ${comp} ${region} ${conf}`);\n }\n\n lines.push('');\n lines.push(` Summary: Found ${report.findings.length} differences (${severityCounts(report.findings)})`);\n lines.push('');\n lines.push(` Run: ${report.runId}`);\n lines.push('');\n return lines.join('\\n');\n },\n\n markdown(data) {\n const { report, device, artifactDir } = data;\n const pm = getPixelMeta(report.analyses);\n const lines: string[] = ['# Driftx Compare Report', ''];\n\n if (device) lines.push(`**Device:** ${device.name} (${device.platform})`);\n const meta = report.metadata;\n if (meta.gitCommit || meta.gitBranch) {\n const git = [meta.gitCommit, meta.gitBranch].filter(Boolean).join(' on ');\n lines.push(`**Git:** ${git}`);\n }\n if (meta.framework && meta.framework !== 'unknown') lines.push(`**Framework:** ${meta.framework}`);\n lines.push(`**Diff:** ${pm.diffPercentage.toFixed(2)}% (${pm.diffPixels.toLocaleString()} / ${pm.totalPixels.toLocaleString()} pixels)`);\n if (pm.regions.length > 0) lines.push(`**Regions:** ${pm.regions.length}`);\n lines.push(`**Duration:** ${report.durationMs}ms`);\n lines.push(`**Run ID:** ${report.runId}`);\n\n if (report.analyses.length > 0) {\n lines.push('', '## Analyses', '');\n for (const a of report.analyses) {\n lines.push(`- **${a.analysisName}** (${a.durationMs}ms): ${a.summary}`);\n }\n }\n\n if (report.findings.length === 0) {\n lines.push('', 'No differences found.');\n return lines.join('\\n');\n }\n\n lines.push('', '## Artifacts', '');\n lines.push(`- Screenshot: \\`${artifactDir}/screenshot.png\\``);\n lines.push(`- Design: \\`${artifactDir}/design.png\\``);\n lines.push(`- Diff mask: \\`${artifactDir}/diff-mask.png\\``);\n\n lines.push('', '## Findings');\n\n report.findings.forEach((f, i) => {\n const compName = f.component?.name ?? 'Unmatched region';\n lines.push('', `### ${i + 1}. [${f.severity.toUpperCase()}] ${compName} (${f.id})`, '');\n if (f.component) {\n lines.push(`- **Component:** ${f.component.name}`);\n if (f.component.testID) lines.push(`- **testID:** ${f.component.testID}`);\n }\n lines.push(`- **Category:** ${f.category}`);\n lines.push(`- **Region:** (${f.region.x}, ${f.region.y}) ${f.region.width}x${f.region.height}`);\n lines.push(`- **Confidence:** ${confidenceLabel(f.confidence)}`);\n if (f.evidence.length > 0) {\n lines.push('- **Evidence:**');\n for (const e of f.evidence) {\n lines.push(` - ${e.type}: ${Math.round(e.score * 100)}% score — \"${e.note}\"`);\n }\n }\n const regionId = pm.regions[i]?.id;\n if (regionId) lines.push(`- **Region crop:** \\`${artifactDir}/regions/${regionId}.png\\``);\n });\n\n if (data.tree && data.tree.length > 0) {\n lines.push('', '## Component Tree Context', '', '```');\n lines.push(formatTreePlain(data.tree));\n lines.push('```');\n }\n\n if (data.inspectHints && data.inspectHints.length > 0) {\n lines.push('', '## Hints', '');\n for (const hint of data.inspectHints) {\n lines.push(`- ${hint}`);\n }\n }\n\n return lines.join('\\n');\n },\n\n json(data) {\n return JSON.stringify({\n report: data.report,\n device: data.device,\n artifactDir: data.artifactDir,\n }, null, 2);\n },\n};\n","import sharp from 'sharp';\nimport { readFileSync } from 'node:fs';\nimport type { DriftxImage, AnalysisConfig } from './types.js';\n\nexport async function buildDriftxImage(filePath: string): Promise<DriftxImage> {\n const buffer = readFileSync(filePath);\n const image = sharp(buffer);\n const metadata = await image.metadata();\n const width = metadata.width!;\n const height = metadata.height!;\n const rawPixels = await image.raw().ensureAlpha().toBuffer();\n\n return {\n buffer,\n rawPixels,\n width,\n height,\n aspectRatio: width / height,\n path: filePath,\n };\n}\n\nexport function buildAnalysisConfig(\n configAnalyses: { default: string[]; disabled: string[]; options: Record<string, Record<string, unknown>> },\n withFlag?: string,\n withoutFlag?: string,\n): AnalysisConfig {\n const enabled = withFlag\n ? withFlag.split(',').map((s) => s.trim())\n : [...configAnalyses.default];\n\n const disabled = withoutFlag\n ? withoutFlag.split(',').map((s) => s.trim())\n : [...configAnalyses.disabled];\n\n return {\n enabled,\n disabled,\n options: configAnalyses.options,\n };\n}\n","import type { AnalysisPlugin } from './types.js';\n\nexport class AnalysisRegistry {\n private plugins = new Map<string, AnalysisPlugin>();\n\n register(plugin: AnalysisPlugin): void {\n if (this.plugins.has(plugin.name)) {\n throw new Error(`Analysis \"${plugin.name}\" already registered`);\n }\n this.plugins.set(plugin.name, plugin);\n }\n\n get(name: string): AnalysisPlugin | undefined {\n return this.plugins.get(name);\n }\n\n all(): AnalysisPlugin[] {\n return [...this.plugins.values()];\n }\n\n names(): string[] {\n return [...this.plugins.keys()];\n }\n}\n","import sharp from 'sharp';\nimport * as fs from 'node:fs';\n\nexport interface LoadedImage {\n buffer: Buffer;\n width: number;\n height: number;\n aspectRatio: number;\n rawPixels: Buffer;\n}\n\nexport async function loadImage(filePath: string): Promise<LoadedImage> {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Image not found: ${filePath}`);\n }\n\n const input = fs.readFileSync(filePath);\n const metadata = await sharp(input).metadata();\n\n if (!metadata.width || !metadata.height) {\n throw new Error(`Invalid image: could not read dimensions from ${filePath}`);\n }\n\n const rawPixels = await sharp(input)\n .ensureAlpha()\n .raw()\n .toBuffer();\n\n return {\n buffer: input,\n width: metadata.width,\n height: metadata.height,\n aspectRatio: metadata.width / metadata.height,\n rawPixels,\n };\n}\n","import sharp from 'sharp';\nimport type { LoadedImage } from './image-loader.js';\nimport { getLogger } from '../logger.js';\n\nexport interface AlignedImages {\n designPixels: Buffer;\n screenshotPixels: Buffer;\n width: number;\n height: number;\n aspectRatioWarning: boolean;\n}\n\nexport async function alignImages(design: LoadedImage, screenshot: LoadedImage): Promise<AlignedImages> {\n const targetWidth = screenshot.width;\n const targetHeight = screenshot.height;\n const logger = getLogger();\n\n const aspectDiff = Math.abs(design.aspectRatio - screenshot.aspectRatio) / screenshot.aspectRatio;\n const aspectRatioWarning = aspectDiff > 0.05;\n\n if (aspectRatioWarning) {\n logger.warn(\n `Aspect ratio divergence: design=${design.aspectRatio.toFixed(3)} screenshot=${screenshot.aspectRatio.toFixed(3)} (${(aspectDiff * 100).toFixed(1)}%)`,\n );\n }\n\n let designPixels: Buffer;\n if (design.width === targetWidth && design.height === targetHeight) {\n designPixels = design.rawPixels;\n } else {\n designPixels = await sharp(design.buffer)\n .resize(targetWidth, targetHeight, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })\n .ensureAlpha()\n .raw()\n .toBuffer();\n }\n\n return {\n designPixels,\n screenshotPixels: screenshot.rawPixels,\n width: targetWidth,\n height: targetHeight,\n aspectRatioWarning,\n };\n}\n","import pixelmatch from 'pixelmatch';\nimport type { AlignedImages } from './alignment.js';\n\nexport interface PixelDiffResult {\n diffPixels: number;\n totalPixels: number;\n diffPercentage: number;\n diffMask: Buffer;\n width: number;\n height: number;\n}\n\nexport function computePixelDiff(aligned: AlignedImages, threshold: number): PixelDiffResult {\n const { width, height, designPixels, screenshotPixels } = aligned;\n const totalPixels = width * height;\n const diffMask = Buffer.alloc(width * height * 4);\n\n const diffPixels = pixelmatch(\n designPixels, screenshotPixels, diffMask,\n width, height,\n { threshold, includeAA: false },\n );\n\n return {\n diffPixels,\n totalPixels,\n diffPercentage: totalPixels > 0 ? (diffPixels / totalPixels) * 100 : 0,\n diffMask,\n width,\n height,\n };\n}\n","import type { BoundingBox, DiffRegion } from '../types.js';\n\ninterface ExtractOptions {\n mergeGap: number;\n minArea: number;\n}\n\nfunction isDiffPixel(mask: Buffer, idx: number): boolean {\n return mask[idx] > 0 || mask[idx + 1] > 0 || mask[idx + 2] > 0;\n}\n\nfunction floodFill(\n mask: Buffer, visited: Uint8Array, width: number, height: number,\n startX: number, startY: number,\n): { bounds: BoundingBox; pixelCount: number } {\n const stack: Array<[number, number]> = [[startX, startY]];\n let minX = startX, maxX = startX, minY = startY, maxY = startY;\n let count = 0;\n\n while (stack.length > 0) {\n const [x, y] = stack.pop()!;\n const idx = y * width + x;\n\n if (x < 0 || x >= width || y < 0 || y >= height) continue;\n if (visited[idx]) continue;\n if (!isDiffPixel(mask, idx * 4)) continue;\n\n visited[idx] = 1;\n count++;\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n\n stack.push([x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]);\n }\n\n return {\n bounds: { x: minX, y: minY, width: maxX - minX + 1, height: maxY - minY + 1 },\n pixelCount: count,\n };\n}\n\nfunction shouldMerge(a: BoundingBox, b: BoundingBox, gap: number): boolean {\n const aRight = a.x + a.width + gap;\n const aBottom = a.y + a.height + gap;\n const bRight = b.x + b.width + gap;\n const bBottom = b.y + b.height + gap;\n\n return !(a.x - gap > bRight || b.x - gap > aRight || a.y - gap > bBottom || b.y - gap > aBottom);\n}\n\nfunction mergeBounds(a: BoundingBox, b: BoundingBox): BoundingBox {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return {\n x, y,\n width: Math.max(a.x + a.width, b.x + b.width) - x,\n height: Math.max(a.y + a.height, b.y + b.height) - y,\n };\n}\n\nexport function extractRegions(\n diffMask: Buffer, width: number, height: number,\n options: ExtractOptions,\n): DiffRegion[] {\n const visited = new Uint8Array(width * height);\n let rawRegions: Array<{ bounds: BoundingBox; pixelCount: number }> = [];\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const idx = y * width + x;\n if (visited[idx] || !isDiffPixel(diffMask, idx * 4)) continue;\n rawRegions.push(floodFill(diffMask, visited, width, height, x, y));\n }\n }\n\n let merged = true;\n while (merged) {\n merged = false;\n const next: typeof rawRegions = [];\n const used = new Set<number>();\n\n for (let i = 0; i < rawRegions.length; i++) {\n if (used.has(i)) continue;\n let current = rawRegions[i];\n\n for (let j = i + 1; j < rawRegions.length; j++) {\n if (used.has(j)) continue;\n if (shouldMerge(current.bounds, rawRegions[j].bounds, options.mergeGap)) {\n current = {\n bounds: mergeBounds(current.bounds, rawRegions[j].bounds),\n pixelCount: current.pixelCount + rawRegions[j].pixelCount,\n };\n used.add(j);\n merged = true;\n }\n }\n\n next.push(current);\n }\n\n rawRegions = next;\n }\n\n const totalPixels = width * height;\n return rawRegions\n .filter((r) => r.bounds.width * r.bounds.height >= options.minArea)\n .map((r, i) => ({\n id: `region-${i}`,\n bounds: r.bounds,\n pixelCount: r.pixelCount,\n percentage: totalPixels > 0 ? (r.pixelCount / totalPixels) * 100 : 0,\n }));\n}\n","import type { DiffRegion, IgnoreRule, BoundingBox, ColorRange } from '../types.js';\n\nexport interface PixelContext {\n screenshotPixels: Buffer;\n width: number;\n height: number;\n}\n\nfunction boxesOverlap(a: BoundingBox, b: BoundingBox): boolean {\n return !(\n a.x + a.width <= b.x ||\n b.x + b.width <= a.x ||\n a.y + a.height <= b.y ||\n b.y + b.height <= a.y\n );\n}\n\nfunction regionMatchesColorRange(\n region: DiffRegion,\n range: ColorRange,\n ctx: PixelContext,\n): boolean {\n const { bounds } = region;\n const endX = Math.min(bounds.x + bounds.width, ctx.width);\n const endY = Math.min(bounds.y + bounds.height, ctx.height);\n\n for (let y = bounds.y; y < endY; y++) {\n for (let x = bounds.x; x < endX; x++) {\n const idx = (y * ctx.width + x) * 4;\n const r = ctx.screenshotPixels[idx];\n const g = ctx.screenshotPixels[idx + 1];\n const b = ctx.screenshotPixels[idx + 2];\n\n if (r < range.r[0] || r > range.r[1]) return false;\n if (g < range.g[0] || g > range.g[1]) return false;\n if (b < range.b[0] || b > range.b[1]) return false;\n }\n }\n return true;\n}\n\nfunction isIgnored(region: DiffRegion, rule: IgnoreRule, ctx?: PixelContext): boolean {\n switch (rule.type) {\n case 'boundingBox':\n return boxesOverlap(region.bounds, rule.value as BoundingBox);\n case 'colorRange':\n if (!ctx) return false;\n return regionMatchesColorRange(region, rule.value as ColorRange, ctx);\n default:\n return false;\n }\n}\n\nexport function filterByIgnoreRules(\n regions: DiffRegion[],\n rules: IgnoreRule[],\n pixelContext?: PixelContext,\n): DiffRegion[] {\n if (rules.length === 0) return regions;\n return regions.filter((region) => !rules.some((rule) => isIgnored(region, rule, pixelContext)));\n}\n","import sharp from 'sharp';\n\nexport interface MaskColor {\n r: number;\n g: number;\n b: number;\n a: number;\n}\n\nexport async function generateDiffMask(\n screenshotBuffer: Buffer,\n diffMask: Buffer,\n width: number,\n height: number,\n color: MaskColor,\n): Promise<Buffer> {\n const overlay = Buffer.alloc(width * height * 4);\n const alpha = Math.round(color.a * 255);\n\n for (let i = 0; i < width * height; i++) {\n const idx = i * 4;\n const hasDiff = diffMask[idx] > 0 || diffMask[idx + 1] > 0 || diffMask[idx + 2] > 0;\n\n if (hasDiff) {\n overlay[idx] = color.r;\n overlay[idx + 1] = color.g;\n overlay[idx + 2] = color.b;\n overlay[idx + 3] = alpha;\n } else {\n overlay[idx + 3] = 0;\n }\n }\n\n const overlayPng = await sharp(overlay, { raw: { width, height, channels: 4 } })\n .png()\n .toBuffer();\n\n return sharp(screenshotBuffer)\n .composite([{ input: overlayPng, blend: 'over' }])\n .png()\n .toBuffer();\n}\n","import sharp from 'sharp';\n\nexport interface ViewportOptions {\n platform: 'android' | 'ios';\n cropStatusBar: boolean;\n statusBarHeight: { android: number; ios: number };\n cropNavigationBar: boolean;\n}\n\nexport interface CroppedResult {\n buffer: Buffer;\n width: number;\n height: number;\n}\n\nexport async function cropViewport(imageBuffer: Buffer, options: ViewportOptions): Promise<CroppedResult> {\n const metadata = await sharp(imageBuffer).metadata();\n const width = metadata.width!;\n let height = metadata.height!;\n let top = 0;\n\n if (options.cropStatusBar) {\n const barHeight = options.platform === 'android'\n ? options.statusBarHeight.android\n : options.statusBarHeight.ios;\n top = barHeight;\n height -= barHeight;\n }\n\n if (top === 0 && height === metadata.height) {\n return { buffer: imageBuffer, width, height };\n }\n\n const buffer = await sharp(imageBuffer)\n .extract({ left: 0, top, width, height })\n .png()\n .toBuffer();\n\n return { buffer, width, height };\n}\n","import type { DiffRegion, IgnoreRule } from '../types.js';\nimport { loadImage } from './image-loader.js';\nimport { alignImages } from './alignment.js';\nimport { computePixelDiff } from './pixel-diff.js';\nimport { extractRegions } from './region-extractor.js';\nimport { filterByIgnoreRules } from './ignore-rules.js';\nimport { generateDiffMask, type MaskColor } from './mask-generator.js';\nimport { cropViewport, type ViewportOptions } from './viewport.js';\nimport sharp from 'sharp';\n\nexport interface CompareOptions {\n threshold: number;\n diffThreshold: number;\n regionMergeGap: number;\n regionMinArea: number;\n ignoreRules: IgnoreRule[];\n diffMaskColor: MaskColor;\n platform: 'android' | 'ios';\n viewport?: Omit<ViewportOptions, 'platform'>;\n}\n\nexport interface CompareResult {\n totalPixels: number;\n diffPixels: number;\n diffPercentage: number;\n regions: DiffRegion[];\n diffMaskBuffer: Buffer;\n regionCrops: Array<{ id: string; buffer: Buffer }>;\n width: number;\n height: number;\n durationMs: number;\n}\n\nfunction sanitizeDiffMask(mask: Buffer, width: number, height: number): Buffer {\n const clean = Buffer.alloc(width * height * 4);\n for (let i = 0; i < width * height; i++) {\n const idx = i * 4;\n const r = mask[idx];\n const g = mask[idx + 1];\n const b = mask[idx + 2];\n if (r > 0 && g === 0 && b === 0) {\n clean[idx] = r;\n clean[idx + 1] = g;\n clean[idx + 2] = b;\n clean[idx + 3] = mask[idx + 3];\n }\n }\n return clean;\n}\n\nexport async function runComparison(\n designPath: string,\n screenshotPath: string,\n options: CompareOptions,\n): Promise<CompareResult> {\n const start = Date.now();\n\n let design = await loadImage(designPath);\n let screenshot = await loadImage(screenshotPath);\n\n if (options.viewport) {\n const vpOpts: ViewportOptions = { ...options.viewport, platform: options.platform };\n const croppedDesign = await cropViewport(design.buffer, vpOpts);\n const croppedScreenshot = await cropViewport(screenshot.buffer, vpOpts);\n\n design = {\n buffer: croppedDesign.buffer,\n width: croppedDesign.width,\n height: croppedDesign.height,\n aspectRatio: croppedDesign.width / croppedDesign.height,\n rawPixels: await sharp(croppedDesign.buffer).ensureAlpha().raw().toBuffer(),\n };\n screenshot = {\n buffer: croppedScreenshot.buffer,\n width: croppedScreenshot.width,\n height: croppedScreenshot.height,\n aspectRatio: croppedScreenshot.width / croppedScreenshot.height,\n rawPixels: await sharp(croppedScreenshot.buffer).ensureAlpha().raw().toBuffer(),\n };\n }\n\n const aligned = await alignImages(design, screenshot);\n const diff = computePixelDiff(aligned, options.threshold);\n\n const cleanMask = sanitizeDiffMask(diff.diffMask, diff.width, diff.height);\n\n let regions = extractRegions(cleanMask, diff.width, diff.height, {\n mergeGap: options.regionMergeGap,\n minArea: options.regionMinArea,\n });\n\n regions = filterByIgnoreRules(regions, options.ignoreRules);\n\n const diffMaskBuffer = await generateDiffMask(\n screenshot.buffer, cleanMask, diff.width, diff.height, options.diffMaskColor,\n );\n\n const regionCrops = await Promise.all(\n regions.map(async (r) => {\n const crop = await sharp(screenshot.buffer)\n .extract({\n left: r.bounds.x,\n top: r.bounds.y,\n width: Math.min(r.bounds.width, diff.width - r.bounds.x),\n height: Math.min(r.bounds.height, diff.height - r.bounds.y),\n })\n .png()\n .toBuffer();\n return { id: r.id, buffer: crop };\n }),\n );\n\n return {\n totalPixels: diff.totalPixels,\n diffPixels: diff.diffPixels,\n diffPercentage: diff.diffPercentage,\n regions,\n diffMaskBuffer,\n regionCrops,\n width: diff.width,\n height: diff.height,\n durationMs: Date.now() - start,\n };\n}\n","import type { DiffRegion, ComponentNode, ComponentMatch, BoundingBox } from '../types.js';\n\nexport interface RegionComponentMatch {\n regionId: string;\n component: ComponentMatch;\n confidence: number;\n overlapRatio: number;\n}\n\nfunction boxesOverlap(a: BoundingBox, b: BoundingBox): boolean {\n return !(\n a.x + a.width <= b.x ||\n b.x + b.width <= a.x ||\n a.y + a.height <= b.y ||\n b.y + b.height <= a.y\n );\n}\n\nfunction overlapArea(a: BoundingBox, b: BoundingBox): number {\n const x1 = Math.max(a.x, b.x);\n const y1 = Math.max(a.y, b.y);\n const x2 = Math.min(a.x + a.width, b.x + b.width);\n const y2 = Math.min(a.y + a.height, b.y + b.height);\n if (x2 <= x1 || y2 <= y1) return 0;\n return (x2 - x1) * (y2 - y1);\n}\n\ninterface CandidateMatch {\n node: ComponentNode;\n depth: number;\n overlapRatio: number;\n}\n\nfunction findDeepestOverlap(\n nodes: ComponentNode[],\n regionBounds: BoundingBox,\n depth: number,\n): CandidateMatch | null {\n let best: CandidateMatch | null = null;\n const regionArea = regionBounds.width * regionBounds.height;\n\n for (const node of nodes) {\n if (!boxesOverlap(node.bounds, regionBounds)) continue;\n\n const overlap = overlapArea(node.bounds, regionBounds);\n const ratio = regionArea > 0 ? overlap / regionArea : 0;\n\n if (ratio > 0.5) {\n const childMatch = findDeepestOverlap(node.children, regionBounds, depth + 1);\n if (childMatch && childMatch.overlapRatio > 0.5) {\n if (!best || childMatch.depth > best.depth) {\n best = childMatch;\n }\n } else {\n if (!best || depth > best.depth || (depth === best.depth && ratio > best.overlapRatio)) {\n best = { node, depth, overlapRatio: ratio };\n }\n }\n }\n }\n\n return best;\n}\n\nfunction computeConfidence(node: ComponentNode, overlapRatio: number): number {\n let base: number;\n if (node.inspectionTier === 'detailed') {\n base = 0.6;\n if (node.source) base = 0.8;\n } else {\n base = 0.4;\n }\n const overlapBonus = Math.min(overlapRatio * 0.2, 0.2);\n return Math.min(base + overlapBonus, node.inspectionTier === 'detailed' ? 0.95 : 0.6);\n}\n\nexport function matchRegionsToComponents(\n regions: DiffRegion[],\n tree: ComponentNode[],\n): RegionComponentMatch[] {\n const matches: RegionComponentMatch[] = [];\n\n for (const region of regions) {\n const candidate = findDeepestOverlap(tree, region.bounds, 0);\n if (!candidate) continue;\n\n const { node, depth, overlapRatio } = candidate;\n const confidence = computeConfidence(node, overlapRatio);\n\n matches.push({\n regionId: region.id,\n component: {\n name: node.reactName ?? node.name,\n testID: node.testID,\n source: node.source,\n bounds: node.bounds,\n depth,\n },\n confidence,\n overlapRatio,\n });\n }\n\n return matches;\n}\n","import type { DiffRegion, DiffFinding, DiffEvidence } from '../types.js';\nimport type { RegionComponentMatch } from './component-matcher.js';\n\nfunction classifySeverity(pixelPercentage: number): DiffFinding['severity'] {\n if (pixelPercentage >= 10) return 'critical';\n if (pixelPercentage >= 3) return 'major';\n if (pixelPercentage >= 0.5) return 'minor';\n return 'info';\n}\n\nexport function generateFindings(\n regions: DiffRegion[],\n matches: RegionComponentMatch[],\n totalPixels: number,\n): DiffFinding[] {\n const matchMap = new Map(matches.map((m) => [m.regionId, m]));\n\n return regions.map((region, i) => {\n const match = matchMap.get(region.id);\n const pixelPct = totalPixels > 0 ? (region.pixelCount / totalPixels) * 100 : 0;\n\n const evidence: DiffEvidence[] = [\n { type: 'pixel', score: pixelPct / 100, note: `${pixelPct.toFixed(1)}% pixel difference in region` },\n ];\n\n if (match) {\n evidence.push({\n type: 'tree',\n score: match.confidence,\n note: `Matched to ${match.component.name} via bounds overlap (${Math.round(match.overlapRatio * 100)}%)`,\n });\n }\n\n return {\n id: `diff-${i}`,\n category: 'unknown' as const,\n severity: classifySeverity(pixelPct),\n confidence: match?.confidence ?? 0.3,\n region: region.bounds,\n component: match?.component,\n evidence,\n };\n });\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext } from '../types.js';\nimport { runComparison } from '../../diff/compare.js';\nimport { matchRegionsToComponents } from '../../inspect/component-matcher.js';\nimport { generateFindings } from '../../inspect/finding-generator.js';\n\nexport class PixelAnalysis implements AnalysisPlugin {\n name = 'pixel';\n description = 'Pixel-level image comparison between screenshot and design';\n\n isAvailable(ctx: CompareContext): boolean {\n return !!ctx.design;\n }\n\n async run(ctx: CompareContext): Promise<AnalysisResult> {\n const start = Date.now();\n const { config } = ctx;\n const [mr, mg, mb, ma] = config.diffMaskColor;\n\n const compareResult = await runComparison(ctx.design!.path, ctx.screenshot.path, {\n threshold: config.threshold,\n diffThreshold: config.diffThreshold,\n regionMergeGap: config.regionMergeGap,\n regionMinArea: config.regionMinArea,\n ignoreRules: config.ignoreRules,\n diffMaskColor: { r: mr, g: mg, b: mb, a: ma / 255 },\n platform: config.platform,\n });\n\n await ctx.store.writeArtifact(ctx.runId, 'diff-mask.png', compareResult.diffMaskBuffer);\n for (const crop of compareResult.regionCrops) {\n await ctx.store.writeArtifact(ctx.runId, `regions/${crop.id}.png`, crop.buffer);\n }\n\n const matches = ctx.tree?.length\n ? matchRegionsToComponents(compareResult.regions, ctx.tree)\n : [];\n const findings = generateFindings(\n compareResult.regions,\n matches,\n compareResult.totalPixels,\n );\n\n const passed = compareResult.diffPercentage <= config.diffThreshold;\n\n return {\n analysisName: this.name,\n findings,\n summary: passed\n ? `Pixel diff: ${compareResult.diffPercentage.toFixed(3)}% (pass)`\n : `Pixel diff: ${compareResult.diffPercentage.toFixed(3)}% — ${compareResult.regions.length} regions (fail)`,\n metadata: {\n totalPixels: compareResult.totalPixels,\n diffPixels: compareResult.diffPixels,\n diffPercentage: compareResult.diffPercentage,\n regions: compareResult.regions,\n durationMs: compareResult.durationMs,\n passed,\n },\n durationMs: Date.now() - start,\n };\n }\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext } from '../types.js';\nimport type { ComponentNode, DiffFinding } from '../../types.js';\n\nconst INTERACTIVE_NAMES = new Set([\n 'Pressable',\n 'TouchableOpacity',\n 'Button',\n 'TouchableHighlight',\n 'TouchableWithoutFeedback',\n]);\n\nfunction isInteractive(name: string): boolean {\n if (INTERACTIVE_NAMES.has(name)) return true;\n return name.includes('Button') || name.includes('Pressable');\n}\n\nfunction collectNodes(nodes: ComponentNode[]): ComponentNode[] {\n const result: ComponentNode[] = [];\n const stack = [...nodes];\n while (stack.length > 0) {\n const node = stack.pop()!;\n result.push(node);\n for (const child of node.children) {\n stack.push(child);\n }\n }\n return result;\n}\n\nexport class AccessibilityAnalysis implements AnalysisPlugin {\n name = 'a11y';\n description = 'Accessibility audit of component tree';\n\n isAvailable(ctx: CompareContext): boolean {\n return !!ctx.tree?.length;\n }\n\n async run(ctx: CompareContext): Promise<AnalysisResult> {\n const start = Date.now();\n const nodes = collectNodes(ctx.tree ?? []);\n const platform = ctx.config.platform;\n const tapThreshold = platform === 'ios' ? 44 : 48;\n\n const findings: DiffFinding[] = [];\n let labelCount = 0;\n let tapTargetCount = 0;\n let imageCount = 0;\n let emptyTextCount = 0;\n\n for (const node of nodes) {\n if (isInteractive(node.name) && !node.testID) {\n const styles = node.styles ?? {};\n const hasLabel =\n 'accessibilityLabel' in styles ||\n 'aria-label' in styles;\n\n if (!hasLabel) {\n findings.push({\n id: `a11y-label-${labelCount++}`,\n category: 'accessibility',\n severity: 'major',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Interactive component \"${node.name}\" is missing an accessibilityLabel` }],\n description: `Interactive component \"${node.name}\" is missing an accessibilityLabel`,\n });\n }\n }\n\n if (node.bounds.width > 0 && node.bounds.height > 0) {\n if (node.bounds.width < tapThreshold || node.bounds.height < tapThreshold) {\n if (isInteractive(node.name)) {\n findings.push({\n id: `a11y-tap-${tapTargetCount++}`,\n category: 'accessibility',\n severity: 'minor',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Tap target \"${node.name}\" is ${node.bounds.width}x${node.bounds.height}, smaller than ${tapThreshold}x${tapThreshold}` }],\n description: `Tap target \"${node.name}\" is ${node.bounds.width}x${node.bounds.height}, smaller than the recommended ${tapThreshold}x${tapThreshold}`,\n });\n }\n }\n }\n\n if (node.name.includes('Image')) {\n const styles = node.styles ?? {};\n const hasAlt =\n 'accessibilityLabel' in styles ||\n 'aria-label' in styles ||\n 'alt' in styles;\n\n if (!hasAlt) {\n findings.push({\n id: `a11y-image-${imageCount++}`,\n category: 'accessibility',\n severity: 'major',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Image component \"${node.name}\" is missing an accessibilityLabel or alt text` }],\n description: `Image component \"${node.name}\" is missing an accessibilityLabel or alt text`,\n });\n }\n }\n\n if (node.text === '') {\n findings.push({\n id: `a11y-empty-${emptyTextCount++}`,\n category: 'accessibility',\n severity: 'info',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Component \"${node.name}\" has an empty text node` }],\n description: `Component \"${node.name}\" has an empty text node`,\n });\n }\n }\n\n const totalIssues = findings.length;\n const summary = totalIssues === 0 ? 'No accessibility issues' : `${totalIssues} accessibility issue${totalIssues === 1 ? '' : 's'} found`;\n\n return {\n analysisName: this.name,\n findings,\n summary,\n metadata: {\n totalChecked: nodes.length,\n issuesByType: {\n label: labelCount,\n tapTarget: tapTargetCount,\n image: imageCount,\n emptyText: emptyTextCount,\n },\n },\n durationMs: Date.now() - start,\n };\n }\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext } from '../types.js';\nimport { runComparison } from '../../diff/compare.js';\n\nexport class RegressionAnalysis implements AnalysisPlugin {\n name = 'regression';\n description = 'Layout regression detection against previous baseline';\n\n isAvailable(ctx: CompareContext): boolean {\n return !!ctx.baseline;\n }\n\n async run(ctx: CompareContext): Promise<AnalysisResult> {\n const start = Date.now();\n const { config } = ctx;\n const [mr, mg, mb, ma] = config.diffMaskColor;\n\n const compareResult = await runComparison(ctx.baseline!.path, ctx.screenshot.path, {\n threshold: config.threshold,\n diffThreshold: config.diffThreshold,\n regionMergeGap: config.regionMergeGap,\n regionMinArea: config.regionMinArea,\n ignoreRules: config.ignoreRules,\n diffMaskColor: { r: mr, g: mg, b: mb, a: ma / 255 },\n platform: config.platform,\n });\n\n await ctx.store.writeArtifact(ctx.runId, 'regression-diff-mask.png', compareResult.diffMaskBuffer);\n for (const crop of compareResult.regionCrops) {\n await ctx.store.writeArtifact(ctx.runId, `regression-regions/${crop.id}.png`, crop.buffer);\n }\n\n const regressionThreshold = ctx.analysisConfig.options['regression']?.regressionThreshold as number | undefined;\n const passed = compareResult.diffPercentage <= (regressionThreshold ?? config.diffThreshold);\n\n const findings = compareResult.regions.map((region, index) => ({\n id: `regression-${index}`,\n category: 'regression' as const,\n severity: 'major' as const,\n confidence: 1.0,\n region: region.bounds,\n component: { name: 'region', bounds: region.bounds, depth: 0 },\n evidence: [{ type: 'regression' as const, score: region.percentage / 100, note: `${region.percentage.toFixed(3)}% changed` }],\n description: `Region ${region.id}: ${region.percentage.toFixed(3)}% changed (${region.pixelCount}px)`,\n }));\n\n return {\n analysisName: this.name,\n findings,\n summary: passed\n ? 'Regression: no changes detected'\n : `Regression: ${compareResult.diffPercentage.toFixed(3)}% changed, ${compareResult.regions.length} regions`,\n metadata: {\n totalPixels: compareResult.totalPixels,\n diffPixels: compareResult.diffPixels,\n diffPercentage: compareResult.diffPercentage,\n regions: compareResult.regions,\n passed,\n },\n durationMs: Date.now() - start,\n };\n }\n}\n","import { AnalysisRegistry } from './registry.js';\nimport { PixelAnalysis } from './plugins/pixel.js';\nimport { AccessibilityAnalysis } from './plugins/a11y.js';\nimport { RegressionAnalysis } from './plugins/regression.js';\n\nexport function createDefaultRegistry(): AnalysisRegistry {\n const registry = new AnalysisRegistry();\n registry.register(new PixelAnalysis());\n registry.register(new AccessibilityAnalysis());\n registry.register(new RegressionAnalysis());\n return registry;\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext, CompareReport } from './types.js';\nimport type { AnalysisRegistry } from './registry.js';\nimport type { RunMetadata } from '../types.js';\n\nexport class AnalysisOrchestrator {\n constructor(private registry: AnalysisRegistry) {}\n\n async run(ctx: CompareContext): Promise<CompareReport> {\n const start = Date.now();\n const plugins = this.selectPlugins(ctx);\n\n const settled = await Promise.allSettled(\n plugins.map((plugin) => plugin.run(ctx)),\n );\n\n const analyses: AnalysisResult[] = settled.map((result, i) => {\n if (result.status === 'fulfilled') return result.value;\n return {\n analysisName: plugins[i].name,\n findings: [],\n summary: `Error: ${result.reason?.message ?? 'unknown error'}`,\n metadata: {},\n durationMs: 0,\n error: result.reason?.message ?? 'unknown error',\n };\n });\n\n const findings = analyses.flatMap((a) => a.findings);\n const summaries = analyses.map((a) => a.summary).join('; ');\n const durationMs = Date.now() - start;\n\n return {\n runId: ctx.runId,\n analyses,\n findings,\n summary: summaries,\n metadata: {} as RunMetadata,\n durationMs,\n };\n }\n\n private selectPlugins(ctx: CompareContext): AnalysisPlugin[] {\n let plugins = this.registry.all();\n const { enabled, disabled } = ctx.analysisConfig;\n\n if (enabled.length > 0) {\n plugins = plugins.filter((p) => enabled.includes(p.name));\n }\n\n if (disabled.length > 0) {\n plugins = plugins.filter((p) => !disabled.includes(p.name));\n }\n\n return plugins.filter((p) => p.isAvailable(ctx));\n }\n}\n","import type { Shell, RunMetadata, DeviceInfo, InspectionCapabilities } from '../types.js';\nimport type { DriftxConfig } from '../config.js';\nimport type { CompareFormatData } from '../formatters/types.js';\nimport type { InspectResult } from '../inspect/tree-inspector.js';\nimport type { CompareReport } from '../analyses/types.js';\nimport { DeviceDiscovery } from '../devices/discovery.js';\nimport { captureScreenshot } from '../capture/capture.js';\nimport { TreeInspector } from '../inspect/tree-inspector.js';\nimport { RunStore } from '../run-store.js';\nimport { ExitCode } from '../exit-codes.js';\nimport { compareFormatter } from '../formatters/compare.js';\nimport { pickDevice } from './device-picker.js';\nimport { buildDriftxImage, buildAnalysisConfig } from '../analyses/context.js';\nimport { createDefaultRegistry } from '../analyses/default-registry.js';\nimport { AnalysisOrchestrator } from '../analyses/orchestrator.js';\nimport * as fs from 'node:fs';\n\nexport interface CompareCommandOptions {\n design?: string;\n device?: string;\n threshold?: number;\n screenshot?: string;\n with?: string;\n without?: string;\n baseline?: boolean;\n}\n\nexport async function runCompare(\n shell: Shell,\n config: DriftxConfig,\n options: CompareCommandOptions,\n): Promise<{ report: CompareReport; exitCode: number; formatData: CompareFormatData }> {\n const store = new RunStore(process.cwd());\n const run = store.createRun();\n\n let screenshotPath: string;\n let deviceId = 'unknown';\n let platform = config.platform;\n let deviceInfo: DeviceInfo | undefined;\n\n if (options.screenshot) {\n screenshotPath = options.screenshot;\n } else {\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n\n let device;\n if (options.device) {\n device = booted.find((d) => d.id === options.device || d.name === options.device);\n if (!device) throw new Error(`Device not found: ${options.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n deviceId = device.id;\n platform = device.platform;\n deviceInfo = device;\n\n const buffer = await captureScreenshot(shell, device, {\n settleCheck: config.settleCheckEnabled,\n settleMaxDelta: config.settleMaxDelta,\n settleDelayMs: config.settleTimeMs,\n });\n screenshotPath = store.getRunPath(run.runId, 'screenshot.png');\n await store.writeArtifact(run.runId, 'screenshot.png', buffer);\n }\n\n const screenshotImage = await buildDriftxImage(screenshotPath);\n\n let designImage;\n if (options.design) {\n const designBuffer = fs.readFileSync(options.design);\n await store.writeArtifact(run.runId, 'design.png', designBuffer);\n designImage = await buildDriftxImage(options.design);\n }\n\n let baselineImage;\n if (options.baseline) {\n const latestRunId = store.getLatestRun();\n if (latestRunId) {\n const baselinePath = store.getRunPath(latestRunId, 'screenshot.png');\n if (fs.existsSync(baselinePath)) {\n baselineImage = await buildDriftxImage(baselinePath);\n }\n }\n }\n\n let inspectResult: InspectResult | undefined;\n let inspectionCapabilities: InspectionCapabilities = {\n tree: 'none', sourceMapping: 'none', styles: 'none', protocol: 'none',\n };\n\n if (deviceInfo) {\n const inspector = new TreeInspector(shell, process.cwd());\n inspectResult = await inspector.inspect(deviceInfo, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n inspectionCapabilities = inspectResult.capabilities;\n }\n\n const analysisConfig = buildAnalysisConfig(config.analyses, options.with, options.without);\n\n const ctx = {\n screenshot: screenshotImage,\n design: designImage,\n baseline: baselineImage,\n tree: inspectResult?.tree,\n device: deviceInfo,\n config,\n analysisConfig,\n runId: run.runId,\n store,\n };\n\n const registry = createDefaultRegistry();\n const orchestrator = new AnalysisOrchestrator(registry);\n const report = await orchestrator.run(ctx);\n\n const startedAt = new Date().toISOString();\n const metadata: RunMetadata = {\n runId: run.runId,\n startedAt,\n completedAt: new Date().toISOString(),\n projectRoot: process.cwd(),\n deviceId,\n platform,\n orientation: 'portrait',\n framework: 'unknown',\n driftxVersion: '0.1.0',\n configHash: '',\n };\n report.metadata = metadata;\n await store.writeMetadata(run.runId, metadata as unknown as Record<string, unknown>);\n\n const resultJson = JSON.stringify(report, null, 2);\n await store.writeArtifact(run.runId, 'result.json', Buffer.from(resultJson));\n\n const anyFailed = report.analyses.some((a) => {\n const meta = a.metadata as Record<string, unknown>;\n return meta.passed === false;\n });\n const exitCode = anyFailed ? ExitCode.DiffFound : ExitCode.Success;\n\n const formatData: CompareFormatData = {\n report,\n device: deviceInfo ? { name: deviceInfo.name, platform: deviceInfo.platform } : undefined,\n artifactDir: store.getRunPath(run.runId),\n tree: inspectResult?.tree,\n inspectHints: inspectResult?.hints,\n };\n\n const reportMarkdown = compareFormatter.markdown(formatData);\n await store.writeArtifact(run.runId, 'report.md', Buffer.from(reportMarkdown));\n\n return { report, exitCode, formatData };\n}\n","import { exec } from 'node:child_process';\nimport { getLogger } from '../logger.js';\n\nexport function getClipboardCommand(platform: string): string | undefined {\n if (platform === 'darwin') return 'pbcopy';\n if (platform === 'win32') return 'clip';\n if (platform === 'linux') return 'xclip -selection clipboard';\n return undefined;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n const logger = getLogger();\n const cmd = getClipboardCommand(process.platform);\n\n if (!cmd) {\n logger.debug(`Clipboard not supported on ${process.platform}`);\n return;\n }\n\n return new Promise((resolve) => {\n const proc = exec(cmd, (err) => {\n if (err) {\n logger.debug(`Clipboard copy failed: ${err.message}`);\n }\n resolve();\n });\n proc.stdin?.write(text);\n proc.stdin?.end();\n });\n}\n","import type { OutputFormatter, FormatterContext } from './types.js';\nimport { copyToClipboard } from './clipboard.js';\n\nexport async function formatOutput<T>(\n formatter: OutputFormatter<T>,\n data: T,\n ctx: FormatterContext,\n): Promise<string> {\n const output = formatter[ctx.format](data);\n\n if (!ctx.quiet) {\n console.log(output);\n }\n\n if (ctx.copy) {\n const clipboardContent = ctx.format === 'terminal'\n ? formatter.markdown(data)\n : output;\n await copyToClipboard(clipboardContent);\n }\n\n return output;\n}\n","import pc from 'picocolors';\nimport type { DeviceInfo } from '../types.js';\nimport type { OutputFormatter } from './types.js';\n\nfunction stateLabel(state: DeviceInfo['state']): string {\n if (state === 'booted') return pc.green('● booted');\n if (state === 'offline') return pc.yellow('○ offline');\n return pc.red('✗ unauthorized');\n}\n\nfunction stateText(state: DeviceInfo['state']): string {\n if (state === 'booted') return 'booted';\n if (state === 'offline') return 'offline';\n return 'unauthorized';\n}\n\nexport const devicesFormatter: OutputFormatter<DeviceInfo[]> = {\n terminal(devices) {\n if (devices.length === 0) {\n return 'No devices found. Start an emulator or connect a device.';\n }\n const lines: string[] = [];\n const header = ` ${'ID'.padEnd(20)} ${'Name'.padEnd(20)} ${'Platform'.padEnd(10)} ${'OS'.padEnd(10)} ${'State'}`;\n lines.push('');\n lines.push(header);\n lines.push(' ' + '-'.repeat(70));\n for (const d of devices) {\n lines.push(` ${d.id.padEnd(20)} ${d.name.padEnd(20)} ${d.platform.padEnd(10)} ${(d.osVersion || '-').padEnd(10)} ${stateLabel(d.state)}`);\n }\n lines.push('');\n return lines.join('\\n');\n },\n\n markdown(devices) {\n if (devices.length === 0) {\n return '# Driftx Devices\\n\\nNo devices found. Start an emulator or connect a device.';\n }\n const lines: string[] = ['# Driftx Devices', '', '| ID | Name | Platform | OS | State |', '|----|------|----------|-----|-------|'];\n for (const d of devices) {\n lines.push(`| ${d.id} | ${d.name} | ${d.platform} | ${d.osVersion || '-'} | ${stateText(d.state)} |`);\n }\n return lines.join('\\n');\n },\n\n json(devices) {\n return JSON.stringify(devices, null, 2);\n },\n};\n","import pc from 'picocolors';\nimport type { PrerequisiteCheck } from '../types.js';\nimport type { OutputFormatter } from './types.js';\n\nexport const doctorFormatter: OutputFormatter<PrerequisiteCheck[]> = {\n terminal(checks) {\n const lines: string[] = [];\n lines.push('Prerequisite Check');\n lines.push('─'.repeat(60));\n for (const check of checks) {\n const icon = check.available ? pc.green('+') : pc.red('-');\n const status = check.available ? 'ok' : pc.red('missing');\n const version = check.version ?? '';\n const required = check.required ? 'required' : 'optional';\n lines.push(` [${icon}] ${check.name.padEnd(12)} ${String(status).padEnd(10)} ${version.padEnd(16)} (${required})`);\n if (!check.available && check.fix) {\n lines.push(` Fix: ${check.fix}`);\n }\n }\n lines.push('─'.repeat(60));\n return lines.join('\\n');\n },\n\n markdown(checks) {\n const lines: string[] = ['# Driftx Doctor', '', '| Tool | Status | Version | Required | Fix |', '|------|--------|---------|----------|-----|'];\n for (const check of checks) {\n const status = check.available ? 'available' : 'unavailable';\n const version = check.version || '—';\n const required = check.required ? 'yes' : 'no';\n const fix = check.fix || '—';\n lines.push(`| ${check.name} | ${status} | ${version} | ${required} | ${fix} |`);\n }\n return lines.join('\\n');\n },\n\n json(checks) {\n return JSON.stringify(checks, null, 2);\n },\n};\n","import pc from 'picocolors';\nimport type { ComponentNode, InspectionCapabilities } from '../types.js';\nimport type { InspectResult } from '../inspect/tree-inspector.js';\nimport type { OutputFormatter } from './types.js';\n\nconst STRATEGY_LABELS: Record<string, string> = {\n cdp: 'CDP via Metro (React DevTools)',\n uiautomator: 'UIAutomator (native Android)',\n idb: 'idb (native iOS)',\n none: 'None',\n};\n\nfunction formatTreeText(nodes: ComponentNode[], indent: number = 0): string {\n const lines: string[] = [];\n for (const node of nodes) {\n const prefix = ' '.repeat(indent);\n const name = node.reactName ?? node.name;\n const testId = node.testID ? ` [${node.testID}]` : '';\n const text = node.text ? ` \"${node.text}\"` : '';\n const tier = node.inspectionTier === 'detailed' ? ' ⚛' : '';\n const b = node.bounds;\n const bounds = b.width > 0 ? ` (${b.x},${b.y} ${b.width}x${b.height})` : '';\n lines.push(`${prefix}${name}${testId}${text}${bounds}${tier}`);\n const childStr = formatTreeText(node.children, indent + 1);\n if (childStr) lines.push(childStr);\n }\n return lines.join('\\n');\n}\n\nfunction formatStrategySection(result: InspectResult, colored: boolean): string {\n const lines: string[] = [];\n const label = STRATEGY_LABELS[result.strategy.method] ?? result.strategy.method;\n const strategyText = colored\n ? (result.strategy.method === 'none' ? pc.dim(label) : pc.cyan(label))\n : label;\n lines.push('');\n lines.push(` Device: ${result.device.name} (${result.device.platform})`);\n lines.push(` Strategy: ${strategyText}`);\n if (result.strategy.appId) {\n lines.push(` App: ${result.strategy.appId}`);\n }\n lines.push('');\n return lines.join('\\n');\n}\n\nfunction formatCapsSection(caps: InspectionCapabilities): string {\n const lines: string[] = [];\n lines.push(' Capabilities');\n lines.push(' ' + '-'.repeat(40));\n lines.push(` Tree: ${caps.tree}`);\n lines.push(` Source mapping: ${caps.sourceMapping}`);\n lines.push(` Styles: ${caps.styles}`);\n lines.push(` Protocol: ${caps.protocol}`);\n lines.push('');\n return lines.join('\\n');\n}\n\nfunction formatHintsSection(hints: string[], colored: boolean): string {\n if (hints.length === 0) return '';\n const lines = ['', ' Hints', ' ' + '-'.repeat(40)];\n for (const hint of hints) {\n lines.push(colored ? ` ${pc.yellow(hint)}` : ` ${hint}`);\n }\n lines.push('');\n return lines.join('\\n');\n}\n\nexport const inspectFormatter: OutputFormatter<InspectResult> = {\n terminal(result) {\n const parts: string[] = [formatStrategySection(result, true)];\n\n if (result.tree.length === 0) {\n parts.push(' No component tree available. Try running with React DevTools enabled.');\n parts.push(formatHintsSection(result.hints, true));\n return parts.filter(Boolean).join('\\n');\n }\n\n parts.push(formatTreeText(result.tree));\n parts.push('');\n parts.push(formatCapsSection(result.capabilities));\n parts.push(formatHintsSection(result.hints, true));\n return parts.filter(Boolean).join('\\n');\n },\n\n markdown(result) {\n const lines: string[] = [\n '# Driftx Inspect Report',\n '',\n `**Device:** ${result.device.name} (${result.device.platform})`,\n `**Strategy:** ${STRATEGY_LABELS[result.strategy.method] ?? result.strategy.method}`,\n ];\n if (result.strategy.appId) {\n lines.push(`**App:** ${result.strategy.appId}`);\n }\n\n if (result.tree.length > 0) {\n lines.push('', '## Component Tree', '', '```', formatTreeText(result.tree), '```');\n } else {\n lines.push('', 'No component tree available.');\n }\n\n lines.push('', '## Capabilities', '', '| Capability | Level |', '|------------|-------|');\n lines.push(`| Tree | ${result.capabilities.tree} |`);\n lines.push(`| Source mapping | ${result.capabilities.sourceMapping} |`);\n lines.push(`| Styles | ${result.capabilities.styles} |`);\n lines.push(`| Protocol | ${result.capabilities.protocol} |`);\n\n if (result.hints.length > 0) {\n lines.push('', '## Hints', '');\n for (const hint of result.hints) {\n lines.push(`- ${hint}`);\n }\n }\n\n return lines.join('\\n');\n },\n\n json(result) {\n return JSON.stringify({\n tree: result.tree,\n capabilities: result.capabilities,\n strategy: result.strategy,\n device: result.device,\n hints: result.hints,\n }, null, 2);\n },\n};\n","import type { Shell, DeviceInfo } from '../types.js';\nimport type { Point, InteractionBackend } from './types.js';\n\nexport class AndroidBackend implements InteractionBackend {\n constructor(private shell: Shell) {}\n\n async tap(device: DeviceInfo, point: Point): Promise<void> {\n await this.adb(device, ['input', 'tap', String(point.x), String(point.y)]);\n }\n\n async longPress(device: DeviceInfo, point: Point, durationMs: number): Promise<void> {\n await this.adb(device, ['input', 'swipe', String(point.x), String(point.y), String(point.x), String(point.y), String(durationMs)]);\n }\n\n async swipe(device: DeviceInfo, from: Point, to: Point, durationMs: number): Promise<void> {\n await this.adb(device, ['input', 'swipe', String(from.x), String(from.y), String(to.x), String(to.y), String(durationMs)]);\n }\n\n async type(device: DeviceInfo, text: string): Promise<void> {\n const escaped = text.replace(/ /g, '%s');\n await this.adb(device, ['input', 'text', escaped]);\n }\n\n async keyEvent(device: DeviceInfo, key: string): Promise<void> {\n await this.adb(device, ['input', 'keyevent', key]);\n }\n\n async openUrl(device: DeviceInfo, url: string): Promise<void> {\n await this.shell.exec('adb', ['-s', device.id, 'shell', 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', url]);\n }\n\n private async adb(device: DeviceInfo, inputArgs: string[]): Promise<void> {\n await this.shell.exec('adb', ['-s', device.id, 'shell', ...inputArgs]);\n }\n}\n","import type { Shell, DeviceInfo } from '../types.js';\nimport type { Point, InteractionBackend } from './types.js';\n\nexport class IosBackend implements InteractionBackend {\n constructor(private shell: Shell) {}\n\n async tap(device: DeviceInfo, point: Point): Promise<void> {\n await this.simctlIo(device, ['tap', String(point.x), String(point.y)]);\n }\n\n async longPress(device: DeviceInfo, point: Point, _durationMs: number): Promise<void> {\n await this.simctlIo(device, ['longpress', String(point.x), String(point.y)]);\n }\n\n async swipe(device: DeviceInfo, from: Point, to: Point, _durationMs: number): Promise<void> {\n await this.simctlIo(device, ['swipe', String(from.x), String(from.y), String(to.x), String(to.y)]);\n }\n\n async type(device: DeviceInfo, text: string): Promise<void> {\n await this.simctlIo(device, ['type', text]);\n }\n\n async keyEvent(device: DeviceInfo, key: string): Promise<void> {\n await this.simctlIo(device, ['sendkey', key]);\n }\n\n async openUrl(device: DeviceInfo, url: string): Promise<void> {\n await this.shell.exec('xcrun', ['simctl', 'openurl', device.id, url]);\n }\n\n private async simctlIo(device: DeviceInfo, args: string[]): Promise<void> {\n await this.shell.exec('xcrun', ['simctl', 'io', device.id, ...args]);\n }\n}\n","import type { Shell } from '../types.js';\nimport type { InteractionBackend } from './types.js';\nimport { AndroidBackend } from './android.js';\nimport { IosBackend } from './ios.js';\n\nexport function createBackend(shell: Shell, platform: 'android' | 'ios'): InteractionBackend {\n return platform === 'android' ? new AndroidBackend(shell) : new IosBackend(shell);\n}\n","import type { ComponentNode } from '../types.js';\nimport type { TapTarget } from './types.js';\n\nexport function resolveTarget(tree: ComponentNode[], query: string): TapTarget | null {\n const nodes = flattenTree(tree);\n\n const byTestID = nodes.find((n) => n.testID === query && hasSize(n));\n if (byTestID) return centerOf(byTestID, `testID:${query}`);\n\n const byName = nodes.find((n) => n.name === query && hasSize(n));\n if (byName) return centerOf(byName, `name:${query}`);\n\n const byText = nodes.find((n) => n.text === query && hasSize(n));\n if (byText) return centerOf(byText, `text:${query}`);\n\n return null;\n}\n\nfunction flattenTree(nodes: ComponentNode[]): ComponentNode[] {\n const result: ComponentNode[] = [];\n const stack = [...nodes];\n while (stack.length > 0) {\n const node = stack.pop()!;\n result.push(node);\n for (const child of node.children) stack.push(child);\n }\n return result;\n}\n\nfunction hasSize(node: ComponentNode): boolean {\n return node.bounds.width > 0 && node.bounds.height > 0;\n}\n\nfunction centerOf(node: ComponentNode, resolvedFrom: string): TapTarget {\n return {\n x: Math.round(node.bounds.x + node.bounds.width / 2),\n y: Math.round(node.bounds.y + node.bounds.height / 2),\n resolvedFrom,\n };\n}\n","import type { DeviceInfo, ComponentNode } from '../types.js';\nimport type { InteractionBackend, InteractionResult, SwipeDirection } from './types.js';\nimport { resolveTarget } from './resolver.js';\n\nexport class GestureExecutor {\n constructor(private backend: InteractionBackend) {}\n\n async tap(device: DeviceInfo, tree: ComponentNode[], query: string): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = resolveTarget(tree, query);\n if (!target) {\n return { success: false, action: 'tap', durationMs: Date.now() - start, error: `Target not found: ${query}` };\n }\n await this.backend.tap(device, target);\n return { success: true, action: 'tap', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'tap', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async tapXY(device: DeviceInfo, x: number, y: number): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = { x, y };\n await this.backend.tap(device, target);\n return { success: true, action: 'tapXY', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'tapXY', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async longPress(device: DeviceInfo, tree: ComponentNode[], query: string, durationMs = 1000): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = resolveTarget(tree, query);\n if (!target) {\n return { success: false, action: 'longPress', durationMs: Date.now() - start, error: `Target not found: ${query}` };\n }\n await this.backend.longPress(device, target, durationMs);\n return { success: true, action: 'longPress', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'longPress', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async swipe(device: DeviceInfo, direction: SwipeDirection, distance = 600, durationMs = 300): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const cx = device.screenSize?.width ? Math.round(device.screenSize.width / 2) : 540;\n const cy = device.screenSize?.height ? Math.round(device.screenSize.height / 2) : 960;\n const from = { x: cx, y: cy };\n const half = Math.round(distance / 2);\n const to = direction === 'up' ? { x: cx, y: cy - half }\n : direction === 'down' ? { x: cx, y: cy + half }\n : direction === 'left' ? { x: cx - half, y: cy }\n : { x: cx + half, y: cy };\n await this.backend.swipe(device, from, to, durationMs);\n return { success: true, action: 'swipe', durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'swipe', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async typeInto(device: DeviceInfo, tree: ComponentNode[], query: string, text: string): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = resolveTarget(tree, query);\n if (!target) {\n return { success: false, action: 'typeInto', durationMs: Date.now() - start, error: `Target not found: ${query}` };\n }\n await this.backend.tap(device, target);\n await this.backend.type(device, text);\n return { success: true, action: 'typeInto', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'typeInto', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async goBack(device: DeviceInfo): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const key = device.platform === 'android' ? 'KEYCODE_BACK' : 'home';\n await this.backend.keyEvent(device, key);\n return { success: true, action: 'goBack', durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'goBack', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async openUrl(device: DeviceInfo, url: string): Promise<InteractionResult> {\n const start = Date.now();\n try {\n await this.backend.openUrl(device, url);\n return { success: true, action: 'openUrl', durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'openUrl', durationMs: Date.now() - start, error: String(e) };\n }\n }\n}\n","#!/usr/bin/env node\nimport { run } from './cli.js';\n\nrun(process.argv);\n"],"mappings":"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","names":["existsSync","mkdirSync","readFileSync","readdirSync","unlinkSync","writeFileSync","dirname","join","resolve","http","resolve","fs","path","fs","os","path","resolve","fs","path","delay","resolve","run","resolve","fs","path","readFileSync","sharp","fs","sharp","sharp","pixelmatch","sharp","sharp","sharp","boxesOverlap","fs","run","resolve","pc","pc","pc","require","readdirSync","readFileSync","join","writeFileSync","dirname","existsSync","mkdirSync","unlinkSync"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/shell.ts","../src/config.ts","../src/types.ts","../src/logger.ts","../src/prerequisites.ts","../src/exit-codes.ts","../src/commands/doctor.ts","../src/commands/init.ts","../src/devices/android-discovery.ts","../src/devices/ios-discovery.ts","../src/devices/discovery.ts","../src/commands/capture.ts","../src/capture/android-capture.ts","../src/capture/ios-capture.ts","../src/capture/capture.ts","../src/run-store.ts","../src/retry.ts","../src/commands/device-picker.ts","../src/inspect/uiautomator.ts","../src/inspect/ios-accessibility.ts","../src/inspect/cdp-client.ts","../src/inspect/strategy-cache.ts","../src/inspect/tree-inspector.ts","../src/formatters/compare.ts","../src/analyses/context.ts","../src/analyses/registry.ts","../src/diff/image-loader.ts","../src/diff/alignment.ts","../src/diff/pixel-diff.ts","../src/diff/region-extractor.ts","../src/diff/ignore-rules.ts","../src/diff/mask-generator.ts","../src/diff/viewport.ts","../src/diff/compare.ts","../src/inspect/component-matcher.ts","../src/inspect/finding-generator.ts","../src/analyses/plugins/pixel.ts","../src/analyses/plugins/a11y.ts","../src/analyses/plugins/regression.ts","../src/analyses/default-registry.ts","../src/analyses/orchestrator.ts","../src/commands/compare.ts","../src/formatters/clipboard.ts","../src/formatters/format.ts","../src/formatters/devices.ts","../src/formatters/doctor.ts","../src/formatters/inspect.ts","../src/interact/android.ts","../src/interact/ios.ts","../src/interact/backend.ts","../src/interact/resolver.ts","../src/interact/gestures.ts","../src/bin.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createRequire } from 'module';\nimport { existsSync, mkdirSync, readFileSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { homedir } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { RealShell } from './shell.js';\nimport { loadConfig } from './config.js';\nimport { createLogger, setLogger } from './logger.js';\nimport { checkPrerequisites } from './prerequisites.js';\nimport { computeDoctorExitCode } from './commands/doctor.js';\nimport { detectFramework, generateConfig } from './commands/init.js';\nimport { DeviceDiscovery } from './devices/discovery.js';\nimport { runCapture } from './commands/capture.js';\nimport { runCompare } from './commands/compare.js';\nimport { TreeInspector } from './inspect/tree-inspector.js';\nimport { pickDevice } from './commands/device-picker.js';\nimport { formatOutput } from './formatters/format.js';\nimport { devicesFormatter } from './formatters/devices.js';\nimport { doctorFormatter } from './formatters/doctor.js';\nimport { inspectFormatter } from './formatters/inspect.js';\nimport { compareFormatter } from './formatters/compare.js';\nimport type { FormatterContext } from './formatters/types.js';\nimport { createBackend } from './interact/backend.js';\nimport { GestureExecutor } from './interact/gestures.js';\n\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json');\n\nfunction getFormatterContext(opts: Record<string, unknown>): FormatterContext {\n return {\n format: (opts.format as FormatterContext['format']) ?? 'terminal',\n copy: !!opts.copy,\n quiet: !!opts.quiet,\n };\n}\n\nexport function createProgram(): Command {\n const program = new Command();\n program\n .name('driftx')\n .description('Visual diff tool for React Native and Android development')\n .version(pkg.version)\n .option('--verbose', 'enable debug logging')\n .option('--quiet', 'suppress all output except errors')\n .option('--format <type>', 'output format: terminal, markdown, json', 'terminal')\n .option('--copy', 'copy output to clipboard');\n\n program.hook('preAction', (_thisCommand, actionCommand) => {\n const opts = actionCommand.optsWithGlobals();\n const level = opts.verbose ? 'debug' : opts.quiet ? 'silent' : 'info';\n setLogger(createLogger(level));\n });\n\n program\n .command('doctor')\n .description('Check system prerequisites for driftx')\n .action(async function(this: Command) {\n const shell = new RealShell();\n const config = await loadConfig();\n const checks = await checkPrerequisites(shell, config.metroPort);\n const ctx = getFormatterContext(this.optsWithGlobals());\n await formatOutput(doctorFormatter, checks, ctx);\n process.exitCode = computeDoctorExitCode(checks);\n });\n\n program\n .command('init')\n .description('Initialize driftx configuration for this project')\n .action(async () => {\n const cwd = process.cwd();\n const files = readdirSync(cwd);\n let packageJson: Record<string, unknown> | undefined;\n try {\n packageJson = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf-8'));\n } catch {\n // no package.json\n }\n const framework = detectFramework(files, packageJson);\n const config = generateConfig(framework);\n const configPath = join(cwd, '.driftxrc.json');\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n');\n console.log(`Created ${configPath} (framework: ${framework})`);\n });\n\n program\n .command('devices')\n .description('List connected devices and simulators')\n .action(async function(this: Command) {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const ctx = getFormatterContext(this.optsWithGlobals());\n await formatOutput(devicesFormatter, devices, ctx);\n });\n\n program\n .command('capture')\n .description('Capture a screenshot from a device')\n .option('-d, --device <id>', 'device ID or name')\n .option('-o, --output <path>', 'output file path')\n .option('--settle', 'enable settle-time check')\n .option('--no-settle', 'disable settle-time check')\n .action(async (opts) => {\n const shell = new RealShell();\n const config = await loadConfig();\n const result = await runCapture(shell, config, {\n device: opts.device,\n output: opts.output,\n settleCheck: opts.settle,\n });\n console.log(`Screenshot saved: ${result.path}`);\n if (result.runId) {\n console.log(`Run ID: ${result.runId}`);\n }\n });\n\n program\n .command('compare')\n .description('Compare a screenshot against a design')\n .option('--design <path>', 'path to design image')\n .option('-d, --device <id>', 'device ID or name')\n .option('--threshold <n>', 'diff percentage threshold', parseFloat)\n .option('--screenshot <path>', 'use existing screenshot instead of capturing')\n .option('--with <analyses>', 'comma-separated analyses to run')\n .option('--without <analyses>', 'exclude specific analyses')\n .option('--baseline', 'compare against previous run screenshot')\n .action(async function(this: Command, opts: Record<string, unknown>) {\n if (!opts.design && !opts.baseline) {\n throw new Error('Either --design or --baseline must be provided');\n }\n const shell = new RealShell();\n const config = await loadConfig();\n const { exitCode, formatData } = await runCompare(shell, config, {\n design: opts.design as string | undefined,\n device: opts.device as string | undefined,\n threshold: opts.threshold as number | undefined,\n screenshot: opts.screenshot as string | undefined,\n with: opts.with as string | undefined,\n without: opts.without as string | undefined,\n baseline: !!opts.baseline,\n });\n const ctx = getFormatterContext(this.optsWithGlobals());\n await formatOutput(compareFormatter, formatData, ctx);\n process.exitCode = exitCode;\n });\n\n program\n .command('inspect')\n .description('Inspect component tree on device')\n .option('-d, --device <id>', 'device ID or name')\n .option('--json', 'output as JSON (alias for --format json)')\n .option('--capabilities', 'show inspection capabilities only')\n .action(async function(this: Command, opts: Record<string, unknown>) {\n const shell = new RealShell();\n const config = await loadConfig();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const inspector = new TreeInspector(shell, process.cwd());\n const result = await inspector.inspect(device, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n\n const globalOpts = this.optsWithGlobals();\n if (opts.json) globalOpts.format = 'json';\n const ctx = getFormatterContext(globalOpts);\n await formatOutput(inspectFormatter, result, ctx);\n });\n\n program\n .command('tap <target>')\n .description('Tap a component by testID, name, or text')\n .option('-d, --device <id>', 'device ID or name')\n .option('--xy', 'treat target as x,y coordinates')\n .action(async (target: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const config = await loadConfig();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n\n let result;\n if (opts.xy) {\n const [x, y] = target.split(',').map(Number);\n result = await executor.tapXY(device, x, y);\n } else {\n const inspector = new TreeInspector(shell, process.cwd());\n const inspectResult = await inspector.inspect(device, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n result = await executor.tap(device, inspectResult.tree, target);\n }\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('type <target> <text>')\n .description('Tap a component then type text into it')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (target: string, text: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const config = await loadConfig();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const inspector = new TreeInspector(shell, process.cwd());\n const inspectResult = await inspector.inspect(device, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.typeInto(device, inspectResult.tree, target, text);\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('swipe <direction>')\n .description('Swipe up, down, left, or right')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (direction: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.swipe(device, direction as 'up' | 'down' | 'left' | 'right');\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('go-back')\n .description('Press the back button')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.goBack(device);\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('open-url <url>')\n .description('Open a deep link or URL on the device')\n .option('-d, --device <id>', 'device ID or name')\n .action(async (url: string, opts: Record<string, unknown>) => {\n const shell = new RealShell();\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n let device;\n if (opts.device) {\n device = booted.find((d) => d.id === opts.device || d.name === opts.device);\n if (!device) throw new Error(`Device not found: ${opts.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n const backend = createBackend(shell, device.platform);\n const executor = new GestureExecutor(backend);\n const result = await executor.openUrl(device, url);\n console.log(JSON.stringify(result, null, 2));\n });\n\n program\n .command('setup-claude')\n .description('Register driftx as a Claude Code plugin')\n .action(() => {\n const claudeDir = join(homedir(), '.claude');\n const pluginsDir = join(claudeDir, 'plugins');\n const driftxPluginDir = join(pluginsDir, 'driftx');\n const registryPath = join(pluginsDir, 'installed_plugins.json');\n\n const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\n const skillSource = join(packageRoot, 'driftx-plugin');\n\n if (!existsSync(skillSource)) {\n console.error(`driftx-plugin directory not found at ${skillSource}`);\n process.exitCode = 1;\n return;\n }\n\n mkdirSync(pluginsDir, { recursive: true });\n\n if (existsSync(driftxPluginDir)) {\n try { unlinkSync(driftxPluginDir); } catch {\n console.error(`Could not remove existing ${driftxPluginDir}. Remove it manually and retry.`);\n process.exitCode = 1;\n return;\n }\n }\n symlinkSync(skillSource, driftxPluginDir);\n\n let registry: { version: number; plugins: Record<string, unknown[]> } = { version: 2, plugins: {} };\n try {\n registry = JSON.parse(readFileSync(registryPath, 'utf-8'));\n } catch {}\n\n registry.plugins['driftx@local'] = [{\n scope: 'user',\n installPath: driftxPluginDir,\n version: pkg.version,\n installedAt: new Date().toISOString(),\n lastUpdated: new Date().toISOString(),\n }];\n\n writeFileSync(registryPath, JSON.stringify(registry, null, 2));\n console.log('driftx registered as Claude Code plugin.');\n console.log(` Symlink: ${driftxPluginDir} -> ${skillSource}`);\n console.log(` Registry: ${registryPath}`);\n console.log('\\nRestart Claude Code to pick up the driftx skill.');\n });\n\n return program;\n}\n\nexport function run(argv: string[]): void {\n const program = createProgram();\n program.parseAsync(argv);\n}\n","import { execFile } from 'node:child_process';\nimport type { Shell } from './types.js';\n\nexport class RealShell implements Shell {\n async exec(\n cmd: string,\n args: string[],\n options?: { timeout?: number },\n ): Promise<{ stdout: string; stderr: string }> {\n const controller = new AbortController();\n const timeout = options?.timeout;\n\n return new Promise((resolve, reject) => {\n const child = execFile(\n cmd,\n args,\n {\n signal: controller.signal,\n maxBuffer: 10 * 1024 * 1024,\n encoding: 'utf-8',\n },\n (error, stdout, stderr) => {\n if (error) {\n reject(error);\n } else {\n resolve({ stdout, stderr });\n }\n },\n );\n\n if (timeout) {\n setTimeout(() => {\n controller.abort();\n child.kill();\n }, timeout);\n }\n });\n }\n}\n\nexport function createShell(): Shell {\n return new RealShell();\n}\n","import { z } from 'zod';\nimport { cosmiconfig } from 'cosmiconfig';\nimport { DEFAULT_TIMEOUT_CONFIG, DEFAULT_RETRY_POLICY } from './types.js';\n\nconst timeoutSchema = z.object({\n deviceDiscoveryMs: z.number().int().positive().optional(),\n screenshotCaptureMs: z.number().int().positive().optional(),\n treeInspectionMs: z.number().int().positive().optional(),\n devToolsConnectMs: z.number().int().positive().optional(),\n});\n\nconst retrySchema = z.object({\n maxAttempts: z.number().int().positive().optional(),\n baseDelayMs: z.number().int().positive().optional(),\n maxDelayMs: z.number().int().positive().optional(),\n backoffMultiplier: z.number().positive().optional(),\n retryableErrors: z.array(z.string()).optional(),\n});\n\nconst boundingBoxSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number().positive(),\n height: z.number().positive(),\n});\n\nconst colorRangeSchema = z.object({\n r: z.tuple([z.number(), z.number()]),\n g: z.tuple([z.number(), z.number()]),\n b: z.tuple([z.number(), z.number()]),\n a: z.tuple([z.number(), z.number()]).optional(),\n});\n\nconst ignoreRuleSchema = z.object({\n type: z.enum(['testID', 'componentName', 'textPattern', 'boundingBox', 'sourceFile', 'colorRange']),\n value: z.union([z.string(), boundingBoxSchema, colorRangeSchema]),\n reason: z.string().optional(),\n});\n\nconst viewportSchema = z.object({\n cropStatusBar: z.boolean().optional(),\n cropNavigationBar: z.boolean().optional(),\n statusBarHeight: z.number().int().nonnegative().optional(),\n navigationBarHeight: z.number().int().nonnegative().optional(),\n});\n\nconst analysesSchema = z.object({\n default: z.array(z.string()).optional(),\n disabled: z.array(z.string()).optional(),\n options: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),\n}).optional();\n\nexport const configSchema = z.object({\n threshold: z.number().min(0).max(1).optional(),\n diffThreshold: z.number().min(0).max(1).optional(),\n settleTimeMs: z.number().int().positive().optional(),\n settleCheckEnabled: z.boolean().optional(),\n settleMaxDelta: z.number().min(0).max(1).optional(),\n primaryDevice: z.string().optional(),\n groups: z.record(z.string(), z.array(z.string())).optional(),\n platform: z.enum(['android', 'ios']).optional(),\n metroPort: z.number().int().positive().optional(),\n devToolsPort: z.number().int().positive().optional(),\n ignoreRules: z.array(ignoreRuleSchema).optional(),\n viewport: viewportSchema.optional(),\n timeouts: timeoutSchema.optional(),\n retry: retrySchema.optional(),\n regionMergeGap: z.number().int().nonnegative().optional(),\n regionMinArea: z.number().int().nonnegative().optional(),\n diffMaskColor: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional(),\n analyses: analysesSchema,\n});\n\nexport type DriftxConfig = {\n threshold: number;\n diffThreshold: number;\n settleTimeMs: number;\n settleCheckEnabled: boolean;\n settleMaxDelta: number;\n primaryDevice?: string;\n groups: Record<string, string[]>;\n platform: 'android' | 'ios';\n metroPort: number;\n devToolsPort: number;\n ignoreRules: z.infer<typeof ignoreRuleSchema>[];\n viewport: {\n cropStatusBar: boolean;\n cropNavigationBar: boolean;\n statusBarHeight: number;\n navigationBarHeight: number;\n };\n timeouts: typeof DEFAULT_TIMEOUT_CONFIG;\n retry: typeof DEFAULT_RETRY_POLICY;\n regionMergeGap: number;\n regionMinArea: number;\n diffMaskColor: [number, number, number, number];\n analyses: {\n default: string[];\n disabled: string[];\n options: Record<string, Record<string, unknown>>;\n };\n};\n\nconst DEFAULTS: DriftxConfig = {\n threshold: 0.1,\n diffThreshold: 0.01,\n settleTimeMs: 300,\n settleCheckEnabled: true,\n settleMaxDelta: 0.001,\n primaryDevice: undefined,\n groups: {},\n platform: 'android',\n metroPort: 8081,\n devToolsPort: 8097,\n ignoreRules: [],\n viewport: {\n cropStatusBar: true,\n cropNavigationBar: true,\n statusBarHeight: 24,\n navigationBarHeight: 48,\n },\n timeouts: { ...DEFAULT_TIMEOUT_CONFIG },\n retry: { ...DEFAULT_RETRY_POLICY },\n regionMergeGap: 8,\n regionMinArea: 100,\n diffMaskColor: [255, 0, 0, 128],\n analyses: {\n default: [],\n disabled: [],\n options: {},\n },\n};\n\nexport function getDefaultConfig(): DriftxConfig {\n return structuredClone(DEFAULTS);\n}\n\nexport function parseConfig(raw: unknown): DriftxConfig {\n const parsed = configSchema.parse(raw);\n const defaults = getDefaultConfig();\n\n return {\n ...defaults,\n ...parsed,\n viewport: { ...defaults.viewport, ...parsed.viewport },\n timeouts: { ...defaults.timeouts, ...parsed.timeouts },\n retry: { ...defaults.retry, ...parsed.retry },\n analyses: {\n default: parsed.analyses?.default ?? DEFAULTS.analyses.default,\n disabled: parsed.analyses?.disabled ?? DEFAULTS.analyses.disabled,\n options: { ...DEFAULTS.analyses.options, ...parsed.analyses?.options },\n },\n };\n}\n\nconst explorer = cosmiconfig('driftx');\n\nexport async function loadConfig(searchFrom?: string): Promise<DriftxConfig> {\n const result = await explorer.search(searchFrom);\n if (!result || result.isEmpty) {\n return getDefaultConfig();\n }\n return parseConfig(result.config);\n}\n","export interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface InspectionCapabilities {\n tree: 'none' | 'basic' | 'detailed';\n sourceMapping: 'none' | 'partial' | 'precise';\n styles: 'none' | 'partial' | 'detailed';\n protocol: string;\n}\n\nexport interface ScrollCaptureSupport {\n supported: boolean;\n reason: string;\n mode: 'none' | 'experimental' | 'stable';\n}\n\nexport interface SourceResolution {\n fileName: string;\n lineNumber?: number;\n columnNumber?: number;\n method: 'inspectElement' | 'sourceMap' | 'filesystem' | 'resourceId';\n confidence: number;\n}\n\nexport interface ExpectedValue {\n value: string | number;\n source: 'heuristic' | 'design-metadata' | 'unknown';\n confidence: number;\n label?: string;\n}\n\nexport interface DiffEvidence {\n type: 'pixel' | 'tree' | 'accessibility' | 'semantic' | 'token' | 'regression';\n score: number;\n note: string;\n}\n\nexport interface ComponentMatch {\n name: string;\n testID?: string;\n source?: SourceResolution;\n bounds: BoundingBox;\n depth: number;\n}\n\nexport interface DiffFinding {\n id: string;\n category:\n | 'spacing'\n | 'color'\n | 'font'\n | 'alignment'\n | 'size'\n | 'content'\n | 'missing'\n | 'extra'\n | 'unknown'\n | 'accessibility'\n | 'text-mismatch'\n | 'hierarchy'\n | 'regression'\n | 'design-token';\n severity: 'critical' | 'major' | 'minor' | 'info';\n confidence: number;\n region: BoundingBox;\n component?: ComponentMatch;\n expected?: ExpectedValue;\n actual?: ExpectedValue;\n evidence: DiffEvidence[];\n description?: string;\n}\n\nexport interface RunMetadata {\n runId: string;\n startedAt: string;\n completedAt?: string;\n projectRoot: string;\n gitCommit?: string;\n gitBranch?: string;\n deviceId: string;\n platform: 'android' | 'ios';\n framework: 'react-native' | 'native-android' | 'native-ios' | 'unknown';\n orientation: 'portrait' | 'landscape';\n appId?: string;\n configHash: string;\n driftxVersion: string;\n}\n\nexport interface PrerequisiteCheck {\n name: string;\n required: boolean;\n available: boolean;\n version?: string;\n path?: string;\n error?: string;\n fix?: string;\n}\n\nexport interface CapabilityReport {\n inspection: InspectionCapabilities;\n scrollCapture: ScrollCaptureSupport;\n sourceMapping: boolean;\n prerequisites: PrerequisiteCheck[];\n}\n\nexport interface RetryPolicy {\n maxAttempts: number;\n baseDelayMs: number;\n maxDelayMs: number;\n backoffMultiplier: number;\n retryableErrors: string[];\n}\n\nexport interface TimeoutConfig {\n deviceDiscoveryMs: number;\n screenshotCaptureMs: number;\n treeInspectionMs: number;\n devToolsConnectMs: number;\n}\n\nexport interface DeviceInfo {\n id: string;\n name: string;\n platform: 'android' | 'ios';\n osVersion: string;\n screenSize?: { width: number; height: number; density: number };\n state: 'booted' | 'offline' | 'unauthorized';\n transport?: string;\n}\n\nexport interface DiffRegion {\n id: string;\n bounds: BoundingBox;\n pixelCount: number;\n percentage: number;\n cropped?: string;\n}\n\nexport interface DiffResult {\n runId: string;\n metadata: RunMetadata;\n totalPixels: number;\n diffPixels: number;\n diffPercentage: number;\n regions: DiffRegion[];\n findings: DiffFinding[];\n capabilities: CapabilityReport;\n durationMs: number;\n}\n\nexport interface ColorRange {\n r: [number, number];\n g: [number, number];\n b: [number, number];\n a?: [number, number];\n}\n\nexport interface IgnoreRule {\n type:\n | 'testID'\n | 'componentName'\n | 'textPattern'\n | 'boundingBox'\n | 'sourceFile'\n | 'colorRange';\n value: string | BoundingBox | ColorRange;\n reason?: string;\n}\n\nexport interface ComponentNode {\n id: string;\n name: string;\n nativeName?: string;\n reactName?: string;\n testID?: string;\n bounds: BoundingBox;\n text?: string;\n children: ComponentNode[];\n source?: SourceResolution;\n styles?: Record<string, string | number>;\n inspectionTier: 'basic' | 'detailed';\n}\n\nexport interface Shell {\n exec(\n cmd: string,\n args: string[],\n options?: { timeout?: number },\n ): Promise<{ stdout: string; stderr: string }>;\n}\n\nexport const DEFAULT_RETRY_POLICY: RetryPolicy = {\n maxAttempts: 3,\n baseDelayMs: 500,\n maxDelayMs: 5000,\n backoffMultiplier: 2,\n retryableErrors: ['device busy', 'transport error', 'ECONNRESET'],\n};\n\nexport const DEFAULT_TIMEOUT_CONFIG: TimeoutConfig = {\n deviceDiscoveryMs: 5000,\n screenshotCaptureMs: 10000,\n treeInspectionMs: 15000,\n devToolsConnectMs: 3000,\n};\n","import pino from 'pino';\n\nexport type LogLevel = 'debug' | 'info' | 'error' | 'silent';\n\nexport function createLogger(level: LogLevel = 'info'): pino.Logger {\n return pino({\n level: level === 'silent' ? 'silent' : level,\n transport:\n process.env.NODE_ENV !== 'test'\n ? { target: 'pino-pretty', options: { colorize: true } }\n : undefined,\n });\n}\n\nlet _logger: pino.Logger | undefined;\n\nexport function getLogger(): pino.Logger {\n if (!_logger) {\n _logger = createLogger();\n }\n return _logger;\n}\n\nexport function setLogger(logger: pino.Logger): void {\n _logger = logger;\n}\n","import type { Shell, PrerequisiteCheck } from './types.js';\n\ninterface PrerequisiteSpec {\n name: string;\n cmd: string;\n args: string[];\n required: boolean;\n versionParser: (stdout: string) => string;\n fix: string;\n}\n\nconst CLI_PREREQUISITES: PrerequisiteSpec[] = [\n {\n name: 'node',\n cmd: 'node',\n args: ['--version'],\n required: true,\n versionParser: (stdout) => stdout.trim().replace(/^v/, ''),\n fix: 'Install Node.js >= 18 from https://nodejs.org',\n },\n {\n name: 'adb',\n cmd: 'adb',\n args: ['--version'],\n required: false,\n versionParser: (stdout) => {\n const match = stdout.match(/(\\d+\\.\\d+\\.\\d+)/);\n return match?.[1] ?? 'unknown';\n },\n fix: 'Install Android SDK Platform-Tools: https://developer.android.com/studio',\n },\n {\n name: 'xcrun',\n cmd: 'xcrun',\n args: ['--version'],\n required: false,\n versionParser: (stdout) => stdout.trim(),\n fix: 'Install Xcode Command Line Tools: xcode-select --install',\n },\n];\n\nasync function checkOne(spec: PrerequisiteSpec, shell: Shell): Promise<PrerequisiteCheck> {\n try {\n const { stdout } = await shell.exec(spec.cmd, spec.args, { timeout: 5000 });\n return {\n name: spec.name,\n required: spec.required,\n available: true,\n version: spec.versionParser(stdout),\n };\n } catch (err) {\n return {\n name: spec.name,\n required: spec.required,\n available: false,\n error: err instanceof Error ? err.message : String(err),\n fix: spec.fix,\n };\n }\n}\n\nasync function checkMetro(port: number): Promise<PrerequisiteCheck> {\n try {\n const { default: http } = await import('node:http');\n const status = await new Promise<string>((resolve, reject) => {\n const req = http.get(`http://localhost:${port}/status`, { timeout: 2000 }, (res) => {\n let data = '';\n res.on('data', (chunk: Buffer) => { data += chunk; });\n res.on('end', () => resolve(data));\n });\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });\n });\n return {\n name: 'metro',\n required: false,\n available: true,\n version: `running on :${port}`,\n };\n } catch {\n return {\n name: 'metro',\n required: false,\n available: false,\n fix: 'Start Metro bundler: npx react-native start',\n };\n }\n}\n\nexport async function checkPrerequisites(shell: Shell, metroPort = 8081): Promise<PrerequisiteCheck[]> {\n const cliChecks = CLI_PREREQUISITES.map((spec) => checkOne(spec, shell));\n const metro = checkMetro(metroPort);\n return Promise.all([...cliChecks, metro]);\n}\n","export const ExitCode = {\n Success: 0,\n DiffFound: 1,\n ConfigError: 2,\n RuntimeError: 3,\n PrerequisiteMissing: 4,\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n","import type { PrerequisiteCheck } from '../types.js';\nimport { ExitCode } from '../exit-codes.js';\n\nexport function computeDoctorExitCode(checks: PrerequisiteCheck[]): number {\n return checks.some((c) => c.required && !c.available)\n ? ExitCode.PrerequisiteMissing\n : ExitCode.Success;\n}\n","import type { RunMetadata } from '../types.js';\n\ntype Framework = RunMetadata['framework'];\n\nexport function detectFramework(files: string[], packageJson?: Record<string, unknown>): Framework {\n if (packageJson) {\n const deps = {\n ...(packageJson.dependencies as Record<string, string> | undefined),\n ...(packageJson.devDependencies as Record<string, string> | undefined),\n };\n if (deps['react-native']) {\n return 'react-native';\n }\n }\n\n const hasGradle = files.some((f) => f.endsWith('.gradle') || f.endsWith('.gradle.kts'));\n if (hasGradle) return 'native-android';\n\n const hasXcode = files.some((f) => f.endsWith('.xcodeproj') || f.endsWith('.xcworkspace'));\n if (hasXcode) return 'native-ios';\n\n return 'unknown';\n}\n\ninterface InitConfig {\n framework: Framework;\n threshold: number;\n diffThreshold: number;\n settleTimeMs: number;\n platform: 'android' | 'ios';\n metroPort?: number;\n viewport: {\n cropStatusBar: boolean;\n cropNavigationBar: boolean;\n };\n}\n\nexport function generateConfig(framework: Framework): InitConfig {\n const base = {\n threshold: 0.1,\n diffThreshold: 0.01,\n settleTimeMs: 300,\n viewport: {\n cropStatusBar: true,\n cropNavigationBar: true,\n },\n };\n\n switch (framework) {\n case 'react-native':\n return { ...base, framework, platform: 'android', metroPort: 8081 };\n case 'native-android':\n return { ...base, framework, platform: 'android' };\n case 'native-ios':\n return { ...base, framework, platform: 'ios' };\n default:\n return { ...base, framework, platform: 'android' };\n }\n}\n","import type { DeviceInfo, Shell } from '../types.js';\n\nexport function parseAdbDevices(output: string): DeviceInfo[] {\n const devices: DeviceInfo[] = [];\n const lines = output.split('\\n');\n\n for (const line of lines) {\n if (line.startsWith('List of devices') || line.trim() === '') continue;\n\n const match = line.match(/^(\\S+)\\s+(device|offline|unauthorized)(.*)$/);\n if (!match) continue;\n\n const [, id, rawState, rest] = match;\n\n const modelMatch = rest.match(/model:(\\S+)/);\n const transportMatch = rest.match(/transport_id:(\\S+)/);\n\n const state: DeviceInfo['state'] =\n rawState === 'device' ? 'booted' :\n rawState === 'offline' ? 'offline' : 'unauthorized';\n\n devices.push({\n id,\n name: modelMatch?.[1] ?? id,\n platform: 'android',\n osVersion: '',\n state,\n transport: transportMatch?.[1],\n });\n }\n\n return devices;\n}\n\nasync function fetchApiLevel(shell: Shell, deviceId: string): Promise<string> {\n try {\n const { stdout } = await shell.exec('adb', ['-s', deviceId, 'shell', 'getprop', 'ro.build.version.sdk']);\n return stdout.trim();\n } catch {\n return '';\n }\n}\n\nexport async function discoverAndroidDevices(shell: Shell): Promise<DeviceInfo[]> {\n const { stdout } = await shell.exec('adb', ['devices', '-l']);\n const devices = parseAdbDevices(stdout);\n\n for (const device of devices) {\n if (device.state === 'booted') {\n device.osVersion = await fetchApiLevel(shell, device.id);\n }\n }\n\n return devices;\n}\n","import type { DeviceInfo, Shell } from '../types.js';\n\ninterface SimctlDevice {\n udid: string;\n name: string;\n state: string;\n isAvailable: boolean;\n}\n\ninterface SimctlOutput {\n devices: Record<string, SimctlDevice[]>;\n}\n\nfunction parseOsVersion(runtime: string): string {\n const match = runtime.match(/iOS-(\\d+)-(\\d+)/);\n return match ? `${match[1]}.${match[2]}` : '';\n}\n\nexport function parseSimctlDevices(output: string): DeviceInfo[] {\n let parsed: SimctlOutput;\n try {\n parsed = JSON.parse(output);\n } catch {\n return [];\n }\n\n const devices: DeviceInfo[] = [];\n\n for (const [runtime, sims] of Object.entries(parsed.devices)) {\n const osVersion = parseOsVersion(runtime);\n\n for (const sim of sims) {\n if (!sim.isAvailable) continue;\n\n const state: DeviceInfo['state'] =\n sim.state === 'Booted' ? 'booted' : 'offline';\n\n devices.push({\n id: sim.udid,\n name: sim.name,\n platform: 'ios',\n osVersion,\n state,\n });\n }\n }\n\n return devices;\n}\n\nexport async function discoverIosDevices(shell: Shell): Promise<DeviceInfo[]> {\n const { stdout } = await shell.exec('xcrun', ['simctl', 'list', 'devices', '--json']);\n return parseSimctlDevices(stdout);\n}\n","import type { DeviceInfo, Shell } from '../types.js';\nimport { discoverAndroidDevices } from './android-discovery.js';\nimport { discoverIosDevices } from './ios-discovery.js';\nimport { getLogger } from '../logger.js';\n\ninterface DiscoveryOptions {\n cacheTtlMs?: number;\n}\n\nexport class DeviceDiscovery {\n private shell: Shell;\n private cacheTtlMs: number;\n private cache: DeviceInfo[] | null = null;\n private cacheTime = 0;\n\n constructor(shell: Shell, options?: DiscoveryOptions) {\n this.shell = shell;\n this.cacheTtlMs = options?.cacheTtlMs ?? 30000;\n }\n\n async list(): Promise<DeviceInfo[]> {\n if (this.cache && Date.now() - this.cacheTime < this.cacheTtlMs) {\n return this.cache;\n }\n\n const results: DeviceInfo[] = [];\n const logger = getLogger();\n\n try {\n const android = await discoverAndroidDevices(this.shell);\n results.push(...android);\n } catch (err) {\n logger.debug({ err }, 'Android discovery failed');\n }\n\n try {\n const ios = await discoverIosDevices(this.shell);\n results.push(...ios);\n } catch (err) {\n logger.debug({ err }, 'iOS discovery failed');\n }\n\n this.cache = results;\n this.cacheTime = Date.now();\n return results;\n }\n\n async findById(id: string): Promise<DeviceInfo | undefined> {\n const devices = await this.list();\n return devices.find((d) => d.id === id);\n }\n\n invalidateCache(): void {\n this.cache = null;\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { Shell, DeviceInfo } from '../types.js';\nimport { DEFAULT_RETRY_POLICY } from '../types.js';\nimport type { DriftxConfig } from '../config.js';\nimport { DeviceDiscovery } from '../devices/discovery.js';\nimport { captureScreenshot } from '../capture/capture.js';\nimport { RunStore } from '../run-store.js';\nimport { withRetry } from '../retry.js';\nimport { pickDevice } from './device-picker.js';\n\nexport interface CaptureCommandOptions {\n device?: string;\n output?: string;\n settleCheck?: boolean;\n}\n\nexport async function runCapture(\n shell: Shell,\n config: DriftxConfig,\n options: CaptureCommandOptions,\n): Promise<{ path: string; runId: string }> {\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n\n if (booted.length === 0) {\n throw new Error('No booted devices found. Start an emulator or boot a simulator.');\n }\n\n let device: DeviceInfo;\n if (options.device) {\n const found = booted.find((d) => d.id === options.device || d.name === options.device);\n if (!found) throw new Error(`Device not found: ${options.device}`);\n device = found;\n } else if (config.primaryDevice) {\n const found = booted.find((d) => d.id === config.primaryDevice || d.name === config.primaryDevice);\n if (!found) throw new Error(`Primary device not found: ${config.primaryDevice}`);\n device = found;\n } else {\n device = await pickDevice(booted);\n }\n\n const buffer = await withRetry(\n () => captureScreenshot(shell, device, {\n settleCheck: options.settleCheck ?? config.settleCheckEnabled,\n settleMaxDelta: config.settleMaxDelta,\n settleDelayMs: config.settleTimeMs,\n }),\n config.retry ?? DEFAULT_RETRY_POLICY,\n );\n\n const projectRoot = process.cwd();\n\n if (options.output) {\n fs.mkdirSync(path.dirname(options.output), { recursive: true });\n fs.writeFileSync(options.output, buffer);\n return { path: options.output, runId: '' };\n }\n\n const store = new RunStore(projectRoot);\n const run = store.createRun();\n await store.writeArtifact(run.runId, 'screenshot.png', buffer);\n await store.writeMetadata(run.runId, {\n runId: run.runId,\n startedAt: new Date().toISOString(),\n completedAt: new Date().toISOString(),\n deviceId: device.id,\n platform: device.platform,\n orientation: 'portrait',\n framework: 'unknown',\n projectRoot,\n driftxVersion: '0.1.0',\n });\n\n return { path: store.getRunPath(run.runId, 'screenshot.png'), runId: run.runId };\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { Shell } from '../types.js';\n\nconst DEVICE_TMP_PATH = '/sdcard/driftx-tmp.png';\n\nexport async function captureAndroidScreenshot(\n shell: Shell,\n deviceId: string,\n timeout?: number,\n): Promise<Buffer> {\n const localTmp = path.join(os.tmpdir(), `driftx-android-${Date.now()}-${deviceId}.png`);\n\n try {\n await shell.exec(\n 'adb',\n ['-s', deviceId, 'shell', 'screencap', '-p', DEVICE_TMP_PATH],\n timeout ? { timeout } : undefined,\n );\n await shell.exec('adb', ['-s', deviceId, 'pull', DEVICE_TMP_PATH, localTmp]);\n\n if (!fs.existsSync(localTmp)) {\n throw new Error('Screenshot capture returned empty buffer — pull did not create local file');\n }\n const buffer = fs.readFileSync(localTmp);\n if (buffer.length === 0) {\n throw new Error('Screenshot capture returned empty buffer');\n }\n return buffer;\n } finally {\n try {\n await shell.exec('adb', ['-s', deviceId, 'shell', 'rm', DEVICE_TMP_PATH]);\n } catch {}\n try {\n if (fs.existsSync(localTmp)) fs.unlinkSync(localTmp);\n } catch {}\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { Shell } from '../types.js';\n\nexport async function captureIosScreenshot(\n shell: Shell,\n deviceId: string,\n tmpPath?: string,\n): Promise<Buffer> {\n const screenshotPath = tmpPath ?? path.join(os.tmpdir(), `driftx-ios-${Date.now()}.png`);\n await shell.exec('xcrun', ['simctl', 'io', deviceId, 'screenshot', screenshotPath]);\n\n if (!fs.existsSync(screenshotPath)) {\n throw new Error(`iOS screenshot not created at ${screenshotPath}`);\n }\n const buffer = fs.readFileSync(screenshotPath);\n if (!tmpPath) fs.unlinkSync(screenshotPath);\n if (buffer.length === 0) throw new Error('iOS screenshot capture returned empty file');\n return buffer;\n}\n","import type { DeviceInfo, Shell } from '../types.js';\nimport { captureAndroidScreenshot } from './android-capture.js';\nimport { captureIosScreenshot } from './ios-capture.js';\nimport { getLogger } from '../logger.js';\nimport pixelmatch from 'pixelmatch';\nimport { PNG } from 'pngjs';\n\nexport function isScreenSettled(buf1: Buffer, buf2: Buffer, maxDelta: number): boolean {\n const img1 = PNG.sync.read(buf1);\n const img2 = PNG.sync.read(buf2);\n if (img1.width !== img2.width || img1.height !== img2.height) return false;\n const diffPixels = pixelmatch(img1.data, img2.data, undefined, img1.width, img1.height, {\n threshold: 0.1,\n });\n const totalPixels = img1.width * img1.height;\n return diffPixels / totalPixels <= maxDelta;\n}\n\nexport interface CaptureOptions {\n settleCheck?: boolean;\n settleMaxDelta?: number;\n settleDelayMs?: number;\n settleMaxAttempts?: number;\n timeout?: number;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function captureScreenshot(\n shell: Shell,\n device: DeviceInfo,\n options?: CaptureOptions,\n): Promise<Buffer> {\n const logger = getLogger();\n const captureOnce = async (): Promise<Buffer> => {\n if (device.platform === 'android') {\n return captureAndroidScreenshot(shell, device.id, options?.timeout);\n }\n return captureIosScreenshot(shell, device.id);\n };\n\n let buffer = await captureOnce();\n\n if (options?.settleCheck) {\n const maxDelta = options.settleMaxDelta ?? 0.001;\n const delayMs = options.settleDelayMs ?? 300;\n const maxAttempts = options.settleMaxAttempts ?? 5;\n\n for (let i = 0; i < maxAttempts; i++) {\n await delay(delayMs);\n const next = await captureOnce();\n if (isScreenSettled(buffer, next, maxDelta)) {\n logger.debug(`Screen settled after ${i + 1} check(s)`);\n return next;\n }\n buffer = next;\n }\n logger.warn('Screen did not settle within max attempts, using last capture');\n }\n\n return buffer;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { nanoid } from 'nanoid';\n\nexport interface RunHandle {\n runId: string;\n dir: string;\n}\n\nexport class RunStore {\n private baseDir: string;\n\n constructor(projectRoot: string) {\n this.baseDir = path.join(projectRoot, '.driftx', 'runs');\n }\n\n createRun(): RunHandle {\n const runId = nanoid(12);\n const dir = path.join(this.baseDir, runId);\n fs.mkdirSync(dir, { recursive: true });\n return { runId, dir };\n }\n\n private getRunDir(runId: string): string {\n return path.join(this.baseDir, runId);\n }\n\n async writeMetadata(runId: string, metadata: Record<string, unknown>): Promise<void> {\n const filePath = path.join(this.getRunDir(runId), 'metadata.json');\n fs.writeFileSync(filePath, JSON.stringify(metadata, null, 2));\n }\n\n async writeArtifact(runId: string, relativePath: string, data: Buffer): Promise<void> {\n const filePath = path.join(this.getRunDir(runId), relativePath);\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, data);\n }\n\n listRuns(): string[] {\n if (!fs.existsSync(this.baseDir)) return [];\n return fs.readdirSync(this.baseDir).filter((f) => {\n return fs.statSync(path.join(this.baseDir, f)).isDirectory();\n });\n }\n\n getRunPath(runId: string, relativePath?: string): string {\n const dir = this.getRunDir(runId);\n return relativePath ? path.join(dir, relativePath) : dir;\n }\n\n readArtifact(runId: string, relativePath: string): Buffer | null {\n const fullPath = path.join(this.getRunDir(runId), relativePath);\n try {\n return fs.readFileSync(fullPath);\n } catch {\n return null;\n }\n }\n\n getLatestRun(): string | undefined {\n const runs = this.listRuns();\n if (runs.length === 0) return undefined;\n let latest: string | undefined;\n let latestTime = 0;\n for (const runId of runs) {\n try {\n const stat = fs.statSync(this.getRunDir(runId));\n if (stat.mtimeMs > latestTime) {\n latestTime = stat.mtimeMs;\n latest = runId;\n }\n } catch {\n continue;\n }\n }\n return latest;\n }\n}\n","import type { RetryPolicy } from './types.js';\n\nfunction isRetryable(error: Error, policy: RetryPolicy): boolean {\n return policy.retryableErrors.some((pattern) => error.message.includes(pattern));\n}\n\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error('Aborted'));\n return;\n }\n\n const timer = setTimeout(resolve, ms);\n\n signal?.addEventListener('abort', () => {\n clearTimeout(timer);\n reject(new Error('Aborted'));\n }, { once: true });\n });\n}\n\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n policy: RetryPolicy,\n signal?: AbortSignal,\n): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < policy.maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n if (!isRetryable(lastError, policy)) {\n throw lastError;\n }\n\n if (signal?.aborted) {\n throw lastError;\n }\n\n if (attempt < policy.maxAttempts - 1) {\n const backoff = Math.min(\n policy.baseDelayMs * Math.pow(policy.backoffMultiplier, attempt),\n policy.maxDelayMs,\n );\n\n try {\n await delay(backoff, signal);\n } catch {\n throw lastError;\n }\n }\n }\n }\n\n throw lastError;\n}\n","import { select } from '@inquirer/prompts';\nimport type { DeviceInfo } from '../types.js';\n\nexport async function pickDevice(booted: DeviceInfo[]): Promise<DeviceInfo> {\n if (booted.length === 1) return booted[0];\n\n if (!process.stdout.isTTY) {\n const list = booted.map((d) => ` - \"${d.name}\" (${d.platform}, ${d.id})`).join('\\n');\n throw new Error(\n `Multiple booted devices found. Use --device to specify one:\\n${list}`,\n );\n }\n\n const selected = await select({\n message: 'Select a device',\n choices: booted.map((d) => ({\n name: `${d.name} (${d.platform}, ${d.osVersion || 'unknown'})`,\n value: d.id,\n })),\n });\n\n return booted.find((d) => d.id === selected)!;\n}\n","import type { ComponentNode, BoundingBox, Shell } from '../types.js';\n\nfunction parseBounds(boundsStr: string): BoundingBox {\n const match = boundsStr.match(/\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]/);\n if (!match) return { x: 0, y: 0, width: 0, height: 0 };\n const [, x1, y1, x2, y2] = match.map(Number);\n return { x: x1, y: y1, width: x2 - x1, height: y2 - y1 };\n}\n\nfunction parseNode(nodeStr: string, idCounter: { n: number }): { node: ComponentNode; remaining: string } | null {\n const attrMatch = nodeStr.match(/^<node\\s+([^>]*?)(\\/?>)/);\n if (!attrMatch) return null;\n\n const attrs = attrMatch[1];\n const selfClosing = attrMatch[2] === '/>';\n const afterTag = nodeStr.slice(attrMatch[0].length);\n\n const get = (name: string): string => {\n const m = attrs.match(new RegExp(`${name}=\"([^\"]*)\"`));\n return m ? m[1] : '';\n };\n\n const id = String(idCounter.n++);\n const resourceId = get('resource-id');\n const className = get('class');\n\n const node: ComponentNode = {\n id,\n name: className || 'unknown',\n nativeName: className || undefined,\n testID: resourceId || undefined,\n bounds: parseBounds(get('bounds')),\n text: get('text') || undefined,\n children: [],\n inspectionTier: 'basic',\n };\n\n if (selfClosing) {\n return { node, remaining: afterTag };\n }\n\n let rest = afterTag;\n while (true) {\n rest = rest.replace(/^\\s+/, '');\n if (rest.startsWith('</node>')) {\n rest = rest.slice('</node>'.length);\n break;\n }\n const child = parseNode(rest, idCounter);\n if (!child) break;\n node.children.push(child.node);\n rest = child.remaining;\n }\n\n return { node, remaining: rest };\n}\n\nexport function parseUiAutomatorXml(xml: string): ComponentNode[] {\n if (!xml.includes('<hierarchy')) {\n throw new Error('Invalid UIAutomator XML: missing <hierarchy> element');\n }\n\n const hierarchyMatch = xml.match(/<hierarchy[^>]*>([\\s\\S]*)<\\/hierarchy>/);\n if (!hierarchyMatch) return [];\n\n const content = hierarchyMatch[1].trim();\n if (!content) return [];\n\n const nodes: ComponentNode[] = [];\n const idCounter = { n: 0 };\n let remaining = content;\n\n while (remaining.trim()) {\n remaining = remaining.replace(/^\\s+/, '');\n if (!remaining.startsWith('<node')) break;\n const result = parseNode(remaining, idCounter);\n if (!result) break;\n nodes.push(result.node);\n remaining = result.remaining;\n }\n\n return nodes;\n}\n\nexport async function dumpUiAutomator(shell: Shell, deviceId: string, timeout?: number): Promise<ComponentNode[]> {\n const { stdout } = await shell.exec('adb', ['-s', deviceId, 'exec-out', 'uiautomator', 'dump', '/dev/tty'], timeout ? { timeout } : undefined);\n return parseUiAutomatorXml(stdout);\n}\n","import type { ComponentNode, Shell } from '../types.js';\nimport { getLogger } from '../logger.js';\n\ninterface AXElement {\n frame?: { x: number; y: number; width: number; height: number };\n role?: string;\n label?: string;\n identifier?: string;\n children?: AXElement[];\n}\n\nfunction parseElement(el: AXElement, idCounter: { n: number }): ComponentNode {\n const id = String(idCounter.n++);\n return {\n id,\n name: el.role ?? 'unknown',\n nativeName: el.role,\n testID: el.identifier || undefined,\n bounds: el.frame\n ? { x: el.frame.x, y: el.frame.y, width: el.frame.width, height: el.frame.height }\n : { x: 0, y: 0, width: 0, height: 0 },\n text: el.label || undefined,\n children: (el.children ?? []).map((c) => parseElement(c, idCounter)),\n inspectionTier: 'basic',\n };\n}\n\nexport function parseIosAccessibility(json: string): ComponentNode[] {\n const data = JSON.parse(json);\n const elements: AXElement[] = data.AXElements ?? [];\n const idCounter = { n: 0 };\n return elements.map((el) => parseElement(el, idCounter));\n}\n\nexport async function dumpIosAccessibility(shell: Shell, deviceId: string, timeout?: number): Promise<ComponentNode[]> {\n const logger = getLogger();\n const opts = timeout ? { timeout } : undefined;\n\n // Try idb (Facebook's iOS Development Bridge) if available\n try {\n const { stdout } = await shell.exec('idb', ['ui', 'describe-all', '--udid', deviceId], opts);\n return parseIosAccessibility(stdout);\n } catch {\n logger.debug('idb not available, skipping iOS accessibility tree');\n }\n\n throw new Error('iOS accessibility inspection requires idb (brew install idb-companion && pip install fb-idb) or React DevTools');\n}\n","import WebSocket from 'ws';\nimport http from 'node:http';\nimport type { ComponentNode, InspectionCapabilities } from '../types.js';\nimport { getLogger } from '../logger.js';\n\nexport interface CdpTarget {\n id: string;\n title: string;\n description: string;\n appId?: string;\n webSocketDebuggerUrl: string;\n deviceName?: string;\n reactNative?: {\n logicalDeviceId: string;\n };\n}\n\ninterface CdpResponse {\n id: number;\n result?: {\n result?: {\n type: string;\n value?: unknown;\n };\n exceptionDetails?: unknown;\n };\n error?: { message: string };\n}\n\nconst FIBER_WALK_SCRIPT = `(function() {\n try {\n var hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;\n if (!hook || !hook.renderers || hook.renderers.size === 0) return JSON.stringify(null);\n\n var flat = [];\n hook.renderers.forEach(function(renderer, id) {\n var roots = hook.getFiberRoots(id);\n if (!roots) return;\n roots.forEach(function(root) {\n if (root.current) flattenFiber(root.current, 0);\n });\n });\n\n return flat.length > 0 ? JSON.stringify(flat) : JSON.stringify(null);\n } catch(e) {\n return JSON.stringify(null);\n }\n\n function getName(fiber) {\n if (typeof fiber.type === 'string') return fiber.type;\n if (fiber.type && fiber.type.displayName) return fiber.type.displayName;\n if (fiber.type && fiber.type.name) return fiber.type.name;\n if (fiber.tag === 3) return null;\n return null;\n }\n\n function isNoise(name, fiber) {\n if (!name) return true;\n if (fiber.tag === 6) return true;\n var props = fiber.memoizedProps || {};\n var hasSignal = props.testID || props.nativeID || typeof props.children === 'string';\n if (hasSignal) return false;\n if (name === 'Unknown') return true;\n if (fiber.tag === 5) return true;\n if (name.substring(0, 3) === 'RCT' || name.substring(0, 5) === 'RNSVG') return true;\n if (name.indexOf('ViewManagerAdapter_') === 0) return true;\n var len = name.length;\n if (len > 7 && name.indexOf('Context', len - 7) === len - 7) return true;\n if (len > 8 && name.indexOf('Provider', len - 8) === len - 8) return true;\n if (len > 8 && name.indexOf('Consumer', len - 8) === len - 8) return true;\n var c = name.charCodeAt(0);\n if (c >= 97 && c <= 122) return true;\n if (name.indexOf('Animated(') === 0) return true;\n return false;\n }\n\n function flattenFiber(fiber, depth) {\n if (!fiber) return;\n var name = getName(fiber);\n var noise = isNoise(name, fiber);\n\n if (!noise) {\n var props = fiber.memoizedProps || {};\n var testID = props.testID || props.nativeID || undefined;\n var text = typeof props.children === 'string' ? props.children : undefined;\n flat.push({ n: name, d: depth, t: testID, x: text });\n var child = fiber.child;\n while (child) { flattenFiber(child, depth + 1); child = child.sibling; }\n } else {\n var child = fiber.child;\n while (child) { flattenFiber(child, depth); child = child.sibling; }\n }\n }\n})()`;\n\nexport async function discoverTargets(metroPort: number): Promise<CdpTarget[]> {\n return new Promise((resolve, reject) => {\n const req = http.get(`http://localhost:${metroPort}/json/list`, { timeout: 2000 }, (res) => {\n let data = '';\n res.on('data', (chunk: Buffer) => { data += chunk; });\n res.on('end', () => {\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve([]);\n }\n });\n });\n req.on('error', () => resolve([]));\n req.on('timeout', () => { req.destroy(); resolve([]); });\n });\n}\n\nexport function findRuntimeTarget(targets: CdpTarget[], deviceName?: string): CdpTarget | undefined {\n const rnTargets = targets.filter((t) => !!t.reactNative);\n\n if (deviceName) {\n return rnTargets.find((t) =>\n t.deviceName?.toLowerCase().includes(deviceName.toLowerCase()),\n );\n }\n\n return rnTargets[0];\n}\n\nexport class CdpClient {\n private ws: WebSocket | null = null;\n private connected = false;\n private msgId = 0;\n private pending = new Map<number, { resolve: (v: CdpResponse) => void; reject: (e: Error) => void }>();\n\n async connectAndGetTree(metroPort: number, timeoutMs: number, deviceName?: string): Promise<ComponentNode[]> {\n const logger = getLogger();\n\n const targets = await discoverTargets(metroPort);\n const target = findRuntimeTarget(targets, deviceName);\n if (!target) {\n logger.debug('No React Native debug target found via Metro');\n return [];\n }\n\n logger.debug(`Found CDP target: ${target.title} (${target.description})`);\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.cleanup();\n resolve([]);\n }, timeoutMs);\n\n try {\n this.ws = new WebSocket(target.webSocketDebuggerUrl);\n } catch {\n clearTimeout(timer);\n resolve([]);\n return;\n }\n\n this.ws.on('open', async () => {\n this.connected = true;\n try {\n const result = await this.evaluate(FIBER_WALK_SCRIPT);\n clearTimeout(timer);\n resolve(this.parseResult(result));\n } catch {\n clearTimeout(timer);\n resolve([]);\n }\n });\n\n this.ws.on('message', (data: Buffer) => {\n try {\n const msg: CdpResponse = JSON.parse(data.toString());\n if (msg.id !== undefined) {\n const p = this.pending.get(msg.id);\n if (p) {\n this.pending.delete(msg.id);\n p.resolve(msg);\n }\n }\n } catch {}\n });\n\n this.ws.on('error', () => {\n clearTimeout(timer);\n resolve([]);\n });\n\n this.ws.on('close', () => {\n this.connected = false;\n });\n });\n }\n\n private evaluate(expression: string): Promise<CdpResponse> {\n const id = ++this.msgId;\n return new Promise((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n this.ws!.send(JSON.stringify({\n id,\n method: 'Runtime.evaluate',\n params: { expression, returnByValue: true },\n }));\n });\n }\n\n private parseResult(response: CdpResponse): ComponentNode[] {\n const value = response.result?.result?.value;\n if (!value || typeof value !== 'string') return [];\n\n const parsed = JSON.parse(value);\n if (!Array.isArray(parsed)) return [];\n\n return this.optimize(this.rebuildTree(parsed));\n }\n\n private optimize(roots: ComponentNode[]): ComponentNode[] {\n let tree = roots;\n let prevCount = -1;\n for (let i = 0; i < 10; i++) {\n tree = this.dedup(tree);\n tree = this.pruneLeaves(tree);\n const count = this.countNodes(tree);\n if (count === prevCount) break;\n prevCount = count;\n }\n return tree;\n }\n\n private countNodes(nodes: ComponentNode[]): number {\n let c = 0;\n for (const n of nodes) c += 1 + this.countNodes(n.children);\n return c;\n }\n\n private pruneLeaves(nodes: ComponentNode[]): ComponentNode[] {\n return nodes.reduce<ComponentNode[]>((acc, node) => {\n node.children = this.pruneLeaves(node.children);\n if (node.children.length === 0 && !node.testID && !node.text) return acc;\n acc.push(node);\n return acc;\n }, []);\n }\n\n private rebuildTree(flat: Array<{ n: string; d: number; t?: string; x?: string }>): ComponentNode[] {\n const roots: ComponentNode[] = [];\n const stack: ComponentNode[] = [];\n let id = 0;\n\n for (const entry of flat) {\n const node: ComponentNode = {\n id: String(id++),\n name: entry.n,\n reactName: entry.n,\n testID: entry.t || undefined,\n bounds: { x: 0, y: 0, width: 0, height: 0 },\n text: entry.x || undefined,\n children: [],\n inspectionTier: 'detailed',\n };\n\n while (stack.length > entry.d) stack.pop();\n\n if (stack.length === 0) {\n roots.push(node);\n } else {\n stack[stack.length - 1].children.push(node);\n }\n stack.push(node);\n }\n\n return roots;\n }\n\n private dedup(nodes: ComponentNode[]): ComponentNode[] {\n return nodes.map((node) => this.dedupNode(node)).filter(Boolean) as ComponentNode[];\n }\n\n private dedupNode(node: ComponentNode): ComponentNode | null {\n node.children = this.dedup(node.children);\n if (node.children.length === 1) {\n const child = node.children[0];\n const sameText = node.text && child.text && node.text === child.text;\n const sameTestID = node.testID && child.testID && node.testID === child.testID;\n if (sameText || sameTestID) {\n child.children = [...child.children];\n return child;\n }\n const nodeHasSignal = node.testID || node.text;\n if (!nodeHasSignal) {\n child.children = [...child.children];\n return child;\n }\n }\n return node;\n }\n\n getCapabilities(): InspectionCapabilities {\n return {\n tree: this.connected ? 'detailed' : 'none',\n sourceMapping: this.connected ? 'partial' : 'none',\n styles: this.connected ? 'partial' : 'none',\n protocol: 'cdp',\n };\n }\n\n async disconnect(): Promise<void> {\n this.cleanup();\n }\n\n private cleanup(): void {\n if (this.ws) {\n try { this.ws.close(); } catch {}\n this.ws = null;\n }\n this.connected = false;\n for (const [, p] of this.pending) {\n p.reject(new Error('disconnected'));\n }\n this.pending.clear();\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { StrategyMethod } from './tree-inspector.js';\n\nexport interface CachedEntry {\n method: StrategyMethod;\n reason: string;\n appId?: string;\n timestamp: number;\n}\n\nexport class StrategyCache {\n private filePath: string;\n private ttlMs: number;\n private entries: Map<string, CachedEntry>;\n\n constructor(projectRoot: string, ttlMs: number = 60_000) {\n this.filePath = path.join(projectRoot, '.driftx', 'strategy-cache.json');\n this.ttlMs = ttlMs;\n this.entries = this.load();\n }\n\n get(deviceId: string): CachedEntry | undefined {\n const entry = this.entries.get(deviceId);\n if (!entry) return undefined;\n if (Date.now() - entry.timestamp > this.ttlMs) {\n this.entries.delete(deviceId);\n this.persist();\n return undefined;\n }\n return entry;\n }\n\n set(deviceId: string, method: StrategyMethod, reason: string, appId?: string): void {\n this.entries.set(deviceId, { method, reason, appId, timestamp: Date.now() });\n this.persist();\n }\n\n delete(deviceId: string): void {\n this.entries.delete(deviceId);\n this.persist();\n }\n\n clear(): void {\n this.entries.clear();\n this.persist();\n }\n\n private load(): Map<string, CachedEntry> {\n try {\n const raw = fs.readFileSync(this.filePath, 'utf-8');\n const data: Record<string, CachedEntry> = JSON.parse(raw);\n return new Map(Object.entries(data));\n } catch {\n return new Map();\n }\n }\n\n private persist(): void {\n try {\n const dir = path.dirname(this.filePath);\n fs.mkdirSync(dir, { recursive: true });\n const obj: Record<string, CachedEntry> = Object.fromEntries(this.entries);\n fs.writeFileSync(this.filePath, JSON.stringify(obj, null, 2));\n } catch {\n // best-effort — don't break inspection if cache write fails\n }\n }\n}\n","import type { Shell, DeviceInfo, ComponentNode, InspectionCapabilities } from '../types.js';\nimport { dumpUiAutomator } from './uiautomator.js';\nimport { dumpIosAccessibility } from './ios-accessibility.js';\nimport { CdpClient, discoverTargets, findRuntimeTarget } from './cdp-client.js';\nimport type { CdpTarget } from './cdp-client.js';\nimport { StrategyCache } from './strategy-cache.js';\nimport { getLogger } from '../logger.js';\n\nexport interface InspectOptions {\n metroPort: number;\n devToolsPort: number;\n timeoutMs: number;\n}\n\nexport type StrategyMethod = 'cdp' | 'uiautomator' | 'idb' | 'none';\n\nexport interface InspectionStrategy {\n method: StrategyMethod;\n reason: string;\n appId?: string;\n cdpTarget?: CdpTarget;\n}\n\nexport interface InspectResult {\n tree: ComponentNode[];\n capabilities: InspectionCapabilities;\n strategy: InspectionStrategy;\n device: { name: string; platform: 'android' | 'ios' };\n hints: string[];\n}\n\nexport class TreeInspector {\n private shell: Shell;\n private fileCache: StrategyCache | null;\n\n constructor(shell: Shell, projectRoot?: string) {\n this.shell = shell;\n this.fileCache = projectRoot ? new StrategyCache(projectRoot) : null;\n }\n\n invalidateCache(deviceId?: string): void {\n if (!this.fileCache) return;\n if (deviceId) {\n this.fileCache.delete(deviceId);\n } else {\n this.fileCache.clear();\n }\n }\n\n async resolveStrategy(device: DeviceInfo, options: InspectOptions): Promise<InspectionStrategy> {\n if (options.metroPort > 0) {\n const targets = await discoverTargets(options.metroPort);\n const target = findRuntimeTarget(targets, device.name);\n if (target) {\n return {\n method: 'cdp',\n reason: 'React Native app connected via Metro',\n appId: target.appId,\n cdpTarget: target,\n };\n }\n }\n\n if (device.platform === 'android') {\n return { method: 'uiautomator', reason: 'Android native inspection' };\n }\n\n return { method: 'idb', reason: 'iOS native inspection via idb' };\n }\n\n async inspect(device: DeviceInfo, options: InspectOptions): Promise<InspectResult> {\n const logger = getLogger();\n const hints: string[] = [];\n let usedCache = false;\n\n const cachedEntry = this.fileCache?.get(device.id);\n let strategy: InspectionStrategy;\n\n if (cachedEntry && cachedEntry.method !== 'none') {\n logger.debug(`Using cached strategy for ${device.name}: ${cachedEntry.method}`);\n usedCache = true;\n if (cachedEntry.method === 'cdp' && options.metroPort > 0) {\n const targets = await discoverTargets(options.metroPort);\n const target = findRuntimeTarget(targets, device.name);\n strategy = target\n ? { method: 'cdp', reason: cachedEntry.reason, appId: target.appId, cdpTarget: target }\n : await this.resolveStrategy(device, options);\n } else {\n strategy = { method: cachedEntry.method, reason: cachedEntry.reason, appId: cachedEntry.appId };\n }\n } else {\n strategy = await this.resolveStrategy(device, options);\n }\n\n this.fileCache?.set(device.id, strategy.method, strategy.reason, strategy.appId);\n\n const base = { device: { name: device.name, platform: device.platform }, strategy };\n\n if (strategy.method === 'cdp' && strategy.cdpTarget) {\n try {\n const cdp = new CdpClient();\n const tree = await cdp.connectAndGetTree(\n options.metroPort, options.timeoutMs, device.name,\n );\n const caps = cdp.getCapabilities();\n await cdp.disconnect();\n if (tree.length > 0) {\n logger.debug(`CDP: got ${tree.length} root nodes for ${device.name}`);\n return { ...base, tree, capabilities: caps, hints };\n }\n } catch (err) {\n logger.debug(`CDP failed: ${err instanceof Error ? err.message : err}`);\n }\n logger.debug('CDP strategy resolved but returned no tree, falling back to native');\n }\n\n if (strategy.method === 'uiautomator' || (strategy.method === 'cdp' && device.platform === 'android')) {\n try {\n const tree = await dumpUiAutomator(this.shell, device.id, options.timeoutMs);\n logger.debug(`UIAutomator: got ${tree.length} root nodes for ${device.name}`);\n return {\n ...base,\n strategy: { method: 'uiautomator', reason: strategy.method === 'cdp' ? 'CDP fallback to native' : strategy.reason },\n tree,\n capabilities: { tree: 'basic', sourceMapping: 'none', styles: 'none', protocol: 'uiautomator' },\n hints,\n };\n } catch (err) {\n logger.debug(`UIAutomator failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n if (strategy.method === 'idb' || (strategy.method === 'cdp' && device.platform === 'ios')) {\n try {\n const tree = await dumpIosAccessibility(this.shell, device.id, options.timeoutMs);\n logger.debug(`idb: got ${tree.length} root nodes for ${device.name}`);\n return {\n ...base,\n strategy: { method: 'idb', reason: strategy.method === 'cdp' ? 'CDP fallback to native' : strategy.reason },\n tree,\n capabilities: { tree: 'basic', sourceMapping: 'none', styles: 'none', protocol: 'idb' },\n hints,\n };\n } catch (err) {\n logger.debug(`iOS accessibility failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n\n if (device.platform === 'ios') {\n hints.push('Install idb for native iOS tree inspection: brew install idb-companion && pip install fb-idb');\n }\n\n if (usedCache) {\n this.fileCache?.delete(device.id);\n logger.debug(`Invalidated cached strategy for ${device.name} after complete failure`);\n }\n\n return {\n ...base,\n strategy: { method: 'none', reason: 'No inspection method available' },\n tree: [],\n capabilities: { tree: 'none', sourceMapping: 'none', styles: 'none', protocol: 'none' },\n hints,\n };\n }\n}\n","import pc from 'picocolors';\nimport type { DiffFinding, DiffRegion, ComponentNode } from '../types.js';\nimport type { OutputFormatter, CompareFormatData } from './types.js';\nimport type { AnalysisResult } from '../analyses/types.js';\n\nfunction confidenceLabel(confidence: number): string {\n if (confidence >= 0.8) return 'high';\n if (confidence >= 0.5) return 'probable';\n return 'approximate';\n}\n\nfunction severityColor(severity: DiffFinding['severity'], text: string): string {\n if (severity === 'critical') return pc.red(pc.bold(text));\n if (severity === 'major') return pc.yellow(text);\n if (severity === 'minor') return pc.cyan(text);\n return pc.dim(text);\n}\n\nfunction severityCounts(findings: DiffFinding[]): string {\n const counts: Record<string, number> = {};\n for (const f of findings) {\n counts[f.severity] = (counts[f.severity] ?? 0) + 1;\n }\n const parts: string[] = [];\n for (const sev of ['critical', 'major', 'minor', 'info'] as const) {\n if (counts[sev]) parts.push(`${counts[sev]} ${sev}`);\n }\n return parts.join(', ');\n}\n\nfunction formatTreePlain(nodes: ComponentNode[], indent: number = 0): string {\n const lines: string[] = [];\n for (const node of nodes) {\n const prefix = ' '.repeat(indent);\n const name = node.reactName ?? node.name;\n const testId = node.testID ? ` [${node.testID}]` : '';\n const text = node.text ? ` \"${node.text}\"` : '';\n const b = node.bounds;\n const bounds = b.width > 0 ? ` (${b.x},${b.y} ${b.width}x${b.height})` : '';\n lines.push(`${prefix}${name}${testId}${text}${bounds}`);\n const childStr = formatTreePlain(node.children, indent + 1);\n if (childStr) lines.push(childStr);\n }\n return lines.join('\\n');\n}\n\nfunction getPixelMeta(analyses: AnalysisResult[]): {\n diffPercentage: number;\n diffPixels: number;\n totalPixels: number;\n regions: DiffRegion[];\n} {\n const pixel = analyses.find((a) => a.analysisName === 'pixel');\n const meta = pixel?.metadata as Record<string, unknown> | undefined;\n return {\n diffPercentage: (meta?.diffPercentage as number) ?? 0,\n diffPixels: (meta?.diffPixels as number) ?? 0,\n totalPixels: (meta?.totalPixels as number) ?? 0,\n regions: (meta?.regions as DiffRegion[]) ?? [],\n };\n}\n\nexport const compareFormatter: OutputFormatter<CompareFormatData> = {\n terminal(data) {\n const { report } = data;\n const pm = getPixelMeta(report.analyses);\n const lines: string[] = [];\n lines.push('');\n lines.push(` Diff: ${pm.diffPercentage.toFixed(2)}% (${pm.diffPixels.toLocaleString()}/${pm.totalPixels.toLocaleString()} pixels)`);\n if (pm.regions.length > 0) lines.push(` Regions: ${pm.regions.length}`);\n lines.push(` Duration: ${report.durationMs}ms`);\n\n for (const a of report.analyses) {\n lines.push(` [${a.analysisName}] ${a.summary}`);\n }\n\n if (report.findings.length === 0) {\n lines.push('');\n lines.push(pc.green(' No differences found.'));\n lines.push('');\n lines.push(` Run: ${report.runId}`);\n lines.push('');\n return lines.join('\\n');\n }\n\n lines.push('');\n lines.push(' Findings');\n lines.push(' ' + '─'.repeat(70));\n\n for (const f of report.findings) {\n const tag = severityColor(f.severity, `[${f.severity.toUpperCase()}]`);\n const comp = f.component\n ? `${f.component.name}${f.component.testID ? ` [${f.component.testID}]` : ''}`\n : pc.dim('(unmatched)');\n const region = `(${f.region.x},${f.region.y} ${f.region.width}x${f.region.height})`;\n const conf = `(${confidenceLabel(f.confidence)})`;\n lines.push(` ${tag} ${f.id} ${comp} ${region} ${conf}`);\n }\n\n lines.push('');\n lines.push(` Summary: Found ${report.findings.length} differences (${severityCounts(report.findings)})`);\n lines.push('');\n lines.push(` Run: ${report.runId}`);\n lines.push('');\n return lines.join('\\n');\n },\n\n markdown(data) {\n const { report, device, artifactDir } = data;\n const pm = getPixelMeta(report.analyses);\n const lines: string[] = ['# Driftx Compare Report', ''];\n\n if (device) lines.push(`**Device:** ${device.name} (${device.platform})`);\n const meta = report.metadata;\n if (meta.gitCommit || meta.gitBranch) {\n const git = [meta.gitCommit, meta.gitBranch].filter(Boolean).join(' on ');\n lines.push(`**Git:** ${git}`);\n }\n if (meta.framework && meta.framework !== 'unknown') lines.push(`**Framework:** ${meta.framework}`);\n lines.push(`**Diff:** ${pm.diffPercentage.toFixed(2)}% (${pm.diffPixels.toLocaleString()} / ${pm.totalPixels.toLocaleString()} pixels)`);\n if (pm.regions.length > 0) lines.push(`**Regions:** ${pm.regions.length}`);\n lines.push(`**Duration:** ${report.durationMs}ms`);\n lines.push(`**Run ID:** ${report.runId}`);\n\n if (report.analyses.length > 0) {\n lines.push('', '## Analyses', '');\n for (const a of report.analyses) {\n lines.push(`- **${a.analysisName}** (${a.durationMs}ms): ${a.summary}`);\n }\n }\n\n if (report.findings.length === 0) {\n lines.push('', 'No differences found.');\n return lines.join('\\n');\n }\n\n lines.push('', '## Artifacts', '');\n lines.push(`- Screenshot: \\`${artifactDir}/screenshot.png\\``);\n lines.push(`- Design: \\`${artifactDir}/design.png\\``);\n lines.push(`- Diff mask: \\`${artifactDir}/diff-mask.png\\``);\n\n lines.push('', '## Findings');\n\n report.findings.forEach((f, i) => {\n const compName = f.component?.name ?? 'Unmatched region';\n lines.push('', `### ${i + 1}. [${f.severity.toUpperCase()}] ${compName} (${f.id})`, '');\n if (f.component) {\n lines.push(`- **Component:** ${f.component.name}`);\n if (f.component.testID) lines.push(`- **testID:** ${f.component.testID}`);\n }\n lines.push(`- **Category:** ${f.category}`);\n lines.push(`- **Region:** (${f.region.x}, ${f.region.y}) ${f.region.width}x${f.region.height}`);\n lines.push(`- **Confidence:** ${confidenceLabel(f.confidence)}`);\n if (f.evidence.length > 0) {\n lines.push('- **Evidence:**');\n for (const e of f.evidence) {\n lines.push(` - ${e.type}: ${Math.round(e.score * 100)}% score — \"${e.note}\"`);\n }\n }\n const regionId = pm.regions[i]?.id;\n if (regionId) lines.push(`- **Region crop:** \\`${artifactDir}/regions/${regionId}.png\\``);\n });\n\n if (data.tree && data.tree.length > 0) {\n lines.push('', '## Component Tree Context', '', '```');\n lines.push(formatTreePlain(data.tree));\n lines.push('```');\n }\n\n if (data.inspectHints && data.inspectHints.length > 0) {\n lines.push('', '## Hints', '');\n for (const hint of data.inspectHints) {\n lines.push(`- ${hint}`);\n }\n }\n\n return lines.join('\\n');\n },\n\n json(data) {\n return JSON.stringify({\n report: data.report,\n device: data.device,\n artifactDir: data.artifactDir,\n }, null, 2);\n },\n};\n","import sharp from 'sharp';\nimport { readFileSync } from 'node:fs';\nimport type { DriftxImage, AnalysisConfig } from './types.js';\n\nexport async function buildDriftxImage(filePath: string): Promise<DriftxImage> {\n const buffer = readFileSync(filePath);\n const image = sharp(buffer);\n const metadata = await image.metadata();\n const width = metadata.width!;\n const height = metadata.height!;\n const rawPixels = await image.raw().ensureAlpha().toBuffer();\n\n return {\n buffer,\n rawPixels,\n width,\n height,\n aspectRatio: width / height,\n path: filePath,\n };\n}\n\nexport function buildAnalysisConfig(\n configAnalyses: { default: string[]; disabled: string[]; options: Record<string, Record<string, unknown>> },\n withFlag?: string,\n withoutFlag?: string,\n): AnalysisConfig {\n const enabled = withFlag\n ? withFlag.split(',').map((s) => s.trim())\n : [...configAnalyses.default];\n\n const disabled = withoutFlag\n ? withoutFlag.split(',').map((s) => s.trim())\n : [...configAnalyses.disabled];\n\n return {\n enabled,\n disabled,\n options: configAnalyses.options,\n };\n}\n","import type { AnalysisPlugin } from './types.js';\n\nexport class AnalysisRegistry {\n private plugins = new Map<string, AnalysisPlugin>();\n\n register(plugin: AnalysisPlugin): void {\n if (this.plugins.has(plugin.name)) {\n throw new Error(`Analysis \"${plugin.name}\" already registered`);\n }\n this.plugins.set(plugin.name, plugin);\n }\n\n get(name: string): AnalysisPlugin | undefined {\n return this.plugins.get(name);\n }\n\n all(): AnalysisPlugin[] {\n return [...this.plugins.values()];\n }\n\n names(): string[] {\n return [...this.plugins.keys()];\n }\n}\n","import sharp from 'sharp';\nimport * as fs from 'node:fs';\n\nexport interface LoadedImage {\n buffer: Buffer;\n width: number;\n height: number;\n aspectRatio: number;\n rawPixels: Buffer;\n}\n\nexport async function loadImage(filePath: string): Promise<LoadedImage> {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Image not found: ${filePath}`);\n }\n\n const input = fs.readFileSync(filePath);\n const metadata = await sharp(input).metadata();\n\n if (!metadata.width || !metadata.height) {\n throw new Error(`Invalid image: could not read dimensions from ${filePath}`);\n }\n\n const rawPixels = await sharp(input)\n .ensureAlpha()\n .raw()\n .toBuffer();\n\n return {\n buffer: input,\n width: metadata.width,\n height: metadata.height,\n aspectRatio: metadata.width / metadata.height,\n rawPixels,\n };\n}\n","import sharp from 'sharp';\nimport type { LoadedImage } from './image-loader.js';\nimport { getLogger } from '../logger.js';\n\nexport interface AlignedImages {\n designPixels: Buffer;\n screenshotPixels: Buffer;\n width: number;\n height: number;\n aspectRatioWarning: boolean;\n}\n\nexport async function alignImages(design: LoadedImage, screenshot: LoadedImage): Promise<AlignedImages> {\n const targetWidth = screenshot.width;\n const targetHeight = screenshot.height;\n const logger = getLogger();\n\n const aspectDiff = Math.abs(design.aspectRatio - screenshot.aspectRatio) / screenshot.aspectRatio;\n const aspectRatioWarning = aspectDiff > 0.05;\n\n if (aspectRatioWarning) {\n logger.warn(\n `Aspect ratio divergence: design=${design.aspectRatio.toFixed(3)} screenshot=${screenshot.aspectRatio.toFixed(3)} (${(aspectDiff * 100).toFixed(1)}%)`,\n );\n }\n\n let designPixels: Buffer;\n if (design.width === targetWidth && design.height === targetHeight) {\n designPixels = design.rawPixels;\n } else {\n designPixels = await sharp(design.buffer)\n .resize(targetWidth, targetHeight, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })\n .ensureAlpha()\n .raw()\n .toBuffer();\n }\n\n return {\n designPixels,\n screenshotPixels: screenshot.rawPixels,\n width: targetWidth,\n height: targetHeight,\n aspectRatioWarning,\n };\n}\n","import pixelmatch from 'pixelmatch';\nimport type { AlignedImages } from './alignment.js';\n\nexport interface PixelDiffResult {\n diffPixels: number;\n totalPixels: number;\n diffPercentage: number;\n diffMask: Buffer;\n width: number;\n height: number;\n}\n\nexport function computePixelDiff(aligned: AlignedImages, threshold: number): PixelDiffResult {\n const { width, height, designPixels, screenshotPixels } = aligned;\n const totalPixels = width * height;\n const diffMask = Buffer.alloc(width * height * 4);\n\n const diffPixels = pixelmatch(\n designPixels, screenshotPixels, diffMask,\n width, height,\n { threshold, includeAA: false },\n );\n\n return {\n diffPixels,\n totalPixels,\n diffPercentage: totalPixels > 0 ? (diffPixels / totalPixels) * 100 : 0,\n diffMask,\n width,\n height,\n };\n}\n","import type { BoundingBox, DiffRegion } from '../types.js';\n\ninterface ExtractOptions {\n mergeGap: number;\n minArea: number;\n}\n\nfunction isDiffPixel(mask: Buffer, idx: number): boolean {\n return mask[idx] > 0 || mask[idx + 1] > 0 || mask[idx + 2] > 0;\n}\n\nfunction floodFill(\n mask: Buffer, visited: Uint8Array, width: number, height: number,\n startX: number, startY: number,\n): { bounds: BoundingBox; pixelCount: number } {\n const stack: Array<[number, number]> = [[startX, startY]];\n let minX = startX, maxX = startX, minY = startY, maxY = startY;\n let count = 0;\n\n while (stack.length > 0) {\n const [x, y] = stack.pop()!;\n const idx = y * width + x;\n\n if (x < 0 || x >= width || y < 0 || y >= height) continue;\n if (visited[idx]) continue;\n if (!isDiffPixel(mask, idx * 4)) continue;\n\n visited[idx] = 1;\n count++;\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n\n stack.push([x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]);\n }\n\n return {\n bounds: { x: minX, y: minY, width: maxX - minX + 1, height: maxY - minY + 1 },\n pixelCount: count,\n };\n}\n\nfunction shouldMerge(a: BoundingBox, b: BoundingBox, gap: number): boolean {\n const aRight = a.x + a.width + gap;\n const aBottom = a.y + a.height + gap;\n const bRight = b.x + b.width + gap;\n const bBottom = b.y + b.height + gap;\n\n return !(a.x - gap > bRight || b.x - gap > aRight || a.y - gap > bBottom || b.y - gap > aBottom);\n}\n\nfunction mergeBounds(a: BoundingBox, b: BoundingBox): BoundingBox {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return {\n x, y,\n width: Math.max(a.x + a.width, b.x + b.width) - x,\n height: Math.max(a.y + a.height, b.y + b.height) - y,\n };\n}\n\nexport function extractRegions(\n diffMask: Buffer, width: number, height: number,\n options: ExtractOptions,\n): DiffRegion[] {\n const visited = new Uint8Array(width * height);\n let rawRegions: Array<{ bounds: BoundingBox; pixelCount: number }> = [];\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const idx = y * width + x;\n if (visited[idx] || !isDiffPixel(diffMask, idx * 4)) continue;\n rawRegions.push(floodFill(diffMask, visited, width, height, x, y));\n }\n }\n\n let merged = true;\n while (merged) {\n merged = false;\n const next: typeof rawRegions = [];\n const used = new Set<number>();\n\n for (let i = 0; i < rawRegions.length; i++) {\n if (used.has(i)) continue;\n let current = rawRegions[i];\n\n for (let j = i + 1; j < rawRegions.length; j++) {\n if (used.has(j)) continue;\n if (shouldMerge(current.bounds, rawRegions[j].bounds, options.mergeGap)) {\n current = {\n bounds: mergeBounds(current.bounds, rawRegions[j].bounds),\n pixelCount: current.pixelCount + rawRegions[j].pixelCount,\n };\n used.add(j);\n merged = true;\n }\n }\n\n next.push(current);\n }\n\n rawRegions = next;\n }\n\n const totalPixels = width * height;\n return rawRegions\n .filter((r) => r.bounds.width * r.bounds.height >= options.minArea)\n .map((r, i) => ({\n id: `region-${i}`,\n bounds: r.bounds,\n pixelCount: r.pixelCount,\n percentage: totalPixels > 0 ? (r.pixelCount / totalPixels) * 100 : 0,\n }));\n}\n","import type { DiffRegion, IgnoreRule, BoundingBox, ColorRange } from '../types.js';\n\nexport interface PixelContext {\n screenshotPixels: Buffer;\n width: number;\n height: number;\n}\n\nfunction boxesOverlap(a: BoundingBox, b: BoundingBox): boolean {\n return !(\n a.x + a.width <= b.x ||\n b.x + b.width <= a.x ||\n a.y + a.height <= b.y ||\n b.y + b.height <= a.y\n );\n}\n\nfunction regionMatchesColorRange(\n region: DiffRegion,\n range: ColorRange,\n ctx: PixelContext,\n): boolean {\n const { bounds } = region;\n const endX = Math.min(bounds.x + bounds.width, ctx.width);\n const endY = Math.min(bounds.y + bounds.height, ctx.height);\n\n for (let y = bounds.y; y < endY; y++) {\n for (let x = bounds.x; x < endX; x++) {\n const idx = (y * ctx.width + x) * 4;\n const r = ctx.screenshotPixels[idx];\n const g = ctx.screenshotPixels[idx + 1];\n const b = ctx.screenshotPixels[idx + 2];\n\n if (r < range.r[0] || r > range.r[1]) return false;\n if (g < range.g[0] || g > range.g[1]) return false;\n if (b < range.b[0] || b > range.b[1]) return false;\n }\n }\n return true;\n}\n\nfunction isIgnored(region: DiffRegion, rule: IgnoreRule, ctx?: PixelContext): boolean {\n switch (rule.type) {\n case 'boundingBox':\n return boxesOverlap(region.bounds, rule.value as BoundingBox);\n case 'colorRange':\n if (!ctx) return false;\n return regionMatchesColorRange(region, rule.value as ColorRange, ctx);\n default:\n return false;\n }\n}\n\nexport function filterByIgnoreRules(\n regions: DiffRegion[],\n rules: IgnoreRule[],\n pixelContext?: PixelContext,\n): DiffRegion[] {\n if (rules.length === 0) return regions;\n return regions.filter((region) => !rules.some((rule) => isIgnored(region, rule, pixelContext)));\n}\n","import sharp from 'sharp';\n\nexport interface MaskColor {\n r: number;\n g: number;\n b: number;\n a: number;\n}\n\nexport async function generateDiffMask(\n screenshotBuffer: Buffer,\n diffMask: Buffer,\n width: number,\n height: number,\n color: MaskColor,\n): Promise<Buffer> {\n const overlay = Buffer.alloc(width * height * 4);\n const alpha = Math.round(color.a * 255);\n\n for (let i = 0; i < width * height; i++) {\n const idx = i * 4;\n const hasDiff = diffMask[idx] > 0 || diffMask[idx + 1] > 0 || diffMask[idx + 2] > 0;\n\n if (hasDiff) {\n overlay[idx] = color.r;\n overlay[idx + 1] = color.g;\n overlay[idx + 2] = color.b;\n overlay[idx + 3] = alpha;\n } else {\n overlay[idx + 3] = 0;\n }\n }\n\n const overlayPng = await sharp(overlay, { raw: { width, height, channels: 4 } })\n .png()\n .toBuffer();\n\n return sharp(screenshotBuffer)\n .composite([{ input: overlayPng, blend: 'over' }])\n .png()\n .toBuffer();\n}\n","import sharp from 'sharp';\n\nexport interface ViewportOptions {\n platform: 'android' | 'ios';\n cropStatusBar: boolean;\n statusBarHeight: { android: number; ios: number };\n cropNavigationBar: boolean;\n}\n\nexport interface CroppedResult {\n buffer: Buffer;\n width: number;\n height: number;\n}\n\nexport async function cropViewport(imageBuffer: Buffer, options: ViewportOptions): Promise<CroppedResult> {\n const metadata = await sharp(imageBuffer).metadata();\n const width = metadata.width!;\n let height = metadata.height!;\n let top = 0;\n\n if (options.cropStatusBar) {\n const barHeight = options.platform === 'android'\n ? options.statusBarHeight.android\n : options.statusBarHeight.ios;\n top = barHeight;\n height -= barHeight;\n }\n\n if (top === 0 && height === metadata.height) {\n return { buffer: imageBuffer, width, height };\n }\n\n const buffer = await sharp(imageBuffer)\n .extract({ left: 0, top, width, height })\n .png()\n .toBuffer();\n\n return { buffer, width, height };\n}\n","import type { DiffRegion, IgnoreRule } from '../types.js';\nimport { loadImage } from './image-loader.js';\nimport { alignImages } from './alignment.js';\nimport { computePixelDiff } from './pixel-diff.js';\nimport { extractRegions } from './region-extractor.js';\nimport { filterByIgnoreRules } from './ignore-rules.js';\nimport { generateDiffMask, type MaskColor } from './mask-generator.js';\nimport { cropViewport, type ViewportOptions } from './viewport.js';\nimport sharp from 'sharp';\n\nexport interface CompareOptions {\n threshold: number;\n diffThreshold: number;\n regionMergeGap: number;\n regionMinArea: number;\n ignoreRules: IgnoreRule[];\n diffMaskColor: MaskColor;\n platform: 'android' | 'ios';\n viewport?: Omit<ViewportOptions, 'platform'>;\n}\n\nexport interface CompareResult {\n totalPixels: number;\n diffPixels: number;\n diffPercentage: number;\n regions: DiffRegion[];\n diffMaskBuffer: Buffer;\n regionCrops: Array<{ id: string; buffer: Buffer }>;\n width: number;\n height: number;\n durationMs: number;\n}\n\nfunction sanitizeDiffMask(mask: Buffer, width: number, height: number): Buffer {\n const clean = Buffer.alloc(width * height * 4);\n for (let i = 0; i < width * height; i++) {\n const idx = i * 4;\n const r = mask[idx];\n const g = mask[idx + 1];\n const b = mask[idx + 2];\n if (r > 0 && g === 0 && b === 0) {\n clean[idx] = r;\n clean[idx + 1] = g;\n clean[idx + 2] = b;\n clean[idx + 3] = mask[idx + 3];\n }\n }\n return clean;\n}\n\nexport async function runComparison(\n designPath: string,\n screenshotPath: string,\n options: CompareOptions,\n): Promise<CompareResult> {\n const start = Date.now();\n\n let design = await loadImage(designPath);\n let screenshot = await loadImage(screenshotPath);\n\n if (options.viewport) {\n const vpOpts: ViewportOptions = { ...options.viewport, platform: options.platform };\n const croppedDesign = await cropViewport(design.buffer, vpOpts);\n const croppedScreenshot = await cropViewport(screenshot.buffer, vpOpts);\n\n design = {\n buffer: croppedDesign.buffer,\n width: croppedDesign.width,\n height: croppedDesign.height,\n aspectRatio: croppedDesign.width / croppedDesign.height,\n rawPixels: await sharp(croppedDesign.buffer).ensureAlpha().raw().toBuffer(),\n };\n screenshot = {\n buffer: croppedScreenshot.buffer,\n width: croppedScreenshot.width,\n height: croppedScreenshot.height,\n aspectRatio: croppedScreenshot.width / croppedScreenshot.height,\n rawPixels: await sharp(croppedScreenshot.buffer).ensureAlpha().raw().toBuffer(),\n };\n }\n\n const aligned = await alignImages(design, screenshot);\n const diff = computePixelDiff(aligned, options.threshold);\n\n const cleanMask = sanitizeDiffMask(diff.diffMask, diff.width, diff.height);\n\n let regions = extractRegions(cleanMask, diff.width, diff.height, {\n mergeGap: options.regionMergeGap,\n minArea: options.regionMinArea,\n });\n\n regions = filterByIgnoreRules(regions, options.ignoreRules);\n\n const diffMaskBuffer = await generateDiffMask(\n screenshot.buffer, cleanMask, diff.width, diff.height, options.diffMaskColor,\n );\n\n const regionCrops = await Promise.all(\n regions.map(async (r) => {\n const crop = await sharp(screenshot.buffer)\n .extract({\n left: r.bounds.x,\n top: r.bounds.y,\n width: Math.min(r.bounds.width, diff.width - r.bounds.x),\n height: Math.min(r.bounds.height, diff.height - r.bounds.y),\n })\n .png()\n .toBuffer();\n return { id: r.id, buffer: crop };\n }),\n );\n\n return {\n totalPixels: diff.totalPixels,\n diffPixels: diff.diffPixels,\n diffPercentage: diff.diffPercentage,\n regions,\n diffMaskBuffer,\n regionCrops,\n width: diff.width,\n height: diff.height,\n durationMs: Date.now() - start,\n };\n}\n","import type { DiffRegion, ComponentNode, ComponentMatch, BoundingBox } from '../types.js';\n\nexport interface RegionComponentMatch {\n regionId: string;\n component: ComponentMatch;\n confidence: number;\n overlapRatio: number;\n}\n\nfunction boxesOverlap(a: BoundingBox, b: BoundingBox): boolean {\n return !(\n a.x + a.width <= b.x ||\n b.x + b.width <= a.x ||\n a.y + a.height <= b.y ||\n b.y + b.height <= a.y\n );\n}\n\nfunction overlapArea(a: BoundingBox, b: BoundingBox): number {\n const x1 = Math.max(a.x, b.x);\n const y1 = Math.max(a.y, b.y);\n const x2 = Math.min(a.x + a.width, b.x + b.width);\n const y2 = Math.min(a.y + a.height, b.y + b.height);\n if (x2 <= x1 || y2 <= y1) return 0;\n return (x2 - x1) * (y2 - y1);\n}\n\ninterface CandidateMatch {\n node: ComponentNode;\n depth: number;\n overlapRatio: number;\n}\n\nfunction findDeepestOverlap(\n nodes: ComponentNode[],\n regionBounds: BoundingBox,\n depth: number,\n): CandidateMatch | null {\n let best: CandidateMatch | null = null;\n const regionArea = regionBounds.width * regionBounds.height;\n\n for (const node of nodes) {\n if (!boxesOverlap(node.bounds, regionBounds)) continue;\n\n const overlap = overlapArea(node.bounds, regionBounds);\n const ratio = regionArea > 0 ? overlap / regionArea : 0;\n\n if (ratio > 0.5) {\n const childMatch = findDeepestOverlap(node.children, regionBounds, depth + 1);\n if (childMatch && childMatch.overlapRatio > 0.5) {\n if (!best || childMatch.depth > best.depth) {\n best = childMatch;\n }\n } else {\n if (!best || depth > best.depth || (depth === best.depth && ratio > best.overlapRatio)) {\n best = { node, depth, overlapRatio: ratio };\n }\n }\n }\n }\n\n return best;\n}\n\nfunction computeConfidence(node: ComponentNode, overlapRatio: number): number {\n let base: number;\n if (node.inspectionTier === 'detailed') {\n base = 0.6;\n if (node.source) base = 0.8;\n } else {\n base = 0.4;\n }\n const overlapBonus = Math.min(overlapRatio * 0.2, 0.2);\n return Math.min(base + overlapBonus, node.inspectionTier === 'detailed' ? 0.95 : 0.6);\n}\n\nexport function matchRegionsToComponents(\n regions: DiffRegion[],\n tree: ComponentNode[],\n): RegionComponentMatch[] {\n const matches: RegionComponentMatch[] = [];\n\n for (const region of regions) {\n const candidate = findDeepestOverlap(tree, region.bounds, 0);\n if (!candidate) continue;\n\n const { node, depth, overlapRatio } = candidate;\n const confidence = computeConfidence(node, overlapRatio);\n\n matches.push({\n regionId: region.id,\n component: {\n name: node.reactName ?? node.name,\n testID: node.testID,\n source: node.source,\n bounds: node.bounds,\n depth,\n },\n confidence,\n overlapRatio,\n });\n }\n\n return matches;\n}\n","import type { DiffRegion, DiffFinding, DiffEvidence } from '../types.js';\nimport type { RegionComponentMatch } from './component-matcher.js';\n\nfunction classifySeverity(pixelPercentage: number): DiffFinding['severity'] {\n if (pixelPercentage >= 10) return 'critical';\n if (pixelPercentage >= 3) return 'major';\n if (pixelPercentage >= 0.5) return 'minor';\n return 'info';\n}\n\nexport function generateFindings(\n regions: DiffRegion[],\n matches: RegionComponentMatch[],\n totalPixels: number,\n): DiffFinding[] {\n const matchMap = new Map(matches.map((m) => [m.regionId, m]));\n\n return regions.map((region, i) => {\n const match = matchMap.get(region.id);\n const pixelPct = totalPixels > 0 ? (region.pixelCount / totalPixels) * 100 : 0;\n\n const evidence: DiffEvidence[] = [\n { type: 'pixel', score: pixelPct / 100, note: `${pixelPct.toFixed(1)}% pixel difference in region` },\n ];\n\n if (match) {\n evidence.push({\n type: 'tree',\n score: match.confidence,\n note: `Matched to ${match.component.name} via bounds overlap (${Math.round(match.overlapRatio * 100)}%)`,\n });\n }\n\n return {\n id: `diff-${i}`,\n category: 'unknown' as const,\n severity: classifySeverity(pixelPct),\n confidence: match?.confidence ?? 0.3,\n region: region.bounds,\n component: match?.component,\n evidence,\n };\n });\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext } from '../types.js';\nimport { runComparison } from '../../diff/compare.js';\nimport { matchRegionsToComponents } from '../../inspect/component-matcher.js';\nimport { generateFindings } from '../../inspect/finding-generator.js';\n\nexport class PixelAnalysis implements AnalysisPlugin {\n name = 'pixel';\n description = 'Pixel-level image comparison between screenshot and design';\n\n isAvailable(ctx: CompareContext): boolean {\n return !!ctx.design;\n }\n\n async run(ctx: CompareContext): Promise<AnalysisResult> {\n const start = Date.now();\n const { config } = ctx;\n const [mr, mg, mb, ma] = config.diffMaskColor;\n\n const compareResult = await runComparison(ctx.design!.path, ctx.screenshot.path, {\n threshold: config.threshold,\n diffThreshold: config.diffThreshold,\n regionMergeGap: config.regionMergeGap,\n regionMinArea: config.regionMinArea,\n ignoreRules: config.ignoreRules,\n diffMaskColor: { r: mr, g: mg, b: mb, a: ma / 255 },\n platform: config.platform,\n });\n\n await ctx.store.writeArtifact(ctx.runId, 'diff-mask.png', compareResult.diffMaskBuffer);\n for (const crop of compareResult.regionCrops) {\n await ctx.store.writeArtifact(ctx.runId, `regions/${crop.id}.png`, crop.buffer);\n }\n\n const matches = ctx.tree?.length\n ? matchRegionsToComponents(compareResult.regions, ctx.tree)\n : [];\n const findings = generateFindings(\n compareResult.regions,\n matches,\n compareResult.totalPixels,\n );\n\n const passed = compareResult.diffPercentage <= config.diffThreshold;\n\n return {\n analysisName: this.name,\n findings,\n summary: passed\n ? `Pixel diff: ${compareResult.diffPercentage.toFixed(3)}% (pass)`\n : `Pixel diff: ${compareResult.diffPercentage.toFixed(3)}% — ${compareResult.regions.length} regions (fail)`,\n metadata: {\n totalPixels: compareResult.totalPixels,\n diffPixels: compareResult.diffPixels,\n diffPercentage: compareResult.diffPercentage,\n regions: compareResult.regions,\n durationMs: compareResult.durationMs,\n passed,\n },\n durationMs: Date.now() - start,\n };\n }\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext } from '../types.js';\nimport type { ComponentNode, DiffFinding } from '../../types.js';\n\nconst INTERACTIVE_NAMES = new Set([\n 'Pressable',\n 'TouchableOpacity',\n 'Button',\n 'TouchableHighlight',\n 'TouchableWithoutFeedback',\n]);\n\nfunction isInteractive(name: string): boolean {\n if (INTERACTIVE_NAMES.has(name)) return true;\n return name.includes('Button') || name.includes('Pressable');\n}\n\nfunction collectNodes(nodes: ComponentNode[]): ComponentNode[] {\n const result: ComponentNode[] = [];\n const stack = [...nodes];\n while (stack.length > 0) {\n const node = stack.pop()!;\n result.push(node);\n for (const child of node.children) {\n stack.push(child);\n }\n }\n return result;\n}\n\nexport class AccessibilityAnalysis implements AnalysisPlugin {\n name = 'a11y';\n description = 'Accessibility audit of component tree';\n\n isAvailable(ctx: CompareContext): boolean {\n return !!ctx.tree?.length;\n }\n\n async run(ctx: CompareContext): Promise<AnalysisResult> {\n const start = Date.now();\n const nodes = collectNodes(ctx.tree ?? []);\n const platform = ctx.config.platform;\n const tapThreshold = platform === 'ios' ? 44 : 48;\n\n const findings: DiffFinding[] = [];\n let labelCount = 0;\n let tapTargetCount = 0;\n let imageCount = 0;\n let emptyTextCount = 0;\n\n for (const node of nodes) {\n if (isInteractive(node.name) && !node.testID) {\n const styles = node.styles ?? {};\n const hasLabel =\n 'accessibilityLabel' in styles ||\n 'aria-label' in styles;\n\n if (!hasLabel) {\n findings.push({\n id: `a11y-label-${labelCount++}`,\n category: 'accessibility',\n severity: 'major',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Interactive component \"${node.name}\" is missing an accessibilityLabel` }],\n description: `Interactive component \"${node.name}\" is missing an accessibilityLabel`,\n });\n }\n }\n\n if (node.bounds.width > 0 && node.bounds.height > 0) {\n if (node.bounds.width < tapThreshold || node.bounds.height < tapThreshold) {\n if (isInteractive(node.name)) {\n findings.push({\n id: `a11y-tap-${tapTargetCount++}`,\n category: 'accessibility',\n severity: 'minor',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Tap target \"${node.name}\" is ${node.bounds.width}x${node.bounds.height}, smaller than ${tapThreshold}x${tapThreshold}` }],\n description: `Tap target \"${node.name}\" is ${node.bounds.width}x${node.bounds.height}, smaller than the recommended ${tapThreshold}x${tapThreshold}`,\n });\n }\n }\n }\n\n if (node.name.includes('Image')) {\n const styles = node.styles ?? {};\n const hasAlt =\n 'accessibilityLabel' in styles ||\n 'aria-label' in styles ||\n 'alt' in styles;\n\n if (!hasAlt) {\n findings.push({\n id: `a11y-image-${imageCount++}`,\n category: 'accessibility',\n severity: 'major',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Image component \"${node.name}\" is missing an accessibilityLabel or alt text` }],\n description: `Image component \"${node.name}\" is missing an accessibilityLabel or alt text`,\n });\n }\n }\n\n if (node.text === '') {\n findings.push({\n id: `a11y-empty-${emptyTextCount++}`,\n category: 'accessibility',\n severity: 'info',\n confidence: 1.0,\n region: node.bounds,\n component: { name: node.name, testID: node.testID, bounds: node.bounds, depth: 0 },\n evidence: [{ type: 'accessibility', score: 1.0, note: `Component \"${node.name}\" has an empty text node` }],\n description: `Component \"${node.name}\" has an empty text node`,\n });\n }\n }\n\n const totalIssues = findings.length;\n const summary = totalIssues === 0 ? 'No accessibility issues' : `${totalIssues} accessibility issue${totalIssues === 1 ? '' : 's'} found`;\n\n return {\n analysisName: this.name,\n findings,\n summary,\n metadata: {\n totalChecked: nodes.length,\n issuesByType: {\n label: labelCount,\n tapTarget: tapTargetCount,\n image: imageCount,\n emptyText: emptyTextCount,\n },\n },\n durationMs: Date.now() - start,\n };\n }\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext } from '../types.js';\nimport { runComparison } from '../../diff/compare.js';\n\nexport class RegressionAnalysis implements AnalysisPlugin {\n name = 'regression';\n description = 'Layout regression detection against previous baseline';\n\n isAvailable(ctx: CompareContext): boolean {\n return !!ctx.baseline;\n }\n\n async run(ctx: CompareContext): Promise<AnalysisResult> {\n const start = Date.now();\n const { config } = ctx;\n const [mr, mg, mb, ma] = config.diffMaskColor;\n\n const compareResult = await runComparison(ctx.baseline!.path, ctx.screenshot.path, {\n threshold: config.threshold,\n diffThreshold: config.diffThreshold,\n regionMergeGap: config.regionMergeGap,\n regionMinArea: config.regionMinArea,\n ignoreRules: config.ignoreRules,\n diffMaskColor: { r: mr, g: mg, b: mb, a: ma / 255 },\n platform: config.platform,\n });\n\n await ctx.store.writeArtifact(ctx.runId, 'regression-diff-mask.png', compareResult.diffMaskBuffer);\n for (const crop of compareResult.regionCrops) {\n await ctx.store.writeArtifact(ctx.runId, `regression-regions/${crop.id}.png`, crop.buffer);\n }\n\n const regressionThreshold = ctx.analysisConfig.options['regression']?.regressionThreshold as number | undefined;\n const passed = compareResult.diffPercentage <= (regressionThreshold ?? config.diffThreshold);\n\n const findings = compareResult.regions.map((region, index) => ({\n id: `regression-${index}`,\n category: 'regression' as const,\n severity: 'major' as const,\n confidence: 1.0,\n region: region.bounds,\n component: { name: 'region', bounds: region.bounds, depth: 0 },\n evidence: [{ type: 'regression' as const, score: region.percentage / 100, note: `${region.percentage.toFixed(3)}% changed` }],\n description: `Region ${region.id}: ${region.percentage.toFixed(3)}% changed (${region.pixelCount}px)`,\n }));\n\n return {\n analysisName: this.name,\n findings,\n summary: passed\n ? 'Regression: no changes detected'\n : `Regression: ${compareResult.diffPercentage.toFixed(3)}% changed, ${compareResult.regions.length} regions`,\n metadata: {\n totalPixels: compareResult.totalPixels,\n diffPixels: compareResult.diffPixels,\n diffPercentage: compareResult.diffPercentage,\n regions: compareResult.regions,\n passed,\n },\n durationMs: Date.now() - start,\n };\n }\n}\n","import { AnalysisRegistry } from './registry.js';\nimport { PixelAnalysis } from './plugins/pixel.js';\nimport { AccessibilityAnalysis } from './plugins/a11y.js';\nimport { RegressionAnalysis } from './plugins/regression.js';\n\nexport function createDefaultRegistry(): AnalysisRegistry {\n const registry = new AnalysisRegistry();\n registry.register(new PixelAnalysis());\n registry.register(new AccessibilityAnalysis());\n registry.register(new RegressionAnalysis());\n return registry;\n}\n","import type { AnalysisPlugin, AnalysisResult, CompareContext, CompareReport } from './types.js';\nimport type { AnalysisRegistry } from './registry.js';\nimport type { RunMetadata } from '../types.js';\n\nexport class AnalysisOrchestrator {\n constructor(private registry: AnalysisRegistry) {}\n\n async run(ctx: CompareContext): Promise<CompareReport> {\n const start = Date.now();\n const plugins = this.selectPlugins(ctx);\n\n const settled = await Promise.allSettled(\n plugins.map((plugin) => plugin.run(ctx)),\n );\n\n const analyses: AnalysisResult[] = settled.map((result, i) => {\n if (result.status === 'fulfilled') return result.value;\n return {\n analysisName: plugins[i].name,\n findings: [],\n summary: `Error: ${result.reason?.message ?? 'unknown error'}`,\n metadata: {},\n durationMs: 0,\n error: result.reason?.message ?? 'unknown error',\n };\n });\n\n const findings = analyses.flatMap((a) => a.findings);\n const summaries = analyses.map((a) => a.summary).join('; ');\n const durationMs = Date.now() - start;\n\n return {\n runId: ctx.runId,\n analyses,\n findings,\n summary: summaries,\n metadata: {} as RunMetadata,\n durationMs,\n };\n }\n\n private selectPlugins(ctx: CompareContext): AnalysisPlugin[] {\n let plugins = this.registry.all();\n const { enabled, disabled } = ctx.analysisConfig;\n\n if (enabled.length > 0) {\n plugins = plugins.filter((p) => enabled.includes(p.name));\n }\n\n if (disabled.length > 0) {\n plugins = plugins.filter((p) => !disabled.includes(p.name));\n }\n\n return plugins.filter((p) => p.isAvailable(ctx));\n }\n}\n","import type { Shell, RunMetadata, DeviceInfo, InspectionCapabilities } from '../types.js';\nimport type { DriftxConfig } from '../config.js';\nimport type { CompareFormatData } from '../formatters/types.js';\nimport type { InspectResult } from '../inspect/tree-inspector.js';\nimport type { CompareReport } from '../analyses/types.js';\nimport { DeviceDiscovery } from '../devices/discovery.js';\nimport { captureScreenshot } from '../capture/capture.js';\nimport { TreeInspector } from '../inspect/tree-inspector.js';\nimport { RunStore } from '../run-store.js';\nimport { ExitCode } from '../exit-codes.js';\nimport { compareFormatter } from '../formatters/compare.js';\nimport { pickDevice } from './device-picker.js';\nimport { buildDriftxImage, buildAnalysisConfig } from '../analyses/context.js';\nimport { createDefaultRegistry } from '../analyses/default-registry.js';\nimport { AnalysisOrchestrator } from '../analyses/orchestrator.js';\nimport * as fs from 'node:fs';\n\nexport interface CompareCommandOptions {\n design?: string;\n device?: string;\n threshold?: number;\n screenshot?: string;\n with?: string;\n without?: string;\n baseline?: boolean;\n}\n\nexport async function runCompare(\n shell: Shell,\n config: DriftxConfig,\n options: CompareCommandOptions,\n): Promise<{ report: CompareReport; exitCode: number; formatData: CompareFormatData }> {\n const store = new RunStore(process.cwd());\n const run = store.createRun();\n\n let screenshotPath: string;\n let deviceId = 'unknown';\n let platform = config.platform;\n let deviceInfo: DeviceInfo | undefined;\n\n if (options.screenshot) {\n screenshotPath = options.screenshot;\n } else {\n const discovery = new DeviceDiscovery(shell);\n const devices = await discovery.list();\n const booted = devices.filter((d) => d.state === 'booted');\n if (booted.length === 0) throw new Error('No booted devices found');\n\n let device;\n if (options.device) {\n device = booted.find((d) => d.id === options.device || d.name === options.device);\n if (!device) throw new Error(`Device not found: ${options.device}`);\n } else {\n device = await pickDevice(booted);\n }\n\n deviceId = device.id;\n platform = device.platform;\n deviceInfo = device;\n\n const buffer = await captureScreenshot(shell, device, {\n settleCheck: config.settleCheckEnabled,\n settleMaxDelta: config.settleMaxDelta,\n settleDelayMs: config.settleTimeMs,\n });\n screenshotPath = store.getRunPath(run.runId, 'screenshot.png');\n await store.writeArtifact(run.runId, 'screenshot.png', buffer);\n }\n\n const screenshotImage = await buildDriftxImage(screenshotPath);\n\n let designImage;\n if (options.design) {\n const designBuffer = fs.readFileSync(options.design);\n await store.writeArtifact(run.runId, 'design.png', designBuffer);\n designImage = await buildDriftxImage(options.design);\n }\n\n let baselineImage;\n if (options.baseline) {\n const latestRunId = store.getLatestRun();\n if (latestRunId) {\n const baselinePath = store.getRunPath(latestRunId, 'screenshot.png');\n if (fs.existsSync(baselinePath)) {\n baselineImage = await buildDriftxImage(baselinePath);\n }\n }\n }\n\n let inspectResult: InspectResult | undefined;\n let inspectionCapabilities: InspectionCapabilities = {\n tree: 'none', sourceMapping: 'none', styles: 'none', protocol: 'none',\n };\n\n if (deviceInfo) {\n const inspector = new TreeInspector(shell, process.cwd());\n inspectResult = await inspector.inspect(deviceInfo, {\n metroPort: config.metroPort,\n devToolsPort: config.devToolsPort,\n timeoutMs: config.timeouts.treeInspectionMs,\n });\n inspectionCapabilities = inspectResult.capabilities;\n }\n\n const analysisConfig = buildAnalysisConfig(config.analyses, options.with, options.without);\n\n const ctx = {\n screenshot: screenshotImage,\n design: designImage,\n baseline: baselineImage,\n tree: inspectResult?.tree,\n device: deviceInfo,\n config,\n analysisConfig,\n runId: run.runId,\n store,\n };\n\n const registry = createDefaultRegistry();\n const orchestrator = new AnalysisOrchestrator(registry);\n const report = await orchestrator.run(ctx);\n\n const startedAt = new Date().toISOString();\n const metadata: RunMetadata = {\n runId: run.runId,\n startedAt,\n completedAt: new Date().toISOString(),\n projectRoot: process.cwd(),\n deviceId,\n platform,\n orientation: 'portrait',\n framework: 'unknown',\n driftxVersion: '0.1.0',\n configHash: '',\n };\n report.metadata = metadata;\n await store.writeMetadata(run.runId, metadata as unknown as Record<string, unknown>);\n\n const resultJson = JSON.stringify(report, null, 2);\n await store.writeArtifact(run.runId, 'result.json', Buffer.from(resultJson));\n\n const anyFailed = report.analyses.some((a) => {\n const meta = a.metadata as Record<string, unknown>;\n return meta.passed === false;\n });\n const exitCode = anyFailed ? ExitCode.DiffFound : ExitCode.Success;\n\n const formatData: CompareFormatData = {\n report,\n device: deviceInfo ? { name: deviceInfo.name, platform: deviceInfo.platform } : undefined,\n artifactDir: store.getRunPath(run.runId),\n tree: inspectResult?.tree,\n inspectHints: inspectResult?.hints,\n };\n\n const reportMarkdown = compareFormatter.markdown(formatData);\n await store.writeArtifact(run.runId, 'report.md', Buffer.from(reportMarkdown));\n\n return { report, exitCode, formatData };\n}\n","import { exec } from 'node:child_process';\nimport { getLogger } from '../logger.js';\n\nexport function getClipboardCommand(platform: string): string | undefined {\n if (platform === 'darwin') return 'pbcopy';\n if (platform === 'win32') return 'clip';\n if (platform === 'linux') return 'xclip -selection clipboard';\n return undefined;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n const logger = getLogger();\n const cmd = getClipboardCommand(process.platform);\n\n if (!cmd) {\n logger.debug(`Clipboard not supported on ${process.platform}`);\n return;\n }\n\n return new Promise((resolve) => {\n const proc = exec(cmd, (err) => {\n if (err) {\n logger.debug(`Clipboard copy failed: ${err.message}`);\n }\n resolve();\n });\n proc.stdin?.write(text);\n proc.stdin?.end();\n });\n}\n","import type { OutputFormatter, FormatterContext } from './types.js';\nimport { copyToClipboard } from './clipboard.js';\n\nexport async function formatOutput<T>(\n formatter: OutputFormatter<T>,\n data: T,\n ctx: FormatterContext,\n): Promise<string> {\n const output = formatter[ctx.format](data);\n\n if (!ctx.quiet) {\n console.log(output);\n }\n\n if (ctx.copy) {\n const clipboardContent = ctx.format === 'terminal'\n ? formatter.markdown(data)\n : output;\n await copyToClipboard(clipboardContent);\n }\n\n return output;\n}\n","import pc from 'picocolors';\nimport type { DeviceInfo } from '../types.js';\nimport type { OutputFormatter } from './types.js';\n\nfunction stateLabel(state: DeviceInfo['state']): string {\n if (state === 'booted') return pc.green('● booted');\n if (state === 'offline') return pc.yellow('○ offline');\n return pc.red('✗ unauthorized');\n}\n\nfunction stateText(state: DeviceInfo['state']): string {\n if (state === 'booted') return 'booted';\n if (state === 'offline') return 'offline';\n return 'unauthorized';\n}\n\nexport const devicesFormatter: OutputFormatter<DeviceInfo[]> = {\n terminal(devices) {\n if (devices.length === 0) {\n return 'No devices found. Start an emulator or connect a device.';\n }\n const lines: string[] = [];\n const header = ` ${'ID'.padEnd(20)} ${'Name'.padEnd(20)} ${'Platform'.padEnd(10)} ${'OS'.padEnd(10)} ${'State'}`;\n lines.push('');\n lines.push(header);\n lines.push(' ' + '-'.repeat(70));\n for (const d of devices) {\n lines.push(` ${d.id.padEnd(20)} ${d.name.padEnd(20)} ${d.platform.padEnd(10)} ${(d.osVersion || '-').padEnd(10)} ${stateLabel(d.state)}`);\n }\n lines.push('');\n return lines.join('\\n');\n },\n\n markdown(devices) {\n if (devices.length === 0) {\n return '# Driftx Devices\\n\\nNo devices found. Start an emulator or connect a device.';\n }\n const lines: string[] = ['# Driftx Devices', '', '| ID | Name | Platform | OS | State |', '|----|------|----------|-----|-------|'];\n for (const d of devices) {\n lines.push(`| ${d.id} | ${d.name} | ${d.platform} | ${d.osVersion || '-'} | ${stateText(d.state)} |`);\n }\n return lines.join('\\n');\n },\n\n json(devices) {\n return JSON.stringify(devices, null, 2);\n },\n};\n","import pc from 'picocolors';\nimport type { PrerequisiteCheck } from '../types.js';\nimport type { OutputFormatter } from './types.js';\n\nexport const doctorFormatter: OutputFormatter<PrerequisiteCheck[]> = {\n terminal(checks) {\n const lines: string[] = [];\n lines.push('Prerequisite Check');\n lines.push('─'.repeat(60));\n for (const check of checks) {\n const icon = check.available ? pc.green('+') : pc.red('-');\n const status = check.available ? 'ok' : pc.red('missing');\n const version = check.version ?? '';\n const required = check.required ? 'required' : 'optional';\n lines.push(` [${icon}] ${check.name.padEnd(12)} ${String(status).padEnd(10)} ${version.padEnd(16)} (${required})`);\n if (!check.available && check.fix) {\n lines.push(` Fix: ${check.fix}`);\n }\n }\n lines.push('─'.repeat(60));\n return lines.join('\\n');\n },\n\n markdown(checks) {\n const lines: string[] = ['# Driftx Doctor', '', '| Tool | Status | Version | Required | Fix |', '|------|--------|---------|----------|-----|'];\n for (const check of checks) {\n const status = check.available ? 'available' : 'unavailable';\n const version = check.version || '—';\n const required = check.required ? 'yes' : 'no';\n const fix = check.fix || '—';\n lines.push(`| ${check.name} | ${status} | ${version} | ${required} | ${fix} |`);\n }\n return lines.join('\\n');\n },\n\n json(checks) {\n return JSON.stringify(checks, null, 2);\n },\n};\n","import pc from 'picocolors';\nimport type { ComponentNode, InspectionCapabilities } from '../types.js';\nimport type { InspectResult } from '../inspect/tree-inspector.js';\nimport type { OutputFormatter } from './types.js';\n\nconst STRATEGY_LABELS: Record<string, string> = {\n cdp: 'CDP via Metro (React DevTools)',\n uiautomator: 'UIAutomator (native Android)',\n idb: 'idb (native iOS)',\n none: 'None',\n};\n\nfunction formatTreeText(nodes: ComponentNode[], indent: number = 0): string {\n const lines: string[] = [];\n for (const node of nodes) {\n const prefix = ' '.repeat(indent);\n const name = node.reactName ?? node.name;\n const testId = node.testID ? ` [${node.testID}]` : '';\n const text = node.text ? ` \"${node.text}\"` : '';\n const tier = node.inspectionTier === 'detailed' ? ' ⚛' : '';\n const b = node.bounds;\n const bounds = b.width > 0 ? ` (${b.x},${b.y} ${b.width}x${b.height})` : '';\n lines.push(`${prefix}${name}${testId}${text}${bounds}${tier}`);\n const childStr = formatTreeText(node.children, indent + 1);\n if (childStr) lines.push(childStr);\n }\n return lines.join('\\n');\n}\n\nfunction formatStrategySection(result: InspectResult, colored: boolean): string {\n const lines: string[] = [];\n const label = STRATEGY_LABELS[result.strategy.method] ?? result.strategy.method;\n const strategyText = colored\n ? (result.strategy.method === 'none' ? pc.dim(label) : pc.cyan(label))\n : label;\n lines.push('');\n lines.push(` Device: ${result.device.name} (${result.device.platform})`);\n lines.push(` Strategy: ${strategyText}`);\n if (result.strategy.appId) {\n lines.push(` App: ${result.strategy.appId}`);\n }\n lines.push('');\n return lines.join('\\n');\n}\n\nfunction formatCapsSection(caps: InspectionCapabilities): string {\n const lines: string[] = [];\n lines.push(' Capabilities');\n lines.push(' ' + '-'.repeat(40));\n lines.push(` Tree: ${caps.tree}`);\n lines.push(` Source mapping: ${caps.sourceMapping}`);\n lines.push(` Styles: ${caps.styles}`);\n lines.push(` Protocol: ${caps.protocol}`);\n lines.push('');\n return lines.join('\\n');\n}\n\nfunction formatHintsSection(hints: string[], colored: boolean): string {\n if (hints.length === 0) return '';\n const lines = ['', ' Hints', ' ' + '-'.repeat(40)];\n for (const hint of hints) {\n lines.push(colored ? ` ${pc.yellow(hint)}` : ` ${hint}`);\n }\n lines.push('');\n return lines.join('\\n');\n}\n\nexport const inspectFormatter: OutputFormatter<InspectResult> = {\n terminal(result) {\n const parts: string[] = [formatStrategySection(result, true)];\n\n if (result.tree.length === 0) {\n parts.push(' No component tree available. Try running with React DevTools enabled.');\n parts.push(formatHintsSection(result.hints, true));\n return parts.filter(Boolean).join('\\n');\n }\n\n parts.push(formatTreeText(result.tree));\n parts.push('');\n parts.push(formatCapsSection(result.capabilities));\n parts.push(formatHintsSection(result.hints, true));\n return parts.filter(Boolean).join('\\n');\n },\n\n markdown(result) {\n const lines: string[] = [\n '# Driftx Inspect Report',\n '',\n `**Device:** ${result.device.name} (${result.device.platform})`,\n `**Strategy:** ${STRATEGY_LABELS[result.strategy.method] ?? result.strategy.method}`,\n ];\n if (result.strategy.appId) {\n lines.push(`**App:** ${result.strategy.appId}`);\n }\n\n if (result.tree.length > 0) {\n lines.push('', '## Component Tree', '', '```', formatTreeText(result.tree), '```');\n } else {\n lines.push('', 'No component tree available.');\n }\n\n lines.push('', '## Capabilities', '', '| Capability | Level |', '|------------|-------|');\n lines.push(`| Tree | ${result.capabilities.tree} |`);\n lines.push(`| Source mapping | ${result.capabilities.sourceMapping} |`);\n lines.push(`| Styles | ${result.capabilities.styles} |`);\n lines.push(`| Protocol | ${result.capabilities.protocol} |`);\n\n if (result.hints.length > 0) {\n lines.push('', '## Hints', '');\n for (const hint of result.hints) {\n lines.push(`- ${hint}`);\n }\n }\n\n return lines.join('\\n');\n },\n\n json(result) {\n return JSON.stringify({\n tree: result.tree,\n capabilities: result.capabilities,\n strategy: result.strategy,\n device: result.device,\n hints: result.hints,\n }, null, 2);\n },\n};\n","import type { Shell, DeviceInfo } from '../types.js';\nimport type { Point, InteractionBackend } from './types.js';\n\nexport class AndroidBackend implements InteractionBackend {\n constructor(private shell: Shell) {}\n\n async tap(device: DeviceInfo, point: Point): Promise<void> {\n await this.adb(device, ['input', 'tap', String(point.x), String(point.y)]);\n }\n\n async longPress(device: DeviceInfo, point: Point, durationMs: number): Promise<void> {\n await this.adb(device, ['input', 'swipe', String(point.x), String(point.y), String(point.x), String(point.y), String(durationMs)]);\n }\n\n async swipe(device: DeviceInfo, from: Point, to: Point, durationMs: number): Promise<void> {\n await this.adb(device, ['input', 'swipe', String(from.x), String(from.y), String(to.x), String(to.y), String(durationMs)]);\n }\n\n async type(device: DeviceInfo, text: string): Promise<void> {\n const escaped = text.replace(/ /g, '%s');\n await this.adb(device, ['input', 'text', escaped]);\n }\n\n async keyEvent(device: DeviceInfo, key: string): Promise<void> {\n await this.adb(device, ['input', 'keyevent', key]);\n }\n\n async openUrl(device: DeviceInfo, url: string): Promise<void> {\n await this.shell.exec('adb', ['-s', device.id, 'shell', 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', url]);\n }\n\n private async adb(device: DeviceInfo, inputArgs: string[]): Promise<void> {\n await this.shell.exec('adb', ['-s', device.id, 'shell', ...inputArgs]);\n }\n}\n","import type { Shell, DeviceInfo } from '../types.js';\nimport type { Point, InteractionBackend } from './types.js';\n\nexport class IosBackend implements InteractionBackend {\n constructor(private shell: Shell) {}\n\n async tap(device: DeviceInfo, point: Point): Promise<void> {\n await this.simctlIo(device, ['tap', String(point.x), String(point.y)]);\n }\n\n async longPress(device: DeviceInfo, point: Point, _durationMs: number): Promise<void> {\n await this.simctlIo(device, ['longpress', String(point.x), String(point.y)]);\n }\n\n async swipe(device: DeviceInfo, from: Point, to: Point, _durationMs: number): Promise<void> {\n await this.simctlIo(device, ['swipe', String(from.x), String(from.y), String(to.x), String(to.y)]);\n }\n\n async type(device: DeviceInfo, text: string): Promise<void> {\n await this.simctlIo(device, ['type', text]);\n }\n\n async keyEvent(device: DeviceInfo, key: string): Promise<void> {\n await this.simctlIo(device, ['sendkey', key]);\n }\n\n async openUrl(device: DeviceInfo, url: string): Promise<void> {\n await this.shell.exec('xcrun', ['simctl', 'openurl', device.id, url]);\n }\n\n private async simctlIo(device: DeviceInfo, args: string[]): Promise<void> {\n await this.shell.exec('xcrun', ['simctl', 'io', device.id, ...args]);\n }\n}\n","import type { Shell } from '../types.js';\nimport type { InteractionBackend } from './types.js';\nimport { AndroidBackend } from './android.js';\nimport { IosBackend } from './ios.js';\n\nexport function createBackend(shell: Shell, platform: 'android' | 'ios'): InteractionBackend {\n return platform === 'android' ? new AndroidBackend(shell) : new IosBackend(shell);\n}\n","import type { ComponentNode } from '../types.js';\nimport type { TapTarget } from './types.js';\n\nexport function resolveTarget(tree: ComponentNode[], query: string): TapTarget | null {\n const nodes = flattenTree(tree);\n\n const byTestID = nodes.find((n) => n.testID === query && hasSize(n));\n if (byTestID) return centerOf(byTestID, `testID:${query}`);\n\n const byName = nodes.find((n) => n.name === query && hasSize(n));\n if (byName) return centerOf(byName, `name:${query}`);\n\n const byText = nodes.find((n) => n.text === query && hasSize(n));\n if (byText) return centerOf(byText, `text:${query}`);\n\n return null;\n}\n\nfunction flattenTree(nodes: ComponentNode[]): ComponentNode[] {\n const result: ComponentNode[] = [];\n const stack = [...nodes];\n while (stack.length > 0) {\n const node = stack.pop()!;\n result.push(node);\n for (const child of node.children) stack.push(child);\n }\n return result;\n}\n\nfunction hasSize(node: ComponentNode): boolean {\n return node.bounds.width > 0 && node.bounds.height > 0;\n}\n\nfunction centerOf(node: ComponentNode, resolvedFrom: string): TapTarget {\n return {\n x: Math.round(node.bounds.x + node.bounds.width / 2),\n y: Math.round(node.bounds.y + node.bounds.height / 2),\n resolvedFrom,\n };\n}\n","import type { DeviceInfo, ComponentNode } from '../types.js';\nimport type { InteractionBackend, InteractionResult, SwipeDirection } from './types.js';\nimport { resolveTarget } from './resolver.js';\n\nexport class GestureExecutor {\n constructor(private backend: InteractionBackend) {}\n\n async tap(device: DeviceInfo, tree: ComponentNode[], query: string): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = resolveTarget(tree, query);\n if (!target) {\n return { success: false, action: 'tap', durationMs: Date.now() - start, error: `Target not found: ${query}` };\n }\n await this.backend.tap(device, target);\n return { success: true, action: 'tap', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'tap', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async tapXY(device: DeviceInfo, x: number, y: number): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = { x, y };\n await this.backend.tap(device, target);\n return { success: true, action: 'tapXY', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'tapXY', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async longPress(device: DeviceInfo, tree: ComponentNode[], query: string, durationMs = 1000): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = resolveTarget(tree, query);\n if (!target) {\n return { success: false, action: 'longPress', durationMs: Date.now() - start, error: `Target not found: ${query}` };\n }\n await this.backend.longPress(device, target, durationMs);\n return { success: true, action: 'longPress', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'longPress', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async swipe(device: DeviceInfo, direction: SwipeDirection, distance = 600, durationMs = 300): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const cx = device.screenSize?.width ? Math.round(device.screenSize.width / 2) : 540;\n const cy = device.screenSize?.height ? Math.round(device.screenSize.height / 2) : 960;\n const from = { x: cx, y: cy };\n const half = Math.round(distance / 2);\n const to = direction === 'up' ? { x: cx, y: cy - half }\n : direction === 'down' ? { x: cx, y: cy + half }\n : direction === 'left' ? { x: cx - half, y: cy }\n : { x: cx + half, y: cy };\n await this.backend.swipe(device, from, to, durationMs);\n return { success: true, action: 'swipe', durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'swipe', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async typeInto(device: DeviceInfo, tree: ComponentNode[], query: string, text: string): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const target = resolveTarget(tree, query);\n if (!target) {\n return { success: false, action: 'typeInto', durationMs: Date.now() - start, error: `Target not found: ${query}` };\n }\n await this.backend.tap(device, target);\n await this.backend.type(device, text);\n return { success: true, action: 'typeInto', target, durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'typeInto', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async goBack(device: DeviceInfo): Promise<InteractionResult> {\n const start = Date.now();\n try {\n const key = device.platform === 'android' ? 'KEYCODE_BACK' : 'home';\n await this.backend.keyEvent(device, key);\n return { success: true, action: 'goBack', durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'goBack', durationMs: Date.now() - start, error: String(e) };\n }\n }\n\n async openUrl(device: DeviceInfo, url: string): Promise<InteractionResult> {\n const start = Date.now();\n try {\n await this.backend.openUrl(device, url);\n return { success: true, action: 'openUrl', durationMs: Date.now() - start };\n } catch (e) {\n return { success: false, action: 'openUrl', durationMs: Date.now() - start, error: String(e) };\n }\n }\n}\n","#!/usr/bin/env node\nimport { run } from './cli.js';\n\nrun(process.argv);\n"],"mappings":"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","names":["existsSync","mkdirSync","readFileSync","readdirSync","unlinkSync","writeFileSync","dirname","join","resolve","http","resolve","fs","path","fs","os","path","resolve","fs","path","delay","resolve","run","resolve","fs","path","readFileSync","sharp","fs","sharp","sharp","pixelmatch","sharp","sharp","sharp","boxesOverlap","fs","run","resolve","pc","pc","pc","require","readdirSync","readFileSync","join","writeFileSync","dirname","existsSync","mkdirSync","unlinkSync"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "driftx",
3
- "version": "0.1.0",
4
- "description": "Visual diff tool for React Native and Android development",
3
+ "version": "0.1.1",
4
+ "description": "Visual diff tool for mobile development Android, iOS, and React Native",
5
5
  "type": "module",
6
6
  "main": "./dist/bin.js",
7
7
  "bin": {
@@ -22,7 +22,11 @@
22
22
  },
23
23
  "keywords": [
24
24
  "react-native",
25
+ "android",
26
+ "ios",
27
+ "mobile",
25
28
  "visual-diff",
29
+ "accessibility",
26
30
  "screenshot",
27
31
  "testing"
28
32
  ],