| """Build a deterministic compact publication package without raw trajectories.""" |
|
|
| from __future__ import annotations |
|
|
| import gzip |
| import hashlib |
| import io |
| import json |
| import subprocess |
| import tarfile |
| from pathlib import Path |
|
|
|
|
| ROOT = Path(__file__).resolve().parents[1] |
| PACKAGE_NAME = "agent-harness-publication-package" |
| ROOT_FILES = ( |
| ".zenodo.json", |
| "CITATION.cff", |
| "LICENSE", |
| "LICENSE-DATA", |
| ".gitignore", |
| "README.md", |
| "README_ZENODO.md", |
| "REPRODUCING.md", |
| "THIRD_PARTY_NOTICES.md", |
| "pyproject.toml", |
| "requirements-analysis.txt", |
| "requirements.lock", |
| ) |
| SOURCE_DIRS = ( |
| "configs", |
| "docs", |
| "paper", |
| "scripts", |
| "src", |
| "tasks", |
| "tests", |
| "output/pdf", |
| "results/derived/confirmatory_analysis_174ce71bcbce", |
| "results/derived/e07", |
| "results/derived/study2", |
| "results/derived/study3", |
| "results/derived/study4", |
| "results/derived/study4_ancillary", |
| "results/derived/study5", |
| ) |
| EXTRA_FILES = ( |
| "results/reports/study2_preflight.json", |
| "results/reports/study3_preflight.json", |
| "results/reports/study4_preflight.json", |
| "results/reports/study4_ancillary_preflight.json", |
| "results/reports/study5_preflight.json", |
| ) |
|
|
|
|
| def sha256(data: bytes) -> str: |
| return hashlib.sha256(data).hexdigest() |
|
|
|
|
| def collect_files(root: Path) -> list[Path]: |
| candidates = [root / path for path in ROOT_FILES + EXTRA_FILES] |
| for directory in SOURCE_DIRS: |
| candidates.extend((root / directory).rglob("*")) |
| files = sorted({path for path in candidates if path.is_file() and |
| "__pycache__" not in path.parts and path.suffix != ".pyc"}) |
| missing = [str(root / path) for path in ROOT_FILES + EXTRA_FILES |
| if not (root / path).is_file()] |
| if missing: |
| raise FileNotFoundError(f"required publication files are missing: {missing}") |
| return files |
|
|
|
|
| def tar_info(name: str, size: int) -> tarfile.TarInfo: |
| info = tarfile.TarInfo(name=name) |
| info.size = size |
| info.mode = 0o644 |
| info.mtime = 0 |
| info.uid = info.gid = 0 |
| info.uname = info.gname = "" |
| return info |
|
|
|
|
| def build(root: Path = ROOT) -> dict[str, object]: |
| files = collect_files(root) |
| revision = subprocess.run( |
| ["git", "rev-parse", "HEAD"], cwd=root, check=True, |
| capture_output=True, text=True, |
| ).stdout.strip() |
| entries = [] |
| payloads: list[tuple[str, bytes]] = [] |
| for path in files: |
| relative = path.relative_to(root).as_posix() |
| data = path.read_bytes() |
| entries.append({"path": relative, "bytes": len(data), "sha256": sha256(data)}) |
| payloads.append((relative, data)) |
|
|
| package_metadata = { |
| "schema_version": 1, |
| "title": "Dissecting Repository-Scale Code-Agent Harnesses", |
| "author": "Mandeep Sidhu", |
| "version": "1.0.0-preprint", |
| "doi": "10.5281/zenodo.21781711", |
| "licenses": {"software": "MIT", "paper_and_derived_data": "CC-BY-4.0"}, |
| "source_revision": revision, |
| "reported_cells": 5453, |
| "reported_generative_tokens": 368125497, |
| "study2_cells": 912, |
| "study3_cells": 540, |
| "study4_cells": 210, |
| "study5_cells": 2826, |
| "file_count": len(entries), |
| "contents": "compact source, derived evidence, paper, and preflight", |
| "excluded": ["raw trajectories", "repository checkouts", "index caches", "model weights"], |
| } |
| manifest = { |
| "package": package_metadata, |
| "files": entries, |
| } |
| metadata_bytes = json.dumps(package_metadata, indent=2, sort_keys=True).encode() + b"\n" |
| manifest_bytes = json.dumps(manifest, indent=2, sort_keys=True).encode() + b"\n" |
|
|
| output_dir = root / "output" / "releases" |
| output_dir.mkdir(parents=True, exist_ok=True) |
| archive = output_dir / f"{PACKAGE_NAME}.tar.gz" |
| with archive.open("wb") as raw: |
| with gzip.GzipFile(filename="", mode="wb", fileobj=raw, mtime=0) as compressed: |
| with tarfile.open(fileobj=compressed, mode="w", format=tarfile.PAX_FORMAT) as tar: |
| prefix = PACKAGE_NAME |
| for name, data in payloads: |
| info = tar_info(f"{prefix}/{name}", len(data)) |
| tar.addfile(info, io.BytesIO(data)) |
| for name, data in ( |
| ("PUBLICATION_PACKAGE.json", metadata_bytes), |
| ("MANIFEST.sha256.json", manifest_bytes), |
| ): |
| info = tar_info(f"{prefix}/{name}", len(data)) |
| tar.addfile(info, io.BytesIO(data)) |
|
|
| archive_digest = sha256(archive.read_bytes()) |
| checksum = output_dir / f"{archive.name}.sha256" |
| checksum.write_text(f"{archive_digest} {archive.name}\n", encoding="utf-8") |
| return { |
| **package_metadata, |
| "archive": str(archive), |
| "archive_bytes": archive.stat().st_size, |
| "archive_sha256": archive_digest, |
| "checksum": str(checksum), |
| } |
|
|
|
|
| def main() -> None: |
| print(json.dumps(build(), indent=2, sort_keys=True)) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|