1010from openvibecoding_orch .store .run_store import RunStore
1111from openvibecoding_orch .contract .validator import ContractValidator
1212
13+ _CHAT_PROVIDER_HOSTS : dict [str , set [str ]] = {
14+ "gemini_web" : {"gemini.google.com" },
15+ "grok_web" : {"grok.com" },
16+ "chatgpt_web" : {"chatgpt.com" , "chat.openai.com" },
17+ }
18+
1319
1420def _now_ts () -> str :
1521 return datetime .now (timezone .utc ).isoformat ()
@@ -42,6 +48,47 @@ def _domain_from_href(href: str) -> str:
4248 return ""
4349
4450
51+ def _is_chat_provider_homepage (provider : Any , href : Any ) -> bool :
52+ provider_name = str (provider or "" ).strip ().lower ()
53+ domain = _domain_from_href (str (href or "" )).strip ().lower ()
54+ return bool (domain ) and domain in _CHAT_PROVIDER_HOSTS .get (provider_name , set ())
55+
56+
57+ def _has_public_source_hits (results : list [dict [str , Any ]]) -> bool :
58+ for item in results :
59+ if not isinstance (item , dict ):
60+ continue
61+ provider = item .get ("provider" ) or item .get ("resolved_provider" ) or item .get ("mode" ) or "unknown"
62+ hits = item .get ("results" ) if isinstance (item .get ("results" ), list ) else []
63+ for hit in hits :
64+ if not isinstance (hit , dict ):
65+ continue
66+ href = str (hit .get ("href" ) or "" ).strip ()
67+ if href and not _is_chat_provider_homepage (provider , href ):
68+ return True
69+ return False
70+
71+
72+ def _summarize_public_source_failure (results : list [dict [str , Any ]]) -> str :
73+ offenders : list [str ] = []
74+ for item in results :
75+ if not isinstance (item , dict ):
76+ continue
77+ provider = item .get ("provider" ) or item .get ("resolved_provider" ) or item .get ("mode" ) or "unknown"
78+ hits = item .get ("results" ) if isinstance (item .get ("results" ), list ) else []
79+ for hit in hits :
80+ if not isinstance (hit , dict ):
81+ continue
82+ href = str (hit .get ("href" ) or "" ).strip ()
83+ if href and _is_chat_provider_homepage (provider , href ):
84+ offender = f"{ str (provider ).strip ()} -> { _domain_from_href (href )} "
85+ if offender not in offenders :
86+ offenders .append (offender )
87+ if offenders :
88+ return f"来源链路失败:当前结果仍停在 provider 壳页而不是公开来源页面({ ', ' .join (offenders )} )。"
89+ return "来源链路失败:当前结果没有产出可公开审计的来源页面。"
90+
91+
4592def _build_sources (results : list [dict ]) -> list [dict ]:
4693 sources : list [dict ] = []
4794 retrieved_at = _now_ts ()
@@ -117,6 +164,8 @@ def _purify_results(results: list[dict], verification: dict | None = None) -> di
117164 if not href :
118165 missing_href += 1
119166 continue
167+ if _is_chat_provider_homepage (provider , href ):
168+ continue
120169 domain = _domain_from_href (str (href ))
121170 if domain :
122171 domain_counts [domain ] = domain_counts .get (domain , 0 ) + 1
@@ -242,6 +291,7 @@ def _build_digest_result(
242291) -> dict [str , Any ]:
243292 digest_sources : list [dict [str , Any ]] = []
244293 seen_urls : set [str ] = set ()
294+ public_source_hit_found = False
245295 for provider_entry in results :
246296 if not isinstance (provider_entry , dict ):
247297 continue
@@ -256,10 +306,13 @@ def _build_digest_result(
256306 if not isinstance (hit , dict ):
257307 continue
258308 href = str (hit .get ("href" ) or "" ).strip ()
309+ if href and _is_chat_provider_homepage (provider , href ):
310+ continue
259311 if href and href in seen_urls :
260312 continue
261313 if href :
262314 seen_urls .add (href )
315+ public_source_hit_found = True
263316 digest_sources .append (
264317 {
265318 "title" : str (hit .get ("title" ) or hit .get ("name" ) or href or "result" ).strip () or "result" ,
@@ -283,6 +336,13 @@ def _build_digest_result(
283336 " Review failure_reason_zh and the evidence bundle for the detailed provider failure context."
284337 ).strip ()
285338 status = "FAILED"
339+ elif not public_source_hit_found and results :
340+ summary = (
341+ f"The { template_label } for '{ topic } ' did not produce a trustworthy public-source receipt."
342+ " The current provider outputs stayed on provider shell pages instead of auditable source URLs."
343+ )
344+ status = "FAILED"
345+ failure_reason_zh = failure_reason_zh or _summarize_public_source_failure (results )
286346 elif digest_sources :
287347 preview = ", " .join (item ["title" ] for item in digest_sources [:3 ])
288348 summary = (
0 commit comments