migration: preserve review journal alerts and assistant slice

This commit is contained in:
leefer
2026-07-31 11:55:27 +08:00
parent b3df070481
commit 38de3de0a3
20 changed files with 1323 additions and 773 deletions
@@ -0,0 +1,60 @@
# 切片 09:我的复盘、自选、笔记、交易日志、提醒与复盘助手
> 基线:`b3df070`(切片 08
> 回档标签:`xiaobai-preservation-slice-09-20260731`
> 结论:源码、API、数据库、账户隔离、真实页面及全量回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片只机械移动原版复盘、提醒和复盘助手实现,没有从`next/`取用代码,也没有修改自选、笔记、交易日志、提醒、会员灰化、LLM 上下文或流式协议。
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|---|---|---|
| `assistant_agent.py` | `app/backend/features/review/agent.py` | 根级模块指向同一模块对象 |
| `DashboardService`提醒方法 | `app/backend/features/alerts/facade.py` | `AlertServiceMixin` |
| `DashboardService`复盘方法 | `app/backend/features/review/service.py` | `ReviewServiceMixin` |
| `ReviewDatabase`提醒方法 | `app/backend/features/alerts/repository.py` | `AlertRepositoryMixin` |
| `ReviewDatabase`复盘方法 | `app/backend/features/review/repository.py` | `ReviewRepositoryMixin` |
| 五个 POST/流式入口 | `app/backend/features/alerts/http.py``review/http.py` | HTTP Mixin |
原版已经存在的`AlertService``TradeJournalService`、Repository Port 与 SQLite Adapter 继续保留为唯一底层实现。本切片没有制造第二套提醒或交易日志服务。
## 2. 源码等价与必要适配
- `assistant_agent.py`与正式 Agent 文件 SHA-256 一致,根级兼容模块与正式 Agent 是同一模块对象。
- 5 个提醒编排方法、8 个复盘编排方法、6 个提醒 Repository 方法和 13 个复盘 Repository 方法均与原版无位置信息 AST 一致。
- 五个 HTTP 方法只把全局`SERVICE`改为 Mixin 的`self.application_service`;状态码、字段、异常和流式事件写法不变。
- `backend.features.alerts``backend.features.review`仅对旧底层服务采用延迟导出,避免`database -> feature package -> sqlite adapter -> database`初始化循环;外部`from ... import AlertService/TradeJournalService`接口不变。
- 公共`RequestHandler._write_stream_event`继续保留,因为问师和复盘助手共同使用,且现有测试直接覆盖;统一传输层留到切片 10。
## 3. API 与数据库差分
- 原版`8790`和迁移版`8791`使用正式数据库的两个临时副本,未写正式数据库。
- 固定日期下自选、全部复盘笔记、交易日志、提醒中心及复盘助手历史共 5 个鉴权接口,状态码与业务 JSON 完全一致。
- 两版均为 62 个 schema 对象;`watchlist``review_notes``trade_entries``alerts``assistant_messages``users``system_settings``llm_usage`逐行一致。
- 真实浏览器在迁移版临时副本中新增一条交易记录,弹窗正确关闭并显示短提示“交易记录已保存”;没有写正式数据库。
- 未调用真实`/api/assistant/chat`,避免外部模型波动和 LLM 用量写入;Agent、流式累积与权限路径由源码等价和单元测试覆盖。
## 4. 真实浏览器检查
- 1920×1080 检查我的复盘完整布局,自选 6 只、交易日志、每日复盘三个独立输入框和最近复盘均可访问,无横向溢出。
- 添加自选与交易日志弹窗居中可用;交易日志保存后没有出现超长空弹窗。
- 提醒中心正常展示筛选、新建提醒和提醒记录。
- 管理员会员账号显示完整可用的复盘助手;临时普通账号显示相同界面、顶部“复盘助手仅对会员开放”,下方快捷问题、输入框和发送按钮均灰化禁用。
- 临时普通账号自选和交易日志均为空,证明用户私有数据没有串到管理员账号。
- 夜间模式背景为`rgb(18, 20, 22)`,1920×1080 页面无横向溢出,控制台无错误。
- 截图`review-workspace-night-1920x1080.png` SHA-256`bc803305a391930a0aafd68062bab6de86eca14612799eebfda220cf2ad0798e`
## 5. 自动验证与保留边界
| 验证 | 结果 |
|---|---:|
| 原版`python -m unittest discover -s tests -q` | 231 项通过 |
| 迁移版`python -m unittest discover -s tests -q` | 287 项通过 |
| `python -m unittest tests.test_preservation_slice_review_alerts -q` | 7 项通过 |
| `npx.cmd playwright test --reporter=dot` | 45 项通过(2.2 分钟) |
| `git diff --check` | 通过 |
- 前端 DOM、页面 JS、CSS 与移动端行为未改动,统一归位延至切片 10。
- `demo_data.py``static/heaven-loading.js`、五个疑似无引用前端函数和`wencai_saved_queries`继续保留到切片 11 试删。
- 没有修改`next/`、正式数据库、Docker/NAS 或`8765`服务。
@@ -0,0 +1,60 @@
{
"all_equal": true,
"endpoints": [
{
"name": "review watchlist",
"method": "GET",
"endpoint": "/api/watchlist?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "29c001cc6859312fd90082d0fb83818d263827e28ec21157b94c415b71c45078",
"migrated_sha256": "29c001cc6859312fd90082d0fb83818d263827e28ec21157b94c415b71c45078",
"equal": true,
"first_difference": null
},
{
"name": "all review notes",
"method": "GET",
"endpoint": "/api/notes?scope=all",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "a2a1f08610d017de0e46080a1268f72b734eeb80f9cada311d7e03eb1416656a",
"migrated_sha256": "a2a1f08610d017de0e46080a1268f72b734eeb80f9cada311d7e03eb1416656a",
"equal": true,
"first_difference": null
},
{
"name": "trade journal through fixed date",
"method": "GET",
"endpoint": "/api/trades?end_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "77287b34046e22748e94e61ead841e157f6b63f08de1b2fe61f5d715b2e989a4",
"migrated_sha256": "77287b34046e22748e94e61ead841e157f6b63f08de1b2fe61f5d715b2e989a4",
"equal": true,
"first_difference": null
},
{
"name": "alert center through fixed date",
"method": "GET",
"endpoint": "/api/alerts?status=all&as_of=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "8807772f2b611ea8b95033aa19cae84f08b08e92d76fff8e3cd5b79966ea04f4",
"migrated_sha256": "8807772f2b611ea8b95033aa19cae84f08b08e92d76fff8e3cd5b79966ea04f4",
"equal": true,
"first_difference": null
},
{
"name": "review assistant history",
"method": "GET",
"endpoint": "/api/assistant/messages",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "eef46741adfc3a9f76294d3b78f37a45f113092ac9d44ee77c7a038a88ff09a1",
"migrated_sha256": "eef46741adfc3a9f76294d3b78f37a45f113092ac9d44ee77c7a038a88ff09a1",
"equal": true,
"first_difference": null
}
]
}
@@ -0,0 +1,32 @@
[
{
"name": "review watchlist",
"method": "GET",
"endpoint": "/api/watchlist?trade_date=2026-07-30",
"payload": null
},
{
"name": "all review notes",
"method": "GET",
"endpoint": "/api/notes?scope=all",
"payload": null
},
{
"name": "trade journal through fixed date",
"method": "GET",
"endpoint": "/api/trades?end_date=2026-07-30",
"payload": null
},
{
"name": "alert center through fixed date",
"method": "GET",
"endpoint": "/api/alerts?status=all&as_of=2026-07-30",
"payload": null
},
{
"name": "review assistant history",
"method": "GET",
"endpoint": "/api/assistant/messages",
"payload": null
}
]
@@ -0,0 +1,75 @@
{
"all_equal": true,
"schema": {
"object_count": 62,
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"equal": true
},
"tables": [
{
"table": "watchlist",
"original_count": 6,
"migrated_count": 6,
"original_sha256": "070161f5cdcc33addf289f11cb0ae54bfc0d669a39426fc33398b64512dba2fe",
"migrated_sha256": "070161f5cdcc33addf289f11cb0ae54bfc0d669a39426fc33398b64512dba2fe",
"equal": true
},
{
"table": "review_notes",
"original_count": 3,
"migrated_count": 3,
"original_sha256": "86ed485c2ce922e3434f8ac742d38431ef430b5c22024cacb6f64f0e8e71ee98",
"migrated_sha256": "86ed485c2ce922e3434f8ac742d38431ef430b5c22024cacb6f64f0e8e71ee98",
"equal": true
},
{
"table": "trade_entries",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true
},
{
"table": "alerts",
"original_count": 2,
"migrated_count": 2,
"original_sha256": "37b46fb4a754cf9c6179b1be88eed7f5a5398ddfc87160f41ded622ffc313c88",
"migrated_sha256": "37b46fb4a754cf9c6179b1be88eed7f5a5398ddfc87160f41ded622ffc313c88",
"equal": true
},
{
"table": "assistant_messages",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true
},
{
"table": "users",
"original_count": 3,
"migrated_count": 3,
"original_sha256": "4a0f135bef8ebae454693d3f40e1157d84d814d18d849f33e2e760ed1d8a7f89",
"migrated_sha256": "4a0f135bef8ebae454693d3f40e1157d84d814d18d849f33e2e760ed1d8a7f89",
"equal": true
},
{
"table": "system_settings",
"original_count": 1,
"migrated_count": 1,
"original_sha256": "86d333a5c7feaf7111cd79b2db29513326a9b0d3781607f78bf633579e2ca8e9",
"migrated_sha256": "86d333a5c7feaf7111cd79b2db29513326a9b0d3781607f78bf633579e2ca8e9",
"equal": true
},
{
"table": "llm_usage",
"original_count": 72,
"migrated_count": 72,
"original_sha256": "03a070316a125cef904bbfb2bb06b06e792242d5713142e70354402c741393c3",
"migrated_sha256": "03a070316a125cef904bbfb2bb06b06e792242d5713142e70354402c741393c3",
"equal": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

+5 -5
View File
@@ -1,6 +1,6 @@
{
"schema_version": 1,
"updated_at": "2026-07-31T08:55:17+08:00",
"updated_at": "2026-07-31T11:52:29+08:00",
"status": "active",
"migration_mode": "behavior_preserving_source_migration",
"source_of_truth": "current_original_webapp_runtime_and_source",
@@ -9,10 +9,10 @@
"failed_roots": [
"next"
],
"current_slice": "slice-09-review-watchlist-notes-journal-alerts-assistant",
"last_completed_slice": "slice-08-heaven-trend-fortune-heart",
"last_checkpoint": "xiaobai-preservation-slice-08-20260731",
"next_action": "capture_slice-09_review_private_data_and_assistant_contracts_then_move_original_implementations",
"current_slice": "slice-10-frontend-shell-pages-components-css-mobile",
"last_completed_slice": "slice-09-review-watchlist-notes-journal-alerts-assistant",
"last_checkpoint": "xiaobai-preservation-slice-09-20260731",
"next_action": "capture_frontend_asset_dependency_map_then_relocate_original_shell_pages_components_css_and_mobile_responsibilities_without_runtime_changes",
"authoritative_documents": [
"AGENTS.md",
"docs/migration/原版保真迁移总纲.md",
+14 -1
View File
@@ -1,6 +1,6 @@
# 小白复盘保真迁移账本
> 当前状态:正式迁移,切片08“问天、观势、观气与观心”已完成
> 当前状态:正式迁移,切片09“复盘、自选、交易日志、提醒与复盘助手”已完成
本账本是上下文恢复和人工审计的连续记录。任何迁移提交必须在同一提交中更新本文件及
`保真迁移状态.json`
@@ -61,6 +61,9 @@
| 公开`游资skills` | 运行资产 | 问师模型库 | 原样保留 | `app/游资skills/` | 190个文件逐路径和SHA-256一致 | 已复制 |
| `heaven_agent.py``heaven_engine.py`与问天服务 | 业务计算 | 观势、观气、观心 | 机械移动并保留兼容别名 | `app/backend/features/heaven/` | Agent文件哈希、引擎定义AST、20个服务方法、6个API及真实动画页面等价 | 已移动 |
| 问天历史方法 | 持久化 | 三类解读历史与当日解运复用 | 按职责机械移动 | `app/backend/features/heaven/repository.py` | 5个方法AST一致;62个schema对象及6张关键表逐行一致 | 已移动 |
| `assistant_agent.py`与复盘服务 | 业务服务 | 我的复盘、自选、交易日志与复盘助手 | 机械移动并保留兼容别名 | `app/backend/features/review/` | Agent文件哈希、8个服务方法AST、5个真实API及会员/非会员页面等价 | 已移动 |
| 复盘、自选、交易日志与助手消息方法 | 持久化 | 用户私有复盘数据 | 按职责机械移动并保持Mixin原接口 | `app/backend/features/review/repository.py` | 13个方法AST一致;相关表逐行一致;浏览器账户隔离通过 | 已移动 |
| 提醒编排与提醒持久化方法 | 业务服务/持久化 | 提醒中心与策略跟踪提醒 | 按职责机械移动 | `app/backend/features/alerts/` | 5个服务方法、6个Repository方法AST及真实API一致 | 已移动 |
处置只允许:`原样保留``移动``合并重复``待定``确认废弃`
@@ -158,6 +161,16 @@
- 回档:标签`xiaobai-preservation-slice-08-20260731`
- 完整证据:`docs/migration/evidence/slice-08/README.md`
已完成切片:`slice-09-review-watchlist-notes-journal-alerts-assistant`
- 原版基线:提交`b3df070`,即切片08回档点。
- 迁移范围:复盘助手Agent、5个提醒编排方法、8个复盘编排方法、19个持久化方法及5个HTTP入口。
- 兼容边界:根级`assistant_agent.py`指向正式模块对象;提醒与交易日志旧服务继续作为唯一底层实现;包导出采用延迟加载以切断初始化循环。
- API与数据库:5个固定输入真实API完全一致;62个schema对象及8张关键表逐行一致。
- 验收:原版231项、迁移版287项Python测试、7项切片源码等价测试、45项Playwright及1920×1080会员/非会员真实页面通过。
- 回档:标签`xiaobai-preservation-slice-09-20260731`
- 完整证据:`docs/migration/evidence/slice-09/README.md`
## 决策记录
| 日期 | 决策 | 原因 |