/** * Delta-debugging for AI-captured reproduction traces. * * The AI driver typically wanders before stumbling into the bug. A * 15-step trace might have a 3-step minimal reproducer hiding inside. * `minimizeRecipeTrace` greedily removes one step at a time and replays the * remainder; whenever the goal still fires, the shorter sequence * becomes the new working trace. * * Algorithm: 1-minimal delta debugging. * - Worst case: O(N^2) replays for an N-step trace * - Always converges (length is strictly monotonically decreasing) * - Produces a "1-minimal" sequence: removing ANY step would fail * reproduction. Not necessarily globally minimal — pairs of * mutually-required steps survive — but cheap and effective for * typical N ≤ 20. * * The replay loop uses the caller's `setupPage` factory exactly the * same way `verifyAndPromote` does. We do not own browser lifecycle — * that's the caller's concern. */ import type { Page } from "playwright"; import type { ActionTrace, Goal, GoalContext, RecipeStep } from "./types.js"; export interface MinimizeRecipeOptions { /** Trace whose `steps` we want to shrink. Must be `successful: true`. */ trace: ActionTrace; /** Same Goal that the trace satisfied. Polled after each replay. */ goal: Goal; /** * Fresh-page factory. Each replay needs a clean context so prior * steps' side effects don't pollute the new run. The factory * returns a page already navigated to the trace's start URL. */ setupPage: () => Promise<{ page: Page; cleanup: () => Promise; }>; /** Hard cap on replays. Default: `steps.length ** 2`. */ maxReplays?: number; /** * Caller-supplied success check. Defaults to `goal.successCheck`, * but tests can override to skip the page hit. The default needs a * real `Page` (because Goals can read the DOM); test-only overrides * can synthesise their own. */ successCheck?: (ctx: GoalContext) => Promise; verbose?: boolean; } export interface MinimizeRecipeResult { /** Resulting 1-minimal step sequence. */ steps: RecipeStep[]; originalLength: number; minimizedLength: number; replays: number; /** True when at least one step was removed. */ shrank: boolean; /** * Why we stopped: "converged" when no further reduction is * possible; "budget" when `maxReplays` was reached first. */ reason: "converged" | "budget"; } export declare function minimizeRecipeTrace(opts: MinimizeRecipeOptions): Promise; //# sourceMappingURL=minimize.d.ts.map