import type { RunState } from "./state.js"; /** v0.5: shared default age-floor for monitoring. Single source of truth. */ export declare const DEFAULT_AGE_FLOOR_DAYS = 7; export type RefetchReason = "new" | "age" | "ruleset" | "recheck" | "lastmod" | "gsc" | "no-signal" | "watched"; export type SkipReason = "unchanged"; export interface ScrapePlan { refetch: Map; skip: Map; } export interface GscDelta { impressionsDelta: number; clicksDelta: number; } export interface GscThresholds { impressionsPct: number; clicksAbsolute: number; } export interface ScrapeStrategyInputs { candidateUrls: readonly string[]; priorState: RunState | null; sitemapLastmodByUrl: ReadonlyMap; gscDeltasByUrl?: ReadonlyMap; gscThresholds?: GscThresholds; currentRulesetVersion: string; ageFloorDays: number; now: Date; /** * v0.5.3 — caller-supplied "watched pages" list. Any URL appearing here is * marked refetch with reason `"watched"` and short-circuits the rest of the * matrix (age, ruleset, lastmod, etc.). Watched URLs that aren't already in * `candidateUrls` are still added to the audit set — the caller may * legitimately watch a page that has been removed from the sitemap and we * should still audit it so they find out it's gone. * * Owned by the caller (e.g. the web app's per-domain DB-backed list); the * engine treats it as a transient input override and never persists it on * `RunState`. */ forceRefetchUrls?: ReadonlyArray; /** * v0.5.4 — optional budget cap for candidate URL selection. When set, * `planScrapeStrategy` will apply template-stratified sampling to narrow * `candidateUrls` down to this budget before running the per-URL decision * matrix. Watched URLs (from `forceRefetchUrls`) bypass this budget and * are always included regardless of the cap. * * Stratification activates only when: * 1. `candidateUrls.length > sampleSize * 1.5` (no point stratifying when * we can take everything) * 2. `clusterUrlTemplates` produces ≥2 clusters AND the largest cluster * covers ≤80% of the candidate pool (if one template dominates 90%+, * there is nothing to balance — falls back to uniform sampling). * * When stratification doesn't activate, a simple sequential prefix slice is * used (preserving the caller's ordering). The decision matrix runs only * on the selected URLs. */ sampleSize?: number; } export declare function planScrapeStrategy(inputs: ScrapeStrategyInputs): ScrapePlan; //# sourceMappingURL=scrape-strategy.d.ts.map