88e86b3faccd
Rebuild benchmarks as a clean single-root reposi
2 months ago
| 1 | #!/usr/bin/env python3
|
| 2 | """Run the mechanical checks for a public benchmark drop.
|
| 3 |
|
| 4 | This script does not run benchmarks. It takes the JSONL files already intended
|
| 5 | for publication and writes a small readiness bundle:
|
| 6 |
|
| 7 | - publish_gate.txt: hard mechanical gate output
|
| 8 | - benchmark_stats.md: bootstrap confidence intervals for the same JSONL files
|
| 9 | - opportunities.md / opportunities.json: ranked backlog from the same results
|
| 10 | - manifest.json: exact inputs, commands, exit codes, and generated paths
|
| 11 | """
|
| 12 |
|
| 13 | from __future__ import annotations
|
| 14 |
|
| 15 | import argparse
|
| 16 | import contextlib
|
| 17 | import io
|
| 18 | import json
|
| 19 | import subprocess
|
| 20 | import sys
|
| 21 | from datetime import datetime, timezone
|
| 22 | from pathlib import Path
|
| 23 | from typing import Any
|
| 24 |
|
| 25 | import opportunities
|
| 26 | import publish_gate
|
| 27 |
|
| 28 |
|
| 29 | ROOT = Path(__file__).resolve().parents[1]
|
| 30 | DEFAULT_RESULTS = ROOT / "results"
|
| 31 |
|
| 32 |
|
| 33 | def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
| 34 | parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
| 35 | parser.add_argument(
|
| 36 | "jsonl",
|
| 37 | nargs="*",
|
| 38 | type=Path,
|
| 39 | help="Result JSONL files to publish. Defaults to latest JSONL files in --results.",
|
| 40 | )
|
| 41 | parser.add_argument("--results", type=Path, default=DEFAULT_RESULTS)
|
| 42 | parser.add_argument(
|
| 43 | "--out-dir",
|
| 44 | type=Path,
|
| 45 | help="Directory for readiness reports. Default: <results>/public-readiness.",
|
| 46 | )
|
| 47 | parser.add_argument("--bootstrap-samples", type=int, default=2000)
|
| 48 | parser.add_argument("--confidence", type=float, default=0.95)
|
| 49 | parser.add_argument("--skip-stats", action="store_true")
|
| 50 | parser.add_argument("--skip-opportunities", action="store_true")
|
| 51 | return parser.parse_args(argv)
|
| 52 |
|
| 53 |
|
| 54 | def discover_inputs(results: Path) -> list[Path]:
|
| 55 | candidates = [
|
| 56 | results / "latest.jsonl",
|
| 57 | results / "latest.mount.jsonl",
|
| 58 | results / "parallel-contention" / "latest.jsonl",
|
| 59 | ]
|
| 60 | return [path for path in candidates if path.exists()]
|
| 61 |
|
| 62 |
|
| 63 | def write_text(path: Path, text: str) -> str:
|
| 64 | path.parent.mkdir(parents=True, exist_ok=True)
|
| 65 | path.write_text(text)
|
| 66 | return str(path)
|
| 67 |
|
| 68 |
|
| 69 | def run_publish_gate(inputs: list[Path], out_dir: Path) -> dict[str, Any]:
|
| 70 | buf = io.StringIO()
|
| 71 | with contextlib.redirect_stdout(buf):
|
| 72 | exit_code = publish_gate.main([str(path) for path in inputs])
|
| 73 | return {
|
| 74 | "name": "publish_gate",
|
| 75 | "exit_code": exit_code,
|
| 76 | "path": write_text(out_dir / "publish_gate.txt", buf.getvalue()),
|
| 77 | }
|
| 78 |
|
| 79 |
|
| 80 | def run_benchmark_stats(
|
| 81 | inputs: list[Path],
|
| 82 | out_dir: Path,
|
| 83 | bootstrap_samples: int,
|
| 84 | confidence: float,
|
| 85 | ) -> dict[str, Any]:
|
| 86 | command = [
|
| 87 | sys.executable,
|
| 88 | str(ROOT / "scripts" / "benchmark_stats.py"),
|
| 89 | *[str(path) for path in inputs],
|
| 90 | "--bootstrap-samples",
|
| 91 | str(bootstrap_samples),
|
| 92 | "--confidence",
|
| 93 | str(confidence),
|
| 94 | ]
|
| 95 | proc = subprocess.run(command, cwd=ROOT, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
|
| 96 | stats_path = write_text(out_dir / "benchmark_stats.md", proc.stdout)
|
| 97 | stderr_path = None
|
| 98 | if proc.stderr:
|
| 99 | stderr_path = write_text(out_dir / "benchmark_stats.stderr.txt", proc.stderr)
|
| 100 | return {
|
| 101 | "name": "benchmark_stats",
|
| 102 | "exit_code": proc.returncode,
|
| 103 | "command": command,
|
| 104 | "path": stats_path,
|
| 105 | "stderr_path": stderr_path,
|
| 106 | }
|
| 107 |
|
| 108 |
|
| 109 | def run_opportunities(results: Path, inputs: list[Path], out_dir: Path) -> dict[str, Any]:
|
| 110 | report, entries = opportunities.generate_report(results, input_paths=inputs)
|
| 111 | report_path = write_text(out_dir / "opportunities.md", report)
|
| 112 | json_path = out_dir / "opportunities.json"
|
| 113 | json_path.write_text(json.dumps(entries, indent=2, sort_keys=True) + "\n")
|
| 114 | return {
|
| 115 | "name": "opportunities",
|
| 116 | "exit_code": 0,
|
| 117 | "path": str(report_path),
|
| 118 | "json_path": str(json_path),
|
| 119 | "entry_count": len(entries),
|
| 120 | }
|
| 121 |
|
| 122 |
|
| 123 | def main(argv: list[str] | None = None) -> int:
|
| 124 | args = parse_args(argv)
|
| 125 | results = args.results.resolve()
|
| 126 | out_dir = (args.out_dir or (results / "public-readiness")).resolve()
|
| 127 | inputs = [path.resolve() for path in (args.jsonl or discover_inputs(results))]
|
| 128 | if not inputs:
|
| 129 | print(f"No result JSONL files found. Pass files explicitly or populate {results}.")
|
| 130 | return 2
|
| 131 |
|
| 132 | checks: list[dict[str, Any]] = []
|
| 133 | checks.append(run_publish_gate(inputs, out_dir))
|
| 134 | if not args.skip_stats:
|
| 135 | checks.append(run_benchmark_stats(inputs, out_dir, args.bootstrap_samples, args.confidence))
|
| 136 | if not args.skip_opportunities:
|
| 137 | checks.append(run_opportunities(results, inputs, out_dir))
|
| 138 |
|
| 139 | manifest = {
|
| 140 | "generated_at": datetime.now(timezone.utc).isoformat(),
|
| 141 | "results_dir": str(results),
|
| 142 | "inputs": [str(path) for path in inputs],
|
| 143 | "out_dir": str(out_dir),
|
| 144 | "checks": checks,
|
| 145 | "ready": all(check["exit_code"] == 0 for check in checks),
|
| 146 | }
|
| 147 | manifest_path = out_dir / "manifest.json"
|
| 148 | manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n")
|
| 149 |
|
| 150 | print(f"Readiness bundle: {out_dir}")
|
| 151 | print(f"Manifest: {manifest_path}")
|
| 152 | for check in checks:
|
| 153 | status = "PASS" if check["exit_code"] == 0 else "FAIL"
|
| 154 | print(f"{status} {check['name']}: {check.get('path')}")
|
| 155 | return 0 if manifest["ready"] else 1
|
| 156 |
|
| 157 |
|
| 158 | if __name__ == "__main__":
|
| 159 | raise SystemExit(main())
|