| """Frozen E03 end-to-end repair experiment over held-out GitLab Runner tasks.""" |
|
|
| from __future__ import annotations |
|
|
| from contextlib import contextmanager |
| from dataclasses import asdict |
| from hashlib import sha256 |
| import json |
| import os |
| from pathlib import Path |
| import re |
| import shlex |
| import subprocess |
| import sys |
| import tarfile |
| import tempfile |
| import time |
| from typing import Any, Iterator, Sequence |
|
|
| from .components import Candidate |
| from .context_packing import ( |
| EVIDENCE_TOKEN_BUDGET, |
| candidates_from_records, |
| load_ranking_records, |
| pack_snippets, |
| ranking_path, |
| ) |
| from .interactive_experiment import exclusive_loaded |
| from .lm_studio import LMStudioClient |
| from .pilot import research_code_revision, retrieval_metrics |
| from .repository import GitSnapshot |
| from .specs import ( |
| HarnessSpec, |
| TaskSpec, |
| load_experiments, |
| load_harnesses, |
| load_models, |
| load_task_split, |
| load_tasks, |
| ) |
| from .syntax_index import parse_go_file |
| from .telemetry import EventWriter, RunIdentity, run_directory |
| from .tokenization import QwenTokenCounter |
|
|
|
|
| REPAIR_SYSTEM = """You are repairing a held-out issue in a large Go repository. |
| Use only the issue and source evidence supplied by the harness. Return only a valid unified |
| diff that can be applied with `git apply`. Modify only evidence paths, do not add tests, do not |
| use Markdown fences, and do not include explanation outside the diff. Make the smallest correct |
| production-code change. If evidence is insufficient, still make the best evidence-grounded patch.""" |
|
|
|
|
| class RepairExperimentError(RuntimeError): |
| """Raised when E03 infrastructure cannot preserve the frozen protocol.""" |
|
|
|
|
| class PatchOutputError(RepairExperimentError): |
| """Raised when a model patch violates the frozen output interface.""" |
|
|
|
|
| def repair_prompt(task: TaskSpec, evidence: str) -> str: |
| return f"ISSUE:\n{task.statement}\n\nSOURCE EVIDENCE:\n{evidence}" |
|
|
|
|
| def extract_unified_diff(response: dict[str, Any]) -> str: |
| """Extract a model diff without repairing or otherwise changing its content.""" |
|
|
| try: |
| content = response["choices"][0]["message"]["content"] |
| except (KeyError, IndexError, TypeError) as exc: |
| raise PatchOutputError("chat completion has no assistant content") from exc |
| if not isinstance(content, str) or not content.strip(): |
| raise PatchOutputError("assistant returned no patch text") |
| stripped = content.strip() |
| fence = re.search(r"```(?:diff|patch)?\s*\n(.*?)```", stripped, re.DOTALL) |
| if fence: |
| stripped = fence.group(1).strip() |
| starts = [value for value in (stripped.find("diff --git "), stripped.find("--- a/")) if value >= 0] |
| if not starts: |
| raise PatchOutputError("assistant did not return a unified diff") |
| patch = stripped[min(starts) :].rstrip() + "\n" |
| if "+++ b/" not in patch or "@@" not in patch: |
| raise PatchOutputError("assistant patch lacks unified-diff file or hunk headers") |
| return patch |
|
|
|
|
| def modified_paths(patch: str) -> tuple[str, ...]: |
| paths = re.findall(r"(?m)^\+\+\+ b/(.+)$", patch) |
| unique = tuple(dict.fromkeys(item.strip() for item in paths)) |
| if not unique: |
| raise PatchOutputError("assistant patch has no modified repository path") |
| for value in unique: |
| path = Path(value) |
| if path.is_absolute() or ".." in path.parts or value == "/dev/null": |
| raise PatchOutputError(f"assistant patch contains unsafe path: {value}") |
| return unique |
|
|
|
|
| def validate_patch_scope(patch: str, allowed_paths: Sequence[str]) -> tuple[str, ...]: |
| paths = modified_paths(patch) |
| unknown = set(paths) - set(allowed_paths) |
| if unknown: |
| raise PatchOutputError( |
| f"assistant modified paths outside the supplied evidence: {sorted(unknown)}" |
| ) |
| return paths |
|
|
|
|
| def _iterative_ranking_path(root: Path, task_id: str) -> Path: |
| matches = sorted( |
| (root / "results" / "staging" / "E02").glob( |
| f"*/H010/{task_id}/refined_ranking.json" |
| ) |
| ) |
| if len(matches) != 1: |
| raise RepairExperimentError( |
| f"expected one confirmatory H010 refined ranking for {task_id}, found {len(matches)}" |
| ) |
| return matches[0] |
|
|
|
|
| def oracle_hunk_ranges(patch: str, wanted_path: str) -> tuple[tuple[int, int], ...]: |
| """Read only old-file hunk locations for an oracle symbol absent at the base commit.""" |
|
|
| current_path: str | None = None |
| ranges: list[tuple[int, int]] = [] |
| for line in patch.splitlines(): |
| if line.startswith("+++ b/"): |
| current_path = line.removeprefix("+++ b/").strip() |
| continue |
| if current_path != wanted_path or not line.startswith("@@"): |
| continue |
| match = re.match(r"@@ -(\d+)(?:,(\d+))? \+\d+(?:,\d+)? @@", line) |
| if match: |
| start = int(match.group(1)) |
| count = int(match.group(2) or "1") |
| ranges.append((start, max(count, 1))) |
| return tuple(ranges) |
|
|
|
|
| def _oracle_function_candidates( |
| root: Path, snapshot: GitSnapshot, task: TaskSpec |
| ) -> tuple[Candidate, ...]: |
| candidates: list[Candidate] = [] |
| by_path: dict[str, set[str]] = {} |
| for identifier in task.gold_symbols: |
| path, separator, name = identifier.partition("::") |
| if not separator: |
| raise RepairExperimentError(f"malformed oracle symbol: {identifier}") |
| by_path.setdefault(path, set()).add(name) |
| for path, names in by_path.items(): |
| source = snapshot.read_file(task.base_commit, path) |
| lines = source.text.splitlines() |
| matched: set[str] = set() |
| for symbol in parse_go_file(path, source.text): |
| if symbol.name not in names: |
| continue |
| matched.add(symbol.name) |
| start = max(symbol.line_start, 1) |
| end = min(symbol.line_end, len(lines)) |
| candidates.append( |
| Candidate( |
| path=path, |
| line_start=start, |
| line_end=end, |
| text="\n".join(lines[start - 1 : end]), |
| source="oracle_function", |
| score=1.0, |
| symbol=symbol.name, |
| ) |
| ) |
| missing = names - matched |
| if missing: |
| patch = (root / "tasks" / task.gold_patch).read_text(encoding="utf-8") |
| ranges = oracle_hunk_ranges(patch, path) |
| if not ranges: |
| raise RepairExperimentError( |
| f"oracle symbols absent at base and no patch hunk found: {sorted(missing)}" |
| ) |
| for start, count in ranges: |
| window_start = max(start - 20, 1) |
| window_end = min(start + count + 20, len(lines)) |
| candidates.append( |
| Candidate( |
| path=path, |
| line_start=window_start, |
| line_end=window_end, |
| text="\n".join(lines[window_start - 1 : window_end]), |
| source="oracle_hunk_location", |
| score=1.0, |
| symbol=", ".join(sorted(missing)), |
| ) |
| ) |
| return tuple(candidates) |
|
|
|
|
| def repair_context( |
| root: Path, |
| task: TaskSpec, |
| harness: HarnessSpec, |
| snapshot: GitSnapshot, |
| tokenizer: QwenTokenCounter, |
| ) -> tuple[str, tuple[str, ...], int, str]: |
| if harness.harness_id == "H019": |
| candidates = _oracle_function_candidates(root, snapshot, task) |
| source = "oracle_function" |
| else: |
| path = ( |
| _iterative_ranking_path(root, task.task_id) |
| if harness.harness_id == "H010" |
| else ranking_path(root, "E01", harness.harness_id, task.task_id) |
| ) |
| records = load_ranking_records(path) |
| candidates = candidates_from_records(snapshot, task.base_commit, records) |
| source = str(path.relative_to(root)) |
| text, allowed, used = pack_snippets(tokenizer, candidates, EVIDENCE_TOKEN_BUDGET) |
| if not allowed: |
| raise RepairExperimentError(f"{harness.harness_id}/{task.task_id} packed no evidence") |
| return text, allowed, used, source |
|
|
|
|
| @contextmanager |
| def isolated_source_tree(repository: Path, commit: str) -> Iterator[Path]: |
| """Materialize a commit without mutating the user's repository checkout.""" |
|
|
| with tempfile.TemporaryDirectory(prefix="agent-harness-e03-") as temporary: |
| base = Path(temporary) |
| archive = base / "source.tar" |
| tree = base / "tree" |
| tree.mkdir() |
| with archive.open("wb") as handle: |
| result = subprocess.run( |
| ["git", "archive", "--format=tar", commit], |
| cwd=repository, |
| stdout=handle, |
| stderr=subprocess.PIPE, |
| check=False, |
| timeout=120, |
| ) |
| if result.returncode != 0: |
| raise RepairExperimentError( |
| "git archive failed: " + result.stderr.decode("utf-8", errors="replace") |
| ) |
| with tarfile.open(archive, "r") as handle: |
| handle.extractall(tree, filter="data") |
| yield tree |
|
|
|
|
| @contextmanager |
| def isolated_git_tree( |
| repository: Path, |
| commit: str, |
| repository_url: str, |
| ) -> Iterator[Path]: |
| """Create an isolated shared clone with exact Git metadata for test suites.""" |
|
|
| with tempfile.TemporaryDirectory(prefix="agent-harness-study2-") as temporary: |
| tree = Path(temporary) / "tree" |
| clone = subprocess.run( |
| [ |
| "git", |
| "clone", |
| "--quiet", |
| "--shared", |
| "--no-checkout", |
| str(repository.resolve()), |
| str(tree), |
| ], |
| text=True, |
| capture_output=True, |
| check=False, |
| timeout=180, |
| ) |
| if clone.returncode != 0: |
| raise RepairExperimentError( |
| "isolated local clone failed: " + (clone.stderr.strip() or clone.stdout.strip()) |
| ) |
| for arguments in ( |
| ["checkout", "--quiet", "--detach", commit], |
| ["remote", "set-url", "origin", repository_url], |
| ): |
| result = subprocess.run( |
| ["git", *arguments], |
| cwd=tree, |
| text=True, |
| capture_output=True, |
| check=False, |
| timeout=180, |
| ) |
| if result.returncode != 0: |
| raise RepairExperimentError( |
| f"isolated git {' '.join(arguments)} failed: " |
| + (result.stderr.strip() or result.stdout.strip()) |
| ) |
| yield tree |
|
|
|
|
| def _apply_patch(tree: Path, patch_path: Path) -> dict[str, Any]: |
| started = time.monotonic() |
| result = subprocess.run( |
| ["git", "apply", "--whitespace=nowarn", str(patch_path)], |
| cwd=tree, |
| text=True, |
| capture_output=True, |
| check=False, |
| timeout=120, |
| ) |
| return { |
| "returncode": result.returncode, |
| "stdout": result.stdout, |
| "stderr": result.stderr, |
| "elapsed_seconds": time.monotonic() - started, |
| } |
|
|
|
|
| def run_test_command(tree: Path, command: str, timeout_seconds: int = 600) -> dict[str, Any]: |
| arguments = shlex.split(command) |
| is_go = arguments[:2] == ["go", "test"] |
| is_python = arguments[:3] == ["python", "-m", "pytest"] |
| if not (is_go or is_python): |
| raise RepairExperimentError( |
| f"only frozen `go test` or `python -m pytest` commands are permitted: {command}" |
| ) |
| if is_python: |
| arguments[0] = sys.executable |
| environment = None |
| if is_go: |
| environment = dict(os.environ) |
| cache_root = Path(tempfile.gettempdir()) / "agent-harness-go-runtime" |
| build_cache = cache_root / "build" |
| module_cache = cache_root / "modules" |
| build_cache.mkdir(parents=True, exist_ok=True) |
| module_cache.mkdir(parents=True, exist_ok=True) |
| environment["GOCACHE"] = str(build_cache) |
| environment["GOMODCACHE"] = str(module_cache) |
| started = time.monotonic() |
| try: |
| result = subprocess.run( |
| arguments, |
| cwd=tree, |
| text=True, |
| capture_output=True, |
| check=False, |
| timeout=timeout_seconds, |
| env=environment, |
| ) |
| return { |
| "command": command, |
| "returncode": result.returncode, |
| "stdout": result.stdout, |
| "stderr": result.stderr, |
| "elapsed_seconds": time.monotonic() - started, |
| "timed_out": False, |
| } |
| except subprocess.TimeoutExpired as exc: |
| return { |
| "command": command, |
| "returncode": None, |
| "stdout": exc.stdout or "", |
| "stderr": exc.stderr or "", |
| "elapsed_seconds": time.monotonic() - started, |
| "timed_out": True, |
| } |
|
|
|
|
| def validate_generated_patch( |
| root: Path, |
| repository: Path, |
| task: TaskSpec, |
| patch: str, |
| preserve_git_metadata: bool = False, |
| ) -> dict[str, Any]: |
| context = ( |
| isolated_git_tree(repository, task.base_commit, task.repository_url) |
| if preserve_git_metadata |
| else isolated_source_tree(repository, task.base_commit) |
| ) |
| with context as tree: |
| test_patch = (root / "tasks" / task.test_patch).resolve() |
| hidden_apply = _apply_patch(tree, test_patch) |
| if hidden_apply["returncode"] != 0: |
| raise RepairExperimentError( |
| f"frozen hidden test patch failed to apply for {task.task_id}: {hidden_apply['stderr']}" |
| ) |
| model_patch = tree.parent / "model.patch" |
| model_patch.write_text(patch, encoding="utf-8") |
| model_apply = _apply_patch(tree, model_patch) |
| tests: list[dict[str, Any]] = [] |
| if model_apply["returncode"] == 0: |
| for command in dict.fromkeys((*task.fail_to_pass_tests, *task.pass_to_pass_tests)): |
| tests.append(run_test_command(tree, command)) |
| by_command = {item["command"]: item for item in tests} |
| fail_to_pass = all( |
| by_command.get(command, {}).get("returncode") == 0 |
| for command in task.fail_to_pass_tests |
| ) |
| pass_to_pass = all( |
| by_command.get(command, {}).get("returncode") == 0 |
| for command in task.pass_to_pass_tests |
| ) |
| resolved = model_apply["returncode"] == 0 and fail_to_pass and pass_to_pass |
| return { |
| "hidden_test_patch_apply": hidden_apply, |
| "model_patch_apply": model_apply, |
| "tests": tests, |
| "fail_to_pass": fail_to_pass, |
| "pass_to_pass": pass_to_pass, |
| "resolved_at_1": resolved, |
| "failure_stage": ( |
| "resolved" |
| if resolved |
| else "patch_apply" |
| if model_apply["returncode"] != 0 |
| else "tests" |
| ), |
| } |
|
|
|
|
| def _identity( |
| experiment: Any, |
| task: TaskSpec, |
| harness: HarnessSpec, |
| model: Any, |
| revision: str, |
| ) -> RunIdentity: |
| return RunIdentity( |
| experiment_id=experiment.experiment_id, |
| task_id=task.task_id, |
| harness_id=harness.harness_id, |
| harness_hash=harness.config_hash, |
| model_id=model.model_id, |
| model_key=model.expected_inference_key, |
| model_config_hash=model.config_hash, |
| context_budget=experiment.context_budgets[0], |
| seed=experiment.seeds[0], |
| repetition=0, |
| repository_sha=task.base_commit, |
| code_revision=revision, |
| ) |
|
|
|
|
| def run_repair_experiment( |
| root: Path, |
| repository: Path, |
| task_filter: set[str] | None = None, |
| harness_filter: set[str] | None = None, |
| ) -> dict[str, Any]: |
| revision = research_code_revision(root) |
| experiment = load_experiments(root)["E03"] |
| model = load_models(root)[experiment.model_ids[0]] |
| harness_catalog = load_harnesses(root) |
| task_catalog = load_tasks(root) |
| split = load_task_split(root / "tasks" / "splits" / f"{experiment.task_split}.txt") |
| tasks = [ |
| task_catalog[item] |
| for item in split |
| if task_filter is None or item in task_filter |
| ] |
| harnesses = [ |
| harness_catalog[item] |
| for item in experiment.harness_ids |
| if harness_filter is None or item in harness_filter |
| ] |
| if not tasks or not harnesses: |
| raise RepairExperimentError("filters selected no E03 cells") |
| if any(task.validation_status != "end_to_end_ready" for task in tasks): |
| raise RepairExperimentError("E03 split contains a task that is not end-to-end ready") |
|
|
| client = LMStudioClient(model, timeout_seconds=experiment.timeout_seconds) |
| discovery, resolved = client.resolve() |
| loaded = exclusive_loaded(discovery.native_models) |
| if loaded != (model.expected_inference_key,): |
| raise RepairExperimentError(f"E03 requires exclusive Qwen residency: {loaded}") |
| snapshot = GitSnapshot(repository) |
| tokenizer = QwenTokenCounter() |
| rows: list[dict[str, Any]] = [] |
| for task in tasks: |
| snapshot.verify_commit(task.base_commit) |
| for harness in harnesses: |
| identity = _identity(experiment, task, harness, model, revision) |
| directory = run_directory(root / "results", identity) |
| if directory.exists(): |
| final_path = directory / "final_metrics.json" |
| if not final_path.exists(): |
| raise RepairExperimentError(f"incomplete existing run directory: {directory}") |
| rows.append(json.loads(final_path.read_text(encoding="utf-8"))) |
| continue |
| evidence, allowed_paths, context_tokens, evidence_source = repair_context( |
| root, task, harness, snapshot, tokenizer |
| ) |
| prompt = repair_prompt(task, evidence) |
| started = time.monotonic() |
| response = client.chat_completions( |
| resolved.inference_key, |
| [ |
| {"role": "system", "content": REPAIR_SYSTEM}, |
| {"role": "user", "content": prompt}, |
| ], |
| max_tokens=model.max_tokens, |
| ) |
| model_elapsed = time.monotonic() - started |
| protocol_violation: str | None = None |
| patch = "" |
| paths: tuple[str, ...] = () |
| validation: dict[str, Any] |
| try: |
| patch = extract_unified_diff(response) |
| paths = validate_patch_scope(patch, allowed_paths) |
| validation = validate_generated_patch(root, repository, task, patch) |
| except PatchOutputError as exc: |
| protocol_violation = str(exc) |
| validation = { |
| "hidden_test_patch_apply": None, |
| "model_patch_apply": None, |
| "tests": [], |
| "fail_to_pass": False, |
| "pass_to_pass": False, |
| "resolved_at_1": False, |
| "failure_stage": "protocol_violation", |
| } |
| localization = retrieval_metrics(paths, task.gold_files) |
| final = { |
| "run_id": identity.run_id, |
| "experiment_id": "E03", |
| "task_id": task.task_id, |
| "harness_id": harness.harness_id, |
| "resolved_at_1": validation["resolved_at_1"], |
| "failure_stage": validation["failure_stage"], |
| "patch_applied": bool( |
| validation["model_patch_apply"] |
| and validation["model_patch_apply"].get("returncode") == 0 |
| ), |
| "fail_to_pass": validation["fail_to_pass"], |
| "pass_to_pass": validation["pass_to_pass"], |
| "modified_files": paths, |
| "localization_metrics": localization, |
| "protocol_violation": protocol_violation, |
| "evidence_source": evidence_source, |
| "context_tokens": context_tokens, |
| "prompt_sha256": sha256(prompt.encode()).hexdigest(), |
| "patch_sha256": sha256(patch.encode()).hexdigest() if patch else None, |
| "elapsed_seconds": model_elapsed + sum( |
| item.get("elapsed_seconds", 0.0) for item in validation["tests"] |
| ), |
| "model_elapsed_seconds": model_elapsed, |
| "usage": response.get("usage", {}), |
| "test_results": validation["tests"], |
| } |
| with EventWriter( |
| root / "results", identity, asdict(harness), resolved.to_dict() |
| ) as writer: |
| writer.emit("run_started", {"confirmatory": True, "evidence_source": evidence_source}) |
| writer.emit("model_call", {"elapsed_seconds": model_elapsed, "usage": response.get("usage", {})}) |
| writer.write_artifact("prompt.txt", prompt) |
| writer.write_artifact("model_response.json", json.dumps(response, indent=2) + "\n") |
| writer.write_artifact("model.patch", patch) |
| writer.write_artifact("validation.json", json.dumps(validation, indent=2) + "\n") |
| writer.write_artifact("final_metrics.json", json.dumps(final, indent=2) + "\n") |
| for test in validation["tests"]: |
| writer.emit("test_run", test) |
| writer.emit( |
| "run_finished", |
| { |
| "status": "completed_with_protocol_violation" if protocol_violation else "completed", |
| "resolved_at_1": validation["resolved_at_1"], |
| "failure_stage": validation["failure_stage"], |
| }, |
| ) |
| rows.append(final) |
| return { |
| "experiment_id": "E03", |
| "code_revision": revision, |
| "run_count": len(rows), |
| "resolved_count": sum(bool(item["resolved_at_1"]) for item in rows), |
| "rows": rows, |
| } |
|
|