TeX 59%
Python 40.8%
1#!/usr/bin/env python32"""Write results/manifest.json: every result artefact with size, SHA-256, producing script and inputs."""3import hashlib4import json5import subprocess6import time7from pathlib import Path89ROOT = Path(__file__).resolve().parents[1]10R = ROOT / "results"11PRODUCERS = {12 "tables/frame_exclusions.csv": "src/ingestion/build_frame.py", "tables/robots_exclusion_balance.csv": "src/ingestion/build_frame.py",13 "raw/frame_summary.json": "src/ingestion/build_frame.py", "raw/sample_summary.json": "src/ingestion/sample.py",14 "raw/exp_agreement.json": "scripts/06_exp_agreement.py", "raw/exp_cost.json": "scripts/07_exp_cost.py",15 "raw/aggregate_summary.json": "scripts/05_aggregate.py", "raw/api_usage.jsonl": "src/extraction/client.py",16 "raw/image_hosts.json": "ad hoc host census (research_log 2026-10-20)", "raw/robots_check.txt": "curl robots.txt census (research_log)",17}181920def sha(p: Path) -> str:21 h = hashlib.sha256()22 with open(p, "rb") as fh:23 for chunk in iter(lambda: fh.read(1 << 20), b""):24 h.update(chunk)25 return h.hexdigest()262728def main():29 items = []30 for p in sorted(R.rglob("*")):31 if p.is_dir() or p.name == "manifest.json" or ".DS_Store" in p.name:32 continue33 rel = str(p.relative_to(R))34 prod = PRODUCERS.get(rel)35 if prod is None:36 if rel.startswith("tables/exp1") and rel.startswith(("tables/exp1_", "tables/exp2", "tables/exp3", "tables/exp4", "tables/exp9", "tables/exp12", "tables/exp16")):37 prod = "scripts/06_exp_agreement.py"38 elif rel.startswith("tables/exp"):39 prod = "scripts/07_exp_cost.py" if any(rel.startswith(f"tables/exp{k}") for k in ("5", "6", "7", "10", "13", "14", "15")) else "scripts/06_exp_agreement.py"40 elif rel.startswith("tables/tex/"):41 prod = "src/visualization/tables.py"42 elif rel.startswith("figures/"):43 prod = "src/visualization/figures.py"44 elif rel.startswith("raw/batches/"):45 prod = "scripts/04_run_batches.py (Anthropic Message Batches API)"46 items.append({"path": rel, "bytes": p.stat().st_size, "sha256": sha(p), "producer": prod, "modified": time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(p.stat().st_mtime))})47 try:48 commit = subprocess.run(["git", "rev-parse", "HEAD"], cwd=ROOT, capture_output=True, text=True).stdout.strip()49 except Exception:50 commit = None51 manifest = {"generated": time.strftime("%Y-%m-%dT%H:%M:%S"), "git_commit": commit or "uncommitted",52 "schema_version": json.load(open(R / "raw" / "batches" / "run_meta.json"))["schema_version"],53 "prompt_version": json.load(open(R / "raw" / "batches" / "run_meta.json"))["prompt_version"],54 "n_items": len(items), "items": items}55 json.dump(manifest, open(R / "manifest.json", "w"), indent=1)56 print(len(items), "artefacts listed")575859if __name__ == "__main__":60 main()61