Preserve diagnostics in live-mode failure payloads
The previous hardening pass still dropped source diagnostics and data-quality context once live-mode serialized a dual-lane failure. Keep those fields when a structured CombinedSignalFailure reaches the websocket layer so consumers can distinguish provider mismatch, stale data, and other degraded cases even when no final signal exists.
Constraint: Follow-on fix after 63858bf should stay minimal and not reopen unrelated executor/calendar work
Rejected: Fold this into a larger amend of the prior commit | history is already shared and the delta is a single behavioral correction
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When failure exceptions carry structured diagnostics, live serializers must preserve them instead of flattening to a generic message
Tested: python -m pytest web_dashboard/backend/tests/test_executors.py web_dashboard/backend/tests/test_services_migration.py web_dashboard/backend/tests/test_api_smoke.py orchestrator/tests/test_market_calendar.py orchestrator/tests/test_live_mode.py orchestrator/tests/test_application_service.py orchestrator/tests/test_quant_runner.py orchestrator/tests/test_llm_runner.py -q
Tested: python -m compileall orchestrator web_dashboard/backend
Tested: npm run build (web_dashboard/frontend)
Not-tested: real websocket consumers against provider-backed failure paths
This commit is contained in:
parent
a4def7aff9
commit
eb2ab0afcf
|
|
@ -59,9 +59,11 @@ class LiveMode:
|
|||
|
||||
@staticmethod
|
||||
def _serialize_error(*, ticker: str, date: str, exc: Exception) -> dict:
|
||||
reason_codes = []
|
||||
if isinstance(exc, ValueError) and "both quant and llm signals are None" in str(exc):
|
||||
reason_codes = list(getattr(exc, "reason_codes", ()) or ())
|
||||
if not reason_codes and isinstance(exc, ValueError) and "both quant and llm signals are None" in str(exc):
|
||||
reason_codes.append(ReasonCode.BOTH_SIGNALS_UNAVAILABLE.value)
|
||||
source_diagnostics = dict(getattr(exc, "source_diagnostics", {}) or {})
|
||||
data_quality = getattr(exc, "data_quality", None)
|
||||
return {
|
||||
"contract_version": CONTRACT_VERSION,
|
||||
"ticker": ticker,
|
||||
|
|
@ -76,9 +78,9 @@ class LiveMode:
|
|||
"degradation": {
|
||||
"degraded": bool(reason_codes),
|
||||
"reason_codes": reason_codes,
|
||||
"source_diagnostics": {},
|
||||
"source_diagnostics": source_diagnostics,
|
||||
},
|
||||
"data_quality": None,
|
||||
"data_quality": data_quality,
|
||||
}
|
||||
|
||||
async def run_once(self, tickers: List[str], date: Optional[str] = None) -> List[dict]:
|
||||
|
|
|
|||
Loading…
Reference in New Issue