#!/usr/bin/env python3 """常设不变量检查(harness 改造原则 5:从靠预防迁到靠发现)。 逻辑隔离不能全靠预防,必须靠持续发现——从物理隔离迁到逻辑隔离的那一刻, 必须同时从"靠预防"迁到"靠发现"。本脚本跑一组常设不变量,违反即报警(退出码非 0)。 建议常设运行(CI / 看板健康面),违反即报警。 检查项: I1 没有评测候选被接受(run_type=eval/diagnostic 且 state=accepted)——引擎已防,此为发现兜底。 I2 没有正式正文的来源能追溯到评测候选(归因 source_object_id → 评测候选)。 I3 评测候选的质量结果可被生产视图过滤(带评测标记,不混入生产质量视图)。 I4 oracle 读侧红线:oracle/标准答案以 kind='oracle' 标记,生产模型输入不得包含(read-context 生产路径保证;此处校验标记完整)。 I5 COMPLETED 轮次封存:一轮声明的 raw 集合 == 实际落库集合(lease 声明的 content_hashes 数 == 实际 raw_content 行数)。 跑法:.venv/bin/python .claude/skills/runtime/scripts/invariant_checks.py [--run-id X] """ import argparse import json import sys from pathlib import Path DB_SCRIPTS = Path(__file__).resolve().parents[2] / "db" / "scripts" sys.path.insert(0, str(DB_SCRIPTS)) from db import connect # noqa: E402 def _count(conn, sql, params=()): return conn.execute(sql, params).fetchone()[0] def check_invariants(run_id=None): """返回 [(检查项, 是否通过, 说明)]。""" results = [] with connect(readonly=True) as conn: # I1 没有评测候选被接受 n = _count(conn, "SELECT count(*) FROM example_candidate " "WHERE run_type IN ('eval','diagnostic') AND state='accepted'") results.append(("I1 评测候选未被接受", n == 0, f"{n} 个评测候选被接受" if n else "无评测候选被接受")) # I2 没有正式正文来源追溯到评测候选 n = _count(conn, "SELECT count(*) FROM muse_content_block_source_attribution a " "JOIN example_candidate c ON c.id::text = a.source_object_id " "WHERE c.run_type IN ('eval','diagnostic')") results.append(("I2 正式正文来源不追溯到评测候选", n == 0, f"{n} 个正式正文来源追溯到评测候选" if n else "无正式正文来源追溯到评测候选")) # I3 评测候选的质量结果可被生产视图过滤(评测候选的质量结果都能关联到评测候选,即可过滤) n = _count(conn, "SELECT count(*) FROM example_quality_result q " "JOIN example_candidate c ON c.candidate_sha256 = q.candidate_sha256 " "WHERE c.run_type IN ('eval','diagnostic') AND q.candidate_sha256 IS NULL") results.append(("I3 评测质量结果可过滤", n == 0, f"{n} 个评测质量结果无法关联评测候选(无法过滤)" if n else "评测质量结果均可关联过滤")) # I4 oracle 读侧红线:oracle raw 行都带 kind='oracle' 标记(生产路径据此排除) n = _count(conn, "SELECT count(*) FROM example_raw_content " "WHERE kind='oracle' AND content_sha256 IS NULL") results.append(("I4 oracle 标记完整", n == 0, f"{n} 个 oracle raw 缺哈希标记" if n else "oracle raw 标记完整")) # I5 COMPLETED 轮次封存:lease 声明的 content_hashes 数 == 实际 raw_content 行数 if run_id: leases = conn.execute( "SELECT id, content_hashes FROM example_raw_lease WHERE run_id=%s", (run_id,)).fetchall() else: leases = conn.execute("SELECT id, content_hashes FROM example_raw_lease").fetchall() seal_violations = 0 for lease_id, content_hashes in leases: declared = len(content_hashes) if isinstance(content_hashes, list) else 0 actual = _count(conn, "SELECT count(*) FROM example_raw_content WHERE lease_id=%s", (lease_id,)) if declared != actual: seal_violations += 1 results.append(("I5 轮次封存(声明==实际落库)", seal_violations == 0, f"{seal_violations} 个租约声明与实际落库不符" if seal_violations else "所有租约封存一致")) return results def main(): ap = argparse.ArgumentParser(description="常设不变量检查(从靠预防迁到靠发现)") ap.add_argument("--run-id", default=None, help="只检查某轮的轮次封存") args = ap.parse_args() results = check_invariants(run_id=args.run_id) all_pass = True for name, ok, msg in results: print(f"[{'PASS' if ok else 'VIOLATION'}] {name}:{msg}") if not ok: all_pass = False if not all_pass: print("\n有不变量被违反——逻辑隔离出现越界,须排查。", file=sys.stderr) sys.exit(1) print("\n所有不变量通过。") if __name__ == "__main__": main()