@@ -304,13 +304,24 @@ def run_research_input_terminal_watcher(
304304 comment_issue : Callable [[str , str , str ], str ] = comment_github_issue ,
305305 list_issues : Callable [[str ], dict [str , str ]] = list_open_issue_urls ,
306306) -> dict [str , Any ]:
307- """Surface a trusted deferred P1 record as an issue-only finding."""
307+ """Surface a trusted deferred P1 record as an issue-only finding.
308+
309+ An accepted P1 terminal record is not a failure. It simply means that
310+ the producer has not yet emitted the two comparable P3 observations the
311+ watcher needs. Keep that state visible to the unified console without
312+ opening a misleading issue or failing the scheduled watcher.
313+ """
308314 candidate = terminal .get ("candidate" ) if isinstance (terminal .get ("candidate" ), dict ) else {}
315+ status = str (terminal .get ("status" ) or "" ).strip ().upper ()
316+ reason_code = str (terminal .get ("reason_code" ) or "" ).strip ()
317+ if status != "DEFERRED" or not reason_code :
318+ reason = "p1_terminal_accepted" if status == "ACCEPTED" else "p1_terminal_contract_unavailable"
319+ return no_comparable_metrics_result (reason = reason , dry_run = dry_run )
309320 finding = build_research_input_unavailable_finding (
310321 repo = source_repo ,
311322 profile = profile ,
312- status = str ( terminal . get ( " status" ) or "" ) ,
313- reason_code = str ( terminal . get ( " reason_code" ) or "" ) ,
323+ status = status ,
324+ reason_code = reason_code ,
314325 candidate_id = str (candidate .get ("candidate_id" ) or "" ),
315326 date_cutoff = str (terminal .get ("date_cutoff" ) or "" ),
316327 source = source ,
@@ -331,6 +342,32 @@ def run_research_input_terminal_watcher(
331342 return result
332343
333344
345+ def no_comparable_metrics_result (
346+ * , reason : str = "comparable_metrics_unavailable" , dry_run : bool = True
347+ ) -> dict [str , Any ]:
348+ """Return a successful, source-owned unavailable queue snapshot.
349+
350+ This is deliberately not an exception: optimization requires two trusted
351+ comparable P3 observations. Until they exist, the console must show an
352+ unavailable source rather than silently retaining stale tasks or marking
353+ an accepted P1 acquisition as a watcher failure.
354+ """
355+ snapshot = research_task_source_snapshot (
356+ [],
357+ context_available = False ,
358+ computed_at = datetime .now (timezone .utc ).strftime ("%Y-%m-%dT%H:%M:%SZ" ),
359+ )
360+ snapshot ["errors" ] = sorted (set (snapshot ["errors" ] + [reason ]))
361+ return {
362+ "status" : "ok" ,
363+ "dry_run" : dry_run ,
364+ "findings" : 0 ,
365+ "issues" : [],
366+ "errors" : 0 ,
367+ "research_task_source_snapshot" : snapshot ,
368+ }
369+
370+
334371def main () -> int :
335372 try :
336373 input_path = resolve_input_path (
@@ -342,7 +379,8 @@ def main() -> int:
342379 print (json .dumps ({"status" : "error" , "error" : str (exc )}, sort_keys = True ))
343380 return 2
344381 if input_path is None :
345- print (json .dumps ({"status" : "skipped" , "reason" : "strategy metrics input not configured" }, sort_keys = True ))
382+ result = no_comparable_metrics_result (reason = "metrics_input_not_configured" )
383+ print (json .dumps (result , ensure_ascii = False , sort_keys = True ))
346384 return 0
347385 terminal_path_text = os .environ .get ("STRATEGY_WATCH_TERMINAL_STATUS_PATH" , "" ).strip ()
348386 terminal_path = None
@@ -357,7 +395,8 @@ def main() -> int:
357395 return 2
358396 if not input_path .exists ():
359397 if terminal_path is None or not terminal_path .is_file ():
360- print (json .dumps ({"status" : "skipped" , "reason" : "strategy metrics input not found — this is expected when the source repository has not yet published metrics" }, sort_keys = True ))
398+ result = no_comparable_metrics_result ()
399+ print (json .dumps (result , ensure_ascii = False , sort_keys = True ))
361400 return 0
362401 try :
363402 terminal = load_payload (terminal_path )
0 commit comments