debt: D1–D7 工程债清理(Bronze 血缘/预测类型统一/Matches 拆分/Repository 治理/导航单源等) #10

Merged
shangfangjian merged 7 commits from debt-cleanup-d1-d7 into main 2026-09-21 19:57:48 +08:00
Collaborator

基于 main @ f6c0145,逐项修复评审报告列出的 D1–D7 工程债,每项独立提交:

改动摘要

D1 — events 成功路径血缘(P1) 3a9f3f5

  • 新增 _write_events_bronze:插入/变更更新成功后写 RawEvent(幂等键=上游 id,缺失时合成 LEAGUE:home:away:date)+ DataLineage(transform_name=events_ingest)
  • 每联赛每批次一个 batch_id,批内 seen-set 去重;Bronze 写入失败仅 warning,不破坏采集主流程
  • 新增回归测试 tests/test_events_bronze.py(6 例),变异测试验证接线有效

D2 — 统一预测结果类型(P1) 5c7fdce

  • PredictResult 扩展 mode/agent_outputs/status/latency/tokens/raw 等字段,multi/baseline 全部返回它
  • MultiPredictResult 变为 PredictResult 别名(保留 R4 源码守卫标记与 re-export)
  • 路由层删除 isinstance(result, dict) 分支,统一属性访问;API JSON 名称与语义不变

D3 — 拆分 Matches.tsx(P2) 52d6786

  • 1386 行拆为 pages/matches/ 下 types.ts/ui.tsx/hooks/useMatchesList.ts/hooks/useMatchPredict.ts/components/MatchPredictPanel.tsx/components/MatchDetailSection.tsx
  • Matches.tsx 降至 279 行(<300);行为不变,共享 error 状态保持在页面级

D4 — Repository 空壳治理(P2) 4514ef4

  • 新增 MatchRepository.find_by_league_and_date_range / find_finished_with_stats(含 stats 预加载),TeamRepository.get_or_create 支持 name_zh
  • bzzoiro events/standings/stats 三管线 Team/League/Match 查找全部走 Repository;UoW 提交仍归调用方
  • Standing/RawEvent/Lineage 管线内私有读写保留(不强行 Repository 化);docstring 纠正误导性声明

D5 — agent_outputs 类型(P3) 17e99a4

  • Mapped[list[dict] | dict | None] 对齐真实 JSON 形状 + 注释;无列/迁移变更

D6 — Admin 导航单源(P3) 18c8911

  • 新增 admin/nav.ts:NAV_ITEMS 单一数组派生侧栏/命令面板/面包屑
  • 修复三份并行配置的漂移(data-pipeline 缺失、系统/系统设置命名、评估与监控排序)

D7 — 限流/KeyRing 单进程说明(P3) d9aeff2

  • app.py lifespan 在 APP_ENV=production 时一次性 logger.warning(不退出、不引入 Redis);key_ring.py docstring 补充多 worker 后果

验证

  • 后端 pytest 全量:257 passed, 1 skipped(基线一致)
  • 前端 tsc + vite build 通过
  • D1 变异测试双向验证(禁用插入路径/更新路径接线,幸存测试恰好为无关用例)

手动验证建议

  1. 触发一次 events 采集,检查 raw_events/data_lineage 表新增记录(batch_id 形如 bzzoiro-events-E0-…)
  2. 前端 /matches 预测(single/multi/baseline)确认响应字段与改前一致
  3. /admin 各页侧栏、命令面板(Ctrl+K)、面包屑三处导航一致性
  4. 生产环境启动观察一条限流提醒日志

已知未做

  • 限流/KeyRing 仍为进程内实现,未引入 Redis(按规格明确不做)
  • agent_outputs 历史 dict 形状数据未做迁移清洗(类型已兼容)
基于 main @ f6c0145,逐项修复评审报告列出的 D1–D7 工程债,每项独立提交: ## 改动摘要 ### D1 — events 成功路径血缘(P1) 3a9f3f5 - 新增 `_write_events_bronze`:插入/变更更新成功后写 RawEvent(幂等键=上游 id,缺失时合成 `LEAGUE:home:away:date`)+ DataLineage(transform_name=events_ingest) - 每联赛每批次一个 batch_id,批内 seen-set 去重;Bronze 写入失败仅 warning,不破坏采集主流程 - 新增回归测试 tests/test_events_bronze.py(6 例),变异测试验证接线有效 ### D2 — 统一预测结果类型(P1) 5c7fdce - PredictResult 扩展 mode/agent_outputs/status/latency/tokens/raw 等字段,multi/baseline 全部返回它 - MultiPredictResult 变为 PredictResult 别名(保留 R4 源码守卫标记与 re-export) - 路由层删除 isinstance(result, dict) 分支,统一属性访问;API JSON 名称与语义不变 ### D3 — 拆分 Matches.tsx(P2) 52d6786 - 1386 行拆为 pages/matches/ 下 types.ts/ui.tsx/hooks/useMatchesList.ts/hooks/useMatchPredict.ts/components/MatchPredictPanel.tsx/components/MatchDetailSection.tsx - Matches.tsx 降至 279 行(<300);行为不变,共享 error 状态保持在页面级 ### D4 — Repository 空壳治理(P2) 4514ef4 - 新增 MatchRepository.find_by_league_and_date_range / find_finished_with_stats(含 stats 预加载),TeamRepository.get_or_create 支持 name_zh - bzzoiro events/standings/stats 三管线 Team/League/Match 查找全部走 Repository;UoW 提交仍归调用方 - Standing/RawEvent/Lineage 管线内私有读写保留(不强行 Repository 化);docstring 纠正误导性声明 ### D5 — agent_outputs 类型(P3) 17e99a4 - Mapped[list[dict] | dict | None] 对齐真实 JSON 形状 + 注释;无列/迁移变更 ### D6 — Admin 导航单源(P3) 18c8911 - 新增 admin/nav.ts:NAV_ITEMS 单一数组派生侧栏/命令面板/面包屑 - 修复三份并行配置的漂移(data-pipeline 缺失、系统/系统设置命名、评估与监控排序) ### D7 — 限流/KeyRing 单进程说明(P3) d9aeff2 - app.py lifespan 在 APP_ENV=production 时一次性 logger.warning(不退出、不引入 Redis);key_ring.py docstring 补充多 worker 后果 ## 验证 - 后端 pytest 全量:257 passed, 1 skipped(基线一致) - 前端 tsc + vite build 通过 - D1 变异测试双向验证(禁用插入路径/更新路径接线,幸存测试恰好为无关用例) ## 手动验证建议 1. 触发一次 events 采集,检查 raw_events/data_lineage 表新增记录(batch_id 形如 bzzoiro-events-E0-…) 2. 前端 /matches 预测(single/multi/baseline)确认响应字段与改前一致 3. /admin 各页侧栏、命令面板(Ctrl+K)、面包屑三处导航一致性 4. 生产环境启动观察一条限流提醒日志 ## 已知未做 - 限流/KeyRing 仍为进程内实现,未引入 Redis(按规格明确不做) - agent_outputs 历史 dict 形状数据未做迁移清洗(类型已兼容)
WorkBuddy added 7 commits 2026-09-21 19:55:10 +08:00
- 新增 _events_record_id: 上游 id 缺失时用 (league:home:away:date) 合成稳定幂等键
- 新增 _write_events_bronze: best-effort 写 RawEvent(幂等) + Lineage(matches/events_ingest)
- ingest 插入与变更更新后触发;同批 seen 集合防重复;基础设施失败只 warning
- TDD: 6 测试(插入/合成键/幂等跳过/变更更新/无变化不写/失败不拖垮),双变异验证通过
- PredictResult 扩展可选字段 mode/agent_outputs/agent_weights/prompt_tokens/completion_tokens
- MultiPredictResult 变为 PredictResult 别名(保留 R4 守卫标记与 re-export)
- baseline 改返回 PredictResult(修复 backtest 对 baseline AttributeError 的潜伏 bug)
- 预测路由单一属性映射,删除全部 isinstance(result, dict) 分支
- _persist_baseline 属性化,baseline upsert 语义不变(prompt_version/token/latency 同前)
- TDD: 5 新测试 + test_baseline.py 属性化;全量 257 passed
- pages/matches/types.ts: Match/Prediction/AgentReport + 常量(LEAGUES/STATUS_META/AGENT_LABELS 等)
- pages/matches/ui.tsx: Spinner/SkeletonRows/Switch/日期分组工具(Switch 自组件体内提升到模块级)
- pages/matches/hooks/useMatchesList.ts: 列表筛选/游标分页/进行中比赛,竞态防护语义不变
- pages/matches/hooks/useMatchPredict.ts: 预测状态机(连点/竞态/中止/超时)+ 可读错误文案
- pages/matches/components/MatchPredictPanel.tsx: 预测弹窗全套(过程可视化/结果/专家意见)
- pages/matches/components/MatchDetailSection.tsx: MatchRow(原内联行 JSX 抽出)+ 详情面板
- Matches.tsx 组装页 279 行(< 300);error state 共享行为与拆分前一致
- 验证: tsc + vite build 通过,渲染逻辑原样搬迁
- 新增 admin/nav.ts: 唯一配置源 NAV_ITEMS(to/label/group/icon/hideFromSidebar)
- COMMAND_PALETTE_PAGES / ROUTE_LABELS / NAV_SECTIONS 全部由其派生
- 删除 AdminLayout 中三份平行清单(已出现漂移: data-pipeline 不在侧栏、
  「系统」vs「系统设置」命名不一致、monitoring/eval 顺序两处相反)
- 已知微差: 命令面板「评估与监控」组内顺序统一为侧栏口径(eval 在前)
- 行为不变: 路由/标签/分组标题均保持现状;data-pipeline 保持仅面板可达
- repositories.py 新增 MatchRepository.find_by_league_and_date_range /
  find_finished_with_stats(含 stats 预加载),TeamRepository.get_or_create
  支持 name_zh
- bzzoiro events/standings/stats 三条管线的联赛、球队、比赛查找与批量预载
  全部改走 Repository;事务提交仍由调用方 UnitOfWork 控制
- Standing/RawEvent/Lineage 管线内私有读写保留在本模块(不强行 Repository 化)
- 模块 docstring 纠正为准确表述,移除「已全面 Repository 化」的误导性声明
- Mapped[list[dict] | dict | None]:multi 模式存专家报告列表,
  历史数据/兼容路径可能存 dict;加注释说明形状来源
- 仅类型标注修正,列类型(JSONB)与数据、迁移均不变
- app.py lifespan:APP_ENV=production 时 logger.warning 提醒
  进程内 rate-limit/KeyRing 仅单进程有效(不 sys.exit、不引入 Redis)
- key_ring.py docstring 补充多 worker 不共享的后果说明
- deps.py 注释已具备(单进程有效,生产前置 Nginx),无需改动
shangfangjian merged commit 3056a95ef4 into main 2026-09-21 19:57:48 +08:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: shangfangjian/Profeto#10