Files
aetherbound-guild/tools/m89_page_coverage.py
T

102 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""M89 view -> probe -> marker coverage audit (read-only, docs-grade evidence).
Discovery is by preload: a probe is the tool/test file that preloads the view's
script. Markers are read out of the probe source, so a renamed probe is caught
instead of being silently trusted.
"""
import argparse
import pathlib
import re
import sys
ROOT = pathlib.Path(__file__).resolve().parents[1]
RUNTIME = ROOT / "runtime"
VIEWS = RUNTIME / "entry" / "views"
SEARCH_DIRS = [RUNTIME / "tools", RUNTIME / "tests"]
LEDGER = ROOT / "docs" / "EVIDENCE_LEDGER.md"
BATTLE_DRIVEN = "m60+m79+battle_ink"
BATTLE_VIEWS = {"battle_live_page_view", "battle_opening_page_view"}
def probe_for(view_stem: str):
needle = "res://entry/views/%s.gd" % view_stem
for base in SEARCH_DIRS:
for path in sorted(base.rglob("*.gd")):
if path.name.endswith(".uid"):
continue
try:
text = path.read_text(encoding="utf-8", errors="replace")
except OSError:
continue
if needle in text:
return path, text
return None, ""
def markers(text: str):
found = re.findall(r'(ABG_[A-Z0-9_]+)', text)
primaries = [m for m in found if m.endswith("_OK") and "SELF_TEST" not in m]
return primaries
def styleboxflat_count(view_text: str) -> int:
return len(re.findall(r"StyleBoxFlat", view_text))
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--matrix", help="write the refreshed matrix markdown here")
args = parser.parse_args()
ledger = LEDGER.read_text(encoding="utf-8") if LEDGER.exists() else ""
views = sorted(p for p in VIEWS.glob("*.gd") if not p.name.endswith(".uid"))
rows, uncovered, no_marker, no_ledger = [], [], [], []
probes = set()
for view in views:
stem = view.stem
probe_path, probe_text = probe_for(stem)
view_text = view.read_text(encoding="utf-8", errors="replace")
flats = styleboxflat_count(view_text)
if stem in BATTLE_VIEWS and probe_path is None:
rows.append((stem, "driven", "-", flats, "battle ink (driver)", BATTLE_DRIVEN))
continue
if probe_path is None:
uncovered.append(stem)
rows.append((stem, "?", "-", flats, "NONE", "-"))
continue
probes.add(str(probe_path.relative_to(ROOT)))
found = markers(probe_text)
if not found:
no_marker.append(stem)
in_ledger = [m for m in found if m in ledger]
if found and not in_ledger:
no_ledger.append(stem)
rows.append((stem, "shared", str(probe_path.relative_to(ROOT)), flats,
found[0] if found else "NO_MARKER",
"ledger" if in_ledger else "not_in_ledger"))
if args.matrix:
out = ["# M62 页面一致性矩阵(M89 刷新)", "",
"> 由 `tools/m89_page_coverage.py --matrix` 生成;StyleBoxFlat 数为视图源码 grep 实测。", "",
"| 视图 | chrome 族 | 探针 | 页面私有 StyleBoxFlat | marker | 账本 |",
"| --- | --- | --- | --- | --- | --- |"]
for row in rows:
out.append("| `%s` | %s | `%s` | %d | `%s` | %s |" % row)
pathlib.Path(args.matrix).write_text("\n".join(out) + "\n", encoding="utf-8")
ok = not uncovered and not no_marker and not no_ledger
detail = "uncovered=%s markers_missing=%s ledger_missing=%s" % (
",".join(uncovered) or "none", ",".join(no_marker) or "none", ",".join(no_ledger) or "none")
if ok:
print("ABG_M89_PAGE_COVERAGE_OK views=%d probes=%d uncovered=none battle=driven:%s" % (
len(views), len(probes), BATTLE_DRIVEN))
else:
print("ABG_M89_PAGE_COVERAGE_FAIL views=%d probes=%d %s" % (len(views), len(probes), detail))
print("ABG_M89_PAGE_COVERAGE_DETAIL " + detail)
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())