138 lines
6.7 KiB
Python
138 lines
6.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""A3a-1b 重做轮(响应 QC #6/#7 硬门禁):§8 证据索引「跑的是什么」列逐字一致性核对。
|
||
|
||
三类行的处理方式:
|
||
(1) 单命令证据件:列内首反引号段以 `# CMD: ` 开头 → 与该证据文件首行去前缀后逐字比对;
|
||
(2) 转录件(非单命令输出,如 a1c_damage_forensics):列内以 `# FILE: ` 声明首行原文 → 与文件首行原文逐字比对;
|
||
(3) 本核对件自身(自指行):**不再无条件 SKIP-SELF**(QC #7:唯一真实漂移恰好落在自指行上,
|
||
SKIP 会造成假绿)。自指行核对两件事:
|
||
a. §8 自指行「跑的是什么」列引用的 CMD 是否指向本脚本当前实际路径(tests/checks/ 长期工具,脚本自身路径已知);
|
||
b. 本证据件(--evidence 指定)首行 `# CMD:` 去前缀后是否等于 §8 自指行引用 —— 即「生成后二次读取
|
||
自身文件首行」的闭环比对。两项任一不符即计入「不一致」,不接受 SKIP 作为一致。
|
||
|
||
用法:
|
||
取证第一跑(证据件尚未生成):
|
||
./.venv/bin/python tests/checks/m11b2d_a3a1b_cmd_index_consistency.py \
|
||
--evidence tests/evidence/m11b2d_a3a1b_cmd_index_consistency.txt
|
||
闭环第二跑(证据件已生成,同一命令,自指闭环比对生效):同上。
|
||
退出码:无不一致行 → 0;否则 1。
|
||
"""
|
||
import argparse
|
||
import io
|
||
import os
|
||
import sys
|
||
|
||
ROOT = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".."))
|
||
DOC = os.path.join(ROOT, "docs/work-log-2026-09-22-m11b2d-fixture-contract.md")
|
||
SELF_EVID_DEFAULT = "tests/evidence/m11b2d_a3a1b_cmd_index_consistency.txt"
|
||
SELF_SCRIPT_REL = "tests/checks/m11b2d_a3a1b_cmd_index_consistency.py"
|
||
SELF_CMD_BASE = "cd modules/world_sync && ./.venv/bin/python " + SELF_SCRIPT_REL
|
||
|
||
|
||
def read_first(path):
|
||
with io.open(path, encoding="utf-8") as f:
|
||
return f.read().split("\n")[0]
|
||
|
||
|
||
def check_self_row(seg, self_evidence, self_evidence_abs):
|
||
"""返回 (verdict, detail)。自指行不 SKIP,按 QC #7 做闭环比对。"""
|
||
notes = []
|
||
bad = False
|
||
if seg is None:
|
||
return "不一致", ["自指行列内无 CMD 原文可核"]
|
||
if not seg.startswith("# CMD: "):
|
||
return "不一致", ["自指行列内首段非 # CMD(转录件写法):%r" % seg[:40]]
|
||
doc_cmd = seg[len("# CMD: "):]
|
||
# a. §8 自指行 CMD 必须指向本脚本当前实际路径(允许追加 --evidence 参数)
|
||
ok_path = (doc_cmd == SELF_CMD_BASE
|
||
or doc_cmd.startswith(SELF_CMD_BASE + " --evidence ")
|
||
or doc_cmd.startswith(SELF_CMD_BASE + " "))
|
||
if not ok_path:
|
||
bad = True
|
||
notes.append("§8 自指行 CMD 未指向脚本实际路径 DOC=%r EXPECTED_BASE=%r" % (doc_cmd, SELF_CMD_BASE))
|
||
else:
|
||
notes.append("§8 自指行 CMD 指向脚本实际路径 %s" % SELF_SCRIPT_REL)
|
||
# b. 闭环比对:本核对件首行 == §8 自指行引用
|
||
if os.path.exists(self_evidence_abs):
|
||
first = read_first(self_evidence_abs)
|
||
if not first.startswith("# CMD: "):
|
||
bad = True
|
||
notes.append("本核对件首行非 `# CMD:` 原文")
|
||
elif first[len("# CMD: "):] != doc_cmd:
|
||
bad = True
|
||
notes.append("自指闭环失败:本核对件首行 CMD 与 §8 自指行引用不一致 FILE=%r DOC=%r"
|
||
% (first[len("# CMD: "):], doc_cmd))
|
||
else:
|
||
notes.append("自指闭环通过:本核对件首行 `# CMD:` 去前缀后与 §8 自指行引用逐字相同")
|
||
else:
|
||
notes.append("本核对件尚未生成(磁盘无 %s),自指闭环比对留待生成后以同一命令第二跑完成"
|
||
% self_evidence)
|
||
return ("不一致 " if bad else "一致 ") + ";".join(notes), notes
|
||
|
||
|
||
def main():
|
||
ap = argparse.ArgumentParser()
|
||
ap.add_argument("--evidence", default=SELF_EVID_DEFAULT,
|
||
help="本核对件(证据文件)路径,用于自指闭环比对")
|
||
args = ap.parse_args()
|
||
|
||
self_evidence = args.evidence.strip() or SELF_EVID_DEFAULT
|
||
self_evidence_abs = os.path.join(ROOT, self_evidence)
|
||
|
||
lines = io.open(DOC, encoding="utf-8").read().split("\n")
|
||
rows = []
|
||
for ln, text in enumerate(lines, 1):
|
||
t = text.strip()
|
||
if not (t.startswith("| `tests/evidence/") and t.endswith("|")):
|
||
continue
|
||
cells = [c.strip() for c in t.strip("|").split("`")]
|
||
fpath = t.strip("|").split("|")[0].strip().strip("`")
|
||
|
||
if fpath == self_evidence:
|
||
seg = None
|
||
for c in cells[1:]:
|
||
if c.strip().startswith("# CMD: ") or c.strip().startswith("# FILE: "):
|
||
seg = c.strip()
|
||
break
|
||
verdict, _ = check_self_row(seg, self_evidence, self_evidence_abs)
|
||
rows.append((ln, fpath, "自指行(本核对件自身,按 QC #7 闭环比对)", verdict))
|
||
continue
|
||
|
||
seg = None
|
||
for c in cells[1:]:
|
||
if c.strip().startswith("# CMD: ") or c.strip().startswith("# FILE: "):
|
||
seg = c.strip()
|
||
break
|
||
if seg is None:
|
||
rows.append((ln, fpath, "列内无 CMD/FILE 原文可核", "SKIP"))
|
||
continue
|
||
full = os.path.join(ROOT, fpath)
|
||
if not os.path.exists(full):
|
||
rows.append((ln, fpath, "证据文件不存在", "FAIL"))
|
||
continue
|
||
first = read_first(full)
|
||
if seg.startswith("# CMD: "):
|
||
doc_cmd = seg[len("# CMD: "):]
|
||
file_cmd = first[len("# CMD: "):] if first.startswith("# CMD: ") else "(文件首行非 # CMD:)"
|
||
verdict = "一致" if doc_cmd == file_cmd else "不一致 DOC=%r FILE=%r" % (doc_cmd, file_cmd)
|
||
else: # 转录件:核首行原文
|
||
verdict = "一致" if first == seg else "不一致 DOC=%r FILE=%r" % (seg, first)
|
||
rows.append((ln, fpath, seg[:60] + "…", verdict))
|
||
|
||
fails = [r for r in rows if r[3].startswith("不一致") or r[3] == "FAIL"]
|
||
print("SELF-SCRIPT: " + SELF_SCRIPT_REL)
|
||
print("SELF-EVIDENCE: %s (exists=%s)"
|
||
% (self_evidence, "yes" if os.path.exists(self_evidence_abs) else "no"))
|
||
print("SELF-CMD-BASE: " + SELF_CMD_BASE)
|
||
for ln, fpath, seg, verdict in rows:
|
||
print(" L%-4d %-62s %s" % (ln, fpath, verdict))
|
||
print("统计:核对行 %d,一致 %d,跳过(列内无原文可核) %d,不一致 %d"
|
||
% (len(rows), sum(1 for r in rows if r[3].startswith("一致")),
|
||
sum(1 for r in rows if r[3] == "SKIP"), len(fails)))
|
||
print("RESULT: " + ("ALL_ROWS_CONSISTENT" if not fails else "HAS_INCONSISTENT_ROWS"))
|
||
return 0 if not fails else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|