#!/usr/bin/env python3 """Build the browser evidence index from the committed Markdown ledger.""" from __future__ import annotations import argparse import hashlib import json import re from pathlib import Path ROOT = Path(__file__).resolve().parents[1] LEDGER = ROOT / "research" / "completion-verification" / "evidence-ledger.md" OUTPUT = ROOT / "evaluation-site" / "assets" / "evidence-data.js" SECTION_SLUGS = { "完成证明与 evaluator 误差": "verification", "测试、benchmark 和协议会不会错误认证": "protocol", "故障发现、定位和恢复": "recovery", "变更风险、协作和重复可靠性": "reliability", "全文池与排除": "context", } def parse_link(value: str) -> tuple[str, str]: match = re.fullmatch(r"\[([^\]]+)\]\((https?://[^)]+)\)", value.strip()) if not match: raise ValueError(f"Invalid paper link: {value}") return match.group(1), match.group(2) def parse_ledger(text: str) -> list[dict[str, str]]: section = "" records: list[dict[str, str]] = [] for raw_line in text.splitlines(): heading = re.match(r"^## \d+\.\s+(.+)$", raw_line) if heading: title = heading.group(1).strip() section = SECTION_SLUGS.get(title, "") continue if not raw_line.startswith("| ["): continue columns = [column.strip() for column in raw_line.strip().strip("|").split("|")] if len(columns) not in {3, 5}: raise ValueError(f"Unexpected table row with {len(columns)} columns: {raw_line}") title, url = parse_link(columns[0]) arxiv_match = re.search(r"(\d{4}\.\d{5})", url) if not arxiv_match: raise ValueError(f"Missing arXiv id: {url}") arxiv_id = arxiv_match.group(1) title = re.sub(rf",\s*{re.escape(arxiv_id)}$", "", title) record = { "id": arxiv_id, "title": title, "url": url, "depth": columns[1], "theme": section, } if len(columns) == 5: record.update( { "evidence": columns[2], "supports": columns[3], "boundary": columns[4], } ) else: record.update( { "evidence": "", "supports": "", "boundary": columns[2], } ) records.append(record) return records def build_payload(text: str) -> dict[str, object]: records = parse_ledger(text) counts = { "pool": len(records), "audited": sum(record["depth"] in {"core", "support"} for record in records), "core": sum(record["depth"] == "core" for record in records), "support": sum(record["depth"] == "support" for record in records), "context": sum(record["depth"] == "context" for record in records), } return { "source": "research/completion-verification/evidence-ledger.md", "source_sha256": hashlib.sha256(text.encode("utf-8")).hexdigest(), "counts": counts, "records": records, } def render(payload: dict[str, object]) -> str: body = json.dumps(payload, ensure_ascii=False, separators=(",", ":")) return ( "/* Generated by evaluation-site/build_research_data.py. */\n" f"window.K1412_EVIDENCE={body};\n" ) def main() -> int: parser = argparse.ArgumentParser() parser.add_argument( "--check", action="store_true", help="Fail if the generated browser data is stale.", ) args = parser.parse_args() expected = render(build_payload(LEDGER.read_text(encoding="utf-8"))) if args.check: if not OUTPUT.exists() or OUTPUT.read_text(encoding="utf-8") != expected: print(f"stale: {OUTPUT.relative_to(ROOT)}") return 1 print(f"ok: {OUTPUT.relative_to(ROOT)}") return 0 OUTPUT.write_text(expected, encoding="utf-8") print(f"wrote: {OUTPUT.relative_to(ROOT)}") return 0 if __name__ == "__main__": raise SystemExit(main())