export interface InsightProduct { product_uuid: string; name?: string; price?: number; status?: string; } export interface InsightOrder { order_uuid: string; channel?: string; total?: number; items?: { product_name?: string; }[]; } export interface Insight { category: string; finding: string; confidence: 'high' | 'medium' | 'low'; recommendation: string; } export interface OptimizeProposal { product_uuid: string; product_name?: string; action: 'pause' | 'regenerate_design' | 'lower_price' | 'remove_from_channel' | 'optimize_listing' | 'increase_discovery' | 'review'; rationale: string; /** Derived channel state, when the sales channel reports performance. */ signal_state?: string; /** Impressions over the signal window — the demand evidence behind the call. */ impressions?: number; } /** * Per-listing demand signal, keyed by product_uuid. * * Sourced from the platform's channel-analytics endpoints. ABSENT for a product * means we have no demand data — which is NOT the same as no demand. */ export interface DemandSignal { state: string; impressions?: number; units_sold?: number; } export declare function salesCountByName(orders: InsightOrder[]): Map; export declare function deriveInsights(products: InsightProduct[], orders: InsightOrder[]): Insight[]; /** Products with zero recorded sales -> candidates to pause / refresh (a conservative signal). */ /** * Propose what to do about listings that are not selling. * * ⛔ THE RULE THIS FUNCTION EXISTS TO ENFORCE: "no sales" is not "no demand". * * This used to propose `pause` for every product with zero recorded sales, and * the review-and-optimize recipe applies pause autonomously. That meant a * listing with thousands of impressions and no sales — proven demand, broken * conversion, the single most valuable thing in the catalogue — got archived. * * With a demand signal we now only ever pause a listing the channel says is * genuinely inert, and route the rest to the fix they actually need. * * WITHOUT a demand signal we propose `review`, never `pause`. Falling back to * the old sales-only heuristic would silently reintroduce the bug on exactly * the channels that cannot see demand (WooCommerce reports no views at all). * Absence of evidence is not evidence of absence. */ export declare function findUnderperformers(products: InsightProduct[], orders: InsightOrder[], signals?: Map): OptimizeProposal[];