#!/usr/bin/env bash # 外部事实登记表逐条重验:对 policy/facts.md 每条事实执行其验证命令并报告 PASS/FAIL。 # 规则依据:AGENTS.md「证据与验证门禁」(外部事实零信任);verification.md「声明与证据来源」。 # 用法:make facts-verify [ARGS=--update] (--update:把 PASS 项 last_verified 刷为当天并写回) # 表内验证命令约定不含竖线;含 "\|" 转义时按字面还原后执行。 set -uo pipefail F="${FACTS:-policy/facts.md}" [ -f "$F" ] || { echo "ERROR: 事实登记表 $F 不存在" >&2; exit 1; } python3 - "$F" "${1:-}" <<'PY' import re, subprocess, sys, datetime path, update = sys.argv[1], sys.argv[2] == "--update" lines = open(path, encoding="utf-8").read().splitlines(keepends=True) today = datetime.date.today().isoformat() total = fails = 0 for i, line in enumerate(lines): if not re.match(r"^\|\s*F\d+\s*\|", line): continue raw = line.strip().strip("|").replace("\\|", "\x00") cells = [c.strip().replace("\x00", "|") for c in raw.split("|")] if len(cells) < 4: print(f"[row {i+1}] SKIP 格式不符(列数<4)", file=sys.stderr) continue fid, cmd = cells[0], cells[2].strip("`") total += 1 try: r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=90) ok = r.returncode == 0 except subprocess.TimeoutExpired: ok = False print(f"[{fid}] TIMEOUT >90s", file=sys.stderr) print(f"[{fid}] {'PASS' if ok else 'FAIL'} :: {cmd[:80]}") if not ok: fails += 1 elif update and len(cells) >= 4 and re.match(r"\d{4}-\d{2}-\d{2}", cells[3]): cells[3] = today lines[i] = "| " + " | ".join(c.replace("|", "\\|") for c in cells) + " |\n" if update: open(path, "w", encoding="utf-8").writelines(lines) print(f"[facts-verify] total={total} pass={total - fails} fail={fails}" + (";last_verified 已刷新为 " + today if update and total else "")) sys.exit(1 if fails else 0) PY