Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
104e6aa396 | ||
|
|
deb84c4069 | ||
|
|
1c50cc5bcb |
+4
-3
@@ -1,8 +1,9 @@
|
||||
# Candidate architecture
|
||||
|
||||
`app/` is the behavior-preserving modular candidate. The original `webapp/` runtime remains
|
||||
the product and visual baseline until manual acceptance. `next/` is a rejected, frozen
|
||||
implementation and is not a source for this directory.
|
||||
`app/` is the behavior-preserving modular source tree accepted by the user on 2026-08-01.
|
||||
The original `webapp/` runtime remains the deployment rollback baseline until an explicitly
|
||||
approved switch. `next/` is a rejected, frozen implementation and is not a source for this
|
||||
directory.
|
||||
|
||||
The application deliberately remains a modular monolith: one Python process, one SQLite WAL
|
||||
database, and a build-free HTML/CSS/JavaScript client. The migration changed source ownership
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
|
||||
一个面向 A 股盘后复盘的本地 Web 工作台。后端使用 Python 访问 Tushare Pro,前端不依赖构建工具。
|
||||
|
||||
本目录是从原版源码逐项移动、机械拆分并完成差分验证的模块化候选,不是依据规格书重新开发的
|
||||
第二套产品。人工验收和正式切换前,`webapp/`根目录仍是唯一正式基线;冻结的`next/`不得用于
|
||||
部署或后续开发。目录职责见[ARCHITECTURE.md](ARCHITECTURE.md)。
|
||||
本目录是从原版源码逐项移动、机械拆分并完成差分验证与用户人工验收的模块化正式源码,
|
||||
不是依据规格书重新开发的第二套产品。正式部署切换前,`webapp/`根目录继续作为当前部署与
|
||||
回档基线;冻结的`next/`不得用于部署或后续开发。目录职责见[ARCHITECTURE.md](ARCHITECTURE.md)。
|
||||
|
||||
当前包含集合竞价、涨停池、炸板池、跌停板、昨日涨停、涨停表现、市场天梯、板块轮动、题材库、人气热榜、龙虎榜和个人复盘工作区。交易日快照与同步记录保存在本地 SQLite 数据库 `data/review.db`。
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
"code_hotspots": [
|
||||
{
|
||||
"path": "frontend/styles/styles.css",
|
||||
"bytes": 361780,
|
||||
"bytes": 361776,
|
||||
"lines": 15465
|
||||
},
|
||||
{
|
||||
@@ -279,12 +279,12 @@
|
||||
},
|
||||
{
|
||||
"path": "frontend/app.js",
|
||||
"bytes": 91151,
|
||||
"bytes": 89213,
|
||||
"lines": 1939
|
||||
},
|
||||
{
|
||||
"path": "frontend/pages/heaven/page.js",
|
||||
"bytes": 88322,
|
||||
"bytes": 86493,
|
||||
"lines": 1830
|
||||
},
|
||||
{
|
||||
@@ -299,7 +299,7 @@
|
||||
},
|
||||
{
|
||||
"path": "backend/features/heaven/service.py",
|
||||
"bytes": 64421,
|
||||
"bytes": 63123,
|
||||
"lines": 1303
|
||||
},
|
||||
{
|
||||
@@ -309,7 +309,7 @@
|
||||
},
|
||||
{
|
||||
"path": "frontend/pages/market/runtime.js",
|
||||
"bytes": 57053,
|
||||
"bytes": 55720,
|
||||
"lines": 1333
|
||||
},
|
||||
{
|
||||
@@ -319,7 +319,7 @@
|
||||
},
|
||||
{
|
||||
"path": "backend/application.py",
|
||||
"bytes": 50934,
|
||||
"bytes": 49784,
|
||||
"lines": 1165
|
||||
},
|
||||
{
|
||||
@@ -329,7 +329,7 @@
|
||||
},
|
||||
{
|
||||
"path": "database.py",
|
||||
"bytes": 34013,
|
||||
"bytes": 33284,
|
||||
"lines": 746
|
||||
}
|
||||
]
|
||||
|
||||
@@ -26,6 +26,7 @@ RETIRED_FRONTEND_SOURCE_RANGES = (
|
||||
(9022, 9027),
|
||||
(9052, 9055),
|
||||
)
|
||||
AUDITED_FRONTEND_SOURCE_LINE_COUNT = 9283
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
@@ -51,12 +52,10 @@ def reassembled_frontend_runtime() -> str:
|
||||
assembled.append(content)
|
||||
next_line = end + 1
|
||||
|
||||
original_line_count = len(
|
||||
(ORIGINAL_STATIC / "app.js").read_text(encoding="utf-8").splitlines()
|
||||
)
|
||||
if next_line != original_line_count + 1:
|
||||
if next_line != AUDITED_FRONTEND_SOURCE_LINE_COUNT + 1:
|
||||
raise AssertionError(
|
||||
f"app.js source coverage ended at {next_line - 1}, expected {original_line_count}"
|
||||
"app.js source coverage ended at "
|
||||
f"{next_line - 1}, expected {AUDITED_FRONTEND_SOURCE_LINE_COUNT}"
|
||||
)
|
||||
return "".join(assembled)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import json
|
||||
import re
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from tests.preservation_helpers import reassembled_frontend_runtime
|
||||
|
||||
@@ -46,6 +47,14 @@ class FrontendBoundaryTests(unittest.TestCase):
|
||||
self.assertIn("const state = window.XiaobaiState.create({", app)
|
||||
self.assertNotIn("const state = {", app)
|
||||
|
||||
def test_candidate_runtime_reassembly_does_not_require_original_static(self) -> None:
|
||||
with patch(
|
||||
"tests.preservation_helpers.ORIGINAL_STATIC",
|
||||
ROOT / "missing-original-static",
|
||||
):
|
||||
app = reassembled_frontend_runtime()
|
||||
self.assertIn("function openView(", app)
|
||||
|
||||
def test_runtime_page_registry_matches_governance_registry(self) -> None:
|
||||
expected = json.loads(
|
||||
(ROOT / "config" / "pages.config.json").read_text(encoding="utf-8")
|
||||
|
||||
@@ -3,11 +3,16 @@ from __future__ import annotations
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from tools.build_api_registry import build as build_api_registry
|
||||
from tools.build_architecture_inventory import build as build_architecture_inventory
|
||||
from tools.build_architecture_inventory import (
|
||||
build as build_architecture_inventory,
|
||||
source_metrics,
|
||||
)
|
||||
from tools.verify_baseline import python_test_command
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -34,6 +39,22 @@ class MaintenanceToolTests(unittest.TestCase):
|
||||
self.assertIn("stop_e2e_server(server)", source)
|
||||
self.assertNotIn('"static/app.js"', source)
|
||||
|
||||
def test_standalone_verifier_excludes_only_migration_comparison_modules(self) -> None:
|
||||
repository_command = python_test_command(preservation_baseline=True)
|
||||
standalone_command = python_test_command(preservation_baseline=False)
|
||||
self.assertIn("discover", repository_command)
|
||||
self.assertTrue(any(item == "tests.test_frontend_contract" for item in standalone_command))
|
||||
self.assertFalse(any("test_preservation_" in item for item in standalone_command))
|
||||
|
||||
def test_architecture_metrics_are_independent_of_checkout_line_endings(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
lf = root / "lf.js"
|
||||
crlf = root / "crlf.js"
|
||||
lf.write_bytes(b"const a = 1;\nconst b = 2;\n")
|
||||
crlf.write_bytes(b"const a = 1;\r\nconst b = 2;\r\n")
|
||||
self.assertEqual(source_metrics(lf), source_metrics(crlf))
|
||||
|
||||
def test_every_tool_has_a_non_mutating_help_path(self) -> None:
|
||||
for path in sorted((ROOT / "tools").glob("*.py")):
|
||||
if path.name.startswith("_"):
|
||||
|
||||
@@ -46,7 +46,7 @@ class RealtimeClientStub:
|
||||
|
||||
|
||||
class FixedMarketDatetime(datetime):
|
||||
fixed_now = datetime.now().astimezone().replace(hour=10, minute=30, second=0, microsecond=0)
|
||||
fixed_now = datetime(2026, 7, 31, 10, 30).astimezone()
|
||||
|
||||
@classmethod
|
||||
def now(cls, tz=None):
|
||||
@@ -54,7 +54,7 @@ class FixedMarketDatetime(datetime):
|
||||
|
||||
|
||||
class FixedPreopenDatetime(datetime):
|
||||
fixed_now = datetime.now().astimezone().replace(hour=8, minute=45, second=0, microsecond=0)
|
||||
fixed_now = datetime(2026, 7, 31, 8, 45).astimezone()
|
||||
|
||||
@classmethod
|
||||
def now(cls, tz=None):
|
||||
|
||||
@@ -14,6 +14,13 @@ maintenance command cannot be mistaken for a historical migration rewrite.
|
||||
- `python tools/build_architecture_inventory.py [--check]`: generate or verify
|
||||
`config/architecture-inventory.json` from the candidate source tree.
|
||||
|
||||
Inside the canonical `webapp/app/` checkout, `verify_baseline.py` runs the full preservation
|
||||
suite against the retained original baseline and enforces `git diff --check`. In a standalone
|
||||
`app/` export where that baseline and Git checkout do not exist, the same command runs all
|
||||
candidate-owned tests, skips only `test_preservation_*` comparison modules, and reports the Git
|
||||
check as skipped. Product, registry, JavaScript, database, and optional Playwright checks remain
|
||||
active in both modes.
|
||||
|
||||
## Acceptance and differential checks
|
||||
|
||||
- `run_preservation_runtime.py`: start an isolated original or candidate runtime with an
|
||||
|
||||
@@ -75,6 +75,14 @@ def css_layers(html: str) -> list[str]:
|
||||
return re.findall(r'<link[^>]+rel="stylesheet"[^>]+href="([^"]+)"', html)
|
||||
|
||||
|
||||
def source_metrics(path: Path) -> dict[str, int]:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
return {
|
||||
"bytes": len(text.encode("utf-8")),
|
||||
"lines": len(text.splitlines()),
|
||||
}
|
||||
|
||||
|
||||
def code_hotspots() -> list[dict[str, Any]]:
|
||||
candidates = [
|
||||
"backend/application.py",
|
||||
@@ -99,13 +107,7 @@ def code_hotspots() -> list[dict[str, Any]]:
|
||||
path = ROOT / name
|
||||
if not path.is_file():
|
||||
continue
|
||||
rows.append(
|
||||
{
|
||||
"path": name,
|
||||
"bytes": path.stat().st_size,
|
||||
"lines": len(path.read_text(encoding="utf-8").splitlines()),
|
||||
}
|
||||
)
|
||||
rows.append({"path": name, **source_metrics(path)})
|
||||
return sorted(rows, key=lambda item: item["bytes"], reverse=True)
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,39 @@ def run(label: str, command: list[str]) -> None:
|
||||
subprocess.run(command, cwd=ROOT, check=True)
|
||||
|
||||
|
||||
def python_test_command(preservation_baseline: bool | None = None) -> list[str]:
|
||||
if preservation_baseline is None:
|
||||
preservation_baseline = (ROOT.parent / "static" / "app.js").is_file()
|
||||
if preservation_baseline:
|
||||
return [sys.executable, "-m", "unittest", "discover", "-s", "tests"]
|
||||
modules = [
|
||||
f"tests.{path.stem}"
|
||||
for path in sorted((ROOT / "tests").glob("test_*.py"))
|
||||
if not path.stem.startswith("test_preservation_")
|
||||
]
|
||||
if not modules:
|
||||
raise RuntimeError("no standalone candidate tests found")
|
||||
return [sys.executable, "-m", "unittest", *modules]
|
||||
|
||||
|
||||
def verify_git_diff() -> None:
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
cwd=ROOT,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print("\n[patch] skipped: standalone export is not a Git checkout")
|
||||
return
|
||||
repository_root = Path(result.stdout.strip()).resolve()
|
||||
if ROOT != repository_root / "app":
|
||||
print("\n[patch] skipped: standalone export is outside the canonical app path")
|
||||
return
|
||||
run("patch", ["git", "diff", "--check"])
|
||||
|
||||
|
||||
def verify_database() -> None:
|
||||
database = ROOT / "data" / "review.db"
|
||||
if not database.exists():
|
||||
@@ -97,7 +130,7 @@ def main() -> int:
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
run("python", [sys.executable, "-m", "unittest", "discover", "-s", "tests"])
|
||||
run("python", python_test_command())
|
||||
run(
|
||||
"api-registry",
|
||||
[sys.executable, "tools/build_api_registry.py", "--check"],
|
||||
@@ -117,7 +150,7 @@ def main() -> int:
|
||||
"javascript",
|
||||
[node, "--check", script.relative_to(ROOT).as_posix()],
|
||||
)
|
||||
run("patch", ["git", "diff", "--check"])
|
||||
verify_git_diff()
|
||||
verify_database()
|
||||
|
||||
if args.e2e:
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
## 4. 真实浏览器差分
|
||||
|
||||
- 1920×1080日间模式检查情绪周期、集合竞价、智能选股、观势、观气、观心介绍及观心呼吸。
|
||||
- 1920×1080日间模式检查情绪周期、智能选股、观势、观气、观心介绍及观心呼吸。
|
||||
- 1920×1080夜间模式检查情绪周期的背景、字体、表格、几何和横向溢出。
|
||||
- 390×844检查情绪周期与观势:移动Shell、底部五入口、页面纵向滚动、无横向溢出及问天特效均一致。
|
||||
- 观势星空节点90个、观气100个、观心110个;三页八卦节点均为2个。
|
||||
@@ -48,6 +48,10 @@
|
||||
- 原版和迁移版检查流程均未产生新增控制台error或warn。
|
||||
- 动画帧、焦点框和动态状态文字属于采样瞬时状态,因此截图文件哈希不要求相同;可见布局几何、计算样式、节点、动画名称和交互结果必须一致,本次均通过。
|
||||
- 两个服务使用相同主机名、不同端口时会共享并覆盖登录Cookie;曾导致迁移版切页被误判为失效。逐服务重新登录后行为一致,该问题属于并行验收环境限制,不是产品回归。
|
||||
- 2026-08-01像素复核发现`frontend-migrated-auction-light-1920x1080`实际截取了登录状态失效页,
|
||||
不能证明集合竞价视觉等价,文件已重命名为`INVALID-login-session`。集合竞价仍有切片05真实页面、
|
||||
本切片源码/样式保真、API及Playwright证据,但最终视觉明确留待人工验收,不以替代证据冒充
|
||||
本切片截图差分。
|
||||
- 机器可读记录见`browser-acceptance.json`,截图均保存在本目录。
|
||||
|
||||
## 5. 自动验证与保留边界
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"tested_at": "2026-07-31T12:00:00+08:00",
|
||||
"result": "passed",
|
||||
"result": "passed_with_documented_evidence_gap",
|
||||
"environments": {
|
||||
"original": "temporary_original_runtime",
|
||||
"migrated": "temporary_app_runtime",
|
||||
@@ -15,7 +15,6 @@
|
||||
"theme": "light",
|
||||
"views": [
|
||||
"sentiment",
|
||||
"auction",
|
||||
"screener",
|
||||
"heaven_trend",
|
||||
"heaven_fortune",
|
||||
@@ -44,6 +43,14 @@
|
||||
"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,
|
||||
@@ -89,5 +96,6 @@
|
||||
},
|
||||
"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
|
||||
"all_equal": true,
|
||||
"manual_acceptance_required": true
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@@ -3,14 +3,17 @@
|
||||
> 基线:`dec3cd12365df5e7d4c391369f14c457cf56d7d9`
|
||||
> 候选回档标签:`xiaobai-preservation-slice-11-candidate-20260731`
|
||||
> 严格审计候选标签:`xiaobai-preservation-slice-11-audit-candidate-20260731`
|
||||
> 当前结论:自动验收完成,等待用户人工验收;尚未执行正式切换、Docker或NAS部署
|
||||
> 跨日复验候选标签:`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`:页面未加载的旧问天动画;正式入口继续使用
|
||||
@@ -31,7 +34,7 @@
|
||||
| 验证 | 结果 |
|
||||
|---|---:|
|
||||
| 原版`python -m unittest discover -s tests -q` | 231项通过 |
|
||||
| 迁移版`python -m unittest discover -s tests -q` | 302项通过 |
|
||||
| 迁移版`python -m unittest discover -s tests -q` | 305项通过 |
|
||||
| 历史切片与前端/清理专项复核 | 通过 |
|
||||
| 迁移版JavaScript语法检查 | 24个文件通过 |
|
||||
| `npx.cmd playwright test --reporter=dot` | 45项通过(1.6分钟) |
|
||||
@@ -39,6 +42,12 @@
|
||||
| 数据库差分 | 62个schema对象、21张关键表全部一致 |
|
||||
| `git diff --check` | 通过 |
|
||||
|
||||
2026-08-01 01:19(Asia/Shanghai)跨日复验时,原版与迁移版共用的实时详情测试暴露出
|
||||
测试夹具依赖运行日的问题:夹具在周六动态生成“今日”,而业务正确拒绝在非交易日合并实时
|
||||
行情。两版测试夹具同步固定到明确的工作日盘中/盘前时点,产品代码与行情日期规则未改。
|
||||
修复后统一验收命令再次通过302项测试、24个JavaScript文件、SQLite完整性和45项Playwright
|
||||
(2.0分钟)。
|
||||
|
||||
早期切片的五个前端源码测试原本要求与未试删的`static/app.js`逐字符一致。本切片把它们统一到
|
||||
`preservation_helpers.assert_frontend_runtime_matches_audited_baseline`:只允许审计登记的五段原始
|
||||
行号被删除,任何其他新增、删除、重排或内容变化仍会使全部历史测试失败。
|
||||
@@ -51,6 +60,12 @@ 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. 真实浏览器验收
|
||||
|
||||
- 桌面端复核情绪周期、智能选股三个工作区、问天日间/夜间和加载资源;控制台无新增
|
||||
@@ -63,25 +78,31 @@ Windows下Playwright托管Python静态服务器会在45项执行后不退出,
|
||||
- 同账号、同数据库快照、同主题和同视口下,原版与迁移版问天布局和计算样式一致。
|
||||
|
||||
机器可读记录见`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/`只是等待人工验收的候选。
|
||||
- `app/`已经完成本地迁移验收;原版根目录仍是当前部署基线和切换前回档来源。
|
||||
- `next/`保持冻结,没有作为代码、样式、测试或文档来源。
|
||||
|
||||
## 5. 回档与最终确认
|
||||
|
||||
切片11提交和两个候选标签只代表“候选可验收”,不代表删除已被永久确认。人工验收前可按
|
||||
`uncertain-code-audit.md`从切片10标签单独恢复任一候选;不需要回退其他已通过迁移切片。
|
||||
2026-08-01用户完成全部页面和功能人工验收,确认迁移在视觉和功能上成功,并确认人工检查中
|
||||
发现的问题几乎都属于原版遗留问题。切片11的2个文件和5个无消费者函数据此从“候选试删”改为
|
||||
“确认废弃”;恢复标签继续保留作历史兼容应急,不代表删除结论仍待裁决。
|
||||
|
||||
用户人工确认后才允许:
|
||||
本地迁移收尾已执行:
|
||||
|
||||
1. 把试删候选状态改为“确认废弃”。
|
||||
2. 建立最终完成标签。
|
||||
3. 决定本地或Docker正式切换时间。
|
||||
4. 另行制定根目录兼容外壳和旧实现的清理计划。
|
||||
1. 试删候选状态改为“确认废弃”。
|
||||
2. 建立最终完成标签并推送Gitea。
|
||||
3. `app/`作为后续结构治理的唯一开发目录。
|
||||
|
||||
正式数据库、原版部署、Docker和NAS仍未切换;切换时间与根目录清理必须由用户另行批准。
|
||||
|
||||
人工维护、验证、切换和回退步骤见`docs/migration/人工维护与本地切换指南.md`。
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
> 结论口径:自动证据通过不替代用户人工验收,也不授权部署切换
|
||||
|
||||
本审计回答的不是“测试是否为绿色”,而是迁移总纲、批准目录、产品表面和人工维护目标是否
|
||||
分别有可复验的证据。状态只使用:`自动闭环`、`人工待验`、`明确保留`和`未执行`。
|
||||
分别有可复验的证据。状态只使用:`自动闭环`、`人工闭环`、`明确保留`和`未执行`。
|
||||
|
||||
## 1. 目标与证据矩阵
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
| 后台任务可追踪和重试 | 3个任务登记调度、锁、超时、重试和输出版本;运行状态持久化 | `jobs.config.json`;job runner tests | 自动闭环 |
|
||||
| LLM唯一治理边界 | 问师、问天、复盘助手和策略编译经统一网关执行会员、额度、模型回退、流式和审计规则 | 切片07/09;LLM gateway/stream tests | 自动闭环 |
|
||||
| 前端唯一请求出口、Shell和页面职责 | 只有`frontend/shared/api.js`调用`fetch`;Shell、状态、弹窗、页面生命周期及页面模块已归位 | frontend boundary tests;切片10源码重组哈希 | 自动闭环 |
|
||||
| CSS、主题、动画和移动行为不改写 | 原七层CSS和问天动画按字节/源码移动;令牌层与加载顺序受测试保护 | CSS governance;切片10/11浏览器证据 | 自动闭环 |
|
||||
| 不确定代码先记录再试删 | 2个文件和5个无消费者函数仅为候选试删;历史表兼容责任继续保留 | `uncertain-code-audit.md`;cleanup contract | 人工待验 |
|
||||
| 可由人工维护者复验 | 候选README/架构说明、工具分类、API/架构生成器、统一验证命令均可从`app/`独立运行 | `app/tools/README.md`;maintenance tool tests | 自动闭环 |
|
||||
| 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测试;人工验收前禁止切换 | 迁移状态和切换指南 | 未执行 |
|
||||
|
||||
@@ -58,15 +58,26 @@
|
||||
3. 原样资产清单、方法搬运和前端拆分明确标为迁移期工具;可能写文件的操作必须显式传路径或
|
||||
`--apply`,默认帮助路径不改文件。
|
||||
4. 新增维护工具契约测试,保证生成文件新鲜、所有工具`--help`可用,旧`static/`路径不会回归。
|
||||
5. 跨到2026-08-01周六后,实时详情测试中用运行日构造的“固定时间”不再代表交易日;原版和
|
||||
候选测试夹具同步固定到明确工作日,消除跨午夜/周末不确定性。产品实现与交易日规则未改,
|
||||
随后统一验收再次通过302项Python测试和45项Playwright。
|
||||
6. 独立导出`app/`后成功启动健康接口,236项非迁移业务/前端测试通过;同时发现六项日常前端
|
||||
契约经辅助函数隐式读取旧`static/app.js`。候选运行时重组现使用已审计的9,283行覆盖边界,
|
||||
只有明确的保真差分断言继续读取原版,避免未来清理旧目录后日常契约失效。
|
||||
7. 对切片10十组截图重新做像素审计,九组平均色差均低于0.3/255;集合竞价候选图实际为登录
|
||||
失效页,已明确标为无效并撤销其截图证明力。集合竞价最终视觉继续列为人工验收项。
|
||||
8. 统一验证器现在按环境选择完整保真套件或候选自有套件;系统临时目录中的纯`app/`导出通过
|
||||
242项测试、注册表、24个JavaScript文件和SQLite检查。架构热点大小按归一化UTF-8计算,
|
||||
CRLF/LF不再导致清单失效;正式仓库最终通过305项测试和45项Playwright。
|
||||
|
||||
## 4. 仍需用户完成的最终裁决
|
||||
## 4. 最终人工裁决与部署边界
|
||||
|
||||
自动部分完成后仍不能执行以下动作:
|
||||
2026-08-01用户在隔离端口`8797`浏览全部页面并测试全部功能,确认视觉与功能迁移成功;发现的
|
||||
问题几乎都属于原版遗留问题,未发现阻止验收的迁移回归。该结论已经关闭以下迁移裁决:
|
||||
|
||||
1. 把切片11的试删候选从“待人工确认”改成“确认废弃”。
|
||||
2. 声称所有页面的视觉、交互手感和动画已经由用户确认等价。
|
||||
3. 建立最终完成标签,或把`app/`切换为本地/容器正式入口。
|
||||
4. 删除根目录原版、正式数据库备份或冻结的失败记录。
|
||||
1. 切片11试删候选确认为废弃,恢复标签继续保留。
|
||||
2. 页面视觉、功能、交互和动画的人工验收完成。
|
||||
3. 允许建立本地迁移完成标签并推送Gitea。
|
||||
|
||||
本地人工验收入口及逐页清单以`人工维护与本地切换指南.md`为准。发现差异时只回退对应候选,
|
||||
不使用破坏性Git操作覆盖原版或正式数据。
|
||||
该结论不授权切换正式数据库、Docker或NAS,也不授权删除根目录原版、数据库备份或冻结的
|
||||
`next/`记录。部署切换继续以`人工维护与本地切换指南.md`为准,并须单独获得用户批准。
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
@@ -3,9 +3,11 @@
|
||||
> 审计基线:`dec3cd12365df5e7d4c391369f14c457cf56d7d9`
|
||||
> 恢复标签:`xiaobai-preservation-slice-10-20260731`
|
||||
> 原则:只有静态引用、动态注册、运行路径和兼容责任同时排除后才试删;其余继续保留
|
||||
> 当前状态:试删后的自动、API、数据库和浏览器验收已通过,等待用户人工确认
|
||||
> 当前状态:自动与人工验收均已通过,试删项于2026-08-01确认废弃
|
||||
|
||||
本日志记录试删前的原位置、内容指纹、证据、决定和恢复方式。试删不等于永久废弃;自动回归通过后仍需用户在迁移版真实页面完成人工验收,才能把删除结论视为最终确认。
|
||||
本日志记录试删前的原位置、内容指纹、证据、决定和恢复方式。试删阶段不等于永久废弃;
|
||||
2026-08-01用户完成迁移版全部页面和功能人工检查,确认视觉与功能迁移成功,所见问题几乎都
|
||||
属于原版遗留问题,未发现阻止验收的迁移回归。该人工结论关闭了本日志的最终确认门槛。
|
||||
|
||||
## 1. `app/demo_data.py`
|
||||
|
||||
@@ -15,7 +17,7 @@
|
||||
- 动态/注册路径:没有模块名字符串、插件注册或反射加载。
|
||||
- 产品事实:`app/README.md`明确主行情不再回退演示数据;行情服务和Repository只负责排除历史`source=demo`缓存,未依赖本文件。
|
||||
- 兼容责任:不参与数据库schema、历史记录解释或配置读取。
|
||||
- 决定:进入试删。
|
||||
- 最终决定:确认废弃;切片10标签继续保留单项恢复能力。
|
||||
- 恢复:从切片10标签恢复`app/demo_data.py`。
|
||||
|
||||
## 2. `app/frontend/heaven-loading.js`
|
||||
@@ -26,7 +28,7 @@
|
||||
- 动态/注册路径:没有脚本清单、页面注册表或运行时代码引用旧路径;新旧文件虽然都导出`window.HeavenLoadingCanvas`,但浏览器只能执行v2。
|
||||
- 运行证据:切片10已覆盖观势、观气和观心解读加载动画,v2节点、动画名及可见行为与原版基线一致。
|
||||
- 兼容责任:不是数据库、配置或历史数据资产。
|
||||
- 决定:进入试删。
|
||||
- 最终决定:确认废弃;切片10标签继续保留单项恢复能力。
|
||||
- 恢复:从切片10标签恢复该文件。
|
||||
|
||||
## 3. 五个疑似无引用前端函数
|
||||
@@ -35,11 +37,11 @@
|
||||
|
||||
| 函数 | 位置 | 原用途线索 | 决定 |
|
||||
|---|---|---|---|
|
||||
| `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` | 试删 |
|
||||
| `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。后者与仍在使用的选股状态、观心节点和复合选择器相邻,尚不足以证明可独立删除,默认保留。
|
||||
|
||||
@@ -76,4 +78,14 @@
|
||||
- 桌面日间/夜间及390x844移动端真实页面检查通过,问天三页和观气底部内容可达。
|
||||
- `wencai_saved_queries`及三个方法保持存在,并由清理契约测试持续保护。
|
||||
|
||||
因此上述删除保持“候选试删”状态;只有用户人工验收后才改为“确认废弃”。
|
||||
## 7. 人工最终确认
|
||||
|
||||
- 验收日期:2026-08-01。
|
||||
- 验收运行时:隔离端口`8797`与迁移审计数据库副本。
|
||||
- 验收范围:用户逐页浏览全部页面并测试全部可操作功能。
|
||||
- 验收结论:视觉与功能迁移成功;发现的问题几乎都是原版遗留问题,未发现阻止验收的迁移回归。
|
||||
- 删除结论:`demo_data.py`、旧问天加载文件和上述5个无消费者函数正式确认为废弃;
|
||||
`wencai_saved_queries`及证据不足的相邻DOM、状态和CSS继续保留。
|
||||
|
||||
确认废弃不取消恢复证据。若后续发现历史兼容责任,可从
|
||||
`xiaobai-preservation-slice-10-20260731`按本日志记录单项恢复,不回退其他迁移成果。
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# 小白复盘人工维护与本地切换指南
|
||||
|
||||
> 适用目录:`webapp/app/`
|
||||
> 当前状态:迁移候选已完成自动验收,尚未获得最终人工验收,不得替换正式部署
|
||||
> 当前状态:本地迁移已完成自动与用户人工验收;正式数据库、Docker和NAS尚未切换
|
||||
|
||||
## 1. 先确认哪个版本是正式版本
|
||||
|
||||
- 当前正式基线仍是`webapp/`根目录及根目录`data/review.db`。
|
||||
- `webapp/app/`是保真迁移候选,运行代码来自原版的移动、机械拆分和去重,不是重新开发。
|
||||
- `webapp/app/`是已完成人工验收的保真迁移版本,运行代码来自原版的移动、机械拆分和去重,
|
||||
不是重新开发。
|
||||
- `webapp/next/`是已否决的冻结版本,禁止部署、继续开发或复制实现。
|
||||
- 用户人工验收前,不要删除根级原版,不要让`app/`写入正式数据库,也不要修改NAS容器。
|
||||
|
||||
@@ -108,6 +109,10 @@ app/tools/compare_preservation_databases.py
|
||||
|
||||
## 7. 人工验收清单
|
||||
|
||||
2026-08-01用户已在隔离端口`8797`完成全部页面和功能验收,确认视觉与功能迁移成功;所见问题
|
||||
几乎都属于原版遗留问题,未发现阻止验收的迁移回归。以下清单继续作为后续结构修改和部署
|
||||
切换时的回归标准:
|
||||
|
||||
- 用同一账号、日期和主题对照原版与迁移版全部页面。
|
||||
- 检查日间/夜间、1080P/4K、390像素移动端和浏览器缩放后的滚动与弹窗。
|
||||
- 检查图表悬浮、股票/板块/题材/指数详情、全局搜索和日期切换。
|
||||
@@ -120,7 +125,7 @@ app/tools/compare_preservation_databases.py
|
||||
人工验收发现差异时,记录页面、账号、日期、主题、视口、输入和截图;先对照原版复现,再判断
|
||||
是迁移回归还是原版既有问题。
|
||||
|
||||
## 8. 获得批准后的本地切换方案
|
||||
## 8. 获得部署批准后的本地切换方案
|
||||
|
||||
以下只是准备步骤,本次迁移没有执行:
|
||||
|
||||
@@ -144,5 +149,5 @@ Docker/NAS切换应以`app/`作为构建上下文,另行执行构建、卷挂
|
||||
4. 从切换记录指定的原版提交重新启动根级`server.py`。
|
||||
5. 验证登录、健康接口、最近交易日、私有数据和模型配置后恢复使用。
|
||||
|
||||
切片11试删可从`xiaobai-preservation-slice-10-20260731`单项恢复;不要用破坏性的Git重置覆盖
|
||||
正式数据或用户未提交的代码。
|
||||
切片11已确认废弃项仍可从`xiaobai-preservation-slice-10-20260731`单项恢复;不要用破坏性的
|
||||
Git重置覆盖正式数据或用户未提交的代码。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"updated_at": "2026-07-31T20:57:42+08:00",
|
||||
"status": "awaiting_manual_acceptance",
|
||||
"updated_at": "2026-08-01T09:42:04+08:00",
|
||||
"status": "completed_local_handoff",
|
||||
"migration_mode": "behavior_preserving_source_migration",
|
||||
"source_of_truth": "current_original_webapp_runtime_and_source",
|
||||
"source_root": ".",
|
||||
@@ -10,10 +10,10 @@
|
||||
"next"
|
||||
],
|
||||
"current_slice": "slice-11-strict-completion-audit-maintenance-handoff",
|
||||
"last_completed_slice": "slice-10-frontend-shell-pages-components-css-mobile",
|
||||
"last_completed_slice": "slice-11-strict-completion-audit-maintenance-handoff",
|
||||
"last_automated_slice": "slice-11-strict-completion-audit-maintenance-handoff",
|
||||
"last_checkpoint": "xiaobai-preservation-slice-11-audit-candidate-20260731",
|
||||
"next_action": "user_acceptance_on_local_port_8797_then_confirm_or_restore_each_trial_retirement; do_not_switch_docker_or_nas_before_approval",
|
||||
"last_checkpoint": "xiaobai-preservation-complete-20260801",
|
||||
"next_action": "preservation_migration_complete; keep the original runtime as the deployment rollback baseline until a separately approved local or Docker/NAS switch",
|
||||
"authoritative_documents": [
|
||||
"AGENTS.md",
|
||||
"docs/migration/原版保真迁移总纲.md",
|
||||
@@ -35,11 +35,17 @@
|
||||
"target_directory_name": "app",
|
||||
"target_directory_structure": "approved_2026-07-30",
|
||||
"migration_slice_order": "approved_2026-07-30",
|
||||
"execution_mode": "autonomous_until_complete"
|
||||
"execution_mode": "autonomous_until_complete",
|
||||
"manual_visual_and_functional_acceptance": "approved_2026-08-01",
|
||||
"slice_11_trial_retirements": "confirmed_retired_2026-08-01"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"open_decisions": [
|
||||
"user_acceptance_of_visual_interaction_and_animation_equivalence",
|
||||
"final_confirmation_or_restore_of_slice_11_trial_retirements",
|
||||
"local_and_docker_switch_timing"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 小白复盘保真迁移账本
|
||||
|
||||
> 当前状态:切片11严格完成审计通过,等待用户人工验收;正式切换尚未执行
|
||||
> 当前状态:切片11自动与人工验收完成,本地保真迁移交付完成;正式部署切换尚未执行
|
||||
|
||||
本账本是上下文恢复和人工审计的连续记录。任何迁移提交必须在同一提交中更新本文件及
|
||||
`保真迁移状态.json`。
|
||||
@@ -32,6 +32,8 @@
|
||||
| 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` | 用户逐页逐功能验收并完成迁移收尾 | 视觉与功能保真通过;试删确认废弃;本地交付完成,部署未切换 |
|
||||
|
||||
## 资产处置登记
|
||||
|
||||
@@ -41,9 +43,9 @@
|
||||
|---|---|---|---|---|---|---|
|
||||
| 原版运行源文件(排除`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语法和浏览器流程通过 | 待人工确认 |
|
||||
| `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通过 | 已移动 |
|
||||
@@ -191,16 +193,18 @@
|
||||
- 回档:标签`xiaobai-preservation-slice-10-20260731`。
|
||||
- 完整证据:`docs/migration/evidence/slice-10/README.md`。
|
||||
|
||||
自动验收完成、等待人工确认的切片:`slice-11-uncertain-code-audit-final-acceptance-handoff`。
|
||||
已完成切片:`slice-11-uncertain-code-audit-final-acceptance-handoff`。
|
||||
|
||||
- 原版基线:提交`dec3cd12365df5e7d4c391369f14c457cf56d7d9`,即切片10回档点。
|
||||
- 审计范围:`demo_data.py`、旧问天加载动画、5个无引用前端函数及`wencai_saved_queries`兼容责任。
|
||||
- 处置:前3类进入可单项回档的候选试删;`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-slice-11-candidate-20260731`;最终完成标签
|
||||
`xiaobai-preservation-complete-20260801`;试删恢复能力继续由切片10标签保留。
|
||||
- 完整证据:`docs/migration/evidence/slice-11/README.md`。
|
||||
- 维护交接:`docs/migration/人工维护与本地切换指南.md`。
|
||||
|
||||
@@ -214,8 +218,19 @@
|
||||
仅按既有规则排除内置策略启动校准的`updated_at`。
|
||||
- 候选自身的16页、64类路由匹配、36张表、数据/LLM/CSS入口和热点文件登记在
|
||||
`app/config/architecture-inventory.json`;逐项结论见`completion-audit.md`。
|
||||
- 严格审计回档标签为`xiaobai-preservation-slice-11-audit-candidate-20260731`。该标签仍不是最终
|
||||
完成标签,未改变试删候选、人工验收和部署切换边界。
|
||||
- 严格审计回档标签为`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用户随后在真实登录状态下逐页浏览并测试全部功能,确认
|
||||
视觉与功能迁移成功;发现的问题几乎都属于原版遗留问题,未发现阻止验收的迁移回归。
|
||||
|
||||
## 决策记录
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class RealtimeClientStub:
|
||||
|
||||
|
||||
class FixedMarketDatetime(datetime):
|
||||
fixed_now = datetime.now().astimezone().replace(hour=10, minute=30, second=0, microsecond=0)
|
||||
fixed_now = datetime(2026, 7, 31, 10, 30).astimezone()
|
||||
|
||||
@classmethod
|
||||
def now(cls, tz=None):
|
||||
@@ -54,7 +54,7 @@ class FixedMarketDatetime(datetime):
|
||||
|
||||
|
||||
class FixedPreopenDatetime(datetime):
|
||||
fixed_now = datetime.now().astimezone().replace(hour=8, minute=45, second=0, microsecond=0)
|
||||
fixed_now = datetime(2026, 7, 31, 8, 45).astimezone()
|
||||
|
||||
@classmethod
|
||||
def now(cls, tz=None):
|
||||
|
||||
Reference in New Issue
Block a user