import type { Driver } from "../drivers/types.js"; import type { RecipeStore } from "./store.js"; import type { ActionRecipe } from "./types.js"; /** * Aggregated per-run telemetry for one recipe. "Per-run" means * since this driver instance was created — closed over a closure * that the recipeDriver maintains. Distinct from `ActionRecipe.stats` * (lifetime across all runs). */ export interface RecipeRunStats { name: string; /** Number of times the driver fired this recipe in the current run. */ fired: number; succeeded: number; failed: number; /** Mean of succeeded-run durations. */ avgDurationMs: number; /** Earliest firing in this run (ms since epoch). */ firstFiredAt: number; /** Latest firing in this run. */ lastFiredAt: number; } /** * Public surface for a recipeDriver. Adds `getRunStats()` on top of * the base Driver interface — issue #92's observability hook. */ export interface RecipeDriverInstance extends Driver { /** * Per-recipe firing counts since this driver instance was created. * Snapshot — caller mutations don't leak. */ getRunStats(): RecipeRunStats[]; } export interface RecipeDriverOptions { store: RecipeStore; /** * Restrict to recipes captured under this Goal. Recipes from other * goals are still in the store but ignored — keeps a "buy" recipe * from firing during a "bug-hunting" run. */ goal?: string; /** * Pre-filter beyond status + goal. Useful for e.g. only replaying * recipes that haven't been seen this session. */ filter?: (recipe: ActionRecipe) => boolean; /** * Console-log when a recipe fires / fails. Default: false. Surface * via the standard logger once we have one. */ verbose?: boolean; /** Identifier surfaced in DriverPick.source. Default: `"recipe"`. */ source?: string; /** * When true (default), `requires` dependencies are replayed in topo * order before the matched recipe runs. Set false for legacy * "metadata only" semantics — the runner will fire the matched * recipe directly even if its preconditions assume a logged-in * state. * * Already-replayed dependencies are tracked per-Page, so a single * `auth/login` recipe doesn't re-run for every dependent recipe * after it. */ chainRequires?: boolean; } export declare function recipeDriver(opts: RecipeDriverOptions): RecipeDriverInstance; /** * Group a flat firing log by recipe name and compute the public * RecipeRunStats shape. Stable order: most-fired first, then alpha. */ export declare function aggregateFirings(firings: ReadonlyArray<{ name: string; succeeded: boolean; durationMs: number; timestamp: number; }>): RecipeRunStats[]; //# sourceMappingURL=recipe-driver.d.ts.map