migration: prove standalone maintenance and correct visual evidence
This commit is contained in:
@@ -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("_"):
|
||||
|
||||
@@ -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 |
@@ -4,6 +4,7 @@
|
||||
> 候选回档标签:`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`
|
||||
> 当前结论:自动验收完成,等待用户人工验收;尚未执行正式切换、Docker或NAS部署
|
||||
|
||||
## 1. 本切片做了什么
|
||||
@@ -32,7 +33,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分钟) |
|
||||
@@ -58,6 +59,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. 真实浏览器验收
|
||||
|
||||
- 桌面端复核情绪周期、智能选股三个工作区、问天日间/夜间和加载资源;控制台无新增
|
||||
@@ -70,6 +77,8 @@ Windows下Playwright托管Python静态服务器会在45项执行后不退出,
|
||||
- 同账号、同数据库快照、同主题和同视口下,原版与迁移版问天布局和计算样式一致。
|
||||
|
||||
机器可读记录见`browser-acceptance.json`。截图和更广的桌面/移动基线继续沿用切片10证据目录。
|
||||
切片10截图的事后像素复核见`screenshot-pixel-audit.json`;九组有效截图平均色差低于0.3/255,
|
||||
集合竞价候选图因登录状态失效被明确排除,仍等待用户人工视觉验收。
|
||||
|
||||
## 4. 数据与部署边界
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
| 前端唯一请求出口、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 | 自动闭环 |
|
||||
| 可由人工维护者复验 | 候选README/架构说明、工具分类、API/架构生成器、统一验证命令均可从`app/`独立运行;系统临时目录导出实测242项候选测试通过 | `app/tools/README.md`;maintenance tool tests;独立导出复验 | 自动闭环 |
|
||||
| 正式数据库与部署不受影响 | 验收只使用隔离SQLite副本和非8765端口 | 各切片README;运行记录 | 自动闭环 |
|
||||
| Docker/NAS和正式入口切换 | 用户已明确本轮不做NAS Docker测试;人工验收前禁止切换 | 迁移状态和切换指南 | 未执行 |
|
||||
|
||||
@@ -61,6 +61,14 @@
|
||||
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. 仍需用户完成的最终裁决
|
||||
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"updated_at": "2026-08-01T01:19:27+08:00",
|
||||
"updated_at": "2026-08-01T03:14:46+08:00",
|
||||
"status": "awaiting_manual_acceptance",
|
||||
"migration_mode": "behavior_preserving_source_migration",
|
||||
"source_of_truth": "current_original_webapp_runtime_and_source",
|
||||
@@ -12,7 +12,7 @@
|
||||
"current_slice": "slice-11-strict-completion-audit-maintenance-handoff",
|
||||
"last_completed_slice": "slice-10-frontend-shell-pages-components-css-mobile",
|
||||
"last_automated_slice": "slice-11-strict-completion-audit-maintenance-handoff",
|
||||
"last_checkpoint": "xiaobai-preservation-slice-11-audit-candidate-20260801",
|
||||
"last_checkpoint": "xiaobai-preservation-slice-11-audit-candidate-standalone-20260801",
|
||||
"next_action": "user_acceptance_on_local_port_8797_then_confirm_or_restore_each_trial_retirement; do_not_switch_docker_or_nas_before_approval",
|
||||
"authoritative_documents": [
|
||||
"AGENTS.md",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
| 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项测试通过;撤销无效竞价截图;仍等待人工确认 |
|
||||
|
||||
## 资产处置登记
|
||||
|
||||
@@ -220,6 +221,12 @@
|
||||
非交易日误作预期合并日;两版测试夹具同步固定到明确工作日,产品代码和日期规则未改。
|
||||
- 跨日修复后统一验收再次通过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集合竞价候选截图实际为登录失效页,已重命名并撤销证明力;九组有效截图像素差异
|
||||
低于动态渲染噪声阈值,集合竞价最终视觉继续等待人工验收。
|
||||
|
||||
## 决策记录
|
||||
|
||||
|
||||
Reference in New Issue
Block a user