Commit Graph

269 Commits

Author SHA1 Message Date
2569718930@qq.com fd59cd018d Harden Open-Meteo rate limiting 2026-05-18 00:13:51 +08:00
2569718930@qq.com bd21b05fbc 完全移除预热(prewarm)功能
- 删除 src/utils/prewarm_dashboard.py
- 删除 scripts/prewarm_dashboard_cache.py、prewarm_dashboard_worker.py
- docker-compose.yml 移除 polyweather_prewarm 服务
- runtime_coordinator.py 移除预热循环启动逻辑
- web/core.py 移除 prewarm status 上报
- web/routers/system.py 移除 /api/system/prewarm 端点
- web/services/system_api.py 移除 run_system_prewarm
- city_runtime.py DEFAULT_PREWARM_CITIES 改名为 DEFAULT_STATUS_CITIES
- 清理 env.example、测试、VPS .env 中的预热配置
2026-05-17 22:43:17 +08:00
2569718930@qq.com 1ab10a9c90 Add MGM hourly support for Ankara models 2026-05-17 19:19:12 +08:00
2569718930@qq.com d39534dff4 机场推送重构:观测缓存分离 + 全城市覆盖 + 四路并发
- 新增 force_refresh_observations_only 模式:机场推送仅刷新 METAR/AMOS
  观测缓存,多模型预报缓存保留 15 分钟,杜绝 Open-Meteo 429 限流后
  DEB 回退到实测温度的 bug
- 砍掉夜间静默和温度状态机,每条新观测无条件推送
- HIGH_FREQ_AIRPORT_CITIES 从 19 城扩到 30 城(新增 11 个美国城市)
- 美国城市走 airport_primary (MADIS) 优先取温
- 机场周期从串行改为 ThreadPoolExecutor(max_workers=4),周期时间从
  ~120s 压缩到 ~33s

Constraint: 单核 VPS 安全并发上限
Tested: docker compose up -d --build polyweather 重建后推送正常
2026-05-17 18:04:05 +08:00
2569718930@qq.com 2d9aa576dd feat: implement scan terminal mobile dashboard components and data management logic 2026-05-17 15:32:47 +08:00
2569718930@qq.com a83d9e7649 feat: implement 60-second analysis cache TTL for high-frequency airport cities 2026-05-17 13:41:44 +08:00
2569718930@qq.com b27bedbca3 修复网站 API 阻塞与积分同步问题
- uvicorn 改用 import string 格式启动 4 workers,防止数据采集阻塞 event loop
- prewarm 去掉 --force-refresh,仅依赖缓存预热避免每 5 分钟全量采集
- 积分变动时同步写入 Supabase user_metadata,避免前端回退路径失败时显示 0 积分
- /api/auth/me 积分解析增加 Supabase email 回退路径
2026-05-16 13:15:30 +08:00
2569718930@qq.com b45010a92e feat: implement runway observations dashboard panel, add telegram alert utility, and create city payload service 2026-05-15 15:37:25 +08:00
2569718930@qq.com 4cc579ccb3 feat: add AMSC runway observations 2026-05-15 01:41:49 +08:00
2569718930@qq.com 2ee00f8016 MiMo AI 能力扩展:TAF解读、概率分布解读、异常检测、市场概览
AI 解读字段扩展:
    - 新增 taf_read_zh/en:解读机场预报中影响今日峰值窗口的变化
    - 新增 probability_read_zh/en:描述概率分布形态(最高桶、偏左/偏右)
    - stream max_tokens 900→1200 容纳新输出字段
    - 缓存 key 简化为 METAR原文+观测时间,大幅提升命中率
    - 兜底函数补全 TAF 和概率字段的确定性生成

    异常检测:
    - 纯数学计算,零 AI 延迟:实测温度 vs 全部模型预测上下限
    - 三级告警:breakout_above / breakout_below / deviation

    市场概览:
    - 新增 POST /api/scan/terminal/overview(MiMo 批量解读,缓存10分钟)
    - 前端 MarketOverviewBanner 可折叠横幅(顶栏与标签栏之间)
    - 移动端适配 640px/768px 断点,暗色/亮色双主题

    Scope-risk: MEDIUM — 170 测试通过,TypeScript 零错误,ruff 零告警
    Tested: python -m pytest -q (170 passed), npx tsc --noEmit (0 errors), ruff check .
2026-05-14 22:41:31 +08:00
2569718930@qq.com 6c08a68413 @
性能与用户体验全面优化

    前端性能:
    - 移除 Three.js 依赖(~600KB),天气粒子改为纯 CSS 动画 + Canvas 2D
    - Google Fonts 切换为 next/font 自托管,消除跨域字体请求
    - 合并 ScanTerminalLightTheme.module.css (37KB) 到主 CSS,亮/暗主题统一用 CSS 变量
    - 新增 /api/dashboard/init 聚合端点,首次加载 4 次往返 → 1 次
    - 添加 Service Worker 静态资源缓存,修复 PWA manifest 配置

    用户体验:
    - 新增全局错误边界 error.tsx / global-error.tsx,崩溃不再白屏
    - 决策卡和城市详情的更新时间改为相对时间("15秒前"),每秒自动刷新
    - 数据陈旧时状态标签从青色切换为琥珀色提示

    DEB 算法增强:
    - 市场扫描路径接入 Open-Meteo 多模型数据(ECMWF/GFS/ICON/JMA/HRDPS 等)
    - MAE 计算加入时间衰减(decay_factor=0.85),近期模型误差权重更高

    Scope-risk: MEDIUM — 全量 170 测试通过,前端 TypeScript/build 通过,ruff 零告警
    Tested: python -m pytest -q (170 passed), npx tsc --noEmit (0 errors), npm run build (success), ruff check .
@
2026-05-14 21:31:05 +08:00
2569718930@qq.com 37494a7192 @
将 web/routes.py 拆分为模块化 router + service 架构

    - 新增 web/app_factory.py 集中注册 7 个域名 router
    - 新增 web/routers/ 薄壳路由层(auth/city/system/scan/ops/payments/analytics)
    - 新增 web/services/ 业务函数下沉(每域独立 service 文件)
    - web/routes.py 缩减为 city_runtime 的兼容重导出 facade
    - analysis_service.py/app.py 适配新入口并清理冗余导入

    Scope-risk: LOW — 全量 170 测试通过,router 注册顺序与原路由一致
    Tested: python -m pytest -q (170 passed), ruff check . (All checks passed)
@
2026-05-14 20:01:26 +08:00
2569718930@qq.com 02add6d994 feat: implement city weather detail API routing, dashboard data models, and monitoring infrastructure 2026-05-14 14:21:28 +08:00
2569718930@qq.com c006d13fea MonitorPanel 从独立 API 改为复用 DashboardStore 数据,砍掉 /api/m 和 /m/json 2026-05-14 00:43:19 +08:00
2569718930@qq.com c5fdb93ae5 监控页:后端 30s 缓存 + 前端 loading 态 2026-05-14 00:29:51 +08:00
2569718930@qq.com 2202f8e211 砍掉 /m HTML 页面,只保留 /m/json 给 React 组件用 2026-05-14 00:23:03 +08:00
2569718930@qq.com fc48795299 监控页从 iframe 改为原生 React 组件:无加载延迟,30s JSON 轮询 2026-05-14 00:18:26 +08:00
2569718930@qq.com 22b414f69e 监控页时间改为用户本地时间(JS toLocaleTimeString) 2026-05-14 00:10:43 +08:00
2569718930@qq.com 9dd59ceb4e 修复 ruff 风格:多行语句、bare except → except Exception 2026-05-13 23:55:54 +08:00
2569718930@qq.com a9b1449680 放弃 Jinja2,改用 f-string 直接拼 HTML,零模板引擎依赖 2026-05-13 23:54:53 +08:00
2569718930@qq.com a7ba7aed3a Debug:简化 context 排查 Jinja2 500 2026-05-13 23:46:18 +08:00
2569718930@qq.com 1240fbb673 跑道数据改用 tuple 避免 Jinja2 dict unhashable 错误 2026-05-13 23:41:31 +08:00
2569718930@qq.com d56889c2e5 修复 Jinja2 模板 dict 访问方式和条件表达式 2026-05-13 23:38:06 +08:00
2569718930@qq.com b94037f328 路由 /monitor → /m,URL 更短 2026-05-13 23:24:26 +08:00
2569718930@qq.com a221b3e969 用 Python 重写市场监控网页版:FastAPI+Jinja2+HTMX,复用 _analyze() 2026-05-13 23:19:49 +08:00
AmandaloveYang e344fae75f 首尔/釜山 AMOS 数据缓存 TTL 从 300s 降至 60s,对齐官网 1 分钟刷新频率
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 17:28:53 +08:00
2569718930@qq.com 8075fb66b7 AMOS 增加 info 级别日志追踪数据流
- weather_sources.py: _attach_korean_amos_data 记录 fetch 开始、成功/失败、温度/跑道数据
- amos_station_sources.py: _amos_get_page 记录页面匹配/不匹配
- amos_station_sources.py: fetch_amos_official_current 记录 HTML 获取和解析
- analysis_service.py: _analyze 记录 AMOS 数据是否到达分析层

重启后端后在日志中搜索 "AMOS" 可追踪完整数据流:
  AMOS: fetching for city=seoul
  AMOS page matched icao=RKSI length=...
  AMOS fetch_amos_official_current: got HTML for RKSI...
  AMOS: got data for city=seoul temp_c=... source=...
  AMOS _analyze: found amos data for city=seoul temp_c=...
2026-05-10 19:46:26 +08:00
2569718930@qq.com 40cd8fc2a6 修复机场观测面板不显示 + 放宽 AMOS 展示条件 2026-05-10 19:06:22 +08:00
2569718930@qq.com e23a90a961 修复釜山 AMOS 数据获取 + 跑道面板容错
AMOS 页面用 JS 切换机场,GET 参数无效。新增策略:
- 先 GET 建立 session,再 POST form data 切换机场
- 尝试多种 form data 组合(icao/stn/airport/code)
- 回退到 GET 参数尝试

跑道面板容错:
- 无温度数据时仍展示跑道风/能见度/RVR
- 温度缺失显示 "--" 而非隐藏整行
- analysis_service 输出条件放宽:有 temp_c 或 runway_obs 即可

Tested: python -m ruff check ., npx tsc --noEmit
2026-05-10 18:39:37 +08:00
2569718930@qq.com ba352feb34 首尔/釜山机场报文优先使用 AMOS(更新更快)
- analysis_service.py:AMOS 数据覆盖 airport_current 的 raw_metar、wind、pressure
- source_label 设为 "AMOS"(区别于 aviationweather.gov METAR)
- stale_for_today 强制 false(AMOS 数据本身证明了时效性)
- observation_time 优先使用 AMOS 时间戳
- AI 读取的 city_snapshot.current.raw_metar 来自 AMOS 跑道传感器

优先级:AMOS raw_metar > aviationweather.gov METAR(首尔/釜山)

Reason: AMOS 直连韩国机场系统,延迟更低,更新更快
2026-05-10 18:18:40 +08:00
2569718930@qq.com 04b2f0e4a3 AMOS 数据接入分析层和 AI 预测判定
问题:AMOS 数据在采集层取出后从未被 _analyze() 读取,AI 无法看到跑道级数据

修复:
- analysis_service.py:_analyze() 新增 AMOS 温度读取优先级
  观测来源顺序:结算源 > AMOS跑道传感器 > METAR > MGM > NMC
- AMOS 数据自动覆盖 current.wind_speed_kt、current.pressure_hpa、current.raw_metar
- 输出新增 "amos" 字段携带完整跑道数据(temp_source、runway_temps)
- scan_terminal_service.py:AI prompt 的 current 区块新增 pressure_hpa 和 observation_source
- AI 现在知晓数据来自 AMOS 跑道传感器(observation_source="amos"),可据此判断数据权威性

数据流:
  AMOS fetch -> raw["amos"] -> _analyze() -> current.observation_source="amos"
  -> result["amos"] -> _build_city_ai_prompt -> city_snapshot.current
  -> AI reads runway sensor temp/wind/pressure as authoritative observation

Tested: python -m ruff check ., npx tsc --noEmit
2026-05-10 18:16:10 +08:00
2569718930@qq.com e2bea367a1 校准漂移检测增加日志告警 + 更新架构文档
- core.py:drift.drifted=true 时输出 loguru warning,包含 delta% 和 sample 数量
- data-architecture-review.md:标记 2 项误诊(METAR TTL 实际 600s、轮询已有 AbortController 保护)
- 剩余真正待办:校准自动重训练(需算力)、缓存键细化(低优先级)
2026-05-10 17:06:43 +08:00
2569718930@qq.com b3ea8dcfa7 数据链路 P1 修复:ETag 缓存 + 校准漂移检测
P1-5 ETag 支持:
- 后端新增 _etag_middleware:GET /api/* 自动返回 ETag (MD5)
- 支持 If-None-Match 请求头,匹配时返回 304 + 30s Cache-Control
- 前端 cache: no-store → default,浏览器自动处理 ETag/304 节省带宽

P1-6 校准漂移检测:
- probability_calibration.py 新增 check_calibration_drift()
- 对比最近 200 条 daily_records 的 CRPS 与校准基线
- 漂移 >15% 时返回 warning 提示重新训练
- 集成到 /api/system/status 的 probability.drift 字段

Tested: python -m ruff check ., npx tsc --noEmit
2026-05-10 16:54:48 +08:00
2569718930@qq.com c0bb2acf78 修复数据链路 P0 瓶颈:缓存炸弹、Context 重渲染、LGBM 循环、TTL 不匹配
P0-1 sessionStorage 限制:
- writeCityDetailCacheBundle 只保留最近 3 个城市的详情
- 避免 3-10MB JSON 序列化阻塞主线程

P0-2 Context 拆分:
- 新增 CityDetailsContext 独立管理 cityDetailsByName 变更
- 新增 useCityDetails hook,只订阅详情的组件不再因 cities/proAccess 变化重渲染
- DashboardStoreContext 保持不变,向后兼容

P0-3 扫描终端 TTL:
- SCAN_TERMINAL_PAYLOAD_TTL_SEC 30s → 120s
- 匹配 ThreadPoolExecutor(4) x 60 城的实际重算耗时

P0-4 LGBM 循环依赖:
- LGBM 预测值不再作为 DEB 输入参与权重计算
- 保留为独立参考字段 lgbm.prediction 输出给前端展示
- 消除 DEB → LGBM 训练 → DEB 的循环

新增 docs/data-architecture-review.md 完整数据链路审查报告

Tested: npx tsc --noEmit, python -m ruff check .
2026-05-10 16:48:28 +08:00
2569718930@qq.com 9635387beb 移除日历视图:功能与决策卡重叠,维护成本高于价值
- 删除 CalendarView.tsx、calendar-action-utils.ts 及其测试文件
- 删除 ScanTerminalCalendar.module.css
- ScanTerminalDashboard:移除日历 tab 按钮、日历渲染分支、ContentView 类型中的 calendar
- ScanTerminalLightTheme:清理所有 .scan-calendar-* 规则(~40 行)
- scan-root-styles.ts:移除 ScanTerminalCalendar 导入

同时完善地理排序:
- scan_terminal_filters.py:market_region_from_tz_offset 细化为 7 个区域(东亚/东南亚/中亚/西亚/欧洲非洲/南美/北美)并增加 sort_order
- scan_terminal_city_row.py:传递 trading_region_sort
- dashboard-types.ts:增加 trading_region_sort 字段
- decision-utils.ts:sortRowsByUserTime 按 trading_region_sort 优先排序

Rejected: keep-calendar-view, calendar-actions-overlap-with-decision-cards
Tested: npx tsc --noEmit, python -m ruff check .
2026-05-10 15:48:18 +08:00
2569718930@qq.com 30faac989c 秒开 AI 预测最高温:preview 事件提前下发确定性预测值
之前 predicted_max 只在 AI 流式 final 事件返回后才显示(10-25 秒),
但后端 fallback 早在 1ms 内就算好了 cluster median / DEB 中枢。
现在 preview 事件同步下发确定性 predicted_max + range_low/high,
前端也在 fallback payload 中自动从 multi_model + DEB 计算预测值,
用户点击城市后 ~100ms 即可看到 AI 预测最高温。
2026-05-07 21:04:26 +08:00
2569718930@qq.com 7b82ba68df 回退 _analyze_summary 中未启用的 LGBM 增强步骤
LGBM 当前默认禁用 (POLYWEATHER_LGBM_ENABLED=false),predict_lgbm_daily_high
直接返回 None,在 _analyze 中也未实际参与 DEB 计算,_analyze_summary 无需重复。

Rejected: 在 LGBM 正式启用前,_analyze_summary 不应包含会被跳过的 LGBM 调用
2026-05-06 18:30:47 +08:00
2569718930@qq.com a684586cb4 统一 DEB 数据源为单一计算路径
getModelView 优先使用根级 detail.deb.prediction 保证与 AI 证据面板一致,
_build_city_detail_payload 补上缺失的 deb 和 multi_model_daily 字段,
_analyze_summary 补上 LGBM 增强步骤使其与 _analyze 产出相同的 DEB 值。

Constraint: 三个入口 (panel/full/summary) 的 DEB 必须经过同一套 calculate_dynamic_weights + LGBM 重算流程
Tested: ruff + tsc 全过
2026-05-06 18:24:15 +08:00
2569718930@qq.com 2f73828d4d 重构城市决策卡 hero 布局:去除 sticky 固定效果,右侧改为三指标并列对比
将 scan-ai-city-hero 从"左重右轻"改为左右均衡布局,右侧从单一预计高温数字
替换为当前温度/预计最高温/峰值时间三列并排指标卡,中间列高亮为主指标。
移除冗余的 pills 行和隐藏的 mobile-priority div,新鲜度条改为水平单行。
同步更新亮色主题 CSS 新增 metrics 样式。修复 fallback 模块未使用变量。

Constraint: dark/light 双主题完整覆盖
Scope-risk: hero 高度缩减约 30%,需确认移动端 MobileDecisionCard 不受影响
2026-05-06 17:57:40 +08:00
2569718930@qq.com 4ed9321756 修复流式 AI 请求 max_tokens 不足导致 JSON 截断
此前流式 650 tokens,只够 4 个文字字段。新增 predicted_max
等 6 个字段后,中文解读经常超出上限致 JSON 不完整,触发重试。
现提升至 900 tokens(主请求 1200),并更新测试断言。
2026-05-06 16:51:31 +08:00
2569718930@qq.com a1d5435dd7 强化 HKO 天文台观测的 AI 解读能力
- HKO instruction 从纯否定句改为正向指导,明确告知 AI 可用数据维度
  (温度、最高/最低温、湿度、10分钟风速风向)
- AI 输入 current 对象新增 wind_speed_kt/wind_dir/humidity 字段,
  HKO 和 METAR 城市均受益
- 提示词统一补充湿度分析要求
2026-05-06 16:48:05 +08:00
2569718930@qq.com a4ce450dbc 修复 system_prompt 源代码可读性,\uXXXX 转回正常中文
此前为避免 curly quote 问题用 \uXXXX 转义序列写入中文,运行正确但
源码不可读。现在改为正常 UTF-8 中文,引号改用「」避免与 Python
字符串定界符冲突。
2026-05-06 16:15:28 +08:00
2569718930@qq.com eb42d644a3 DEB 降级为模型集群中的普通一员,AI 不再照搬 DEB 做预测
此前 DEB 以独立字段 deb.prediction 传给 AI,提示词又要求"必须综合 DEB",
导致 AI 直接输出 DEB 值而非独立判断。改动:
- 移除 AI 输入中的独立 deb 字段,DEB 只作为 model_cluster.sources 中的
  一条记录 (model: "DEB (fusion)"),与其他模型平等
- 提示词改为:以模型集群集中区间为基线,用报文观测信号独立判断上修/下修/维持
- 流式/非流式提示词均强调"不要直接照搬 DEB 的值,差异是正常的"
- 回退路径改用模型集群中位数作为默认预测,DEB 仅作为备选参考
2026-05-06 16:03:22 +08:00
2569718930@qq.com c296bbb789 AI 机场报文解读流式请求增加最高温预测输出
此前 build_city_ai_stream_request 只要求 AI 输出 metar_read + reasoning,
明确禁止生成 predicted_max/range/confidence 等数值字段,流式解读只有
文字没有温度预测。现在让流式请求同步输出 predicted_max、range_low、
range_high、unit、confidence、final_judgment,使前端报文解读面板能
直接展示 AI 预测的今日最高温及置信区间。
2026-05-06 15:38:58 +08:00
2569718930@qq.com 6c203bee60 This version of Antigravity is no longer supported. Please upgrade to receive the latest features. 2026-05-01 11:27:16 +08:00
2569718930@qq.com 6da72b5488 This version of Antigravity is no longer supported. Please upgrade to receive the latest features. 2026-04-29 19:10:25 +08:00
2569718930@qq.com 5b32e71f5d This version of Antigravity is no longer supported. Please upgrade to receive the latest features. 2026-04-29 18:52:55 +08:00
2569718930@qq.com 20516000a2 Clarify scan terminal service boundaries
The scan terminal service had accumulated cache, payload, filtering, AI prompt, AI merge, METAR gate, ranking, and city-row construction details in one file. This splits those stable responsibilities into focused modules while preserving the endpoint payload shape and existing behavior.

Constraint: User-visible behavior and release version must remain unchanged for this internal refactor

Rejected: Rewrite the terminal scan flow around a new abstraction | too risky while production behavior is being stabilized

Confidence: high

Scope-risk: moderate

Directive: Keep scan_terminal_service.py as orchestration; add detailed rule changes to the focused modules instead of re-growing the service file

Tested: py_compile for extracted modules; ruff check .; pytest tests/test_scan_terminal_modules.py tests/test_web_observability.py; full pytest; npm run test:business; npm run build; git diff --cached --check
2026-04-28 17:13:45 +08:00
2569718930@qq.com b122e7cbae Stabilize the decision workspace data boundaries
The scan terminal had grown into overlapping CSS, request-state, AI-provider, and city-card data responsibilities. This refactor separates those boundaries without changing product behavior: CSS modules are split by surface, city AI prompt/provider/fallback logic is isolated, and scan terminal request state now has reusable RemoteData adapters plus business-state tests.

Constraint: Preserve existing global scan-terminal class names and API responses during the refactor

Constraint: No new dependencies; keep this as a file-boundary cleanup

Rejected: Introduce React Query now | higher migration risk than the requested lightweight query-client path

Rejected: Rewrite AI stream behavior | progressive/fallback states are product-sensitive and were only adapter-split

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Keep AI stream state changes covered by business snapshots before changing fallback/cache wording

Tested: npm run test:business; npx tsc --noEmit; npm run build; python pytest -q; ruff check; py_compile targeted city AI modules

Not-tested: Live DeepSeek provider network replay and browser visual QA
2026-04-28 14:45:34 +08:00
2569718930@qq.com 51969d0b4a Keep scan terminal lint clean after helper split
The AI helper extraction left a stale private helper import in the scan terminal service. Removing it keeps CI aligned with the current call graph without changing runtime behavior.

Constraint: CI runs ruff F401 as a blocking check.
Confidence: high
Scope-risk: narrow
Reversibility: clean
Tested: .\.codex-tmp\pydeps\bin\ruff.exe check .
Not-tested: Full backend test suite; change is import-only.
2026-04-28 08:38:00 +08:00