Files
Agent-System-Dev/scripts/facts-verify.sh
T
weichen ba83a17c11 Add evidence gates: facts registry, evidence tooling, and precheck checks
Why: declarations were passing as capability; hand-transcribed outputs flowed
through cards and PR bodies as if they were execution evidence, and stale
external facts (e.g. the dead git-panel host) kept being trusted until burned.

Evidence: guidelines draft.10 (PR Development-Guidelines#4, merged af199ee)
pinned here; policy/facts.md F1-F4 each re-verified on 2026-10-05 before
registration (endpoint version, token HTTP 200 via header only, SSH ls-remote,
dead-host negative probe); scripts syntax-checked (bash -n); tool self-tests
and make test recorded in the task card via the new make evidence.

Impact: new AGENTS.md section (SELF/REPLAY/GATE, tool-written evidence,
replay-on-review, zero-trust facts, honest-empty); make evidence/facts-verify;
precheck gains [hooks]/[facts], task-sync gains stale-evidence-HEAD warning;
task-start cards now embed the evidence table; gitlink advances to draft.10.

Refs: task card .task/feature-evidence-driven-gates.md; guidelines CHANGELOG
0.1.0-draft.10.
2026-10-05 10:47:27 +00:00

43 lines
2.0 KiB
Bash
Executable File
Raw 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.
#!/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