Spaces:
Sleeping
Sleeping
| type VerificationStatus = "verified" | "unverified" | "likely_misleading"; | |
| type Confidence = "high" | "medium" | "low"; | |
| type Reality = "REAL" | "FAKE" | "UNCERTAIN"; | |
| type DealQuality = "GOOD" | "AVERAGE" | "BAD"; | |
| type FinalAdvice = "ACT_FAST" | "COMPARE_OPTIONS" | "RELAX_IGNORE"; | |
| type CheckOutcome = "real_signal" | "fake_signal" | "inconclusive"; | |
| export type DealSignalType = "limited_time" | "limited_stock" | "high_demand" | "flash_sale"; | |
| export type ProductCandidateInput = { | |
| title: string; | |
| listedPrice?: number | null; | |
| originalPrice?: number | null; | |
| historicalMinPrice?: number | null; | |
| currency?: string | null; | |
| url?: string | null; | |
| dealSignals?: string[] | null; | |
| stockText?: string | null; | |
| urgencyText?: string | null; | |
| hasTimer?: boolean | null; | |
| timerResetsOnRefresh?: boolean | null; | |
| reloadStockChanges?: boolean | null; | |
| crossPlatformMatch?: boolean | null; | |
| historySnapshot?: { | |
| observations?: number; | |
| scarcityClaimRate?: number; | |
| uniquePricePoints?: number; | |
| lastSeenAt?: string | null; | |
| } | null; | |
| }; | |
| export type DealItemResult = { | |
| productTitle: string; | |
| listedPrice: number | null; | |
| currency: string; | |
| status: VerificationStatus; | |
| confidence: Confidence; | |
| claimSignals: DealSignalType[]; | |
| evidence: string[]; | |
| rationale: string; | |
| recommendation: string; | |
| saferAlternatives: string[]; | |
| trustVerification: { | |
| reality: Reality; | |
| confidence: Confidence; | |
| confidence_score: number; | |
| fomo_detected: boolean; | |
| deal_quality: DealQuality; | |
| final_advice: FinalAdvice; | |
| checks: { | |
| pattern_check: CheckOutcome; | |
| stability_check: CheckOutcome; | |
| reset_check: CheckOutcome; | |
| external_validation: CheckOutcome; | |
| price_truth_check: CheckOutcome; | |
| }; | |
| signal_tally: { | |
| strong_fake: number; | |
| strong_real: number; | |
| }; | |
| reasoning: string[]; | |
| }; | |
| }; | |
| export type DealIntelligenceResult = { | |
| summary: string; | |
| researchMode: "page_evidence_only" | "provider_verified"; | |
| items: DealItemResult[]; | |
| }; | |
| export type DealIntelligenceInput = { | |
| domain: string; | |
| url?: string; | |
| pageType?: "non_commerce" | "product" | "cart" | "checkout" | "listing" | "unknown" | string; | |
| pageText?: string; | |
| hasTimer?: boolean | null; | |
| timerResetsOnRefresh?: boolean | null; | |
| reloadStockChanges?: boolean | null; | |
| timerElements?: string[]; | |
| stockAlerts?: string[]; | |
| variantUrgency?: string[]; | |
| productCandidates?: ProductCandidateInput[]; | |
| }; | |
| function normalizeText(value: unknown): string { | |
| return typeof value === "string" ? value.replace(/\s+/g, " ").trim() : ""; | |
| } | |
| function toLowerJoined(values: unknown[] | undefined): string { | |
| return (values ?? []) | |
| .map((value) => normalizeText(value).toLowerCase()) | |
| .filter(Boolean) | |
| .join(" "); | |
| } | |
| function parseSignalsFromText(text: string): DealSignalType[] { | |
| const signals: DealSignalType[] = []; | |
| if (/limited time|deal ends|ends in|expires|flash sale|today only|offer ends/i.test(text)) { | |
| signals.push("limited_time"); | |
| } | |
| if (/only \d+|remaining|left at this price|few seats left|few rooms left/i.test(text)) { | |
| signals.push("limited_stock"); | |
| } | |
| if (/people viewing|booked in the last|sold in last|high demand|trending now/i.test(text)) { | |
| signals.push("high_demand"); | |
| } | |
| if (/flash sale|lightning deal|mega deal|limited deal/i.test(text)) { | |
| signals.push("flash_sale"); | |
| } | |
| return Array.from(new Set(signals)); | |
| } | |
| function unique<T>(values: T[]): T[] { | |
| return Array.from(new Set(values)); | |
| } | |
| function defaultAlternativeDomains(domain: string): string[] { | |
| const key = normalizeText(domain).toLowerCase(); | |
| if (key.includes("amazon")) return ["walmart.com", "bestbuy.com", "target.com"]; | |
| if (key.includes("booking") || key.includes("trip") || key.includes("makemytrip")) return ["agoda.com", "goibibo.com", "hotels.com"]; | |
| if (key.includes("air") || key.includes("flight")) return ["skyscanner.com", "kayak.com", "google.com/travel/flights"]; | |
| return []; | |
| } | |
| function parseStockNumber(text: string): number | null { | |
| const match = text.match(/\bonly\s+(\d+)\b|\b(\d+)\s+(left|remaining)\b/i); | |
| if (!match) return null; | |
| const value = Number(match[1] || match[2]); | |
| return Number.isFinite(value) ? value : null; | |
| } | |
| function inferPriceFluctuation(uniquePricePoints: number): "high" | "medium" | "low" { | |
| if (uniquePricePoints >= 3) return "high"; | |
| if (uniquePricePoints === 2) return "medium"; | |
| return "low"; | |
| } | |
| function inferHistoricalScarcityFrequency(scarcityClaimRate: number): "high" | "medium" | "low" { | |
| if (scarcityClaimRate >= 0.7) return "high"; | |
| if (scarcityClaimRate >= 0.35) return "medium"; | |
| return "low"; | |
| } | |
| function mapTrustVerification(input: { | |
| urgency_text: string; | |
| stock_text: string; | |
| stock_number: number | null; | |
| has_timer: boolean; | |
| timer_resets_on_refresh: boolean | null; | |
| same_urgency_count: number; | |
| same_discount_count: number; | |
| appears_in_listing: boolean; | |
| appears_in_product_page: boolean; | |
| reload_stock_changes: boolean | null; | |
| cross_platform_match: boolean | null; | |
| price_current: number | null; | |
| price_original: number | null; | |
| price_history_min: number | null; | |
| price_fluctuation: "high" | "medium" | "low"; | |
| historical_scarcity_frequency: "high" | "medium" | "low"; | |
| page_type?: string | null; | |
| }): DealItemResult["trustVerification"] { | |
| const reasons: string[] = []; | |
| let strongFakeSignals = 0; | |
| let strongRealSignals = 0; | |
| const checks: DealItemResult["trustVerification"]["checks"] = { | |
| pattern_check: "inconclusive", | |
| stability_check: "inconclusive", | |
| reset_check: "inconclusive", | |
| external_validation: "inconclusive", | |
| price_truth_check: "inconclusive", | |
| }; | |
| // 1. Pattern check | |
| if (input.same_urgency_count >= 3 || input.same_discount_count >= 3) { | |
| strongFakeSignals += 1; | |
| checks.pattern_check = "fake_signal"; | |
| reasons.push("The same urgency/discount framing appears across many products, which is a strong manufactured-pressure signal."); | |
| } else if (input.same_urgency_count <= 1 && input.same_discount_count <= 1 && (input.stock_number ?? 0) > 0) { | |
| strongRealSignals += 1; | |
| checks.pattern_check = "real_signal"; | |
| reasons.push("Urgency appears item-specific instead of being repeated across many products."); | |
| } | |
| // 2. Specificity check | |
| if (input.stock_number !== null) { | |
| strongRealSignals += 1; | |
| reasons.push("The scarcity claim includes an exact stock count, which is more concrete than vague pressure text."); | |
| } else if (/\bfew left|selling fast|hurry|almost gone\b/i.test(input.stock_text)) { | |
| strongFakeSignals += 1; | |
| reasons.push("The scarcity text is vague ('few left' / 'selling fast') and not tied to a verifiable count."); | |
| } | |
| // 3. Time/stability check | |
| if (input.reload_stock_changes === false) { | |
| strongFakeSignals += 1; | |
| checks.stability_check = "fake_signal"; | |
| reasons.push("Scarcity/urgency signals stayed static across observations, which weakens authenticity."); | |
| } else if (input.reload_stock_changes === true) { | |
| strongRealSignals += 1; | |
| checks.stability_check = "real_signal"; | |
| reasons.push("Stock/urgency changed over time in a way that can indicate real inventory dynamics."); | |
| } | |
| // 4. Reset check | |
| if (input.timer_resets_on_refresh === true) { | |
| strongFakeSignals += 2; | |
| checks.reset_check = "fake_signal"; | |
| reasons.push("The timer appears to reset on refresh, which is a very strong fake-urgency behavior."); | |
| } else if (input.has_timer && input.timer_resets_on_refresh === false) { | |
| strongRealSignals += 1; | |
| checks.reset_check = "real_signal"; | |
| reasons.push("The timer does not reset across refresh checks, which supports authenticity."); | |
| } | |
| // 5. Cross-page check | |
| if (input.appears_in_listing && !input.appears_in_product_page) { | |
| strongFakeSignals += 1; | |
| reasons.push("Urgency appears in listing context but not on the product detail page, suggesting promo framing rather than item-specific scarcity."); | |
| } else if (input.appears_in_product_page) { | |
| strongRealSignals += 1; | |
| reasons.push("The urgency/scarcity signal is present on the product detail page, not only in listing cards."); | |
| } | |
| // 6. Cross-platform check | |
| if (input.cross_platform_match === false) { | |
| strongFakeSignals += 1; | |
| checks.external_validation = "fake_signal"; | |
| reasons.push("Cross-platform checks did not confirm the same scarcity narrative."); | |
| } else if (input.cross_platform_match === true) { | |
| strongRealSignals += 1; | |
| checks.external_validation = "real_signal"; | |
| reasons.push("Cross-platform checks show similar scarcity signals, which supports authenticity."); | |
| } | |
| // 7. Price validation | |
| let dealQuality: DealQuality = "AVERAGE"; | |
| if (input.price_current !== null && input.price_history_min !== null) { | |
| const delta = input.price_current - input.price_history_min; | |
| if (delta <= Math.max(1, input.price_history_min * 0.05)) { | |
| dealQuality = "GOOD"; | |
| checks.price_truth_check = "real_signal"; | |
| reasons.push("Current price is close to the observed historical minimum, so the deal quality looks strong."); | |
| } else if (input.price_fluctuation === "high") { | |
| dealQuality = "BAD"; | |
| checks.price_truth_check = "fake_signal"; | |
| reasons.push("Price behavior is highly volatile, reducing reliability of the advertised discount."); | |
| } | |
| } else if (input.price_fluctuation === "high") { | |
| dealQuality = "BAD"; | |
| checks.price_truth_check = "fake_signal"; | |
| reasons.push("Price fluctuations are high and historical floor is unclear, so this deal is not reliably strong."); | |
| } | |
| if (input.price_current !== null && input.price_original !== null && input.price_current >= input.price_original * 0.9) { | |
| strongFakeSignals += 1; | |
| dealQuality = "BAD"; | |
| checks.price_truth_check = "fake_signal"; | |
| reasons.push("The claimed original price is close to current price, which weakens the credibility of the discount framing."); | |
| } | |
| // 8. History check | |
| if (input.historical_scarcity_frequency === "high") { | |
| strongFakeSignals += 1; | |
| reasons.push("Historical observations show frequent recurring scarcity claims for this item, indicating likely persistent pressure tactics."); | |
| } else if (input.historical_scarcity_frequency === "low" && input.stock_number !== null) { | |
| strongRealSignals += 1; | |
| reasons.push("Scarcity signaling is not continuously repeated in history and includes specific stock information."); | |
| } | |
| // Positive trust signals for clean product/checkout flows. | |
| if ((input.page_type === "checkout" || input.page_type === "product") && !input.urgency_text && !input.stock_text) { | |
| strongRealSignals += 1; | |
| reasons.push("Clean product/checkout flow with no pressure tactics detected on the page."); | |
| } | |
| if (!input.has_timer) { | |
| strongRealSignals += 1; | |
| reasons.push("No countdown timer was detected, which reduces the chance of artificial urgency."); | |
| } | |
| if (input.timer_resets_on_refresh === false) { | |
| strongRealSignals += 1; | |
| reasons.push("Timer behavior stayed consistent across refresh checks."); | |
| } | |
| if (input.reload_stock_changes === false && input.stock_text) { | |
| strongRealSignals += 1; | |
| reasons.push("Stock message stayed stable across reload checks instead of fluctuating upward."); | |
| } | |
| const reality: Reality = | |
| strongFakeSignals >= 3 ? "FAKE" : strongRealSignals > strongFakeSignals && strongFakeSignals === 0 ? "REAL" : "UNCERTAIN"; | |
| const confidence: Confidence = | |
| Math.abs(strongRealSignals - strongFakeSignals) >= 3 ? "high" : Math.abs(strongRealSignals - strongFakeSignals) >= 1 ? "medium" : "low"; | |
| const confidenceScore = Math.min(1, Math.max(0, 0.5 + (strongRealSignals - strongFakeSignals) * 0.12)); | |
| const fomoDetected = | |
| /\blimited|hurry|few left|last chance|selling fast|ends in|expires|only \d+\b/i.test(`${input.urgency_text} ${input.stock_text}`) || | |
| input.has_timer; | |
| const finalAdvice: FinalAdvice = | |
| reality === "REAL" && dealQuality !== "BAD" | |
| ? "ACT_FAST" | |
| : reality === "FAKE" | |
| ? "RELAX_IGNORE" | |
| : "COMPARE_OPTIONS"; | |
| if (reasons.length === 0) { | |
| reasons.push("Evidence is insufficient to verify whether urgency is genuine, so this is treated as uncertain."); | |
| } | |
| return { | |
| reality, | |
| confidence, | |
| confidence_score: Number(confidenceScore.toFixed(2)), | |
| fomo_detected: fomoDetected, | |
| deal_quality: dealQuality, | |
| final_advice: finalAdvice, | |
| checks, | |
| signal_tally: { | |
| strong_fake: strongFakeSignals, | |
| strong_real: strongRealSignals, | |
| }, | |
| reasoning: reasons.slice(0, 6), | |
| }; | |
| } | |
| function evaluateSingleDeal(input: { | |
| productTitle: string; | |
| listedPrice: number | null; | |
| currency: string; | |
| url?: string | null; | |
| candidateSignals: DealSignalType[]; | |
| urgencyText: string; | |
| pageSignals: DealSignalType[]; | |
| timerText: string; | |
| stockText: string; | |
| pageText: string; | |
| domain: string; | |
| repeatedClaimPressure: boolean; | |
| historySignalPressure: boolean; | |
| priceInstabilitySignal: boolean; | |
| sameUrgencyCount: number; | |
| sameDiscountCount: number; | |
| hasTimer: boolean; | |
| crossPlatformMatch: boolean | null; | |
| priceOriginal: number | null; | |
| priceHistoryMin: number | null; | |
| priceFluctuation: "high" | "medium" | "low"; | |
| historicalScarcityFrequency: "high" | "medium" | "low"; | |
| reloadStockChanges: boolean | null; | |
| timerResetsOnRefresh: boolean | null; | |
| pageType?: string | null; | |
| }): DealItemResult { | |
| const combinedSignals = unique([...input.candidateSignals, ...input.pageSignals]); | |
| const hasDealClaim = combinedSignals.length > 0; | |
| const hasSpecificAbsoluteExpiry = | |
| /\b(20\d{2}|jan|feb|mar|apr|may|jun|jul|aug|sep|sept|oct|nov|dec)\b/i.test(input.timerText) && | |
| /\b(\d{1,2}:\d{2}|\d{1,2}(am|pm))\b/i.test(input.timerText); | |
| const hasOnlyGenericCountdown = /\b\d{1,2}:\d{2}(:\d{2})?\b/.test(input.timerText) && !hasSpecificAbsoluteExpiry; | |
| const hasCrowdPressure = /people viewing|booked in the last|sold in last|high demand/i.test(input.stockText); | |
| const hasWeakEvidence = | |
| hasOnlyGenericCountdown || | |
| hasCrowdPressure || | |
| input.repeatedClaimPressure || | |
| input.historySignalPressure || | |
| input.priceInstabilitySignal; | |
| let status: VerificationStatus = "unverified"; | |
| let confidence: Confidence = "low"; | |
| const evidence: string[] = []; | |
| if (!hasDealClaim) { | |
| status = "unverified"; | |
| confidence = "low"; | |
| evidence.push("No explicit limited-deal or scarcity claim was detected for this item."); | |
| } else if (hasSpecificAbsoluteExpiry && !hasCrowdPressure) { | |
| status = "verified"; | |
| confidence = "medium"; | |
| evidence.push("The deal includes a concrete expiry window (date/time), which is more auditable than generic urgency copy."); | |
| } else if (hasWeakEvidence) { | |
| status = "likely_misleading"; | |
| confidence = "medium"; | |
| if (hasOnlyGenericCountdown) { | |
| evidence.push("Claim relies on a generic countdown timer without independently verifiable expiration context."); | |
| } | |
| if (hasCrowdPressure) { | |
| evidence.push("Claim includes crowd-pressure language (for example, 'people viewing/booked') that is often unverifiable."); | |
| } | |
| if (input.repeatedClaimPressure) { | |
| evidence.push("The same limited-deal pressure appears across many products, which often indicates promotional framing rather than item-specific scarcity."); | |
| } | |
| if (input.historySignalPressure) { | |
| evidence.push("Guardian history shows this product repeatedly carries scarcity language across multiple observations."); | |
| } | |
| if (input.priceInstabilitySignal) { | |
| evidence.push("Guardian history shows unstable price points for this product while scarcity pressure remains active."); | |
| } | |
| } else { | |
| status = "unverified"; | |
| confidence = "low"; | |
| evidence.push("The page includes urgency/scarcity language, but there is not enough hard evidence to verify the claim."); | |
| } | |
| const saferAlternatives = defaultAlternativeDomains(input.domain); | |
| const trustVerification = mapTrustVerification({ | |
| urgency_text: input.urgencyText || input.timerText, | |
| stock_text: input.stockText, | |
| stock_number: parseStockNumber(`${input.timerText} ${input.stockText}`), | |
| has_timer: input.hasTimer, | |
| timer_resets_on_refresh: input.timerResetsOnRefresh, | |
| same_urgency_count: input.sameUrgencyCount, | |
| same_discount_count: input.sameDiscountCount, | |
| appears_in_listing: /\/s\?|search|deals|goldbox|category|collections?/i.test(input.url ?? ""), | |
| appears_in_product_page: /\/dp\/|\/p\/|\/product|\/gp\/product/i.test(input.url ?? ""), | |
| reload_stock_changes: input.reloadStockChanges, | |
| cross_platform_match: input.crossPlatformMatch, | |
| price_current: input.listedPrice, | |
| price_original: input.priceOriginal, | |
| price_history_min: input.priceHistoryMin, | |
| price_fluctuation: input.priceFluctuation, | |
| historical_scarcity_frequency: input.historicalScarcityFrequency, | |
| page_type: input.pageType || null, | |
| }); | |
| const rationale = | |
| trustVerification.reality === "REAL" || status === "verified" | |
| ? "Guardian found stronger-than-usual expiry evidence, but the user should still compare the final payable amount." | |
| : trustVerification.reality === "FAKE" || status === "likely_misleading" | |
| ? "Guardian found deal pressure patterns that are common in manufactured FOMO flows." | |
| : "Guardian cannot prove this deal claim from page evidence alone."; | |
| const recommendation = | |
| trustVerification.final_advice === "ACT_FAST" | |
| ? "Proceed, but verify final payable amount and terms before payment." | |
| : trustVerification.final_advice === "RELAX_IGNORE" | |
| ? "This looks like manipulative pressure; relax and compare alternatives before deciding." | |
| : "Compare options and verify stock/deal persistence before committing."; | |
| return { | |
| productTitle: input.productTitle, | |
| listedPrice: input.listedPrice, | |
| currency: input.currency, | |
| status, | |
| confidence, | |
| claimSignals: combinedSignals, | |
| evidence, | |
| rationale, | |
| recommendation, | |
| saferAlternatives, | |
| trustVerification, | |
| }; | |
| } | |
| export function analyzeDealIntelligence(input: DealIntelligenceInput): DealIntelligenceResult { | |
| const timerText = toLowerJoined(input.timerElements); | |
| const stockText = toLowerJoined(input.stockAlerts); | |
| const pageText = normalizeText(input.pageText).toLowerCase(); | |
| const pageSignals = parseSignalsFromText(`${timerText} ${stockText} ${pageText}`); | |
| const candidates = (input.productCandidates ?? []) | |
| .map((candidate) => ({ | |
| title: normalizeText(candidate.title), | |
| listedPrice: typeof candidate.listedPrice === "number" && Number.isFinite(candidate.listedPrice) ? candidate.listedPrice : null, | |
| originalPrice: typeof candidate.originalPrice === "number" && Number.isFinite(candidate.originalPrice) ? candidate.originalPrice : null, | |
| historicalMinPrice: | |
| typeof candidate.historicalMinPrice === "number" && Number.isFinite(candidate.historicalMinPrice) ? candidate.historicalMinPrice : null, | |
| currency: normalizeText(candidate.currency) || "USD", | |
| url: normalizeText(candidate.url) || null, | |
| stockText: normalizeText(candidate.stockText) || null, | |
| urgencyText: normalizeText(candidate.urgencyText) || null, | |
| hasTimer: candidate.hasTimer === true, | |
| timerResetsOnRefresh: typeof candidate.timerResetsOnRefresh === "boolean" ? candidate.timerResetsOnRefresh : null, | |
| reloadStockChanges: typeof candidate.reloadStockChanges === "boolean" ? candidate.reloadStockChanges : null, | |
| crossPlatformMatch: typeof candidate.crossPlatformMatch === "boolean" ? candidate.crossPlatformMatch : null, | |
| dealSignals: unique( | |
| (candidate.dealSignals ?? []) | |
| .map((signal) => normalizeText(signal).toLowerCase()) | |
| .filter(Boolean), | |
| ), | |
| historySnapshot: | |
| candidate.historySnapshot && typeof candidate.historySnapshot === "object" | |
| ? { | |
| observations: typeof candidate.historySnapshot.observations === "number" ? candidate.historySnapshot.observations : 0, | |
| scarcityClaimRate: | |
| typeof candidate.historySnapshot.scarcityClaimRate === "number" ? candidate.historySnapshot.scarcityClaimRate : 0, | |
| uniquePricePoints: | |
| typeof candidate.historySnapshot.uniquePricePoints === "number" ? candidate.historySnapshot.uniquePricePoints : 0, | |
| } | |
| : null, | |
| })) | |
| .filter((candidate) => candidate.title.length > 0) | |
| .slice(0, 12); | |
| const normalizedCandidates = candidates.length | |
| ? candidates | |
| : [ | |
| { | |
| title: "Current page offer", | |
| listedPrice: null, | |
| originalPrice: null, | |
| historicalMinPrice: null, | |
| currency: "USD", | |
| url: normalizeText(input.url) || null, | |
| stockText: null, | |
| urgencyText: null, | |
| hasTimer: input.hasTimer === true, | |
| timerResetsOnRefresh: null, | |
| reloadStockChanges: null, | |
| crossPlatformMatch: null, | |
| dealSignals: parseSignalsFromText(pageText), | |
| historySnapshot: null, | |
| }, | |
| ]; | |
| const broadDealPressureCount = normalizedCandidates.filter((candidate) => | |
| candidate.dealSignals.some((signal) => /limited|flash|lightning|deal|ends in|expires|only \d+ left/.test(signal)), | |
| ).length; | |
| const urgencyBucket = new Map<string, number>(); | |
| const discountBucket = new Map<string, number>(); | |
| for (const candidate of normalizedCandidates) { | |
| for (const signal of candidate.dealSignals) { | |
| const normalized = normalizeText(signal).toLowerCase(); | |
| if (!normalized) continue; | |
| if (/limited|ends in|expires|few left|only \d+ left|selling fast|flash|lightning/.test(normalized)) { | |
| urgencyBucket.set(normalized, (urgencyBucket.get(normalized) ?? 0) + 1); | |
| } | |
| if (/%\s*off|discount|save|m\.?r\.?p/i.test(normalized)) { | |
| discountBucket.set(normalized, (discountBucket.get(normalized) ?? 0) + 1); | |
| } | |
| } | |
| } | |
| const items = normalizedCandidates.map((candidate) => | |
| evaluateSingleDeal({ | |
| productTitle: candidate.title, | |
| listedPrice: candidate.listedPrice, | |
| currency: candidate.currency, | |
| url: candidate.url, | |
| candidateSignals: parseSignalsFromText(candidate.dealSignals.join(" ")), | |
| urgencyText: candidate.urgencyText || candidate.dealSignals.join(" "), | |
| pageSignals, | |
| timerText, | |
| stockText: candidate.stockText || stockText, | |
| pageText, | |
| domain: input.domain, | |
| repeatedClaimPressure: | |
| broadDealPressureCount >= 3 && | |
| candidate.dealSignals.some((signal) => /limited|flash|lightning|deal|ends in|expires|only \d+ left/.test(signal)), | |
| historySignalPressure: | |
| Number(candidate?.historySnapshot?.observations || 0) >= 3 && | |
| Number(candidate?.historySnapshot?.scarcityClaimRate || 0) >= 0.75, | |
| priceInstabilitySignal: | |
| Number(candidate?.historySnapshot?.observations || 0) >= 4 && | |
| Number(candidate?.historySnapshot?.uniquePricePoints || 0) >= 3, | |
| sameUrgencyCount: Math.max( | |
| 1, | |
| ...candidate.dealSignals | |
| .map((signal) => urgencyBucket.get(normalizeText(signal).toLowerCase()) ?? 1) | |
| .filter((count) => Number.isFinite(count)), | |
| ), | |
| sameDiscountCount: Math.max( | |
| 1, | |
| ...candidate.dealSignals | |
| .map((signal) => discountBucket.get(normalizeText(signal).toLowerCase()) ?? 1) | |
| .filter((count) => Number.isFinite(count)), | |
| ), | |
| hasTimer: candidate.hasTimer === true || input.hasTimer === true || /\b\d{1,2}:\d{2}(:\d{2})?\b|ends in|expires|countdown/i.test(timerText), | |
| crossPlatformMatch: candidate.crossPlatformMatch ?? null, | |
| priceOriginal: candidate.originalPrice ?? null, | |
| priceHistoryMin: candidate.historicalMinPrice ?? null, | |
| priceFluctuation: inferPriceFluctuation(Number(candidate?.historySnapshot?.uniquePricePoints || 1)), | |
| historicalScarcityFrequency: inferHistoricalScarcityFrequency( | |
| Number(candidate?.historySnapshot?.scarcityClaimRate || 0), | |
| ), | |
| reloadStockChanges: | |
| candidate.reloadStockChanges ?? | |
| input.reloadStockChanges ?? | |
| (Number(candidate?.historySnapshot?.observations || 0) >= 3 | |
| ? Number(candidate?.historySnapshot?.scarcityClaimRate || 0) < 0.95 | |
| : null), | |
| timerResetsOnRefresh: candidate.timerResetsOnRefresh ?? input.timerResetsOnRefresh ?? null, | |
| pageType: input.pageType || null, | |
| }), | |
| ); | |
| const likelyMisleadingCount = items.filter((item) => item.status === "likely_misleading").length; | |
| const verifiedCount = items.filter((item) => item.status === "verified").length; | |
| const summary = | |
| likelyMisleadingCount > 0 | |
| ? `Guardian reviewed ${items.length} offer(s) and found ${likelyMisleadingCount} likely misleading limited-deal claim(s).` | |
| : verifiedCount > 0 | |
| ? `Guardian reviewed ${items.length} offer(s) and found ${verifiedCount} claim(s) with moderate verification evidence.` | |
| : `Guardian reviewed ${items.length} offer(s), but the limited-deal claims remain unverified from page evidence alone.`; | |
| return { | |
| summary, | |
| researchMode: "page_evidence_only", | |
| items, | |
| }; | |
| } | |