| """Validate held-out task patches against clean archived Git snapshots.""" |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| from io import BytesIO |
| import json |
| from pathlib import Path |
| import shlex |
| import subprocess |
| import tarfile |
| import tempfile |
| import time |
| from typing import Any, Iterable |
|
|
| from agent_harness.specs import TaskSpec, load_tasks |
|
|
|
|
| def run( |
| arguments: list[str], |
| cwd: Path, |
| timeout: int = 900, |
| ) -> dict[str, Any]: |
| started = time.monotonic() |
| result = subprocess.run( |
| arguments, |
| cwd=cwd, |
| check=False, |
| capture_output=True, |
| text=True, |
| timeout=timeout, |
| ) |
| combined = result.stdout + result.stderr |
| return { |
| "command": shlex.join(arguments), |
| "exit_code": result.returncode, |
| "elapsed_seconds": time.monotonic() - started, |
| "output_tail": combined[-12000:], |
| } |
|
|
|
|
| def extract_snapshot(repository: Path, commit: str, destination: Path) -> None: |
| archive = subprocess.run( |
| ["git", "archive", "--format=tar", commit], |
| cwd=repository, |
| check=True, |
| capture_output=True, |
| timeout=120, |
| ).stdout |
| with tarfile.open(fileobj=BytesIO(archive), mode="r:") as handle: |
| for member in handle.getmembers(): |
| path = Path(member.name) |
| if path.is_absolute() or ".." in path.parts: |
| raise RuntimeError(f"Unsafe git archive member: {member.name}") |
| handle.extractall(destination) |
|
|
|
|
| def apply_patch(checkout: Path, patch: Path) -> dict[str, Any]: |
| return run( |
| ["git", "apply", "--whitespace=nowarn", str(patch.resolve())], |
| checkout, |
| timeout=120, |
| ) |
|
|
|
|
| def run_commands(checkout: Path, commands: Iterable[str]) -> list[dict[str, Any]]: |
| results: list[dict[str, Any]] = [] |
| for command in commands: |
| arguments = shlex.split(command) |
| if not arguments or arguments[0] != "go" or arguments[1:2] != ["test"]: |
| raise RuntimeError(f"Only explicit go test validation is allowed: {command}") |
| results.append(run(arguments, checkout)) |
| return results |
|
|
|
|
| def all_pass(results: Iterable[dict[str, Any]]) -> bool: |
| values = list(results) |
| return bool(values) and all(item["exit_code"] == 0 for item in values) |
|
|
|
|
| def validate_task(root: Path, repository: Path, task: TaskSpec) -> dict[str, Any]: |
| if not task.gold_patch or not task.test_patch: |
| raise RuntimeError(f"{task.task_id} has no source/test patch pair") |
| source_patch = root / "tasks" / task.gold_patch |
| test_patch = root / "tasks" / task.test_patch |
| started = time.monotonic() |
| with tempfile.TemporaryDirectory(prefix=f"{task.task_id.lower()}-") as raw_checkout: |
| checkout = Path(raw_checkout) |
| extract_snapshot(repository, task.base_commit, checkout) |
|
|
| original_tests = run_commands(checkout, task.pass_to_pass_tests) |
| test_apply = apply_patch(checkout, test_patch) |
| test_only_results = ( |
| run_commands(checkout, task.fail_to_pass_tests) |
| if test_apply["exit_code"] == 0 |
| else [] |
| ) |
| source_apply = apply_patch(checkout, source_patch) |
| gold_results = ( |
| run_commands(checkout, task.pass_to_pass_tests) |
| if source_apply["exit_code"] == 0 |
| else [] |
| ) |
|
|
| original_pass = all_pass(original_tests) |
| test_exposes_bug = bool(test_only_results) and any( |
| item["exit_code"] != 0 for item in test_only_results |
| ) |
| gold_pass = all_pass(gold_results) |
| valid = ( |
| original_pass |
| and test_apply["exit_code"] == 0 |
| and test_exposes_bug |
| and source_apply["exit_code"] == 0 |
| and gold_pass |
| ) |
| return { |
| "schema_version": 1, |
| "task_id": task.task_id, |
| "base_commit": task.base_commit, |
| "gold_commit": task.gold_commit, |
| "valid_end_to_end": valid, |
| "checks": { |
| "original_suite_passes": original_pass, |
| "test_patch_applies": test_apply["exit_code"] == 0, |
| "test_patch_exposes_bug": test_exposes_bug, |
| "source_patch_applies": source_apply["exit_code"] == 0, |
| "gold_suite_passes": gold_pass, |
| }, |
| "original_tests": original_tests, |
| "test_patch_apply": test_apply, |
| "test_only_results": test_only_results, |
| "source_patch_apply": source_apply, |
| "gold_results": gold_results, |
| "elapsed_seconds": time.monotonic() - started, |
| } |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1]) |
| parser.add_argument("--repository", type=Path, default=Path("data/repos/gitlab-runner")) |
| parser.add_argument("--task", action="append") |
| args = parser.parse_args() |
| root = args.root.resolve() |
| repository = args.repository.resolve() |
| selected = set(args.task or []) |
| tasks = [ |
| task |
| for task_id, task in load_tasks(root).items() |
| if task_id.startswith("TASK_CR_") and (not selected or task_id in selected) |
| ] |
| if not tasks: |
| raise SystemExit("No confirmatory tasks selected") |
| output_dir = root / "tasks" / "validation" |
| output_dir.mkdir(parents=True, exist_ok=True) |
| go_version = subprocess.run( |
| ["go", "version"], check=True, capture_output=True, text=True, timeout=30 |
| ).stdout.strip() |
| summary: list[dict[str, Any]] = [] |
| for task in tasks: |
| print(f"VALIDATING {task.task_id}", flush=True) |
| result = validate_task(root, repository, task) |
| result["go_version"] = go_version |
| (output_dir / f"{task.task_id}.json").write_text( |
| json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8" |
| ) |
| summary.append( |
| { |
| "task_id": task.task_id, |
| "valid_end_to_end": result["valid_end_to_end"], |
| "elapsed_seconds": result["elapsed_seconds"], |
| "checks": result["checks"], |
| } |
| ) |
| print(json.dumps(summary[-1], sort_keys=True), flush=True) |
| (output_dir / "summary.json").write_text( |
| json.dumps( |
| { |
| "schema_version": 1, |
| "go_version": go_version, |
| "tasks": summary, |
| "valid_task_ids": [item["task_id"] for item in summary if item["valid_end_to_end"]], |
| }, |
| indent=2, |
| sort_keys=True, |
| ) |
| + "\n", |
| encoding="utf-8", |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|