76 lines
3.4 KiB
Python
76 lines
3.4 KiB
Python
|
|
# 文档技术选型漂移门禁(plan.md §12 / 矩阵「跨层契约和文档同轮同步」)
|
|||
|
|
# ============================================================
|
|||
|
|
# 桌面技术选型描述必须与代码事实一致(Electron)或明确标注「待决策」;
|
|||
|
|
# 禁止出现孤立「Tauri(后期/规划)」式绝对描述。Hybrid 求解描述与代码一致。
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|||
|
|
DOCS = ROOT / "docs"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _lines(rel: str) -> list[str]:
|
|||
|
|
return (DOCS / rel).read_text(encoding="utf-8").splitlines()
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _desktop_related(lines: list[str]) -> list[tuple[int, str]]:
|
|||
|
|
"""返回提及桌面/桌面壳/Tauri/Electron 的行。"""
|
|||
|
|
out = []
|
|||
|
|
for i, line in enumerate(lines, 1):
|
|||
|
|
low = line.lower()
|
|||
|
|
if any(k in low for k in ("桌面", "tauri", "electron", "desktop")):
|
|||
|
|
out.append((i, line))
|
|||
|
|
return out
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_overview_desktop_row_matches_implementation():
|
|||
|
|
"""overview.md 技术选型表:桌面行必须指向 Electron 实现,Tauri 仅作待决策目标态。"""
|
|||
|
|
lines = _lines("architecture/overview.md")
|
|||
|
|
hits = _desktop_related(lines)
|
|||
|
|
assert hits, "overview.md 应有桌面技术选型行"
|
|||
|
|
# 至少一行同时含 Electron 与 待决策(或明确当前实现)
|
|||
|
|
joined = "\n".join(text for _, text in hits).lower()
|
|||
|
|
assert "electron" in joined
|
|||
|
|
assert "tauri" not in joined or "决策" in joined or "待定" in joined
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_positioning_desktop_row_matches_implementation():
|
|||
|
|
"""positioning.md 形态行:Electron 已实现,Tauri 目标态须标注待决策。"""
|
|||
|
|
lines = _lines("product/positioning.md")
|
|||
|
|
hits = _desktop_related(lines)
|
|||
|
|
assert hits, "positioning.md 应有形态行"
|
|||
|
|
joined = "\n".join(text for _, text in hits).lower()
|
|||
|
|
assert "electron" in joined
|
|||
|
|
if "tauri" in joined:
|
|||
|
|
assert "待决策" in joined or "待定" in joined
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_no_lone_tauri_future_claim():
|
|||
|
|
"""禁止孤立「Tauri(后期/规划)」式绝对描述(与 Electron 现状矛盾)。"""
|
|||
|
|
for rel in ("architecture/overview.md", "product/positioning.md"):
|
|||
|
|
for i, line in _desktop_related(_lines(rel)):
|
|||
|
|
low = line.lower()
|
|||
|
|
if "tauri" in low and "electron" not in low:
|
|||
|
|
assert "待决策" in low or "待定" in low, f"{rel}:{i} Tauri 描述缺待决策标注"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_hybrid_engine_descriptions_consistent():
|
|||
|
|
"""Hybrid 求解描述:文档提及 HYBRID 时必须与代码引擎一致(不能写纯 Tauri 式虚构)。"""
|
|||
|
|
from server.engines import get_engine
|
|||
|
|
engines = get_engine
|
|||
|
|
assert callable(engines)
|
|||
|
|
# 代码支持 HYBRID(docs/architecture/harness.md 变更记录已记录 HybridEngine)
|
|||
|
|
harness = (DOCS / "architecture" / "harness.md").read_text(encoding="utf-8")
|
|||
|
|
assert "HYBRID" in harness or "HybridEngine" in harness
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_ruiyang_runbook_separates_skipped_rows_from_problem_rows():
|
|||
|
|
"""round-61 文档必须区分真实问题行与非排产块跳过行。"""
|
|||
|
|
runbook = (DOCS / "product" / "ruiyang-data-runbook.md").read_text(encoding="utf-8")
|
|||
|
|
assert "非排产数据块已跳过且不计问题行" in runbook
|
|||
|
|
assert "`totalErrors`" in runbook
|
|||
|
|
assert "`skippedRows`" in runbook
|
|||
|
|
for stale in ("会记为问题行", "会算作问题行"):
|
|||
|
|
assert stale not in runbook, f"ruiyang-data-runbook.md 仍含 round-61 前的过期语义:{stale}"
|