#!/usr/bin/env python3 # -*- coding: utf-8 -*- """判读等价对拍工具(结算期文字列表退役批 R4 载体——日志零文案改后分析判读逐位一致)。 用法: python tools/analyze_parity_check.py <输入A> <输入B> [<输入C> ...] [--runs N] 输入 = 日志(.jsonl,各跑一次 tools/analyze_playtest.py 完整判读)或基线快照 (.md,analyze_playtest.py 输出重定向落盘的静态文本,直读不重跑)。全部剥去文件名 标题行后相邻逐位 diff——任一对不一致即 exit 1 并打印第一条分歧行。 三读数跑法(改前改后配对,卡 R4): ① 历史锚日志 vs 改前 T0 基线快照(兼容分支等价) ② 改前同种子日志 vs 改前 T0 基线快照(复现等价) ③ 改前同种子日志 vs 改后同种子新日志(同种子+玩法零改动=事件流逐位同) 退出码: 0=全部逐位一致 1=判读分歧 2=参数/执行错误 """ import subprocess import sys from pathlib import Path HERE = Path(__file__).resolve().parent ANALYZE = HERE / "analyze_playtest.py" def run_analyze(log_path: str, runs: str) -> str: cmd = [sys.executable, str(ANALYZE), log_path] if runs: cmd += [runs] proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8") if proc.returncode != 0: print("[parity] 判读执行失败(%s)exit=%d" % (log_path, proc.returncode)) print(proc.stdout[-2000:]) print(proc.stderr[-2000:]) sys.exit(2) # 剥文件名标题行(playtest_*.jsonl 文件名随输入变,不参与逐位比对) return strip_name_lines(proc.stdout) def strip_name_lines(text: str) -> str: out_lines = [] for ln in text.splitlines(): if "playtest_" in ln and ".jsonl" in ln: continue out_lines.append(ln) return "\n".join(out_lines) def first_diff(a: str, b: str): la, lb = a.splitlines(), b.splitlines() for i in range(max(len(la), len(lb))): xa = la[i] if i < len(la) else "<缺行>" xb = lb[i] if i < len(lb) else "<缺行>" if xa != xb: return i + 1, xa, xb return None def main(): args = sys.argv[1:] runs = "" if "--runs" in args: i = args.index("--runs") runs = args[i + 1] args = args[:i] + args[i + 2:] if len(args) < 2: print(__doc__) sys.exit(2) outputs = [] for p in args: if p.lower().endswith(".jsonl"): outputs.append(run_analyze(p, runs)) else: # 基线快照(.md)——静态文本直读,剥名规则同判读输出 outputs.append(strip_name_lines(Path(p).read_text(encoding="utf-8"))) ok = True for i in range(1, len(outputs)): d = first_diff(outputs[i - 1], outputs[i]) pair = "%s <-> %s" % (Path(args[i - 1]).name, Path(args[i]).name) if d is None: print("[parity] 一致 | %s | 判读逐位一致" % pair) else: ln, xa, xb = d print("[parity] 分歧 | %s | 第 %d 行" % (pair, ln)) print(" A: %s" % xa) print(" B: %s" % xb) ok = False sys.exit(0 if ok else 1) if __name__ == "__main__": main()