migration: audit uncertain code and prepare handoff

This commit is contained in:
leefer
2026-07-31 16:48:13 +08:00
parent dec3cd1236
commit faac60b1a6
23 changed files with 979 additions and 1166 deletions
+2
View File
@@ -7,5 +7,7 @@
3. [`保真迁移状态.json`](保真迁移状态.json):机器可读当前状态和下一步。
4. [`保真迁移账本.md`](保真迁移账本.md):连续检查点、资产处置和决策记录。
5. [`next失败冻结记录.md`](next失败冻结记录.md):失败实现的隔离边界。
6. [`人工维护与本地切换指南.md`](人工维护与本地切换指南.md):迁移版目录、验证、数据边界、人工验收、切换与回退。
7. [`evidence/slice-11/README.md`](evidence/slice-11/README.md):当前候选的试删审计和全量自动验收结果。
`重建迁移章程.md``next/`内阶段文档均是失败过程历史记录,不再指导后续实施。
@@ -0,0 +1,80 @@
# 切片 11:不确定代码审计、全量验收与交接准备
> 基线:`dec3cd12365df5e7d4c391369f14c457cf56d7d9`
> 候选回档标签:`xiaobai-preservation-slice-11-candidate-20260731`
> 当前结论:自动验收完成,等待用户人工验收;尚未执行正式切换、Docker或NAS部署
## 1. 本切片做了什么
本切片不增加功能、不调整视觉,也不继续拆分业务代码。它逐项审计切片10保留的待定资产,
把有完整证据的无效实现放入可单独回档的试删候选,并为人工接管和后续切换准备文档。
试删候选:
- `app/demo_data.py`:没有运行导入、动态注册、数据库或配置责任的旧演示数据构造器。
- `app/frontend/heaven-loading.js`:页面未加载的旧问天动画;正式入口继续使用
`frontend/pages/heaven/loading-v2.js`
- 五个只有定义、没有消费者的前端函数:`commonReviewColumns``outcomeClass`
`screenerResultMatchesSelection``selectRegime``showHeartRitualCurtain`
明确保留:
- `wencai_saved_queries`表及三个Repository方法。它们承担历史数据库兼容和用户隔离责任,
当前库为空不能证明其他部署库也为空。
- 与试删函数相邻但证据不足的DOM、状态字段和CSS。没有为追求行数继续连带删除。
逐项指纹、引用扫描、责任判断和恢复位置见`uncertain-code-audit.md`
## 2. 自动验证结果
| 验证 | 结果 |
|---|---:|
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
| 迁移版`python -m unittest discover -s tests -q` | 298项通过 |
| 历史切片与前端/清理专项复核 | 通过 |
| 迁移版JavaScript语法检查 | 24个文件通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过(1.6分钟) |
| 固定只读API差分 | 21个端点全部一致 |
| 数据库差分 | 62个schema对象、21张关键表全部一致 |
| `git diff --check` | 通过 |
早期切片的五个前端源码测试原本要求与未试删的`static/app.js`逐字符一致。本切片把它们统一到
`preservation_helpers.assert_frontend_runtime_matches_audited_baseline`:只允许审计登记的五段原始
行号被删除,任何其他新增、删除、重排或内容变化仍会使全部历史测试失败。
完整API和数据库结果分别见`api-diff.json``database-diff.json`,二者`all_equal`均为`true`
## 3. 真实浏览器验收
- 桌面端复核情绪周期、智能选股三个工作区、问天日间/夜间和加载资源;控制台无新增
error或warn,页面无横向溢出。
- 问天只加载`/pages/heaven/loading-v2.js`,未请求已试删的`/heaven-loading.js`
- 观势、观气、观心星空与八卦节点、原动画名称和可见行为保持不变。
- `390x844`逐一点击涨停池、智能选股、问师、问天、我的复盘五个移动入口;底部导航固定,
页面均可完整纵向滚动且没有文档级横向溢出。
- 观势、观气、观心三页均复核;观气滚动到底后“个人合参”和“五行对应行业”可达。
- 同账号、同数据库快照、同主题和同视口下,原版与迁移版问天布局和计算样式一致。
机器可读记录见`browser-acceptance.json`。截图和更广的桌面/移动基线继续沿用切片10证据目录。
## 4. 数据与部署边界
- API/数据库比较使用两个隔离副本:`slice11-final-original``slice11-final-migrated`
- 没有写入根目录正式`data/review.db`,没有修改`.env`或私有Skill。
- 没有占用`8765`,没有执行Docker构建、NAS测试或服务器切换。
- 原版根目录仍是正式运行基线;`app/`只是等待人工验收的候选。
- `next/`保持冻结,没有作为代码、样式、测试或文档来源。
## 5. 回档与最终确认
切片11提交和标签只代表“候选可验收”,不代表删除已被永久确认。人工验收前可按
`uncertain-code-audit.md`从切片10标签单独恢复任一候选;不需要回退其他已通过迁移切片。
用户人工确认后才允许:
1. 把试删候选状态改为“确认废弃”。
2. 建立最终完成标签。
3. 决定本地或Docker正式切换时间。
4. 另行制定根目录兼容外壳和旧实现的清理计划。
人工维护、验证、切换和回退步骤见`docs/migration/人工维护与本地切换指南.md`
@@ -0,0 +1,236 @@
{
"all_equal": true,
"endpoints": [
{
"name": "当前账号",
"method": "GET",
"endpoint": "/api/auth/me",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "33e0c08463d5f14a142840f894d92985135c6ce2bee22c93c4dde34dc433cf5b",
"migrated_sha256": "33e0c08463d5f14a142840f894d92985135c6ce2bee22c93c4dde34dc433cf5b",
"equal": true,
"first_difference": null
},
{
"name": "账号状态",
"method": "GET",
"endpoint": "/api/account/status",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "094530da01cbc633de4e2a09d1b3a58689ed9743d2ab2207c495e6c44781fc1e",
"migrated_sha256": "094530da01cbc633de4e2a09d1b3a58689ed9743d2ab2207c495e6c44781fc1e",
"equal": true,
"first_difference": null
},
{
"name": "全市场总览",
"method": "GET",
"endpoint": "/api/dashboard?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "565730fb75cec6f6758321074dfeba7bff19db6611476d511f9bc7257a5870f5",
"migrated_sha256": "565730fb75cec6f6758321074dfeba7bff19db6611476d511f9bc7257a5870f5",
"equal": true,
"first_difference": null
},
{
"name": "情绪周期历史",
"method": "GET",
"endpoint": "/api/sentiment/history?trade_date=2026-07-30&limit=9",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "1a577fb859a2fd06749169e1d0f08f78b51c5217b55506c7903487a956b6192b",
"migrated_sha256": "1a577fb859a2fd06749169e1d0f08f78b51c5217b55506c7903487a956b6192b",
"equal": true,
"first_difference": null
},
{
"name": "板块轮动历史",
"method": "GET",
"endpoint": "/api/rotation/history?trade_date=2026-07-30&limit=9",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "eaf3ac41f479c0f57f161546f197c1321721b4a8390486a916232fe6ea1d3d37",
"migrated_sha256": "eaf3ac41f479c0f57f161546f197c1321721b4a8390486a916232fe6ea1d3d37",
"equal": true,
"first_difference": null
},
{
"name": "集合竞价",
"method": "GET",
"endpoint": "/api/auction?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "5a6b643ab1d7e2285ae5667bca12e6ed887ba4aa7512ba989e0dcfb2032e755b",
"migrated_sha256": "5a6b643ab1d7e2285ae5667bca12e6ed887ba4aa7512ba989e0dcfb2032e755b",
"equal": true,
"first_difference": null
},
{
"name": "题材库",
"method": "GET",
"endpoint": "/api/themes?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "f45e218d9bff5191445fe45b03fc62f3d9c440b8353404ae4b54901c20929552",
"migrated_sha256": "f45e218d9bff5191445fe45b03fc62f3d9c440b8353404ae4b54901c20929552",
"equal": true,
"first_difference": null
},
{
"name": "人气热榜",
"method": "GET",
"endpoint": "/api/popularity?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "69987a80f02ac02bf9ff49b3a0a99782385f1933c643c9e3dbb5a75a1e20dd29",
"migrated_sha256": "69987a80f02ac02bf9ff49b3a0a99782385f1933c643c9e3dbb5a75a1e20dd29",
"equal": true,
"first_difference": null
},
{
"name": "龙虎榜",
"method": "GET",
"endpoint": "/api/dragon-tiger?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "9d19029f655813ed40a25deb0b3250423a40ae0ee779638ec90f85333f859c6f",
"migrated_sha256": "9d19029f655813ed40a25deb0b3250423a40ae0ee779638ec90f85333f859c6f",
"equal": true,
"first_difference": null
},
{
"name": "游资档案",
"method": "GET",
"endpoint": "/api/dragon-tiger/profiles",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "dfb1e534c018ec12fd8d8ee0e7fe0f234e73dc7715d7f0a948f74ef8d12d779a",
"migrated_sha256": "dfb1e534c018ec12fd8d8ee0e7fe0f234e73dc7715d7f0a948f74ef8d12d779a",
"equal": true,
"first_difference": null
},
{
"name": "智能选股工作区",
"method": "GET",
"endpoint": "/api/screener/setup?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "e33a10e94accda4948c2af53887ea97736697f588ee1a92f561aa5c4bb28c2fd",
"migrated_sha256": "e33a10e94accda4948c2af53887ea97736697f588ee1a92f561aa5c4bb28c2fd",
"equal": true,
"first_difference": null
},
{
"name": "策略持续跟踪",
"method": "GET",
"endpoint": "/api/screener/tracking?limit=12",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "f4476f53152b6a2ce01f2918da5999246cfd0ad7d0b71e80fdea8fa59c7456c2",
"migrated_sha256": "f4476f53152b6a2ce01f2918da5999246cfd0ad7d0b71e80fdea8fa59c7456c2",
"equal": true,
"first_difference": null
},
{
"name": "问师模型库",
"method": "GET",
"endpoint": "/api/mentors/setup?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "0ff7794fe45f49ab980221fa855b64c70d5c9b83c78ef86edc041e713490b626",
"migrated_sha256": "0ff7794fe45f49ab980221fa855b64c70d5c9b83c78ef86edc041e713490b626",
"equal": true,
"first_difference": null
},
{
"name": "问师历史",
"method": "GET",
"endpoint": "/api/mentors/messages?mentor_id=kobe92-perspective&trade_date=20260730",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "eef46741adfc3a9f76294d3b78f37a45f113092ac9d44ee77c7a038a88ff09a1",
"migrated_sha256": "eef46741adfc3a9f76294d3b78f37a45f113092ac9d44ee77c7a038a88ff09a1",
"equal": true,
"first_difference": null
},
{
"name": "问天初始化",
"method": "GET",
"endpoint": "/api/heaven/setup?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "c814c2004c7dd672c397887725af000c150693a50900bb0ce1aa94599af1a3c8",
"migrated_sha256": "c814c2004c7dd672c397887725af000c150693a50900bb0ce1aa94599af1a3c8",
"equal": true,
"first_difference": null
},
{
"name": "问天历史",
"method": "GET",
"endpoint": "/api/heaven/readings?mode=trend&limit=20",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "2aa83ea177bd5cb2351ac4f3a60fdcd17e02cfc14b5753e157e515f03fc2c6c1",
"migrated_sha256": "2aa83ea177bd5cb2351ac4f3a60fdcd17e02cfc14b5753e157e515f03fc2c6c1",
"equal": true,
"first_difference": null
},
{
"name": "自选追踪",
"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": "全部复盘笔记",
"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": "交易日志",
"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": "提醒中心",
"method": "GET",
"endpoint": "/api/alerts?status=all&as_of=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "01e8f169fbc8700313dbdf8379e682b78d7b372cfbee556e1d68f46cd6cbeecf",
"migrated_sha256": "01e8f169fbc8700313dbdf8379e682b78d7b372cfbee556e1d68f46cd6cbeecf",
"equal": true,
"first_difference": null
},
{
"name": "复盘助手历史",
"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,101 @@
{
"schema_version": 1,
"tested_at": "2026-07-31T16:10:00+08:00",
"runtime": {
"url": "http://127.0.0.1:8797/",
"root": "app",
"database": "app/data/backups/slice11-final-migrated/review.db",
"production_data_modified": false
},
"overall": true,
"desktop": {
"checked": true,
"views": [
"sentimentCycleView",
"screenerView",
"heavenView"
],
"themes": [
"light",
"dark"
],
"console_errors": 0,
"console_warnings": 0,
"horizontal_overflow": false
},
"mobile": {
"viewport": [
390,
844
],
"fixed_navigation": {
"selector": ".module-nav",
"position": "fixed",
"height": 58,
"bottom_offset": 0,
"primary_tab_count": 5
},
"views": [
{
"id": "limitPool",
"document_height": 1607,
"horizontal_overflow": false,
"vertical_content_reachable": true
},
{
"id": "screenerView",
"document_height": 1555,
"horizontal_overflow": false,
"vertical_content_reachable": true
},
{
"id": "mentorView",
"document_height": 961,
"horizontal_overflow": false,
"vertical_content_reachable": true
},
{
"id": "heavenView",
"document_height": 844,
"horizontal_overflow": false,
"vertical_content_reachable": true
},
{
"id": "reviewWorkspaceView",
"document_height": 1475,
"horizontal_overflow": false,
"vertical_content_reachable": true
}
],
"heaven_panels": [
{
"id": "trend",
"document_height": 844,
"vertical_content_reachable": true
},
{
"id": "fortune",
"document_height": 1730,
"vertical_content_reachable": true,
"bottom_content_checked": "五行对应行业"
},
{
"id": "heart",
"document_height": 1156,
"vertical_content_reachable": true
}
]
},
"preservation_comparison": {
"same_account": true,
"same_database_snapshot": true,
"same_theme": "dark",
"same_mobile_viewport": [
390,
844
],
"original_and_migrated_layout_equal": true,
"theme_toggle_icon_note": "原版和迁移版都保留切换后图标需重载才同步的既有行为;相同加载序列下结果一致。"
},
"manual_acceptance_required": true
}
@@ -0,0 +1,202 @@
{
"all_equal": true,
"schema": {
"object_count": 62,
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"equal": true
},
"tables": [
{
"table": "users",
"original_count": 3,
"migrated_count": 3,
"original_sha256": "4a0f135bef8ebae454693d3f40e1157d84d814d18d849f33e2e760ed1d8a7f89",
"migrated_sha256": "4a0f135bef8ebae454693d3f40e1157d84d814d18d849f33e2e760ed1d8a7f89",
"equal": true,
"excluded_columns": []
},
{
"table": "system_settings",
"original_count": 1,
"migrated_count": 1,
"original_sha256": "86d333a5c7feaf7111cd79b2db29513326a9b0d3781607f78bf633579e2ca8e9",
"migrated_sha256": "86d333a5c7feaf7111cd79b2db29513326a9b0d3781607f78bf633579e2ca8e9",
"equal": true,
"excluded_columns": []
},
{
"table": "watchlist",
"original_count": 6,
"migrated_count": 6,
"original_sha256": "070161f5cdcc33addf289f11cb0ae54bfc0d669a39426fc33398b64512dba2fe",
"migrated_sha256": "070161f5cdcc33addf289f11cb0ae54bfc0d669a39426fc33398b64512dba2fe",
"equal": true,
"excluded_columns": []
},
{
"table": "review_notes",
"original_count": 3,
"migrated_count": 3,
"original_sha256": "86ed485c2ce922e3434f8ac742d38431ef430b5c22024cacb6f64f0e8e71ee98",
"migrated_sha256": "86ed485c2ce922e3434f8ac742d38431ef430b5c22024cacb6f64f0e8e71ee98",
"equal": true,
"excluded_columns": []
},
{
"table": "trade_entries",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true,
"excluded_columns": []
},
{
"table": "alerts",
"original_count": 2,
"migrated_count": 2,
"original_sha256": "a496857f915d8ba0870274455182a2d7f180a931836b7078e9676dc0e7bbe430",
"migrated_sha256": "a496857f915d8ba0870274455182a2d7f180a931836b7078e9676dc0e7bbe430",
"equal": true,
"excluded_columns": []
},
{
"table": "assistant_messages",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true,
"excluded_columns": []
},
{
"table": "mentor_messages",
"original_count": 28,
"migrated_count": 28,
"original_sha256": "b906b776d575ff6fe459b2aa0e8b396267feed36d3d85f7edd7947b284482aeb",
"migrated_sha256": "b906b776d575ff6fe459b2aa0e8b396267feed36d3d85f7edd7947b284482aeb",
"equal": true,
"excluded_columns": []
},
{
"table": "mentor_preferences",
"original_count": 45,
"migrated_count": 45,
"original_sha256": "c19c7d05e6745e4f1787d1eed5f39d7e555ec24f8e490b585c19158edc2505ec",
"migrated_sha256": "c19c7d05e6745e4f1787d1eed5f39d7e555ec24f8e490b585c19158edc2505ec",
"equal": true,
"excluded_columns": []
},
{
"table": "heaven_readings",
"original_count": 31,
"migrated_count": 31,
"original_sha256": "e6cfc86f010fb182d7522bb99e5d268e826f93896035172120df51a011590951",
"migrated_sha256": "e6cfc86f010fb182d7522bb99e5d268e826f93896035172120df51a011590951",
"equal": true,
"excluded_columns": []
},
{
"table": "user_birth_profiles",
"original_count": 1,
"migrated_count": 1,
"original_sha256": "2a74d4b2edd3a730a46f17fb6ab3926575c42662c1d968643b0d54586ab68b13",
"migrated_sha256": "2a74d4b2edd3a730a46f17fb6ab3926575c42662c1d968643b0d54586ab68b13",
"equal": true,
"excluded_columns": []
},
{
"table": "sector_phase_overrides",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true,
"excluded_columns": []
},
{
"table": "screener_strategies",
"original_count": 36,
"migrated_count": 36,
"original_sha256": "872846dcb746446bda37723e63db737a2a0cf0540eb6a1da264012248887f4c5",
"migrated_sha256": "872846dcb746446bda37723e63db737a2a0cf0540eb6a1da264012248887f4c5",
"equal": true,
"excluded_columns": [
"updated_at"
]
},
{
"table": "screener_runs",
"original_count": 250,
"migrated_count": 250,
"original_sha256": "9f58ff2f85e5b85878153f7694161620d77cb9b0f351754f2974a8a0cc8ad8fb",
"migrated_sha256": "9f58ff2f85e5b85878153f7694161620d77cb9b0f351754f2974a8a0cc8ad8fb",
"equal": true,
"excluded_columns": []
},
{
"table": "strategy_tracks",
"original_count": 16,
"migrated_count": 16,
"original_sha256": "f0639b1386b69c92fd815f929864b3b2457a6bf4ca515bee2dca87e9ea29e8c4",
"migrated_sha256": "f0639b1386b69c92fd815f929864b3b2457a6bf4ca515bee2dca87e9ea29e8c4",
"equal": true,
"excluded_columns": []
},
{
"table": "auction_factors",
"original_count": 511914,
"migrated_count": 511914,
"original_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
"migrated_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
"equal": true,
"excluded_columns": []
},
{
"table": "popularity_factors",
"original_count": 232,
"migrated_count": 232,
"original_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
"migrated_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
"equal": true,
"excluded_columns": []
},
{
"table": "seat_aliases",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true,
"excluded_columns": []
},
{
"table": "reason_overrides",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true,
"excluded_columns": []
},
{
"table": "llm_usage",
"original_count": 72,
"migrated_count": 72,
"original_sha256": "03a070316a125cef904bbfb2bb06b06e792242d5713142e70354402c741393c3",
"migrated_sha256": "03a070316a125cef904bbfb2bb06b06e792242d5713142e70354402c741393c3",
"equal": true,
"excluded_columns": []
},
{
"table": "wencai_saved_queries",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true,
"excluded_columns": []
}
]
}
@@ -0,0 +1,79 @@
# 切片 11:不确定代码审计日志
> 审计基线:`dec3cd12365df5e7d4c391369f14c457cf56d7d9`
> 恢复标签:`xiaobai-preservation-slice-10-20260731`
> 原则:只有静态引用、动态注册、运行路径和兼容责任同时排除后才试删;其余继续保留
> 当前状态:试删后的自动、API、数据库和浏览器验收已通过,等待用户人工确认
本日志记录试删前的原位置、内容指纹、证据、决定和恢复方式。试删不等于永久废弃;自动回归通过后仍需用户在迁移版真实页面完成人工验收,才能把删除结论视为最终确认。
## 1. `app/demo_data.py`
- 类型:旧演示行情构造器,376行、17,199字节。
- SHA-256`fb69682d499993534e7ee029989b35cf512c455eec49e07d7b09658cddd9e028`
- 静态引用:运行代码、配置、启动入口、Docker、页面及后台任务均没有导入或调用`DEMO_LIMITS``build_demo_dashboard``build_demo_dragon_tiger``build_demo_stock_detail`
- 动态/注册路径:没有模块名字符串、插件注册或反射加载。
- 产品事实:`app/README.md`明确主行情不再回退演示数据;行情服务和Repository只负责排除历史`source=demo`缓存,未依赖本文件。
- 兼容责任:不参与数据库schema、历史记录解释或配置读取。
- 决定:进入试删。
- 恢复:从切片10标签恢复`app/demo_data.py`
## 2. `app/frontend/heaven-loading.js`
- 类型:旧版问天加载动画,642行、30,563字节。
- SHA-256`ee914762b893a89f745e9e705cac6840c1dbd6c5b68dc7a47620b8c4db3615c7`
- 静态引用:`app/frontend/index.html`只加载`/pages/heaven/loading-v2.js`,没有加载本文件。
- 动态/注册路径:没有脚本清单、页面注册表或运行时代码引用旧路径;新旧文件虽然都导出`window.HeavenLoadingCanvas`,但浏览器只能执行v2。
- 运行证据:切片10已覆盖观势、观气和观心解读加载动画,v2节点、动画名及可见行为与原版基线一致。
- 兼容责任:不是数据库、配置或历史数据资产。
- 决定:进入试删。
- 恢复:从切片10标签恢复该文件。
## 3. 五个疑似无引用前端函数
全前端非供应商JavaScript逐词扫描后,下列符号都只有定义本身一次;HTML、页面注册表、事件绑定、字符串查找、测试入口和其他脚本均无消费者:
| 函数 | 位置 | 原用途线索 | 决定 |
|---|---|---|---|
| `commonReviewColumns` | `frontend/shared/export.js` | 旧通用导出列定义;当前每个导出入口均显式传列 | 试删 |
| `outcomeClass` | `frontend/app.js` | 旧昨日涨停结果样式映射;当前渲染不调用 | 试删 |
| `screenerResultMatchesSelection` | `frontend/pages/screener/page.js` | 旧选股结果存在性包装;已由`activeScreenerResultEntry`直接承担 | 试删 |
| `selectRegime` | `frontend/pages/screener/page.js` | 旧阶段手动切换;当前阶段由盘后数据写入且无按钮绑定 | 试删 |
| `showHeartRitualCurtain` | `frontend/pages/heaven/page.js` | 旧观心幕帘过场;当前流程直接调用`activateHeartRises` | 试删 |
本次只删除这5个函数,不连带删除`selectedRegime``heartRitualCurtain`隐藏节点、`heartCurtainTimer`或相关CSS。后者与仍在使用的选股状态、观心节点和复合选择器相邻,尚不足以证明可独立删除,默认保留。
恢复:从切片10标签按上述文件恢复对应函数;源码映射可通过`docs/migration/evidence/slice-10/frontend-source-map.json`定位。
## 4. `wencai_saved_queries`及其方法
- 类型:历史兼容数据表及用户隔离Repository方法。
- 当前入口:问财前端和`/api/wencai*`已按用户决定取消;iFinD的`wencai()`能力仍由股池原因补全使用,但不依赖保存查询表。
- 保留责任:数据库初始化仍创建表和用户索引;`list_wencai_saved_queries``save_wencai_query``delete_wencai_saved_query`保持已有数据可读取;`test_ifind_features`明确验证跨用户隔离。
- 风险:当前数据库表为空不能证明所有用户历史库均为空;删除会改变62项schema契约并破坏旧库兼容。
- 决定:保留,不试删。只有未来正式数据库迁移、导出/归档和用户批准同时具备时才允许移除。
## 5. 试删验收门槛
每次试删后必须同时满足:
1. 全前端符号与资源引用扫描没有悬空消费者。
2. 全部JavaScript通过`node --check`
3. 原版231项测试继续通过,迁移版全量测试通过。
4. 21个固定只读API与数据库schema/关键表差分继续一致;明确批准删除的运行外文件不应改变API或数据库。
5. 45项Playwright通过,问天加载动画与智能选股流程无回归。
6. 用户使用迁移版完成最终人工页面验收。
任一项失败时,按本日志指向的切片10标签恢复对应候选,不把其他已通过候选一起回退。
## 6. 试删后结果
- 五个前端符号在全部非供应商JavaScript中的剩余引用均为0。
- 运行代码中没有`demo_data`导入;页面只请求`/pages/heaven/loading-v2.js`
- 24个现存前端JavaScript文件通过`node --check`
- 原版231项、迁移版298项Python测试和45项Playwright全部通过。
- 21个只读API、62个schema对象和21张关键表继续与原版一致。
- 桌面日间/夜间及390x844移动端真实页面检查通过,问天三页和观气底部内容可达。
- `wencai_saved_queries`及三个方法保持存在,并由清理契约测试持续保护。
因此上述删除保持“候选试删”状态;只有用户人工验收后才改为“确认废弃”。
@@ -0,0 +1,154 @@
# 小白复盘人工维护与本地切换指南
> 适用目录:`webapp/app/`
> 当前状态:迁移候选已完成自动验收,尚未获得最终人工验收,不得替换正式部署
## 1. 先确认哪个版本是正式版本
- 当前正式基线仍是`webapp/`根目录及根目录`data/review.db`
- `webapp/app/`是保真迁移候选,运行代码来自原版的移动、机械拆分和去重,不是重新开发。
- `webapp/next/`是已否决的冻结版本,禁止部署、继续开发或复制实现。
- 用户人工验收前,不要删除根级原版,不要让`app/`写入正式数据库,也不要修改NAS容器。
发生产品含义冲突时,依次以用户明确决定、原版真实运行、原版源码与数据、产品规格书为准。
## 2. 迁移版目录怎么找代码
```text
app/
server.py 进程兼容入口;正式实现装配在backend/
backend/bootstrap/ 路径、环境、配置、依赖组装和HTTP服务器
backend/http/ 鉴权、路由元数据、响应与静态资源传输
backend/features/ 按产品领域组织的服务和Repository
backend/data/ 数据网关、质量策略、实时聚合和供应商适配
backend/database/ SQLite连接、schema和组合Repository
backend/jobs/ 后台任务定义、状态、调度与重试
backend/llm/ 所有模型调用、流式传输、额度与审计边界
frontend/shared/ API、状态、Shell、组件和跨页能力
frontend/pages/ 每个产品页面的原版行为;问天样式也在对应目录
frontend/styles/ 原版七层样式和共享令牌
config/ 页面、功能、API、任务、字段和数据质量注册表
tests/ 单元、边界、保真差分和浏览器回归
tools/ 清单、API/数据库差分和保真运行工具
data/ 运行数据库、私有Skill和备份;不提交Git
游资skills/ 可公开的问师Skill
```
根级`app/*.py`多数是兼容导入壳。维护业务时先到`backend/features/<领域>/`找正式实现,
不要在兼容壳中新增第二套逻辑。所有浏览器网络请求必须继续经过
`frontend/shared/api.js`,所有LLM调用必须继续经过`backend/llm/`
## 3. 本地隔离启动
不要直接拿正式数据库做迁移验收。先创建一个目录并用SQLite backup API生成一致副本,或使用
`app/data/backups/`中专门的验收副本。然后在`webapp`根目录运行:
```powershell
python -u app\tools\run_preservation_runtime.py `
--runtime-root app `
--data-dir app\data\backups\manual-acceptance `
--port 8797
```
浏览器打开`http://127.0.0.1:8797/`。该命令不占用正式`8765`,并把数据库、私有Skill和
运行写入限制在指定测试目录。验收完成后先停止该进程,再处理测试副本。
## 4. 每次改动的最低流程
1. 阅读`AGENTS.md`、保真迁移状态、迁移账本和对应领域测试。
2.`config/pages.config.json``features.config.json`确认页面、功能和权限边界。
3. 只修改一个完整领域路径;不要同时在兼容壳和正式模块写实现。
4. 新增API时同步检查`config/api.config.json``backend/http/`的权限元数据。
5. 用户私有表必须包含并按`user_id`查询,补充跨账号隔离测试。
6. 行情字段必须登记来源、时间、单位、复权、新鲜度和降级规则,不允许静默换源。
7. 先跑领域测试,再跑下面的全量门槛,最后用真实浏览器检查桌面、夜间和移动端。
8. 更新迁移/维护文档后再提交;一个可回档节点只包含一个可以独立解释的改动。
## 5. 全量验证命令
原版基线:
```powershell
cd webapp
python -m unittest discover -s tests -q
```
迁移版:
```powershell
cd webapp\app
python -m unittest discover -s tests -q
npx.cmd playwright test --reporter=dot
```
JavaScript和Git差异:
```powershell
cd webapp\app
$files = Get-ChildItem frontend -Recurse -Filter *.js
foreach ($file in $files) { node --check $file.FullName }
cd ..
git diff --check
```
Playwright需要能够启动本机无头Edge。若测试停在浏览器启动前且没有`msedge`进程,先检查执行
环境是否禁止GUI/无头浏览器进程;这不是页面失败,不要通过删除测试或延长产品超时绕过。
API和数据库差分工具:
```text
app/tools/compare_preservation_apis.py
app/tools/compare_preservation_databases.py
```
运行前先查看脚本参数,并使用同一时点生成的原版/迁移版数据库副本。任何`all_equal=false`都应
阻止提交和切换。
## 6. 数据、密钥和私有内容
- SQLite数据库与`.env`中的`APP_ENCRYPTION_KEY`必须成对备份;密钥丢失后不能恢复加密字段。
- `data/private-mentor-skills/`只属于管理员本机/服务器,不进入Git和Docker镜像。
- 不要用文件管理器复制正在写入的`review.db`;使用SQLite backup API或停服后复制。
- 不要把Tushare、iFinD、LLM Token、账号密码、数据库副本或私有Skill提交到仓库。
- 切换期间只有一个数据库可以成为写入主库,禁止让原版与迁移版长期各写一份后再人工合并。
## 7. 人工验收清单
- 用同一账号、日期和主题对照原版与迁移版全部页面。
- 检查日间/夜间、1080P/4K、390像素移动端和浏览器缩放后的滚动与弹窗。
- 检查图表悬浮、股票/板块/题材/指数详情、全局搜索和日期切换。
- 检查选股三个工作区、策略跟踪、刷新后结果保持和候选来源隔离。
- 检查问师流式回答只出现一次、置顶排序、历史和会员限制。
- 检查问天三页全部过场、呼吸/铜钱、加载动画、历史和解读结果。
- 使用两个账号检查自选、笔记、交易日志、提醒和对话互不可见。
- 检查系统管理、会员期限、模型池、数据回补和后台任务状态。
人工验收发现差异时,记录页面、账号、日期、主题、视口、输入和截图;先对照原版复现,再判断
是迁移回归还是原版既有问题。
## 8. 获得批准后的本地切换方案
以下只是准备步骤,本次迁移没有执行:
1. 停止原版和迁移版进程,确认没有后台任务继续写库。
2. 对根目录正式数据库执行SQLite一致性备份,同时备份`.env`和私有Skill。
3. 把同一份最新正式数据恢复到`app/data/`,保持原`APP_ENCRYPTION_KEY`不变。
4. 在非`8765`端口启动`app/server.py`并完成健康、登录、关键页面和写入冒烟测试。
5. 记录切换提交、数据库备份位置和启动时间后,才把正式入口指向`app/`
6. 切换观察期内保留根级原版和切换前数据库,只允许迁移版写主库。
Docker/NAS切换应以`app/`作为构建上下文,另行执行构建、卷挂载、权限、健康检查和回退演练。
本轮没有进行这些操作。
## 9. 回退方案
若切换后出现问题:
1. 立即停止迁移版,避免继续写库。
2. 保存故障日志和当前数据库副本用于调查。
3. 恢复切换前成对备份的`review.db``.env`
4. 从切换记录指定的原版提交重新启动根级`server.py`
5. 验证登录、健康接口、最近交易日、私有数据和模型配置后恢复使用。
切片11试删可从`xiaobai-preservation-slice-10-20260731`单项恢复;不要用破坏性的Git重置覆盖
正式数据或用户未提交的代码。
+12 -6
View File
@@ -1,7 +1,7 @@
{
"schema_version": 1,
"updated_at": "2026-07-31T12:30:00+08:00",
"status": "active",
"updated_at": "2026-07-31T16:10:00+08:00",
"status": "awaiting_manual_acceptance",
"migration_mode": "behavior_preserving_source_migration",
"source_of_truth": "current_original_webapp_runtime_and_source",
"source_root": ".",
@@ -11,8 +11,9 @@
],
"current_slice": "slice-11-uncertain-code-audit-final-acceptance-handoff",
"last_completed_slice": "slice-10-frontend-shell-pages-components-css-mobile",
"last_checkpoint": "xiaobai-preservation-slice-10-20260731",
"next_action": "commit_and_push_slice_10_then_audit_each_uncertain_asset_with_independent_evidence_and_retain_any_asset_not_proven_safe_to_remove",
"last_automated_slice": "slice-11-uncertain-code-audit-final-acceptance-handoff",
"last_checkpoint": "xiaobai-preservation-slice-11-candidate-20260731",
"next_action": "user_acceptance_on_local_port_8797_then_confirm_or_restore_each_trial_retirement; do_not_switch_docker_or_nas_before_approval",
"authoritative_documents": [
"AGENTS.md",
"docs/migration/原版保真迁移总纲.md",
@@ -27,7 +28,8 @@
"preserve_visual_interaction_animation_calculation_and_data_semantics",
"require_old_new_differential_evidence_for_every_slice",
"keep_original_runtime_available",
"do_not_delete_uncertain_code"
"do_not_make_trial_retirements_permanent_before_user_acceptance",
"do_not_switch_docker_or_nas_before_user_approval"
],
"approved_decisions": {
"target_directory_name": "app",
@@ -35,5 +37,9 @@
"migration_slice_order": "approved_2026-07-30",
"execution_mode": "autonomous_until_complete"
},
"open_decisions": []
"open_decisions": [
"user_acceptance_of_visual_interaction_and_animation_equivalence",
"final_confirmation_or_restore_of_slice_11_trial_retirements",
"local_and_docker_switch_timing"
]
}
+19 -5
View File
@@ -1,6 +1,6 @@
# 小白复盘保真迁移账本
> 当前状态:正式迁移,切片10“前端Shell、页面、样式与移动端职责归位”已完成
> 当前状态:切片11自动验收完成,等待用户人工验收;正式切换尚未执行
本账本是上下文恢复和人工审计的连续记录。任何迁移提交必须在同一提交中更新本文件及
`保真迁移状态.json`
@@ -30,6 +30,7 @@
| 2026-07-31 | `xiaobai-preservation-slice-08-20260731` | 问天、观势、观气与观心原实现归位 | 自动、API、数据库、动画与浏览器差分通过,进入切片09 |
| 2026-07-31 | `xiaobai-preservation-slice-09-20260731` | 复盘、自选、交易日志、提醒与复盘助手原实现归位 | 自动、API、数据库、账户隔离与浏览器差分通过,进入切片10 |
| 2026-07-31 | `xiaobai-preservation-slice-10-20260731` | 前端Shell、页面、CSS、动画与移动端职责归位 | 源码重组、自动、API、数据库、桌面、夜间、移动端与动画差分通过,进入切片11 |
| 2026-07-31 | `xiaobai-preservation-slice-11-candidate-20260731` | 不确定代码审计、全量验收与人工交接准备 | 自动、API、数据库和浏览器验收通过;等待人工确认,未切换部署 |
## 资产处置登记
@@ -39,10 +40,10 @@
|---|---|---|---|---|---|---|
| 原版运行源文件(排除`next/`、日志、缓存、构建产物和正式数据库) | 运行资产 | 全站 | 原样保留后逐项移动 | `app/` | 388项受控资产哈希一致;231项Python与45项Playwright测试通过 | 已复制 |
| `next/` | 失败实现 | 无正式消费者 | 原样保留但禁止迁移 | - | 用户冻结决定 | 已冻结 |
| `demo_data.py` | 疑似旧兼容代码 | 未发现运行导入 | 待定 | 待删隔离账本 | 静态扫描不足以授权删除 | 保留 |
| `static/heaven-loading.js` | 疑似旧动画 | 当前页面加载`heaven-loading-v2.js` | 待定 | 待删隔离账本 | 仍需动画运行覆盖 | 保留 |
| `commonReviewColumns`等5个前端函数 | 疑似无引用符号 | 未发现静态调用 | 待定 | 待删隔离账本 | 仍需动态注册与浏览器覆盖 | 保留 |
| `wencai_saved_queries`及其方法 | 历史兼容数据 | 当前无前端入口 | 待定 | 数据库兼容区 | 不允许在迁移期破坏旧库 | 保留 |
| `demo_data.py` | 旧演示代码 | 无运行、动态、配置或兼容消费者 | 候选试删 | 切片10标签可单项恢复 | 全量自动、API、数据库与浏览器验收通过 | 待人工确认 |
| `static/heaven-loading.js` | 旧动画 | 页面加载`heaven-loading-v2.js` | 候选试删 | 切片10标签可单项恢复 | 问天三页加载动画与45项Playwright通过 | 待人工确认 |
| `commonReviewColumns`等5个前端函数 | 无引用符号 | 定义外引用为0 | 候选试删 | 切片10标签可按原行号恢复 | 审计白名单比较、24个JS语法和浏览器流程通过 | 待人工确认 |
| `wencai_saved_queries`及其方法 | 历史兼容数据 | 旧库兼容与用户隔离 | 原样保留 | `app/backend/database/`兼容区 | schema及关键表差分一致;清理契约持续保护 | 保留 |
| 现有7层CSS | 视觉运行资产 | 全部页面和主题 | 原样保留后逐页归档 | `app/frontend/` | 必须通过截图与计算样式差分 | 保留 |
| `sentiment_engine.py` | 情绪周期计算 | 总览、轮动、选股 | 移动并保留兼容别名 | `app/backend/features/sentiment/engine.py` | 文件哈希与原版一致;248项Python与45项Playwright通过 | 已移动 |
| `DashboardService`情绪及股池原因方法 | 业务服务 | 情绪页、五类股池、涨停表现 | 按职责机械移动 | `app/backend/features/sentiment/``app/backend/features/pools/` | 8个方法AST与原版一致;真实API完全一致 | 已移动 |
@@ -189,6 +190,19 @@
- 回档:标签`xiaobai-preservation-slice-10-20260731`
- 完整证据:`docs/migration/evidence/slice-10/README.md`
自动验收完成、等待人工确认的切片:`slice-11-uncertain-code-audit-final-acceptance-handoff`
- 原版基线:提交`dec3cd12365df5e7d4c391369f14c457cf56d7d9`,即切片10回档点。
- 审计范围:`demo_data.py`、旧问天加载动画、5个无引用前端函数及`wencai_saved_queries`兼容责任。
- 处置:前3类进入可单项回档的候选试删;`wencai_saved_queries`表和方法因旧库兼容与用户隔离继续保留。
- 保护方式:全部历史前端源码测试统一使用审计白名单比较,只允许登记的原`app.js`行号缺失,其他差异仍会失败。
- API与数据库:21个全站只读API全部一致;62个schema对象和21张关键表逐行一致。
- 验收:原版231项、迁移版298项Python测试、24个JavaScript语法检查和45项Playwright(1.6分钟)通过;桌面日间/夜间、390×844五个移动入口和问天三页真实检查通过。
- 部署边界:未改正式数据库、`.env``8765`、Docker或NAS;原版仍是正式运行基线。
- 候选回档:标签`xiaobai-preservation-slice-11-candidate-20260731`;试删最终结论仍等待用户人工确认。
- 完整证据:`docs/migration/evidence/slice-11/README.md`
- 维护交接:`docs/migration/人工维护与本地切换指南.md`
## 决策记录
| 日期 | 决策 | 原因 |