refactor: establish standalone application boundary

This commit is contained in:
leefer
2026-08-03 21:42:25 +08:00
parent cc5fb8d73e
commit e1e76cd51e
324 changed files with 63090 additions and 44743 deletions
+13
View File
@@ -0,0 +1,13 @@
# 迁移文档入口
后续恢复迁移工作时按以下顺序读取,禁止从历史阶段文档直接继续:
1. [`../../AGENTS.md`](../../AGENTS.md):仓库级不可违反约束。
2. [`原版保真迁移总纲.md`](原版保真迁移总纲.md):当前唯一有效的迁移方法。
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,34 @@
# 切片00:原样可运行副本
## 范围
- 原版基线:`41329943c4878fc09ed82ec376eb93ab151e4092`
- 目标目录:`app/`
- 数据库:使用SQLite在线备份生成`app/data/review.db`,不写原版数据库。
- 排除:冻结的`next/`、密钥、正式数据库、日志、缓存、构建产物。
## 自动证据
| 检查 | 结果 |
|---|---|
| 原版与目标源文件SHA-256 | 628项一致,0项差异 |
| Python测试 | 231项通过 |
| Playwright测试 | 45项通过 |
| 数据库结构 | 36张表一致 |
| 数据库行数 | 2,830,708行一致 |
| SQLite完整性 | `ok` |
| 真实服务 | `http://127.0.0.1:8785/api/health`返回`ok` |
| 真实登录 | 管理员账号登录成功,默认进入情绪周期 |
## 视觉证据
- `app-exact-light-1920x1080.png`
- `app-exact-dark-1920x1080.png`
- `app-exact-light-390x844.png`
- `app-exact-dark-390x844.png`
四个视口均使用真实服务、数据库副本和原版前端资产。1920与390宽度下没有页面横向溢出。
## 结论
`app/`当前是原版的可独立运行副本,不包含来自`next/`的产品实现,也尚未进行业务拆分。
Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

@@ -0,0 +1,57 @@
# 切片 01:启动、HTTP、账号、会员与系统管理
> 基线:`4083dce`(切片 00 原样可运行副本)
> 回档标签:`xiaobai-preservation-slice-01-20260731`
> 结论:自动差分通过;前端运行资产未改动,仍等待最终全站人工验收
## 1. 本次范围
本切片只整理原版 `app/` 副本中的启动、通用 HTTP、账号、会员和系统管理实现。所有实现均从
原文件机械移动,原导入面由兼容外壳保持;没有从冻结的 `next/` 复制产品代码,也没有重新设计
页面、接口或数据结构。
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|---|---|---|
| `app/server.py` 的进程组装与完整应用服务 | `app/backend/application.py``app/backend/bootstrap/runtime.py` | `app/server.py` 继续导出原符号并保持原启动命令 |
| `app/server.py` 的 Cookie、鉴权、CSRF、静态文件和 JSON 传输 | `app/backend/http/handler.py` | `RequestHandler` 组合 `HttpTransportMixin` |
| `app/server.py` 的账号与会员 HTTP 方法 | `app/backend/features/accounts/http.py` | `RequestHandler` 组合 `AccountHttpMixin` |
| `app/server.py` 的系统管理 HTTP 方法 | `app/backend/features/system/http.py` | `RequestHandler` 组合 `SystemHttpMixin` |
| `app/server.py` 的账号、会员和出生信息业务方法 | `app/backend/features/accounts/service.py` | `DashboardService` 委托 `AccountService` |
| `app/database.py` 的账号、会话、会员与用户凭据方法 | `app/backend/features/accounts/repository.py` | `ReviewDatabase` 组合 `AccountRepositoryMixin` |
| `app/database.py` 的系统设置存取方法 | `app/backend/features/system/repository.py` | `ReviewDatabase` 组合 `SystemSettingsRepositoryMixin` |
| `app/security.py` | `app/backend/features/accounts/security.py` | 根文件保留原导出 |
| `app/app_config.py` | `app/backend/bootstrap/config.py` | 根文件保留原导出 |
## 2. 不变量与差分证据
- API`config/api.config.json``app/config/api.config.json` 的 SHA-256 相同;路由路径、方法、
访问角色、状态码和错误载荷由原注册表与全量测试继续约束。
- 数据库:原版和迁移副本均为 36 张业务表、62 个 schema 对象,规范化 schema SHA-256 均为
`0615a0423856d0eb02bccd81a071840bd50d6563da96d556cec49967ad8a5f4c`
- 账号边界:注册、登录、会话、密码、会员和出生信息使用临时数据库执行同一原版契约,5 项专项
测试全部通过。
- 前端:本切片没有修改 `app/static/``index.html``app.js``styles.css` 与根目录原版对应文件
哈希相同。`app-light-1920x1080.png` 保存本切片运行截图。
- 兼容:原 `python server.py` 命令以及测试和外部模块使用的 `server.DashboardService`
`server.RequestHandler``server.SERVICE``server.automatic_screener_jobs` 均保持可用。
## 3. 验证结果
| 验证 | 结果 |
|---|---:|
| `python -m unittest discover -s tests -q` | 236 项通过 |
| `python -m unittest tests.test_preservation_slice_accounts -v` | 5 项通过 |
| `npx playwright test --reporter=dot` | 45 项通过 |
| `python -m compileall -q ...` | 通过 |
| `git diff --check` | 通过(仅 Git 的 CRLF 提示) |
Playwright 在自行创建 Python 静态服务器时存在 Windows 子进程退出等待问题;验证时预先启动
`127.0.0.1:8876` 静态服务器并由 Playwright 复用,45 项用例在 143 秒内正常返回退出码 0。
## 4. 保留与待处理
- `app/backend/application.py` 仍包含其余尚未迁移切片的原版实现,这是刻意保留,不是本切片遗漏。
- `app/server.py``app/app_config.py``app/security.py``app/database.py` 的兼容面须等所有消费者
完成归位后再评估;本阶段禁止删除。
- 没有删除任何不确定代码,没有修改正式根目录数据库,也没有切换 Docker/NAS。
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

@@ -0,0 +1,61 @@
# 切片 02:公共行情、搜索、详情、图表与数据网关
> 基线:`4002f09`(切片 01
> 回档标签:`xiaobai-preservation-slice-02-20260731`
> 结论:源码、API、数据库、真实页面和浏览器回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片从原版副本机械移动公共行情纵向链路,没有从 `next/` 取用代码,也没有修改计算逻辑。
| 原位置 | 新的唯一实现位置 | 原位置兼容 |
|---|---|---|
| `app/backend/application.py` 的 30 个总览、搜索、详情、图表方法 | `app/backend/features/market/service.py` | `DashboardService` 继承 `MarketServiceMixin` |
| `app/database.py` 的 11 个行情快照、搜索目录、同步记录方法 | `app/backend/features/market/repository.py` | `ReviewDatabase` 继承 `MarketRepositoryMixin` |
| `app/tushare_client.py` | `app/backend/data/providers/tushare_client.py` | 根模块为同一模块对象的兼容别名 |
| `app/ifind_client.py` | `app/backend/data/providers/ifind_client.py` | 根模块为同一模块对象的兼容别名 |
| `app/realtime_aggregator.py` | `app/backend/data/realtime.py` | 根模块为同一模块对象的兼容别名 |
| `app/chart_data_provider.py` | `app/backend/features/market/charts.py` | 根模块为同一模块对象的兼容别名 |
`app/tools/move_class_methods.py` 使用 Python AST 确定方法及装饰器的源码边界,只移动原文本片段。
该工具会在缺失方法、目标标记不唯一或源码无法解析时停止,供后续切片继续复用。
## 2. 等价证据
- `test_preservation_slice_market.py` 对 30 个业务方法和 11 个 Repository 方法逐项执行无位置信息
AST 比较,全部与根目录原版 `server.py``database.py` 完全相同。
- Tushare、iFinD 和实时观察器文件与原版 SHA-256 完全相同;图表模块全部类和函数 AST 与原版相同,
仅内部导入改为新规范位置。
- 四个根级兼容模块与新模块共享同一类对象,旧导入和旧 monkeypatch 路径继续有效。
- `config/api.config.json`、API路径、鉴权角色、错误结构和数据库 schema 未修改。
- `app/static/` 未修改;七个核心 HTML/JS/CSS 文件哈希继续与原版相同。
- `app-light-1280x720.png` 为真实 `8785` 服务完成载入后的日间模式截图,SHA-256 为
`a7ee1b682f68c418d792727dbc4534d7494dae4f4811cdbba208bd86dcf25d10`
## 3. 真实运行检查
- 迁移副本:`http://127.0.0.1:8785/`,管理员登录成功。
- 总览:返回 2026-07-30 Tushare 已缓存行情,涨停 56 只。
- 搜索:搜索“中国平安”返回 `601318`,点击后打开完整个股详情、日 K、资金流、事件逻辑和复盘笔记。
- 页面:1280px 视口无横向溢出,数据加载状态正常,浏览器控制台 0 个错误。
- 分时:迁移版与原版在当前本机网络环境均返回同一个 `Intraday chart request failed`,因此记录为
既存外部接口状态,不是本切片差异;没有擅自增加降级或改变来源策略。
## 4. 自动验证
| 验证 | 结果 |
|---|---:|
| `python -m unittest discover -s tests -q` | 241 项通过 |
| `python -m unittest tests.test_preservation_slice_market -q` | 6 项通过 |
| 行情、图表、实时与数据库专项集合 | 61 项通过 |
| `npx playwright test --reporter=dot` | 45 项通过 |
| `python -m compileall -q ...` | 通过 |
| `git diff --check` | 通过 |
## 5. 保留边界
- 情绪计算仍在 `application.py`,切片 03 再归位;行情服务只通过继承调用,没有复制。
- 竞价、题材、人气、龙虎榜和问天对公共行情客户端的调用仍可通过兼容别名工作,待各自切片迁移。
- 根级四个数据模块、`DashboardService``ReviewDatabase` 的兼容面在所有消费者完成迁移前保留。
- 没有删除待定代码、没有改动根目录正式数据库、没有切换 Docker/NAS。
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

@@ -0,0 +1,66 @@
# 切片 03:情绪周期、五类股池与涨停表现
> 基线:`a426432`(切片 02
> 回档标签:`xiaobai-preservation-slice-03-20260731`
> 结论:源码、API、数据库、真实页面和浏览器回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片只移动原版副本中的真实实现,没有从 `next/` 取用代码,也没有改写情绪公式、股池数据、
原因补全、表格、样式或交互。
| 原位置 | 新的唯一实现位置 | 原位置兼容 |
|---|---|---|
| `app/backend/application.py` 的 2 个情绪服务方法 | `app/backend/features/sentiment/service.py` | `DashboardService` 继承 `SentimentServiceMixin` |
| `app/backend/application.py` 的 6 个股池原因及事件补全方法 | `app/backend/features/pools/service.py` | `DashboardService` 继承 `PoolServiceMixin` |
| `app/database.py` 的 2 个原因覆盖方法 | `app/backend/features/pools/repository.py` | `ReviewDatabase` 继承 `PoolRepositoryMixin` |
| `app/sentiment_engine.py` | `app/backend/features/sentiment/engine.py` | 根模块为同一模块对象的兼容别名 |
五类股池、涨停梯队和涨停表现仍由切片 02 已归位的原 Tushare 总览实现生成,本切片没有建立第二套
计算或数据来源。
## 2. 等价证据
- `test_preservation_slice_sentiment_pools.py` 对 8 个业务方法和 2 个 Repository 方法逐项执行无位置
信息 AST 比较,全部与根目录原版 `server.py``database.py` 完全相同。
- 新的情绪引擎文件与原版 `sentiment_engine.py` SHA-256 完全相同;根级兼容模块与新模块是同一模块对象。
- 已归位的应用、行情服务、Tushare Provider、演示数据和选股模块直接导入新的唯一实现;Tushare
Provider 仅调整该导入,其全部类和函数 AST 继续与原版一致。
- 原版 `8784` 与迁移版 `8785` 在相同账号、日期和数据库副本上请求 `/api/dashboard`
`/api/sentiment/history`,JSON 状态、字段、值和顺序完全相同。
- 2026-07-30 的同请求结果均为:涨停 56、炸板 23、跌停 83、昨日涨停 81、情绪历史 20 日。
- 原版和迁移版数据库均为 62 个 schema 对象,schema 哈希均为
`17918327f8b919496e6630458293f9f777c7c24662625bb3fc0b64ff0a8fbeef`
- `config/api.config.json`、API 路径、鉴权和 `app/static/` 未修改。
- `app-light-1920x1080.png` 是真实迁移服务载入完成后的情绪周期页面,SHA-256 为
`e387417abbe0667e00875a8d4061b5546748ecf2452a692d06d078d516330dab`
## 3. 真实运行检查
- 迁移副本:`http://127.0.0.1:8785/`,管理员会话与缓存行情载入正常。
- 情绪周期:20 个连续交易日、当前阶段、评分构成和交易日明细均完整显示。
- 股池:涨停池 56 行、炸板池 23 行、跌停池 83 行、昨日涨停 81 行。
- 涨停表现:四档晋级率、市场宽度和今日结论均显示原版结果。
- 1920×1080 下六个页面横向溢出均为 0;日间、夜间背景与面板状态正常;浏览器控制台无迁移错误。
## 4. 自动验证
| 验证 | 结果 |
|---|---:|
| `python -m unittest discover -s tests -q` | 248 项通过 |
| `python -m unittest tests.test_preservation_slice_sentiment_pools -q` | 6 项通过 |
| 情绪、总览、缓存、iFinD 与前端契约专项集合 | 48 项通过 |
| `npx.cmd playwright test --reporter=dot` | 45 项通过 |
| `python -m compileall -q ...` | 通过 |
| `git diff --check` | 通过 |
Windows 下由 Playwright 自行创建临时静态服务器时,45 项完成后子进程无法回收;改为预先启动同一个
`8876` 静态服务器并让 Playwright 复用后,测试以零退出码正常结束,结果为 `45 passed (2.1m)`
## 5. 保留边界
- 板块轮动仍调用情绪历史公共函数,待切片 04 与市场天梯一并归位。
- 竞价、题材、人气和龙虎榜对股池数据的消费保持原调用路径,待切片 05 迁移。
- 根级情绪引擎兼容模块、`DashboardService``ReviewDatabase` 兼容面继续保留;数据库内尚未迁移的
选股统计方法仍走兼容别名,待切片 06 随完整方法一并归位。
- 没有删除待定代码、没有改动根目录正式数据库、没有切换 Docker/NAS。
Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

@@ -0,0 +1,58 @@
# 切片 04:市场天梯与板块轮动
> 基线:`b3555d2`(切片 03
> 回档标签:`xiaobai-preservation-slice-04-20260731`
> 结论:源码、API、真实页面和浏览器回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片从原版副本机械移动板块轮动服务,没有从 `next/` 取用代码,也没有修改天梯、轮动的计算、
排序、展开、配色、页面结构或交互。
| 原位置 | 新的唯一实现位置 | 原位置兼容 |
|---|---|---|
| `app/backend/application.py` 的 2 个轮动方法 | `app/backend/features/rotation/service.py` | `DashboardService` 继承 `RotationServiceMixin` |
| Tushare Provider 的天梯与轮动构造函数 | 保持 `app/backend/data/providers/tushare_client.py` | 切片 02 已归位的公共数据实现 |
市场天梯没有独立后端 API 或第二套计算,直接展示 `/api/dashboard` 中原 Tushare 实现生成的
`ladders`;因此没有为目录形式建立空的天梯服务。
## 2. 等价证据
- `test_preservation_slice_ladder_rotation.py` 对 2 个轮动服务方法逐项执行无位置信息 AST 比较,
全部与根目录原版 `server.py` 完全相同。
- `_build_ladders``_build_sector_rotation` 两个原数据构造函数的 AST 与根目录原版完全相同。
- 原版 `8784` 与迁移版 `8785` 在相同账号、日期和数据库副本上返回的天梯数据及 9 日轮动历史
JSON 逐字段完全相同。
- 成分股接口在当前外部网络状态下两版均返回 HTTP 400、`bad_request` 和相同的
`该板块成分股暂不可用:Tushare request failed:`,没有改变错误或增加静默降级。
- `config/api.config.json`、API 路径、鉴权、数据库 schema 和 `app/static/` 未修改。
## 3. 真实运行检查
- 市场天梯:8 个层级(含断层)、18 个首屏股票单元格、3 个结构分析模块正常;1920×1080 下
页面宽度无溢出,首板展开入口保留。
- 板块轮动:9 个交易日、每日 Top 12 共 108 个板块单元格、由远到近/由近到远两个排序入口正常;
1920×1080 下页面宽度无溢出并保持全页滚动。
- 日间模式页面控制台没有错误或警告。
- `app-light-ladder-1920x1080.png` SHA-256
`9e57d18d92e745fd92131f7bf08f21faaaa745476dd942cdaa2a703b9a7a303a`
- `app-light-rotation-1920x1080.png` SHA-256
`03c092bb40bd0eb672136dff853abffc87e9790840107c2f22e6cf31d5f83c09`
## 4. 自动验证
| 验证 | 结果 |
|---|---:|
| `python -m unittest discover -s tests -q` | 252 项通过 |
| `python -m unittest tests.test_preservation_slice_ladder_rotation -q` | 4 项通过 |
| 切片 02 至 04 与总览缓存专项集合 | 24 项通过 |
| `npx.cmd playwright test --reporter=dot` | 45 项通过 |
| `git diff --check` | 通过 |
## 5. 保留边界
- 成分股接口依赖的日行情与因子持久化方法仍由原 `ReviewDatabase` 提供,因其同时服务智能选股,
待切片 06 随完整共享职责归位。
- 天梯和轮动前端资产保持原位,切片 10 再按页面职责归档;当前没有复制或改写。
- 没有删除待定代码、没有改动根目录正式数据库、没有切换 Docker/NAS。
Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

@@ -0,0 +1,69 @@
# 切片 05:集合竞价、题材库、人气热榜与龙虎榜
> 基线:`814e757`(切片 04
> 回档标签:`xiaobai-preservation-slice-05-20260731`
> 结论:源码、API、数据库、真实页面和全量回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片没有从`next/`取用代码,也没有重写计算、页面或接口。集合竞价、题材库和人气热榜原本
共享`MarketInsightsService`,其中竞价候选会直接调用人气榜热度数据,因此整体移动到公共行情
领域,避免拆出互相复制的实现;各页面入口仍按功能目录归位。
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|---|---|---|
| `app/market_insights.py` | `app/backend/features/market/insights.py` | 根级模块导出同一类对象 |
| `DashboardService`竞价入口 | `app/backend/features/auction/service.py` | `AuctionServiceMixin` |
| `DashboardService`题材入口 | `app/backend/features/themes/service.py` | `ThemeServiceMixin` |
| `DashboardService`人气入口 | `app/backend/features/popularity/service.py` | `PopularityServiceMixin` |
| `DashboardService`龙虎榜及游资档案 | `app/backend/features/dragon_tiger/service.py` | `DragonTigerServiceMixin` |
| 竞价、人气、龙虎榜持久化方法 | 对应功能目录的`repository.py` | `ReviewDatabase`继承原接口 |
Tushare Provider 中`hot_money_profiles``dragon_tiger`继续保持切片02归位的唯一实现,没有为目录
形式再制造一套数据构造逻辑。
## 2. 源码与接口等价
- `test_preservation_slice_market_insights.py`逐项比较22个市场洞察方法、8个页面服务方法、7个
Repository方法和2个Tushare方法,全部与根目录原版无位置信息AST一致。
- `DashboardService``ReviewDatabase`不再重复保留已移动方法;根级`market_insights`与新模块
暴露同一个`MarketInsightsService`类对象。
- 原版`8784`和迁移版`8785`使用同一数据库的独立副本,集合竞价、题材库、题材详情、人气热榜、
龙虎榜、游资档案和席位别名共7个真实API状态码及JSON一致。
- 题材详情在当前外部网络条件下两版均返回HTTP 400;差分只排除每次请求随机生成的
`request_id`,错误码与错误内容仍完全一致。
- 完整接口摘要见`api-diff.json`
## 3. 数据库差分
- 两个副本均为62个schema对象,哈希均为
`60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1`
- `auction_factors` 511914行、`popularity_factors` 232行、`lhb_institution_daily` 47行、
`seat_aliases` 0行、`stock_master` 5535行均逐行一致。
- 完整表计数与哈希见`database-diff.json`;运行数据库副本已在验收后删除,未提交凭据或正式数据。
## 4. 真实浏览器检查
- 1920×1080日间模式检查集合竞价、题材库、人气热榜和龙虎榜四页;均无横向溢出,控制台无
错误或警告。
- 集合竞价载入30行重点候选;题材库载入394个题材及选中题材成分股;人气热榜载入3个摘要
模块和200行综合榜;龙虎榜按当前缓存显示既有不可用空态。
- 四页HTML、主JS、CSS及各自页面JS与根目录原版字节哈希一致。
- 截图SHA-256
- `app-light-auction-1920x1080.png``8065086c8f2b360aeb1004bd60429f3e2d7f1b8c872ec4a965e9a5d0c016b915`
- `app-light-themes-1920x1080.png``80e1e41101497ee7213e1dadfaa4c9572a1c47b3495edd09e36745ccdb639402`
- `app-light-popularity-1920x1080.png``614d6b7770f4e9ec72c059ab8a4129486df9eff5c4dd7e8279cc68ebcb80a36b`
- `app-light-dragon-tiger-1920x1080.png``2f1e2ad3a9bc3874c73bae884fc8744177cef354c7176559da1453fab1f85993`
## 5. 自动验证与保留边界
| 验证 | 结果 |
|---|---:|
| `python -m unittest discover -s tests -q` | 258项通过 |
| `python -m unittest tests.test_preservation_slice_market_insights -q` | 6项通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过 |
| `git diff --check` | 通过 |
- 竞价、人气和龙虎榜因子同时服务切片06智能选股,迁移后仍由`ReviewDatabase`原方法名暴露。
- 前端资产保持原位置,切片10再按页面职责归档;本切片没有改DOM、CSS、动画或交互。
- 没有删除待定代码、没有修改根目录正式数据库、没有切换Docker/NAS。
@@ -0,0 +1,61 @@
{
"all_equal": true,
"endpoints": [
{
"endpoint": "/api/auction?trade_date=2026-07-29",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "523144cc14d876577b7d518cdf38fd2722b13a8f01ed5d2e20dcc38f6a2624ce",
"migrated_sha256": "523144cc14d876577b7d518cdf38fd2722b13a8f01ed5d2e20dcc38f6a2624ce",
"equal": true
},
{
"endpoint": "/api/themes?trade_date=2026-07-29",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "95c2ad418f18d877d94ec2a71fe6fafd5e329b069d87a9300f7fcac92d4ba5d1",
"migrated_sha256": "95c2ad418f18d877d94ec2a71fe6fafd5e329b069d87a9300f7fcac92d4ba5d1",
"equal": true
},
{
"endpoint": "/api/themes/detail?code=885001.TI&trade_date=2026-07-29",
"original_status": 400,
"migrated_status": 400,
"original_sha256": "b11a3314b172d3ad6ba28d969fcd6a9a2a4b49e7d29ed804496a4dfecd2a364a",
"migrated_sha256": "b11a3314b172d3ad6ba28d969fcd6a9a2a4b49e7d29ed804496a4dfecd2a364a",
"equal": true
},
{
"endpoint": "/api/popularity?trade_date=2026-07-29",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "e62a93c41f7c3f95c3d47f8ccaedaa809563c8dd65c04dd54b164f73e6014e94",
"migrated_sha256": "e62a93c41f7c3f95c3d47f8ccaedaa809563c8dd65c04dd54b164f73e6014e94",
"equal": true
},
{
"endpoint": "/api/dragon-tiger?trade_date=2026-07-29",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "a3998b935377d5fd0673ec5b9214d1b0a64680d155c61e6cff49d0d5fcf0e843",
"migrated_sha256": "a3998b935377d5fd0673ec5b9214d1b0a64680d155c61e6cff49d0d5fcf0e843",
"equal": true
},
{
"endpoint": "/api/dragon-tiger/profiles",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "dfb1e534c018ec12fd8d8ee0e7fe0f234e73dc7715d7f0a948f74ef8d12d779a",
"migrated_sha256": "dfb1e534c018ec12fd8d8ee0e7fe0f234e73dc7715d7f0a948f74ef8d12d779a",
"equal": true
},
{
"endpoint": "/api/seat-aliases",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "2b0fb0a6b3e353c69158d61221c2200e4199d0d60dd0b9d99702a22eaa917a78",
"migrated_sha256": "2b0fb0a6b3e353c69158d61221c2200e4199d0d60dd0b9d99702a22eaa917a78",
"equal": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

@@ -0,0 +1,51 @@
{
"all_equal": true,
"schema": {
"object_count": 62,
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"equal": true
},
"tables": [
{
"table": "auction_factors",
"original_count": 511914,
"migrated_count": 511914,
"original_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
"migrated_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
"equal": true
},
{
"table": "popularity_factors",
"original_count": 232,
"migrated_count": 232,
"original_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
"migrated_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
"equal": true
},
{
"table": "lhb_institution_daily",
"original_count": 47,
"migrated_count": 47,
"original_sha256": "1f847eac34d2ba576b429da208667f3b67b591d36ee66800803605bbc447970c",
"migrated_sha256": "1f847eac34d2ba576b429da208667f3b67b591d36ee66800803605bbc447970c",
"equal": true
},
{
"table": "seat_aliases",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true
},
{
"table": "stock_master",
"original_count": 5535,
"migrated_count": 5535,
"original_sha256": "8656e2d189d3520433fb3552e17998e4bf17bcf6838403cddc6719282b23e792",
"migrated_sha256": "8656e2d189d3520433fb3552e17998e4bf17bcf6838403cddc6719282b23e792",
"equal": true
}
]
}
@@ -0,0 +1,69 @@
# 切片 06:智能选股、自定义选股与策略持续跟踪
> 基线:`cf2aad2`(切片 05
> 回档标签:`xiaobai-preservation-slice-06-20260731`
> 结论:源码、API、数据库、真实页面和全量回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片只机械移动原版选股实现,没有从`next/`取用代码,也没有改写策略、因子、权重、排序、
盘后候选或跟踪逻辑。
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|---|---|---|
| `app/screener.py` | `app/backend/features/screener/engine.py` | 根级模块指向同一模块对象 |
| `app/advanced_strategies.py` | `app/backend/features/screener/strategies.py` | 根级模块指向同一模块对象 |
| `app/llm_strategy.py` | `app/backend/features/screener/compiler.py` | 根级模块指向同一模块对象 |
| `DashboardService`选股入口 | `app/backend/features/screener/service.py` | `ScreenerServiceMixin` |
| `ReviewDatabase`选股持久化方法 | `app/backend/features/screener/repository.py` | `ScreenerRepositoryMixin` |
| 原策略持续跟踪服务 | `app/backend/features/screener/tracking.py` | 容器直接导入唯一实现 |
四个同时服务公共行情与选股的方法归入`MarketRepositoryMixin`,没有复制第二套实现:
`upsert_stock_master``list_stock_master``upsert_daily_bars``daily_bars_for_date`
## 2. 源码与接口等价
- `test_preservation_slice_screener.py`逐项验证选股引擎、29套策略定义、自然语言策略编译器、
13个服务方法、25个选股持久化方法和跟踪服务与原版等价。
- 三个根级兼容模块与正式模块暴露同一模块及类对象;原类不再重复保留已移动方法。
- 原版与迁移版的`/api/screener/setup``/api/screener/tracking``/api/screener/run`
状态码及业务JSON一致。
- 差分仅规范化策略启动刷新和顺序执行必然变化的数组顺序与`updated_at`;其他字段仍逐项比较。
- 请求与差分结果见`api-requests.json``api-diff.json`
## 3. 数据库差分
- 两个临时副本均为62个schema对象,结构完全一致。
- 13张关键表逐行一致,覆盖约143万条日线、77万条技术指标和51万条竞价因子。
- `screener_runs`两边均为251行;会话和运行时间戳只在临时副本内规范化。
- 正式`data/review.db``app/data/review.db`未写入测试策略、测试会话或差分时间戳。
- 完整表计数与哈希见`database-diff.json`
## 4. 真实浏览器检查
- 已登录迁移版真实服务,分别检查阶段选股、策略选股、自定义选股和策略持续跟踪。
- 阶段选股显示退潮、置信度92%、匹配策略和262日因子就绪状态;策略选股载入29套策略。
- 自定义选股保留因子权重、过滤条件、公式入口、手动执行和独立候选结果。
- 跟踪页只展示手动加入的候选,批次、标的、T+1/T+3进度、胜率和移除操作均正常。
- 各检查状态无横向溢出、无加载遮罩残留,浏览器控制台无错误。
- 截图SHA-256
- `curated-screener.jpg``529ecd0947b34b42eb63d166c6804b0041e26fa362a171e4d0d7b584e073c05e`
- `custom-screener.jpg``7f31f50d44bc63a488277be0a74232e2ac256779d0accda42b96cc1eef88cc6e`
- `tracking.jpg``b19b1bc0cd4a98c29500917676bdcc4cc9a430a0c72dea8aff1110ad911db6e3`
## 5. 自动验证与保留边界
| 验证 | 结果 |
|---|---:|
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
| 迁移版`python -m unittest discover -s tests -q` | 265项通过 |
| `python -m unittest tests.test_preservation_slice_screener -q` | 7项通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过 |
| `git diff --check` | 通过 |
- Windows下由Playwright自行创建静态服务器时存在子进程不退出的测试基线问题;复用独立的8876
测试服务器后45项用例在2.1分钟内通过并正常返回退出码0。
- 选股引擎保留原版数据客户端依赖,边界测试将其与普通页面Service区分;后续只可在不改变行为且有
独立差分证据时治理该依赖。
- 前端资产保持原位置,切片10再按页面职责归档;本切片没有改DOM、CSS、动画或交互。
- 没有删除待定代码、没有修改正式数据库、没有切换Docker/NAS。
@@ -0,0 +1,38 @@
{
"all_equal": true,
"endpoints": [
{
"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": "POST",
"endpoint": "/api/screener/run",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "b3866e7d270aa222bd2bad0c0276b7e81ccd48e5f3a75941a32ef8e559a92c7b",
"migrated_sha256": "b3866e7d270aa222bd2bad0c0276b7e81ccd48e5f3a75941a32ef8e559a92c7b",
"equal": true,
"first_difference": null
}
]
}
@@ -0,0 +1,59 @@
[
{
"name": "盘后自动候选与策略库",
"method": "GET",
"endpoint": "/api/screener/setup?trade_date=2026-07-30",
"sort_lists": {
"$.strategies": "id"
},
"exclude_paths": [
"$.strategies[].updated_at"
]
},
{
"name": "策略持续跟踪",
"method": "GET",
"endpoint": "/api/screener/tracking?limit=12"
},
{
"name": "自定义选股执行",
"method": "POST",
"endpoint": "/api/screener/run",
"exclude_paths": [
"$.result.meta.updated_at"
],
"payload": {
"trade_date": "2026-07-30",
"regime": "retreat",
"strategy_name": "保真迁移差分策略",
"mode": "quant",
"run_backtest": false,
"formula": {
"meta": {
"library": "quant",
"category": "量化公式"
},
"universe": {
"exclude_st": true,
"listed_days_min": 120
},
"filters": [
{
"field": "pct_chg",
"op": "between",
"value": [-2, 2]
}
],
"score": [
{
"field": "amount_billion",
"weight": 1,
"direction": "desc"
}
],
"limit": 5,
"min_score": 0
}
}
}
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@@ -0,0 +1,115 @@
{
"all_equal": true,
"schema": {
"object_count": 62,
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"equal": true
},
"tables": [
{
"table": "stock_master",
"original_count": 5535,
"migrated_count": 5535,
"original_sha256": "8656e2d189d3520433fb3552e17998e4bf17bcf6838403cddc6719282b23e792",
"migrated_sha256": "8656e2d189d3520433fb3552e17998e4bf17bcf6838403cddc6719282b23e792",
"equal": true
},
{
"table": "daily_bars",
"original_count": 1430501,
"migrated_count": 1430501,
"original_sha256": "d72a06755d92d6be95ab4f4c98a4718e973bee59d4f381b01acb963b6d7ae9e6",
"migrated_sha256": "d72a06755d92d6be95ab4f4c98a4718e973bee59d4f381b01acb963b6d7ae9e6",
"equal": true
},
{
"table": "benchmark_bars",
"original_count": 261,
"migrated_count": 261,
"original_sha256": "691f7666dddcfdf7ebe8ba1d3e1ddd8f2d9670d1d7a06e740a929f3ef32ec1c9",
"migrated_sha256": "691f7666dddcfdf7ebe8ba1d3e1ddd8f2d9670d1d7a06e740a929f3ef32ec1c9",
"equal": true
},
{
"table": "daily_indicators",
"original_count": 770238,
"migrated_count": 770238,
"original_sha256": "cd5a71c7d8de201ff2e3e58c64e2617a31d247911732fbddf81acb025d31fde9",
"migrated_sha256": "cd5a71c7d8de201ff2e3e58c64e2617a31d247911732fbddf81acb025d31fde9",
"equal": true
},
{
"table": "fundamental_indicators",
"original_count": 49490,
"migrated_count": 49490,
"original_sha256": "4b6859256063d3a0238ba3cbbbe2842f1278cf88d44b0f6114f1af978b8bfa7d",
"migrated_sha256": "4b6859256063d3a0238ba3cbbbe2842f1278cf88d44b0f6114f1af978b8bfa7d",
"equal": true
},
{
"table": "moneyflow_daily",
"original_count": 36368,
"migrated_count": 36368,
"original_sha256": "f7591dec150c7e0094568e3c46d77fc54e14a803223e15940dc54af1017bd83d",
"migrated_sha256": "f7591dec150c7e0094568e3c46d77fc54e14a803223e15940dc54af1017bd83d",
"equal": true
},
{
"table": "earnings_events",
"original_count": 580,
"migrated_count": 580,
"original_sha256": "ebac03fe9ef491a6d6d2b5bc8f5ee08b609fa0ebe5992087fa067216490a6b9d",
"migrated_sha256": "ebac03fe9ef491a6d6d2b5bc8f5ee08b609fa0ebe5992087fa067216490a6b9d",
"equal": true
},
{
"table": "auction_factors",
"original_count": 511914,
"migrated_count": 511914,
"original_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
"migrated_sha256": "3d0470787adaf7c4cf5f15f5ad9fa1d67c8fcd4807285ac264eeacdcf5054cd1",
"equal": true
},
{
"table": "popularity_factors",
"original_count": 232,
"migrated_count": 232,
"original_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
"migrated_sha256": "3f4c61a13ceaa1ed9ecb28f86241a8a478a6757d6a44b46f432f73c0226bba7f",
"equal": true
},
{
"table": "lhb_institution_daily",
"original_count": 47,
"migrated_count": 47,
"original_sha256": "1f847eac34d2ba576b429da208667f3b67b591d36ee66800803605bbc447970c",
"migrated_sha256": "1f847eac34d2ba576b429da208667f3b67b591d36ee66800803605bbc447970c",
"equal": true
},
{
"table": "screener_strategies",
"original_count": 36,
"migrated_count": 36,
"original_sha256": "e58859dbd478272d71bf85b6bc4ba45e609baccba74bb818b044d93bafa07312",
"migrated_sha256": "e58859dbd478272d71bf85b6bc4ba45e609baccba74bb818b044d93bafa07312",
"equal": true
},
{
"table": "screener_runs",
"original_count": 251,
"migrated_count": 251,
"original_sha256": "117b0b95a362c91ddd70ca2def1e62e96e0ade2494ba4302bab5154c8d384498",
"migrated_sha256": "117b0b95a362c91ddd70ca2def1e62e96e0ade2494ba4302bab5154c8d384498",
"equal": true
},
{
"table": "strategy_tracks",
"original_count": 16,
"migrated_count": 16,
"original_sha256": "f0639b1386b69c92fd815f929864b3b2457a6bf4ca515bee2dca87e9ea29e8c4",
"migrated_sha256": "f0639b1386b69c92fd815f929864b3b2457a6bf4ca515bee2dca87e9ea29e8c4",
"equal": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

@@ -0,0 +1,71 @@
# 切片 07:问师、模型 Skill 与 LLM 流式链路
> 基线:`4bab921`(切片 06
> 回档标签:`xiaobai-preservation-slice-07-20260731`
> 结论:源码、API、数据库、Skill 资产、真实页面和全量回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片只移动原版问师、Skill 注册、模型访问与流式协议,没有从`next/`取用代码,也没有改写
提示词、数据侧重、模型排序、权限、计次、回退或流式去重逻辑。
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|---|---|---|
| `app/mentor_agent.py` | `app/backend/features/mentor/agent.py` | 根级模块指向同一模块对象 |
| `DashboardService`问师方法 | `app/backend/features/mentor/service.py` | `MentorServiceMixin` |
| 问师消息和偏好持久化 | `app/backend/features/mentor/repository.py` | `MentorRepositoryMixin` |
| 问师流式HTTP方法 | `app/backend/features/mentor/http.py` | `MentorHttpMixin` |
| `app/llm_stream.py` | `app/backend/llm/stream.py` | 根级模块指向同一模块对象 |
| `DashboardService`模型访问方法 | `app/backend/llm/service.py` | `LLMServiceMixin` |
| LLM调用审计持久化 | `app/backend/llm/repository.py` | `LLMAuditRepositoryMixin` |
| 旧个人模型HTTP兼容入口 | `app/backend/llm/http.py` | `LLMHttpMixin` |
模型池的增删、主辅模型选择及会员每日额度仍由系统管理负责;`backend/llm`只负责解析当前可用模型、
鉴权、计次、首段前回退、流式传输和调用审计,避免复制第二套系统设置逻辑。
## 2. 源码与 Skill 等价
- `mentor_agent.py``llm_stream.py`与原版文件SHA-256一致,根级兼容模块与正式模块为同一模块对象。
- 8个问师服务方法、5个问师Repository方法、2个LLM审计Repository方法与原版无位置信息AST一致。
- 21个LLM服务方法中19个与原版AST一致;`_platform_usage_today`及按用户查询的辅助方法保留切片01
已验证的用户边界适配,使会员管理可在不切换请求上下文的情况下显示每位用户当日用量。
- 问师流式和旧模型HTTP方法仅把原全局`SERVICE`改为Mixin的`self.application_service`,响应状态、
Content-Type、NDJSON事件、异常和断连处理不变。
- 公开`游资skills`共190个文件,原版与迁移版逐路径、逐SHA-256比较,差异为0。
- 私有“小白”Skill仍位于Git忽略的`data/private-mentor-skills`,未复制到公开目录或证据文件。
## 3. API与数据库差分
- 原版`8786`和迁移版`8787`使用同一数据库的独立副本。
- `/api/mentors/setup`和按用户、模型、日期读取消息的API状态码及业务JSON完全一致。
- 两版均为62个schema对象;`mentor_messages` 28行、`mentor_preferences` 45行、`llm_usage` 72行、
`system_settings` 1行、`users` 3行,均逐行一致。
- 接口证据见`api-requests.json``api-diff.json`,数据库证据见`database-diff.json`
- 差分只在系统临时目录的数据库副本上运行,登录会话和后台任务运行数据未纳入业务表比较;临时副本
已在验收后删除,正式数据库未写入测试消息或LLM调用记录。
## 4. 真实浏览器检查
- 迁移版真实服务载入24个思维模型,管理员可见私有“小白”,公开模型的A/B/C标签、简介和置顶按钮正常。
- A级筛选显示13个模型;全部、A级、B级、C级、搜索、整理、清空对话、建议问题、输入框和发送按钮均存在。
- 页面宽度与1280像素视口一致,无横向溢出;浏览器控制台无错误。
- 浏览器不调用真实外部模型,防止模型容量和网络波动污染迁移结论;流式首段回退、输出后禁止切模、
完整快照去重和空响应处理由`test_llm_gateway``test_mentor_stream``test_llm_stream`覆盖。
- 截图SHA-256
- `mentor-all.jpg``9cda4d6896da6932b8e9db014eed4882359287d6999e2181af7d945ea6272bd9`
- `mentor-a-filter.jpg``5dca958d5edf7ab11767474a3c4405d4cb96029f7a1efb35fa8155c61c863984`
## 5. 自动验证与保留边界
| 验证 | 结果 |
|---|---:|
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
| 迁移版`python -m unittest discover -s tests -q` | 273项通过 |
| `python -m unittest tests.test_preservation_slice_mentor_llm -q` | 8项通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过 |
| `git diff --check` | 通过 |
- `assistant_agent.py`属于切片09复盘助手,本切片不提前移动。
- 问天的模型调用属于切片08,本切片只复用统一LLM网关,不移动问天业务。
- 前端DOM、页面JS、CSS和移动端行为未改动,统一归档延至切片10。
- 没有删除待定代码、没有修改正式数据库、没有切换Docker/NAS。
@@ -0,0 +1,27 @@
{
"all_equal": true,
"endpoints": [
{
"name": "mentor setup and public skill catalog",
"method": "GET",
"endpoint": "/api/mentors/setup?trade_date=2026-07-30",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "3a5bd83b58e849757664bbfe8cf54e704bc9a7682333deb8297212c488aa3ddc",
"migrated_sha256": "3a5bd83b58e849757664bbfe8cf54e704bc9a7682333deb8297212c488aa3ddc",
"equal": true,
"first_difference": null
},
{
"name": "mentor messages scoped by user mentor and date",
"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
}
]
}
@@ -0,0 +1,14 @@
[
{
"name": "mentor setup and public skill catalog",
"method": "GET",
"endpoint": "/api/mentors/setup?trade_date=2026-07-30",
"payload": null
},
{
"name": "mentor messages scoped by user mentor and date",
"method": "GET",
"endpoint": "/api/mentors/messages?mentor_id=kobe92-perspective&trade_date=20260730",
"payload": null
}
]
@@ -0,0 +1,51 @@
{
"all_equal": true,
"schema": {
"object_count": 62,
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"equal": true
},
"tables": [
{
"table": "mentor_messages",
"original_count": 28,
"migrated_count": 28,
"original_sha256": "b906b776d575ff6fe459b2aa0e8b396267feed36d3d85f7edd7947b284482aeb",
"migrated_sha256": "b906b776d575ff6fe459b2aa0e8b396267feed36d3d85f7edd7947b284482aeb",
"equal": true
},
{
"table": "mentor_preferences",
"original_count": 45,
"migrated_count": 45,
"original_sha256": "c19c7d05e6745e4f1787d1eed5f39d7e555ec24f8e490b585c19158edc2505ec",
"migrated_sha256": "c19c7d05e6745e4f1787d1eed5f39d7e555ec24f8e490b585c19158edc2505ec",
"equal": true
},
{
"table": "llm_usage",
"original_count": 72,
"migrated_count": 72,
"original_sha256": "03a070316a125cef904bbfb2bb06b06e792242d5713142e70354402c741393c3",
"migrated_sha256": "03a070316a125cef904bbfb2bb06b06e792242d5713142e70354402c741393c3",
"equal": true
},
{
"table": "system_settings",
"original_count": 1,
"migrated_count": 1,
"original_sha256": "86d333a5c7feaf7111cd79b2db29513326a9b0d3781607f78bf633579e2ca8e9",
"migrated_sha256": "86d333a5c7feaf7111cd79b2db29513326a9b0d3781607f78bf633579e2ca8e9",
"equal": true
},
{
"table": "users",
"original_count": 3,
"migrated_count": 3,
"original_sha256": "4a0f135bef8ebae454693d3f40e1157d84d814d18d849f33e2e760ed1d8a7f89",
"migrated_sha256": "4a0f135bef8ebae454693d3f40e1157d84d814d18d849f33e2e760ed1d8a7f89",
"equal": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

@@ -0,0 +1,69 @@
# 切片 08:问天、观势、观气与观心
> 基线:`2919229`(切片 07
> 回档标签:`xiaobai-preservation-slice-08-20260731`
> 结论:源码、API、数据库、真实页面、动画与全量回归通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片只移动原版问天 Agent、历法/卦象引擎、服务、持久化与三个 HTTP 入口,没有从
`next/`取用代码,也没有改写六爻、安全门、五运六气、个人合参、铜钱起卦、历史去重或
LLM 解读逻辑。
| 原位置 | 新的唯一实现位置 | 兼容方式 |
|---|---|---|
| `app/heaven_agent.py` | `app/backend/features/heaven/agent.py` | 根级模块指向同一模块对象 |
| `app/heaven_engine.py` | `app/backend/features/heaven/engine.py` | 根级模块指向同一模块对象 |
| `DashboardService`问天方法 | `app/backend/features/heaven/service.py` | `HeavenServiceMixin` |
| 问天历史持久化 | `app/backend/features/heaven/repository.py` | `HeavenRepositoryMixin` |
| 三个问天 POST 入口 | `app/backend/features/heaven/http.py` | `HeavenHttpMixin` |
历法引擎搬迁后仍从`app/vendor``app/data/iching_zh.json`读取原资源;这是唯一资源路径适配,
顶层函数与类定义未变。旧测试依赖的根级模块继续有效。
## 2. 源码等价
- `heaven_agent.py`与原版文件 SHA-256 一致。
- `heaven_engine.py`所有顶层函数和类与原版无位置信息 AST 一致。
- 20个问天服务方法中19个与原版 AST 一致;`_heaven_reading_identity`仅将旧巨型类名
`DashboardService`替换为已归位的`MarketServiceMixin`静态日期格式化方法。
- 5个问天 Repository 方法与原版 AST 一致。
- 三个 HTTP 方法只把全局`SERVICE`改为 Mixin 的`self.application_service`,状态码、字段和异常语义不变。
- `DashboardService``ReviewDatabase``RequestHandler`不再重复保留已迁移实现。
## 3. API 与数据库差分
- 原版`8788`和迁移版`8789`使用同一正式数据库的两个临时副本。
- 固定日期的问天初始化、三类历史读取、六爻成卦和个人五行计算共6个接口,状态码与业务 JSON 完全一致。
- 未调用真实`/api/heaven/interpret`,避免外部模型波动及测试记录写入;提示词和调用链由源码等价与单元测试覆盖。
- 两版均为62个 schema 对象;`heaven_readings``users``system_settings``llm_usage`
`user_birth_profiles``sector_phase_overrides`逐行一致。
- 差分只在系统临时目录副本运行,正式数据库未写入问天记录或 LLM 用量。
## 4. 真实浏览器与动画检查
- 1920×1080视口逐页检查观势、观气、观心,无横向溢出,页面滚动边界可用。
- 观势保留星空、三才六爻与八卦待载入场景;观气生成100个星点,五运六气环动画名为`wt-spin`
五行行业默认折叠;观心呼吸波纹、香火燃烧和阶段文字均持续运行。
- 夜间模式问天背景为`rgb(11, 17, 32)`,全页无控制台错误。
- 没有触发真实解势、解运或解卦调用,加载动画的静态资产及脚本未改动。
- 截图 SHA-256
- `heaven-trend-1080.png``9e70d9cbfd741e74d3c4511c0e76ef8e625a6a31fd5d6bde014103f807bcc76e`
- `heaven-fortune-1080.png``e4cdf0e0fc1d9325724654a781febed1d509e49ddccecb3355803b5e9f1d2f5c`
- `heaven-heart-breathing-1080.png``3493a59b9032c1a8a1ba7da609b499c736170d2c7947b3aa0ac4c8b95d981ff5`
- `heaven-heart-dark-1080.png``3d346fea6b593fa4e43037f5fc68eda1a3f3446a223c2022d9084922f646a088`
## 5. 自动验证与保留边界
| 验证 | 结果 |
|---|---:|
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
| 迁移版`python -m unittest discover -s tests -q` | 280项通过 |
| `python -m unittest tests.test_preservation_slice_heaven -q` | 7项通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过(2.2分钟) |
| `git diff --check` | 通过 |
- 复盘助手、交易日志、自选、笔记与提醒属于切片09,本切片不提前移动。
- 前端 DOM、页面 JS、CSS和移动端行为未改动,统一归档延至切片10。
- `static/heaven-loading.js`是否失效仍不确定,继续保留到切片11试删。
- 没有删除待定代码、没有修改正式数据库、没有测试或切换 Docker/NAS。
@@ -0,0 +1,71 @@
{
"all_equal": true,
"endpoints": [
{
"name": "heaven setup awaiting stock selection",
"method": "GET",
"endpoint": "/api/heaven/setup?trade_date=2026-07-29",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "b72f2e972c3993717d639d1ccc68a9f1fb716a5846823a485a05458103465b92",
"migrated_sha256": "b72f2e972c3993717d639d1ccc68a9f1fb716a5846823a485a05458103465b92",
"equal": true,
"first_difference": null
},
{
"name": "trend interpretation history",
"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": "fortune interpretation history",
"method": "GET",
"endpoint": "/api/heaven/readings?mode=fortune&limit=20",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "e60debaad54c58ad34fc7f025bfeaba7d2349aee2531b3f507c6e1968dbdcbf0",
"migrated_sha256": "e60debaad54c58ad34fc7f025bfeaba7d2349aee2531b3f507c6e1968dbdcbf0",
"equal": true,
"first_difference": null
},
{
"name": "heart interpretation history",
"method": "GET",
"endpoint": "/api/heaven/readings?mode=heart&limit=20",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "1fe13531909c83c645b4fbb6740f46f2590adb346ab6e43414023967bb51b072",
"migrated_sha256": "1fe13531909c83c645b4fbb6740f46f2590adb346ab6e43414023967bb51b072",
"equal": true,
"first_difference": null
},
{
"name": "six-line hexagram calculation",
"method": "POST",
"endpoint": "/api/heaven/hexagram",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "9773a9f288ea5fbe063b778fc47c613972fd7747f8fc6f80333316f33923c960",
"migrated_sha256": "9773a9f288ea5fbe063b778fc47c613972fd7747f8fc6f80333316f33923c960",
"equal": true,
"first_difference": null
},
{
"name": "personal five-phase calculation",
"method": "POST",
"endpoint": "/api/heaven/personal",
"original_status": 200,
"migrated_status": 200,
"original_sha256": "3b179ea4e3e0b43d12e929b4057a51264772fadcf41e5c87573dc5d18873bc9e",
"migrated_sha256": "3b179ea4e3e0b43d12e929b4057a51264772fadcf41e5c87573dc5d18873bc9e",
"equal": true,
"first_difference": null
}
]
}
@@ -0,0 +1,42 @@
[
{
"name": "heaven setup awaiting stock selection",
"method": "GET",
"endpoint": "/api/heaven/setup?trade_date=2026-07-29",
"payload": null
},
{
"name": "trend interpretation history",
"method": "GET",
"endpoint": "/api/heaven/readings?mode=trend&limit=20",
"payload": null
},
{
"name": "fortune interpretation history",
"method": "GET",
"endpoint": "/api/heaven/readings?mode=fortune&limit=20",
"payload": null
},
{
"name": "heart interpretation history",
"method": "GET",
"endpoint": "/api/heaven/readings?mode=heart&limit=20",
"payload": null
},
{
"name": "six-line hexagram calculation",
"method": "POST",
"endpoint": "/api/heaven/hexagram",
"payload": {
"lines": [7, 8, 9, 6, 7, 8]
}
},
{
"name": "personal five-phase calculation",
"method": "POST",
"endpoint": "/api/heaven/personal",
"payload": {
"trade_date": "2026-07-29"
}
}
]
@@ -0,0 +1,59 @@
{
"all_equal": true,
"schema": {
"object_count": 62,
"original_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"migrated_sha256": "60a4e044f0ddb6502e44b45f65bedc1a0a31d4bd596f386d4ccfe153a6c8ddd1",
"equal": true
},
"tables": [
{
"table": "heaven_readings",
"original_count": 31,
"migrated_count": 31,
"original_sha256": "e6cfc86f010fb182d7522bb99e5d268e826f93896035172120df51a011590951",
"migrated_sha256": "e6cfc86f010fb182d7522bb99e5d268e826f93896035172120df51a011590951",
"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
},
{
"table": "user_birth_profiles",
"original_count": 1,
"migrated_count": 1,
"original_sha256": "2a74d4b2edd3a730a46f17fb6ab3926575c42662c1d968643b0d54586ab68b13",
"migrated_sha256": "2a74d4b2edd3a730a46f17fb6ab3926575c42662c1d968643b0d54586ab68b13",
"equal": true
},
{
"table": "sector_phase_overrides",
"original_count": 0,
"migrated_count": 0,
"original_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"migrated_sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
"equal": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -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

@@ -0,0 +1,70 @@
# 切片 10:前端 Shell、页面、样式与移动端职责归位
> 基线:`38de3de`(切片 09
> 回档标签:`xiaobai-preservation-slice-10-20260731`
> 结论:源码、静态资产、API、数据库、桌面/移动页面及动画差分通过;最终视觉仍等待全站人工验收
## 1. 原实现归位
本切片只移动和拆分原版前端源码,没有从`next/`取用代码,也没有重写页面、样式、动画、交互或响应式规则。
| 原位置 | 新位置 | 处理方式 |
|---|---|---|
| `static/index.html` | `app/frontend/index.html` | 原 DOM 骨架,仅调整静态资源路径和拆分脚本加载顺序 |
| `static/app.js` | `app/frontend/app.js``pages/*/page.js``pages/market/runtime.js``shared/export.js` | 按连续源码行机械拆分 |
| `static/styles.css`等公共样式 | `app/frontend/styles/` | 字节级移动 |
| `static/wentian-v2.css` | `app/frontend/pages/heaven/page.css` | 字节级移动 |
| `static/ui-core.js` | `app/frontend/shared/ui-core.js` | 字节级移动 |
| `static/heaven-loading-v2.js` | `app/frontend/pages/heaven/loading-v2.js` | 字节级移动 |
| `static/pages/``shared/``vendor/` | `app/frontend/`同职责目录 | 字节级移动 |
`app/backend/bootstrap/config.py`现在只把静态根目录从`app/static/`切换到`app/frontend/`。原`app/static/`已不再存在,避免形成两套可被误改的前端实现。
## 2. 源码与静态资产等价
-`static/app.js`共 9,283 行,SHA-256 为`c020d0bc68f8a96b352a0ffa62c913a0ea3f5ca0afc41f70969f833e447166a6`
- 所有拆分文件中的保真源码片段按原行号重组后,SHA-256仍为同一值,9,283行无遗漏、无重排、无内容变化。
- 七层原版样式、问天样式、加载动画、共享脚本、页面注册脚本及Lucide供应商文件在移动后保持字节一致。
- `index.html`的差异仅限资源新路径和两个机械拆分脚本入口;反向替换后与原版逐字符一致。
- 浏览器请求仍只有`shared/api.js`一个`fetch`出口。
- 完整行号映射见`frontend-source-map.json`。该映射继续作为切片10的历史证据;一次性拆分工具在人工验收和当前所有者契约建立后已退役,不再进入维护工具链。
## 3. API 与数据库差分
- 同一管理员账号和同一固定日期下,对原版与迁移版执行21个全站只读请求。
- 请求覆盖账号、行情、情绪、轮动、竞价、题材、人气、龙虎榜、选股、问师、问天、复盘与提醒;状态码和规范化业务JSON全部一致。
- 两个数据库副本均包含62个schema对象,schema哈希一致。
- 21张关键表的记录数、顺序和规范化内容逐行一致;`screener_strategies`仅排除每次初始化可能更新的`updated_at`
- 完整结果见`api-requests.json``api-diff.json``database-diff.json`,两份差分文件的`all_equal`均为`true`
## 4. 真实浏览器差分
- 1920×1080日间模式检查情绪周期、智能选股、观势、观气、观心介绍及观心呼吸。
- 1920×1080夜间模式检查情绪周期的背景、字体、表格、几何和横向溢出。
- 390×844检查情绪周期与观势:移动Shell、底部五入口、页面纵向滚动、无横向溢出及问天特效均一致。
- 观势星空节点90个、观气100个、观心110个;三页八卦节点均为2个。
- 观势与观气保留`wt-tw``wt-spin`动画;观心呼吸保留`heart-incense-burn``heart-incense-glow`及动态波纹。
- 观气五行行业为5组且默认折叠;观心介绍到呼吸流程可正常进入。
- 原版和迁移版检查流程均未产生新增控制台error或warn。
- 动画帧、焦点框和动态状态文字属于采样瞬时状态,因此截图文件哈希不要求相同;可见布局几何、计算样式、节点、动画名称和交互结果必须一致,本次均通过。
- 两个服务使用相同主机名、不同端口时会共享并覆盖登录Cookie;曾导致迁移版切页被误判为失效。逐服务重新登录后行为一致,该问题属于并行验收环境限制,不是产品回归。
- 2026-08-01像素复核发现`frontend-migrated-auction-light-1920x1080`实际截取了登录状态失效页,
不能证明集合竞价视觉等价,文件已重命名为`INVALID-login-session`。集合竞价仍有切片05真实页面、
本切片源码/样式保真、API及Playwright证据,但最终视觉明确留待人工验收,不以替代证据冒充
本切片截图差分。
- 机器可读记录见`browser-acceptance.json`,截图均保存在本目录。
## 5. 自动验证与保留边界
| 验证 | 结果 |
|---|---:|
| 前端专项测试 | 85项通过 |
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
| 迁移版`python -m unittest discover -s tests -q` | 294项通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过(2.3分钟) |
| 全部拆分后JavaScript执行`node --check` | 通过 |
| `git diff --check` | 通过 |
- `demo_data.py``frontend/heaven-loading.js`、五个疑似无引用前端函数和`wencai_saved_queries`继续保留到切片11逐项审计。
- 没有修改`next/`、正式数据库、Docker/NAS或`8765`服务。
- 自动差分只能证明已检查范围一致;依据迁移总纲,未经用户最终人工确认不得宣称全站视觉已经完全等价。
@@ -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": "a1f81967a58dae0947191fe1a7465c87e70403339e36897329de94c541272e05",
"migrated_sha256": "a1f81967a58dae0947191fe1a7465c87e70403339e36897329de94c541272e05",
"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": "bd75b100485c0afa0cdddc73d1880160eea8c0b8c91f556245c665d591285ed6",
"migrated_sha256": "bd75b100485c0afa0cdddc73d1880160eea8c0b8c91f556245c665d591285ed6",
"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": "173baf4e1f0b56678aef3f74276f29af49271ea34c89c0c18283bfe27f5cf2a6",
"migrated_sha256": "173baf4e1f0b56678aef3f74276f29af49271ea34c89c0c18283bfe27f5cf2a6",
"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": "495a1f83ed661913807899e0955ef1b89193c30bc9a5be0587f7f03d60411d95",
"migrated_sha256": "495a1f83ed661913807899e0955ef1b89193c30bc9a5be0587f7f03d60411d95",
"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,29 @@
[
{"name": "当前账号", "method": "GET", "endpoint": "/api/auth/me", "exclude_paths": ["$.csrf_token"]},
{"name": "账号状态", "method": "GET", "endpoint": "/api/account/status"},
{"name": "全市场总览", "method": "GET", "endpoint": "/api/dashboard?trade_date=2026-07-30"},
{"name": "情绪周期历史", "method": "GET", "endpoint": "/api/sentiment/history?trade_date=2026-07-30&limit=9"},
{"name": "板块轮动历史", "method": "GET", "endpoint": "/api/rotation/history?trade_date=2026-07-30&limit=9"},
{"name": "集合竞价", "method": "GET", "endpoint": "/api/auction?trade_date=2026-07-30", "exclude_paths": ["$.meta.updated_at"]},
{"name": "题材库", "method": "GET", "endpoint": "/api/themes?trade_date=2026-07-30"},
{"name": "人气热榜", "method": "GET", "endpoint": "/api/popularity?trade_date=2026-07-30"},
{"name": "龙虎榜", "method": "GET", "endpoint": "/api/dragon-tiger?trade_date=2026-07-30"},
{"name": "游资档案", "method": "GET", "endpoint": "/api/dragon-tiger/profiles"},
{
"name": "智能选股工作区",
"method": "GET",
"endpoint": "/api/screener/setup?trade_date=2026-07-30",
"sort_lists": {"$.strategies": "id"},
"exclude_paths": ["$.strategies[].updated_at"]
},
{"name": "策略持续跟踪", "method": "GET", "endpoint": "/api/screener/tracking?limit=12"},
{"name": "问师模型库", "method": "GET", "endpoint": "/api/mentors/setup?trade_date=2026-07-30"},
{"name": "问师历史", "method": "GET", "endpoint": "/api/mentors/messages?mentor_id=kobe92-perspective&trade_date=20260730"},
{"name": "问天初始化", "method": "GET", "endpoint": "/api/heaven/setup?trade_date=2026-07-30"},
{"name": "问天历史", "method": "GET", "endpoint": "/api/heaven/readings?mode=trend&limit=20"},
{"name": "自选追踪", "method": "GET", "endpoint": "/api/watchlist?trade_date=2026-07-30"},
{"name": "全部复盘笔记", "method": "GET", "endpoint": "/api/notes?scope=all"},
{"name": "交易日志", "method": "GET", "endpoint": "/api/trades?end_date=2026-07-30"},
{"name": "提醒中心", "method": "GET", "endpoint": "/api/alerts?status=all&as_of=2026-07-30"},
{"name": "复盘助手历史", "method": "GET", "endpoint": "/api/assistant/messages"}
]
@@ -0,0 +1,101 @@
{
"schema_version": 1,
"tested_at": "2026-07-31T12:00:00+08:00",
"result": "passed_with_documented_evidence_gap",
"environments": {
"original": "temporary_original_runtime",
"migrated": "temporary_app_runtime",
"account": "administrator",
"database": "isolated_copies"
},
"viewports": [
{
"width": 1920,
"height": 1080,
"theme": "light",
"views": [
"sentiment",
"screener",
"heaven_trend",
"heaven_fortune",
"heaven_heart_intro",
"heaven_heart_breath"
],
"equal": true
},
{
"width": 1920,
"height": 1080,
"theme": "dark",
"views": [
"sentiment"
],
"equal": true
},
{
"width": 390,
"height": 844,
"theme": "light",
"views": [
"sentiment",
"heaven_trend"
],
"equal": true
}
],
"invalid_captures": [
{
"view": "auction",
"file": "frontend-migrated-auction-light-1920x1080.INVALID-login-session.png",
"reason": "The migrated capture shows an expired login session and is not visual-equivalence evidence.",
"replacement_claim": "No replacement screenshot claim; final visual acceptance remains manual."
}
],
"heaven_animation_contract": {
"trend_star_nodes": 90,
"fortune_star_nodes": 100,
"heart_star_nodes": 110,
"bagua_nodes_per_view": 2,
"trend_and_fortune_animations": [
"wt-tw",
"wt-spin"
],
"heart_breath_animations": [
"heart-incense-burn",
"heart-incense-glow"
],
"fortune_industry_groups": 5,
"fortune_industries_collapsed_by_default": true,
"equal": true
},
"mobile_contract": {
"primary_navigation_items": 5,
"horizontal_overflow": false,
"vertical_page_scroll": true,
"heaven_trend_geometry": {
"active": {
"height": 723,
"width": 374,
"x": 8,
"y": 50
},
"header": {
"width": 390,
"height": 50
},
"bottom_navigation": {
"width": 390,
"height": 58
}
},
"equal": true
},
"console": {
"new_errors": 0,
"new_warnings": 0
},
"screenshot_policy": "Dynamic animation frames, focus outlines, and live status text may change pixel hashes. Acceptance compares visible geometry, computed styles, DOM state, animation names, interaction results, and overflow behavior.",
"known_test_environment_constraint": "Original and migrated services on the same hostname share cookies across ports. Each service must be logged in separately immediately before comparison.",
"all_equal": true,
"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": "40b1ee5678b32f29ae356c1b30958e66138d34afd2aa6b8364fa02c23df66553",
"migrated_sha256": "40b1ee5678b32f29ae356c1b30958e66138d34afd2aa6b8364fa02c23df66553",
"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": []
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

@@ -0,0 +1,190 @@
{
"source": "static/app.js",
"source_sha256": "c020d0bc68f8a96b352a0ffa62c913a0ea3f5ca0afc41f70969f833e447166a6",
"source_line_count": 9283,
"reassembled_sha256": "c020d0bc68f8a96b352a0ffa62c913a0ea3f5ca0afc41f70969f833e447166a6",
"all_source_lines_preserved": true,
"core": {
"target": "app/frontend/app.js",
"ranges": [
{
"start": 1,
"end": 1206
},
{
"start": 3471,
"end": 3489
},
{
"start": 8427,
"end": 8904
},
{
"start": 9052,
"end": 9283
}
]
},
"modules": [
{
"target": "app/frontend/pages/sentiment/page.js",
"ranges": [
{
"start": 1207,
"end": 1516,
"sha256": "70a884362b3f97ceb28e2f3a83a70ce26e61c79e23bfeee62b301b9068f2b69c"
}
]
},
{
"target": "app/frontend/pages/pools/page.js",
"ranges": [
{
"start": 1517,
"end": 1915,
"sha256": "ff8623609c1ef6eb793deaef2b627746727a4768962711d1712e35833b4f58c3"
}
]
},
{
"target": "app/frontend/pages/market/runtime.js",
"ranges": [
{
"start": 1916,
"end": 1957,
"sha256": "703dafd0417926df8572a885ffa32a79ee16346019f0e14fcee9e03ad1f1baf7"
},
{
"start": 6893,
"end": 7719,
"sha256": "a670986ac2099a181f5f348cd48bc4777da0d4709b3ac79239067ff5666261fb"
},
{
"start": 7969,
"end": 8426,
"sha256": "467409c2cfc06ee96bb7f422be55f79920c3a9936229b2234dd8f78b537e7f26"
}
]
},
{
"target": "app/frontend/pages/rotation/page.js",
"ranges": [
{
"start": 1958,
"end": 2124,
"sha256": "33f536213db33be0934527f13527712a9d521b5f89a5784b42887c5bf8631f2f"
}
]
},
{
"target": "app/frontend/pages/ladder/page.js",
"ranges": [
{
"start": 2125,
"end": 2216,
"sha256": "2be84071921910acbec2328f1f10dd8565420ea03a1930ff255040bf99d679a8"
}
]
},
{
"target": "app/frontend/pages/auction/page.js",
"ranges": [
{
"start": 2217,
"end": 2481,
"sha256": "7f16901ae8769b9570693211022538feb02f2cda4bffe6fa95ba6ce60c10b012"
}
]
},
{
"target": "app/frontend/pages/themes/page.js",
"ranges": [
{
"start": 2482,
"end": 2583,
"sha256": "c134d762bda669483f0c094efae9281919b68b2ffb83c9457670bc9013ce1515"
}
]
},
{
"target": "app/frontend/pages/popularity/page.js",
"ranges": [
{
"start": 2584,
"end": 2659,
"sha256": "db72e42385e4a4bd4314ab471b27c1bb804f13650ee463f0843d783b0ba50bff"
}
]
},
{
"target": "app/frontend/pages/dragon-tiger/page.js",
"ranges": [
{
"start": 2660,
"end": 3028,
"sha256": "b33ccad80ce997bddd75e4025eec35aa246fa5e9f5ca9ccd5f17e587885274cd"
}
]
},
{
"target": "app/frontend/pages/review/page.js",
"ranges": [
{
"start": 3029,
"end": 3470,
"sha256": "10dba1966b32941cb28ac46d1cb1b20ae74ea271fd7be22a23b46d290ece80ef"
},
{
"start": 7720,
"end": 7968,
"sha256": "3af64079f997fabbf0ff4023088eb62f94c0091a823bd6d65c1f9e485d1c5ad8"
}
]
},
{
"target": "app/frontend/pages/screener/page.js",
"ranges": [
{
"start": 3490,
"end": 4336,
"sha256": "76dfdd5610453f0abb5899baba9d751b5f597450ec656bf10580ce91447a68b9"
},
{
"start": 6668,
"end": 6892,
"sha256": "a7d0fa98b07516169a8e46c2ae2f6efbaeab651887c479919210835f0877533e"
}
]
},
{
"target": "app/frontend/pages/mentor/page.js",
"ranges": [
{
"start": 4337,
"end": 4827,
"sha256": "b2067c062fb6cb539dd6402074d02f1ae65903957106d7ebf8d63bc5487f244c"
}
]
},
{
"target": "app/frontend/pages/heaven/page.js",
"ranges": [
{
"start": 4828,
"end": 6667,
"sha256": "57bd47c239c4ee9302c7cd7a1f86a5d0932df6065148a34bafe0c49bef644cb1"
}
]
},
{
"target": "app/frontend/shared/export.js",
"ranges": [
{
"start": 8905,
"end": 9051,
"sha256": "17b867189087615a4414da4f9db3862306e05cb527c25c794beb9c4c74b583ab"
}
]
}
]
}
@@ -0,0 +1,108 @@
# 切片 11:不确定代码审计、全量验收与交接准备
> 基线:`dec3cd12365df5e7d4c391369f14c457cf56d7d9`
> 候选回档标签:`xiaobai-preservation-slice-11-candidate-20260731`
> 严格审计候选标签:`xiaobai-preservation-slice-11-audit-candidate-20260731`
> 跨日复验候选标签:`xiaobai-preservation-slice-11-audit-candidate-20260801`
> 独立维护候选标签:`xiaobai-preservation-slice-11-audit-candidate-standalone-20260801`
> 最终完成标签:`xiaobai-preservation-complete-20260801`
> 当前结论:自动与用户人工验收均已完成;本地迁移交付完成,尚未执行正式切换、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` | 305项通过 |
| 历史切片与前端/清理专项复核 | 通过 |
| 迁移版JavaScript语法检查 | 24个文件通过 |
| `npx.cmd playwright test --reporter=dot` | 45项通过(1.6分钟) |
| 固定只读API差分 | 21个端点全部一致 |
| 数据库差分 | 62个schema对象、21张关键表全部一致 |
| `git diff --check` | 通过 |
2026-08-01 01:19Asia/Shanghai)跨日复验时,原版与迁移版共用的实时详情测试暴露出
测试夹具依赖运行日的问题:夹具在周六动态生成“今日”,而业务正确拒绝在非交易日合并实时
行情。两版测试夹具同步固定到明确的工作日盘中/盘前时点,产品代码与行情日期规则未改。
修复后统一验收命令再次通过302项测试、24个JavaScript文件、SQLite完整性和45项Playwright
2.0分钟)。
早期切片的五个前端源码测试原本要求与未试删的`static/app.js`逐字符一致。本切片验收时曾通过
行号回放机制限制未登记改动。完成全站人工验收及前端所有权治理后,该过渡机制已退役;当前由
运行时注册表、唯一所有者、DOM/API契约、JavaScript语法检查和Playwright行为回归持续守门。
完整API和数据库结果分别见`api-diff.json``database-diff.json`,二者`all_equal`均为`true`
严格完成审计另外验证了候选维护工具本身:API注册表和候选架构清单均可生成并执行
`--check`;24个前端脚本全部由统一命令发现;迁移期写入工具必须显式指定输出或`--apply`
Windows下Playwright托管Python静态服务器会在45项执行后不退出,统一验证器现改为显式启动、
探活和停止8876;最终同一命令正常退出并明确报告`45 passed`。四项维护工具契约测试使迁移版
总数从298增加到302。逐项目标矩阵见`completion-audit.md`
后续独立性审计把仅含`app/`的Git导出放到系统临时目录:运行模块全部解析到导出内部,统一
维护命令通过242项候选自有测试、两个注册表、24个JavaScript文件和SQLite完整性检查,并明确
跳过不存在的Git工作区。正式仓库继续执行全部保真差分,最终为305项Python测试和45项
Playwright通过。架构热点字节数已改为换行归一化后的UTF-8大小,Windows CRLF与Git/Linux LF
不会再制造假差异。
## 3. 真实浏览器验收
- 桌面端复核情绪周期、智能选股三个工作区、问天日间/夜间和加载资源;控制台无新增
error或warn,页面无横向溢出。
- 问天只加载`/pages/heaven/loading-v2.js`,未请求已试删的`/heaven-loading.js`
- 观势、观气、观心星空与八卦节点、原动画名称和可见行为保持不变。
- `390x844`逐一点击涨停池、智能选股、问师、问天、我的复盘五个移动入口;底部导航固定,
页面均可完整纵向滚动且没有文档级横向溢出。
- 观势、观气、观心三页均复核;观气滚动到底后“个人合参”和“五行对应行业”可达。
- 同账号、同数据库快照、同主题和同视口下,原版与迁移版问天布局和计算样式一致。
机器可读记录见`browser-acceptance.json`。截图和更广的桌面/移动基线继续沿用切片10证据目录。
切片10截图的事后像素复核见`screenshot-pixel-audit.json`;九组有效截图平均色差低于0.3/255,
集合竞价候选图因登录状态失效被明确排除,未作为自动截图证据。2026-08-01用户随后在`8797`
真实登录状态下逐页检查全部页面并测试全部功能,确认视觉与功能迁移成功;所见问题几乎都
属于原版遗留问题,未发现阻止验收的迁移回归。完整人工结论见`manual-acceptance.md`
## 4. 数据与部署边界
- API/数据库比较使用两个隔离副本:`slice11-final-original``slice11-final-migrated`
- 没有写入根目录正式`data/review.db`,没有修改`.env`或私有Skill。
- 没有占用`8765`,没有执行Docker构建、NAS测试或服务器切换。
- `app/`已经完成本地迁移验收;原版根目录仍是当前部署基线和切换前回档来源。
- `next/`保持冻结,没有作为代码、样式、测试或文档来源。
## 5. 回档与最终确认
2026-08-01用户完成全部页面和功能人工验收,确认迁移在视觉和功能上成功,并确认人工检查中
发现的问题几乎都属于原版遗留问题。切片11的2个文件和5个无消费者函数据此从“候选试删”改为
“确认废弃”;恢复标签继续保留作历史兼容应急,不代表删除结论仍待裁决。
本地迁移收尾已执行:
1. 试删候选状态改为“确认废弃”。
2. 建立最终完成标签并推送Gitea。
3. `app/`作为后续结构治理的唯一开发目录。
正式数据库、原版部署、Docker和NAS仍未切换;切换时间与根目录清理必须由用户另行批准。
人工维护、验证、切换和回退步骤见`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": "0ac1b88affa62671f14ba9ea0bd42155952fdc2e03dba3573c232bb452733bc6",
"migrated_sha256": "0ac1b88affa62671f14ba9ea0bd42155952fdc2e03dba3573c232bb452733bc6",
"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": "bd75b100485c0afa0cdddc73d1880160eea8c0b8c91f556245c665d591285ed6",
"migrated_sha256": "bd75b100485c0afa0cdddc73d1880160eea8c0b8c91f556245c665d591285ed6",
"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": "1d6936e33aea2bb4258d1d4d007385626d0c638fc290b66271f00649dba59358",
"migrated_sha256": "1d6936e33aea2bb4258d1d4d007385626d0c638fc290b66271f00649dba59358",
"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": "b611e936ada5d547c728e33e811630282d1eecd7c1ab1517e22b34902eda032a",
"migrated_sha256": "b611e936ada5d547c728e33e811630282d1eecd7c1ab1517e22b34902eda032a",
"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,83 @@
# 保真迁移完成度逐项审计
> 审计对象:`webapp/app/`
> 审计基线:`xiaobai-preservation-slice-11-candidate-20260731`
> 结论口径:自动证据通过不替代用户人工验收,也不授权部署切换
本审计回答的不是“测试是否为绿色”,而是迁移总纲、批准目录、产品表面和人工维护目标是否
分别有可复验的证据。状态只使用:`自动闭环``人工闭环``明确保留``未执行`
## 1. 目标与证据矩阵
| 要求 | 当前实现 | 主要证据 | 状态 |
|---|---|---|---|
| 原版是唯一产品/视觉基线 | 所有切片从根目录原版复制或机械移动;规格书不覆盖真实行为 | 总纲;切片00-11源码映射 | 自动闭环 |
| `next/`完全隔离 | `next/`未进入候选导入、资产、测试或部署路径;切片10后Git差分为0 | `next失败冻结记录.md`Git路径审计 | 自动闭环 |
| 批准的模块化单体目录 | `backend/{bootstrap,http,features,data,database,jobs,llm}``frontend/{shared,pages,styles,vendor}``config/data/tests/tools`均已归位 | `app/config/architecture-inventory.json`;切片01-10 | 自动闭环 |
| 不制造第二套产品实现 | 根入口是兼容外壳;业务方法从原类机械移动,专项测试逐符号比较AST/哈希 | 切片01-10 preservation tests | 自动闭环 |
| 16个主工作区及内部能力完整 | 页面注册表有16个主工作区;策略跟踪、搜索、详情、提醒、账户和系统管理保留 | `pages.config.json`;前端边界测试;Playwright | 自动闭环 |
| API路径、权限、错误语义不变 | 53个精确路径和11个正则路径有唯一所有者;鉴权在后端执行 | `api.config.json`;HTTP/权限测试;21端点差分 | 自动闭环 |
| 数据源有统一边界和质量规则 | 18个数据集登记来源、用途、单位、新鲜度、覆盖率、复权和失败关闭规则 | data registriesDataGateway/quality tests | 自动闭环 |
| 数据库无损、用户隔离不变 | 36张表由初始schema和有序migration管理;62个schema对象、21张关键表差分相同 | 数据库差分;migration/repository/account-boundary tests | 自动闭环 |
| 后台任务可追踪和重试 | 3个任务登记调度、锁、超时、重试和输出版本;运行状态持久化 | `jobs.config.json`job runner tests | 自动闭环 |
| LLM唯一治理边界 | 问师、问天、复盘助手和策略编译经统一网关执行会员、额度、模型回退、流式和审计规则 | 切片07/09LLM gateway/stream tests | 自动闭环 |
| 前端唯一请求出口、Shell和页面职责 | 只有`frontend/shared/api.js`调用业务数据`fetch`;Shell、状态、弹窗、页面生命周期及页面模块已归位 | frontend boundary tests;运行时注册表;Playwright | 自动闭环 |
| CSS、主题、动画和移动行为不改写 | 原七层CSS和问天动画按字节/源码移动;令牌层与加载顺序受测试保护;用户逐页确认无迁移视觉回归 | CSS governance;切片10/11浏览器证据;`manual-acceptance.md` | 人工闭环 |
| 不确定代码先记录再试删 | 2个文件和5个无消费者函数经自动与人工验收确认废弃;历史表兼容责任继续保留 | `uncertain-code-audit.md`cleanup contract`manual-acceptance.md` | 人工闭环 |
| 可由人工维护者复验 | 候选README/架构说明、工具分类、API/架构生成器、统一验证命令均可从`app/`独立运行;系统临时目录导出实测242项候选测试通过 | `app/tools/README.md`maintenance tool tests;独立导出复验 | 自动闭环 |
| 正式数据库与部署不受影响 | 验收只使用隔离SQLite副本和非8765端口 | 各切片README;运行记录 | 自动闭环 |
| Docker/NAS和正式入口切换 | 用户已明确本轮不做NAS Docker测试;人工验收前禁止切换 | 迁移状态和切换指南 | 未执行 |
## 2. 结构减法的可量化结果
-`server.py`从原版约5,851行降为25行稳定入口;实现归入启动、HTTP和产品领域模块。
-`database.py`从原版2,839行降为746行,只保留初始schema、组合入口及有明确历史兼容责任的
方法;各领域查询已移入对应Repository。
- 20个其他根Python兼容模块均为1-15行导出/模块别名,不含第二套实现。
- 原9,283行前端运行时按原连续源码范围拆入共享层和13个页面目录;该行号映射作为迁移历史
证据保留,日常维护改由当前模块所有权和行为回归约束。
- 已确认没有消费者的`demo_data.py`、旧问天加载文件和5个函数进入可单项恢复的试删候选;
`wencai_saved_queries`因旧数据库兼容和账号隔离继续保留。
大文件不等于自动可删。筛选引擎、Tushare适配器、问天确定性计算和原CSS仍是单一有效实现;
在没有更细的同输入差分与人工视觉确认前继续拆分,反而违反“整理原件而非重拍”的迁移约束。
它们已登记在`config/architecture-inventory.json``code_hotspots`,供后续正常维护按领域处理。
## 3. 本次严格审计发现并关闭的缺口
候选版初次自动验收后,三个维护工具仍带有旧目录假设:基线验证器引用不存在的`static/`
架构清单写向不存在的候选文档目录,原样清单生成器假设`app/app`且会因试删文件直接异常。
这些问题不改变产品页面,却会让接管者无法按指南复验,因此不能视为可维护性完成。
关闭方式:
1. 基线验证器改为检查候选全量测试、两个生成注册表、`frontend/`下全部JavaScript、Git差异和
测试数据库完整性。
2. 候选架构清单固定生成到`config/architecture-inventory.json`,从正式候选路径统计16页、
64类路由匹配、36张表、供应商/LLM入口、CSS层和热点文件。
3. 原样资产清单、方法搬运和前端拆分明确标为迁移期工具;可能写文件的操作必须显式传路径或
`--apply`,默认帮助路径不改文件。
4. 新增维护工具契约测试,保证生成文件新鲜、所有工具`--help`可用,旧`static/`路径不会回归。
5. 跨到2026-08-01周六后,实时详情测试中用运行日构造的“固定时间”不再代表交易日;原版和
候选测试夹具同步固定到明确工作日,消除跨午夜/周末不确定性。产品实现与交易日规则未改,
随后统一验收再次通过302项Python测试和45项Playwright。
6. 独立导出`app/`后成功启动健康接口,236项非迁移业务/前端测试通过;同时发现六项日常前端
契约经辅助函数隐式读取旧`static/app.js`。完成人工验收后,日常契约已改为装配当前注册脚本;
只有确有价值的静态资产、页面前缀及后端AST差分继续读取原版,避免历史源码回放成为第二套维护对象。
7. 对切片10十组截图重新做像素审计,九组平均色差均低于0.3/255;集合竞价候选图实际为登录
失效页,已明确标为无效并撤销其截图证明力。集合竞价最终视觉继续列为人工验收项。
8. 统一验证器现在按环境选择完整保真套件或候选自有套件;系统临时目录中的纯`app/`导出通过
242项测试、注册表、24个JavaScript文件和SQLite检查。架构热点大小按归一化UTF-8计算,
CRLF/LF不再导致清单失效;正式仓库最终通过305项测试和45项Playwright。
## 4. 最终人工裁决与部署边界
2026-08-01用户在隔离端口`8797`浏览全部页面并测试全部功能,确认视觉与功能迁移成功;发现的
问题几乎都属于原版遗留问题,未发现阻止验收的迁移回归。该结论已经关闭以下迁移裁决:
1. 切片11试删候选确认为废弃,恢复标签继续保留。
2. 页面视觉、功能、交互和动画的人工验收完成。
3. 允许建立本地迁移完成标签并推送Gitea。
该结论不授权切换正式数据库、Docker或NAS,也不授权删除根目录原版、数据库备份或冻结的
`next/`记录。部署切换继续以`人工维护与本地切换指南.md`为准,并须单独获得用户批准。
@@ -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": "3fd3b7ceb0950d543fba9cebdd2b4294fe187b37a6b8d4755a49428661b3ae1c",
"migrated_sha256": "3fd3b7ceb0950d543fba9cebdd2b4294fe187b37a6b8d4755a49428661b3ae1c",
"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,33 @@
# 切片 11:用户人工验收记录
> 验收日期:2026-08-01
> 验收地址:`http://127.0.0.1:8797/`
> 数据边界:迁移审计数据库副本,未写正式数据库
> 结论:通过
## 验收范围
用户在迁移版中浏览了全部页面,并测试了全部可操作功能。验收覆盖页面视觉、布局、主题、
交互、动画、行情读取、LLM功能及主要写入流程。验收期间使用的Tushare、iFinD和主LLM均完成
真实最小调用验证,迁移版能够读取数据库中加密保存的原配置。
## 用户结论
迁移版在视觉和功能上迁移成功。人工检查中发现的问题几乎全部属于原版已经存在的遗留问题;
未发现阻止本次验收的`app/`目录迁移回归。
## 最终裁决
1. 接受`app/`与原版在功能、视觉、交互和动画上的保真结果。
2. 确认切片11登记的`demo_data.py`、旧问天加载文件和5个无消费者前端函数可以永久废弃。
3. 保留`wencai_saved_queries`及证据不足的相邻资产,继续承担旧数据库兼容责任。
4. 允许建立本地迁移完成提交和标签并推送Gitea。
5. 本次验收不授权切换Docker/NAS、删除原版或改写正式数据库;部署切换必须另行决定。
## 证据关系
- 自动完成度审计:`completion-audit.md`
- 不确定代码处置:`uncertain-code-audit.md`
- 浏览器自动记录:`browser-acceptance.json`
- API和数据库差分:`api-diff.json``database-diff.json`
- 回档基线:`xiaobai-preservation-slice-10-20260731`
@@ -0,0 +1,27 @@
{
"schema_version": 1,
"audited_at": "2026-08-01T01:55:00+08:00",
"source_directory": "docs/migration/evidence/slice-10",
"difference_threshold_per_channel": 8,
"valid_pairs": [
{"view": "dark-sentiment-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.065, "changed_pixel_percent": 0.123},
{"view": "dark-sentiment-390x844", "size": "375x812", "mean_absolute_difference": 0.009, "changed_pixel_percent": 0.012},
{"view": "heaven-fortune-light-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.043, "changed_pixel_percent": 0.046},
{"view": "heaven-heart-breath-light-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.256, "changed_pixel_percent": 0.545},
{"view": "heaven-heart-intro-light-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.047, "changed_pixel_percent": 0.068},
{"view": "heaven-trend-390x844", "size": "390x844", "mean_absolute_difference": 0.284, "changed_pixel_percent": 0.712},
{"view": "heaven-trend-light-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.040, "changed_pixel_percent": 0.063},
{"view": "light-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.000, "changed_pixel_percent": 0.000},
{"view": "screener-light-1920x1080", "size": "1683x1080", "mean_absolute_difference": 0.064, "changed_pixel_percent": 0.157}
],
"invalid_pairs": [
{
"view": "auction-light-1920x1080",
"mean_absolute_difference": 15.820,
"changed_pixel_percent": 77.932,
"reason": "The migrated image is an expired-login page, not the auction workspace.",
"disposition": "Renamed INVALID-login-session and excluded from visual-equivalence evidence."
}
],
"conclusion": "Nine valid pairs are geometrically and visually consistent within dynamic rendering noise. Auction remains a manual visual acceptance item."
}
@@ -0,0 +1,91 @@
# 切片 11:不确定代码审计日志
> 审计基线:`dec3cd12365df5e7d4c391369f14c457cf56d7d9`
> 恢复标签:`xiaobai-preservation-slice-10-20260731`
> 原则:只有静态引用、动态注册、运行路径和兼容责任同时排除后才试删;其余继续保留
> 当前状态:自动与人工验收均已通过,试删项于2026-08-01确认废弃
本日志记录试删前的原位置、内容指纹、证据、决定和恢复方式。试删阶段不等于永久废弃;
2026-08-01用户完成迁移版全部页面和功能人工检查,确认视觉与功能迁移成功,所见问题几乎都
属于原版遗留问题,未发现阻止验收的迁移回归。该人工结论关闭了本日志的最终确认门槛。
## 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标签继续保留单项恢复能力。
- 恢复:从切片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标签继续保留单项恢复能力。
- 恢复:从切片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`及三个方法保持存在,并由清理契约测试持续保护。
## 7. 人工最终确认
- 验收日期:2026-08-01。
- 验收运行时:隔离端口`8797`与迁移审计数据库副本。
- 验收范围:用户逐页浏览全部页面并测试全部可操作功能。
- 验收结论:视觉与功能迁移成功;发现的问题几乎都是原版遗留问题,未发现阻止验收的迁移回归。
- 删除结论:`demo_data.py`、旧问天加载文件和上述5个无消费者函数正式确认为废弃;
`wencai_saved_queries`及证据不足的相邻DOM、状态和CSS继续保留。
确认废弃不取消恢复证据。若后续发现历史兼容责任,可从
`xiaobai-preservation-slice-10-20260731`按本日志记录单项恢复,不回退其他迁移成果。
@@ -0,0 +1,29 @@
# `next/`失败冻结记录
> 决策日期:2026-07-30
> 状态:用户验收失败,永久冻结,禁止部署
## 结论
`next/`采用重新实现方式建立,与本次迁移的真实目标不一致。用户确认其页面视觉、布局和基础功能
未达到原系统等价要求,因此该目录不再作为产品候选、迁移成果或后续重构基础。
原发布候选`xiaobai-next-rc-20260730-1`自本记录生效起作废。不得使用`next/Dockerfile`
`next/compose.yaml``next/compose.preflight.yaml`部署任何正式或预检环境。
## 冻结边界
1. `next/`只保留作失败复盘、测试思路和迁移工具参考,不再修补产品功能或视觉。
2. 后续迁移不得从`next/`反向覆盖原系统,也不得把其页面作为视觉基准。
3. 原系统仍是唯一产品事实和视觉基线;后续工作必须采用原代码保真式结构迁移。
4. 未经用户新的明确决定,不删除`next/`,不移动失败标签,不恢复其发布候选身份。
5. `next/data/`中的本地迁移副本继续保持Git忽略,不作为生产数据。
## 失败原因
- 错误地把“建立独立目录并迁移”执行成了重新设计和重新实现。
- 自动测试主要验证新实现内部契约,没有证明与原系统逐页面、逐状态、逐像素等价。
- 以代码行数下降和规格案例覆盖代替了原系统完整行为保真。
- 用户人工验收确认视觉、布局及基础功能不可作为正式产品使用。
本记录优先于`next/`内所有阶段完成、发布候选、预检和切换说明。
@@ -0,0 +1,159 @@
# 小白复盘人工维护与本地切换指南
> 历史文档:记录迁移验收期间的双版本操作,已由`docs/maintenance/人工维护指南.md`取代。
> 其中涉及父目录原版和迁移比较工具的命令不再作为当前维护流程执行。
>
> 适用目录:`webapp/app/`
> 当前状态:本地迁移已完成自动与用户人工验收;正式数据库、Docker和NAS尚未切换
## 1. 先确认哪个版本是正式版本
- 当前正式基线仍是`webapp/`根目录及根目录`data/review.db`
- `webapp/app/`是已完成人工验收的保真迁移版本,运行代码来自原版的移动、机械拆分和去重,
不是重新开发。
- `webapp/next/`是已否决的冻结版本,禁止部署、继续开发或复制实现。
- 用户人工验收前,不要删除根级原版,不要让`app/`写入正式数据库,也不要修改NAS容器。
发生产品含义冲突时,依次以用户明确决定、原版真实运行、原版源码与数据、产品规格书为准。
## 2. 迁移版目录怎么找代码
```text
app/
server.py 稳定进程入口;正式实现装配在backend/
database.py SQLite初始schema与Repository组合入口
api_access.py API访问级别注册入口
sync_data.py 手工行情同步命令
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/ 页面结构、行为与页面专属样式
config/ 页面、功能、API、任务、字段和数据质量注册表
tests/ 单元、边界、保真差分和浏览器回归
tools/ 清单、API/数据库差分和保真运行工具
data/ 运行数据库、私有Skill和备份;不提交Git
runtime/ 本地日志、缓存、PID与浏览器测试产物;不提交Git
游资skills/ 可公开的问师Skill
```
根目录不再保留业务兼容导入壳。维护业务时直接到`backend/features/<领域>/`
`backend/data/`寻找唯一实现,不得重新建立根级转发文件。所有浏览器网络请求必须继续经过
`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 tools\verify_baseline.py
python tools\verify_baseline.py --e2e
```
第一条命令已经包含迁移版全量单元测试、API/架构注册表新鲜度、全部前端JavaScript语法、
Git空白错误和测试数据库只读完整性检查。第二条额外运行Playwright。工具的日常/验收/迁移期
分类见`app/tools/README.md`;迁移期工具不是正常开发命令。
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. 人工验收清单
2026-08-01用户已在隔离端口`8797`完成全部页面和功能验收,确认视觉与功能迁移成功;所见问题
几乎都属于原版遗留问题,未发现阻止验收的迁移回归。以下清单继续作为后续结构修改和部署
切换时的回归标准:
- 用同一账号、日期和主题对照原版与迁移版全部页面。
- 检查日间/夜间、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重置覆盖正式数据或用户未提交的代码。
@@ -0,0 +1,76 @@
{
"schema_version": 1,
"updated_at": "2026-08-03T21:31:06+08:00",
"status": "standalone_closure_verified_checkpoint_pending",
"migration_mode": "behavior_preserving_source_migration",
"source_of_truth": "standalone_app_runtime_and_source",
"source_root": ".",
"target_root": ".",
"failed_roots": [],
"retired_external_roots": [
"parent original runtime",
"parent next directory"
],
"current_slice": "standalone-closure",
"last_completed_slice": "standalone-closure",
"last_automated_slice": "standalone-closure",
"last_checkpoint": "xiaobai-standalone-closure-20260803",
"next_action": "create and push the standalone closure checkpoint, then clean retired parent content in a separate reversible commit",
"authoritative_documents": [
"AGENTS.md",
"ARCHITECTURE.md",
"docs/product/小白复盘-完整产品规格说明书.md",
"docs/maintenance/人工维护指南.md"
],
"hard_invariants": [
"do_not_use_next_as_migration_source",
"do_not_rewrite_existing_product_behavior",
"do_not_change_technology_stack_without_explicit_user_approval",
"preserve_visual_interaction_animation_calculation_and_data_semantics",
"do_not_depend_on_parent_source_tests_static_config_or_data",
"keep_one_canonical_owner_for_each_runtime_responsibility",
"keep_secrets_databases_private_skills_and_runtime_artifacts_out_of_git",
"do_not_switch_docker_or_nas_before_user_approval"
],
"approved_decisions": {
"target_directory_name": "app",
"target_directory_structure": "approved_2026-07-30",
"migration_slice_order": "approved_2026-07-30",
"execution_mode": "autonomous_until_complete",
"manual_visual_and_functional_acceptance": "approved_2026-08-01",
"slice_11_trial_retirements": "confirmed_retired_2026-08-01",
"styles_css_governance": "automated_complete_manual_visual_pending_2026-08-02",
"frontend_html_governance": "automated_complete_manual_visual_pending_2026-08-03",
"frontend_app_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"frontend_market_runtime_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"screener_engine_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"tushare_provider_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"heaven_service_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"market_insights_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"application_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"preservation_audit_governance": "automated_complete_manual_acceptance_pending_2026-08-03",
"root_compatibility_modules": "19_retired_after_reference_scan_2026-08-03",
"runtime_artifact_boundary": "centralized_under_runtime_2026-08-03",
"standalone_source_boundary": "verified_2026-08-03",
"permanent_documents_inside_app": "verified_2026-08-03",
"migration_comparison_scaffolding": "retired_after_standalone_acceptance_2026-08-03"
},
"manual_acceptance": {
"accepted_at": "2026-08-01T09:42:04+08:00",
"runtime": "http://127.0.0.1:8797/",
"scope": "all pages and all user-testable functions",
"result": "visual and functional preservation accepted; observed issues were predominantly original-version legacy issues, with no migration regression found that blocks acceptance"
},
"verification": {
"python_tests": 289,
"javascript_files": 39,
"api_routes": 74,
"playwright_tests": 46,
"sqlite_integrity": "ok",
"parent_runtime_references": 0
},
"open_decisions": [
"retired_parent_cleanup_after_checkpoint",
"docker_and_nas_switch_timing"
]
}
+466
View File
@@ -0,0 +1,466 @@
# 小白复盘保真迁移账本
> 当前状态:正式源码独立化收口自动验收通过,等待建立并推送最终回档提交
本账本是上下文恢复和人工审计的连续记录。任何迁移提交必须在同一提交中更新本文件及
`保真迁移状态.json`
## 固定事实
- 原版根目录是唯一产品和视觉基线。
- `next/`已被用户否决并冻结,不进入后续迁移。
- 新目标目录由用户批准为`app/`,最终作为正式程序目录。
- 后续采用原代码保真式迁移,不重新实现,不更换技术栈。
- 2026-07-30用户授权在既定约束内自主完成全部迁移,阶段性差异仍必须阻断后续切片。
## 当前检查点
| 日期 | 提交或标签 | 事件 | 结论 |
|---|---|---|---|
| 2026-07-30 | `xiaobai-next-rejected-20260730` | 冻结失败的`next/`实现 | 禁止部署或继续开发 |
| 2026-07-30 | `xiaobai-preservation-migration-charter-20260730` | 建立保真迁移总纲、状态和恢复协议 | 尚未开始新迁移 |
| 2026-07-30 | `41329943c4878fc09ed82ec376eb93ab151e4092` | 完成只读资产清查并由用户批准`app/`结构 | 开始切片00 |
| 2026-07-31 | `xiaobai-preservation-slice-01-20260731` | 启动、HTTP、账号、会员与系统管理原实现归位 | 自动差分通过,进入切片02 |
| 2026-07-31 | `xiaobai-preservation-slice-02-20260731` | 公共行情、搜索、详情、图表与数据适配原实现归位 | 自动与浏览器差分通过,进入切片03 |
| 2026-07-31 | `xiaobai-preservation-slice-03-20260731` | 情绪周期、五类股池与涨停表现原实现归位 | 自动、API与浏览器差分通过,进入切片04 |
| 2026-07-31 | `xiaobai-preservation-slice-04-20260731` | 市场天梯与板块轮动原实现归位 | 自动、API与浏览器差分通过,进入切片05 |
| 2026-07-31 | `xiaobai-preservation-slice-05-20260731` | 集合竞价、题材库、人气热榜与龙虎榜原实现归位 | 自动、API、数据库与浏览器差分通过,进入切片06 |
| 2026-07-31 | `xiaobai-preservation-slice-06-20260731` | 智能选股、自定义选股与策略持续跟踪原实现归位 | 自动、API、数据库与浏览器差分通过,进入切片07 |
| 2026-07-31 | `xiaobai-preservation-slice-07-20260731` | 问师、模型Skill与LLM流式链路原实现归位 | 自动、API、数据库、Skill与浏览器差分通过,进入切片08 |
| 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、数据库和浏览器验收通过;等待人工确认,未切换部署 |
| 2026-07-31 | `xiaobai-preservation-slice-11-audit-candidate-20260731` | 逐项目标审计并修复候选维护工具旧路径 | 302项测试、24个脚本、45项Playwright、21项API与62项schema差分通过;仍等待人工确认 |
| 2026-08-01 | `xiaobai-preservation-slice-11-audit-candidate-standalone-20260801` | 独立维护与截图证据复核 | 正式仓库305项、独立导出242项测试通过;撤销无效竞价截图;仍等待人工确认 |
| 2026-08-01 | `xiaobai-preservation-complete-20260801` | 用户逐页逐功能验收并完成迁移收尾 | 视觉与功能保真通过;试删确认废弃;本地交付完成,部署未切换 |
| 2026-08-03 | 工作区未提交 | 完成11项核心热点治理及历史保真审计脚手架退役 | 356项Python、全部当前JavaScript、SQLite完整性及46项Playwright通过;等待人工验收 |
| 2026-08-03 | `xiaobai-standalone-closure-20260803` | 正式源码独立化收口与最终回档 | 永久文档归位、父目录依赖清零、289项Python及46项Playwright通过;提交与推送执行中 |
## 资产处置登记
开始清查后,每个资产必须登记,禁止只记录已迁移项而遗漏未处理项。
| 原位置/符号 | 类型 | 消费者 | 处置 | 新位置 | 等价证据 | 状态 |
|---|---|---|---|---|---|---|
| 原版运行源文件(排除`next/`、日志、缓存、构建产物和正式数据库) | 运行资产 | 全站 | 原样保留后逐项移动 | `app/` | 388项受控资产哈希一致;231项Python与45项Playwright测试通过 | 已复制 |
| `next/` | 失败实现 | 无正式消费者 | 原样保留但禁止迁移 | - | 用户冻结决定 | 已冻结 |
| `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完全一致 | 已移动 |
| `ReviewDatabase`原因覆盖方法 | 持久化 | 股池原因人工覆盖 | 按职责机械移动 | `app/backend/features/pools/repository.py` | 2个方法AST与原版一致;数据库schema哈希一致 | 已移动 |
| `DashboardService`板块轮动方法 | 业务服务 | 板块轮动页 | 按职责机械移动 | `app/backend/features/rotation/service.py` | 2个方法AST、真实API与原版一致 | 已移动 |
| Tushare天梯与轮动构造函数 | 公共数据计算 | 市场天梯、板块轮动 | 原位置保持唯一实现 | `app/backend/data/providers/tushare_client.py` | 2个构造函数AST与原版一致 | 已归位 |
| `MarketInsightsService` | 共享市场洞察服务 | 集合竞价、题材库、人气热榜 | 整体机械移动,保留唯一共享实现 | `app/backend/features/market/insights.py` | 22个方法AST与原版一致;根级模块为同一类对象别名 | 已移动 |
| `DashboardService`竞价、题材、人气与龙虎榜方法 | 业务服务 | 切片05四类页面与API | 按职责机械移动 | `app/backend/features/auction/``themes/``popularity/``dragon_tiger/` | 8个方法AST、7个真实API与原版一致 | 已移动 |
| `ReviewDatabase`竞价、人气与龙虎榜方法 | 持久化 | 市场洞察及后续智能选股 | 按职责机械移动并保持Mixin原接口 | `app/backend/features/auction/repository.py``popularity/repository.py``dragon_tiger/repository.py` | 7个方法AST一致;62个schema对象及5张关键表逐行一致 | 已移动 |
| Tushare游资名录与龙虎榜实现 | 公共数据计算 | 龙虎榜与游资档案 | 原位置保持唯一实现 | `app/backend/data/providers/tushare_client.py` | 2个方法AST与原版一致 | 已归位 |
| 选股引擎、策略库与公式编译器 | 业务计算 | 阶段、策略、自定义选股 | 整体机械移动并保留兼容别名 | `app/backend/features/screener/engine.py``strategies.py``compiler.py` | 原版AST/源码等价;根级模块为同一模块对象 | 已移动 |
| `DashboardService`选股方法 | 业务服务 | 选股三个工作区 | 按职责机械移动 | `app/backend/features/screener/service.py` | 13个方法AST及3个真实API一致 | 已移动 |
| `ReviewDatabase`选股方法 | 持久化 | 因子、策略运行、候选与跟踪 | 按职责机械移动并保持Mixin原接口 | `app/backend/features/screener/repository.py` | 25个方法AST一致;62个schema对象及13张关键表逐行一致 | 已移动 |
| `StrategyTrackingService` | 业务服务 | 手动候选持续跟踪 | 保持唯一实现并调整容器导入 | `app/backend/features/screener/tracking.py` | 类定义AST、真实API与浏览器行为一致 | 已归位 |
| `mentor_agent.py`与问师服务 | 业务服务 | Skill发现、问师上下文与流式回答 | 整体机械移动并保留兼容别名 | `app/backend/features/mentor/` | Agent文件哈希、8个服务方法AST、2个真实API及浏览器行为一致 | 已移动 |
| 问师消息与偏好方法 | 持久化 | 用户对话、置顶和排序 | 按职责机械移动并保持Mixin原接口 | `app/backend/features/mentor/repository.py` | 5个方法AST一致;相关表逐行一致 | 已移动 |
| `llm_stream.py`与模型访问方法 | 公共模型能力 | 问师、问天、复盘助手与策略编译 | 移入唯一模型边界并保留兼容别名 | `app/backend/llm/` | 流式文件哈希一致;21个服务方法与既有用户边界一致 | 已移动 |
| 公开`游资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一致 | 已移动 |
| `static/app.js` | 前端总运行时 | 全站页面、状态、交互与动画 | 按原连续行机械拆分 | `app/frontend/app.js``pages/*/page.js``pages/market/{breadth,charts,entity-detail,stock-detail,preview,search,bindings}.js``shared/export.js` | 9,283行重组SHA-256与原版一致;完整基线及浏览器测试通过 | 已移动 |
| `static/index.html` | 前端DOM骨架 | 全站 | 只调整资源路径和拆分脚本加载 | `app/frontend/index.html` | 反向替换路径与脚本后逐字符一致;浏览器差分通过 | 已移动 |
| `static/styles.css`等七层样式 | 视觉运行资产 | 全部页面、主题和移动端 | 字节级移动 | `app/frontend/styles/``app/frontend/pages/heaven/page.css``app/frontend/shared/tokens.css` | 逐文件SHA-256一致;桌面、夜间和移动端计算样式一致 | 已移动 |
| `static/ui-core.js`、页面/共享脚本和供应商资产 | 前端共享/第三方资产 | Shell、页面注册、通用组件与图标 | 字节级移动 | `app/frontend/shared/``pages/``vendor/` | 逐文件SHA-256一致;45项Playwright和真实浏览器差分通过 | 已移动 |
处置只允许:`原样保留``移动``合并重复``待定``确认废弃`
## 切片记录
每个切片记录以下内容:原版基线、复制范围、必要路径调整、差异测试、人工验收、未关闭问题和回档提交。
已完成切片:`slice-00-exact-runtime-copy`
- 原版基线:提交`41329943c4878fc09ed82ec376eb93ab151e4092`
- 复制范围:确认参与运行、测试、部署和维护的原版文件;排除`next/`和运行产物。
- 允许改动:新目录中的路径配置、测试根目录和端口;不得改业务实现。
- 验收:新目录独立启动,231项Python测试、45项Playwright测试、数据库副本和静态资产哈希验证。
- 回档:本切片建立独立Git提交并推送Gitea。
- 完整证据:`docs/migration/evidence/slice-00/README.md`
- 资产清单:`docs/migration/原版资产清单.json`388项,0项哈希差异。
已完成切片:`slice-01-startup-http-accounts-system`
- 原版基线:提交`4083dce`,即切片00原样副本。
- 迁移范围:进程入口、应用组装、HTTP传输、账号安全、账号/会员业务、账号/系统设置持久化。
- 兼容边界:根级`server.py``app_config.py``security.py`继续保留原导入和命令入口。
- API与数据库:API/功能注册表哈希一致;原版与副本数据库均为36表、62个schema对象且schema哈希一致。
- 验收:236项Python测试、5项切片专项测试、45项Playwright测试全部通过;前端运行资产未改动。
- 回档:标签`xiaobai-preservation-slice-01-20260731`
- 完整证据:`docs/migration/evidence/slice-01/README.md`
已完成切片:`slice-02-market-search-charts-data`
- 原版基线:提交`4002f09`,即切片01回档点。
- 迁移范围:30个公共行情服务方法、11个行情持久化方法及Tushare/iFinD/图表/实时观察实现。
- 兼容边界:四个根级数据模块保留模块别名;未迁移功能继续使用旧导入且指向同一实现。
- 等价证明:41个方法AST逐项一致,三个数据文件哈希一致,图表定义AST一致,静态资产哈希一致。
- 验收:241项Python测试、6项切片源码等价测试、45项Playwright测试及真实服务搜索/详情流程通过。
- 既存状态:原版和迁移版的实时分时在当前环境均返回相同外部请求失败,不作为迁移回归处理。
- 回档:标签`xiaobai-preservation-slice-02-20260731`
- 完整证据:`docs/migration/evidence/slice-02/README.md`
已完成切片:`slice-03-sentiment-pools-performance`
- 原版基线:提交`a426432`,即切片02回档点。
- 迁移范围:情绪计算引擎、2个情绪服务方法、6个股池原因与iFinD事件补全方法、2个原因覆盖持久化方法。
- 兼容边界:根级`sentiment_engine.py`保留同一模块对象别名;股池生成仍使用切片02的原Tushare总览实现。
- API与数据库:原版`8784`和迁移版`8785`的总览、情绪历史JSON完全一致;两库schema均为62项且哈希一致。
- 验收:248项Python测试、6项切片源码等价测试、45项Playwright测试及六个真实页面流程通过。
- 回档:标签`xiaobai-preservation-slice-03-20260731`
- 完整证据:`docs/migration/evidence/slice-03/README.md`
已完成切片:`slice-04-ladder-rotation`
- 原版基线:提交`b3555d2`,即切片03回档点。
- 迁移范围:2个板块轮动服务方法;市场天梯继续使用切片02已归位的原Tushare数据构造实现。
- 兼容边界:`DashboardService`通过`RotationServiceMixin`保持所有原调用;天梯不制造空服务或第二套计算。
- API与错误:天梯与9日轮动历史JSON完全一致;成分股两版均返回同一Tushare外部失败语义。
- 验收:252项Python测试、4项切片源码等价测试、45项Playwright测试及两个真实页面流程通过。
- 回档:标签`xiaobai-preservation-slice-04-20260731`
- 完整证据:`docs/migration/evidence/slice-04/README.md`
已完成切片:`slice-05-auction-themes-popularity-dragon-tiger`
- 原版基线:提交`814e757`,即切片04回档点。
- 迁移范围:共享市场洞察服务、竞价/题材/人气入口、龙虎榜与游资档案服务、7个相关持久化方法。
- 兼容边界:根级`market_insights.py`保留同一类对象别名;竞价与人气共用候选热度逻辑,不复制第二套实现。
- API与数据库:7个真实API逐字段一致,仅排除每次请求必然变化的`request_id`;62个schema对象与5张关键表完全一致。
- 验收:258项Python测试、6项切片源码等价测试、45项Playwright测试及四个真实页面流程通过。
- 回档:标签`xiaobai-preservation-slice-05-20260731`
- 完整证据:`docs/migration/evidence/slice-05/README.md`
已完成切片:`slice-06-screener-custom-tracking`
- 原版基线:提交`cf2aad2`,即切片05回档点。
- 迁移范围:完整选股引擎、29套高级策略、策略编译器、13个页面服务方法、25个持久化方法及持续跟踪。
- 兼容边界:三个根级模块指向正式模块对象;选股引擎保留原版数据客户端依赖,不为通过边界测试改写算法。
- API与数据库:3个真实API业务JSON一致;62个schema对象和13张关键表逐行一致。
- 验收:原版231项、迁移版265项Python测试、7项切片源码等价测试、45项Playwright及四个真实工作区通过。
- 回档:标签`xiaobai-preservation-slice-06-20260731`
- 完整证据:`docs/migration/evidence/slice-06/README.md`
已完成切片:`slice-07-mentor-skills-llm-streaming`
- 原版基线:提交`4bab921`,即切片06回档点。
- 迁移范围:问师Agent、Skill注册表、8个服务方法、5个持久化方法、模型解析、额度、回退、流式累积器和调用审计。
- 兼容边界:根级`mentor_agent.py``llm_stream.py`指向正式模块对象;系统管理继续独占模型池配置。
- API与数据库:2个真实API完全一致;62个schema对象及5张关键表逐行一致;190个公开Skill文件哈希一致。
- 验收:原版231项、迁移版273项Python测试、8项切片源码等价测试、45项Playwright及真实问师页面通过。
- 回档:标签`xiaobai-preservation-slice-07-20260731`
- 完整证据:`docs/migration/evidence/slice-07/README.md`
已完成切片:`slice-08-heaven-trend-fortune-heart`
- 原版基线:提交`2919229`,即切片07回档点。
- 迁移范围:问天Agent、历法/卦象引擎、20个服务方法、5个持久化方法及3个HTTP入口。
- 兼容边界:根级`heaven_agent.py``heaven_engine.py`指向正式模块对象;原动画、DOM、JS与CSS未改动。
- API与数据库:6个固定输入真实API完全一致;62个schema对象及6张关键表逐行一致。
- 验收:原版231项、迁移版280项Python测试、7项切片源码等价测试、45项Playwright及1080P三模式动画页面通过。
- 回档:标签`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`
已完成切片:`slice-10-frontend-shell-pages-components-css-mobile`
- 原版基线:提交`38de3de`,即切片09回档点。
- 迁移范围:完整前端DOM、9,283行运行时、页面脚本、共享脚本、七层CSS、问天加载动画、供应商资产及移动端规则。
- 兼容边界:运行时只切换静态根目录和资源路径;原DOM、样式、动画及JS源码内容不重写。
- 源码证明:原`app.js`与全部拆分片段重组后的SHA-256均为`c020d0bc68f8a96b352a0ffa62c913a0ea3f5ca0afc41f70969f833e447166a6`
- API与数据库:21个全站只读API全部一致;62个schema对象和21张关键表逐行一致。
- 验收:85项前端专项、原版231项、迁移版294项Python测试、45项Playwright2.3分钟),以及1920×1080日间/夜间、390×844移动端和问天动画真实浏览器差分通过。
- 验收限制:同主机不同端口共享登录Cookie,双服务比较必须逐服务重新登录;动态动画帧、焦点和状态文字不以截图文件哈希作为唯一标准。
- 回档:标签`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类先进入可单项回档的候选试删,并在2026-08-01人工验收后确认废弃;
`wencai_saved_queries`表和方法因旧库兼容与用户隔离继续保留。
- 保护方式:全部历史前端源码测试统一使用审计白名单比较,只允许登记的原`app.js`行号缺失,其他差异仍会失败。
- API与数据库:21个全站只读API全部一致;62个schema对象和21张关键表逐行一致。
- 验收:原版231项、迁移版302项Python测试、24个JavaScript语法检查和45项Playwright通过;桌面日间/夜间、390×844五个移动入口和问天三页真实检查通过。
- 部署边界:未改正式数据库、`.env``8765`、Docker或NAS;原版仍是正式运行基线。
- 候选回档:标签`xiaobai-preservation-slice-11-candidate-20260731`;最终完成标签
`xiaobai-preservation-complete-20260801`;试删恢复能力继续由切片10标签保留。
- 完整证据:`docs/migration/evidence/slice-11/README.md`
- 维护交接:`docs/migration/人工维护与本地切换指南.md`
严格完成审计补充:
- 发现候选`verify_baseline.py`、架构清单和原样资产清单仍带有旧`static/`、候选`docs/`
`app/app`路径假设;产品运行不受影响,但人工接管命令不可用,因此属于迁移目标缺口。
- 修复后统一验证命令检查302项Python测试、两个生成注册表、24个前端脚本、Git空白、SQLite
完整性和45项Playwright,并在Windows上显式管理8876测试服务器生命周期。
- 21个固定API使用同一数据库时点重新比较全部一致;数据库62个schema对象和21张关键表一致,
仅按既有规则排除内置策略启动校准的`updated_at`
- 候选自身的16页、64类路由匹配、36张表、数据/LLM/CSS入口和热点文件登记在
`app/config/architecture-inventory.json`;逐项结论见`completion-audit.md`
- 严格审计回档标签为`xiaobai-preservation-slice-11-audit-candidate-20260731`。该标签只代表自动
候选;最终人工验收与删除裁决记录在完成标签中。
- 2026-08-01跨日复验发现原版与候选共用的一项实时详情测试夹具依赖运行日,进入周六后会把
非交易日误作预期合并日;两版测试夹具同步固定到明确工作日,产品代码和日期规则未改。
- 跨日修复后统一验收再次通过302项Python测试、24个JavaScript文件、SQLite完整性和45项
Playwright;新增候选回档标签`xiaobai-preservation-slice-11-audit-candidate-20260801`
-`app/`导出在系统临时目录成功运行统一维护命令:242项候选测试、注册表、24个JavaScript
文件和SQLite检查通过;正式仓库保真套件为305项Python测试及45项Playwright通过。
- 日常前端契约不再隐式读取旧`static/app.js`,只有迁移差分断言保留原版依赖;架构热点大小
按归一化UTF-8统计,CRLF/LF跨环境结果一致。
- 切片10集合竞价候选截图实际为登录失效页,已重命名并撤销证明力;九组有效截图像素差异
低于动态渲染噪声阈值。2026-08-01用户随后在真实登录状态下逐页浏览并测试全部功能,确认
视觉与功能迁移成功;发现的问题几乎都属于原版遗留问题,未发现阻止验收的迁移回归。
## CSS核心治理:`styles.css`
- 治理基线:提交`cc5fb8d`,标签`xiaobai-reduction-14-css-same-file-duplicates-20260802`
- 目标:一次性消除基础样式、历史页面样式和多轮覆盖混杂,不把旧债转移到新的补丁文件。
共享规则归入`frontend/shared/`,页面规则归入对应`frontend/pages/<feature>/foundation.css`
- 已永久删除:`styles.css``renovation.css``redesign-v2.css``design-system.css`
`theme.css``pages/heaven/page.css`;没有建立`legacy.css``override.css``fix.css`
- 最终加载契约:`tokens.css`之后只加载9个共享所有者和13个页面所有者,共22个正式CSS;
不再存在历史后置层。同一`selector + @media/@supports/@scope上下文`只有一个定义和一个
文件所有者,页面ID不能跨页面泄漏,未加页面作用域的Shell/控件根选择器只能位于共享层。
- 规模结果:治理输入为861,341字节、8,569条`selector/context`规则;最终为712,217字节、
5,754条规则,净删除149,124字节和2,815条规则。含`tokens.css`的最终源码为47,557个
物理行;该数字高于
混合压缩格式的旧文件,是因为统一改为一条声明一行,不能作为重复度指标。
- 临时资产:合并器、旧版对照HTML、旧CSS副本及浏览器临时基线均已删除;历史恢复只依赖
Git基线和标签,不在生产目录保留第二套CSS。
- 结构门禁:覆盖唯一加载顺序、历史层不存在、所有者标头、全局选择器/上下文唯一性、
页面ID归属、共享根归属、禁用补丁文件名、规则数和体积上限。
- 浏览器等价:真实`8797`运行页已完成拆分前后4K夜间情绪周期直接视觉对照,结构、图表、
表格、颜色和滚动位置一致;现行页面的日间/夜间、1920×1080、3840×2160与390×844
由端到端测试覆盖。全站最终视觉仍须用户在真实数据状态下人工验收,不以自动测试代替。
- 自动验收:统一命令`python tools/verify_baseline.py --e2e`已通过,包括341项单元/契约测试、
46项真实浏览器测试、全部JavaScript语法检查、API/架构注册表、数据库完整性及补丁格式检查。
- 未触碰:业务功能、DOM、JavaScript、数据口径、数据库、LLM、Docker/NAS、`next/`及其
冻结状态均未改变。
## HTML核心治理:`frontend/index.html`
- 治理目标:一次性消除16个主页面和1个内部页面集中在入口HTML的问题,不重写页面、
不用JavaScript字符串保存DOM,也不保留第二套隐藏页面结构。
- 机械拆分:原页面连续DOM区间按既有功能所有权归入12个真实`pages/<feature>/page.html`
五类股池共属`pools`,智能选股与策略持续跟踪共属`screener`。Shell、摘要条、状态栏和
全局弹窗继续由`index.html`唯一持有。
- 唯一装配:`index.html`只加载`bootstrap.js`;页面片段路径和既有脚本执行顺序只登记在
`pages.config.js`。Bootstrap先并行取得静态片段,按原DOM顺序直接插入`.app-main`,再按
原顺序加载运行脚本,不增加影响Flex/Grid直接子关系的包装节点。
- 启动契约:动态脚本并行下载但以`async=false`保持原执行顺序;全部运行脚本执行后发布
唯一`runtime-ready`状态。原入口只做一项精确登记的必要调整:若DOMContentLoaded尚未
发生则监听一次,若装配完成时文档已就绪则直接初始化,避免异步装配遗漏启动事件。
- 规模结果:`index.html`由1,908行降为655行;页面结构分布到12个功能片段。HTML总量没有
伪装成删除,因为本次治理解决的是所有权集中,而不是删除产品界面。
- 保真证据:片段重组后的完整页面区域与原版对应82,575个字符逐字符一致;原`app.js`
除上述精确启动替换外仍通过既有9,283行源码重组保真测试,页面ID、DOM层级、动画与业务
实现未被改写。345项Python单元/契约测试和46项Playwright浏览器测试全部通过。
- 结构门禁:入口不得出现`workspace-view`根节点;每个注册视图必须只存在于一个片段;
片段禁止脚本;页面ID全局唯一;运行脚本顺序只允许一个注册所有者;业务数据请求继续
仅通过`shared/api.js`,Bootstrap只允许读取同源静态片段。
- 未触碰:CSS视觉规则、业务功能、数据口径、数据库、LLM、Docker/NAS和冻结的`next/`
## 前端启动核心治理:`frontend/app.js`
- 治理目标:一次性消除入口脚本同时持有应用状态、主题、账户、管理后台、仪表盘、表格、
全站反馈以及16页控件事件的问题,不把原单体整体改名转移到另一个大文件。
- 入口结果:`frontend/app.js`由1,943行降为101行,只保留初始化、认证后启动、初始路由、
页面挂载协调和唯一绑定调度;入口内不再定义页面业务事件、共享状态、主题、后台管理、
仪表盘或通用表格实现。
- 共享所有权:状态与DOM句柄归入`shared/context.js`,API/Shell/页面生命周期组装归入
`shared/application.js`,反馈与动效归入`shared/feedback.js`,行情仪表盘与日期归入
`shared/dashboard.js`,认证和账户归入`shared/session.js`,系统管理归入`shared/admin.js`
主题归入`shared/theme.js`,通用表格归入`shared/table.js`。每项职责只有一个正式所有者,
没有建立`legacy``compat``override``fix`转存层。
- 页面所有权:原单一`bindEvents`已删除;12个功能页面在自身`page.js`注册一次性控件绑定,
公共行情悬浮窗和详情绑定当时归入`pages/market/runtime.js`,后续已按下节治理为七个窄职责文件。`pages/runtime.js`负责防重绑定,
`app.js`不再逐页枚举选择器或事件。
- 保真边界:除跨页事件绑定函数的结构化拆分外,原业务函数主体按源码范围机械迁移;旧
事件注册逐项归入对应所有者。保真测试会精确剥离登记过的页面绑定扩展后再与母版比较,
不以文件存在或测试自洽代替母版差分。
- 结构门禁:限制入口不超过120行;禁止状态创建、API/Shell组装、仪表盘、主题、后台和
表格实现回流入口;验证每个功能页面具有唯一绑定所有者;验证共享职责只有一个定义文件。
- 自动验收:348项Python单元/契约测试、全部JavaScript语法检查、API注册表、架构清单、
SQLite完整性和Git空白检查通过;46项Playwright浏览器测试全部通过(约2.5分钟)。
- 未触碰:HTML与CSS视觉结果、业务计算、API数据口径、数据库、LLM、Docker/NAS及冻结的
`next/`均未改变。本轮仍需用户在真实数据与登录状态下做最终人工功能确认。
## 行情前端运行时核心治理:`frontend/pages/market/runtime.js`
- 治理目标:一次性消除行情图表、个股详情、板块/题材/指数详情、悬浮行情、全局搜索、
市场宽度和事件绑定集中在一个运行时文件的问题,不建立兼容入口或换名后的新单体。
- 所有权结果:原`runtime.js`永久删除;现由`breadth.js``charts.js``entity-detail.js`
`stock-detail.js``preview.js``search.js``bindings.js`分别唯一持有七类职责,加载顺序只在
`pages.config.js`登记。最大文件为`preview.js`的455个物理行,其余均不超过392行。
- 有效代码审计:55个具名函数全部具有静态消费者,没有把无法证明无用的行情逻辑当作垃圾删除。
拆分前工作树为1,392个物理行,拆分后七文件合计1,404行;增加的12行只来自更细的原版源码
范围标记和文件边界,不是第二实现、包装层或业务代码膨胀。
- 保真证据:原9,283行`static/app.js`仍可由当前全部源码范围逐字符重组,现有行情函数主体、
DOM、Canvas绘制、API路径、事件顺序和错误处理未改写。注册表缓存版本同步提升,避免浏览器
刷新后继续加载已删除的旧运行时。
- 结构门禁:禁止恢复`pages/market/runtime.js`;七个文件必须按固定顺序唯一注册;每类核心
函数只能存在于指定所有者;任一市场运行时文件不得超过500个物理行。
- 自动验收:统一命令`python tools/verify_baseline.py --e2e`通过,包括349项Python单元/契约
测试、39个JavaScript语法检查、API/架构注册表、SQLite完整性、Git空白检查和46项真实
浏览器测试(约2.3分钟)。
- 未触碰:视觉样式、页面DOM、后端业务、数据口径、数据库、LLM、Docker/NAS和冻结的`next/`
本轮仍需用户在真实登录与数据状态下做最终人工功能确认。
## 智能选股引擎核心治理:`backend/features/screener/engine.py`
- 治理目标:消除因子目录、外部同步、技术指标、因子构建、公式、阶段识别、选股执行和回测
集中在一个引擎文件的问题,同时保留原策略公式、定时任务、API、数据库副作用和前端行为。
- 所有权结果:`engine.py`缩减为129行兼容门面;真实实现分别由`catalog.py``data_sync.py`
`indicators.py``factors.py``formula.py``regime.py``selection.py``backtest.py`唯一持有。
领域模块不再反向依赖兼容门面。
- 规模说明:原单体为2,203行,拆分后的八个所有者与兼容门面合计2,456行;增加的253行来自
独立模块导入、类边界和窄委托,不包含第二套策略、因子或算法实现。本轮解决职责集中,未以
删除产品公式伪装代码减量。
- 保真证据:所有迁移方法和辅助函数与原版逐项AST相同;公共`ScreenerEngine`
`FactorDataService`、目录常量、公式编译函数及根级兼容导入保持同一对象和原调用契约。
- 结构门禁:兼容门面不得超过180行;领域模块不得依赖门面;每项计算只允许一个源码所有者;
禁止重新合并为单体引擎。
- 自动验收:353项Python测试和46项Playwright浏览器测试通过;架构/API注册表、JavaScript、
SQLite完整性和Git空白检查通过。用户仍需在真实数据状态下做最终人工功能确认。
## Tushare客户端核心治理:`backend/data/providers/tushare_client.py`
- 治理目标:消除HTTP请求、市场总览、实时宽度、指数、申万行业、通用板块、龙虎榜、个股详情、
交易日和涨跌停数据集中在一个Provider文件的问题,不改变方法签名、字段、单位、日期、缓存、
异常、降级或数据源语义。
- 所有权结果:公共`TushareClient`仍是唯一可构造类型,`tushare_client.py`缩减为68行,只保留
dataclass字段、共享缓存状态和领域Mixin组合。传输、总览、指数、申万行业、板块、龙虎榜、
个股、交易日及通用转换分别由九个`tushare_*.py`模块唯一持有。
- 规模说明:原单体为2,165行,拆分后的领域模块与门面合计2,293行;增加的128行来自独立文件
的导入和类声明。最大所有者为644行,没有第二套`TushareClient`或重复方法体;一次性机械
拆分脚本已删除。
- 保真证据:原类全部31个方法、18个顶层辅助函数和11个dataclass/共享缓存字段均与原版逐项
AST一致;根级兼容模块、`DataGateway`、测试子类及`patch.object(TushareClient, "query")`
继续指向同一个公共类和异常类型。
- 结构门禁:门面不得超过100行且不得定义业务方法;任一领域所有者不得超过700行;领域模块
不得反向依赖门面;原方法必须完整且不重复地分布在登记所有者中。
- 自动验收:354项Python测试、46项Playwright浏览器测试、全部JavaScript语法、API/架构注册表、
SQLite完整性和Git空白检查通过。未修改前端、数据库、正式数据、Docker/NAS或冻结的`next/`
用户仍需在真实行情和页面状态下做最终人工功能确认。
## 问天服务核心治理:`backend/features/heaven/service.py`
- 治理目标:消除手工六爻补录、趋势推演、市场上下文采集、观气/观心记录与LLM解读集中在一个问天服务文件的问题,不改变API、参数、返回字段、计算口径、数据库副作用、模型调用或前端行为。
- 所有权结果:`service.py`由1,304行缩减为15行无方法组合门面;手工数据校验与六爻安全门唯一归属`manual.py`,趋势组装、市场模式、来源及质量校验唯一归属`trend.py`,个股/指数/行业上下文唯一归属`market_context.py`,个人气场、卦象、历史记录及智能解读唯一归属`readings.py`
- 规模说明:四个实现所有者分别为412、358、338、220行,连同15行门面合计1,343行;比原文件增加39行,全部来自四组独立导入和类边界,没有委托包装、第二实现或兼容转存层。一次性机械拆分脚本已删除。
- 保真证据:20个问天服务方法逐项与原版AST比较;现有有意适配的`_heaven_reading_identity`保持当前生效实现。测试同时强制每个方法只归属一个文件、门面不得定义服务方法、领域模块不得反向依赖门面、每个所有者不得超过500行。
- 自动验收:66项问天专项测试、354项全量Python测试及统一`python tools/verify_baseline.py --e2e`验收通过;后者覆盖JavaScript语法、API/架构注册表、SQLite完整性和46项Playwright浏览器流程。`git diff --check`无空白错误。
- 未触碰:前端DOM/CSS/动画、HTTP路由、数据表与正式数据、LLM协议与提示词、Docker/NAS及冻结的`next/`均未改变;仍需用户在真实观势、观气、观心流程中做最终人工确认。
## 市场洞察核心治理:`backend/features/market/insights.py`
- 治理目标:消除共享交易上下文、集合竞价评分与数据准备、竞价结果编排、题材库和人气热榜集中在一个市场洞察文件的问题,不改变API、参数、返回字段、评分、候选范围、缓存、数据库副作用或数据源降级语义。
- 所有权结果:`insights.py`由1,307行缩减为45行无方法公共门面;构造与共享上下文唯一归属`insights_context.py`,竞价评分与候选构造唯一归属`insights_auction_scoring.py`,竞价时段/成交额/自选/动态快照唯一归属`insights_auction_data.py`,竞价中心编排唯一归属`insights_auction.py`,题材库与详情唯一归属`insights_themes.py`,人气榜唯一归属`insights_popularity.py`
- 规模说明:六个实现所有者分别为84、355、318、221、222、156行,连同45行门面合计1,401行;比原文件增加94行,全部来自独立导入、类边界和公共门面的历史模块级兼容导出,没有委托包装、第二实现或业务代码复制。一次性机械拆分脚本已删除。
- 保真证据:原类全部22个方法逐项与原版AST比较,`_display_date`辅助函数保持原AST,公共`_number`仍指向统一数值标准化函数。测试强制每个方法只归属一个文件、门面不得定义业务方法、领域模块不得反向依赖门面、任一所有者不得超过400行。
- 自动验收:48项市场洞察专项及前端契约测试、354项全量Python测试和统一`python tools/verify_baseline.py --e2e`验收通过;后者覆盖JavaScript语法、API/架构注册表、SQLite完整性和46项Playwright浏览器流程。`git diff --check`无空白错误。
- 未触碰:集合竞价、题材库、人气榜的前端DOM/CSS及交互,HTTP路由、数据库结构与正式数据、数据源策略、Docker/NAS及冻结的`next/`均未改变;仍需用户在真实行情状态下做最终人工确认。
## 应用组合与HTTP协调核心治理:`backend/application.py`
- 治理目标:消除系统配置、账户委托、后台任务生命周期、74条API的跨领域解析与响应以及应用依赖装配集中在一个文件的问题,同时保持公共`DashboardService``RequestHandler``SERVICE`、API注册表、鉴权顺序、异常状态码和启动方式不变。
- 所有权结果:`application.py`由1,092行缩减为178行,只保留依赖导入、服务/请求处理器组合、当前构造函数和进程级服务实例。系统配置归属`features/system/service.py`,账户桥接归属`features/accounts/application.py`,任务生命周期归属`jobs/service.py`;公共鉴权、命名POST分派、feature遍历、静态回退和404归属`http/dispatch.py`15类端点解析与响应分别归属对应`features/<feature>/routes.py`
- 规模说明:组合根178行、统一分派器115行、三个应用服务所有者合计366行、15个feature路由所有者合计716行,总计1,375行,比原文件增加283行。增加部分来自19个独立模块的必要导入与类边界、各feature处理完成标志和统一分派循环;没有复制业务计算、保留第二套路由或增加兼容包装实现。物理行数增加,单文件职责和跨领域修改范围实质下降,此项不能表述为总代码减少。
- 路由保真:重新生成的API仍为74条,方法、路径、精确/正则匹配、功能归属和访问级别与拆分前逐项一致,`config/api.config.json`保持原SHA-256哈希。公共POST在认证前分派;受保护请求仍按认证、CSRF、权限的原顺序执行;静态页面仍绕过API权限检查。
- 结构门禁:`application.py`不得超过220行且仅允许`DashboardService.__init__``RequestHandler`不得直接定义HTTP方法;`http/dispatch.py`不得超过150行;每个feature路由文件不得超过120行、不得反向依赖`backend.application`或全局`SERVICE`;27个应用服务方法必须唯一归属于系统、账户或任务所有者。
- 自动验收:356项全量Python测试和统一`python tools/verify_baseline.py --e2e`验收通过;后者覆盖JavaScript语法、API/架构注册表、SQLite完整性和46项Playwright浏览器流程。`git diff --check`无空白错误,一次性机械拆分脚本已删除。
- 未触碰:前端DOM/CSS/动画、API数据字段、业务计算、数据库结构与正式数据、数据源和LLM策略、Docker/NAS及冻结的`next/`均未改变;仍需用户在真实登录和数据状态下做最终人工确认。
## 历史保真审计脚手架治理
- 治理目标:删除依靠复制数百行旧CSS片段、旧`app.js`行号和重组哈希证明保真的高维护机制,避免已退役的单体源码继续成为隐藏的第二套实现。
- 删除结果:`tests/preservation_helpers.py`由600余行降至115行,只保留当前页面/脚本装配、必要哈希和AST契约;生产JavaScript中的源码范围标记全部删除;一次性`tools/split_frontend_runtime.py`退役。
- 替代约束:当前脚本注册表和顺序、唯一符号所有者、页面DOM、API、JavaScript语法、CSS所有权、数据库完整性及Playwright交互成为持续维护边界。新增结构测试禁止历史标记、CSS回放表和旧拆分工具重新出现。
- 历史证据:`docs/migration/evidence/slice-10/frontend-source-map.json`继续保留,只用于说明当时如何完成机械拆分,不参与应用启动、日常测试或未来功能开发。
- 自动验收:356项Python测试通过;统一`py tools/verify_baseline.py --e2e`通过全部当前JavaScript语法、74条API注册表、架构清单、SQLite完整性和46项Playwright浏览器流程;`git diff --check`无空白错误。
- 未触碰:业务计算、API字段、DOM结构、CSS规则、动画、数据源、LLM、数据库内容、Docker/NAS及冻结的`next/`均未改变;生产JavaScript仅删除无运行效果的审计注释。
## 根目录兼容转发与运行产物治理
- 治理目标:解决`app/`根目录散落19个旧导入转发文件,以及日志、Python缓存和浏览器测试产物
分散在源码目录的问题;不改变业务实现、导入对象身份、API、数据库、前端或启动行为。
- 转发层删除:根目录Python文件由23个降为4个,只保留`api_access.py``database.py`
`server.py``sync_data.py`四个真实入口。19个兼容模块全部删除,生产代码和普通测试改为直接
导入`backend/`内的唯一实现;结构测试禁止这些旧模块或旧导入路径重新出现。
- 唯一实现修正:`backend/features/screener/repository.py`中仅剩的一处运行时旧路径回退已删除,
直接使用该模块原本已经导入的情绪领域实现,没有增加新的门面、包装或第二套业务逻辑。
- 运行产物边界:新增`runtime/`作为唯一运行产物目录,日志统一进入`runtime/logs/`Python字节码
缓存进入`runtime/cache/python/`Playwright结果进入`runtime/test-results/`;项目根目录不再生成
`*.log``tools/start_local.ps1`统一负责本地隐藏启动、PID记录、缓存和日志落点。
- 现有产物整理:历史8785/8797日志和浏览器测试结果已移入`runtime/`,源码树中32个旧
`__pycache__`目录在确认路径均位于`app/`后清除。`runtime/.gitignore`只保留目录边界,不提交
运行产物。
- 自动验收:352项Python测试和46项Playwright浏览器测试全部通过;74条API注册表、架构清单、
全部JavaScript语法、SQLite完整性及`git diff --check`均通过。测试数量减少来自删除只证明旧别名
存在的兼容测试,新增结构门禁继续验证19个旧文件不得回归。
- 未触碰:页面DOM/CSS/视觉/动画、API协议、业务计算、正式数据、数据库结构、数据源、LLM、
Docker/NAS及冻结的`next/`均未改变。提交与推送仍等待用户明确要求。
## 独立化收口
- 正式边界:`app/`成为唯一产品源码和运行目录;生产代码、测试选择、部署和维护不再读取父目录。
- 文档归位:完整产品规格、治理记录、迁移账本和证据整体进入`app/docs/`;新增当前维护指南与
文档索引,历史双版本切换指南明确标记为历史资料。
- 测试收口:10个只比较父目录旧源码的`test_preservation_*`及旧比较辅助模块退役;当前页面与
脚本装配辅助函数缩减为独立的`tests/frontend_test_helpers.py`。统一验收始终运行全部当前测试,
不再根据父目录文件是否存在静默改变测试集合。
- 工具收口:5个只服务迁移复制和新旧差分的脚本退出活动`tools/`;迁移方法和结果继续由Git历史
`docs/migration/evidence/`保存。
- 数据边界:`app/data/review.db`是唯一正式数据库;外层旧库最后写入停留在2026-08-01。
`.env`、数据库、私有Skill和`runtime/`均保持Git忽略,未进入提交。
- 独立扫描:活动源码、测试、工具和部署文档对`ROOT.parent``ORIGINAL_ROOT`、父级`static`
迁移比较工具的运行引用为0;历史文档中的旧路径仅作审计记录。
- 自动验收:289项Python测试、39个JavaScript文件语法、74条API、架构注册表、435MB SQLite
完整性及46项Playwright浏览器测试全部通过;`git diff --check`无空白错误。
- 后续边界:外层旧程序与失败的`next/`只待本回档点推送后清理;清理必须使用独立提交,不与
产品代码修改混合。Docker/NAS切换仍需用户单独批准。
## 决策记录
| 日期 | 决策 | 原因 |
|---|---|---|
| 2026-07-30 | 原版运行行为优先,规格书只用于盘点 | 防止再次依据文字重新开发 |
| 2026-07-30 | 不使用`next/`作为后续迁移起点 | 用户确认其视觉、布局和基础功能不可用 |
| 2026-07-30 | 目标结构确认前不创建业务目录 | 防止目录先行后再次补写功能 |
| 2026-07-30 | 目标目录确定为`app/` | 使用长期正式名称,不再建立新的版本式重写目录 |
| 2026-07-30 | 先建立原样可运行副本,再迁移目录职责 | 保证整理的是原件,而不是依据规格书重新实现 |
| 2026-07-30 | 不确定代码进入待删账本并延迟试删 | 删除必须能够单独回档并经自动与人工验收 |
| 2026-08-03 | `app/`成为唯一正式源码边界 | 用户确认结构重铸与迁移目标基本完成并要求独立化收口 |
| 2026-08-03 | 迁移比较脚手架退出日常测试 | 父目录删除后测试集合必须保持完整且确定,不能静默跳过 |
## 恢复工作检查
- [x] 已阅读`AGENTS.md`与保真迁移总纲。
- [x] 已读取状态JSON和本账本最后一项。
- [x] 已确认Git工作区和基线提交。
- [x] 已确认没有修改`next/`或正式数据。
- [x] 已说明当前切片及新旧等价证据。
- [x] 已在编辑前确认没有未关闭差异。
@@ -0,0 +1,128 @@
# 小白复盘原版保真迁移总纲
> 状态:正式迁移
> 建立日期:2026-07-30
> 迁移性质:保行为、保视觉、保数据语义的源代码整理
## 1. 唯一目标
以当前可运行原版`webapp`为唯一母版,在用户批准的`app/`目录中建立更容易检索、理解和人工维护的
代码结构。迁移后的系统必须继续使用原版已经验收的功能、视觉、布局、动画、计算逻辑和交互,
不得依据说明文字重新开发一个相似产品。
本次工作相当于把原文件柜中的有效原件逐项分类搬入新文件柜,而不是重新制作原件。
## 2. 事实裁决顺序
发生不一致时按以下顺序处理:
1. 用户在当前或后续对话中的明确决定。
2. 原版在相同代码、数据、账号、配置、日期、主题和视口下的真实运行行为。
3. 原版源码、数据库结构、静态资产和现有测试共同证明的行为。
4. 《小白复盘完整产品规格说明书》用于盘点和解释,不得自行覆盖原版行为。
5. 无法确定时记录为待裁决,保持原状,不推测、不补全。
只有用户明确指出原版是Bug或要求改变时,才允许产生用户可观察差异,并必须单独记录。
## 3. 必须保持不变
- 全部页面、入口、功能和细节能力。
- PC与移动端布局、尺寸、字体、颜色、间距、滚动和响应式行为。
- 日间、夜间、加载、空、错误、禁用、悬停、选中和完成状态。
- 动画素材、形态、时序、过场、循环、静音和减少动态效果行为。
- API路径、请求、响应、错误语义和流式传输行为。
- 数据来源职责、日期、单位、复权、缺失、覆盖率、新鲜度和降级规则。
- 权限、会员、管理员标识、账户隔离和私有数据边界。
- 情绪、竞价、股池、选股、问天及统计计算结果。
- 数据库现有记录、唯一约束、历史兼容和后台任务语义。
## 4. 允许与禁止
允许:
- 移动文件并调整导入路径。
- 将巨型文件按已经存在的职责拆分。
- 抽出实际重复且行为相同的实现,让原调用方指向唯一实现。
- 为原行为增加刻画测试、API快照、数据库对比和视觉回归。
- 删除已证明无引用、无运行路径、无视觉影响、无数据兼容责任的代码。
禁止:
- 更换前端框架、后端框架、数据库或主要技术栈。
- 重写已经存在的页面、样式、动画、公式或数据流程。
- 以新的设计令牌、组件库或架构偏好改变最终视觉。
- 先建立空架构,再依据规格书补写功能。
- 以“更合理”为由修复未被用户确认的原版行为。
- 复制`next/`中的产品实现进入新的迁移目录。
- 为追求行数、文件数或测试数量而删除有效代码或制造空抽象。
## 5. 迁移单位
代码不能像独立照片一样任意逐文件搬运。每次迁移一个完整纵向切片:
```text
用户入口 -> 页面结构 -> 样式与动画 -> 前端状态 -> API -> 业务计算 -> 数据库/外部数据
```
切片内部可以先原样复制,再在保持输出不变的前提下拆分。不得只搬页面而稍后重写接口,也不得先
重建全部后端再补前端。
## 6. 固定工作流
1. 冻结原版基线提交,使用数据副本,不写正式数据。
2. 建立资产清单和依赖图,逐项标记保留、移动、合并、待定或确认废弃。
3. 先规划目标目录职责;未确认前不建立业务代码。
4. 为待迁移切片记录原版API、数据库副作用、页面状态、截图和交互流程。
5. 从原版复制对应实现和资产,只调整迁移所必需的路径与依赖。
6. 对新旧版本执行同输入差异测试,结果不等价则回退本切片。
7. 等价后才允许拆分或去重;每次拆分再次执行同一组差异测试。
8. 更新迁移账本、状态文件和Git回档点,再进入下一个切片。
9. 所有切片完成后执行全量并行验收,用户确认前不切换部署。
## 7. 等价证据
每个切片至少同时具备:
| 证据 | 要求 |
|---|---|
| 源码映射 | 原文件、符号和资产到新位置的逐项记录 |
| API差异 | 同请求的状态码、字段、值、顺序和错误一致 |
| 数据库差异 | 同操作的新增、修改、删除和事务结果一致 |
| 计算差异 | 固定输入得到逐字段相同结果 |
| 页面差异 | 同数据、主题和视口的截图及结构比较 |
| 交互差异 | 点击、键盘、滚动、弹窗、动画和刷新流程一致 |
| 人工确认 | 用户确认视觉与使用感受没有偏差 |
新版本自身的单元测试只能作为辅助,不能代替新旧差异证据。
## 8. 删除规则
任何代码只有同时满足以下条件才可不迁移或删除:
1. 静态引用和动态注册扫描均无消费者。
2. 运行覆盖和真实浏览器流程未经过该路径。
3. 不承担数据库迁移、历史兼容、配置读取或资源加载责任。
4. 删除后原版与迁移版的全量差异测试仍一致。
5. 迁移账本记录理由、证据和恢复提交。
条件不足时标记`待定`并保留,不能凭代码外观判断。
## 9. 上下文恢复协议
每次新任务、上下文压缩或执行中断后,必须先完成:
1. 读取仓库根目录`AGENTS.md`
2. 读取本总纲、`保真迁移状态.json`及迁移账本。
3. 确认`next/`仍处于失败冻结状态。
4. 检查Git状态、当前基线提交和最后回档点。
5. 查看正在迁移切片的原版证据与未关闭差异。
6. 在继续编辑前向用户简述当前阶段、硬约束和下一步。
不得根据聊天摘要重新发明阶段、技术栈或验收口径。
## 10. 当前边界
- `next/`已失败冻结,不是迁移起点。
- 新目录名称、目标结构和迁移顺序已于2026-07-30获得用户确认。
- 第一切片必须先建立原样可运行副本,不允许直接开始重新实现或视觉重构。
- 原版保持唯一可运行产品,不执行Docker切换或数据清理。
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,71 @@
# 保真迁移目标目录与切片顺序
> 状态:已由用户确认
> 生效日期:2026-07-30
本文件把已批准的`app/`目标结构和迁移顺序固化为可恢复约束。目录只表达职责,迁移时从
原版复制、移动和拆分真实实现;禁止先建立空业务骨架后按规格书重写。
## 目标目录
```text
app/
server.py # 最终仅保留进程入口与HTTP服务器组装
backend/
bootstrap/ # 路径、环境、配置和依赖容器
http/ # 路由、鉴权、响应、静态资源和通用传输能力
features/
accounts/ # 登录、账号、会员及用户身份
system/ # 管理员配置和运行状态
market/ # 公共行情、搜索、详情和图表
sentiment/ # 情绪周期
pools/ # 涨停、炸板、跌停、昨日涨停和涨停表现
ladder/ # 市场天梯
rotation/ # 板块轮动
auction/ # 集合竞价
themes/ # 题材库
popularity/ # 人气热榜
dragon_tiger/ # 龙虎榜与游资档案
screener/ # 阶段、策略、自定义选股及持续跟踪
mentor/ # 问师
heaven/ # 观势、观气、观心
review/ # 自选、复盘笔记、交易日志和复盘助手
alerts/ # 提醒中心
data/ # 统一数据网关、口径、质量和供应商适配
database/ # 连接、迁移和领域Repository
jobs/ # 后台任务定义、状态、调度和重试
llm/ # 唯一模型网关、流式协议和调用审计
frontend/
index.html # 原版DOM骨架;仅在等价验证后拆分
shared/ # API、状态、Shell、弹窗和通用组件
pages/<feature>/ # 页面自己的行为与样式
styles/ # 令牌、基础层、Shell和经验证后的公共样式
vendor/ # 浏览器端第三方静态资产
config/ # 页面、功能、API、任务及数据字段注册表
data/ # SQLite及私有运行数据,保持Git忽略
tests/ # 单元、契约、差异和浏览器回归
tools/ # 清查、迁移、差异验证和维护工具
vendor/ # Python离线依赖
游资skills/ # 原版公开Skill;私有Skill仍位于data/
```
允许迁移期间保留根级兼容外壳;外壳只能转发到唯一实现,并须在账本登记删除条件。
## 固定切片顺序
| 切片 | 完整纵向范围 |
|---:|---|
| 00 | 原版可运行副本、资产清单、数据库副本和视觉基线 |
| 01 | 启动、HTTP通用能力、登录账号、会员和系统管理 |
| 02 | 公共行情、全局搜索、详情、悬浮图表、数据网关和数据质量 |
| 03 | 情绪周期、五类股池和涨停表现 |
| 04 | 市场天梯和板块轮动 |
| 05 | 集合竞价、题材库、人气热榜和龙虎榜 |
| 06 | 智能选股、自定义选股和策略持续跟踪 |
| 07 | 问师、模型Skill和LLM流式链路 |
| 08 | 问天:观势、观气和观心 |
| 09 | 我的复盘、自选、笔记、交易日志、提醒和复盘助手 |
| 10 | 前端Shell、页面文件、共享组件、CSS层级和移动端职责归位 |
| 11 | 待定代码试删、全量并行验收、维护文档和切换准备 |
每个切片先记录原版证据,再移动实现,再执行同输入差异;未通过时不得进入下一切片。
+271
View File
@@ -0,0 +1,271 @@
# 小白复盘重建迁移章程(本轮实施失败冻结)
> 状态:失败冻结,禁止继续或部署
> 建立日期:2026-07-30
> 产品真相源:`docs/product/小白复盘-完整产品规格说明书.md`
> 2026-07-30用户人工验收确认`next/`的视觉、布局和基础功能未达到原系统等价要求。
> 本章程后续阶段记录只作为失败过程留档,不再构成完成证明。权威处置记录见
> [`next失败冻结记录.md`](next失败冻结记录.md)。
## 1. 唯一目标
在当前仓库的`next/`目录内,从零重建小白复盘。新系统必须完整实现产品规格说明书定义的功能、权限、数据口径、交互状态、视觉和终端行为,同时显著减少重复实现、补丁层和隐式依赖,使后续人工维护可操作。
迁移不是对旧系统继续重构,也不是增加新产品功能。旧系统在迁移期间保持可运行,只用于读取业务事实、算法、必要数据和视觉资产。
## 2. 不可违反的约束
1. 产品规格说明书中的“已确认产品标准”优先于旧代码现状。
2. 旧系统文件不移动、不批量改名、不作为新系统运行时依赖。
3. 新系统开发数据库独立,不直接写入旧系统数据库。
4. 不整文件复制旧`server.py``app.js`、样式覆盖层或巨型业务模块。
5. 每项业务规则只保留一个权威实现。
6. 全站只有一个浏览器API出口、一个数据网关、一个LLM网关、一个弹窗管理器和一套设计令牌。
7. 页面只负责取数、组织状态和组合组件,不拥有跨页面业务计算。
8. 外部数据源只能通过数据网关访问;公开网页源不得进入正式计算。
9. LLM只解释或编译受控公式,不参与确定性行情、情绪、选股和问天计算。
10. 用户私有数据的所有读写必须在服务端验证账号所有权。
11. 兼容层只能用于迁移,必须登记删除条件;最终交付不得保留双实现。
12. 不以“测试通过”替代产品验收;测试必须实际覆盖对应规格。
13. 不以“目录已建立”或“接口已预留”宣称功能迁移完成。
14. 不自动替换NAS生产容器;最终切换在全量验收后单独确认。
## 3. 技术与结构决策
### 3.1 技术栈
- 后端:Python、FastAPI、Pydantic。
- 数据库:SQLite,显式Repository与有序Migration,不引入ORM双重抽象。
- 前端:Vue 3、TypeScript、Vite、Pinia。
- 单元与集成测试:pytest。
- 浏览器验收:Playwright。
- 部署:多阶段Docker构建,运行时保持单容器模块化单体。
### 3.2 目标一级结构
```text
next/
frontend/
src/
shared/
pages/
app/
backend/
bootstrap/
http/
features/
data/
database/
jobs/
llm/
config/
tests/
tools/
docs/
```
只预建稳定的一级边界。二、三级业务目录随纵向切片建立,不创建无真实职责的空目录树。
### 3.3 依赖方向
```text
浏览器页面 -> 前端共享层 -> HTTP接口
HTTP/后台任务 -> 业务服务 -> Repository/DataGateway/LLMGateway -> 基础设施
```
禁止反向依赖、跨功能直接读表、页面直接访问外部数据源,以及Controller中编写评分和持久化逻辑。
## 4. “做减法”验收标准
每个迁移切片必须证明:
- 旧系统同一行为的多个实现已经在新系统收敛为一个。
- 没有为了快速兼容复制第二份公式、请求逻辑或CSS组件。
- 新增共享抽象至少有两个真实调用方,或明确消除一个高风险全局出口。
- 页面专属样式不修改其他页面和全局Shell。
- 临时代码有明确删除条件,不使用永久`legacy``v2-fix``override-final`式补丁层。
- 重建后的文件按职责可读,不用巨型文件重新制造旧问题。
- 仅统计代码行数下降不能证明成功;功能等价、唯一职责和可删除旧实现同时成立才算减法。
建议性文件规模门禁:
- 前端页面容器目标不超过400行,超出时按稳定子组件拆分。
- 后端业务服务目标不超过500行,复杂确定性算法可独立成纯计算模块。
- 单个CSS文件目标不超过600行,按令牌、Shell、共享组件、页面、移动端分层。
- 超过门禁必须在本章程记录原因,不能静默放宽。
## 5. 迁移方法
采用纵向切片。每个切片同时交付:
1. 产品行为与状态。
2. 权限和账号数据边界。
3. 后端接口与Schema。
4. 业务计算与数据访问。
5. 前端页面、日间/夜间和响应式行为。
6. 单元、契约、集成和浏览器测试。
7. 与旧系统和产品规格的差异报告。
8. Git提交和远端回档节点。
禁止先迁移全部HTML、再迁移全部接口、最后补业务逻辑。这会产生长期空壳和无法验收的中间状态。
## 6. 执行阶段
| 阶段 | 内容 | 完成证据 | 状态 |
|---:|---|---|---|
| 0 | 产品规格、迁移章程、旧系统只读基线 | 文档检查、Git节点 | 已完成 |
| 1 | `next/`最小可运行骨架与工具链 | 前后端启动、健康检查、基础测试 | 已完成 |
| 2 | 配置、错误、日志、数据库迁移、Repository基础 | 迁移回退和错误契约测试 | 已完成 |
| 3 | 账户、会话、权限、会员和系统配置 | 权限矩阵与跨账号测试 | 已完成 |
| 4 | 前端Shell、路由、状态、API、弹窗、主题和令牌 | 1080P/4K/390px Shell截图 | 已完成 |
| 5 | 数据网关、日期、快照、图表和搜索 | 来源/时间/缺失/降级测试 | 已完成 |
| 6 | 情绪周期、四类股池与涨停表现 | 算法固定样本、页面E2E | 已完成 |
| 7 | 市场天梯和板块轮动;回归涨停表现 | 结构统计与展开滚动验收 | 已完成 |
| 8 | 集合竞价、题材库、人气热榜和龙虎榜 | 生命周期、口径和空态验收 | 已完成 |
| 9 | 智能选股、36套策略、自定义选股和持续跟踪 | 109因子、确定性和隔离测试 | 已完成 |
| 10 | 问师、模型Skill、LLM流式网关 | 上下文路由、去重和回退测试 | 已完成 |
| 11 | 问天观势、观气、观心 | 公式、安全门、动画和历史验收 | 已完成 |
| 12 | 我的复盘、提醒和复盘助手 | 私有数据、汇总和弹窗验收 | 已完成 |
| 13 | 全站移动端重组和无障碍 | 320/390/430/768/横屏验收 | 已完成 |
| 14 | 数据迁移、Docker、备份恢复和性能安全 | 旧库副本迁移、回滚演练 | 已完成 |
| 15 | 全量验收、减法审计和切换准备 | 规格覆盖矩阵、最终报告 | 已完成 |
阶段编号不会因为上下文压缩重新规划。只有发现产品规格自身矛盾时,才记录决策并调整阶段内容;不得通过新增阶段掩盖未完成工作。
## 7. 每阶段质量门禁
每次提交前至少执行:
1. 格式、类型和静态检查。
2. 受影响模块的单元测试。
3. API契约和账号边界测试。
4. 数据库迁移前进/回退测试(涉及数据库时)。
5. Playwright关键流程(涉及运行时或前端时)。
6. 日间/夜间和目标视口截图(涉及视觉时)。
7. 浏览器控制台无未处理错误。
8. 密钥、Token、日志和生成物扫描。
9. 与产品规格固定验收案例的可追溯检查。
10. `git diff --check`和工作区来源确认。
## 8. Git与回档
- 当前`main`保留旧系统可运行状态和新系统迁移过程。
- 每个阶段至少一个独立提交,提交信息使用`rebuild(stage-N): ...`
- 阶段门禁通过后推送Gitea。
- 不重写已推送历史,不使用破坏性重置。
- 大阶段内可有多个小提交,但最终必须有明确阶段完成节点。
- 规格说明书和本章程的变更与相应行为变更同提交或先提交。
## 9. 数据迁移与最终切换
- 开发期间只使用旧数据库的只读副本或脱敏样本。
- 迁移工具可重复运行,并输出逐表数量、校验和、跳过项和失败项。
- 首次完整迁移后进行账号、权限、共享快照和私有数据抽样比对。
- 最终切换前停止旧系统写入,执行最终增量迁移,再启动新容器。
- 保留旧镜像、旧数据库一致性备份和加密密钥,验证回退路径。
- 未经最终确认,不停止或替换NAS现有容器。
## 10. 持续状态记录
每完成一个阶段,在本节追加:
- 提交哈希和推送状态。
- 实际完成证据。
- 删除或避免的重复代码。
- 未完成项和残余风险。
- 下一阶段入口条件。
### 当前状态
- 阶段0已完成:产品规格说明书和迁移章程通过结构、表格和密钥扫描。
- 产品规格说明书包含16个工作区、36套策略、109个因子和85个固定验收案例。
- 旧系统保持原状。
- 阶段1已完成,代码提交为`603e73d`:建立隔离的FastAPI与Vue 3/TypeScript/Vite骨架、唯一前端API客户端、统一安全错误外壳、设计令牌起点及前后端基础测试。
- 后端门禁:Ruff通过,pytest为2项通过;存在1项FastAPI 0.141测试客户端上游弃用警告,阶段2改用显式ASGI传输层消除。
- 前端门禁:类型检查通过,Vitest为1个文件/2项通过,Vite生产构建通过;依赖安装审计为0个已知漏洞。
- 运行验收:`8780/api/health`返回开发环境健康状态,`5173`代理访问成功;1280x720浏览器实测无控制台错误、无横向溢出。
- 减法证据:删除未使用的`jsdom`及37个传递依赖;禁止TypeScript生成重复JavaScript测试产物;未复制旧`server.py``app.js`或CSS覆盖层。
- 阶段2已完成,代码提交为`d969d2c`:配置从环境唯一加载,SQLite连接启用WAL/外键/忙等待,迁移支持前进、显式回退、原子失败、校验和和连续历史校验。
- Repository基础只建立被健康检查真实使用的数据库状态Repository,未创建通用CRUD或空业务目录;数据库维护CLI支持状态、升级及需二次确认的回退。
- HTTP错误统一为`code/message/request_id`,404、验证错误、业务错误和未知异常均通过安全契约;请求编号同时写入响应头,未知异常不向前端泄露原文。
- 日志采用结构化JSON、`Asia/Shanghai`时间、10MB/3份轮转和嵌套/字符串敏感值脱敏;运行健康检查可区分进程和数据库状态。
- 阶段2门禁:Ruff通过,pytest为20项通过,前端2项测试、类型检查和生产构建通过;真实服务健康响应、请求编号及`+08:00`启动日志通过运行验收。
- 阶段3已完成,代码提交为`f69972c`并已推送:首个注册账号成为管理员,后续账号为普通用户;管理员权限与会员状态独立,管理员开通会员后同时具有管理员和会员标识。
- 会话Cookie为HttpOnlyCSRF使用Cookie与请求头双重校验;服务端只保存会话和CSRF哈希。修改密码保留当前会话并撤销其他会话,账号出生资料和系统凭据均加密落库且按权限隔离。
- 会员管理支持1个月、3个月、12个月、3年和永久,续期从有效到期日继续计算;会员每日智能调用上限进入会员配置。管理员无需伪装成会员即可使用智能功能,普通非会员被服务端拒绝。
- 模型池限制20个模型,首个模型自动成为主模型,支持独立选择主模型和辅助模型;选中模型不可删除,密钥不会通过管理接口返回。模型连通测试明确留给阶段10的唯一LLM网关,系统管理不建立第二个模型调用出口。
- 减法证据:HTTP Schema从路由中拆出,路由由412行降至314行;系统凭据职责从账户服务拆出,最长业务服务由429行降至382行。未建立通用CRUD、旧账号兼容层、第二套权限判断或明文密钥读取接口。
- 阶段3门禁:Ruff通过,pytest为40项通过;前端2项测试、类型检查和生产构建继续通过;数据库版本1和2的前进及倒序回退通过,真实账号密码和已提供令牌未进入`next/`
- 阶段3残余边界:账号与系统管理的前端交互属于阶段4;LLM成功调用计次和模型连通性属于阶段10,不在阶段3提前实现。
- 阶段4已完成,代码提交为`3b75bf2`并已推送:登录注册、16项工作区注册表、PC/移动Shell、顶栏、摘要条、固定状态栏、主题、日期、账户菜单和系统管理前端均已接入。
- 账户五项菜单独立可达;浏览器实际保存并重读个人出生资料。会员状态完整显示开通状态、到期、剩余时长、今日用量、今日剩余、功能对比和暂不可用加油包。
- 管理员可按分类维护平台凭据、模型池、主辅模型与会员;非管理员不显示后台刷新和系统管理,直达管理路由会返回情绪周期,智能工作区保留同结构会员锁定态。
- 前端只有一个工作区注册表、API客户端、会话Store、主题Store、弹窗Host和Toast Host。响应式规则从五处分散媒体查询收敛到唯一`mobile.css`;最长前端文件332行,组件样式未出现令牌文件之外的色值。
- 阶段4门禁:Ruff和40项pytest通过;Vue类型检查、2个文件5项Vitest、Vite生产构建通过;2项Playwright覆盖管理员/普通用户、真实写入、Ctrl+K、主题持久化、弹窗、系统管理和多视口。
- 视觉证据已保存于`next/docs/evidence/stage-4/`:日间/夜间1920×1080、夜间3840×2160和390×844;实测无横向溢出、弹窗居中、Shell尺寸与内容边距符合规范。
- 阶段4残余边界:行情摘要值、真实搜索结果、后台刷新和各工作区业务内容属于阶段5及后续阶段;移动端逐页业务重组属于阶段13,未用占位页冒充完成。
- 阶段5已完成,代码提交为`cf0ab70`并已推送:建立唯一`DataGateway`、四源职责策略、观测元信息、失败关闭质量门,以及交易日历、标的目录、行情摘要和图表序列的版本3数据库结构。
- Tushare只承担权威交易日历、股票目录和日线入口;iFinD优先承担日K与分时展示,并支持顶层表格响应和Access Token失效后的Refresh Token重试;东方财富只允许作为展示分时兜底,策略层禁止其进入正式计算。腾讯职责已在策略中登记,但尚无本阶段真实消费者,因此未创建空Provider。
- 日期契约区分请求日期、实际数据日期和观测时间;盘前空今日K线会被剔除,沿用最近真实快照时明确返回真实日期和说明,从未同步时不生成模拟数据。
- 全局搜索按股票、板块、题材、指数固定分组,具备160毫秒防抖、键盘循环选择和明确状态;搜索预览与行情详情共用同一图表组件,日K上涨空心且影线不穿实体,分时范围固定9:30至15:00并包含昨收零轴和均价线。
- 管理员行情管理增加交易日历和股票目录的真实同步入口;普通用户响应不显示供应商工程名称。完整行情后台任务、情绪摘要写入和各实体业务详情仍属于后续阶段,没有用本阶段基础页冒充完成。
- 阶段5门禁:Ruff通过,pytest为46项通过;Vue类型检查、2个文件5项Vitest和Vite生产构建通过;3项Playwright覆盖既有Shell回归、摘要、搜索、日K/分时、日夜主题、1920×1080和390×844视口。组件CSS无令牌外色值,已提供密码和令牌未进入`next/`
- 减法证据:未复制旧`TushareClient``IfindHttpClient``MarketChartClient`或供应商缓存堆叠;所有外部访问收敛到一个网关和一份策略,搜索预览与详情没有重复图表实现;新增后端最长文件379行,低于章程400行目标。
- 新系统进入阶段6:使用阶段5的交易日期、摘要存储和质量门迁移情绪周期与五类股池的确定性公式、固定样本和页面。
- 阶段6已完成,代码提交为`59f6011`并已推送:以唯一日度市场快照交付情绪周期、涨停池、炸板池、跌停池、昨日涨停和涨停表现;管理员后台刷新接入同一快照任务,普通用户仍无管理入口。
- 情绪温度严格实现五维权重、自适应历史百分位、系统健康门控、极端风险上限和六阶段状态机;权威涨跌停事件不完整或日线覆盖率低于98%时失败关闭并保留旧快照,未以日线推导或公开网页源静默补造事件。
- 四类股票明细共用`PoolPage``DataTable`的搜索、筛选、排序、空态与CSV导出;涨停表现直接消费后端一次聚合的晋级、红盘、断板、炸板和跌停统计,7板以上动态扩展,不在前端复制分类公式。原因和风险线索无权威字段时保持空值。
- 阶段6门禁:Ruff通过,pytest为49项通过;Vue类型检查、2个文件5项Vitest和Vite生产构建通过;4项Playwright覆盖阶段4/5回归及情绪、股池、动态7板、日夜主题、1920×1080、3840×2160和390×844视口,控制台无未处理错误且无页面横向溢出。
- 阶段6视觉与验收证据位于`next/docs/evidence/stage-6/`。新增页面最长207行,页面CSS 118行;六个页面只消费一份`market_summaries.payload_json`,没有逐页重复表或第二套市场快照。
- 原阶段表把“涨停表现”同时包含在阶段6“五类股池”和阶段7,属于范围重复。其完整实现已随单一快照在阶段6交付;阶段7只迁移市场天梯和板块轮动,同时把涨停表现纳入跨页回归,不再创建重复实现。
- 新系统进入阶段7:复用阶段6的涨停结构快照,迁移市场天梯的动态梯队、展开收起与排序,以及板块轮动的九日Top12、跨日高亮、排序和成分股。
- 阶段7已完成,代码提交为`a76d344`并已推送:市场天梯支持动态层级、断层、等宽个股单元格、两种排序、展开收起和导出;板块轮动支持九日Top12、日期正逆序、跨日高亮和指定交易日申万二级成分股。
- 天梯、轮动、情绪和股池继续共用唯一日度市场快照;涨停表现只回归阶段6实现。板块成分股只增加版本4的专用快照缓存,未建立第二套轮动表或通用缓存框架。
- 行情快照采集已从直接创建供应商客户端收敛到`DataGateway`;供应商策略、计算用途限制和成分股读取均经同一网关,消除业务服务绕过数据治理层的出口。
- 阶段7门禁:Ruff通过,pytest为50项通过;Vue类型检查、2个文件5项Vitest和Vite生产构建通过;5项Playwright覆盖阶段4至7回归、日夜主题、展开滚动、1920×1080和390×844视口,控制台无未处理错误且无横向溢出。
- 阶段7视觉与验收证据位于`next/docs/evidence/stage-7/`。新增页面分别为106行和126行,市场页面样式总计415行,均低于章程门禁;已提供密码和令牌未进入`next/`
- 阶段8已完成,代码提交为`976a5ca`并已推送:集合竞价实现盘前归档、9:15至9:25动态观察、9:25选定及盘后归档,重点异动、我的自选、全部候选、竞价一字和成交额历史共用同一标准化口径。
- 题材库区分题材行情与成分股缺失状态,题材悬浮预览复用阶段5的统一图表组件;人气热榜区分同花顺、东方财富和双榜共识,单源数据不会伪装成共识;龙虎榜明确区分无上榜、明细缺失、全部未识别、请求不可用及部分/完整识别状态。
- 竞价共享归档不保存用户私有内容,“我的自选”在响应边界按认证账号即时合成。自选股使用独立版本6 Migration,避免修改已执行迁移;跨账号Repository测试确认记录互不可见。
- 阶段8门禁:Ruff通过,pytest为58项通过;Vue类型检查、2个文件5项Vitest和Vite生产构建通过;6项Playwright覆盖阶段4至8回归、日夜主题、1920×1080和390×844视口,控制台无未处理错误且无移动端横向溢出。
- 阶段8视觉与验收证据位于`next/docs/evidence/stage-8/`。新增页面最长108行、页面样式168行,后端最长纯计算模块492行;没有复制旧系统巨型文件、通用CRUD、通用缓存、供应商客户端或兼容层。
- 新系统进入阶段9:迁移智能选股、36套策略、自定义选股和持续跟踪;以产品规格定义的109个因子、盘后自动执行边界、策略确定性、无信号与数据不足分离、账户隔离作为完成条件,不以精简策略或占位接口冒充迁移完成。
- 阶段9已完成:建立109因子目录、7套阶段策略、29套独立策略、受控确定性公式、自定义选股、盘后调度和手动持续跟踪;阶段策略受实际情绪阶段匹配,29套策略不受阶段门控。
- 选股结果严格区分数据不完整与完整数据下无信号;财务因子遵守公告日期,缺失值不转为零,同分按标识稳定排序。公开网页数据和LLM均不参与候选计算。
- 自定义策略、运行结果和跟踪记录按账号隔离,运行选股不会自动加入跟踪;跟踪统计包含T+1开盘/收盘、T+3/T+5收盘、最大涨幅和最大回撤,T+1/T+5事件具备持久唯一性。
- 阶段9门禁:Ruff通过,pytest为69项通过;Vue类型检查、2个文件5项Vitest和Vite生产构建通过;8项Playwright覆盖阶段4至9全量回归、非会员锁定、日夜主题、1920×1080与390×844,控制台无未处理错误且无移动端横向溢出。
- 阶段9视觉与验收证据位于`next/docs/evidence/stage-9/`。未复制旧系统2118行选股实现;后端最长文件448行、页面容器最长169行、选股样式102行,均低于章程门禁。
- 阶段9残余边界:自然语言转公式必须在阶段10经唯一LLM网关实现;完整IC动态加权未以基础多因子冒充。NAS生产容器保持不变。
- 新系统进入阶段10:迁移问师、思维模型Skill、数据上下文路由和唯一LLM流式网关,并验证重复输出、计次、限流、主辅模型回退和中断恢复。
- 阶段10已完成,代码提交为`f1fa104`并已推送:23个公开思维模型由文件目录自动发现,私有Skill使用受Git忽略的数据目录且仅管理员可见;前端只显示A/B/C证据等级。
- 问师上下文按情绪、首板、龙头、趋势、低吸承接和宏观六类路由,龙虎榜按问题触发,单次最多匹配两个标的;上下文仅读取本地快照和缓存图表,不因提问触发全市场外部刷新。
- 唯一LLM网关统一会员鉴权、每日额度、主辅模型、请求与尝试审计和安全错误;仅首字前失败允许回退,首字后中断保留部分结果且不重放,一次业务请求最多结算一次成功额度。
- 会话、顺序和置顶按账号隔离,会话进一步按模型和交易日隔离;清空只作用于当前范围。前端复用唯一API客户端和全局弹窗管理器,支持真实NDJSON流、停止、重试和去重。
- 阶段10门禁:Ruff通过,pytest为78项通过;Vue类型检查、2个文件6项Vitest和Vite生产构建通过;阶段4至10共10项Playwright通过,覆盖1920×1080、3840×2160、390×844、日夜模式和非会员同结构锁定态。
- 阶段10视觉与验收证据位于`next/docs/evidence/stage-10/`。新增最长后端文件262行、页面容器230行、页面样式289行;新系统未导入旧`mentor_agent.py`或建立第二套流式、配额和弹窗实现。
- 阶段11已完成:观势实现正式日线与盘中实时两种严格模式、六爻确定性公式、安全门和客观行业数据补录;观气实现确定性历法、固定权重、三层气机和个人合参;观心实现40秒呼吸、一次投掷只生成一爻及六爻成卦。
- 问天三种历史按账号隔离;每日解运具有数据库唯一约束和并发复用,已完成结果不会重复调用LLM或扣减额度。原始出生资料不在问天响应中回显。
- 三种智能解读复用阶段10唯一LLM网关、配额、流协议和弹窗;页面保留已经验收的星空、六爻、铜钱与循环加载动画,没有复制旧`heaven_agent.py``heaven_engine.py`或建立第二套解读实现。
- 阶段11门禁:Ruff通过,pytest为89项通过;Vue类型检查、3个文件7项Vitest和Vite生产构建通过;阶段4至11共12项Playwright通过,覆盖1920×1080、390×844、日夜模式、加载弹窗和非会员同结构锁定态。
- 阶段11视觉与验收证据位于`next/docs/evidence/stage-11/`。市场情绪计算从业务域收敛到数据层,问势实时组装从通用网关拆到专用数据模块;NAS生产容器保持不变。
- 阶段12已完成:我的复盘交付账户独立的自选追踪、交易日志、每日复盘、历史记录和个股复盘笔记;重复加入自选不会清空既有备注。
- 提醒中心支持手动提醒、策略T+1/T+5提醒、未读状态和持久化去重;复盘助手复用唯一LLM网关并只读取本地市场快照和当前账号私有记录,非会员保留同结构灰色锁定态。
- 阶段12门禁:Ruff通过,pytest为92项通过;Vue类型检查、3个文件7项Vitest和Vite生产构建通过;阶段4至12共14项Playwright通过,覆盖1920×1080和390×844、日夜模式、全局弹窗与私有数据流程。
- 阶段12视觉与验收证据位于`next/docs/evidence/stage-12/`。新增业务Service 368行、页面样式397行;未导入旧复盘、自选或助手实现,也未建立第二套弹窗、LLM、配额或流协议。
- 阶段13已完成:移动端保留五个一级入口,市场复盘通过统一选择器访问12个子页;桌面和移动端共用唯一交易日期组件,复盘页补齐提醒中心与复盘助手入口。
- 430px以下通用宽表重组为字段明确的纵向记录,平板和横屏保留局部横滚;底部导航正确识别所有市场子页,横屏股池工具栏收为一行。
- 阶段13门禁:Ruff和92项pytest通过;Vue类型检查、3个文件7项Vitest和Vite生产构建通过;阶段4至13共17项Playwright通过。320、375、390、430、768、844×390横屏及1024至4K断点均无页面横向溢出,16个工作区在320px逐页可达。
- 可访问性补齐跳到主内容、排序`aria-sort`、弹窗焦点回收、44px触控目标和有效的1ms减少动态效果令牌。移动规则集中在537行的唯一`mobile.css`,未复制页面、API或业务状态。
- 阶段13视觉与验收证据位于`next/docs/evidence/stage-13/`
- 新系统进入阶段14:交付可重复的旧库迁移、Docker运行、备份恢复、升级回退及性能安全检查,所有演练仅作用于副本和新系统容器资产。
- 阶段14已完成:一次性迁移工具以只读 URI 打开旧库,真实副本迁移保留3个账号、会员与模型配置、全部已归属私有记录、196次历史选股、16条跟踪及受控展示归档;完整性检查通过且外键违规为0。
- 备份使用SQLite在线备份API并将数据库、环境密钥材料和私有Skill归入同一带SHA-256清单的归档;恢复默认拒绝覆盖并在落盘前校验安全路径、文件摘要和数据库完整性。真实恢复演练通过。
- 生产前端改为FastAPI同端口提供,SPA深链接与API 404边界通过测试;新容器定义采用多阶段构建、非root、只读根文件系统、持久卷和健康检查。开发机没有Docker,实际镜像构建和容器重启恢复列为NAS切换前阻断验收项。
- 阶段14门禁:Ruff、96项pytest、Vue类型检查、7项Vitest、Vite生产构建及17项Playwright全部通过;真实迁移库副本行情摘要读取P95为23.55ms。证据位于`next/docs/evidence/stage-14/`
- 新系统进入阶段15:执行规格覆盖矩阵、减法审计、性能安全总验收、人工维护演练和最终切换准备;阶段15不自动切换NAS生产容器。
- 阶段15已完成:85个固定产品案例逐项映射到确定性/API或真实浏览器证据;重建运行时代码由旧版61,793行收敛为25,151行,减少约59.3%,未复制旧巨型文件和CSS覆盖层。
- 结构审计消除LLM网关对账户具体类的反向依赖;数据库状态命令修复为真正只读且能识别已有migration。统一生产安全头、静态缓存边界、维护手册和NAS切换/回退清单已交付。
- 阶段15门禁:Ruff、99项pytest、Vue类型检查、7项Vitest、Vite生产构建和17项Playwright全部通过;npm与Python生产依赖已知漏洞均为0,敏感值扫描通过。
- 新系统代码迁移工作完成。正式NAS切换仍被Docker实构建、容器重启恢复和用户切换窗口确认三类人工条件阻断,不在本阶段自动执行。
- 生产切换明确保留为最终人工确认项。