prowl-tools 0.1.3

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/runner/healing.ts","../src/runner/history.ts","../src/runner/index.ts","../src/browser/controller.ts","../src/runner/steps.ts","../src/browser/actions.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/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","import type { Locator, Page } from \"playwright\";\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 page: Pick<Page, \"locator\">,\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: Pick<Locator, \"count\"> = page.locator(candidate.selector);\n count = await locator.count();\n } catch {\n continue; // ignore candidates Playwright can't 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, RunResult, Step, StepResult, TraceCorrelation } from \"../types/index.js\";\nimport { loadConfig, loadHunt, ensureAllowedDomain, resolveViewport } from \"../config/loader.js\";\nimport { interpolateHunt } from \"../config/interpolate.js\";\nimport { launchBrowser, closeBrowser } from \"../browser/controller.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};\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 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 session.page.on(\"response\", (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 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(session.page, 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 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\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","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { chromium, firefox, webkit, type Browser, type BrowserContext, type Page } from \"playwright\";\nimport type { BrowserChannel, BrowserEngine, Viewport } from \"../types/index.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 engine = ENGINES[options.engine ?? \"chromium\"];\n const browser = await engine.launch({\n headless: options.headless,\n slowMo: options.slowMo,\n channel: options.channel\n });\n\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}\n\nexport async function closeBrowser(session: BrowserSession): Promise<void> {\n if (session.tracePath) {\n await session.context.tracing.stop({ path: session.tracePath });\n }\n await session.context.close();\n await session.browser.close();\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Download, Page } from \"playwright\";\nimport {\n clickElement,\n fillElement,\n pressKey,\n selectOption,\n setupDialogHandler,\n setInputFiles\n} from \"../browser/actions.js\";\nimport type { Step, StepResult } from \"../types/index.js\";\nimport { loadHunt } from \"../config/loader.js\";\nimport { interpolateHunt } from \"../config/interpolate.js\";\nimport { healSelector } from \"./healing.js\";\n\nexport type StepCallback = (result: StepResult, step: Step, index: number) => void;\n\nexport type StepExecutionContext = {\n page: Page;\n steps: Step[];\n targetUrl: string;\n runDir: string;\n screenshotsMode: \"on-failure\" | \"all\";\n forbiddenSelectors: string[];\n allowedDomains: 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<Download>;\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\nconst ALWAYS_ALLOWED_PROTOCOLS = [\"about:\", \"data:\"];\n\nfunction unwrapTextSelector(value: string): string | null {\n const trimmed = value.trim();\n if (trimmed.startsWith('text=\"') && trimmed.endsWith('\"')) {\n return trimmed.slice(6, -1);\n }\n if (trimmed.startsWith(\"text='\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(6, -1);\n }\n if (trimmed.startsWith(\"text=\")) {\n return trimmed.slice(5);\n }\n return null;\n}\n\n// Substring match: if both the selector and forbidden pattern are text= selectors,\n// the selector's text is checked for whether it *contains* the forbidden text.\n// For example, forbidden 'text=\"Delete\"' would match selector 'text=\"Delete All\"'.\nfunction matchesForbiddenPattern(selector: string, forbidden: string): boolean {\n const selectorText = unwrapTextSelector(selector);\n if (selectorText === null) {\n return false;\n }\n\n const forbiddenText = unwrapTextSelector(forbidden);\n if (forbiddenText !== null) {\n return selectorText.includes(forbiddenText);\n }\n\n return selectorText.includes(forbidden);\n}\n\n// Uses substring matching: a selector is forbidden if it contains any forbidden\n// pattern as a substring (e.g., forbidden \"[data-danger]\" matches \"[data-danger].active\"),\n// or if the text-based pattern match above succeeds.\nfunction isForbiddenSelector(selector: string, forbiddenSelectors: string[]): boolean {\n return forbiddenSelectors.some(\n (forbidden) => selector.includes(forbidden) || matchesForbiddenPattern(selector, forbidden)\n );\n}\n\nfunction assertAllowedSelector(selector: string, forbiddenSelectors: string[]): void {\n if (isForbiddenSelector(selector, forbiddenSelectors)) {\n throw new Error(`Forbidden selector: ${selector}`);\n }\n}\n\n/**\n * Resolve the selector an explicit-selector action should operate on. Asserts it\n * is allowed, then — when `guardrails.selfHealing` is on and the selector matches\n * nothing — attempts to heal to an equivalent selector. A healed selector is also\n * re-checked against the forbidden list. Returns the selector to use plus, when\n * healing occurred, the original selector for reporting.\n */\nasync function resolveActionSelector(\n context: StepExecutionContext,\n selector: string\n): Promise<{ selector: string; healedFrom?: string }> {\n assertAllowedSelector(selector, context.forbiddenSelectors);\n\n if (!context.selfHealing) {\n return { selector };\n }\n\n let matched = false;\n try {\n matched = (await context.page.locator(selector).count()) > 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(context.page, selector, { enabled: true });\n if (!healed) {\n return { selector };\n }\n\n assertAllowedSelector(healed.selector, context.forbiddenSelectors);\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\nfunction assertWithinMaxSteps(stepCount: number, maxSteps: 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\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 ensureAllowedUrl(urlValue: string, allowedDomains: string[]): void {\n for (const protocol of ALWAYS_ALLOWED_PROTOCOLS) {\n if (urlValue.startsWith(protocol)) {\n return;\n }\n }\n const url = new URL(urlValue);\n if (!allowedDomains.includes(url.hostname)) {\n throw new Error(`Navigation to disallowed domain: ${url.hostname}`);\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 page: Page,\n text: string,\n forbiddenSelectors: string[]\n): Promise<string> {\n const roleSelector = `role=button[name=\"${escapeForAttribute(text)}\"]`;\n assertAllowedSelector(roleSelector, forbiddenSelectors);\n const button = page.getByRole(\"button\", { name: text });\n if (await button.count()) {\n await button.first().click();\n return roleSelector;\n }\n\n const selector = exactTextSelector(text);\n assertAllowedSelector(selector, forbiddenSelectors);\n await page.locator(selector).first().click();\n return selector;\n}\n\nasync function fillByLabelOrPlaceholder(\n page: Page,\n label: string,\n value: string,\n forbiddenSelectors: string[]\n): Promise<string> {\n const labelSelector = `label=\"${escapeForAttribute(label)}\"`;\n assertAllowedSelector(labelSelector, forbiddenSelectors);\n const byLabel = page.getByLabel(label, { exact: true });\n if (await byLabel.count()) {\n await byLabel.first().fill(value);\n return labelSelector;\n }\n\n const placeholder = `input[placeholder=\"${escapeForAttribute(label)}\"], textarea[placeholder=\"${escapeForAttribute(label)}\"]`;\n assertAllowedSelector(placeholder, forbiddenSelectors);\n const byPlaceholder = page.locator(placeholder);\n if (await byPlaceholder.count()) {\n await byPlaceholder.first().fill(value);\n return placeholder;\n }\n\n throw new Error(`Could not resolve fill shorthand for \"${label}\"`);\n}\n\nasync function selectByLabelOrFallback(\n page: Page,\n label: string,\n value: string,\n forbiddenSelectors: string[]\n): Promise<string> {\n const labelSelector = `label=\"${escapeForAttribute(label)}\"`;\n assertAllowedSelector(labelSelector, forbiddenSelectors);\n const byLabel = page.getByLabel(label, { exact: true });\n if (await byLabel.count()) {\n await byLabel.first().selectOption(value);\n return labelSelector;\n }\n\n const ariaSelector = `select[aria-label=\"${escapeForAttribute(label)}\"]`;\n assertAllowedSelector(ariaSelector, forbiddenSelectors);\n const byAria = page.locator(ariaSelector);\n if (await byAria.count()) {\n await byAria.first().selectOption(value);\n return ariaSelector;\n }\n\n const placeholderSelector = `select[placeholder=\"${escapeForAttribute(label)}\"]`;\n assertAllowedSelector(placeholderSelector, forbiddenSelectors);\n const byPlaceholder = page.locator(placeholderSelector);\n if (await byPlaceholder.count()) {\n await byPlaceholder.first().selectOption(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 page: Page,\n assertion: {\n visible?: string;\n notVisible?: string;\n urlIncludes?: string;\n urlEquals?: string;\n },\n forbiddenSelectors: string[]\n): Promise<string> {\n if (assertion.visible !== undefined) {\n const selector = toVisibilitySelector(assertion.visible);\n assertAllowedSelector(selector, forbiddenSelectors);\n const count = await page.locator(selector).count();\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 assertAllowedSelector(selector, forbiddenSelectors);\n const count = await page.locator(selector).count();\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 = page.url();\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 = page.url();\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(page: Page, timeout: number): Promise<Download> {\n const downloadPromise = page.waitForEvent(\"download\", { 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(page: Page, filePath: string): Promise<void> {\n try {\n await page.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\nexport async function executeSteps(context: StepExecutionContext): Promise<StepExecutionResult> {\n const screenshotsDir = path.join(context.runDir, \"screenshots\");\n fs.mkdirSync(screenshotsDir, { recursive: true });\n const currentHuntName = context.huntStack?.[context.huntStack.length - 1];\n assertWithinMaxSteps(context.steps.length, context.maxSteps, 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(context.page, fullPath);\n const relative = path.join(\"screenshots\", fileName);\n screenshots.push(relative);\n return relative;\n };\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 context.page,\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 if (\"navigate\" in step) {\n const destination = resolveNavigationTarget(context.targetUrl, step.navigate);\n ensureAllowedUrl(destination, context.allowedDomains);\n await context.page.goto(destination);\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = { type: \"navigate\", status: \"pass\", durationMs: Date.now() - stepStart };\n } else if (\"click\" in step) {\n let selector: string;\n let healedFrom: string | undefined;\n if (typeof step.click === \"string\") {\n selector = await clickByTextWithFallback(\n context.page,\n step.click,\n context.forbiddenSelectors\n );\n } else {\n const resolved = await resolveActionSelector(context, step.click.selector);\n await clickElement(context.page, resolved.selector);\n selector = resolved.selector;\n healedFrom = resolved.healedFrom;\n }\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"click\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector,\n ...(healedFrom ? { healedFrom } : {})\n };\n } else if (\"fill\" in step) {\n let selector: string;\n let value: string;\n let healedFrom: string | undefined;\n if (isExplicitFillStep(step.fill)) {\n const resolved = await resolveActionSelector(context, step.fill.selector);\n await fillElement(context.page, resolved.selector, step.fill.value);\n selector = resolved.selector;\n healedFrom = resolved.healedFrom;\n value = step.fill.value;\n } else {\n const [label, shorthandValue] = getSinglePair(step.fill, \"fill\");\n selector = await fillByLabelOrPlaceholder(\n context.page,\n label,\n shorthandValue,\n context.forbiddenSelectors\n );\n value = shorthandValue;\n }\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"fill\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector,\n value: context.redactedFillSteps.has(currentStepPath) ? \"[REDACTED]\" : value,\n ...(healedFrom ? { healedFrom } : {})\n };\n } else if (\"type\" in step) {\n assertAllowedSelector(\":focus\", context.forbiddenSelectors);\n await fillElement(context.page, \":focus\", step.type);\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"type\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: \":focus\",\n value: context.redactedFillSteps.has(currentStepPath) ? \"[REDACTED]\" : step.type\n };\n } else if (\"selectOption\" in step) {\n const resolved = await resolveActionSelector(context, step.selectOption.selector);\n await selectOption(context.page, resolved.selector, step.selectOption.value);\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"selectOption\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: resolved.selector,\n value: step.selectOption.value,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n };\n } else if (\"select\" in step) {\n const [label, value] = getSinglePair(step.select, \"select\");\n const selector = await selectByLabelOrFallback(\n context.page,\n label,\n value,\n context.forbiddenSelectors\n );\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"select\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector,\n value\n };\n } else if (\"onDialog\" in step) {\n setupDialogHandler(context.page, step.onDialog.action);\n stepResult = {\n type: \"onDialog\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: step.onDialog.action\n };\n } else if (\"setInputFiles\" in step) {\n const resolvedInput = await resolveActionSelector(context, step.setInputFiles.selector);\n const rawFiles = step.setInputFiles.files;\n const resolveFile = (f: string) =>\n path.isAbsolute(f) ? f : path.join(context.configDir, f);\n const resolvedFiles = Array.isArray(rawFiles)\n ? rawFiles.map(resolveFile)\n : resolveFile(rawFiles);\n await setInputFiles(context.page, resolvedInput.selector, resolvedFiles);\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n const filesLabel = Array.isArray(rawFiles) ? rawFiles.join(\", \") : rawFiles;\n stepResult = {\n type: \"setInputFiles\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: resolvedInput.selector,\n ...(resolvedInput.healedFrom ? { healedFrom: resolvedInput.healedFrom } : {}),\n value: filesLabel\n };\n } else if (\"runHunt\" in step) {\n const huntName = typeof step.runHunt === \"string\" ? step.runHunt : step.runHunt.name;\n const overrideVars = typeof step.runHunt === \"string\" ? undefined : step.runHunt.vars;\n const stack = context.huntStack ?? [];\n if (stack.includes(huntName)) {\n throw new Error(`Circular hunt dependency: ${[...stack, huntName].join(\" → \")}`);\n }\n const subHunt = loadHunt(huntName, context.configDir);\n if (overrideVars) {\n subHunt.vars = { ...subHunt.vars, ...overrideVars };\n }\n const {\n hunt: interpolatedSubHunt,\n redactedFillSteps: subRedacted,\n randomVars\n } = interpolateHunt(\n subHunt,\n process.env,\n context.randomVars\n );\n assertWithinMaxSteps(interpolatedSubHunt.steps.length, context.maxSteps, huntName);\n const subResult = await executeNestedSteps(context, {\n steps: interpolatedSubHunt.steps,\n redactedFillSteps: subRedacted,\n randomVars,\n stepPathPrefix: undefined,\n huntStack: [...stack, huntName],\n onStep: context.onStep\n });\n for (const sr of subResult.results) {\n results.push({ ...sr, type: `${huntName} > ${sr.type}` });\n }\n screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return {\n results,\n screenshots,\n failed: true,\n error: `Sub-hunt \"${huntName}\" failed: ${subResult.error}`\n };\n }\n stepResult = {\n type: \"runHunt\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: huntName\n };\n } else if (\"press\" in step) {\n const resolved = await resolveActionSelector(context, step.press.selector);\n await pressKey(context.page, resolved.selector, step.press.key);\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"press\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: resolved.selector,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n };\n } else if (\"assert\" in step) {\n const value = await runInlineAssert(context.page, step.assert, context.forbiddenSelectors);\n stepResult = {\n type: \"assert\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value\n };\n } else if (\"wait\" in step) {\n const text = typeof step.wait === \"string\" ? step.wait : step.wait.for;\n const timeout = typeof step.wait === \"string\" ? undefined : step.wait.timeout;\n const selector = `text=${escapeForText(text)}`;\n assertAllowedSelector(selector, context.forbiddenSelectors);\n await context.page.waitForSelector(selector, { timeout });\n stepResult = {\n type: \"wait\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector\n };\n } else if (\"waitForSelector\" in step) {\n assertAllowedSelector(step.waitForSelector.selector, context.forbiddenSelectors);\n await context.page.waitForSelector(step.waitForSelector.selector, {\n timeout: step.waitForSelector.timeout\n });\n stepResult = {\n type: \"waitForSelector\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: step.waitForSelector.selector\n };\n } else if (\"waitForUrl\" in step) {\n await context.page.waitForURL(\n (url) => url.toString().includes(step.waitForUrl.value),\n { timeout: step.waitForUrl.timeout }\n );\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"waitForUrl\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: step.waitForUrl.value\n };\n } else if (\"waitForNetworkIdle\" in step) {\n await context.page.waitForLoadState(\"networkidle\", {\n timeout: step.waitForNetworkIdle.timeout\n });\n stepResult = {\n type: \"waitForNetworkIdle\",\n status: \"pass\",\n durationMs: Date.now() - stepStart\n };\n } else if (\"hover\" in step) {\n const resolved = await resolveActionSelector(context, step.hover.selector);\n await context.page.locator(resolved.selector).hover();\n ensureAllowedUrl(context.page.url(), context.allowedDomains);\n stepResult = {\n type: \"hover\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: resolved.selector,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n };\n } else if (\"scroll\" in step) {\n const amount = 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[step.scroll.direction];\n await context.page.evaluate(([sx, sy]) => window.scrollBy(sx, sy), [x, y] as [number, number]);\n stepResult = {\n type: \"scroll\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: `${step.scroll.direction} ${amount}px`\n };\n } else if (\"scrollTo\" in step) {\n const resolved = await resolveActionSelector(context, step.scrollTo.selector);\n await context.page.locator(resolved.selector).scrollIntoViewIfNeeded();\n stepResult = {\n type: \"scrollTo\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: resolved.selector,\n ...(resolved.healedFrom ? { healedFrom: resolved.healedFrom } : {})\n };\n } else if (\"screenshot\" in step) {\n const name = step.screenshot.name ?? `manual_step_${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 addScreenshot(fileName);\n stepResult = {\n type: \"screenshot\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n screenshot: relative\n };\n } else if (\"if\" in step) {\n const condition = step.if;\n const selector = condition.visible ?? condition.notVisible!;\n assertAllowedSelector(selector, context.forbiddenSelectors);\n const count = await context.page.locator(selector).count();\n const conditionMet = condition.visible !== undefined ? count > 0 : count === 0;\n\n if (conditionMet) {\n const subResult = await executeNestedSteps(context, {\n steps: condition.then,\n stepPathPrefix: `${currentStepPath}.if.then`\n });\n for (const sr of subResult.results) {\n results.push({ ...sr, type: `if > ${sr.type}` });\n }\n screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return {\n results,\n screenshots,\n failed: true,\n error: subResult.error\n };\n }\n stepResult = {\n type: \"if\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: `condition met, executed ${condition.then.length} steps`\n };\n } else {\n if (condition.else && condition.else.length > 0) {\n const subResult = await executeNestedSteps(context, {\n steps: condition.else,\n stepPathPrefix: `${currentStepPath}.if.else`\n });\n for (const sr of subResult.results) {\n results.push({ ...sr, type: `if > ${sr.type}` });\n }\n screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return {\n results,\n screenshots,\n failed: true,\n error: subResult.error\n };\n }\n stepResult = {\n type: \"if\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: `condition not met, executed ${condition.else.length} else steps`\n };\n } else {\n stepResult = {\n type: \"if\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: \"condition not met, skipped\"\n };\n }\n }\n } else if (\"repeat\" in step) {\n const repeat = step.repeat;\n let totalSubSteps = 0;\n\n if (repeat.times !== undefined) {\n const totalPlanned = repeat.times * repeat.steps.length;\n if (totalPlanned + totalSubSteps > context.maxSteps) {\n throw new Error(`Repeat exceeded maxSteps guardrail (${context.maxSteps})`);\n }\n for (let i = 0; i < repeat.times; i++) {\n totalSubSteps += repeat.steps.length;\n const subResult = await executeNestedSteps(context, {\n steps: repeat.steps,\n stepPathPrefix: `${currentStepPath}.repeat.steps`\n });\n for (const sr of subResult.results) {\n results.push({ ...sr, type: `repeat[${i}] > ${sr.type}` });\n }\n screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return {\n results,\n screenshots,\n failed: true,\n error: subResult.error\n };\n }\n }\n } else if (repeat.while !== undefined) {\n const maxIter = repeat.maxIterations!;\n const whileSelector = repeat.while.visible ?? repeat.while.notVisible!;\n assertAllowedSelector(whileSelector, context.forbiddenSelectors);\n for (let i = 0; i < maxIter; i++) {\n const whileCount = await context.page.locator(whileSelector).count();\n const shouldContinue = repeat.while.visible !== undefined ? whileCount > 0 : whileCount === 0;\n if (!shouldContinue) break;\n\n totalSubSteps += repeat.steps.length;\n if (totalSubSteps > context.maxSteps) {\n throw new Error(`Repeat exceeded maxSteps guardrail (${context.maxSteps})`);\n }\n const subResult = await executeNestedSteps(context, {\n steps: repeat.steps,\n stepPathPrefix: `${currentStepPath}.repeat.steps`\n });\n for (const sr of subResult.results) {\n results.push({ ...sr, type: `repeat[${i}] > ${sr.type}` });\n }\n screenshots.push(...subResult.screenshots);\n if (subResult.failed) {\n return {\n results,\n screenshots,\n failed: true,\n error: subResult.error\n };\n }\n }\n }\n\n stepResult = {\n type: \"repeat\",\n status: \"pass\",\n durationMs: Date.now() - stepStart\n };\n } else if (\"mockRoute\" in step) {\n const mock = step.mockRoute;\n const mocks = context.activeMocks ?? new Map<string, () => Promise<void>>();\n 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(context.configDir, responseFile);\n const resolvedConfigDir = path.resolve(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 context.page.route(mock.url, (route) => {\n route.fulfill({\n status,\n contentType,\n body: responseBody\n });\n });\n\n mocks.set(mock.url, async () => {\n await context.page.unroute(mock.url);\n });\n\n stepResult = {\n type: \"mockRoute\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: mock.url\n };\n } else if (\"unmockRoute\" in step) {\n const url = typeof step.unmockRoute === \"string\" ? step.unmockRoute : step.unmockRoute.url;\n const mocks = 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 stepResult = {\n type: \"unmockRoute\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: url\n };\n } else if (\"evalScript\" in step) {\n const expression = typeof step.evalScript === \"string\"\n ? step.evalScript\n : step.evalScript.expression;\n const result = await context.page.evaluate(expression);\n const resultStr = String(result);\n if (typeof step.evalScript !== \"string\" && step.evalScript.as) {\n runtimeVars.set(step.evalScript.as, resultStr);\n }\n stepResult = {\n type: \"evalScript\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: resultStr.length > 200 ? resultStr.slice(0, 200) + \"\\u2026\" : resultStr\n };\n } else if (\"runScript\" in step) {\n const filePath = path.isAbsolute(step.runScript.file)\n ? step.runScript.file\n : path.join(context.configDir, step.runScript.file);\n const fileContents = fs.readFileSync(filePath, \"utf-8\");\n await context.page.evaluate(fileContents);\n stepResult = {\n type: \"runScript\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: step.runScript.file\n };\n } else if (\"assertScreenshot\" in step) {\n const { compareScreenshots, ensureBaselineDir } = await import(\"./visual.js\");\n const name = step.assertScreenshot.name;\n const threshold = step.assertScreenshot.threshold ?? 0.1;\n const baselineDir = ensureBaselineDir(context.configDir);\n const baselinePath = path.join(baselineDir, `${name}.png`);\n const currentScreenshotPath = path.join(context.runDir, \"screenshots\", `${name}-current.png`);\n fs.mkdirSync(path.dirname(currentScreenshotPath), { recursive: true });\n await context.page.screenshot({ path: currentScreenshotPath, fullPage: true });\n screenshots.push(path.join(\"screenshots\", `${name}-current.png`));\n\n if (!fs.existsSync(baselinePath)) {\n fs.copyFileSync(currentScreenshotPath, baselinePath);\n stepResult = {\n type: \"assertScreenshot\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: \"baseline created\"\n };\n } else {\n const diffPath = path.join(context.runDir, \"screenshots\", `${name}-diff.png`);\n const comparison = await compareScreenshots(baselinePath, currentScreenshotPath, diffPath, threshold);\n if (comparison.match) {\n stepResult = {\n type: \"assertScreenshot\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: `diff: ${(comparison.diffPercentage * 100).toFixed(2)}%`\n };\n } else {\n 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 } else if (\"copyText\" in step) {\n assertAllowedSelector(step.copyText.selector, context.forbiddenSelectors);\n const text = await context.page.locator(step.copyText.selector).textContent();\n if (text === null) {\n throw new Error(`No text content found for selector: ${step.copyText.selector}`);\n }\n runtimeVars.set(step.copyText.as, text);\n stepResult = {\n type: \"copyText\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n selector: step.copyText.selector,\n value: \"[REDACTED]\"\n };\n } else if (\"waitForDownload\" in step) {\n const opts = step.waitForDownload;\n const downloadPromise = context.pendingDownload ?? armDownloadListener(\n context.page,\n opts?.timeout ?? 30000\n );\n 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(context.runDir, suggestedFilename);\n await download.saveAs(savePath);\n stepResult = {\n type: \"waitForDownload\",\n status: \"pass\",\n durationMs: Date.now() - stepStart,\n value: suggestedFilename\n };\n }\n\n if (!stepResult) {\n throw new Error(\"Unknown step type\");\n }\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: Page, 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","import type { Page } from \"playwright\";\n\nexport async function clickElement(page: Page, selector: string): Promise<void> {\n await page.locator(selector).click();\n}\n\nexport async function fillElement(page: Page, selector: string, value: string): Promise<void> {\n await page.locator(selector).fill(value);\n}\n\nexport async function pressKey(page: Page, selector: string, key: string): Promise<void> {\n await page.locator(selector).press(key);\n}\n\nexport async function selectOption(page: Page, selector: string, value: string): Promise<void> {\n await page.locator(selector).selectOption(value);\n}\n\nexport function setupDialogHandler(page: Page, action: \"accept\" | \"dismiss\"): void {\n page.once(\"dialog\", async (dialog) => {\n if (action === \"accept\") {\n await dialog.accept();\n } else {\n await dialog.dismiss();\n }\n });\n}\n\nexport async function setInputFiles(page: Page, selector: string, files: string | string[]): Promise<void> {\n await page.locator(selector).setInputFiles(files);\n}\n","import type { Page } from \"playwright\";\nimport type { Assertion, AssertionResult, Config } from \"../types/index.js\";\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: Page;\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 { Response } from \"playwright\";\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: Pick<Response, \"url\" | \"status\" | \"headers\">,\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","import type { Page } from \"playwright\";\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: Page): 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 { chromium } from \"playwright\";\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 { 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\nexport async function generateHunt(options: GenerateOptions): Promise<string> {\n let analysis = options.analysis;\n\n if (!analysis && options.url) {\n const browser = await chromium.launch({ headless: true });\n const context = await browser.newContext();\n const page = await context.newPage();\n try {\n await page.goto(options.url, { waitUntil: \"networkidle\" });\n analysis = await analyzePage(page);\n } finally {\n await context.close();\n await browser.close();\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 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":["stepPath","valueResult","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","chromium","chromium"]}