# 策略执行结果持久化与查询实施计划 ## 实施原则 - 只修改 `zhixing-system`;保留用户已有的 `CONTEXT.md` 和 ADR 工作区变更。 - 先锁定数据库事务、批次状态和 HTTP 响应测试,再接入前端交互。 - 复用已有 `EvaluateZhixingB1`、`PostgresMarketDataReader` 和 shared UI,不复制公式 逻辑或网络 transport。 - 任何重跑都必须通过“策略 + 目标日”业务键清空旧结果;不要用插入多版本结果来 规避唯一约束。 - 后台任务只承担当前进程内异步执行;不得在本任务擅自引入任务队列、定时器或新的 外部服务。 ## 1. 规划复核与数据库契约 - [x] 将 `prd.md`、`design.md`、本文件从头读一遍,确认产品决策、验收标准和实现 细节没有重复或冲突。 - [x] 阅读 `.trellis/spec/backend`、`.trellis/spec/frontend` 及 cross-layer guide, 确认 migration、HTTP、前端类型和测试边界。 - [x] 设计并实现 `0002_selection_results`:`selection_run`、`selection_run_item`、 `selection_signal`、唯一约束、状态索引、JSONB details 和安全 downgrade。 - [x] 更新 `modules/market_data/infrastructure/schema.py` metadata,使 Alembic 离线/在线上下文包含新表。 验证: ```bash cd zhixing-server uv run alembic check uv run pytest tests/integration/test_market_data_migration.py ``` 回滚点:migration 或 schema metadata 不一致时只回滚新 migration 和 selection 表, 不修改 `0001_market_data`。 ## 2. 领域端口与 PostgreSQL 适配器 - [x] 在 selection domain 增加批次状态、股票 item、持久化查询模型和明确端口协议。 - [x] 为 `PostgresMarketDataReader` 增加读取当前有效执行股票集合的能力,使用目标日、 `market_sync_batch.strategy_eligible`、active stock 和 bar/basic 完整性约束。 - [x] 在清理旧结果前完成市场同步资格预检;目标日没有可用合格同步批次时返回 `market_data_not_ready`,保留已有结果不做破坏性变更。 - [x] 新增 selection PostgreSQL repository:短事务创建/删除/完成 run、记录 item 和 signal、按 run 或业务键读取;写入 details 时保持 JSON 可序列化。 - [x] 以 advisory transaction lock、终态检查和 `rerun` 参数实现首次执行、重复执行、 运行中冲突;清理和创建必须在同一事务。 验证: ```bash cd zhixing-server uv run pytest tests/unit/selection/test_postgres_runs.py uv run pytest tests/unit/selection/test_postgres_reader.py ``` 回滚点:若 SQL 适配器无法通过 fake connection 测试,保留纯领域端口和 migration, 先修适配器,不触碰已有市场数据写入代码。 ## 3. 全股票池执行用例与异步服务 - [x] 实现 `RunZhixingB1`:准备 run、读取有效股票、逐只调用已有评估用例、保存 item 和全部信号、汇总并完成 run。 - [x] 为 selected/no_signal/insufficient_history/missing_target_bar/data_error 建立 明确计数和终态映射;单股失败不影响其他股票,批次级异常收敛为 failed。 - [x] 为后台执行提供可注入的 service/worker 入口,确保 HTTP 响应提交后才调度,异常 时更新持久化状态;避免把数据库连接对象跨请求/跨线程复用。 - [x] 为首次执行、重跑清理、重复运行冲突、失败重试和多分类信号编写应用测试。 验证: ```bash cd zhixing-server uv run pytest tests/unit/selection/test_run.py uv run pytest tests/unit/selection/test_evaluate.py ``` ## 4. HTTP 接口与后端契约测试 - [x] 在 `selection/presentation/http.py` 定义请求和响应 Pydantic 模型,稳定声明日期、 状态、计数、coverage、失败 item 和 signal details。 - [x] 实现 `POST /api/v1/selection/runs`,成功返回 `202 + run_id`;将 `run_in_progress`、`rerun_confirmation_required`、输入错误和数据库错误映射为稳定 HTTP 响应。 - [x] 实现 `GET /api/v1/selection/runs/{run_id}` 和按策略/日期查询结果的 GET 端点; 无当前结果返回 `status=no_data`,不要制造假的成功结果。 - [x] 在顶层 router 挂载 selection router,保持 `/api/v1` 唯一目录入口;依赖使用 `Settings` 注入并提供测试 override。 - [x] 用 `TestClient(create_app())` 覆盖真实路由、202、冲突、无数据、轮询和终态 JSON。 验证: ```bash cd zhixing-server uv run pytest tests/test_selection_http.py ``` ## 5. 前端 feature 与交互 - [x] 新增 `features/selection/api/selection.types.ts`、`selection.api.ts`、 `selection.query.ts`,实现结果查询、run 查询/轮询和触发 mutation。 - [x] 新增 selection 页面及结果表/统计卡片/重跑确认 Dialog,覆盖初次执行、成功、 无命中、失败、部分成功、查询错误和运行中状态。 - [x] 为“选股策略”启用 `/selection` 路由和导航,保持 HomeShell 的布局及可访问性; 不让未实现的其他导航入口误显为可用。 - [x] 重跑或失败重试按钮只打开确认框;取消不调用 POST,确认后才传 `rerun=true`, 并在返回的 run 完成后刷新结果查询。 - [x] 同一股票多 category 用独立 badge/行展示,details 只显示后端稳定字段。 - [x] 更新页面测试和路由相关测试,使用 query hook mock,不依赖真实后端。 验证: ```bash cd zhixing-web pnpm format:check pnpm lint pnpm typecheck pnpm test pnpm build ``` ## 6. 全量质量检查与交付门禁 - [x] 运行后端 Ruff、Pyright、pytest;运行前端格式、lint、typecheck、test、build。 - [x] 检查 `rg -n "except Exception|fetch\(|xg_composite"`,确认没有吞异常、页面直 接请求或旧策略运行时依赖。 - [x] 检查 migration downgrade、重复执行事务、run status 与前端轮询是否一致。 - [x] 使用 `task.py validate` 校验任务清单和上下文 manifests,再由 `trellis-check` 做最终规格/跨层检查。 ## 风险与回滚点 - 新表/适配器失败:只回滚 `0002_selection_results` 和 selection 新代码,不撤销市场 数据 migration 或用户既有修改。 - 后台任务进程崩溃:当前 run 可能停在 `running`;必须在页面可见并记录为后续恢复 机制,不将其当作成功。 - 全股票池逐只读取过慢:保留结果契约和端口,后续在 reader/application 层做批量读 取;本任务不通过放宽历史数据或减少股票池来掩盖性能问题。