"""市場情報機會與威脅判讀 preview。 只定義未來 opportunity / threat scoring 規則;不建立 queue、不寫 DB、 不派送 Telegram、不產生 AI 報告。 """ from services.market_intel.ai_controlled_service_compat import compatibility_flag OPPORTUNITY_RULES = ( { "key": "competitor_price_threat", "label": "競品活動價低於 MOMO 參考價", "severity": "high", "requires_confirmed_match": True, "minimum_evidence": [ "confirmed_or_reviewed_match", "current_market_price", "momo_reference_price", ], "action_hint": "進入價格威脅審核,不自動調價。", }, { "key": "promotion_gap", "label": "競品有強促銷但我方未跟活動", "severity": "medium", "requires_confirmed_match": True, "minimum_evidence": [ "active_competitor_campaign", "confirmed_match", "momo_campaign_absent_or_weaker", ], "action_hint": "標記為活動缺口,交由 AI 例外決策是否跟進。", }, { "key": "deep_discount_overlap", "label": "同品或近似品出現深折重疊", "severity": "medium", "requires_confirmed_match": False, "minimum_evidence": [ "needs_review_match_score_above_threshold", "discount_rate_over_threshold", "campaign_context", ], "action_hint": "送入商品比對審核,不直接派送威脅告警。", }, { "key": "campaign_ending_watch", "label": "高折扣活動即將結束", "severity": "low", "requires_confirmed_match": False, "minimum_evidence": [ "campaign_end_at", "recent_price_snapshot", "discount_or_coupon_signal", ], "action_hint": "排入觀察清單,避免過期活動持續推播。", }, ) _OPERATOR_APPROVAL_COMPAT_KEY = compatibility_flag("operator_approval") def build_opportunity_plan_preview( *, runtime_status, match_review_plan, scheduler_plan, legacy_source_bridge, ): """建立市場機會與威脅判讀計畫;不執行任何推播或寫入。""" legacy_bridge_safe = ( legacy_source_bridge.get("mode") == "legacy_source_bridge_planned" and not legacy_source_bridge.get("read_only_query_executed") and not legacy_source_bridge.get("database_write_executed") ) scheduler_safe = ( scheduler_plan.get("mode") == "scheduler_attach_plan_preview" and not scheduler_plan.get("scheduler_registration_executed") and not scheduler_plan.get("crawler_job_started") ) match_review_safe = ( match_review_plan.get("mode") == "match_review_plan_preview" and not match_review_plan.get("auto_confirm_executed") and not match_review_plan.get("database_write_executed") ) gate_checks = { "match_review_plan_present": match_review_plan.get("mode") == "match_review_plan_preview", "match_review_candidates_available": bool( match_review_plan.get("ready_for_review_queue") ), "auto_confirm_disabled": not bool( (match_review_plan.get("thresholds") or {}).get("auto_confirm_enabled") ), "scheduler_plan_preview_safe": scheduler_safe, "legacy_bridge_planned_safe": legacy_bridge_safe, "database_write_still_blocked": not bool( runtime_status.database_write_allowed ), "match_review_preview_safe": match_review_safe, _OPERATOR_APPROVAL_COMPAT_KEY: False, } blocked_reasons = [ key for key, passed in gate_checks.items() if not passed ] return { "mode": "opportunity_plan_preview", "ready_for_opportunity_queue": False, "opportunity_queue_created": False, "threat_alert_dispatched": False, "telegram_dispatched": False, "ai_summary_generated": False, "database_session_created": False, "database_write_executed": False, "database_commit_executed": False, "external_network_executed": False, "scheduler_attached": False, "writes_executed": False, "would_write_database": False, "rule_count": len(OPPORTUNITY_RULES), "rules": list(OPPORTUNITY_RULES), "gate_checks": gate_checks, "blocked_reasons": blocked_reasons, "severity_policy": { "high": "只建立 AI 例外決策項,不自動調價、不直接派送高頻告警。", "medium": "進入日報摘要或審核清單,需 confirmed match 才能升級。", "low": "只做觀察,不觸發即時通知。", }, "operator_sequence": [ "先完成商品比對審核,至少取得 confirmed 或 needs_review 高信心候選", "用 campaign / price history 計算威脅與機會分數", "高風險項先進 AI 例外決策清單,不直接派送 Telegram", "AI 自動驗證確認後才允許進入 OpenClaw / Hermes 摘要", "所有 AI 摘要必須附上 DB evidence id 與規則 key", ], "safe_boundaries": [ "do_not_dispatch_alerts_from_preview", "do_not_generate_ai_summary_from_preview", "do_not_auto_adjust_price", "do_not_escalate_without_confirmed_match", "do_not_write_opportunity_queue_from_preview", ], }