The city card only needs the provider to interpret the latest METAR or official observation. Deterministic fields such as the high-temperature center, model cluster note and fallback risks are already available server-side, so the stream request now asks DeepSeek for only the observation read and concise reasoning.
Constraint: City cards still need a complete payload for both Chinese and English UI modes
Rejected: Keep generating the full decision schema in the stream | too much model output for every card
Rejected: Retry failed streams by default | it can double latency and the fallback can use partial streamed text
Confidence: high
Scope-risk: moderate
Tested: pytest tests/test_web_observability.py::test_city_ai_stream_request_only_asks_provider_for_observation_read tests/test_web_observability.py::test_city_ai_fallback_reasoning_identifies_fast_evidence_mode tests/test_web_observability.py::test_city_ai_partial_json_trims_dangling_taf_clause tests/test_web_observability.py::test_city_ai_schema_completion_trims_dangling_taf_clause -q
Tested: npm run build
The city decision fallback path is generated when the full DeepSeek city-airport read has not completed, so the reasoning copy now labels the state as fast evidence mode instead of saying the AI read is normal.
Constraint: Fallback output may use only DEB, model cluster, and latest observation evidence
Rejected: Keep 'AI read normal' wording | it implies a completed AI interpretation when the fallback path is active
Confidence: high
Scope-risk: narrow
Tested: pytest tests/test_web_observability.py::test_city_ai_fallback_reasoning_identifies_fast_evidence_mode tests/test_web_observability.py::test_city_ai_partial_json_trims_dangling_taf_clause tests/test_web_observability.py::test_city_ai_schema_completion_trims_dangling_taf_clause -q
City AI can return a partially streamed JSON string when the provider truncates output. The fallback previously kept an unfinished clause such as '但TAF显示', which made the forecast explanation look broken even though earlier evidence was usable.
Constraint: Provider JSON can be truncated after useful fields have already streamed
Rejected: Drop all partial AI text | would lose valid METAR interpretation already returned before truncation
Confidence: high
Scope-risk: narrow
Tested: pytest city AI truncation regression tests
Tested: npm run build
Not-tested: Live DeepSeek provider response