pbl_runtime_ext/scripts/m11b2c_a3_replay_check.py
2026-09-22 11:56:06 +08:00

120 lines
4.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""M11b-2c-A3 交付自洽性重放校验器(可复跑,QC 复核用)。
背景(QC 退回 #10):上一轮引擎在交付时又代为提交了一次补丁器修正(51c3f26),
说明 agent 交付的仓库状态并非最终自洽状态——补丁器与定稿 tx_write.py 不一致,
靠引擎收口补齐。本脚本把「HEAD 即最终态」变成可机械复验的断言。
做法(不污染工作区,全部在临时目录内完成):
1. 从 git 取 HEAD 版本的补丁器 scripts/m11b2c_a3_patch_tx_write.py;
2. 从 git 取 5542cf5^(修复前)版本的 pbl_runtime_ext/tx_write.py 原文;
3. 在临时目录里按补丁器自身的 TARGET 相对路径摆好文件,直接 import 并调用其
main()(等价于在机构工作空间根执行该补丁器);
4. 把重放产物与 HEAD 版本的 tx_write.py 逐字节比对(cmp + sha256 双口径);
5. 一致 -> REPLAY_IDENTICAL: YES,退出码 0;不一致 -> NO,退出码 1。
用法(在模块仓库内或机构工作空间根均可):
python3 scripts/m11b2c_a3_replay_check.py
"""
import hashlib
import io
import os
import shutil
import subprocess
import sys
import tempfile
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PATCHER = "scripts/m11b2c_a3_patch_tx_write.py"
TX_WRITE = "pbl_runtime_ext/tx_write.py"
FIX_COMMIT = "5542cf5d5182130aa929e5aa37d0c22a043cee25"
def _git_rev_parse(rev):
return _git("rev-parse", rev).strip()
def _git(*args):
out = subprocess.run(["git", "-C", REPO] + list(args),
check=True, stdout=subprocess.PIPE)
return out.stdout.decode("utf-8")
def _sha(path):
with io.open(path, "rb") as f:
return hashlib.sha256(f.read()).hexdigest()
def main():
print("== M11b-2c-A3 补丁器/定稿一致性重放校验 ==")
print("repo : %s" % REPO)
head = _git_rev_parse("HEAD")
print("HEAD : %s" % head)
print("HEAD subject : %s" % _git("log", "-1", "--format=%s").strip())
print("fix commit : %s" % FIX_COMMIT)
print("patcher@HEAD : %s" % _git_rev_parse("HEAD:%s" % PATCHER))
print("tx_write@HEAD : %s" % _git_rev_parse("HEAD:%s" % TX_WRITE))
print("tx_write@fix^ : %s" % _git_rev_parse("%s^:%s" % (FIX_COMMIT, TX_WRITE)))
tmp = tempfile.mkdtemp(prefix="m11b2c_a3_replay_")
rc = 1
try:
# 1) 取 HEAD 版补丁器
patcher_dir = os.path.join(tmp, "inst", "modules", "pbl_runtime_ext", "scripts")
target_dir = os.path.join(tmp, "inst", "modules", "pbl_runtime_ext", "pbl_runtime_ext")
os.makedirs(patcher_dir)
os.makedirs(target_dir)
with io.open(os.path.join(patcher_dir, os.path.basename(PATCHER)), "w",
encoding="utf-8") as f:
f.write(_git("show", "HEAD:%s" % PATCHER))
# 2) 取修复前 tx_write.py 原文,摆到补丁器 TARGET 的相对位置
pre_path = os.path.join(target_dir, "tx_write.py")
with io.open(pre_path, "w", encoding="utf-8") as f:
f.write(_git("show", "%s^:%s" % (FIX_COMMIT, TX_WRITE)))
head_path = os.path.join(tmp, "tx_write_HEAD.py")
with io.open(head_path, "w", encoding="utf-8") as f:
f.write(_git("show", "HEAD:%s" % TX_WRITE))
pre_sha = _sha(pre_path)
head_sha = _sha(head_path)
print("pre-fix sha256 : %s" % pre_sha)
print("HEAD sha256 : %s" % head_sha)
# 3) 在临时目录内执行 HEAD 版补丁器(TARGET 是相对路径,故 cwd 必须是 inst/)
sys.path.insert(0, patcher_dir)
mod_name = "m11b2c_a3_patch_tx_write"
if mod_name in sys.modules:
del sys.modules[mod_name]
patcher = __import__(mod_name)
cwd = os.getcwd()
os.chdir(os.path.join(tmp, "inst"))
try:
prc = patcher.main()
finally:
os.chdir(cwd)
print("patcher exit rc : %d (0=已应用 4 处补丁, 2=片段命中数异常)" % prc)
if prc != 0:
print("REPLAY_IDENTICAL: NO(补丁器在修复前原文上执行失败,rc=%d)" % prc)
return 1
# 4) 逐字节比对
replayed_sha = _sha(pre_path)
print("replayed sha256 : %s" % replayed_sha)
cmp_rc = subprocess.run(["cmp", pre_path, head_path]).returncode
print("cmp 退出码 : %d (0=逐字节一致)" % cmp_rc)
if replayed_sha == head_sha and cmp_rc == 0:
print("REPLAY_IDENTICAL: YES(补丁器重放产物 == HEAD 定稿,逐字节一致)")
print("结论:HEAD 即最终自洽态,补丁器与定稿 tx_write.py 一致,无待引擎收口内容。")
rc = 0
else:
print("REPLAY_IDENTICAL: NO(补丁器与定稿不一致,仓库状态非最终态)")
rc = 1
return rc
finally:
shutil.rmtree(tmp, ignore_errors=True)
if __name__ == "__main__":
sys.exit(main())