prowl-tools 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/interpolate.ts","../src/config/target.ts","../src/browser/mac-driver.ts","../src/browser/mac-helper.ts","../src/runner/healing.ts","../src/runner/history.ts","../src/runner/index.ts","../src/browser/playwright-driver.ts","../src/runner/steps.ts","../src/runner/policy.ts","../src/runner/assertions.ts","../src/runner/tracing.ts","../src/reporter/result.ts","../src/reporter/summary.ts","../src/reporter/junit.ts","../src/reporter/index.ts","../src/utils/timestamp.ts","../src/runner/flaky.ts","../src/backlog/fingerprint.ts","../src/runner/clustering.ts","../src/backlog/index.ts","../src/backlog/parse.ts","../src/backlog/write.ts","../src/runner/suite.ts","../src/reporter/ci-summary.ts","../src/utils/concurrency.ts","../src/analyzer/index.ts","../src/generator/index.ts","../src/browser/engines.ts","../src/generator/prompt.ts","../src/generator/ai.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport type { Assertion, Hunt, Step } from \"../types/index.js\";\n\nexport type InterpolatedHunt = {\n hunt: Hunt;\n redactedFillSteps: Set<string>;\n randomVars: Record<string, string>;\n redactionValues: string[];\n};\n\nexport type InterpolationResult = {\n value: string;\n usedVars: string[];\n};\n\nconst VAR_PATTERN = /\\{\\{([A-Z0-9_]+)\\}\\}/g;\n\nfunction collectInterpolatedValues(input: unknown, vars: Record<string, string>, values: Set<string>): void {\n if (typeof input === \"string\") {\n for (const match of input.matchAll(VAR_PATTERN)) {\n const varValue = vars[match[1]];\n if (varValue) values.add(varValue);\n }\n return;\n }\n\n if (Array.isArray(input)) {\n for (const item of input) {\n collectInterpolatedValues(item, vars, values);\n }\n return;\n }\n\n if (input && typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n collectInterpolatedValues(key, vars, values);\n collectInterpolatedValues(value, vars, values);\n }\n }\n}\n\nexport function interpolateString(\n input: string,\n vars: Record<string, string>\n): InterpolationResult {\n const usedVars: string[] = [];\n const value = input.replace(VAR_PATTERN, (_, name: string) => {\n const varValue = vars[name];\n if (varValue === undefined) {\n throw new Error(`Missing variable: ${name}`);\n }\n usedVars.push(name);\n return varValue;\n });\n return { value, usedVars };\n}\n\nconst RANDOM_FIRST_NAMES = [\"Alex\", \"Jordan\", \"Morgan\", \"Taylor\", \"Casey\", \"Riley\", \"Quinn\", \"Avery\"];\nconst RANDOM_LAST_NAMES = [\"Smith\", \"Johnson\", \"Brown\", \"Davis\", \"Wilson\", \"Clark\", \"Hall\", \"Young\"];\n\ntype RandomSource = {\n random: () => number;\n randomBytes: (size: number) => Buffer;\n randomUUID: () => string;\n};\n\nexport function generateRandomVars(randomSource?: Partial<RandomSource>): Record<string, string> {\n const random = randomSource?.random ?? Math.random;\n const randomBytes = randomSource?.randomBytes ?? crypto.randomBytes;\n const randomUUID = randomSource?.randomUUID ?? crypto.randomUUID;\n const hex = randomBytes(4).toString(\"hex\");\n const firstIndex = Math.floor(random() * RANDOM_FIRST_NAMES.length);\n const lastIndex = Math.floor(random() * RANDOM_LAST_NAMES.length);\n const num = Math.floor(random() * 9000) + 1000;\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n let text = \"\";\n for (let i = 0; i < 8; i++) {\n text += chars[Math.floor(random() * chars.length)];\n }\n return {\n RANDOM_EMAIL: `prowl_${hex}@test.com`,\n RANDOM_NAME: `${RANDOM_FIRST_NAMES[firstIndex]} ${RANDOM_LAST_NAMES[lastIndex]}`,\n RANDOM_NUMBER: String(num),\n RANDOM_UUID: randomUUID(),\n RANDOM_TEXT: text\n };\n}\n\nfunction interpolateStep(\n step: Step,\n vars: Record<string, string>,\n stepPath: string,\n redacted: Set<string>\n): Step {\n const isExplicitFill = (\n value: { selector: string; value: string } | Record<string, string>\n ): value is { selector: string; value: string } =>\n typeof (value as { selector?: unknown }).selector === \"string\" &&\n typeof (value as { value?: unknown }).value === \"string\";\n\n const interpolateSinglePair = (record: Record<string, string>): Record<string, string> => {\n const entries = Object.entries(record);\n if (entries.length !== 1) {\n throw new Error(\"Shorthand step expects exactly one key-value pair\");\n }\n const [key, value] = entries[0];\n return {\n [interpolateString(key, vars).value]: interpolateString(value, vars).value\n };\n };\n\n if (\"navigate\" in step) {\n const result = interpolateString(step.navigate, vars);\n return { navigate: result.value };\n }\n if (\"click\" in step) {\n if (typeof step.click === \"string\") {\n return { click: interpolateString(step.click, vars).value };\n }\n const result = interpolateString(step.click.selector, vars);\n return { click: { selector: result.value } };\n }\n if (\"fill\" in step) {\n if (isExplicitFill(step.fill)) {\n const selectorResult = interpolateString(step.fill.selector, vars);\n const valueResult = interpolateString(step.fill.value, vars);\n if (valueResult.usedVars.length > 0) {\n redacted.add(stepPath);\n }\n return { fill: { selector: selectorResult.value, value: valueResult.value } };\n }\n const [rawLabel, rawValue] = Object.entries(step.fill)[0] ?? [];\n if (rawLabel === undefined || rawValue === undefined) {\n throw new Error(\"Shorthand fill expects exactly one key-value pair\");\n }\n const labelResult = interpolateString(rawLabel, vars);\n const valueResult = interpolateString(rawValue, vars);\n if (valueResult.usedVars.length > 0) {\n redacted.add(stepPath);\n }\n return {\n fill: {\n [labelResult.value]: valueResult.value\n }\n };\n }\n if (\"type\" in step) {\n const valueResult = interpolateString(step.type, vars);\n if (valueResult.usedVars.length > 0) {\n redacted.add(stepPath);\n }\n return { type: valueResult.value };\n }\n if (\"selectOption\" in step) {\n const selectorResult = interpolateString(step.selectOption.selector, vars);\n const valueResult = interpolateString(step.selectOption.value, vars);\n return { selectOption: { selector: selectorResult.value, value: valueResult.value } };\n }\n if (\"select\" in step) {\n return { select: interpolateSinglePair(step.select) };\n }\n if (\"press\" in step) {\n const selectorResult = interpolateString(step.press.selector, vars);\n const keyResult = interpolateString(step.press.key, vars);\n return { press: { selector: selectorResult.value, key: keyResult.value } };\n }\n if (\"onDialog\" in step) {\n return { onDialog: { action: step.onDialog.action } };\n }\n if (\"setInputFiles\" in step) {\n const selectorResult = interpolateString(step.setInputFiles.selector, vars);\n const rawFiles = step.setInputFiles.files;\n const files = Array.isArray(rawFiles)\n ? rawFiles.map((f) => interpolateString(f, vars).value)\n : interpolateString(rawFiles, vars).value;\n return { setInputFiles: { selector: selectorResult.value, files } };\n }\n if (\"runHunt\" in step) {\n if (typeof step.runHunt === \"string\") {\n return { runHunt: interpolateString(step.runHunt, vars).value };\n }\n const nameResult = interpolateString(step.runHunt.name, vars);\n const interpolatedVars: Record<string, string> = {};\n for (const [key, value] of Object.entries(step.runHunt.vars ?? {})) {\n interpolatedVars[key] = interpolateString(value, vars).value;\n }\n return {\n runHunt: {\n name: nameResult.value,\n ...(Object.keys(interpolatedVars).length > 0 ? { vars: interpolatedVars } : {})\n }\n };\n }\n if (\"assert\" in step) {\n if (step.assert.visible !== undefined) {\n return { assert: { visible: interpolateString(step.assert.visible, vars).value } };\n }\n if (step.assert.notVisible !== undefined) {\n return { assert: { notVisible: interpolateString(step.assert.notVisible, vars).value } };\n }\n if (step.assert.urlIncludes !== undefined) {\n return { assert: { urlIncludes: interpolateString(step.assert.urlIncludes, vars).value } };\n }\n if (step.assert.urlEquals !== undefined) {\n return { assert: { urlEquals: interpolateString(step.assert.urlEquals, vars).value } };\n }\n return step;\n }\n if (\"wait\" in step) {\n if (typeof step.wait === \"string\") {\n return { wait: interpolateString(step.wait, vars).value };\n }\n return {\n wait: {\n for: interpolateString(step.wait.for, vars).value,\n timeout: step.wait.timeout\n }\n };\n }\n if (\"waitForSelector\" in step) {\n const selectorResult = interpolateString(step.waitForSelector.selector, vars);\n return {\n waitForSelector: {\n selector: selectorResult.value,\n timeout: step.waitForSelector.timeout\n }\n };\n }\n if (\"waitForUrl\" in step) {\n const valueResult = interpolateString(step.waitForUrl.value, vars);\n return {\n waitForUrl: {\n value: valueResult.value,\n timeout: step.waitForUrl.timeout\n }\n };\n }\n if (\"waitForNetworkIdle\" in step) {\n return { waitForNetworkIdle: { timeout: step.waitForNetworkIdle.timeout } };\n }\n if (\"hover\" in step) {\n const selectorResult = interpolateString(step.hover.selector, vars);\n return { hover: { selector: selectorResult.value } };\n }\n if (\"scroll\" in step) {\n return { scroll: { direction: step.scroll.direction, amount: step.scroll.amount } };\n }\n if (\"scrollTo\" in step) {\n const selectorResult = interpolateString(step.scrollTo.selector, vars);\n return { scrollTo: { selector: selectorResult.value } };\n }\n if (\"screenshot\" in step) {\n return { screenshot: { name: step.screenshot.name } };\n }\n if (\"if\" in step) {\n const condition = step.if;\n const thenSteps = condition.then.map((s, i) =>\n interpolateStep(s, vars, `${stepPath}.if.then.${i}`, redacted)\n );\n const elseSteps = condition.else?.map((s, i) =>\n interpolateStep(s, vars, `${stepPath}.if.else.${i}`, redacted)\n );\n return {\n if: {\n ...(condition.visible !== undefined\n ? { visible: interpolateString(condition.visible, vars).value }\n : {}),\n ...(condition.notVisible !== undefined\n ? { notVisible: interpolateString(condition.notVisible, vars).value }\n : {}),\n then: thenSteps,\n ...(elseSteps !== undefined ? { else: elseSteps } : {})\n }\n };\n }\n if (\"repeat\" in step) {\n const repeat = step.repeat;\n const subSteps = repeat.steps.map((s, i) =>\n interpolateStep(s, vars, `${stepPath}.repeat.steps.${i}`, redacted)\n );\n return {\n repeat: {\n ...(repeat.times !== undefined ? { times: repeat.times } : {}),\n ...(repeat.while !== undefined\n ? {\n while: {\n ...(repeat.while.visible !== undefined\n ? { visible: interpolateString(repeat.while.visible, vars).value }\n : {}),\n ...(repeat.while.notVisible !== undefined\n ? { notVisible: interpolateString(repeat.while.notVisible, vars).value }\n : {})\n }\n }\n : {}),\n ...(repeat.maxIterations !== undefined ? { maxIterations: repeat.maxIterations } : {}),\n steps: subSteps\n }\n };\n }\n if (\"mockRoute\" in step) {\n const mock = step.mockRoute;\n return {\n mockRoute: {\n url: interpolateString(mock.url, vars).value,\n response: {\n status: mock.response.status,\n ...(mock.response.contentType !== undefined\n ? { contentType: interpolateString(mock.response.contentType, vars).value }\n : {}),\n ...(mock.response.body !== undefined\n ? { body: interpolateString(mock.response.body, vars).value }\n : {}),\n ...(mock.response.file !== undefined\n ? { file: interpolateString(mock.response.file, vars).value }\n : {})\n }\n }\n };\n }\n if (\"unmockRoute\" in step) {\n if (typeof step.unmockRoute === \"string\") {\n return { unmockRoute: interpolateString(step.unmockRoute, vars).value };\n }\n return {\n unmockRoute: { url: interpolateString(step.unmockRoute.url, vars).value }\n };\n }\n if (\"evalScript\" in step) {\n if (typeof step.evalScript === \"string\") {\n return { evalScript: interpolateString(step.evalScript, vars).value };\n }\n return {\n evalScript: {\n expression: interpolateString(step.evalScript.expression, vars).value,\n ...(step.evalScript.as !== undefined ? { as: step.evalScript.as } : {})\n }\n };\n }\n if (\"runScript\" in step) {\n return {\n runScript: { file: interpolateString(step.runScript.file, vars).value }\n };\n }\n if (\"assertScreenshot\" in step) {\n return {\n assertScreenshot: {\n name: interpolateString(step.assertScreenshot.name, vars).value,\n ...(step.assertScreenshot.threshold !== undefined\n ? { threshold: step.assertScreenshot.threshold }\n : {})\n }\n };\n }\n if (\"copyText\" in step) {\n return {\n copyText: {\n selector: interpolateString(step.copyText.selector, vars).value,\n as: step.copyText.as\n }\n };\n }\n if (\"waitForDownload\" in step) {\n if (step.waitForDownload === null) {\n return { waitForDownload: null };\n }\n return {\n waitForDownload: {\n ...(step.waitForDownload.filename !== undefined\n ? { filename: interpolateString(step.waitForDownload.filename, vars).value }\n : {}),\n ...(step.waitForDownload.timeout !== undefined\n ? { timeout: step.waitForDownload.timeout }\n : {})\n }\n };\n }\n return step;\n}\n\nfunction interpolateAssertion(assertion: Assertion, vars: Record<string, string>): Assertion {\n if (\"selectorExists\" in assertion) {\n return { selectorExists: interpolateString(assertion.selectorExists, vars).value };\n }\n if (\"selectorNotExists\" in assertion) {\n return { selectorNotExists: interpolateString(assertion.selectorNotExists, vars).value };\n }\n if (\"urlIncludes\" in assertion) {\n return { urlIncludes: interpolateString(assertion.urlIncludes, vars).value };\n }\n if (\"urlEquals\" in assertion) {\n return { urlEquals: interpolateString(assertion.urlEquals, vars).value };\n }\n if (\"noConsoleErrors\" in assertion) {\n return { noConsoleErrors: assertion.noConsoleErrors };\n }\n if (\"noNetworkErrors\" in assertion) {\n return { noNetworkErrors: assertion.noNetworkErrors };\n }\n return assertion;\n}\n\nexport function interpolateHunt(\n hunt: Hunt,\n env: NodeJS.ProcessEnv,\n randomVars: Record<string, string> = generateRandomVars()\n): InterpolatedHunt {\n const redactedFillSteps = new Set<string>();\n\n const envVars = Object.fromEntries(\n Object.entries(env).filter(([, value]) => value !== undefined) as Array<[string, string]>\n );\n const baseVars = { ...randomVars, ...envVars };\n\n const resolvedHuntVars: Record<string, string> = {};\n for (const [key, value] of Object.entries(hunt.vars ?? {})) {\n resolvedHuntVars[key] = interpolateString(value, baseVars).value;\n }\n\n const vars = { ...baseVars, ...resolvedHuntVars };\n const redactionValues = new Set<string>();\n collectInterpolatedValues(hunt.steps, vars, redactionValues);\n collectInterpolatedValues(hunt.assertions, vars, redactionValues);\n\n const steps = hunt.steps.map((step, index) =>\n interpolateStep(step, vars, `${index}`, redactedFillSteps)\n );\n const assertions = hunt.assertions?.map((assertion) => interpolateAssertion(assertion, vars));\n return {\n hunt: {\n ...hunt,\n steps,\n assertions\n },\n redactedFillSteps,\n randomVars,\n redactionValues: [...redactionValues]\n };\n}\n","/**\n * PROWL-048 / ARCH-002 — target ⇄ step compatibility.\n *\n * The runtime capability gate in the step runner already rejects steps a driver\n * cannot honor. This adds a friendlier, earlier validation-time rejection: when\n * the selected target is macOS, hunts using web-only steps fail fast with a\n * clear message before anything launches.\n */\nimport type { Step, Target } from \"../types/index.js\";\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Step types that only make sense on the web target. Everything else\n * (`click`, `fill`, `type`, `press`, `wait`, `assert visible/notVisible`,\n * `screenshot`, `assertScreenshot`, `repeat`, `runHunt`, `if`, `copyText`,\n * `hover`, `scrollTo`, `waitForSelector`) is portable across targets.\n */\nexport const WEB_ONLY_STEP_TYPES: ReadonlySet<string> = new Set([\n \"navigate\",\n \"waitForUrl\",\n \"waitForNetworkIdle\",\n \"mockRoute\",\n \"unmockRoute\",\n \"evalScript\",\n \"runScript\",\n \"onDialog\",\n \"select\",\n \"selectOption\",\n \"setInputFiles\",\n \"waitForDownload\",\n \"scroll\" // directional scroll runs window.scrollBy (evaluate) — use scrollTo instead\n]);\n\n/** The web-only reason a step is unsupported on a non-web target, or null if portable. */\nexport function webOnlyReason(step: Step): string | null {\n for (const type of WEB_ONLY_STEP_TYPES) {\n if (type in step) {\n return type;\n }\n }\n // URL assertions are web-only; visible/notVisible assertions are portable.\n if (\"assert\" in step) {\n const assertion = step.assert;\n if (assertion.urlIncludes !== undefined || assertion.urlEquals !== undefined) {\n return \"assert (url)\";\n }\n }\n return null;\n}\n\n/**\n * Throw if any step in `steps` (recursing into `if`/`repeat` bodies) is not\n * supported by `target`. `runHunt` references are validated when the referenced\n * hunt itself runs. No-op for the web target.\n */\nexport function assertStepsSupportedByTarget(steps: Step[], target: Target[\"type\"]): void {\n if (target !== \"macos\") {\n return;\n }\n for (const step of steps) {\n const reason = webOnlyReason(step);\n if (reason) {\n throw new Error(\n `Step \"${reason}\" is not supported by the macOS target. It is web-only; ` +\n \"use a portable step (click, fill, type, press, wait, assert visible, screenshot, etc.).\"\n );\n }\n if (\"if\" in step) {\n assertStepsSupportedByTarget(step.if.then, target);\n if (step.if.else) {\n assertStepsSupportedByTarget(step.if.else, target);\n }\n }\n if (\"repeat\" in step) {\n assertStepsSupportedByTarget(step.repeat.steps, target);\n }\n }\n}\n\nexport function assertHuntAssertionsSupportedByTarget(\n assertions: unknown[] | undefined,\n target: Target[\"type\"]\n): void {\n if (target !== \"macos\" || !assertions || assertions.length === 0) {\n return;\n }\n throw new Error(\n \"Hunt-level assertions are not supported by the macOS target. \" +\n \"Use inline assert visible/notVisible steps instead.\"\n );\n}\n\nfunction trimTrailingPathSeparators(value: string): string {\n return value.replace(/[\\\\/]+$/g, \"\");\n}\n\nfunction looksLikeMacosAppPath(app: string): boolean {\n const trimmed = trimTrailingPathSeparators(app);\n return trimmed.includes(\"/\") || trimmed.toLowerCase().endsWith(\".app\");\n}\n\nfunction normalizeAppPath(app: string): string {\n return path.resolve(trimTrailingPathSeparators(app));\n}\n\nfunction parseBundleIdentifier(plist: string): string | null {\n const match = /<key>\\s*CFBundleIdentifier\\s*<\\/key>\\s*<string>\\s*([^<]+?)\\s*<\\/string>/s.exec(plist);\n return match?.[1]?.trim() || null;\n}\n\nfunction readBundleIdentifier(appPath: string): string | null {\n const infoPlistPath = path.join(normalizeAppPath(appPath), \"Contents\", \"Info.plist\");\n if (!fs.existsSync(infoPlistPath)) {\n return null;\n }\n\n try {\n const parsed = parseBundleIdentifier(fs.readFileSync(infoPlistPath, \"utf-8\"));\n if (parsed) {\n return parsed;\n }\n } catch {\n // Fall through to plutil for binary plists on macOS.\n }\n\n if (process.platform !== \"darwin\" || !fs.existsSync(\"/usr/bin/plutil\")) {\n return null;\n }\n\n try {\n const output = execFileSync(\n \"/usr/bin/plutil\",\n [\"-extract\", \"CFBundleIdentifier\", \"raw\", \"-o\", \"-\", infoPlistPath],\n { encoding: \"utf-8\", stdio: [\"ignore\", \"pipe\", \"ignore\"], timeout: 1000 }\n );\n return output.trim() || null;\n } catch {\n return null;\n }\n}\n\nexport function macosAppAllowedIdentities(app: string): string[] {\n const identities = new Set<string>([app]);\n\n if (looksLikeMacosAppPath(app)) {\n const normalizedPath = normalizeAppPath(app);\n identities.add(trimTrailingPathSeparators(app));\n identities.add(normalizedPath);\n\n const bundleName = path.basename(normalizedPath).replace(/\\.app$/i, \"\");\n if (bundleName) {\n identities.add(bundleName);\n }\n\n const bundleId = readBundleIdentifier(app);\n if (bundleId) {\n identities.add(bundleId);\n }\n }\n\n return [...identities];\n}\n\n/**\n * Native scope guardrail: if `allowedApps` is non-empty it must include an\n * accepted identity for the target app: bundle id, app bundle name, or `.app`\n * path. An empty list means the scope is unset and the target app is implicitly\n * allowed — mirroring how allowedDomains auto-includes the web target's host.\n */\nexport function assertTargetAppAllowed(allowedApps: string[], app: string): void {\n if (allowedApps.length === 0) {\n return;\n }\n const allowedIdentities = new Set(allowedApps.flatMap((allowedApp) => macosAppAllowedIdentities(allowedApp)));\n if (macosAppAllowedIdentities(app).some((identity) => allowedIdentities.has(identity))) {\n return;\n }\n throw new Error(\n `Target app \"${app}\" is not in guardrails.allowedApps (${allowedApps.join(\", \")}).`\n );\n}\n","/**\n * PROWL-048 / ARCH-002 — macOS native implementation of {@link SessionDriver}.\n *\n * `MacDriver` drives a native macOS app through the `prowl-macdriver` Swift\n * helper (Accessibility / AXUIElement) over a long-lived JSON-over-stdio\n * transport ({@link MacHelperClient}). It implements only the portable subset of\n * the driver surface — its `capabilities` set is honest: `query`, `interact`,\n * `wait`, `screenshot`. Web-only verbs (navigation, network, dialogs, files,\n * downloads, script evaluation) are unsupported stubs; the runner never reaches\n * them because both the target step-compatibility check and the runtime\n * capability gate reject web-only steps for the macOS target.\n *\n * Selector dialect (parsed here, so the Swift helper only matches attributes):\n * id=openSettings → accessibility identifier\n * role=button[name=\"Save\"] → AX role + accessible name\n * label=\"Email\" → exact accessibility label\n * text=\"Save\" | Save → title/description/value substring\n * statusItem → open the app's menu bar status-item menu\n * menu=Preferences… → open the status-item menu and click an item\n */\nimport type {\n DialogAction,\n DriverCapability,\n DriverDownload,\n DriverResponse,\n DriverRoute,\n NavigateOptions,\n SessionDriver\n} from \"./driver.js\";\n\n/** A structured accessibility query understood by the Swift helper. */\nexport type MacQuery =\n | { by: \"id\"; value: string }\n | { by: \"role\"; role: string; name?: string }\n | { by: \"text\"; value: string }\n | { by: \"label\"; value: string }\n | { by: \"focused\" };\n\n/** The transport MacDriver talks to: one request → one response, matched by id. */\nexport interface MacHelperClient {\n /** Send a command; resolve with its `result` payload or reject with its error. */\n request(cmd: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;\n /** Shut the helper down. */\n close(): Promise<void>;\n}\n\nexport type MacDriverOptions = {\n /** Bundle id / app label, used only for the informational `currentUrl()` value. */\n appLabel?: string;\n};\n\nconst MAC_CAPABILITIES: ReadonlySet<DriverCapability> = new Set<DriverCapability>([\n \"query\",\n \"interact\",\n \"wait\",\n \"screenshot\"\n]);\n\nconst STATUS_ITEM_SELECTOR = \"statusitem\";\nconst MENU_PREFIX = \"menu=\";\n\nfunction unquote(value: string): string {\n const trimmed = value.trim();\n const first = trimmed[0];\n if ((first === '\"' || first === \"'\") && trimmed.endsWith(first) && trimmed.length >= 2) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\n/** Parse a Prowl selector string into a {@link MacQuery}. Bare text matches by text. */\nexport function parseMacSelector(selector: string): MacQuery {\n const trimmed = selector.trim();\n\n const idMatch = /^id=(.+)$/s.exec(trimmed);\n if (idMatch) {\n return { by: \"id\", value: unquote(idMatch[1]) };\n }\n\n const roleMatch = /^role=([A-Za-z][\\w-]*)(?:\\[name=(.+)\\])?$/s.exec(trimmed);\n if (roleMatch) {\n const name = roleMatch[2] !== undefined ? unquote(roleMatch[2]) : undefined;\n return name !== undefined && name.length > 0\n ? { by: \"role\", role: roleMatch[1], name }\n : { by: \"role\", role: roleMatch[1] };\n }\n\n const labelMatch = /^label=(.+)$/s.exec(trimmed);\n if (labelMatch) {\n return { by: \"label\", value: unquote(labelMatch[1]) };\n }\n\n const textMatch = /^text=(.+)$/s.exec(trimmed);\n if (textMatch) {\n return { by: \"text\", value: unquote(textMatch[1]) };\n }\n\n return { by: \"text\", value: trimmed };\n}\n\n/** The literal text a `text=` selector matches, else null (mirrors the web driver). */\nexport function unwrapMacTextSelector(selector: string): string | null {\n const trimmed = selector.trim();\n if (!trimmed.startsWith(\"text=\")) {\n return null;\n }\n return unquote(trimmed.slice(5));\n}\n\nfunction num(value: unknown): number {\n return typeof value === \"number\" ? value : Number(value ?? 0);\n}\n\n/** Wrap a live {@link MacHelperClient} as a {@link SessionDriver}. */\nexport function createMacDriver(client: MacHelperClient, options: MacDriverOptions = {}): SessionDriver {\n const unsupported = (verb: string): Error => new Error(`${verb} is not supported by the macOS target`);\n const rejectUnsupported = (verb: string): Promise<never> => Promise.reject(unsupported(verb));\n\n async function query(cmd: string, selector: string, extra?: Record<string, unknown>): Promise<Record<string, unknown>> {\n return client.request(cmd, { query: parseMacSelector(selector), ...extra });\n }\n\n async function clickSelector(selector: string): Promise<void> {\n const trimmed = selector.trim();\n if (trimmed.toLowerCase() === STATUS_ITEM_SELECTOR) {\n await client.request(\"openMenu\");\n return;\n }\n if (trimmed.toLowerCase().startsWith(MENU_PREFIX)) {\n await client.request(\"clickMenu\", { title: trimmed.slice(MENU_PREFIX.length).trim() });\n return;\n }\n await query(\"click\", selector);\n }\n\n async function fillSelector(selector: string, value: string): Promise<void> {\n if (selector.trim() === \":focus\") {\n await client.request(\"fill\", { query: { by: \"focused\" } as MacQuery, value });\n return;\n }\n await query(\"fill\", selector, { value });\n }\n\n return {\n capabilities: MAC_CAPABILITIES,\n\n // navigation -----------------------------------------------------------\n goto(_url: string, _options?: NavigateOptions): Promise<void> {\n return rejectUnsupported(\"navigate\");\n },\n currentUrl(): string {\n return `macos:${options.appLabel ?? \"\"}`;\n },\n\n // queries --------------------------------------------------------------\n async count(selector: string): Promise<number> {\n const result = await query(\"count\", selector);\n return num(result.count);\n },\n async textContent(selector: string): Promise<string | null> {\n const result = await query(\"text\", selector);\n return result.text === undefined || result.text === null ? null : String(result.text);\n },\n\n // interactions ---------------------------------------------------------\n click: clickSelector,\n clickFirst: clickSelector,\n fill: fillSelector,\n fillFirst: fillSelector,\n async press(selector: string, key: string): Promise<void> {\n await query(\"press\", selector, { key });\n },\n selectOption(): Promise<void> {\n return rejectUnsupported(\"select\");\n },\n selectOptionFirst(): Promise<void> {\n return rejectUnsupported(\"select\");\n },\n async hover(selector: string): Promise<void> {\n await query(\"hover\", selector);\n },\n async scrollIntoView(selector: string): Promise<void> {\n await query(\"scrollTo\", selector);\n },\n setInputFiles(): Promise<void> {\n return rejectUnsupported(\"setInputFiles\");\n },\n\n // semantic locators ----------------------------------------------------\n async countByRole(role: string, name: string): Promise<number> {\n const result = await client.request(\"count\", { query: { by: \"role\", role, name } });\n return num(result.count);\n },\n async clickFirstByRole(role: string, name: string): Promise<void> {\n await client.request(\"click\", { query: { by: \"role\", role, name } });\n },\n async countByLabel(label: string): Promise<number> {\n const result = await client.request(\"count\", { query: { by: \"label\", value: label } });\n return num(result.count);\n },\n async fillFirstByLabel(label: string, value: string): Promise<void> {\n await client.request(\"fill\", { query: { by: \"label\", value: label }, value });\n },\n selectOptionFirstByLabel(): Promise<void> {\n return rejectUnsupported(\"select\");\n },\n\n // waiting --------------------------------------------------------------\n async waitForSelector(selector: string, waitOptions?: { timeout?: number }): Promise<void> {\n const extra = waitOptions?.timeout !== undefined ? { timeout: waitOptions.timeout / 1000 } : undefined;\n await query(\"waitFor\", selector, extra);\n },\n waitForUrl(): Promise<void> {\n return rejectUnsupported(\"waitForUrl\");\n },\n waitForNetworkIdle(): Promise<void> {\n return rejectUnsupported(\"waitForNetworkIdle\");\n },\n\n // scripting & artifacts ------------------------------------------------\n evaluate<R = unknown>(): Promise<R> {\n return rejectUnsupported(\"evalScript\") as Promise<R>;\n },\n async screenshot(screenshotOptions: { path: string; fullPage?: boolean }): Promise<void> {\n await client.request(\"screenshot\", { path: screenshotOptions.path });\n },\n\n // network / dialogs / downloads (all web-only) -------------------------\n onResponse(_handler: (response: DriverResponse) => void): void {\n throw unsupported(\"onResponse\");\n },\n route(_url: string, _handler: (route: DriverRoute) => void | Promise<void>): Promise<void> {\n return rejectUnsupported(\"mockRoute\");\n },\n unroute(): Promise<void> {\n return rejectUnsupported(\"unmockRoute\");\n },\n onDialog(_action: DialogAction): void {\n throw unsupported(\"onDialog\");\n },\n waitForDownloadEvent(): Promise<DriverDownload> {\n return rejectUnsupported(\"waitForDownload\") as Promise<DriverDownload>;\n },\n\n parseTextSelector(selector: string): string | null {\n return unwrapMacTextSelector(selector);\n }\n };\n}\n","/**\n * PROWL-048 / ARCH-002 — transport + launch/teardown for the macOS target.\n *\n * Spawns the `prowl-macdriver` Swift helper in `serve` mode and speaks its\n * newline-delimited JSON protocol (one request/response per line, matched by\n * id). The helper is built locally (`swift build` in `macdriver/`) and is NOT\n * bundled in the npm package, so binary resolution fails with a clear \"build\n * the helper\" message rather than crashing.\n */\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createMacDriver, type MacHelperClient } from \"./mac-driver.js\";\nimport type { SessionDriver } from \"./driver.js\";\n\nexport const HELPER_BINARY = \"prowl-macdriver\";\n\nexport function macdriverBuildInstructions(): string {\n return (\n \"The macOS target requires the experimental `prowl-macdriver` helper, which is \" +\n \"not shipped in the npm package. Build it locally:\\n\" +\n \" cd macdriver && swift build -c release\\n\" +\n \"or point Prowl at a prebuilt binary via the PROWL_MACDRIVER_BIN environment variable.\"\n );\n}\n\nfunction getPackageRoot(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n const root = path.parse(dir).root;\n while (dir !== root) {\n if (fs.existsSync(path.join(dir, \"package.json\"))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return root;\n}\n\n/**\n * Resolve the helper binary path. Order: `PROWL_MACDRIVER_BIN`, then the\n * release then debug build under `macdriver/.build/`. Throws with build\n * instructions when none is found.\n */\nexport function resolveHelperBinary(env: NodeJS.ProcessEnv = process.env): string {\n const override = env.PROWL_MACDRIVER_BIN;\n if (override) {\n if (!fs.existsSync(override)) {\n throw new Error(\n `PROWL_MACDRIVER_BIN points at a missing file: ${override}\\n${macdriverBuildInstructions()}`\n );\n }\n return override;\n }\n\n const root = getPackageRoot();\n const candidates = [\n path.join(root, \"macdriver\", \".build\", \"release\", HELPER_BINARY),\n path.join(root, \"macdriver\", \".build\", \"debug\", HELPER_BINARY)\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n throw new Error(`Could not find the ${HELPER_BINARY} helper binary.\\n${macdriverBuildInstructions()}`);\n}\n\ntype Pending = {\n cmd: string;\n resolve: (result: Record<string, unknown>) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n};\n\n/** Default per-request deadline for the helper transport. */\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 30000;\n\nexport type SpawnMacHelperOptions = {\n /** Per-request deadline; a request that gets no response by then rejects. */\n requestTimeoutMs?: number;\n};\n\n/** A {@link MacHelperClient} backed by a spawned `prowl-macdriver serve` process. */\nexport class SpawnMacHelperClient implements MacHelperClient {\n private readonly child: ChildProcess;\n private readonly pending = new Map<number, Pending>();\n private readonly requestTimeoutMs: number;\n private stdoutBuffer = \"\";\n private stderrBuffer = \"\";\n private nextId = 1;\n private closed = false;\n private terminalError: Error | undefined;\n\n constructor(binaryPath: string, options: SpawnMacHelperOptions = {}) {\n this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.child = spawn(binaryPath, [\"serve\"], { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n this.child.stdout?.setEncoding(\"utf-8\");\n this.child.stderr?.setEncoding(\"utf-8\");\n this.child.stdout?.on(\"data\", (chunk: string) => this.onStdout(chunk));\n this.child.stderr?.on(\"data\", (chunk: string) => {\n this.stderrBuffer = (this.stderrBuffer + chunk).slice(-4000);\n });\n this.child.on(\"error\", (error) => this.recordTerminalFailure(error));\n this.child.on(\"exit\", (code) => {\n if (!this.closed) {\n const detail = this.stderrBuffer.trim();\n this.recordTerminalFailure(\n new Error(`prowl-macdriver exited unexpectedly (code ${code ?? \"null\"})${detail ? `: ${detail}` : \"\"}`)\n );\n }\n });\n }\n\n private onStdout(chunk: string): void {\n this.stdoutBuffer += chunk;\n let newlineIndex = this.stdoutBuffer.indexOf(\"\\n\");\n while (newlineIndex !== -1) {\n const line = this.stdoutBuffer.slice(0, newlineIndex).trim();\n this.stdoutBuffer = this.stdoutBuffer.slice(newlineIndex + 1);\n if (line.length > 0) {\n this.dispatch(line);\n }\n newlineIndex = this.stdoutBuffer.indexOf(\"\\n\");\n }\n }\n\n private dispatch(line: string): void {\n let message: Record<string, unknown>;\n try {\n message = JSON.parse(line) as Record<string, unknown>;\n } catch {\n return; // ignore non-JSON noise\n }\n const id = typeof message.id === \"number\" ? message.id : undefined;\n if (id === undefined) {\n return;\n }\n const pending = this.pending.get(id);\n if (!pending) {\n return;\n }\n this.pending.delete(id);\n clearTimeout(pending.timer);\n if (message.ok === true) {\n pending.resolve((message.result as Record<string, unknown>) ?? {});\n } else {\n pending.reject(new Error(typeof message.error === \"string\" ? message.error : \"prowl-macdriver error\"));\n }\n }\n\n private failAll(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timer);\n pending.reject(error);\n }\n this.pending.clear();\n }\n\n private recordTerminalFailure(error: Error): void {\n this.terminalError ??= error;\n this.closed = true;\n this.failAll(this.terminalError);\n }\n\n /** Number of in-flight requests awaiting a response (for teardown/tests). */\n get pendingCount(): number {\n return this.pending.size;\n }\n\n request(cmd: string, params: Record<string, unknown> = {}): Promise<Record<string, unknown>> {\n if (this.terminalError) {\n return Promise.reject(this.terminalError);\n }\n if (this.closed) {\n return Promise.reject(new Error(\"prowl-macdriver client is closed\"));\n }\n const id = this.nextId++;\n const payload = JSON.stringify({ id, cmd, ...params });\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.pending.delete(id)) {\n const shown =\n this.requestTimeoutMs >= 1000\n ? `${Math.round(this.requestTimeoutMs / 1000)}s`\n : `${this.requestTimeoutMs}ms`;\n reject(new Error(`prowl-macdriver request \"${cmd}\" timed out after ${shown}`));\n }\n }, this.requestTimeoutMs);\n // Don't let a pending deadline keep the event loop alive on its own.\n timer.unref?.();\n this.pending.set(id, { cmd, resolve, reject, timer });\n this.child.stdin?.write(payload + \"\\n\", (error) => {\n if (error && this.pending.delete(id)) {\n clearTimeout(timer);\n reject(error);\n }\n });\n });\n }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n this.closed = true;\n try {\n this.child.stdin?.write(JSON.stringify({ cmd: \"shutdown\" }) + \"\\n\");\n this.child.stdin?.end();\n } catch {\n // best effort\n }\n await new Promise<void>((resolve) => {\n if (this.child.exitCode !== null || this.child.signalCode !== null) {\n resolve();\n return;\n }\n const timer = setTimeout(() => {\n this.child.kill(\"SIGKILL\");\n resolve();\n }, 2000);\n this.child.once(\"exit\", () => {\n clearTimeout(timer);\n resolve();\n });\n });\n this.failAll(new Error(\"prowl-macdriver client is closed\"));\n }\n}\n\nexport type MacSession = {\n client: MacHelperClient;\n driver: SessionDriver;\n bundleId: string;\n};\n\nexport type LaunchMacOptions = {\n /** Bundle id or absolute `.app` path. */\n app: string;\n timeoutMs?: number;\n /** Inject a helper client (tests / a prebuilt binary); defaults to spawning the helper. */\n clientFactory?: () => MacHelperClient;\n};\n\n/** Launch/attach the target app through the helper and build a {@link MacDriver}. */\nexport async function launchMacSession(options: LaunchMacOptions): Promise<MacSession> {\n // Give the transport headroom over the app-level timeout so a legitimately\n // slow verb (launch, waitFor) isn't killed early by the request deadline.\n const requestTimeoutMs = Math.max(options.timeoutMs ?? 10000, DEFAULT_REQUEST_TIMEOUT_MS) + 5000;\n const client = options.clientFactory\n ? options.clientFactory()\n : new SpawnMacHelperClient(resolveHelperBinary(), { requestTimeoutMs });\n const timeoutSeconds = (options.timeoutMs ?? 10000) / 1000;\n\n try {\n const trust = await client.request(\"check\");\n if (trust.trusted !== true) {\n throw new Error(\n \"Prowl's macOS target is not trusted for Accessibility. Grant the hosting terminal/app \" +\n \"permission in System Settings → Privacy & Security → Accessibility, then retry.\"\n );\n }\n const launched = await client.request(\"launch\", { app: options.app, timeout: timeoutSeconds });\n const bundleId = String(launched.bundleId ?? options.app);\n const driver = createMacDriver(client, { appLabel: bundleId });\n return { client, driver, bundleId };\n } catch (error) {\n await client.close().catch(() => undefined);\n throw error;\n }\n}\n\n/** Quit the target app (best effort) and shut the helper down. */\nexport async function closeMacSession(session: MacSession): Promise<void> {\n try {\n await session.client.request(\"quit\");\n } catch {\n // best effort — the app may already be gone\n } finally {\n await session.client.close();\n }\n}\n","/**\n * The minimal probe surface healing needs: count matches for a candidate\n * selector. A live Playwright page and a {@link SessionDriver}-backed adapter\n * both satisfy it, so healing carries no Playwright dependency.\n */\nexport type SelectorProbe = {\n locator(selector: string): { count(): Promise<number> };\n};\n\n/**\n * Self-healing selectors (PROWL-023). When an explicit selector matches nothing,\n * derive the human \"intent\" from the selector and try alternative strategies —\n * fuzzy text, ARIA label, and structural (interactive element + text) — healing\n * ONLY to a candidate that resolves to exactly one element. Opt-in via\n * `guardrails.selfHealing`; never guesses among multiple matches.\n */\n\nexport type HealResult = {\n /** The candidate selector that uniquely matched. */\n selector: string;\n /** The original selector that failed. */\n healedFrom: string;\n /** Which strategy produced the match (for reporting). */\n strategy: \"text\" | \"aria\" | \"structural\";\n};\n\nconst INTERACTIVE_TAGS = [\"button\", \"a\", \"input\", \"select\", \"textarea\"];\n\n/**\n * Pull human-meaningful words out of a raw selector. Reads id (`#submit-btn`),\n * class tokens (`.login-form`), and attribute values (`[data-testid=\"sign-in\"]`,\n * `[aria-label='Close']`), splitting on separators and camelCase. Returns the\n * lowercased words (de-duped, in order) and a space-joined label. Mapping is\n * intentionally literal/predictable — no noise-word filtering.\n */\nexport function extractSelectorIntent(selector: string): { words: string[]; label: string } {\n const raw: string[] = [];\n\n // #id and .class tokens\n for (const match of selector.matchAll(/[#.]([A-Za-z_][\\w-]*)/g)) {\n raw.push(match[1]);\n }\n // attribute values: [attr=\"value\"] / [attr='value'] / [attr=value]\n for (const match of selector.matchAll(/\\[[A-Za-z_:-]+\\s*[~|^$*]?=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\]\\s]+))\\]/g)) {\n const value = match[1] ?? match[2] ?? match[3];\n if (value) raw.push(value);\n }\n\n const words: string[] = [];\n for (const token of raw) {\n for (const part of splitToken(token)) {\n const lower = part.toLowerCase();\n if (lower.length > 0 && !words.includes(lower)) {\n words.push(lower);\n }\n }\n }\n\n return { words, label: words.join(\" \") };\n}\n\nfunction splitToken(token: string): string[] {\n return token\n // camelCase / PascalCase boundaries\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n // separators\n .split(/[\\s\\-_.:]+/)\n .filter((part) => part.length > 0);\n}\n\n/**\n * Build candidate Playwright selectors for a derived intent, in AC priority order:\n * (1) fuzzy text, (2) ARIA label, (3) structural (interactive element + text).\n * Returns [] when the selector carried no usable words.\n */\nexport function buildHealCandidates(selector: string): Array<{ selector: string; strategy: HealResult[\"strategy\"] }> {\n const { words, label } = extractSelectorIntent(selector);\n if (words.length === 0) return [];\n\n const escaped = label.replace(/\"/g, '\\\\\"');\n const candidates: Array<{ selector: string; strategy: HealResult[\"strategy\"] }> = [];\n\n // 1. Similar text content (case-insensitive substring via Playwright text engine)\n candidates.push({ selector: `text=${label}`, strategy: \"text\" });\n\n // 2. Similar ARIA label (case-insensitive attribute substring)\n candidates.push({ selector: `[aria-label*=\"${escaped}\" i]`, strategy: \"aria\" });\n\n // 3. Nearby element with matching structure: an interactive element containing the text\n for (const tag of INTERACTIVE_TAGS) {\n candidates.push({ selector: `${tag}:has-text(\"${escaped}\")`, strategy: \"structural\" });\n }\n\n return candidates;\n}\n\n/**\n * Attempt to heal a failed selector. Returns a HealResult only when a candidate\n * resolves to exactly one element; otherwise null. Counting is delegated so this\n * is unit-testable with a fake page.\n */\nexport async function healSelector(\n probe: SelectorProbe,\n selector: string,\n options: { enabled: boolean }\n): Promise<HealResult | null> {\n if (!options.enabled) return null;\n\n for (const candidate of buildHealCandidates(selector)) {\n let count: number;\n try {\n const locator = probe.locator(candidate.selector);\n count = await locator.count();\n } catch {\n continue; // ignore candidates the engine cannot parse\n }\n if (count === 1) {\n return { selector: candidate.selector, healedFrom: selector, strategy: candidate.strategy };\n }\n }\n\n return null;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { HistoryEntry, HistoryFile } from \"../types/index.js\";\n\nconst HISTORY_FILE = \"history.json\";\nconst LOCK_FILE_SUFFIX = \".lock\";\nconst LOCK_RETRY_MS = 10;\nconst LOCK_TIMEOUT_MS = 5000;\nconst SLEEP_BUFFER = new Int32Array(new SharedArrayBuffer(4));\n\nfunction historyPath(configDir: string): string {\n return path.join(configDir, HISTORY_FILE);\n}\n\nfunction isHistoryEntry(value: unknown): value is HistoryEntry {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const entry = value as Record<string, unknown>;\n return (\n typeof entry.hunt === \"string\" &&\n (entry.status === \"pass\" || entry.status === \"fail\") &&\n typeof entry.durationMs === \"number\" &&\n Number.isFinite(entry.durationMs) &&\n typeof entry.startedAt === \"string\" &&\n (entry.runDir === undefined || typeof entry.runDir === \"string\")\n );\n}\n\nexport function readHistory(configDir: string): HistoryFile {\n const filePath = historyPath(configDir);\n if (!fs.existsSync(filePath)) {\n return { entries: [] };\n }\n try {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"entries\" in parsed &&\n Array.isArray((parsed as { entries: unknown }).entries)\n ) {\n const validatedEntries = (parsed as { entries: unknown[] }).entries.filter(isHistoryEntry);\n return { entries: validatedEntries };\n }\n return { entries: [] };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.warn(`Failed to read history file at ${filePath}: ${message}`);\n return { entries: [] };\n }\n}\n\nexport function readHuntHistory(configDir: string, huntName: string): HistoryEntry[] {\n const { entries } = readHistory(configDir);\n return entries.filter((entry) => entry.hunt === huntName);\n}\n\nexport function pruneEntries(entries: HistoryEntry[], maxRuns: number): HistoryEntry[] {\n const perHunt = new Map<string, HistoryEntry[]>();\n for (const entry of entries) {\n const list = perHunt.get(entry.hunt) ?? [];\n list.push(entry);\n perHunt.set(entry.hunt, list);\n }\n\n const keptEntries = new Set<HistoryEntry>();\n for (const list of perHunt.values()) {\n const kept = list.length > maxRuns ? list.slice(list.length - maxRuns) : list;\n for (const entry of kept) {\n keptEntries.add(entry);\n }\n }\n return entries.filter((entry) => keptEntries.has(entry));\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(SLEEP_BUFFER, 0, 0, ms);\n}\n\nfunction withHistoryLock<T>(configDir: string, fn: () => T): T {\n const filePath = historyPath(configDir);\n const lockPath = `${filePath}${LOCK_FILE_SUFFIX}`;\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const startedAt = Date.now();\n\n while (Date.now() - startedAt < LOCK_TIMEOUT_MS) {\n let fd: number;\n try {\n fd = fs.openSync(lockPath, \"wx\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n sleepSync(LOCK_RETRY_MS);\n continue;\n }\n throw error;\n }\n\n try {\n return fn();\n } finally {\n try {\n fs.closeSync(fd);\n } catch {\n // Ignore close failures during cleanup.\n }\n fs.rmSync(lockPath, { force: true });\n }\n }\n\n throw new Error(\n `Failed to acquire history lock before timeout (${LOCK_TIMEOUT_MS}ms): ${lockPath}; started waiting at ${new Date(startedAt).toISOString()}`\n );\n}\n\nexport function appendEntry(\n configDir: string,\n entry: HistoryEntry,\n maxRuns: number\n): void {\n const filePath = historyPath(configDir);\n withHistoryLock(configDir, () => {\n const current = readHistory(configDir);\n const next = pruneEntries([...current.entries, entry], maxRuns);\n const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n fs.writeFileSync(tempPath, `${JSON.stringify({ entries: next }, null, 2)}\\n`);\n fs.renameSync(tempPath, filePath);\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AssertionResult, BrowserChannel, Config, MacosTarget, RunResult, Step, StepResult, TraceCorrelation } from \"../types/index.js\";\nimport { loadConfig, loadHunt, ensureAllowedDomain, resolveViewport } from \"../config/loader.js\";\nimport { interpolateHunt } from \"../config/interpolate.js\";\nimport {\n assertHuntAssertionsSupportedByTarget,\n assertStepsSupportedByTarget,\n assertTargetAppAllowed\n} from \"../config/target.js\";\nimport { launchBrowser, closeBrowser, createPlaywrightDriver } from \"../browser/controller.js\";\nimport { launchMacSession, closeMacSession } from \"../browser/mac-helper.js\";\nimport type { MacHelperClient } from \"../browser/mac-driver.js\";\nimport { captureFinalScreenshot, executeSteps, type StepCallback } from \"./steps.js\";\nimport { evaluateAssertions, type ConsoleEntry, type NetworkEntry } from \"./assertions.js\";\nimport { captureTraceCorrelation, DEFAULT_TRACE_HEADER } from \"./tracing.js\";\nimport { writeReports } from \"../reporter/index.js\";\nimport { timestamp } from \"../utils/timestamp.js\";\nimport { appendEntry as appendHistoryEntry } from \"./history.js\";\n\nexport type RunOptions = {\n huntName: string;\n urlOverride?: string;\n headed?: boolean;\n slowMo?: number;\n trace?: boolean;\n configPath?: string;\n onStep?: StepCallback;\n browser?: \"chromium\" | \"firefox\" | \"webkit\";\n channel?: BrowserChannel;\n viewport?: string;\n junit?: boolean;\n /** Inject a macOS helper client (tests / a prebuilt binary); defaults to spawning the helper. */\n macClientFactory?: () => MacHelperClient;\n};\n\nfunction parseViewportFlag(value: string): string | { width: number; height: number } {\n const match = /^(\\d+)x(\\d+)$/i.exec(value);\n if (match) {\n return { width: Number(match[1]), height: Number(match[2]) };\n }\n return value;\n}\n\nfunction resolvePath(configDir: string, inputPath: string): string {\n if (path.isAbsolute(inputPath)) {\n return inputPath;\n }\n const projectRoot = path.dirname(configDir);\n return path.join(projectRoot, inputPath);\n}\n\nfunction buildRunResult(options: {\n status: \"pass\" | \"fail\";\n startedAt: string;\n durationMs: number;\n hunt: string;\n targetUrl: string;\n steps: StepResult[];\n assertions: AssertionResult[];\n artifacts: RunResult[\"artifacts\"];\n traceCorrelations?: TraceCorrelation[];\n}): RunResult {\n return {\n status: options.status,\n exitCode: options.status === \"pass\" ? 0 : 1,\n startedAt: options.startedAt,\n durationMs: options.durationMs,\n hunt: options.hunt,\n targetUrl: options.targetUrl,\n steps: options.steps,\n assertions: options.assertions,\n artifacts: options.artifacts,\n // Omit entirely when there are no correlations, so passing/clean runs stay tidy.\n ...(options.traceCorrelations && options.traceCorrelations.length > 0\n ? { traceCorrelations: options.traceCorrelations }\n : {})\n };\n}\n\nfunction writeConsoleLog(runDir: string, entries: ConsoleEntry[]): string {\n const fileName = \"console.log\";\n const filePath = path.join(runDir, fileName);\n const lines = entries.map((entry) => {\n const location = entry.location ? ` (${entry.location})` : \"\";\n return `[${entry.type}] ${entry.text}${location}`;\n });\n fs.writeFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n return fileName;\n}\n\nasync function executeHuntAttempt(\n options: RunOptions,\n config: ReturnType<typeof loadConfig>[\"config\"],\n configDir: string,\n interpolatedHunt: ReturnType<typeof interpolateHunt>[\"hunt\"],\n redactedFillSteps: Set<string>,\n randomVars: ReturnType<typeof interpolateHunt>[\"randomVars\"],\n redactionValues: readonly string[],\n targetUrl: string,\n allowedDomains: string[]\n): Promise<{ result: RunResult; runDir: string; steps: Step[] }> {\n const headless = options.headed ? false : config.browser.headless;\n const slowMo = options.slowMo ?? config.browser.slowMo;\n const maxSteps = config.guardrails.maxSteps;\n\n const runDir = path.join(configDir, \"runs\", timestamp());\n fs.mkdirSync(runDir, { recursive: true });\n\n const storageStatePath = config.auth.storageStatePath\n ? resolvePath(configDir, config.auth.storageStatePath)\n : undefined;\n\n const engine = options.browser ?? config.browser.engine;\n const channel = options.channel ?? config.browser.channel;\n const viewport = options.viewport\n ? resolveViewport(parseViewportFlag(options.viewport))\n : config.browser.viewport;\n\n const session = await launchBrowser({\n headless,\n slowMo,\n timeout: config.browser.timeout,\n storageStatePath,\n trace: Boolean(options.trace),\n recordHar: config.artifacts.networkHar,\n runDir,\n engine,\n channel,\n viewport\n });\n\n let result: RunResult;\n try {\n const driver = createPlaywrightDriver(session.page);\n const consoleEntries: ConsoleEntry[] = [];\n const networkEntries: NetworkEntry[] = [];\n const traceCorrelations: TraceCorrelation[] = [];\n const traceHeader = config.tracing?.header ?? DEFAULT_TRACE_HEADER;\n\n session.page.on(\"console\", (message) => {\n consoleEntries.push({\n type: message.type(),\n text: message.text(),\n location: message.location().url\n });\n });\n\n driver.onResponse((response) => {\n if (response.status() >= 400) {\n networkEntries.push({ url: response.url(), status: response.status() });\n captureTraceCorrelation(response, traceHeader, traceCorrelations, redactionValues);\n }\n });\n\n const startedAt = new Date().toISOString();\n const startTime = Date.now();\n\n let stepResults: StepResult[] = [];\n let stepScreenshots: string[] = [];\n let stepFailed = false;\n\n try {\n const stepExecution = await executeSteps({\n page: session.page,\n driver,\n steps: interpolatedHunt.steps,\n targetUrl,\n runDir,\n screenshotsMode: config.artifacts.screenshots,\n forbiddenSelectors: config.guardrails.forbiddenSelectors,\n allowedDomains,\n maxSteps,\n maxTotalTimeMs: config.assertions.maxTotalTimeMs,\n selfHealing: config.guardrails.selfHealing,\n redactedFillSteps,\n randomVars,\n configDir,\n huntStack: [options.huntName],\n onStep: options.onStep\n });\n\n stepResults = stepExecution.results;\n stepScreenshots = stepExecution.screenshots;\n stepFailed = stepExecution.failed;\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Step execution failed\";\n stepResults = [\n {\n type: \"steps\",\n status: \"fail\",\n durationMs: 0,\n error: message\n }\n ];\n stepFailed = true;\n }\n\n let finalScreenshot: string | undefined;\n try {\n finalScreenshot = await captureFinalScreenshot(driver, runDir);\n } catch {\n finalScreenshot = undefined;\n }\n\n const assertionResults = await evaluateAssertions({\n page: session.page,\n config,\n huntAssertions: interpolatedHunt.assertions,\n consoleEntries,\n networkEntries\n });\n\n const durationMs = Date.now() - startTime;\n const assertionsFailed = assertionResults.some((assertion) => assertion.status === \"fail\");\n\n const status: \"pass\" | \"fail\" = stepFailed || assertionsFailed ? \"fail\" : \"pass\";\n\n const artifacts: RunResult[\"artifacts\"] = {\n screenshots: finalScreenshot\n ? [...stepScreenshots, finalScreenshot]\n : stepScreenshots,\n trace: session.tracePath ? \"trace.zip\" : undefined,\n networkHar: config.artifacts.networkHar ? \"network.har\" : undefined\n };\n\n if (config.artifacts.console) {\n artifacts.console = writeConsoleLog(runDir, consoleEntries);\n }\n\n const runResult = buildRunResult({\n status,\n startedAt,\n durationMs,\n hunt: options.huntName,\n targetUrl,\n steps: stepResults,\n assertions: assertionResults,\n artifacts,\n traceCorrelations\n });\n\n result = writeReports(runDir, runResult, { junit: options.junit ?? config.artifacts.junit });\n } finally {\n await closeBrowser(session);\n }\n\n return { result, runDir, steps: interpolatedHunt.steps };\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function runHunt(\n options: RunOptions\n): Promise<{ result: RunResult; runDir: string; steps: Step[] }> {\n const { config, configDir } = loadConfig(options.configPath);\n\n if (config.target.type === \"macos\") {\n return runMacHunt(options, config, configDir, config.target);\n }\n\n const hunt = loadHunt(options.huntName, configDir);\n const {\n hunt: interpolatedHunt,\n redactedFillSteps,\n randomVars,\n redactionValues = []\n } = interpolateHunt(\n hunt,\n process.env\n );\n\n const targetUrl = options.urlOverride ?? config.target.url;\n const allowedDomains = ensureAllowedDomain([...config.guardrails.allowedDomains], targetUrl);\n const maxSteps = config.guardrails.maxSteps;\n\n if (interpolatedHunt.steps.length > maxSteps) {\n throw new Error(`Hunt has ${interpolatedHunt.steps.length} steps. Max allowed is ${maxSteps}.`);\n }\n\n const maxRetries = hunt.retry?.maxRetries ?? 0;\n const retryDelay = hunt.retry?.delay ?? 0;\n\n let lastResult: { result: RunResult; runDir: string; steps: Step[] } | undefined;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (attempt > 0 && retryDelay > 0) {\n await delay(retryDelay);\n }\n\n lastResult = await executeHuntAttempt(\n options,\n config,\n configDir,\n interpolatedHunt,\n redactedFillSteps,\n randomVars,\n redactionValues,\n targetUrl,\n allowedDomains\n );\n\n if (lastResult.result.status === \"pass\") {\n if (attempt > 0) {\n lastResult.result.artifacts.summary =\n `Passed on attempt ${attempt + 1} of ${maxRetries + 1}`;\n }\n recordHistory(configDir, lastResult, config.history.maxRuns);\n return lastResult;\n }\n }\n\n if (maxRetries > 0 && lastResult) {\n lastResult.result.artifacts.summary =\n `Failed after ${maxRetries + 1} attempts`;\n }\n\n if (lastResult) {\n recordHistory(configDir, lastResult, config.history.maxRuns);\n }\n\n return lastResult!;\n}\n\n// ---------------------------------------------------------------------------\n// macOS native target (PROWL-048). A dedicated run path: no browser, no console/\n// network assertions or HAR/trace (all web concepts). Steps run through the\n// MacDriver over the prowl-macdriver helper; artifacts are step + final\n// screenshots and the usual reports.\n// ---------------------------------------------------------------------------\n\nasync function executeMacHuntAttempt(\n options: RunOptions,\n config: Config,\n configDir: string,\n target: MacosTarget,\n interpolatedHunt: ReturnType<typeof interpolateHunt>[\"hunt\"],\n redactedFillSteps: Set<string>,\n randomVars: ReturnType<typeof interpolateHunt>[\"randomVars\"],\n allowedApps: string[]\n): Promise<{ result: RunResult; runDir: string; steps: Step[] }> {\n const maxSteps = config.guardrails.maxSteps;\n const runDir = path.join(configDir, \"runs\", timestamp());\n fs.mkdirSync(runDir, { recursive: true });\n\n const session = await launchMacSession({\n app: target.app,\n timeoutMs: config.browser.timeout,\n clientFactory: options.macClientFactory\n });\n\n let result: RunResult;\n try {\n const targetLabel = `macos:${session.bundleId}`;\n const effectiveAllowedApps = [...new Set([...allowedApps, target.app, session.bundleId])];\n const startedAt = new Date().toISOString();\n const startTime = Date.now();\n\n let stepResults: StepResult[] = [];\n let stepScreenshots: string[] = [];\n let stepFailed = false;\n\n try {\n const stepExecution = await executeSteps({\n driver: session.driver,\n steps: interpolatedHunt.steps,\n targetUrl: targetLabel,\n runDir,\n screenshotsMode: config.artifacts.screenshots,\n forbiddenSelectors: config.guardrails.forbiddenSelectors,\n allowedDomains: [],\n allowedApps: effectiveAllowedApps,\n maxSteps,\n maxTotalTimeMs: config.assertions.maxTotalTimeMs,\n selfHealing: config.guardrails.selfHealing,\n redactedFillSteps,\n randomVars,\n configDir,\n huntStack: [options.huntName],\n onStep: options.onStep\n });\n stepResults = stepExecution.results;\n stepScreenshots = stepExecution.screenshots;\n stepFailed = stepExecution.failed;\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Step execution failed\";\n stepResults = [{ type: \"steps\", status: \"fail\", durationMs: 0, error: message }];\n stepFailed = true;\n }\n\n let finalScreenshot: string | undefined;\n try {\n finalScreenshot = await captureFinalScreenshot(session.driver, runDir);\n } catch {\n finalScreenshot = undefined;\n }\n\n const durationMs = Date.now() - startTime;\n const status: \"pass\" | \"fail\" = stepFailed ? \"fail\" : \"pass\";\n const artifacts: RunResult[\"artifacts\"] = {\n screenshots: finalScreenshot ? [...stepScreenshots, finalScreenshot] : stepScreenshots\n };\n\n const runResult = buildRunResult({\n status,\n startedAt,\n durationMs,\n hunt: options.huntName,\n targetUrl: targetLabel,\n steps: stepResults,\n assertions: [],\n artifacts\n });\n\n result = writeReports(runDir, runResult, { junit: options.junit ?? config.artifacts.junit });\n } finally {\n await closeMacSession(session);\n }\n\n return { result, runDir, steps: interpolatedHunt.steps };\n}\n\nasync function runMacHunt(\n options: RunOptions,\n config: Config,\n configDir: string,\n target: MacosTarget\n): Promise<{ result: RunResult; runDir: string; steps: Step[] }> {\n const hunt = loadHunt(options.huntName, configDir);\n const { hunt: interpolatedHunt, redactedFillSteps, randomVars } = interpolateHunt(hunt, process.env);\n\n // Fail fast on web-only steps/assertions and out-of-scope apps before launching anything.\n assertStepsSupportedByTarget(interpolatedHunt.steps, \"macos\");\n assertHuntAssertionsSupportedByTarget(interpolatedHunt.assertions, \"macos\");\n assertTargetAppAllowed(config.guardrails.allowedApps, target.app);\n\n const maxSteps = config.guardrails.maxSteps;\n if (interpolatedHunt.steps.length > maxSteps) {\n throw new Error(`Hunt has ${interpolatedHunt.steps.length} steps. Max allowed is ${maxSteps}.`);\n }\n\n const maxRetries = hunt.retry?.maxRetries ?? 0;\n const retryDelay = hunt.retry?.delay ?? 0;\n let lastResult: { result: RunResult; runDir: string; steps: Step[] } | undefined;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (attempt > 0 && retryDelay > 0) {\n await delay(retryDelay);\n }\n lastResult = await executeMacHuntAttempt(\n options,\n config,\n configDir,\n target,\n interpolatedHunt,\n redactedFillSteps,\n randomVars,\n config.guardrails.allowedApps\n );\n if (lastResult.result.status === \"pass\") {\n if (attempt > 0) {\n lastResult.result.artifacts.summary = `Passed on attempt ${attempt + 1} of ${maxRetries + 1}`;\n }\n recordHistory(configDir, lastResult, config.history.maxRuns);\n return lastResult;\n }\n }\n\n if (maxRetries > 0 && lastResult) {\n lastResult.result.artifacts.summary = `Failed after ${maxRetries + 1} attempts`;\n }\n if (lastResult) {\n recordHistory(configDir, lastResult, config.history.maxRuns);\n }\n return lastResult!;\n}\n\nfunction recordHistory(\n configDir: string,\n outcome: { result: RunResult; runDir: string },\n maxRuns: number\n): void {\n try {\n const relativeRunDir = path.relative(configDir, outcome.runDir);\n appendHistoryEntry(\n configDir,\n {\n hunt: outcome.result.hunt,\n status: outcome.result.status,\n durationMs: outcome.result.durationMs,\n startedAt: outcome.result.startedAt,\n runDir: relativeRunDir || undefined\n },\n maxRuns\n );\n } catch {\n // History is observability only; a write failure must never break a run.\n }\n}\n","/**\n * PROWL-047 / ARCH-001 — Playwright implementation of {@link SessionDriver}.\n *\n * This is the ONLY module in the codebase that imports Playwright at runtime;\n * everything else drives the session through the engine-neutral `SessionDriver`\n * interface. Browser launch/teardown lives here too (re-exported by\n * `controller.ts` to keep the public import path stable), so the Playwright\n * dependency is confined to this file.\n *\n * Every driver method is a faithful pass-through to the exact Playwright\n * Page/Locator call the legacy runner made — this refactor changes structure,\n * not behaviour.\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n chromium,\n firefox,\n webkit,\n type Browser,\n type BrowserContext,\n type Page\n} from \"playwright\";\nimport type { BrowserChannel, BrowserEngine, Viewport } from \"../types/index.js\";\nimport type {\n DialogAction,\n DriverCapability,\n DriverDownload,\n DriverResponse,\n DriverRoute,\n NavigateOptions,\n SessionDriver\n} from \"./driver.js\";\n\nconst ENGINES = { chromium, firefox, webkit } as const;\n\nexport type BrowserSession = {\n browser: Browser;\n context: BrowserContext;\n page: Page;\n tracePath?: string;\n};\n\nexport type BrowserOptions = {\n headless: boolean;\n slowMo: number;\n timeout: number;\n storageStatePath?: string;\n trace: boolean;\n recordHar: boolean;\n runDir: string;\n engine?: BrowserEngine;\n channel?: BrowserChannel;\n viewport?: Viewport;\n};\n\nexport async function launchBrowser(options: BrowserOptions): Promise<BrowserSession> {\n const engineName = options.engine ?? \"chromium\";\n const engine = Object.prototype.hasOwnProperty.call(ENGINES, engineName)\n ? ENGINES[engineName as keyof typeof ENGINES]\n : undefined;\n if (!engine) {\n throw new Error(\n `Unsupported browser engine \"${String(engineName)}\". Available engines: ${Object.keys(ENGINES).join(\", \")}.`\n );\n }\n const browser = await engine.launch({\n headless: options.headless,\n slowMo: options.slowMo,\n channel: options.channel\n });\n\n try {\n const contextOptions: Parameters<typeof browser.newContext>[0] = {};\n\n if (options.viewport) {\n contextOptions.viewport = options.viewport;\n }\n\n if (options.storageStatePath) {\n if (fs.existsSync(options.storageStatePath)) {\n contextOptions.storageState = options.storageStatePath;\n } else {\n console.warn(`Auth state file not found: ${options.storageStatePath}. Run \"prowl login\" to create it.`);\n }\n }\n\n if (options.recordHar) {\n contextOptions.recordHar = { path: path.join(options.runDir, \"network.har\") };\n }\n\n const context = await browser.newContext(contextOptions);\n const page = await context.newPage();\n page.setDefaultTimeout(options.timeout);\n page.setDefaultNavigationTimeout(options.timeout);\n\n let tracePath: string | undefined;\n if (options.trace) {\n tracePath = path.join(options.runDir, \"trace.zip\");\n await context.tracing.start({ screenshots: true, snapshots: true, sources: true });\n }\n\n return { browser, context, page, tracePath };\n } catch (error) {\n try {\n await browser.close();\n } catch (closeError) {\n console.warn(`Failed to close browser after setup error: ${formatError(closeError)}`);\n }\n throw error;\n }\n}\n\nexport async function closeBrowser(session: BrowserSession): Promise<void> {\n try {\n if (session.tracePath) {\n await session.context.tracing.stop({ path: session.tracePath });\n }\n await session.context.close();\n } finally {\n await session.browser.close();\n }\n}\n\n/** Persist the session's storage state (cookies + localStorage) to disk. */\nexport async function saveStorageState(session: BrowserSession, storageStatePath: string): Promise<void> {\n await session.context.storageState({ path: storageStatePath });\n}\n\nconst ALL_CAPABILITIES: ReadonlySet<DriverCapability> = new Set<DriverCapability>([\n \"navigate\",\n \"query\",\n \"interact\",\n \"wait\",\n \"screenshot\",\n \"evaluate\",\n \"response\",\n \"route\",\n \"dialog\",\n \"files\",\n \"download\"\n]);\n\ntype PlaywrightRole = Parameters<Page[\"getByRole\"]>[0];\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction unwrapTextSelector(value: string): string | null {\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"text=\")) {\n return null;\n }\n const raw = trimmed.slice(5);\n const first = raw[0];\n if (first === '\"' || first === \"'\") {\n const unquoted = raw.slice(1);\n return unquoted.endsWith(first) ? unquoted.slice(0, -1) : unquoted;\n }\n return raw;\n}\n\n/**\n * Wrap a live Playwright {@link Page} as a {@link SessionDriver}. Each method\n * delegates to the same Page/Locator call the runner previously made inline.\n */\nexport function createPlaywrightDriver(page: Page): SessionDriver {\n return {\n capabilities: ALL_CAPABILITIES,\n\n async goto(url: string, options?: NavigateOptions): Promise<void> {\n if (options?.waitUntil !== undefined) {\n await page.goto(url, { waitUntil: options.waitUntil });\n } else {\n await page.goto(url);\n }\n },\n\n currentUrl(): string {\n return page.url();\n },\n\n count(selector: string): Promise<number> {\n return page.locator(selector).count();\n },\n\n textContent(selector: string): Promise<string | null> {\n return page.locator(selector).textContent();\n },\n\n async click(selector: string): Promise<void> {\n await page.locator(selector).click();\n },\n\n async clickFirst(selector: string): Promise<void> {\n await page.locator(selector).first().click();\n },\n\n async fill(selector: string, value: string): Promise<void> {\n await page.locator(selector).fill(value);\n },\n\n async fillFirst(selector: string, value: string): Promise<void> {\n await page.locator(selector).first().fill(value);\n },\n\n async press(selector: string, key: string): Promise<void> {\n await page.locator(selector).press(key);\n },\n\n async selectOption(selector: string, value: string): Promise<void> {\n await page.locator(selector).selectOption(value);\n },\n\n async selectOptionFirst(selector: string, value: string): Promise<void> {\n await page.locator(selector).first().selectOption(value);\n },\n\n async hover(selector: string): Promise<void> {\n await page.locator(selector).hover();\n },\n\n async scrollIntoView(selector: string): Promise<void> {\n await page.locator(selector).scrollIntoViewIfNeeded();\n },\n\n async setInputFiles(selector: string, files: string | string[]): Promise<void> {\n await page.locator(selector).setInputFiles(files);\n },\n\n countByRole(role: string, name: string): Promise<number> {\n return page.getByRole(role as PlaywrightRole, { name }).count();\n },\n\n async clickFirstByRole(role: string, name: string): Promise<void> {\n await page.getByRole(role as PlaywrightRole, { name }).first().click();\n },\n\n countByLabel(label: string): Promise<number> {\n return page.getByLabel(label, { exact: true }).count();\n },\n\n async fillFirstByLabel(label: string, value: string): Promise<void> {\n await page.getByLabel(label, { exact: true }).first().fill(value);\n },\n\n async selectOptionFirstByLabel(label: string, value: string): Promise<void> {\n await page.getByLabel(label, { exact: true }).first().selectOption(value);\n },\n\n async waitForSelector(selector: string, options?: { timeout?: number }): Promise<void> {\n await page.waitForSelector(selector, { timeout: options?.timeout });\n },\n\n async waitForUrl(predicate: (url: string) => boolean, options?: { timeout?: number }): Promise<void> {\n await page.waitForURL((url) => predicate(url.toString()), { timeout: options?.timeout });\n },\n\n async waitForNetworkIdle(options?: { timeout?: number }): Promise<void> {\n await page.waitForLoadState(\"networkidle\", { timeout: options?.timeout });\n },\n\n evaluate<R = unknown, A = unknown>(\n pageFunction: string | ((arg: A) => R | Promise<R>),\n arg?: A\n ): Promise<R> {\n const raw = page.evaluate as unknown as (fn: unknown, a?: unknown) => Promise<unknown>;\n const result = arg === undefined\n ? raw.call(page, pageFunction)\n : raw.call(page, pageFunction, arg);\n return result as Promise<R>;\n },\n\n async screenshot(options: { path: string; fullPage?: boolean }): Promise<void> {\n await page.screenshot({ path: options.path, fullPage: options.fullPage });\n },\n\n onResponse(handler: (response: DriverResponse) => void): void {\n page.on(\"response\", handler);\n },\n\n async route(url: string, handler: (route: DriverRoute) => void | Promise<void>): Promise<void> {\n await page.route(url, async (pwRoute) => {\n try {\n await handler({\n fulfill: (response) => pwRoute.fulfill(response)\n });\n } catch (error) {\n try {\n await pwRoute.abort(\"failed\");\n } catch (abortError) {\n throw new Error(\n `Route handler failed for ${url}: ${formatError(error)}. Route abort also failed: ${formatError(abortError)}`\n );\n }\n throw new Error(`Route handler failed for ${url}: ${formatError(error)}`);\n }\n });\n },\n\n async unroute(url: string): Promise<void> {\n await page.unroute(url);\n },\n\n onDialog(action: DialogAction): void {\n page.once(\"dialog\", (dialog) => {\n const response = action === \"accept\"\n ? dialog.accept()\n : dialog.dismiss();\n response.catch((error: unknown) => {\n console.warn(`Failed to ${action} dialog: ${formatError(error)}`);\n });\n });\n },\n\n waitForDownloadEvent(options?: { timeout?: number }): Promise<DriverDownload> {\n return page.waitForEvent(\"download\", { timeout: options?.timeout });\n },\n\n parseTextSelector(selector: string): string | null {\n return unwrapTextSelector(selector);\n }\n };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n// Type-only: the runner hands executeSteps a live Playwright page as the\n// driver entrypoint. All *runtime* Playwright use lives in the driver\n// (src/browser/playwright-driver.ts); this import is erased at build.\nimport type { Page } from \"playwright\";\nimport { createPlaywrightDriver } from \"../browser/controller.js\";\nimport type { DriverCapability, DriverDownload, SessionDriver } from \"../browser/driver.js\";\nimport type { Step, StepResult } from \"../types/index.js\";\nimport { loadHunt } from \"../config/loader.js\";\nimport { interpolateHunt } from \"../config/interpolate.js\";\nimport { assertHuntAssertionsSupportedByTarget, assertStepsSupportedByTarget } from \"../config/target.js\";\nimport { createRunPolicy, type RunPolicy } from \"./policy.js\";\n\nexport type StepCallback = (result: StepResult, step: Step, index: number) => void;\n\nexport type StepExecutionContext = {\n /** Playwright page entrypoint for the web target; omitted for non-web drivers. */\n page?: Page;\n /** Pre-built driver; required when `page` is omitted (e.g. the macOS target). */\n driver?: SessionDriver;\n steps: Step[];\n targetUrl: string;\n runDir: string;\n screenshotsMode: \"on-failure\" | \"all\";\n forbiddenSelectors: string[];\n allowedDomains: string[];\n /** Allow-listed bundle IDs / process names for the macOS target (optional). */\n allowedApps?: string[];\n maxSteps: number;\n selfHealing?: boolean;\n maxTotalTimeMs: number;\n redactedFillSteps: Set<string>;\n configDir: string;\n onStep?: StepCallback;\n huntStack?: string[];\n activeMocks?: Map<string, () => Promise<void>>;\n runtimeVars?: Map<string, string>;\n randomVars?: Record<string, string>;\n pendingDownload?: Promise<DriverDownload>;\n runStartedAtMs?: number;\n stepPathPrefix?: string;\n};\n\nexport type StepExecutionResult = {\n results: StepResult[];\n screenshots: string[];\n failed: boolean;\n error?: string;\n};\n\n/** Anything that can take a full-page screenshot (a driver or a Playwright page). */\ntype ScreenshotTaker = {\n screenshot(options: { path: string; fullPage?: boolean }): Promise<unknown>;\n};\n\nfunction getStepType(step: Step): string {\n if (\"navigate\" in step) return \"navigate\";\n if (\"click\" in step) return \"click\";\n if (\"fill\" in step) return \"fill\";\n if (\"type\" in step) return \"type\";\n if (\"selectOption\" in step) return \"selectOption\";\n if (\"select\" in step) return \"select\";\n if (\"onDialog\" in step) return \"onDialog\";\n if (\"setInputFiles\" in step) return \"setInputFiles\";\n if (\"runHunt\" in step) return \"runHunt\";\n if (\"assert\" in step) return \"assert\";\n if (\"press\" in step) return \"press\";\n if (\"wait\" in step) return \"wait\";\n if (\"waitForSelector\" in step) return \"waitForSelector\";\n if (\"waitForUrl\" in step) return \"waitForUrl\";\n if (\"waitForNetworkIdle\" in step) return \"waitForNetworkIdle\";\n if (\"hover\" in step) return \"hover\";\n if (\"scroll\" in step) return \"scroll\";\n if (\"scrollTo\" in step) return \"scrollTo\";\n if (\"screenshot\" in step) return \"screenshot\";\n if (\"if\" in step) return \"if\";\n if (\"repeat\" in step) return \"repeat\";\n if (\"mockRoute\" in step) return \"mockRoute\";\n if (\"unmockRoute\" in step) return \"unmockRoute\";\n if (\"evalScript\" in step) return \"evalScript\";\n if (\"runScript\" in step) return \"runScript\";\n if (\"assertScreenshot\" in step) return \"assertScreenshot\";\n if (\"copyText\" in step) return \"copyText\";\n if (\"waitForDownload\" in step) return \"waitForDownload\";\n return \"step\";\n}\n\nconst RUNTIME_VAR_PATTERN = /\\{\\{([A-Z0-9_]+)\\}\\}/g;\n\nfunction substituteRuntimeVars(input: string, vars: Map<string, string>): string {\n return input.replace(RUNTIME_VAR_PATTERN, (match, name: string) => {\n const value = vars.get(name);\n return value !== undefined ? value : match;\n });\n}\n\nfunction applyRuntimeVars(step: Step, vars: Map<string, string>): Step {\n const sub = (s: string) => substituteRuntimeVars(s, vars);\n\n if (\"navigate\" in step) return { navigate: sub(step.navigate) };\n if (\"click\" in step) {\n if (typeof step.click === \"string\") return { click: sub(step.click) };\n return { click: { selector: sub(step.click.selector) } };\n }\n if (\"fill\" in step) {\n if (\"selector\" in step.fill && \"value\" in step.fill) {\n const f = step.fill as { selector: string; value: string };\n return { fill: { selector: sub(f.selector), value: sub(f.value) } };\n }\n const [key, value] = Object.entries(step.fill)[0];\n return { fill: { [sub(key)]: sub(value) } };\n }\n if (\"type\" in step) return { type: sub(step.type) };\n if (\"assert\" in step) {\n const a = step.assert;\n if (a.visible !== undefined) return { assert: { visible: sub(a.visible) } };\n if (a.notVisible !== undefined) return { assert: { notVisible: sub(a.notVisible) } };\n if (a.urlIncludes !== undefined) return { assert: { urlIncludes: sub(a.urlIncludes) } };\n if (a.urlEquals !== undefined) return { assert: { urlEquals: sub(a.urlEquals) } };\n return step;\n }\n if (\"wait\" in step) {\n if (typeof step.wait === \"string\") return { wait: sub(step.wait) };\n return { wait: { for: sub(step.wait.for), timeout: step.wait.timeout } };\n }\n if (\"waitForSelector\" in step) {\n return { waitForSelector: { selector: sub(step.waitForSelector.selector), timeout: step.waitForSelector.timeout } };\n }\n if (\"evalScript\" in step) {\n if (typeof step.evalScript === \"string\") return { evalScript: sub(step.evalScript) };\n return {\n evalScript: {\n expression: sub(step.evalScript.expression),\n ...(step.evalScript.as !== undefined ? { as: step.evalScript.as } : {})\n }\n };\n }\n if (\"assertScreenshot\" in step) {\n return {\n assertScreenshot: {\n name: sub(step.assertScreenshot.name),\n ...(step.assertScreenshot.threshold !== undefined ? { threshold: step.assertScreenshot.threshold } : {})\n }\n };\n }\n if (\"copyText\" in step) {\n return { copyText: { selector: sub(step.copyText.selector), as: step.copyText.as } };\n }\n if (\"waitForDownload\" in step) {\n if (step.waitForDownload === null) return step;\n return {\n waitForDownload: {\n ...(step.waitForDownload.filename !== undefined ? { filename: sub(step.waitForDownload.filename) } : {}),\n ...(step.waitForDownload.timeout !== undefined ? { timeout: step.waitForDownload.timeout } : {})\n }\n };\n }\n return step;\n}\n\nfunction isExplicitFillStep(\n value: { selector: string; value: string } | Record<string, string>\n): value is { selector: string; value: string } {\n return (\n typeof (value as { selector?: unknown }).selector === \"string\" &&\n typeof (value as { value?: unknown }).value === \"string\"\n );\n}\n\nfunction resolveNavigationTarget(targetUrl: string, value: string): string {\n try {\n return new URL(value, targetUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction escapeForText(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction escapeForAttribute(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction exactTextSelector(text: string): string {\n return `text=\"${escapeForText(text)}\"`;\n}\n\nfunction textContainsSelector(text: string): string {\n return `text=${escapeForText(text)}`;\n}\n\nfunction getSinglePair(value: Record<string, string>, stepType: string): [string, string] {\n const entries = Object.entries(value);\n if (entries.length !== 1) {\n throw new Error(`${stepType} shorthand expects exactly one key-value pair`);\n }\n return entries[0];\n}\n\nasync function clickByTextWithFallback(\n driver: SessionDriver,\n policy: RunPolicy,\n text: string\n): Promise<string> {\n const roleSelector = `role=button[name=\"${escapeForAttribute(text)}\"]`;\n policy.assertAllowedSelector(roleSelector);\n if (await driver.countByRole(\"button\", text)) {\n await driver.clickFirstByRole(\"button\", text);\n return roleSelector;\n }\n\n const selector = exactTextSelector(text);\n policy.assertAllowedSelector(selector);\n await driver.clickFirst(selector);\n return selector;\n}\n\nasync function fillByLabelOrPlaceholder(\n driver: SessionDriver,\n policy: RunPolicy,\n label: string,\n value: string\n): Promise<string> {\n const labelSelector = `label=\"${escapeForAttribute(label)}\"`;\n policy.assertAllowedSelector(labelSelector);\n if (await driver.countByLabel(label)) {\n await driver.fillFirstByLabel(label, value);\n return labelSelector;\n }\n\n const placeholder = `input[placeholder=\"${escapeForAttribute(label)}\"], textarea[placeholder=\"${escapeForAttribute(label)}\"]`;\n policy.assertAllowedSelector(placeholder);\n if (await driver.count(placeholder)) {\n await driver.fillFirst(placeholder, value);\n return placeholder;\n }\n\n throw new Error(`Could not resolve fill shorthand for \"${label}\"`);\n}\n\nasync function selectByLabelOrFallback(\n driver: SessionDriver,\n policy: RunPolicy,\n label: string,\n value: string\n): Promise<string> {\n const labelSelector = `label=\"${escapeForAttribute(label)}\"`;\n policy.assertAllowedSelector(labelSelector);\n if (await driver.countByLabel(label)) {\n await driver.selectOptionFirstByLabel(label, value);\n return labelSelector;\n }\n\n const ariaSelector = `select[aria-label=\"${escapeForAttribute(label)}\"]`;\n policy.assertAllowedSelector(ariaSelector);\n if (await driver.count(ariaSelector)) {\n await driver.selectOptionFirst(ariaSelector, value);\n return ariaSelector;\n }\n\n const placeholderSelector = `select[placeholder=\"${escapeForAttribute(label)}\"]`;\n policy.assertAllowedSelector(placeholderSelector);\n if (await driver.count(placeholderSelector)) {\n await driver.selectOptionFirst(placeholderSelector, value);\n return placeholderSelector;\n }\n\n throw new Error(`Could not resolve select shorthand for \"${label}\"`);\n}\n\n// Playwright engine prefixes (e.g. `css=`, `xpath=…`, `text=\"…\"`) that mark a\n// value as an explicit selector rather than text to match.\nconst SELECTOR_ENGINE_PREFIX = /^(?:css|xpath|text|id|role|data-testid)=/i;\nconst HTML_TYPE_SELECTORS = new Set([\n \"a\",\n \"article\",\n \"aside\",\n \"body\",\n \"button\",\n \"canvas\",\n \"dialog\",\n \"div\",\n \"fieldset\",\n \"footer\",\n \"form\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"header\",\n \"html\",\n \"iframe\",\n \"img\",\n \"input\",\n \"label\",\n \"li\",\n \"main\",\n \"nav\",\n \"ol\",\n \"option\",\n \"p\",\n \"section\",\n \"select\",\n \"span\",\n \"table\",\n \"tbody\",\n \"td\",\n \"textarea\",\n \"th\",\n \"thead\",\n \"tr\",\n \"ul\"\n]);\n\nfunction isKnownCssTypeSelector(value: string): boolean {\n return value === \"*\" || value.includes(\"-\") || HTML_TYPE_SELECTORS.has(value.toLowerCase());\n}\n\nfunction readCssTypeSelector(value: string, start: number): { end: number; isKnown: boolean } | null {\n const match = /^(?:[A-Za-z][\\w-]*|\\*)/.exec(value.slice(start));\n if (!match) return null;\n return { end: start + match[0].length, isKnown: isKnownCssTypeSelector(match[0]) };\n}\n\nfunction readCssStructuralSelectorPart(value: string, start: number): number | null {\n const rest = value.slice(start);\n const classOrId = /^[.#][A-Za-z_][\\w-]*/.exec(rest);\n if (classOrId) return start + classOrId[0].length;\n\n const attribute = /^\\[[A-Za-z_][\\w:-]*(?:\\s*(?:[~|^$*]?=)\\s*(?:\"[^\"]*\"|'[^']*'|[^\\]\\s]+))?\\]/.exec(rest);\n if (attribute) return start + attribute[0].length;\n\n return null;\n}\n\nfunction readCssCompoundSelector(value: string, start: number): { end: number; hasStructuralPart: boolean } | null {\n let cursor = start;\n const type = readCssTypeSelector(value, cursor);\n if (type) {\n cursor = type.end;\n }\n\n let hasStructuralPart = false;\n for (;;) {\n const next = readCssStructuralSelectorPart(value, cursor);\n if (next === null) break;\n hasStructuralPart = true;\n cursor = next;\n }\n\n if (cursor === start) return null;\n if (type && !type.isKnown) return null;\n return { end: cursor, hasStructuralPart };\n}\n\nfunction readCssSelectorSeparator(value: string, start: number): number | null {\n let cursor = start;\n let sawWhitespace = false;\n while (/\\s/.test(value[cursor] ?? \"\")) {\n sawWhitespace = true;\n cursor += 1;\n }\n\n if (/[>+~]/.test(value[cursor] ?? \"\")) {\n cursor += 1;\n while (/\\s/.test(value[cursor] ?? \"\")) {\n cursor += 1;\n }\n return cursor;\n }\n\n return sawWhitespace ? cursor : null;\n}\n\nfunction isCssSelectorSequence(value: string): boolean {\n const first = readCssCompoundSelector(value, 0);\n if (!first) return false;\n\n let cursor = first.end;\n let sawSeparator = false;\n let hasStructuralPart = first.hasStructuralPart;\n\n while (cursor < value.length) {\n const afterSeparator = readCssSelectorSeparator(value, cursor);\n if (afterSeparator === null) return false;\n\n const next = readCssCompoundSelector(value, afterSeparator);\n if (!next) return false;\n\n sawSeparator = true;\n hasStructuralPart = hasStructuralPart || next.hasStructuralPart;\n cursor = next.end;\n }\n\n return sawSeparator && hasStructuralPart;\n}\n\n// A visibility value is treated as a selector only when it has a clear\n// structural signature: a leading class/id/attribute token, a supported CSS\n// compound/sequence, or explicit Playwright engine prefix (incl. `//` xpath).\n// Everything else — including prose that merely contains punctuation such as\n// \"name:\" or a sentence ending in \".\" — is matched as text, so assertions read\n// the way they are written. For exotic selectors (pseudo-classes), use an\n// explicit engine prefix like `css=input:checked`.\nexport function looksLikeSelector(value: string): boolean {\n const trimmed = value.trim();\n if (trimmed.length === 0) return false;\n if (SELECTOR_ENGINE_PREFIX.test(trimmed) || trimmed.startsWith(\"//\")) return true;\n if (/^[.#]/.test(trimmed)) return true; // leading class or id selector\n const compound = readCssCompoundSelector(trimmed, 0);\n if (compound?.end === trimmed.length && compound.hasStructuralPart) return true;\n if (isCssSelectorSequence(trimmed)) return true;\n return false;\n}\n\nexport function toVisibilitySelector(value: string): string {\n if (looksLikeSelector(value)) return value;\n return textContainsSelector(value);\n}\n\nasync function runInlineAssert(\n driver: SessionDriver,\n policy: RunPolicy,\n assertion: {\n visible?: string;\n notVisible?: string;\n urlIncludes?: string;\n urlEquals?: string;\n }\n): Promise<string> {\n if (assertion.visible !== undefined) {\n const selector = toVisibilitySelector(assertion.visible);\n policy.assertAllowedSelector(selector);\n const count = await driver.count(selector);\n if (count === 0) {\n throw new Error(`Expected visible: ${assertion.visible}`);\n }\n return `visible:${assertion.visible}`;\n }\n\n if (assertion.notVisible !== undefined) {\n const selector = toVisibilitySelector(assertion.notVisible);\n policy.assertAllowedSelector(selector);\n const count = await driver.count(selector);\n if (count > 0) {\n throw new Error(`Expected not visible: ${assertion.notVisible}`);\n }\n return `notVisible:${assertion.notVisible}`;\n }\n\n if (assertion.urlIncludes !== undefined) {\n const current = driver.currentUrl();\n if (!current.includes(assertion.urlIncludes)) {\n throw new Error(`URL did not include ${assertion.urlIncludes}`);\n }\n return `urlIncludes:${assertion.urlIncludes}`;\n }\n\n if (assertion.urlEquals !== undefined) {\n const current = driver.currentUrl();\n if (current !== assertion.urlEquals) {\n throw new Error(`URL did not equal ${assertion.urlEquals}`);\n }\n return `urlEquals:${assertion.urlEquals}`;\n }\n\n throw new Error(\"assert step is missing an assertion type\");\n}\n\nfunction screenshotPath(screenshotsDir: string, fileName: string): string {\n return path.join(screenshotsDir, fileName);\n}\n\nfunction stepPath(prefix: string | undefined, index: number): string {\n return prefix ? `${prefix}.${index}` : `${index}`;\n}\n\nfunction isWaitForDownloadStep(step: Step | undefined): step is Extract<Step, { waitForDownload: unknown }> {\n return step !== undefined && \"waitForDownload\" in step;\n}\n\nfunction armDownloadListener(driver: SessionDriver, timeout: number): Promise<DriverDownload> {\n const downloadPromise = driver.waitForDownloadEvent({ timeout });\n void downloadPromise.catch(() => undefined);\n return downloadPromise;\n}\n\nfunction validateDownloadFilename(suggestedFilename: string): string {\n const safeFilename = suggestedFilename.trim();\n const allowedFilenamePattern = /^[^<>:\"/\\\\|?*]+$/;\n const hasControlCharacter = Array.from(safeFilename).some((char) => char.charCodeAt(0) < 32);\n\n if (\n safeFilename.length === 0\n || safeFilename !== suggestedFilename\n || safeFilename !== path.basename(safeFilename)\n || safeFilename.includes(\"..\")\n || /[/\\\\]/.test(safeFilename)\n || hasControlCharacter\n || !allowedFilenamePattern.test(safeFilename)\n ) {\n throw new Error(`Invalid download filename: \"${suggestedFilename}\"`);\n }\n\n return safeFilename;\n}\n\nasync function captureScreenshot(taker: ScreenshotTaker, filePath: string): Promise<void> {\n try {\n await taker.screenshot({ path: filePath, fullPage: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Screenshot failed\";\n throw new Error(`Failed to capture screenshot at ${filePath}: ${message}`);\n }\n}\n\nasync function executeNestedSteps(\n context: StepExecutionContext,\n overrides: Partial<StepExecutionContext> & Pick<StepExecutionContext, \"steps\">\n): Promise<StepExecutionResult> {\n const nestedContext: StepExecutionContext = {\n ...context,\n ...overrides,\n pendingDownload: context.pendingDownload\n };\n const result = await executeSteps(nestedContext);\n context.pendingDownload = nestedContext.pendingDownload;\n if (nestedContext.randomVars !== undefined) {\n context.randomVars = nestedContext.randomVars;\n }\n return result;\n}\n\n/**\n * A step handler's outcome. `result` is a single completed step (which goes\n * through the common tail — \"all\"-mode screenshot + onStep callback). `abort`\n * signals that a nested execution failed and the whole run must stop; the\n * handler has already pushed its nested results/screenshots.\n */\ntype HandlerOutcome =\n | { kind: \"result\"; result: StepResult }\n | { kind: \"abort\"; error?: string };\n\n/** Everything a step handler needs from the executing loop. */\ntype StepHandlerContext = {\n driver: SessionDriver;\n policy: RunPolicy;\n context: StepExecutionContext;\n step: Step;\n index: number;\n stepPath: string;\n stepStart: number;\n runtimeVars: Map<string, string>;\n results: StepResult[];\n screenshots: string[];\n addScreenshot: (fileName: string) => Promise<string>;\n executeNested: (\n overrides: Partial<StepExecutionContext> & Pick<StepExecutionContext, \"steps\">\n ) => Promise<StepExecutionResult>;\n};\n\ntype StepHandler = {\n /** Driver capabilities this handler requires; checked before dispatch. */\n capabilities: DriverCapability[];\n run: (h: StepHandlerContext) => Promise<HandlerOutcome>;\n};\n\nfunction unknownStep(): never {\n throw new Error(\"Unknown step type\");\n}\n\nconst STEP_HANDLERS: Record<string, StepHandler> = {\n navigate: {\n capabilities: [\"navigate\"],\n run: async (h) => {\n if (!(\"navigate\" in h.step)) unknownStep();\n const destination = resolveNavigationTarget(h.context.targetUrl, h.step.navigate);\n h.policy.ensureUrlAllowed(destination);\n await h.driver.goto(destination);\n h.policy.ensureLocationAllowed(h.driver);\n return { kind: \"result\", result: { type: \"navigate\", status: \"pass\", durationMs: Date.now() - h.stepStart } };\n }\n },\n\n click: {\n capabilities: [\"interact\", \"query\"],\n run: async (h) => {\n if (!(\"click\" in h.step)) unknownStep();\n let selector: string;\n let healedFrom: string | undefined;\n if (typeof h.step.click === \"string\") {\n selector = await clickByTextWithFallback(h.driver, h.policy, h.step.click);\n } else {\n const resolved = await h.policy.resolveActionSelector(h.step.click.selector);\n await h.driver.click(resolved.selector);\n selector = resolved.selector;\n healedFrom = resolved.healedFrom;\n }\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"click\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector,\n ...(healedFrom ? { healedFrom } : {})\n }\n };\n }\n },\n\n fill: {\n capabilities: [\"interact\", \"query\"],\n run: async (h) => {\n if (!(\"fill\" in h.step)) unknownStep();\n let selector: string;\n let value: string;\n let healedFrom: string | undefined;\n if (isExplicitFillStep(h.step.fill)) {\n const resolved = await h.policy.resolveActionSelector(h.step.fill.selector);\n await h.driver.fill(resolved.selector, h.step.fill.value);\n selector = resolved.selector;\n healedFrom = resolved.healedFrom;\n value = h.step.fill.value;\n } else {\n const [label, shorthandValue] = getSinglePair(h.step.fill, \"fill\");\n selector = await fillByLabelOrPlaceholder(h.driver, h.policy, label, shorthandValue);\n value = shorthandValue;\n }\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"fill\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector,\n value: h.context.redactedFillSteps.has(h.stepPath) ? \"[REDACTED]\" : value,\n ...(healedFrom ? { healedFrom } : {})\n }\n };\n }\n },\n\n type: {\n capabilities: [\"interact\"],\n run: async (h) => {\n if (!(\"type\" in h.step)) unknownStep();\n h.policy.assertAllowedSelector(\":focus\");\n await h.driver.fill(\":focus\", h.step.type);\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"type\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: \":focus\",\n value: h.context.redactedFillSteps.has(h.stepPath) ? \"[REDACTED]\" : h.step.type\n }\n };\n }\n },\n\n selectOption: {\n capabilities: [\"navigate\", \"interact\", \"query\"],\n run: async (h) => {\n if (!(\"selectOption\" in h.step)) unknownStep();\n const resolved = await h.policy.resolveActionSelector(h.step.selectOption.selector);\n await h.driver.selectOption(resolved.selector, h.step.selectOption.value);\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"selectOption\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: resolved.selector,\n value: h.step.selectOption.value,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n }\n };\n }\n },\n\n select: {\n capabilities: [\"navigate\", \"interact\", \"query\"],\n run: async (h) => {\n if (!(\"select\" in h.step)) unknownStep();\n const [label, value] = getSinglePair(h.step.select, \"select\");\n const selector = await selectByLabelOrFallback(h.driver, h.policy, label, value);\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"select\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector,\n value\n }\n };\n }\n },\n\n onDialog: {\n capabilities: [\"dialog\"],\n run: async (h) => {\n if (!(\"onDialog\" in h.step)) unknownStep();\n h.driver.onDialog(h.step.onDialog.action);\n return {\n kind: \"result\",\n result: {\n type: \"onDialog\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: h.step.onDialog.action\n }\n };\n }\n },\n\n setInputFiles: {\n capabilities: [\"navigate\", \"interact\", \"query\", \"files\"],\n run: async (h) => {\n if (!(\"setInputFiles\" in h.step)) unknownStep();\n const resolvedInput = await h.policy.resolveActionSelector(h.step.setInputFiles.selector);\n const rawFiles = h.step.setInputFiles.files;\n const resolveFile = (f: string) => (path.isAbsolute(f) ? f : path.join(h.context.configDir, f));\n const resolvedFiles = Array.isArray(rawFiles) ? rawFiles.map(resolveFile) : resolveFile(rawFiles);\n await h.driver.setInputFiles(resolvedInput.selector, resolvedFiles);\n h.policy.ensureLocationAllowed(h.driver);\n const filesLabel = Array.isArray(rawFiles) ? rawFiles.join(\", \") : rawFiles;\n return {\n kind: \"result\",\n result: {\n type: \"setInputFiles\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: resolvedInput.selector,\n ...(resolvedInput.healedFrom ? { healedFrom: resolvedInput.healedFrom } : {}),\n value: filesLabel\n }\n };\n }\n },\n\n runHunt: {\n capabilities: [],\n run: async (h) => {\n if (!(\"runHunt\" in h.step)) unknownStep();\n const huntName = typeof h.step.runHunt === \"string\" ? h.step.runHunt : h.step.runHunt.name;\n const overrideVars = typeof h.step.runHunt === \"string\" ? undefined : h.step.runHunt.vars;\n const stack = h.context.huntStack ?? [];\n if (stack.includes(huntName)) {\n throw new Error(`Circular hunt dependency: ${[...stack, huntName].join(\" → \")}`);\n }\n const subHunt = loadHunt(huntName, h.context.configDir);\n if (overrideVars) {\n subHunt.vars = { ...subHunt.vars, ...overrideVars };\n }\n const {\n hunt: interpolatedSubHunt,\n redactedFillSteps: subRedacted,\n randomVars\n } = interpolateHunt(subHunt, process.env, h.context.randomVars);\n // Sub-hunts bypass the top-level target check, so re-run it here against\n // the sub-hunt's own steps. The target type is derived from the driver: a\n // driver without the `navigate` capability is the (non-web) macOS target,\n // where web-only steps — including `assert: urlIncludes`/`urlEquals`\n // against a bundle-id `currentUrl()` — must be rejected, not silently run.\n const subTargetType = h.driver.capabilities.has(\"navigate\") ? \"web\" : \"macos\";\n assertStepsSupportedByTarget(interpolatedSubHunt.steps, subTargetType);\n assertHuntAssertionsSupportedByTarget(interpolatedSubHunt.assertions, subTargetType);\n h.policy.assertWithinMaxSteps(interpolatedSubHunt.steps.length, huntName);\n const subResult = await h.executeNested({\n steps: interpolatedSubHunt.steps,\n redactedFillSteps: subRedacted,\n randomVars,\n stepPathPrefix: undefined,\n huntStack: [...stack, huntName],\n onStep: h.context.onStep\n });\n for (const sr of subResult.results) {\n h.results.push({ ...sr, type: `${huntName} > ${sr.type}` });\n }\n h.screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return { kind: \"abort\", error: `Sub-hunt \"${huntName}\" failed: ${subResult.error}` };\n }\n return {\n kind: \"result\",\n result: { type: \"runHunt\", status: \"pass\", durationMs: Date.now() - h.stepStart, value: huntName }\n };\n }\n },\n\n press: {\n capabilities: [\"interact\", \"query\"],\n run: async (h) => {\n if (!(\"press\" in h.step)) unknownStep();\n const resolved = await h.policy.resolveActionSelector(h.step.press.selector);\n await h.driver.press(resolved.selector, h.step.press.key);\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"press\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: resolved.selector,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n }\n };\n }\n },\n\n assert: {\n capabilities: [\"query\"],\n run: async (h) => {\n if (!(\"assert\" in h.step)) unknownStep();\n const value = await runInlineAssert(h.driver, h.policy, h.step.assert);\n return {\n kind: \"result\",\n result: { type: \"assert\", status: \"pass\", durationMs: Date.now() - h.stepStart, value }\n };\n }\n },\n\n wait: {\n capabilities: [\"wait\"],\n run: async (h) => {\n if (!(\"wait\" in h.step)) unknownStep();\n const text = typeof h.step.wait === \"string\" ? h.step.wait : h.step.wait.for;\n const timeout = typeof h.step.wait === \"string\" ? undefined : h.step.wait.timeout;\n const selector = `text=${escapeForText(text)}`;\n h.policy.assertAllowedSelector(selector);\n await h.driver.waitForSelector(selector, { timeout });\n return {\n kind: \"result\",\n result: { type: \"wait\", status: \"pass\", durationMs: Date.now() - h.stepStart, selector }\n };\n }\n },\n\n waitForSelector: {\n capabilities: [\"wait\"],\n run: async (h) => {\n if (!(\"waitForSelector\" in h.step)) unknownStep();\n h.policy.assertAllowedSelector(h.step.waitForSelector.selector);\n await h.driver.waitForSelector(h.step.waitForSelector.selector, {\n timeout: h.step.waitForSelector.timeout\n });\n return {\n kind: \"result\",\n result: {\n type: \"waitForSelector\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: h.step.waitForSelector.selector\n }\n };\n }\n },\n\n waitForUrl: {\n capabilities: [\"navigate\", \"wait\"],\n run: async (h) => {\n if (!(\"waitForUrl\" in h.step)) unknownStep();\n const value = h.step.waitForUrl.value;\n await h.driver.waitForUrl((url) => url.includes(value), { timeout: h.step.waitForUrl.timeout });\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: { type: \"waitForUrl\", status: \"pass\", durationMs: Date.now() - h.stepStart, value }\n };\n }\n },\n\n waitForNetworkIdle: {\n capabilities: [\"wait\"],\n run: async (h) => {\n if (!(\"waitForNetworkIdle\" in h.step)) unknownStep();\n await h.driver.waitForNetworkIdle({ timeout: h.step.waitForNetworkIdle.timeout });\n return {\n kind: \"result\",\n result: { type: \"waitForNetworkIdle\", status: \"pass\", durationMs: Date.now() - h.stepStart }\n };\n }\n },\n\n hover: {\n capabilities: [\"interact\", \"query\"],\n run: async (h) => {\n if (!(\"hover\" in h.step)) unknownStep();\n const resolved = await h.policy.resolveActionSelector(h.step.hover.selector);\n await h.driver.hover(resolved.selector);\n h.policy.ensureLocationAllowed(h.driver);\n return {\n kind: \"result\",\n result: {\n type: \"hover\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: resolved.selector,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n }\n };\n }\n },\n\n scroll: {\n capabilities: [\"evaluate\"],\n run: async (h) => {\n if (!(\"scroll\" in h.step)) unknownStep();\n const amount = h.step.scroll.amount ?? 500;\n const scrollMap: Record<string, [number, number]> = {\n up: [0, -amount],\n down: [0, amount],\n left: [-amount, 0],\n right: [amount, 0]\n };\n const [x, y] = scrollMap[h.step.scroll.direction];\n await h.driver.evaluate(([sx, sy]) => window.scrollBy(sx, sy), [x, y] as [number, number]);\n return {\n kind: \"result\",\n result: {\n type: \"scroll\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: `${h.step.scroll.direction} ${amount}px`\n }\n };\n }\n },\n\n scrollTo: {\n capabilities: [\"interact\", \"query\"],\n run: async (h) => {\n if (!(\"scrollTo\" in h.step)) unknownStep();\n const resolved = await h.policy.resolveActionSelector(h.step.scrollTo.selector);\n await h.driver.scrollIntoView(resolved.selector);\n return {\n kind: \"result\",\n result: {\n type: \"scrollTo\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: resolved.selector,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n }\n };\n }\n },\n\n screenshot: {\n capabilities: [\"screenshot\"],\n run: async (h) => {\n if (!(\"screenshot\" in h.step)) unknownStep();\n const name = h.step.screenshot.name ?? `manual_step_${h.index + 1}.png`;\n if (/[/\\\\]|\\.\\./.test(name)) {\n throw new Error(`Invalid screenshot name: \"${name}\" must not contain path separators or \"..\"`);\n }\n const fileName = name.endsWith(\".png\") ? name : `${name}.png`;\n const relative = await h.addScreenshot(fileName);\n return {\n kind: \"result\",\n result: { type: \"screenshot\", status: \"pass\", durationMs: Date.now() - h.stepStart, screenshot: relative }\n };\n }\n },\n\n if: {\n capabilities: [\"query\"],\n run: async (h) => {\n if (!(\"if\" in h.step)) unknownStep();\n const condition = h.step.if;\n const selector = condition.visible ?? condition.notVisible!;\n h.policy.assertAllowedSelector(selector);\n const count = await h.driver.count(selector);\n const conditionMet = condition.visible !== undefined ? count > 0 : count === 0;\n\n if (conditionMet) {\n const subResult = await h.executeNested({\n steps: condition.then,\n stepPathPrefix: `${h.stepPath}.if.then`\n });\n for (const sr of subResult.results) {\n h.results.push({ ...sr, type: `if > ${sr.type}` });\n }\n h.screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return { kind: \"abort\", error: subResult.error };\n }\n return {\n kind: \"result\",\n result: {\n type: \"if\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: `condition met, executed ${condition.then.length} steps`\n }\n };\n }\n\n if (condition.else && condition.else.length > 0) {\n const subResult = await h.executeNested({\n steps: condition.else,\n stepPathPrefix: `${h.stepPath}.if.else`\n });\n for (const sr of subResult.results) {\n h.results.push({ ...sr, type: `if > ${sr.type}` });\n }\n h.screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return { kind: \"abort\", error: subResult.error };\n }\n return {\n kind: \"result\",\n result: {\n type: \"if\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: `condition not met, executed ${condition.else.length} else steps`\n }\n };\n }\n\n return {\n kind: \"result\",\n result: {\n type: \"if\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: \"condition not met, skipped\"\n }\n };\n }\n },\n\n repeat: {\n capabilities: [\"query\"],\n run: async (h) => {\n if (!(\"repeat\" in h.step)) unknownStep();\n const repeat = h.step.repeat;\n let totalSubSteps = 0;\n\n if (repeat.times !== undefined) {\n const totalPlanned = repeat.times * repeat.steps.length;\n if (totalPlanned + totalSubSteps > h.context.maxSteps) {\n throw new Error(`Repeat exceeded maxSteps guardrail (${h.context.maxSteps})`);\n }\n for (let i = 0; i < repeat.times; i++) {\n totalSubSteps += repeat.steps.length;\n const subResult = await h.executeNested({\n steps: repeat.steps,\n stepPathPrefix: `${h.stepPath}.repeat.steps`\n });\n for (const sr of subResult.results) {\n h.results.push({ ...sr, type: `repeat[${i}] > ${sr.type}` });\n }\n h.screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return { kind: \"abort\", error: subResult.error };\n }\n }\n } else if (repeat.while !== undefined) {\n const maxIter = repeat.maxIterations!;\n const whileSelector = repeat.while.visible ?? repeat.while.notVisible!;\n h.policy.assertAllowedSelector(whileSelector);\n for (let i = 0; i < maxIter; i++) {\n const whileCount = await h.driver.count(whileSelector);\n const shouldContinue = repeat.while.visible !== undefined ? whileCount > 0 : whileCount === 0;\n if (!shouldContinue) break;\n\n totalSubSteps += repeat.steps.length;\n if (totalSubSteps > h.context.maxSteps) {\n throw new Error(`Repeat exceeded maxSteps guardrail (${h.context.maxSteps})`);\n }\n const subResult = await h.executeNested({\n steps: repeat.steps,\n stepPathPrefix: `${h.stepPath}.repeat.steps`\n });\n for (const sr of subResult.results) {\n h.results.push({ ...sr, type: `repeat[${i}] > ${sr.type}` });\n }\n h.screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return { kind: \"abort\", error: subResult.error };\n }\n }\n }\n\n return {\n kind: \"result\",\n result: { type: \"repeat\", status: \"pass\", durationMs: Date.now() - h.stepStart }\n };\n }\n },\n\n mockRoute: {\n capabilities: [\"route\"],\n run: async (h) => {\n if (!(\"mockRoute\" in h.step)) unknownStep();\n const mock = h.step.mockRoute;\n const mocks = h.context.activeMocks ?? new Map<string, () => Promise<void>>();\n h.context.activeMocks = mocks;\n\n let responseBody: string;\n if (mock.response.body !== undefined) {\n responseBody = mock.response.body;\n } else {\n const responseFile = mock.response.file;\n if (!responseFile) {\n throw new Error(\"mock.response must include either body or file\");\n }\n const candidateFilePath = path.isAbsolute(responseFile)\n ? responseFile\n : path.join(h.context.configDir, responseFile);\n const resolvedConfigDir = path.resolve(h.context.configDir);\n const resolvedFilePath = path.resolve(candidateFilePath);\n const relativePath = path.relative(resolvedConfigDir, resolvedFilePath);\n const isWithinConfigDir =\n relativePath === \"\"\n || (\n relativePath !== \"..\"\n && !relativePath.startsWith(`..${path.sep}`)\n && !path.isAbsolute(relativePath)\n );\n if (!isWithinConfigDir) {\n throw new Error(\"mock.response.file must resolve within config directory\");\n }\n responseBody = await fs.promises.readFile(resolvedFilePath, \"utf-8\");\n }\n\n const contentType = mock.response.contentType ?? \"application/json\";\n const status = mock.response.status;\n\n await h.driver.route(mock.url, async (route) => {\n await route.fulfill({\n status,\n contentType,\n body: responseBody\n });\n });\n\n mocks.set(mock.url, async () => {\n await h.driver.unroute(mock.url);\n });\n\n return {\n kind: \"result\",\n result: { type: \"mockRoute\", status: \"pass\", durationMs: Date.now() - h.stepStart, value: mock.url }\n };\n }\n },\n\n unmockRoute: {\n capabilities: [\"route\"],\n run: async (h) => {\n if (!(\"unmockRoute\" in h.step)) unknownStep();\n const url = typeof h.step.unmockRoute === \"string\" ? h.step.unmockRoute : h.step.unmockRoute.url;\n const mocks = h.context.activeMocks;\n if (!mocks || !mocks.has(url)) {\n throw new Error(`No active mock for URL: ${url}`);\n }\n const cleanup = mocks.get(url)!;\n await cleanup();\n mocks.delete(url);\n\n return {\n kind: \"result\",\n result: { type: \"unmockRoute\", status: \"pass\", durationMs: Date.now() - h.stepStart, value: url }\n };\n }\n },\n\n evalScript: {\n capabilities: [\"evaluate\"],\n run: async (h) => {\n if (!(\"evalScript\" in h.step)) unknownStep();\n const expression = typeof h.step.evalScript === \"string\" ? h.step.evalScript : h.step.evalScript.expression;\n const result = await h.driver.evaluate(expression);\n const resultStr = String(result);\n if (typeof h.step.evalScript !== \"string\" && h.step.evalScript.as) {\n h.runtimeVars.set(h.step.evalScript.as, resultStr);\n }\n return {\n kind: \"result\",\n result: {\n type: \"evalScript\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: resultStr.length > 200 ? resultStr.slice(0, 200) + \"…\" : resultStr\n }\n };\n }\n },\n\n runScript: {\n capabilities: [\"evaluate\"],\n run: async (h) => {\n if (!(\"runScript\" in h.step)) unknownStep();\n const filePath = path.isAbsolute(h.step.runScript.file)\n ? h.step.runScript.file\n : path.join(h.context.configDir, h.step.runScript.file);\n const fileContents = fs.readFileSync(filePath, \"utf-8\");\n await h.driver.evaluate(fileContents);\n return {\n kind: \"result\",\n result: {\n type: \"runScript\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: h.step.runScript.file\n }\n };\n }\n },\n\n assertScreenshot: {\n capabilities: [\"screenshot\"],\n run: async (h) => {\n if (!(\"assertScreenshot\" in h.step)) unknownStep();\n const { compareScreenshots, ensureBaselineDir } = await import(\"./visual.js\");\n const name = h.step.assertScreenshot.name;\n const threshold = h.step.assertScreenshot.threshold ?? 0.1;\n const baselineDir = ensureBaselineDir(h.context.configDir);\n const baselinePath = path.join(baselineDir, `${name}.png`);\n const currentScreenshotPath = path.join(h.context.runDir, \"screenshots\", `${name}-current.png`);\n fs.mkdirSync(path.dirname(currentScreenshotPath), { recursive: true });\n await h.driver.screenshot({ path: currentScreenshotPath, fullPage: true });\n h.screenshots.push(path.join(\"screenshots\", `${name}-current.png`));\n\n if (!fs.existsSync(baselinePath)) {\n fs.copyFileSync(currentScreenshotPath, baselinePath);\n return {\n kind: \"result\",\n result: { type: \"assertScreenshot\", status: \"pass\", durationMs: Date.now() - h.stepStart, value: \"baseline created\" }\n };\n }\n\n const diffPath = path.join(h.context.runDir, \"screenshots\", `${name}-diff.png`);\n const comparison = await compareScreenshots(baselinePath, currentScreenshotPath, diffPath, threshold);\n if (comparison.match) {\n return {\n kind: \"result\",\n result: {\n type: \"assertScreenshot\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: `diff: ${(comparison.diffPercentage * 100).toFixed(2)}%`\n }\n };\n }\n h.screenshots.push(path.join(\"screenshots\", `${name}-diff.png`));\n throw new Error(\n `Visual regression: ${(comparison.diffPercentage * 100).toFixed(2)}% diff exceeds threshold ${(threshold * 100).toFixed(0)}%`\n );\n }\n },\n\n copyText: {\n capabilities: [\"query\"],\n run: async (h) => {\n if (!(\"copyText\" in h.step)) unknownStep();\n h.policy.assertAllowedSelector(h.step.copyText.selector);\n const text = await h.driver.textContent(h.step.copyText.selector);\n if (text === null) {\n throw new Error(`No text content found for selector: ${h.step.copyText.selector}`);\n }\n h.runtimeVars.set(h.step.copyText.as, text);\n return {\n kind: \"result\",\n result: {\n type: \"copyText\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n selector: h.step.copyText.selector,\n value: \"[REDACTED]\"\n }\n };\n }\n },\n\n waitForDownload: {\n capabilities: [\"download\"],\n run: async (h) => {\n if (!(\"waitForDownload\" in h.step)) unknownStep();\n const opts = h.step.waitForDownload;\n const downloadPromise = h.context.pendingDownload ?? armDownloadListener(h.driver, opts?.timeout ?? 30000);\n h.context.pendingDownload = undefined;\n const download = await downloadPromise;\n const suggestedFilename = validateDownloadFilename(download.suggestedFilename());\n if (opts?.filename !== undefined && suggestedFilename !== opts.filename) {\n throw new Error(\n `Download filename mismatch: expected \"${opts.filename}\", got \"${suggestedFilename}\"`\n );\n }\n const savePath = path.join(h.context.runDir, suggestedFilename);\n await download.saveAs(savePath);\n return {\n kind: \"result\",\n result: {\n type: \"waitForDownload\",\n status: \"pass\",\n durationMs: Date.now() - h.stepStart,\n value: suggestedFilename\n }\n };\n }\n }\n};\n\nexport async function executeSteps(context: StepExecutionContext): Promise<StepExecutionResult> {\n let driver = context.driver;\n if (!driver) {\n if (!context.page) {\n throw new Error(\"executeSteps requires a driver or a Playwright page\");\n }\n driver = createPlaywrightDriver(context.page);\n }\n const policy = createRunPolicy(driver, {\n forbiddenSelectors: context.forbiddenSelectors,\n allowedDomains: context.allowedDomains,\n allowedApps: context.allowedApps,\n maxSteps: context.maxSteps,\n selfHealing: context.selfHealing\n });\n\n const screenshotsDir = path.join(context.runDir, \"screenshots\");\n fs.mkdirSync(screenshotsDir, { recursive: true });\n const currentHuntName = context.huntStack?.[context.huntStack.length - 1];\n policy.assertWithinMaxSteps(context.steps.length, currentHuntName);\n\n const results: StepResult[] = [];\n const screenshots: string[] = [];\n const runStartedAtMs = context.runStartedAtMs ?? Date.now();\n context.runStartedAtMs = runStartedAtMs;\n\n const addScreenshot = async (fileName: string): Promise<string> => {\n const fullPath = screenshotPath(screenshotsDir, fileName);\n await captureScreenshot(driver, fullPath);\n const relative = path.join(\"screenshots\", fileName);\n screenshots.push(relative);\n return relative;\n };\n\n const executeNested = (\n overrides: Partial<StepExecutionContext> & Pick<StepExecutionContext, \"steps\">\n ): Promise<StepExecutionResult> => executeNestedSteps(context, { driver, ...overrides });\n\n for (let index = 0; index < context.steps.length; index += 1) {\n const currentStepPath = stepPath(context.stepPathPrefix, index);\n if (Date.now() - runStartedAtMs > context.maxTotalTimeMs) {\n results.push({\n type: \"timeout\",\n status: \"fail\",\n durationMs: 0,\n error: `Max total time exceeded (${context.maxTotalTimeMs}ms)`\n });\n return { results, screenshots, failed: true, error: \"Max total time exceeded\" };\n }\n\n const runtimeVars = context.runtimeVars ?? new Map<string, string>();\n context.runtimeVars = runtimeVars;\n\n let step = context.steps[index];\n if (runtimeVars.size > 0) {\n step = applyRuntimeVars(step, runtimeVars);\n }\n const nextStep = context.steps[index + 1];\n if (\n !isWaitForDownloadStep(step)\n && context.pendingDownload === undefined\n && isWaitForDownloadStep(nextStep)\n ) {\n context.pendingDownload = armDownloadListener(\n driver,\n nextStep.waitForDownload?.timeout ?? 30000\n );\n }\n const stepStart = Date.now();\n const stepType = getStepType(step);\n let stepResult: StepResult | null = null;\n\n try {\n const handler = STEP_HANDLERS[stepType];\n if (!handler) {\n throw new Error(\"Unknown step type\");\n }\n for (const capability of handler.capabilities) {\n if (!driver.capabilities.has(capability)) {\n throw new Error(\n `Driver does not support capability \"${capability}\" required by step \"${stepType}\"`\n );\n }\n }\n\n const outcome = await handler.run({\n driver,\n policy,\n context,\n step,\n index,\n stepPath: currentStepPath,\n stepStart,\n runtimeVars,\n results,\n screenshots,\n addScreenshot,\n executeNested\n });\n\n if (outcome.kind === \"abort\") {\n return { results, screenshots, failed: true, error: outcome.error };\n }\n\n stepResult = outcome.result;\n\n if (context.screenshotsMode === \"all\" && stepResult.type !== \"screenshot\") {\n const fileName = `step_${index + 1}.png`;\n await addScreenshot(fileName);\n }\n\n results.push(stepResult);\n context.onStep?.(stepResult, step, index);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Step failed\";\n stepResult = {\n type: stepResult?.type ?? stepType,\n status: \"fail\",\n durationMs: Date.now() - stepStart,\n error: message\n };\n\n if (context.screenshotsMode === \"on-failure\") {\n const fileName = `failure_step_${index + 1}.png`;\n await addScreenshot(fileName);\n }\n\n results.push(stepResult);\n context.onStep?.(stepResult, step, index);\n return { results, screenshots, failed: true, error: message };\n }\n }\n\n return { results, screenshots, failed: false };\n}\n\nexport async function captureFinalScreenshot(page: ScreenshotTaker, runDir: string): Promise<string> {\n const screenshotsDir = path.join(runDir, \"screenshots\");\n fs.mkdirSync(screenshotsDir, { recursive: true });\n const fileName = \"final.png\";\n const filePath = screenshotPath(screenshotsDir, fileName);\n await captureScreenshot(page, filePath);\n return path.join(\"screenshots\", fileName);\n}\n","/**\n * PROWL-047 / ARCH-001 — Guardrail policy layer.\n *\n * The guardrails that used to be enforced inline in `steps.ts`\n * (`allowedDomains`, `forbiddenSelectors`, `maxSteps`, and self-healing) now\n * live here, wrapping a {@link SessionDriver}. Handlers call the policy for\n * selector/URL/step-count checks and to resolve (guard + optionally heal) the\n * selector an explicit-selector action should run against.\n *\n * The forbidden-selector matcher uses the driver-supplied selector parser\n * (`driver.parseTextSelector`) so it can interpret text-engine selectors\n * without hard-coding the engine's dialect.\n */\nimport type { SessionDriver } from \"../browser/driver.js\";\nimport { healSelector, type SelectorProbe } from \"./healing.js\";\n\nconst ALWAYS_ALLOWED_PROTOCOLS = [\"about:\", \"data:\"];\n\nexport type RunPolicyOptions = {\n forbiddenSelectors: string[];\n allowedDomains: string[];\n /**\n * Allow-listed bundle IDs / process names for the macOS target. Defaults to\n * `[]`, which denies every app. This is the inverse of\n * `assertTargetAppAllowed`, where an empty list allows the configured target.\n */\n allowedApps?: string[];\n maxSteps: number;\n selfHealing?: boolean;\n};\n\nexport type RunPolicy = {\n /** Throw if a hunt/step list exceeds the configured `maxSteps`. */\n assertWithinMaxSteps(stepCount: number, huntName?: string): void;\n /** Throw if navigating/landing on a URL whose host is not allow-listed. */\n ensureUrlAllowed(urlValue: string): void;\n /** Throw if a bundle id / process name is not allow-listed; an empty list denies all apps. */\n ensureAppAllowed(app: string): void;\n /**\n * Re-assert scope after an action, in a target-aware way: on a URL-capable\n * driver (web) this is the allowed-domain check on the current URL; on a\n * driver without the `navigate` capability (e.g. macOS) there is no URL to\n * check and app scope is enforced at launch, so this is a no-op.\n */\n ensureLocationAllowed(driver: SessionDriver): void;\n /** Throw if a selector matches the forbidden list. */\n assertAllowedSelector(selector: string): void;\n /**\n * Guard a selector, then — when self-healing is on and it matches nothing —\n * attempt to heal to an equivalent selector (re-checked against the forbidden\n * list). Returns the selector to use plus, when healed, the original.\n */\n resolveActionSelector(selector: string): Promise<{ selector: string; healedFrom?: string }>;\n};\n\nexport function createRunPolicy(driver: SessionDriver, options: RunPolicyOptions): RunPolicy {\n const { forbiddenSelectors, allowedDomains, maxSteps, selfHealing } = options;\n const allowedApps = options.allowedApps ?? [];\n\n // Substring match: if both the selector and forbidden pattern are text=\n // selectors, the selector's text is checked for whether it *contains* the\n // forbidden text. For example, forbidden 'text=\"Delete\"' matches selector\n // 'text=\"Delete All\"'. The driver supplies the text-selector parser.\n function matchesForbiddenPattern(selector: string, forbidden: string): boolean {\n const selectorText = driver.parseTextSelector(selector);\n if (selectorText === null) {\n return false;\n }\n const forbiddenText = driver.parseTextSelector(forbidden);\n if (forbiddenText !== null) {\n return selectorText.includes(forbiddenText);\n }\n return selectorText.includes(forbidden);\n }\n\n // A selector is forbidden if it contains any forbidden pattern as a substring\n // (e.g. forbidden \"[data-danger]\" matches \"[data-danger].active\"), or if the\n // text-based pattern match above succeeds.\n function isForbiddenSelector(selector: string): boolean {\n return forbiddenSelectors.some(\n (forbidden) => selector.includes(forbidden) || matchesForbiddenPattern(selector, forbidden)\n );\n }\n\n function assertAllowedSelector(selector: string): void {\n if (isForbiddenSelector(selector)) {\n throw new Error(`Forbidden selector: ${selector}`);\n }\n }\n\n function assertWithinMaxSteps(stepCount: number, huntName?: string): void {\n if (stepCount > maxSteps) {\n if (huntName) {\n throw new Error(`Hunt \"${huntName}\" has ${stepCount} steps. Max allowed is ${maxSteps}.`);\n }\n throw new Error(`Hunt has ${stepCount} steps. Max allowed is ${maxSteps}.`);\n }\n }\n\n function ensureUrlAllowed(urlValue: string): void {\n for (const protocol of ALWAYS_ALLOWED_PROTOCOLS) {\n if (urlValue.startsWith(protocol)) {\n return;\n }\n }\n let url: URL;\n try {\n url = new URL(urlValue);\n } catch {\n throw new Error(`Navigation target is not a valid absolute URL: ${urlValue}`);\n }\n if (!allowedDomains.includes(url.hostname)) {\n throw new Error(`Navigation to disallowed domain: ${url.hostname}`);\n }\n }\n\n function ensureAppAllowed(app: string): void {\n if (!allowedApps.includes(app)) {\n throw new Error(`Interaction with disallowed app: ${app}`);\n }\n }\n\n function ensureLocationAllowed(activeDriver: SessionDriver): void {\n // URL scope only applies to URL-capable (web) drivers. Non-navigating\n // drivers (macOS) have no URL; their app scope is enforced at launch.\n if (activeDriver.capabilities.has(\"navigate\")) {\n ensureUrlAllowed(activeDriver.currentUrl());\n }\n }\n\n // Bridge the driver's `count` verb to the healing probe surface, so healing\n // stays driver-agnostic.\n const healProbe: SelectorProbe = {\n locator: (selector: string) => ({ count: () => driver.count(selector) })\n };\n\n async function resolveActionSelector(\n selector: string\n ): Promise<{ selector: string; healedFrom?: string }> {\n assertAllowedSelector(selector);\n\n if (!selfHealing) {\n return { selector };\n }\n\n let matched = false;\n try {\n matched = (await driver.count(selector)) > 0;\n } catch {\n // Unparseable/odd selector — let the real action surface the error.\n return { selector };\n }\n if (matched) {\n return { selector };\n }\n\n const healed = await healSelector(healProbe, selector, { enabled: true });\n if (!healed) {\n return { selector };\n }\n\n assertAllowedSelector(healed.selector);\n console.warn(\n `Self-healed selector: \"${selector}\" → \"${healed.selector}\" (${healed.strategy}). ` +\n \"Update your hunt to use a stable selector.\"\n );\n return { selector: healed.selector, healedFrom: healed.healedFrom };\n }\n\n return {\n assertWithinMaxSteps,\n ensureUrlAllowed,\n ensureAppAllowed,\n ensureLocationAllowed,\n assertAllowedSelector,\n resolveActionSelector\n };\n}\n","import type { Assertion, AssertionResult, Config } from \"../types/index.js\";\n\n/**\n * The minimal session surface assertions read from. Both a live Playwright page\n * and a {@link SessionDriver}-backed page satisfy it structurally, so\n * `evaluateAssertions` has no Playwright dependency.\n */\ntype AssertionSession = {\n url(): string;\n locator(selector: string): { count(): Promise<number> };\n};\n\nexport type ConsoleEntry = {\n type: string;\n text: string;\n location?: string;\n};\n\nexport type NetworkEntry = {\n url: string;\n status: number;\n};\n\nfunction shouldIgnoreNetwork(url: string, patterns: string[]): boolean {\n return patterns.some((pattern) => url.includes(pattern));\n}\n\nfunction filterNetworkEntries(entries: NetworkEntry[], patterns: string[]): NetworkEntry[] {\n if (patterns.length === 0) {\n return entries;\n }\n return entries.filter((entry) => !shouldIgnoreNetwork(entry.url, patterns));\n}\n\nfunction mergeAssertions(config: Config, huntAssertions: Assertion[] = []): Assertion[] {\n let noConsoleErrors = config.assertions.noConsoleErrors;\n let noNetworkErrors = config.assertions.noNetworkErrors;\n\n for (const assertion of huntAssertions) {\n if (\"noConsoleErrors\" in assertion) {\n noConsoleErrors = assertion.noConsoleErrors;\n }\n if (\"noNetworkErrors\" in assertion) {\n noNetworkErrors = assertion.noNetworkErrors;\n }\n }\n\n const merged: Assertion[] = [];\n if (noConsoleErrors) {\n merged.push({ noConsoleErrors: true });\n }\n if (noNetworkErrors) {\n merged.push({ noNetworkErrors: true });\n }\n\n for (const assertion of huntAssertions) {\n if (\"noConsoleErrors\" in assertion || \"noNetworkErrors\" in assertion) {\n continue;\n }\n merged.push(assertion);\n }\n\n return merged;\n}\n\nexport async function evaluateAssertions(options: {\n page: AssertionSession;\n config: Config;\n huntAssertions?: Assertion[];\n consoleEntries: ConsoleEntry[];\n networkEntries: NetworkEntry[];\n}): Promise<AssertionResult[]> {\n const assertions = mergeAssertions(options.config, options.huntAssertions);\n const results: AssertionResult[] = [];\n const networkEntries = filterNetworkEntries(\n options.networkEntries,\n options.config.assertions.networkIgnorePatterns\n );\n\n for (const assertion of assertions) {\n try {\n if (\"selectorExists\" in assertion) {\n const count = await options.page.locator(assertion.selectorExists).count();\n results.push({\n type: \"selectorExists\",\n value: assertion.selectorExists,\n status: count > 0 ? \"pass\" : \"fail\",\n error: count > 0 ? undefined : \"Selector not found\"\n });\n continue;\n }\n if (\"selectorNotExists\" in assertion) {\n const count = await options.page.locator(assertion.selectorNotExists).count();\n results.push({\n type: \"selectorNotExists\",\n value: assertion.selectorNotExists,\n status: count === 0 ? \"pass\" : \"fail\",\n error: count === 0 ? undefined : \"Selector exists\"\n });\n continue;\n }\n if (\"urlIncludes\" in assertion) {\n const current = options.page.url();\n const pass = current.includes(assertion.urlIncludes);\n results.push({\n type: \"urlIncludes\",\n value: assertion.urlIncludes,\n status: pass ? \"pass\" : \"fail\",\n error: pass ? undefined : `URL did not include ${assertion.urlIncludes}`\n });\n continue;\n }\n if (\"urlEquals\" in assertion) {\n const current = options.page.url();\n const pass = current === assertion.urlEquals;\n results.push({\n type: \"urlEquals\",\n value: assertion.urlEquals,\n status: pass ? \"pass\" : \"fail\",\n error: pass ? undefined : `URL did not equal ${assertion.urlEquals}`\n });\n continue;\n }\n if (\"noConsoleErrors\" in assertion) {\n const errors = options.consoleEntries.filter((entry) => entry.type === \"error\");\n const pass = errors.length === 0;\n results.push({\n type: \"noConsoleErrors\",\n value: true,\n status: pass ? \"pass\" : \"fail\",\n error: pass ? undefined : `${errors.length} console error(s)`\n });\n continue;\n }\n if (\"noNetworkErrors\" in assertion) {\n const pass = networkEntries.length === 0;\n results.push({\n type: \"noNetworkErrors\",\n value: true,\n status: pass ? \"pass\" : \"fail\",\n error: pass ? undefined : `${networkEntries.length} network error(s)`\n });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Assertion failed\";\n const type = Object.keys(assertion)[0] ?? \"assertion\";\n results.push({\n type,\n status: \"fail\",\n error: message\n });\n }\n }\n\n return results;\n}\n","import type { DriverResponse } from \"../browser/driver.js\";\nimport type { TraceCorrelation } from \"../types/index.js\";\n\n/** Default response header carrying a distributed-trace id (W3C Trace Context). */\nexport const DEFAULT_TRACE_HEADER = \"traceparent\";\n\n/**\n * Extract a trace id from a trace header value.\n *\n * For the W3C `traceparent` format (`version-traceid-spanid-flags`, e.g.\n * `00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01`) the 32-hex trace id\n * is returned. For a non-standard header that simply carries an id, the trimmed\n * raw value is used. Returns undefined for an empty value.\n */\nexport function parseTraceId(headerValue: string): string | undefined {\n const raw = headerValue.trim();\n if (raw.length === 0) return undefined;\n\n const parts = raw.split(\"-\");\n if (parts.length >= 3 && /^[0-9a-f]{32}$/i.test(parts[1])) {\n return parts[1];\n }\n\n return raw;\n}\n\nfunction readHeader(headers: Record<string, string>, headerName: string): string | undefined {\n const normalizedName = headerName.toLowerCase();\n return headers[normalizedName];\n}\n\nfunction redactValues(text: string, values: readonly string[]): string {\n let redacted = text;\n for (const value of values) {\n if (value.length === 0) continue;\n redacted = redacted.split(value).join(\"[REDACTED]\");\n }\n return redacted;\n}\n\n/**\n * If a failing response carries the configured trace header, record a correlation\n * linking the response URL/status to its trace id. No-op when the header is absent\n * or empty, so passing apps produce no noise.\n */\nexport function captureTraceCorrelation(\n response: DriverResponse,\n headerName: string,\n sink: TraceCorrelation[],\n redactionValues: readonly string[] = []\n): void {\n const value = readHeader(response.headers(), headerName);\n if (!value) return;\n\n const traceId = parseTraceId(value);\n if (!traceId) return;\n\n sink.push({\n url: redactValues(response.url(), redactionValues),\n status: response.status(),\n traceId,\n header: value\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { RunResult } from \"../types/index.js\";\n\nexport function writeResult(runDir: string, result: RunResult): string {\n const fileName = \"result.json\";\n const fullPath = path.join(runDir, fileName);\n fs.writeFileSync(fullPath, JSON.stringify(result, null, 2));\n return fileName;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AssertionResult, RunResult, StepResult } from \"../types/index.js\";\n\nexport function escapeMd(text: string): string {\n return text.replace(/([|`*_{}[\\]()#+\\-!\\\\])/g, \"\\\\$1\");\n}\n\nfunction formatStep(step: StepResult): string {\n const base = `- [${step.status.toUpperCase()}] ${step.type} (${step.durationMs}ms)`;\n const selector = step.selector ? ` selector=${step.selector}` : \"\";\n const healed = step.healedFrom ? ` healed-from=${escapeMd(step.healedFrom)}` : \"\";\n const value = step.value ? ` value=${escapeMd(step.value)}` : \"\";\n const error = step.error ? ` error=${escapeMd(step.error)}` : \"\";\n return `${base}${selector}${healed}${value}${error}`;\n}\n\nfunction formatAssertion(assertion: AssertionResult): string {\n const value = assertion.value !== undefined ? ` value=${typeof assertion.value === \"string\" ? escapeMd(assertion.value) : assertion.value}` : \"\";\n const error = assertion.error ? ` error=${escapeMd(assertion.error)}` : \"\";\n return `- [${assertion.status.toUpperCase()}] ${assertion.type}${value}${error}`;\n}\n\nexport function writeSummary(runDir: string, result: RunResult): string {\n const lines: string[] = [];\n lines.push(\"# Prowl Run Summary\");\n lines.push(\"\");\n lines.push(`Status: ${result.status.toUpperCase()}`);\n lines.push(`Hunt: ${result.hunt}`);\n lines.push(`Target: ${result.targetUrl}`);\n lines.push(`Started: ${result.startedAt}`);\n lines.push(`Duration: ${result.durationMs}ms`);\n lines.push(\"\");\n lines.push(\"## Steps\");\n for (const step of result.steps) {\n lines.push(formatStep(step));\n }\n\n const healed = result.steps.filter((step) => step.healedFrom);\n if (healed.length > 0) {\n lines.push(\"\");\n lines.push(\"## Self-Healed Selectors\");\n lines.push(\"These selectors no longer matched and were auto-healed. Update your hunt to use the healed selector (or a stable `data-testid`):\");\n for (const step of healed) {\n lines.push(`- ${escapeMd(step.healedFrom ?? \"\")} → ${escapeMd(step.selector ?? \"\")}`);\n }\n }\n\n lines.push(\"\");\n lines.push(\"## Assertions\");\n for (const assertion of result.assertions) {\n lines.push(formatAssertion(assertion));\n }\n if (result.traceCorrelations && result.traceCorrelations.length > 0) {\n lines.push(\"\");\n lines.push(\"## Trace Correlations\");\n for (const correlation of result.traceCorrelations) {\n lines.push(\n `- [${correlation.status}] ${escapeMd(correlation.url)} traceId=${escapeMd(correlation.traceId)}`\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\"## Artifacts\");\n const artifacts = result.artifacts;\n if (artifacts.summary) {\n lines.push(`- summary: ${artifacts.summary}`);\n }\n if (artifacts.console) {\n lines.push(`- console: ${artifacts.console}`);\n }\n if (artifacts.trace) {\n lines.push(`- trace: ${artifacts.trace}`);\n }\n if (artifacts.networkHar) {\n lines.push(`- network: ${artifacts.networkHar}`);\n }\n if (artifacts.junit) {\n lines.push(`- junit: ${artifacts.junit}`);\n }\n if (artifacts.screenshots && artifacts.screenshots.length > 0) {\n for (const screenshot of artifacts.screenshots) {\n lines.push(`- screenshot: ${screenshot}`);\n }\n }\n\n const fileName = \"summary.md\";\n const fullPath = path.join(runDir, fileName);\n fs.writeFileSync(fullPath, `${lines.join(\"\\n\")}\\n`);\n return fileName;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { RunResult } from \"../types/index.js\";\n\nexport function escapeXml(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nexport function writeJunit(runDir: string, result: RunResult): string {\n const totalTests = result.steps.length + result.assertions.length;\n const failures =\n result.steps.filter((s) => s.status === \"fail\").length +\n result.assertions.filter((a) => a.status === \"fail\").length;\n const timeSeconds = (result.durationMs / 1000).toFixed(3);\n const huntName = escapeXml(result.hunt);\n\n const lines: string[] = [];\n lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n lines.push(\"<testsuites>\");\n lines.push(\n ` <testsuite name=\"${huntName}\" tests=\"${totalTests}\" failures=\"${failures}\" errors=\"0\" time=\"${timeSeconds}\" timestamp=\"${escapeXml(result.startedAt)}\">`\n );\n\n for (let i = 0; i < result.steps.length; i++) {\n const step = result.steps[i];\n const stepTime = (step.durationMs / 1000).toFixed(3);\n const caseName = escapeXml(`step ${i + 1}: ${step.type}`);\n\n if (step.status === \"fail\") {\n const failureText = step.error ?? `Step ${step.type} failed with no error provided`;\n const escapedFailureText = escapeXml(failureText);\n lines.push(` <testcase name=\"${caseName}\" classname=\"${huntName}\" time=\"${stepTime}\">`);\n lines.push(` <failure message=\"${escapedFailureText}\" type=\"step\">${escapedFailureText}</failure>`);\n lines.push(\" </testcase>\");\n } else {\n lines.push(` <testcase name=\"${caseName}\" classname=\"${huntName}\" time=\"${stepTime}\"/>`);\n }\n }\n\n for (const assertion of result.assertions) {\n const caseName = escapeXml(`assertion: ${assertion.type}`);\n\n if (assertion.status === \"fail\") {\n const failureText = assertion.error ?? `Assertion ${assertion.type} failed with no error provided`;\n const escapedFailureText = escapeXml(failureText);\n lines.push(` <testcase name=\"${caseName}\" classname=\"${huntName}\" time=\"0\">`);\n lines.push(` <failure message=\"${escapedFailureText}\" type=\"assertion\">${escapedFailureText}</failure>`);\n lines.push(\" </testcase>\");\n } else {\n lines.push(` <testcase name=\"${caseName}\" classname=\"${huntName}\" time=\"0\"/>`);\n }\n }\n\n lines.push(\" </testsuite>\");\n lines.push(\"</testsuites>\");\n\n const fileName = \"junit.xml\";\n const fullPath = path.join(runDir, fileName);\n fs.writeFileSync(fullPath, `${lines.join(\"\\n\")}\\n`);\n return fileName;\n}\n","import type { RunResult } from \"../types/index.js\";\nimport { writeResult } from \"./result.js\";\nimport { writeSummary } from \"./summary.js\";\nimport { writeJunit } from \"./junit.js\";\n\nexport type ReportOptions = {\n junit?: boolean;\n};\n\nexport function writeReports(runDir: string, result: RunResult, options?: ReportOptions): RunResult {\n const summary = writeSummary(runDir, result);\n const updated: RunResult = {\n ...result,\n artifacts: {\n ...result.artifacts,\n summary\n }\n };\n\n if (options?.junit) {\n updated.artifacts.junit = writeJunit(runDir, updated);\n }\n\n writeResult(runDir, updated);\n\n return updated;\n}\n","export function timestamp(prefix?: string): string {\n const now = new Date();\n const pad = (value: number): string => value.toString().padStart(2, \"0\");\n const pad3 = (value: number): string => value.toString().padStart(3, \"0\");\n const ts = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(\n now.getHours()\n )}-${pad(now.getMinutes())}-${pad(now.getSeconds())}-${pad3(now.getMilliseconds())}`;\n return prefix ? `${prefix}-${ts}` : ts;\n}\n","import type { HistoryEntry } from \"../types/index.js\";\nimport { readHistory } from \"./history.js\";\n\nexport const DEFAULT_FLAKY_THRESHOLD = 0.3;\n\nexport type FlakyScore = {\n hunt: string;\n /** Oscillation rate in [0,1]: share of consecutive run pairs whose status changed. */\n score: number;\n runs: number;\n flaky: boolean;\n};\n\n/**\n * Flake score for a single hunt's run history (oldest→newest): the fraction of\n * consecutive run pairs where the status flipped (pass↔fail). 0 = perfectly\n * stable, 1 = flips every run. Needs at least 2 runs; fewer returns 0.\n */\nexport function computeFlakeScore(entries: HistoryEntry[], lastN?: number): number {\n const slice = lastN !== undefined && lastN > 0 ? entries.slice(-lastN) : entries;\n if (slice.length < 2) return 0;\n\n let transitions = 0;\n for (let i = 1; i < slice.length; i++) {\n if (slice[i].status !== slice[i - 1].status) {\n transitions += 1;\n }\n }\n return transitions / (slice.length - 1);\n}\n\nexport type RankFlakyOptions = {\n /** Only score the most recent N runs per hunt. */\n lastN?: number;\n /** Score at/above this is flagged flaky. Defaults to DEFAULT_FLAKY_THRESHOLD. */\n threshold?: number;\n};\n\n/**\n * Rank every hunt in the project's history by flake score, highest first.\n * Hunts are tie-broken by run count (more runs first) then name for stable output.\n */\nexport function rankFlaky(configDir: string, options: RankFlakyOptions = {}): FlakyScore[] {\n const threshold = options.threshold ?? DEFAULT_FLAKY_THRESHOLD;\n const { entries } = readHistory(configDir);\n\n const byHunt = new Map<string, HistoryEntry[]>();\n for (const entry of entries) {\n const list = byHunt.get(entry.hunt) ?? [];\n list.push(entry);\n byHunt.set(entry.hunt, list);\n }\n\n const scores: FlakyScore[] = [];\n for (const [hunt, huntEntries] of byHunt) {\n const considered = options.lastN !== undefined && options.lastN > 0\n ? huntEntries.slice(-options.lastN)\n : huntEntries;\n const score = computeFlakeScore(considered);\n scores.push({\n hunt,\n score,\n runs: considered.length,\n flaky: score >= threshold\n });\n }\n\n scores.sort((a, b) => b.score - a.score || b.runs - a.runs || a.hunt.localeCompare(b.hunt));\n return scores;\n}\n","import { createHash } from \"node:crypto\";\n\n/**\n * A single failure worth logging as a bug: a specific hunt failing at a specific\n * spot. `stepType`/`selector`/`stepIndex` are absent when the hunt threw before\n * producing step results (e.g. a missing hunt file).\n */\nexport interface BugFailure {\n hunt: string;\n stepIndex?: number;\n stepType?: string;\n selector?: string;\n error: string;\n runDir?: string;\n}\n\n/**\n * Reduce an error message to its stable \"class\" by removing volatile details\n * (timeout durations, pixel coordinates, hex ids) so the same underlying failure\n * keeps the same fingerprint across runs.\n */\nexport function normalizeError(error: string): string {\n return error\n .toLowerCase()\n .replace(/0x[0-9a-f]+/g, \"\") // hex ids\n .replace(/\\b\\d+(?:\\.\\d+)?\\s*(?:ms|s|px)\\b/g, \"\") // unit-qualified timings/coordinates\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/**\n * Stable label for the failing spot within a hunt, e.g. `4:click@#submit`.\n * Used in the human-readable marker. Returns `-` when no step is known.\n */\nexport function stepLabel(failure: BugFailure): string {\n if (failure.stepType === undefined && failure.selector === undefined) {\n return \"-\";\n }\n const index = failure.stepIndex === undefined ? \"?\" : String(failure.stepIndex);\n const type = failure.stepType ?? \"?\";\n const selector = failure.selector ? `@${failure.selector}` : \"\";\n return `${index}:${type}${selector}`;\n}\n\n/** Keep untrusted metadata from changing the hidden HTML-comment shape. */\nfunction sanitizeMarkerValue(value: string): string {\n return value\n .replace(/\\r?\\n/g, \" \")\n .replace(/-->/g, \"--&gt;\")\n .trim();\n}\n\n/**\n * Identifies \"the same bug\" across runs: the hunt, the failing step's type and\n * selector, and the normalized error class. The step *index* is deliberately\n * excluded so reordering/inserting steps in a hunt does not spawn a duplicate.\n */\nexport function computeFingerprint(failure: BugFailure): string {\n const parts = [\n failure.hunt,\n failure.stepType ?? \"\",\n failure.selector ?? \"\",\n normalizeError(failure.error)\n ];\n return createHash(\"sha1\").update(parts.join(\"|\")).digest(\"hex\").slice(0, 8);\n}\n\n/** Hidden HTML-comment marker embedded in each ticket so re-runs can recognize it. */\nexport function buildMarker(failure: BugFailure, hash: string): string {\n const hunt = sanitizeMarkerValue(failure.hunt);\n const step = sanitizeMarkerValue(stepLabel(failure));\n return `<!-- prowl:fp=${hash} hunt=${hunt} step=${step} -->`;\n}\n","import type { BugFailure } from \"../backlog/fingerprint.js\";\nimport { normalizeError } from \"../backlog/fingerprint.js\";\nimport type { CiFailureCluster } from \"../types/index.js\";\n\n/**\n * Failure clustering (PROWL-034). Groups failures that share a common cause —\n * the same normalized error on the same step type and selector — so a single\n * root cause (e.g. one renamed selector breaking 5 hunts) surfaces as one\n * cluster instead of N independent failures.\n */\nexport type FailureCluster = CiFailureCluster;\n\nfunction clusterKey(failure: BugFailure, normalizedError: string): string {\n return [failure.stepType ?? \"\", failure.selector ?? \"\", normalizedError].join(\"|\");\n}\n\nfunction describeCause(failure: BugFailure, error: string): string {\n const where = failure.stepType\n ? `${failure.stepType}${failure.selector ? ` (${failure.selector})` : \"\"}`\n : \"run\";\n return `${where}: ${error}`;\n}\n\n/**\n * Group failures by shared cause. Returns clusters sorted by size (largest first),\n * then by cause for stable output. Every failure lands in a cluster — single-hunt\n * clusters are included so the full picture is preserved; callers can filter to\n * `count > 1` to show only shared root causes.\n */\nexport function clusterFailures(failures: BugFailure[]): FailureCluster[] {\n const groups = new Map<string, { sample: BugFailure; error: string; hunts: Set<string> }>();\n\n for (const failure of failures) {\n const error = normalizeError(failure.error);\n const key = clusterKey(failure, error);\n const existing = groups.get(key);\n if (existing) {\n existing.hunts.add(failure.hunt);\n } else {\n groups.set(key, { sample: failure, error, hunts: new Set([failure.hunt]) });\n }\n }\n\n const clusters: FailureCluster[] = [];\n for (const { sample, error, hunts } of groups.values()) {\n clusters.push({\n cause: describeCause(sample, error),\n stepType: sample.stepType,\n selector: sample.selector,\n error,\n count: hunts.size,\n hunts: [...hunts].sort()\n });\n }\n\n clusters.sort((a, b) => b.count - a.count || a.cause.localeCompare(b.cause));\n return clusters;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { CiHuntResult, RunResult } from \"../types/index.js\";\nimport type { RunSuiteResult } from \"../runner/suite.js\";\nimport { type BugFailure, buildMarker, computeFingerprint } from \"./fingerprint.js\";\nimport { classifyFingerprint, extractFingerprints, nextTicketId } from \"./parse.js\";\nimport { insertTickets, renderTicket } from \"./write.js\";\n\nexport type { BugFailure } from \"./fingerprint.js\";\nexport { SECTION_HEADING } from \"./write.js\";\n\nexport interface UpdateBacklogOptions {\n /** Project root containing docs/. Defaults to process.cwd(). */\n projectRoot?: string;\n /** Overrides the backlog path (default: <projectRoot>/docs/backlog.md). */\n backlogPath?: string;\n /** Overrides the resolved path (default: <projectRoot>/docs/resolved.md). */\n resolvedPath?: string;\n /** Date stamp for new tickets (default: today, YYYY-MM-DD). */\n date?: string;\n}\n\nexport interface BugLogSummary {\n /** QA-NNN ids created for brand-new failures. */\n created: string[];\n /** QA-NNN ids created for failures that recurred after being resolved. */\n regressions: string[];\n /** QA-NNN ids of already-open tickets that were left untouched. */\n skipped: string[];\n backlogPath: string;\n}\n\n/** Read optional backlog state, returning empty content only when the file is absent. */\nfunction readFileOrEmpty(filePath: string): string {\n try {\n return fs.readFileSync(filePath, \"utf-8\");\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === \"ENOENT\") return \"\";\n throw new Error(`Failed to read \"${filePath}\": ${err.message}`);\n }\n}\n\n/** Convert a failed CI hunt result into the most specific backlog failure available. */\nfunction buildFailure(hunt: CiHuntResult): BugFailure {\n const failure: BugFailure = {\n hunt: hunt.hunt,\n error: hunt.error ?? \"Run failed\",\n runDir: hunt.runDir\n };\n\n if (!hunt.runDir) return failure;\n\n let run: RunResult;\n try {\n const resultJson = readFileOrEmpty(path.join(hunt.runDir, \"result.json\"));\n if (!resultJson) return failure;\n run = JSON.parse(resultJson) as RunResult;\n } catch (error) {\n if (!(error instanceof SyntaxError)) throw error;\n return failure; // Malformed result.json; keep the message-only failure.\n }\n if (!run || !Array.isArray(run.steps)) return failure;\n\n const stepIndex = run.steps.findIndex((step) => step.status === \"fail\");\n if (stepIndex !== -1) {\n const step = run.steps[stepIndex];\n failure.stepIndex = stepIndex;\n failure.stepType = step.type;\n failure.selector = step.selector;\n if (step.error) failure.error = step.error;\n return failure;\n }\n\n const failedAssertion = run.assertions?.find((assertion) => assertion.status === \"fail\");\n if (failedAssertion) {\n failure.stepType = `assert:${failedAssertion.type}`;\n if (failedAssertion.error) failure.error = failedAssertion.error;\n }\n\n return failure;\n}\n\n/** Extract one BugFailure per failed hunt from a completed suite run. */\nexport function extractFailures(suiteResult: RunSuiteResult): BugFailure[] {\n return suiteResult.result.hunts\n .filter((hunt) => hunt.status === \"fail\")\n .map(buildFailure);\n}\n\n/**\n * Logs failures from a completed suite run as deduplicated bug tickets in the\n * target project's backlog. New failures get a fresh QA-NNN ticket; failures that\n * already have an open ticket are skipped; failures matching a resolved ticket are\n * logged as regressions that reference the old id. Idempotent across runs.\n */\nexport function updateBacklogFromSuite(\n suiteResult: RunSuiteResult,\n options: UpdateBacklogOptions = {}\n): BugLogSummary {\n const projectRoot = options.projectRoot ?? process.cwd();\n const backlogPath = options.backlogPath ?? path.join(projectRoot, \"docs\", \"backlog.md\");\n const resolvedPath = options.resolvedPath ?? path.join(projectRoot, \"docs\", \"resolved.md\");\n const date = options.date ?? new Date().toISOString().slice(0, 10);\n\n const summary: BugLogSummary = { created: [], regressions: [], skipped: [], backlogPath };\n\n const failures = extractFailures(suiteResult);\n if (failures.length === 0) return summary;\n\n const backlogContent = readFileOrEmpty(backlogPath);\n const resolvedContent = readFileOrEmpty(resolvedPath);\n\n const activeFps = extractFingerprints(backlogContent);\n const resolvedFps = extractFingerprints(resolvedContent);\n\n let counter = Number(nextTicketId([backlogContent, resolvedContent]).slice(3));\n const makeId = (): string => `QA-${String(counter++).padStart(3, \"0\")}`;\n\n const seenThisRun = new Set<string>();\n const ticketsToAdd: string[] = [];\n\n for (const failure of failures) {\n const fp = computeFingerprint(failure);\n if (seenThisRun.has(fp)) continue;\n seenThisRun.add(fp);\n\n const classification = classifyFingerprint(fp, activeFps, resolvedFps);\n if (classification.kind === \"open\") {\n summary.skipped.push(classification.ticketId);\n continue;\n }\n\n const id = makeId();\n const regressionOf = classification.kind === \"regression\" ? classification.resolvedId : undefined;\n ticketsToAdd.push(renderTicket({ id, failure, marker: buildMarker(failure, fp), regressionOf, date }));\n\n if (regressionOf) {\n summary.regressions.push(id);\n } else {\n summary.created.push(id);\n }\n }\n\n if (ticketsToAdd.length > 0) {\n fs.mkdirSync(path.dirname(backlogPath), { recursive: true });\n fs.writeFileSync(backlogPath, insertTickets(backlogContent, ticketsToAdd));\n }\n\n return summary;\n}\n","const MARKER_FP = /<!--\\s*prowl:fp=([0-9a-f]+)/;\nconst TICKET_ID = /\\bQA-(\\d+)\\b/;\nconst TICKET_ID_GLOBAL = /\\bQA-(\\d+)\\b/g;\nconst HEADING = /^#{1,6}\\s/;\n\n/**\n * Map each embedded fingerprint to the QA-NNN ticket id that owns it, by pairing\n * every `prowl:fp=` marker with the most recent ticket heading above it.\n */\nexport function extractFingerprints(content: string): Map<string, string> {\n const map = new Map<string, string>();\n let currentId: string | undefined;\n\n for (const line of content.split(\"\\n\")) {\n if (HEADING.test(line)) {\n const idMatch = TICKET_ID.exec(line);\n currentId = idMatch ? `QA-${idMatch[1]}` : undefined;\n }\n const fpMatch = MARKER_FP.exec(line);\n if (fpMatch && currentId) {\n map.set(fpMatch[1], currentId);\n }\n }\n\n return map;\n}\n\n/** The next available QA-NNN id across all provided file contents (max + 1, zero-padded). */\nexport function nextTicketId(contents: string[]): string {\n let max = 0;\n for (const content of contents) {\n for (const match of content.matchAll(TICKET_ID_GLOBAL)) {\n const n = Number(match[1]);\n if (n > max) max = n;\n }\n }\n return `QA-${String(max + 1).padStart(3, \"0\")}`;\n}\n\nexport type Classification =\n | { kind: \"new\" }\n | { kind: \"open\"; ticketId: string }\n | { kind: \"regression\"; resolvedId: string };\n\n/**\n * Decide how to handle a failure fingerprint:\n * - already tracked in the active backlog -> `open` (skip, no duplicate)\n * - previously resolved -> `regression` (link the old id)\n * - otherwise -> `new`\n */\nexport function classifyFingerprint(\n fp: string,\n activeFps: Map<string, string>,\n resolvedFps: Map<string, string>\n): Classification {\n const openId = activeFps.get(fp);\n if (openId) return { kind: \"open\", ticketId: openId };\n\n const resolvedId = resolvedFps.get(fp);\n if (resolvedId) return { kind: \"regression\", resolvedId };\n\n return { kind: \"new\" };\n}\n","import type { BugFailure } from \"./fingerprint.js\";\n\n/** Heading of the dedicated, agent-owned section in the target project's backlog. */\nexport const SECTION_HEADING = \"## QA Findings (automated)\";\n\nexport interface RenderTicketOptions {\n id: string;\n failure: BugFailure;\n marker: string;\n /** When set, this failure previously had a resolved ticket — link it as a regression. */\n regressionOf?: string;\n /** YYYY-MM-DD */\n date: string;\n}\n\n/** Render one failure as a markdown QA ticket with stable machine-readable metadata. */\nexport function renderTicket(opts: RenderTicketOptions): string {\n const { id, failure, marker, regressionOf, date } = opts;\n\n const spot = failure.stepType\n ? `${failure.stepType}${failure.selector ? ` (${failure.selector})` : \"\"}`\n : \"run failed before steps executed\";\n\n const lines: string[] = [];\n lines.push(`### ${id}: ${failure.hunt} — ${spot}`);\n lines.push(marker);\n lines.push(`**Logged**: ${date}`);\n if (regressionOf) {\n lines.push(`**Regression of**: ${regressionOf} (previously resolved — see resolved.md)`);\n }\n lines.push(`**Hunt**: ${failure.hunt}`);\n const stepDesc = failure.stepType\n ? `step ${failure.stepIndex ?? \"?\"} — ${failure.stepType}${failure.selector ? ` ${failure.selector}` : \"\"}`\n : \"n/a (hunt did not produce step results)\";\n lines.push(`**Failing step**: ${stepDesc}`);\n lines.push(`**Error**: ${failure.error}`);\n if (failure.runDir) {\n lines.push(`**Artifacts**: ${failure.runDir}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Append rendered tickets into the agent-owned section, creating the section at\n * the end of the file if it does not exist. Existing content is preserved.\n */\nexport function insertTickets(content: string, tickets: string[]): string {\n if (tickets.length === 0) return content;\n const block = tickets.join(\"\\n\\n\");\n\n const headingIndex = content.indexOf(SECTION_HEADING);\n if (headingIndex === -1) {\n const base = content.replace(/\\n*$/, \"\");\n const prefix = base ? `${base}\\n\\n` : \"\";\n return `${prefix}${SECTION_HEADING}\\n\\n${block}\\n`;\n }\n\n // Insert at the end of the section: just before the next top-level heading, or EOF.\n const afterHeading = headingIndex + SECTION_HEADING.length;\n const rest = content.slice(afterHeading);\n const nextHeadingRel = rest.search(/\\n## /);\n const insertAt = nextHeadingRel === -1 ? content.length : afterHeading + nextHeadingRel;\n\n const before = content.slice(0, insertAt).replace(/\\n*$/, \"\");\n const after = content.slice(insertAt);\n return `${before}\\n\\n${block}\\n${after}`;\n}\n","import path from \"node:path\";\nimport { runHunt, type RunOptions } from \"./index.js\";\nimport { loadConfig, listHunts, loadHuntTags } from \"../config/loader.js\";\nimport { writeCiResult, resolveCiStatus, countCiResults } from \"../reporter/ci-summary.js\";\nimport { timestamp } from \"../utils/timestamp.js\";\nimport { runWithConcurrency } from \"../utils/concurrency.js\";\nimport type { CiFailureCluster, CiFlakyHunt, CiHuntResult, CiResult, RunResult } from \"../types/index.js\";\nimport { rankFlaky, DEFAULT_FLAKY_THRESHOLD } from \"./flaky.js\";\nimport { clusterFailures } from \"./clustering.js\";\nimport { extractFailures } from \"../backlog/index.js\";\n\nexport type SkipReason = \"include\" | \"exclude\";\ntype SuiteHookResult = void | Promise<void>;\n\nexport interface RunSuiteHooks {\n onHuntStart?: (huntName: string) => SuiteHookResult;\n onStep?: RunOptions[\"onStep\"];\n onHuntSuccess?: (huntName: string, result: RunResult, runDir: string) => SuiteHookResult;\n onHuntFailure?: (huntName: string, message: string) => SuiteHookResult;\n onHuntSkipped?: (huntName: string, reason: SkipReason) => SuiteHookResult;\n}\n\nexport interface RunSuiteOptions {\n configPath?: string;\n urlOverride?: string;\n headed?: boolean;\n slowMo?: number;\n trace?: boolean;\n browser?: RunOptions[\"browser\"];\n channel?: RunOptions[\"channel\"];\n viewport?: string;\n junit?: boolean;\n includeTags?: string[];\n excludeTags?: string[];\n parallel?: number;\n hooks?: RunSuiteHooks;\n}\n\nexport interface RunSuiteResult {\n result: CiResult;\n /** Path to the written ci-result.json, or null when there were no hunts to run. */\n resultPath: string | null;\n}\n\nfunction normalizeTagFilter(tags: string[] | undefined): string[] | undefined {\n const normalized = tags?.map((tag) => tag.trim()).filter(Boolean);\n return normalized && normalized.length > 0 ? normalized : undefined;\n}\n\nasync function callHook(callback: (() => SuiteHookResult | undefined) | undefined): Promise<void> {\n if (!callback) return;\n try {\n await callback();\n } catch {\n // Presentation hooks must never change suite or hunt outcomes.\n }\n}\n\nfunction safeOnStep(hooks: RunSuiteHooks): RunOptions[\"onStep\"] {\n if (!hooks.onStep) return undefined;\n return (result, step, index) => {\n try {\n hooks.onStep?.(result, step, index);\n } catch {\n // Presentation hooks must never change suite or hunt outcomes.\n }\n };\n}\n\nfunction firstRunFailureMessage(result: RunResult): string | undefined {\n const failedStep = result.steps.find((step) => step.status === \"fail\" && step.error);\n if (failedStep?.error) return failedStep.error;\n\n const failedAssertion = result.assertions.find((assertion) => assertion.status === \"fail\" && assertion.error);\n return failedAssertion?.error;\n}\n\n/**\n * Runs every hunt in the project and aggregates a CiResult. Side-effect-free with\n * respect to the console and process exit — callers provide hooks for presentation\n * and inspect the returned status for exit codes.\n */\nexport async function runSuite(options: RunSuiteOptions = {}): Promise<RunSuiteResult> {\n const startedAt = new Date().toISOString();\n const startTime = Date.now();\n const hooks = options.hooks ?? {};\n\n const { config, configDir } = loadConfig(options.configPath);\n const hunts = listHunts(configDir);\n\n if (hunts.length === 0) {\n return {\n result: {\n status: \"no-hunts\",\n startedAt,\n durationMs: 0,\n totalHunts: 0,\n passed: 0,\n failed: 0,\n skipped: 0,\n hunts: []\n },\n resultPath: null\n };\n }\n\n const includeTags = normalizeTagFilter(options.includeTags);\n const excludeTags = normalizeTagFilter(options.excludeTags);\n const resultsByIndex: Array<CiHuntResult | undefined> = new Array(hunts.length);\n const onStep = safeOnStep(hooks);\n\n // Phase 1: Tag filtering (always sequential, preserves hunt order)\n const huntsToRun: Array<{ huntName: string; index: number }> = [];\n for (let index = 0; index < hunts.length; index++) {\n const huntName = hunts[index];\n if (includeTags || excludeTags) {\n const tags = loadHuntTags(huntName, configDir);\n\n if (includeTags && !includeTags.some((t) => tags.includes(t))) {\n await callHook(() => hooks.onHuntSkipped?.(huntName, \"include\"));\n resultsByIndex[index] = { hunt: huntName, status: \"skipped\", durationMs: 0 };\n continue;\n }\n if (excludeTags && excludeTags.some((t) => tags.includes(t))) {\n await callHook(() => hooks.onHuntSkipped?.(huntName, \"exclude\"));\n resultsByIndex[index] = { hunt: huntName, status: \"skipped\", durationMs: 0 };\n continue;\n }\n }\n huntsToRun.push({ huntName, index });\n }\n\n // Phase 2: Build a task per hunt to run\n const buildTask = (huntName: string) => async (): Promise<CiHuntResult> => {\n const huntStart = Date.now();\n try {\n await callHook(() => hooks.onHuntStart?.(huntName));\n\n const { result, runDir } = await runHunt({\n huntName,\n urlOverride: options.urlOverride,\n headed: options.headed,\n slowMo: options.slowMo,\n trace: options.trace,\n browser: options.browser,\n channel: options.channel,\n viewport: options.viewport,\n junit: options.junit,\n configPath: options.configPath,\n onStep\n });\n\n const error = result.status === \"fail\" ? firstRunFailureMessage(result) ?? \"Run failed\" : undefined;\n if (error) {\n await callHook(() => hooks.onHuntFailure?.(huntName, error));\n } else {\n await callHook(() => hooks.onHuntSuccess?.(huntName, result, runDir));\n }\n\n return {\n hunt: huntName,\n status: result.status,\n durationMs: result.durationMs,\n runDir,\n error\n };\n } catch (error) {\n const durationMs = Date.now() - huntStart;\n const message = error instanceof Error ? error.message : \"Run failed\";\n await callHook(() => hooks.onHuntFailure?.(huntName, message));\n return {\n hunt: huntName,\n status: \"fail\",\n durationMs,\n error: message\n };\n }\n };\n\n // Phase 3: Execute (parallel when requested, otherwise sequential in hunt order)\n const parallel = options.parallel;\n if (parallel !== undefined && parallel > 1) {\n const tasks = huntsToRun.map((entry) => ({ ...entry, task: buildTask(entry.huntName) }));\n const parallelResults = await runWithConcurrency(\n tasks.map((entry) => entry.task),\n parallel\n );\n for (let i = 0; i < parallelResults.length; i++) {\n const pr = parallelResults[i];\n const task = tasks[i];\n if (pr.status === \"fulfilled\") {\n resultsByIndex[task.index] = pr.value;\n } else {\n const message = pr.reason instanceof Error ? pr.reason.message : \"Run failed\";\n resultsByIndex[task.index] = {\n hunt: task.huntName,\n status: \"fail\",\n durationMs: 0,\n error: message\n };\n }\n }\n } else {\n for (const { huntName, index } of huntsToRun) {\n resultsByIndex[index] = await buildTask(huntName)();\n }\n }\n\n const totalDurationMs = Date.now() - startTime;\n const results: CiHuntResult[] = resultsByIndex.map((result, index) => {\n return result ?? {\n hunt: hunts[index],\n status: \"fail\",\n durationMs: 0,\n error: \"Run did not produce a result\"\n };\n });\n\n // Flag flaky hunts among those that actually ran this suite, using accumulated\n // run history (which already includes this run's entries). Omitted when none.\n const threshold = config.reliability?.flakyThreshold ?? DEFAULT_FLAKY_THRESHOLD;\n const ranThisSuite = new Set(\n results.filter((r) => r.status !== \"skipped\").map((r) => r.hunt)\n );\n const flaky: CiFlakyHunt[] = rankFlaky(configDir, { threshold })\n .filter((entry) => entry.flaky && ranThisSuite.has(entry.hunt))\n .map((entry) => ({ hunt: entry.hunt, score: entry.score }));\n\n // Cluster failures from this suite by shared cause; surface only multi-hunt\n // clusters (a single failing hunt is just that failure, not a \"cluster\").\n const clusters: CiFailureCluster[] = clusterFailures(\n extractFailures({ result: { hunts: results } as CiResult, resultPath: null })\n ).filter((cluster) => cluster.count > 1);\n\n const ciRunDir = path.join(configDir, \"runs\", timestamp(\"ci\"));\n const resultPath = writeCiResult(ciRunDir, results, startedAt, totalDurationMs, flaky, clusters);\n\n const { passed, failed, skipped } = countCiResults(results);\n\n return {\n result: {\n status: resolveCiStatus(results),\n startedAt,\n durationMs: totalDurationMs,\n totalHunts: results.length,\n passed,\n failed,\n skipped,\n hunts: results,\n ...(flaky.length > 0 ? { flaky } : {}),\n ...(clusters.length > 0 ? { clusters } : {})\n },\n resultPath\n };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport type { CiFailureCluster, CiFlakyHunt, CiHuntResult, CiResult, CiStatus } from \"../types/index.js\";\n\nexport type CiCounts = {\n passed: number;\n failed: number;\n skipped: number;\n};\n\nexport function countCiResults(results: CiHuntResult[]): CiCounts {\n return {\n passed: results.filter((r) => r.status === \"pass\").length,\n failed: results.filter((r) => r.status === \"fail\").length,\n skipped: results.filter((r) => r.status === \"skipped\").length\n };\n}\n\nexport function resolveCiStatus(results: CiHuntResult[]): CiStatus {\n if (results.length === 0) return \"no-hunts\";\n const { failed, passed } = countCiResults(results);\n if (failed > 0) return \"fail\";\n if (passed > 0) return \"pass\";\n return \"all-skipped\";\n}\n\nexport function printCiSummary(\n results: CiHuntResult[],\n totalDurationMs: number,\n flaky: CiFlakyHunt[] = [],\n clusters: CiFailureCluster[] = []\n): void {\n const { passed, failed, skipped } = countCiResults(results);\n\n const lineWidth = 45;\n console.log(`\\n ── CI Summary ${\"─\".repeat(lineWidth - 15)}`);\n\n for (const r of results) {\n const icon = r.status === \"pass\" ? chalk.green(\"✓\") : r.status === \"fail\" ? chalk.red(\"✗\") : chalk.yellow(\"○\");\n const name = r.status === \"fail\" ? chalk.red(r.hunt) : r.status === \"skipped\" ? chalk.yellow(r.hunt) : r.hunt;\n const duration = r.status === \"skipped\" ? \"\" : chalk.gray(`(${r.durationMs}ms)`);\n const pad = \" \".repeat(Math.max(1, 40 - r.hunt.length));\n console.log(` ${icon} ${name}${pad}${duration}`);\n }\n\n console.log(` ${\"─\".repeat(lineWidth)}`);\n\n const parts: string[] = [];\n if (passed > 0) parts.push(chalk.green(`${passed} passed`));\n if (failed > 0) parts.push(chalk.red(`${failed} failed`));\n if (skipped > 0) parts.push(chalk.yellow(`${skipped} skipped`));\n parts.push(chalk.gray(`(${totalDurationMs}ms)`));\n\n console.log(` ${parts.join(\" \")}`);\n\n if (flaky.length > 0) {\n console.log(`\\n ${chalk.yellow(\"Flaky hunts\")} (oscillating pass/fail):`);\n for (const entry of flaky) {\n console.log(` ${chalk.yellow(\"~\")} ${entry.hunt} ${chalk.gray(`(score ${entry.score.toFixed(2)})`)}`);\n }\n }\n\n if (clusters.length > 0) {\n console.log(`\\n ${chalk.red(\"Failure clusters\")} (shared root causes):`);\n for (const cluster of clusters) {\n console.log(` ${chalk.red(\"✗\")} ${cluster.cause} ${chalk.gray(`(${cluster.count} hunts: ${cluster.hunts.join(\", \")})`)}`);\n }\n }\n}\n\nexport function writeCiResult(\n ciRunDir: string,\n results: CiHuntResult[],\n startedAt: string,\n totalDurationMs: number,\n flaky: CiFlakyHunt[] = [],\n clusters: CiFailureCluster[] = []\n): string {\n const { passed, failed, skipped } = countCiResults(results);\n\n const ciResult: CiResult = {\n status: resolveCiStatus(results),\n startedAt,\n durationMs: totalDurationMs,\n totalHunts: results.length,\n passed,\n failed,\n skipped,\n hunts: results,\n ...(flaky.length > 0 ? { flaky } : {}),\n ...(clusters.length > 0 ? { clusters } : {})\n };\n\n fs.mkdirSync(ciRunDir, { recursive: true });\n const filePath = path.join(ciRunDir, \"ci-result.json\");\n fs.writeFileSync(filePath, JSON.stringify(ciResult, null, 2) + \"\\n\");\n return filePath;\n}\n","export type ConcurrencyResult<T> =\n | { status: \"fulfilled\"; value: T }\n | { status: \"rejected\"; reason: unknown };\n\nexport async function runWithConcurrency<T>(\n tasks: Array<() => Promise<T>>,\n concurrency: number\n): Promise<Array<ConcurrencyResult<T>>> {\n const normalizedConcurrency =\n Number.isFinite(concurrency) && concurrency > 0\n ? Math.floor(concurrency)\n : 1;\n const results: Array<ConcurrencyResult<T>> = new Array(tasks.length);\n let nextIndex = 0;\n\n async function worker(): Promise<void> {\n while (nextIndex < tasks.length) {\n const index = nextIndex;\n nextIndex += 1;\n try {\n const value = await tasks[index]();\n results[index] = { status: \"fulfilled\", value };\n } catch (reason) {\n results[index] = { status: \"rejected\", reason };\n }\n }\n }\n\n const workers = Array.from(\n { length: Math.min(normalizedConcurrency, tasks.length) },\n () => worker()\n );\n await Promise.all(workers);\n return results;\n}\n","/**\n * The minimal surface `analyzePage` needs: a way to evaluate a DOM-scraping\n * function in the page. Both a live Playwright page and a {@link SessionDriver}\n * satisfy it (the driver's `evaluate` verb), so the analyzer has no direct\n * Playwright dependency — its DOM scraping runs through the driver.\n */\nexport type DomEvaluator = {\n evaluate(pageFunction: () => unknown): Promise<unknown>;\n};\n\nexport type PageElement = {\n tag: string;\n type?: string;\n selectors: Record<string, string>;\n role?: string;\n label?: string;\n placeholder?: string;\n required: boolean;\n formGroup?: number;\n};\n\nexport type PageForm = {\n index: number;\n action?: string;\n method?: string;\n fieldCount: number;\n};\n\nexport type PageLink = {\n text: string;\n href: string;\n selector: string;\n};\n\nexport type AnalysisResult = {\n url: string;\n title: string;\n elements: PageElement[];\n forms: PageForm[];\n links: PageLink[];\n};\n\ntype RawElement = {\n tag: string;\n type?: string;\n testId?: string;\n ariaLabel?: string;\n role?: string;\n id?: string;\n name?: string;\n label?: string;\n placeholder?: string;\n required: boolean;\n formIndex: number;\n text?: string;\n href?: string;\n};\n\ntype RawForm = {\n index: number;\n action?: string;\n method?: string;\n fieldCount: number;\n};\n\ntype RawAnalysis = {\n title: string;\n url: string;\n elements: RawElement[];\n forms: RawForm[];\n};\n\nexport async function analyzePage(page: DomEvaluator): Promise<AnalysisResult> {\n const raw = await page.evaluate(() => {\n const forms = Array.from(document.querySelectorAll(\"form\"));\n const formData = forms.map((form, index) => ({\n index,\n action: form.getAttribute(\"action\") || undefined,\n method: (form.getAttribute(\"method\") || \"GET\").toUpperCase(),\n fieldCount: form.querySelectorAll(\"input, textarea, select\").length\n }));\n\n function getFormIndex(el: Element): number {\n const form = el.closest(\"form\");\n if (!form) return -1;\n return forms.indexOf(form);\n }\n\n function getLabel(el: Element): string | undefined {\n const id = el.getAttribute(\"id\");\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label) return label.textContent?.trim() || undefined;\n }\n const parentLabel = el.closest(\"label\");\n if (parentLabel) return parentLabel.textContent?.trim() || undefined;\n return undefined;\n }\n\n const selectors = \"input, textarea, select, button, [role=button], a\";\n const rawElements = Array.from(document.querySelectorAll(selectors));\n\n const elements = rawElements\n .filter((el) => {\n if (el.tagName.toLowerCase() === \"input\" && el.getAttribute(\"type\") === \"hidden\") {\n return false;\n }\n return true;\n })\n .map((el) => {\n const tag = el.tagName.toLowerCase();\n const type = el.getAttribute(\"type\") || undefined;\n const testId = el.getAttribute(\"data-testid\") || undefined;\n const ariaLabel = el.getAttribute(\"aria-label\") || undefined;\n const role = el.getAttribute(\"role\") || undefined;\n const id = el.getAttribute(\"id\") || undefined;\n const name = el.getAttribute(\"name\") || undefined;\n const label = getLabel(el);\n const placeholder = el.getAttribute(\"placeholder\") || undefined;\n const required = el.hasAttribute(\"required\");\n const formIndex = getFormIndex(el);\n const text = el.textContent?.trim() || undefined;\n const href = el.getAttribute(\"href\") || undefined;\n\n return {\n tag,\n type: type || undefined,\n testId,\n ariaLabel,\n role,\n id,\n name,\n label,\n placeholder,\n required,\n formIndex,\n text: tag === \"a\" || tag === \"button\" || role === \"button\" ? text : undefined,\n href: tag === \"a\" ? href : undefined\n };\n });\n\n return {\n title: document.title,\n url: window.location.href,\n elements,\n forms: formData\n };\n }) as RawAnalysis;\n\n const elements: PageElement[] = raw.elements\n .filter((el) => el.tag !== \"a\")\n .map((el) => {\n const selectors: Record<string, string> = {};\n if (el.testId) selectors.testId = `[data-testid=\"${el.testId}\"]`;\n if (el.ariaLabel) selectors.ariaLabel = el.ariaLabel;\n if (el.label) selectors.label = el.label;\n if (el.id) selectors.css = `#${el.id}`;\n if (el.name) selectors.name = `[name=\"${el.name}\"]`;\n if (el.placeholder) selectors.placeholder = el.placeholder;\n if (el.text) selectors.text = el.text;\n if (el.role) selectors.role = el.role;\n\n return {\n tag: el.tag,\n ...(el.type ? { type: el.type } : {}),\n selectors,\n ...(el.role ? { role: el.role } : {}),\n ...(el.label ? { label: el.label } : {}),\n ...(el.placeholder ? { placeholder: el.placeholder } : {}),\n required: el.required,\n ...(el.formIndex >= 0 ? { formGroup: el.formIndex } : {})\n };\n });\n\n const links: PageLink[] = raw.elements\n .filter((el) => el.tag === \"a\" && el.href)\n .map((el) => {\n let selector: string;\n if (el.testId) {\n selector = `[data-testid=\"${el.testId}\"]`;\n } else if (el.href) {\n selector = `a[href=\"${el.href}\"]`;\n } else {\n selector = `a`;\n }\n return {\n text: el.text || \"\",\n href: el.href!,\n selector\n };\n });\n\n const forms: PageForm[] = raw.forms;\n\n return {\n url: raw.url,\n title: raw.title,\n elements,\n forms,\n links\n };\n}\n","import yaml from \"yaml\";\nimport { launchBrowser, closeBrowser, createPlaywrightDriver } from \"../browser/controller.js\";\nimport { parseBrowserEngine } from \"../browser/engines.js\";\nimport type { AnalysisResult } from \"../analyzer/index.js\";\nimport { analyzePage } from \"../analyzer/index.js\";\nimport { buildGenerationPrompt, extractYamlFromResponse } from \"./prompt.js\";\nimport { generateWithAi, resolveAiConfig } from \"./ai.js\";\nimport type { AiConfig } from \"./ai.js\";\nimport { resolveViewport } from \"../config/loader.js\";\nimport { huntSchema } from \"../config/schema.js\";\n\nexport type GenerateOptions = {\n url?: string;\n analysis?: AnalysisResult;\n intent: string;\n browser?: string;\n viewport?: string;\n aiConfig?: AiConfig;\n};\n\nfunction parseViewportFlag(value: string): string | { width: number; height: number } {\n const match = /^(\\d+)x(\\d+)$/i.exec(value);\n if (match) {\n return { width: Number(match[1]), height: Number(match[2]) };\n }\n return value;\n}\n\nexport async function generateHunt(options: GenerateOptions): Promise<string> {\n let analysis = options.analysis;\n\n if (!analysis && options.url) {\n const engine = parseBrowserEngine(options.browser);\n const viewport = options.viewport\n ? resolveViewport(parseViewportFlag(options.viewport))\n : resolveViewport(undefined);\n const session = await launchBrowser({\n headless: true,\n slowMo: 0,\n timeout: 30000,\n trace: false,\n recordHar: false,\n runDir: process.cwd(),\n engine,\n viewport\n });\n const driver = createPlaywrightDriver(session.page);\n try {\n await driver.goto(options.url, { waitUntil: \"networkidle\" });\n analysis = await analyzePage(driver);\n } finally {\n await closeBrowser(session);\n }\n }\n\n if (!analysis) {\n throw new Error(\"Either --url or piped analysis JSON is required\");\n }\n\n const config = options.aiConfig ?? resolveAiConfig();\n const prompt = buildGenerationPrompt(analysis, options.intent);\n const response = await generateWithAi(prompt, config);\n const yamlStr = extractYamlFromResponse(response);\n\n // Validate generated YAML\n const parsed = yaml.parse(yamlStr);\n huntSchema.parse(parsed);\n\n return yamlStr;\n}\n","import { SUPPORTED_BROWSER_ENGINES, type BrowserEngine } from \"../types/index.js\";\n\nexport function formatSupportedBrowserEngines(): string {\n return SUPPORTED_BROWSER_ENGINES.join(\", \");\n}\n\nexport function parseBrowserEngine(value: string | undefined, fallback: BrowserEngine = \"chromium\"): BrowserEngine {\n if (value === undefined || value.length === 0) {\n return fallback;\n }\n if ((SUPPORTED_BROWSER_ENGINES as readonly string[]).includes(value)) {\n return value as BrowserEngine;\n }\n throw new Error(`Unsupported browser engine \"${value}\". Use ${formatSupportedBrowserEngines()}.`);\n}\n","import type { AnalysisResult } from \"../analyzer/index.js\";\n\nconst STEP_REFERENCE = `\n## Prowl Step Types\n\n### Navigation & Waiting\n- navigate: \"/path\" — navigate to URL (relative to target)\n- wait: \"Text\" — wait for text to appear\n- wait: { for: \"Text\", timeout: 5000 } — with timeout\n- waitForSelector: { selector: \"#el\", timeout: 5000 }\n- waitForUrl: { value: \"/path\", timeout: 5000 }\n- waitForNetworkIdle: { timeout: 5000 }\n\n### Interaction\n- click: \"Button Text\" — click by text (tries role=button first)\n- click: { selector: \"[data-testid=btn]\" } — click by selector\n- fill: { \"Label\": \"value\" } — fill by label/placeholder\n- fill: { selector: \"#input\", value: \"text\" } — fill by selector\n- type: \"text\" — type into focused element\n- press: { selector: \"#input\", key: \"Enter\" }\n- hover: { selector: \"#menu\" }\n- selectOption: { selector: \"select\", value: \"option\" }\n- select: { \"Label\": \"value\" } — select by label\n- setInputFiles: { selector: \"#file\", files: \"path.png\" }\n- onDialog: { action: \"accept\" } — handle browser dialogs\n\n### Assertions\n- assert: { visible: \"Text\" }\n- assert: { notVisible: \"Error\" }\n- assert: { urlIncludes: \"/dashboard\" }\n- assert: { urlEquals: \"https://...\" }\n\n### Scrolling & Screenshots\n- scroll: { direction: \"down\", amount: 500 }\n- scrollTo: { selector: \"#section\" }\n- screenshot: { name: \"step-name\" }\n\n### Script Execution\n- evalScript: \"document.title\" — evaluate JS expression\n- evalScript: { expression: \"expr\", as: \"VAR\" } — capture to variable\n- runScript: { file: \"scripts/setup.js\" }\n\n### Visual Regression\n- assertScreenshot: { name: \"baseline-name\", threshold: 0.1 }\n\n### Control Flow\n- if: { visible: \".banner\", then: [steps...] }\n- repeat: { times: 3, steps: [steps...] }\n- repeat: { while: { visible: \".more\" }, maxIterations: 10, steps: [steps...] }\n- runHunt: \"other-hunt\" — run another hunt file\n- mockRoute: { url: \"**/api/data\", response: { status: 200, body: \"{}\" } }\n- unmockRoute: { url: \"**/api/data\" }\n`.trim();\n\nexport function buildGenerationPrompt(analysis: AnalysisResult, intent: string): string {\n return `You are a QA test generator for Prowl. Generate a YAML hunt file that tests the described intent using the page analysis data below.\n\n${STEP_REFERENCE}\n\n## Page Analysis\n\\`\\`\\`json\n${JSON.stringify(analysis, null, 2)}\n\\`\\`\\`\n\n## Test Intent\n${intent}\n\n## Instructions\n1. Output ONLY a valid Prowl YAML hunt between \\`\\`\\`yaml fences\n2. Use shorthand syntax when possible (click: \"Text\", fill: { \"Label\": \"value\" })\n3. Prefer stable selectors: data-testid > aria-label > text > CSS selectors\n4. Include assertions to verify expected outcomes\n5. Add a descriptive name and description\n6. Keep steps focused and minimal — test exactly what the intent describes\n\n\\`\\`\\`yaml\n`;\n}\n\nexport function extractYamlFromResponse(response: string): string {\n const fenceMatch = response.match(/```ya?ml\\n?([\\s\\S]*?)```/);\n if (fenceMatch) {\n return fenceMatch[1].trim();\n }\n return response.trim();\n}\n","export type AiProvider = \"anthropic\" | \"openai\";\n\nexport type AiConfig = {\n provider: AiProvider;\n model: string;\n apiKey: string;\n};\n\nexport function resolveAiConfig(): AiConfig {\n const provider = (process.env.PROWL_AI_PROVIDER ?? \"anthropic\") as AiProvider;\n if (provider !== \"anthropic\" && provider !== \"openai\") {\n throw new Error(`Unsupported AI provider: ${provider}. Use \"anthropic\" or \"openai\".`);\n }\n\n const apiKey = process.env.PROWL_AI_KEY;\n if (!apiKey) {\n throw new Error(\n \"PROWL_AI_KEY environment variable is required. Set it to your Anthropic or OpenAI API key.\"\n );\n }\n\n const defaultModel = provider === \"anthropic\"\n ? \"claude-sonnet-4-5-20250929\"\n : \"gpt-4o\";\n const model = process.env.PROWL_AI_MODEL ?? defaultModel;\n\n return { provider, model, apiKey };\n}\n\nexport async function generateWithAi(prompt: string, config: AiConfig): Promise<string> {\n if (config.provider === \"anthropic\") {\n return generateWithAnthropic(prompt, config);\n }\n return generateWithOpenAi(prompt, config);\n}\n\nasync function generateWithAnthropic(prompt: string, config: AiConfig): Promise<string> {\n const response = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": config.apiKey,\n \"anthropic-version\": \"2023-06-01\"\n },\n body: JSON.stringify({\n model: config.model,\n max_tokens: 4096,\n messages: [\n { role: \"user\", content: prompt }\n ]\n })\n });\n\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Anthropic API error (${response.status}): ${body}`);\n }\n\n const data = await response.json() as {\n content: Array<{ type: string; text?: string }>;\n };\n\n const textBlock = data.content.find((c) => c.type === \"text\");\n if (!textBlock?.text) {\n throw new Error(\"Anthropic API returned no text content\");\n }\n\n return textBlock.text;\n}\n\nasync function generateWithOpenAi(prompt: string, config: AiConfig): Promise<string> {\n const response = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${config.apiKey}`\n },\n body: JSON.stringify({\n model: config.model,\n messages: [\n { role: \"user\", content: prompt }\n ],\n max_tokens: 4096\n })\n });\n\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`OpenAI API error (${response.status}): ${body}`);\n }\n\n const data = await response.json() as {\n choices: Array<{ message: { content: string } }>;\n };\n\n if (!data.choices?.[0]?.message?.content) {\n throw new Error(\"OpenAI API returned no content\");\n }\n\n return data.choices[0].message.content;\n}\n"],"mappings":"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","names":["num","stepPath","valueResult","fs","path","path","fs","fs","path","fs","path","fs","path","fs","path","path","fs","fs","path","fs","path","fs","path","path","fs","fs","path","fs","path","path","fs","path","path","forms","elements","parseViewportFlag"]}