mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-28 06:22:22 +00:00
* feat(eval): measure PR cost before merge Reuse authenticated historical MCP measurements for one pinned PR preview. Keep the protected main evaluator and publish separate evidence that cannot authorize a release. * fix(eval): gate PR cost runs on a label Require a repository writer label event and retain the opt-in label and exact PR head before dispatch and paid sessions. Keep the request handler on trusted base code and execute evaluation on main. * ci: document trusted cost label trigger * fix(eval): restrict previews to maintainer labels Remove manual PR preview inputs and authorize Maintain/Admin roles before calling the protected reusable evaluator. Compare workflow measurement settings with historical evidence instead of exempting the entire workflow. --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
601 lines
22 KiB
Python
601 lines
22 KiB
Python
"""PR cost measurements retain the historical task pins and quality floor."""
|
|
|
|
import json
|
|
from copy import deepcopy
|
|
from datetime import UTC, datetime
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from workflow_bench import pr_evaluation
|
|
from workflow_bench.release_report import build_report, validate_report
|
|
|
|
NOW = datetime.now(UTC)
|
|
OLD = "a" * 40
|
|
NEW = "b" * 40
|
|
HARNESS = "c" * 40
|
|
REPO = "owner/repo"
|
|
|
|
|
|
@pytest.fixture
|
|
def evidence():
|
|
metadata = {
|
|
"runtime_sha": OLD,
|
|
"harness_sha": OLD,
|
|
"task_set_digest": "d" * 64,
|
|
"model": "gpt-5.6-sol",
|
|
"effort": "xhigh",
|
|
"runs": 3,
|
|
"tasks": {name: {"sha": "e" * 40, "oracle_digest": "f" * 64} for name in ("one", "two")},
|
|
}
|
|
rows = [
|
|
{
|
|
"task": task,
|
|
"run": run,
|
|
"arm": arm,
|
|
"model": metadata["model"],
|
|
"effort": "xhigh",
|
|
"task_base_sha": "e" * 40,
|
|
"oracle_digest": "f" * 64,
|
|
"sandbox_backend": "bwrap",
|
|
"sandbox_dependency_content_digest": "9" * 64,
|
|
"ok": True,
|
|
"resolved": True,
|
|
"authored_tests_passed": True,
|
|
"oracle_passed": True,
|
|
"error_kind": None,
|
|
"transcript_missing": False,
|
|
"cost_usd": 1.0,
|
|
"duration_s": 60.0,
|
|
}
|
|
for task in metadata["tasks"]
|
|
for run in range(3)
|
|
for arm in ("baseline_nomcp", "baseline")
|
|
]
|
|
previous = build_report(rows, metadata, now=NOW)
|
|
candidate = [
|
|
{**row, "cost_usd": 0.8, "internal_path": "/private/transcript"} for row in rows if row["arm"] == "baseline"
|
|
]
|
|
return previous, candidate, {**metadata, "runtime_sha": NEW, "harness_sha": HARNESS}
|
|
|
|
|
|
def compare(evidence):
|
|
previous, rows, metadata = evidence
|
|
return pr_evaluation.compare_candidate(
|
|
rows, metadata, previous, candidate_sha=NEW, pr=3621, baseline_run=39039452570, now=NOW
|
|
)
|
|
|
|
|
|
def test_comparison_measures_only_new_mcp_cells_and_preserves_historical_cost(evidence):
|
|
before = deepcopy(evidence)
|
|
report = compare(evidence)
|
|
assert report["complete"] and report["quality_preserved"] and report["improved"]
|
|
assert report["previous"]["total_cost_usd"] == 6
|
|
assert report["candidate"]["total_cost_usd"] == pytest.approx(4.8)
|
|
assert report["cost_reduction_pct"] == pytest.approx(20)
|
|
assert report["candidate"]["solved"] == report["previous"]["solved"] == 6
|
|
assert len(report["per_run"]) == 6
|
|
assert all(row["arm"] == "baseline" and "internal_path" not in row for row in report["per_run"])
|
|
assert evidence == before
|
|
assert "not release approval" in pr_evaluation.render_markdown(report)
|
|
with pytest.raises(ValueError, match="unsupported"):
|
|
validate_report(report, runtime_sha=NEW, task_set_digest=evidence[0]["task_set_digest"], now=NOW)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"change",
|
|
[
|
|
lambda rows: rows.pop(),
|
|
lambda rows: rows.append(dict(rows[0])),
|
|
lambda rows: rows[0].update(cost_usd=None),
|
|
lambda rows: rows[0].update(cost_usd=float("nan")),
|
|
lambda rows: rows[0].update(cost_usd=10**1000),
|
|
lambda rows: rows[0].update(duration_s=-1),
|
|
lambda rows: rows[0].update(model="other-model"),
|
|
lambda rows: rows[0].update(task_base_sha="0" * 40),
|
|
lambda rows: rows[0].update(oracle_digest="0" * 64),
|
|
lambda rows: rows[0].update(sandbox_dependency_content_digest="0" * 64),
|
|
lambda rows: rows[0].update(sandbox_backend="host-unsafe"),
|
|
lambda rows: rows[0].update(error_kind="session-error", ok=False),
|
|
lambda rows: rows[0].update(transcript_missing=True),
|
|
lambda rows: rows[0].update(arm="baseline_nomcp"),
|
|
lambda rows: rows[0].update(resolved="true"),
|
|
lambda rows: rows[0].update(oracle_passed=False),
|
|
lambda rows: rows.append(None),
|
|
],
|
|
)
|
|
def test_incomplete_or_mismatched_cells_cannot_claim_savings(evidence, change):
|
|
change(evidence[1])
|
|
report = compare(evidence)
|
|
assert not report["complete"] and not report["improved"]
|
|
assert report["problems"]
|
|
assert report["cost_reduction_pct"] is None
|
|
json.dumps(report, allow_nan=False)
|
|
|
|
|
|
def test_lower_cost_with_a_per_task_solve_regression_is_not_an_improvement(evidence):
|
|
evidence[1][0].update(resolved=False, oracle_passed=False, error_kind="oracle-failed")
|
|
report = compare(evidence)
|
|
assert report["complete"] and not report["quality_preserved"] and not report["improved"]
|
|
assert report["tasks"]["one"]["solve_delta"] == -1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"field,value",
|
|
[
|
|
("runtime_sha", OLD),
|
|
("model", "other"),
|
|
("effort", "high"),
|
|
("runs", 1),
|
|
("task_set_digest", "0" * 64),
|
|
("tasks", {}),
|
|
],
|
|
)
|
|
def test_candidate_metadata_must_match_the_requested_revision_and_previous_protocol(evidence, field, value):
|
|
evidence[2][field] = value
|
|
assert not compare(evidence)["complete"]
|
|
|
|
|
|
def test_cost_regression_remains_a_valid_measurement(evidence):
|
|
for row in evidence[1]:
|
|
row["cost_usd"] = 1.1
|
|
report = compare(evidence)
|
|
assert report["complete"] and report["quality_preserved"] and not report["improved"]
|
|
assert report["cost_reduction_pct"] == pytest.approx(-10)
|
|
|
|
|
|
def pr_payload():
|
|
return {
|
|
"state": "open",
|
|
"head": {"sha": NEW},
|
|
"base": {"ref": "main", "repo": {"full_name": REPO}},
|
|
"labels": [{"name": pr_evaluation.COST_LABEL}],
|
|
}
|
|
|
|
|
|
def test_pr_resolution_is_bound_to_the_explicit_reviewed_sha(monkeypatch):
|
|
monkeypatch.setattr(pr_evaluation, "_gh_json", lambda endpoint: pr_payload())
|
|
assert pr_evaluation.resolve_pr(REPO, 3621, NEW) == NEW
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mutation",
|
|
[
|
|
lambda pr: pr.update(state="closed"),
|
|
lambda pr: pr["head"].update(sha=OLD),
|
|
lambda pr: pr["base"].update(ref="feature"),
|
|
lambda pr: pr["base"]["repo"].update(full_name="other/repo"),
|
|
lambda pr: pr.update(labels=[]),
|
|
lambda pr: pr.pop("labels"),
|
|
],
|
|
)
|
|
def test_moved_or_wrong_target_pr_is_rejected_before_paid_work(monkeypatch, mutation):
|
|
payload = pr_payload()
|
|
mutation(payload)
|
|
monkeypatch.setattr(pr_evaluation, "_gh_json", lambda endpoint: payload)
|
|
with pytest.raises(ValueError):
|
|
pr_evaluation.resolve_pr(REPO, 3621, NEW)
|
|
|
|
|
|
@pytest.fixture
|
|
def label_request(monkeypatch):
|
|
event = {
|
|
"repository": {"full_name": REPO},
|
|
"action": "labeled",
|
|
"label": {"name": pr_evaluation.COST_LABEL},
|
|
"sender": {"login": "maintainer"},
|
|
"number": 3621,
|
|
"pull_request": pr_payload(),
|
|
}
|
|
run = {
|
|
"id": 90,
|
|
"conclusion": "success",
|
|
"head_branch": "main",
|
|
"event": "workflow_dispatch",
|
|
"head_repository": {"full_name": REPO},
|
|
"head_sha": OLD,
|
|
}
|
|
payloads = {
|
|
f"repos/{REPO}/collaborators/maintainer/permission": {"permission": "write", "role_name": "maintain"},
|
|
f"repos/{REPO}/pulls/3621": pr_payload(),
|
|
f"repos/{REPO}/actions/workflows/release-evaluation.yml/runs?branch=main&status=success&per_page=100": {
|
|
"workflow_runs": [run],
|
|
},
|
|
f"repos/{REPO}/actions/runs/90/artifacts?per_page=100": {
|
|
"total_count": 1,
|
|
"artifacts": [{"name": f"release-agent-evaluation-{OLD}", "expired": False}],
|
|
},
|
|
}
|
|
calls = []
|
|
monkeypatch.setattr(pr_evaluation, "_gh_json", payloads.__getitem__)
|
|
monkeypatch.setattr(pr_evaluation, "_gh", lambda args: calls.append(args))
|
|
return event, payloads, calls
|
|
|
|
|
|
def test_label_dispatch_pins_head_main_baseline_and_model(label_request):
|
|
event, _, calls = label_request
|
|
assert pr_evaluation.dispatch_labeled_pr(REPO, event) == 90
|
|
assert not calls # Requests emit outputs for a reusable job, never manual dispatch.
|
|
|
|
|
|
@pytest.mark.parametrize("permission", ["write", "read", "triage", "none", "custom-role", ""])
|
|
def test_label_requires_repository_write_permission(label_request, permission):
|
|
event, payloads, calls = label_request
|
|
payloads[f"repos/{REPO}/collaborators/maintainer/permission"]["role_name"] = permission
|
|
with pytest.raises(ValueError, match="repository maintainers or administrators"):
|
|
pr_evaluation.dispatch_labeled_pr(REPO, event)
|
|
assert not calls
|
|
|
|
|
|
@pytest.mark.parametrize("role,permission", [("maintain", "write"), ("admin", "admin")])
|
|
def test_maintain_and_admin_roles_may_request_comparison(label_request, role, permission):
|
|
event, payloads, calls = label_request
|
|
payloads[f"repos/{REPO}/collaborators/maintainer/permission"].update(role_name=role, permission=permission)
|
|
assert pr_evaluation.dispatch_labeled_pr(REPO, event) == 90
|
|
assert not calls
|
|
|
|
|
|
def test_missing_role_does_not_grant_maintainer_authority(label_request):
|
|
event, payloads, calls = label_request
|
|
payloads[f"repos/{REPO}/collaborators/maintainer/permission"].pop("role_name")
|
|
with pytest.raises(ValueError, match="maintainers"):
|
|
pr_evaluation.dispatch_labeled_pr(REPO, event)
|
|
assert not calls
|
|
|
|
|
|
def test_label_cli_emits_validated_reusable_workflow_outputs(label_request, monkeypatch, tmp_path, capsys):
|
|
event, _, calls = label_request
|
|
source = tmp_path / "event.json"
|
|
source.write_text(json.dumps(event))
|
|
monkeypatch.setattr("sys.argv", ["pr_evaluation", "dispatch-label", "--repo", REPO, "--event", str(source)])
|
|
pr_evaluation.main()
|
|
assert capsys.readouterr().out == f"pr=3621\nsha={NEW}\ncomparison_run_id=90\n"
|
|
assert not calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mutation",
|
|
[
|
|
lambda event: event.update(action="synchronize"),
|
|
lambda event: event["label"].update(name="run-ci"),
|
|
lambda event: event["repository"].update(full_name="other/repo"),
|
|
lambda event: event["sender"].update(login="name/permission"),
|
|
],
|
|
)
|
|
def test_unrelated_events_never_dispatch(label_request, mutation):
|
|
event, _, calls = label_request
|
|
mutation(event)
|
|
with pytest.raises(ValueError):
|
|
pr_evaluation.dispatch_labeled_pr(REPO, event)
|
|
assert not calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mutation",
|
|
[
|
|
lambda pr: pr.update(labels=[]),
|
|
lambda pr: pr["head"].update(sha=OLD),
|
|
],
|
|
)
|
|
def test_label_or_head_changed_during_discovery_never_dispatches(label_request, monkeypatch, mutation):
|
|
event, payloads, calls = label_request
|
|
reads = 0
|
|
|
|
def api(endpoint):
|
|
nonlocal reads
|
|
if endpoint == f"repos/{REPO}/pulls/3621":
|
|
reads += 1
|
|
if reads == 2:
|
|
mutation(payloads[endpoint])
|
|
return payloads[endpoint]
|
|
|
|
monkeypatch.setattr(pr_evaluation, "_gh_json", api)
|
|
with pytest.raises(ValueError):
|
|
pr_evaluation.dispatch_labeled_pr(REPO, event)
|
|
assert reads == 2 and not calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"artifact",
|
|
[
|
|
{"name": f"pr-cost-comparison-{NEW}", "expired": False},
|
|
{"name": f"release-agent-evaluation-{OLD}", "expired": True},
|
|
None,
|
|
],
|
|
)
|
|
def test_label_skips_preview_expired_and_probe_runs(label_request, artifact):
|
|
event, payloads, calls = label_request
|
|
runs = next(value["workflow_runs"] for value in payloads.values() if "workflow_runs" in value)
|
|
runs.insert(0, {**runs[0], "id": 91})
|
|
payloads[f"repos/{REPO}/actions/runs/91/artifacts?per_page=100"] = {
|
|
"total_count": int(artifact is not None),
|
|
"artifacts": [] if artifact is None else [artifact],
|
|
}
|
|
assert pr_evaluation.dispatch_labeled_pr(REPO, event) == 90
|
|
assert not calls
|
|
|
|
|
|
def test_label_without_a_full_baseline_does_not_dispatch(label_request):
|
|
event, payloads, calls = label_request
|
|
payloads[f"repos/{REPO}/actions/runs/90/artifacts?per_page=100"]["artifacts"] = []
|
|
with pytest.raises(ValueError, match="no full successful"):
|
|
pr_evaluation.dispatch_labeled_pr(REPO, event)
|
|
assert not calls
|
|
|
|
|
|
def test_previous_measurement_accepts_only_preview_orchestration_changes(monkeypatch):
|
|
monkeypatch.setattr(
|
|
pr_evaluation,
|
|
"_gh_json",
|
|
lambda endpoint: {"status": "ahead", "files": [{"filename": "eval/workflow_bench/pr_evaluation.py"}]},
|
|
)
|
|
pr_evaluation.require_comparable_harness(REPO, OLD, HARNESS)
|
|
|
|
|
|
@pytest.fixture
|
|
def workflow_protocol_pair():
|
|
old = {
|
|
"jobs": {
|
|
"evaluate": {
|
|
"runs-on": "self-hosted",
|
|
"environment": "gitnexus-evolution",
|
|
"timeout-minutes": 1260,
|
|
"env": {"MODEL": "gpt-5.6-sol", "EFFORT": "xhigh"},
|
|
"steps": [
|
|
{"uses": "setup-node@abc", "with": {"node-version": "22"}},
|
|
{"name": "Prepare", "run": "uv run prepare --runs 3\n"},
|
|
{
|
|
"name": "Run",
|
|
"timeout-minutes": 1140,
|
|
"run": (
|
|
"set -euo pipefail\nfor runtime in stable candidate; do\n"
|
|
" uv run --locked --extra dev python -m workflow_bench.runner "
|
|
"--arms baseline_nomcp baseline --runs 3 --include-expensive "
|
|
"--workers 3 --timeout 3600\ndone\n"
|
|
),
|
|
},
|
|
],
|
|
}
|
|
},
|
|
}
|
|
new = deepcopy(old)
|
|
job = new["jobs"]["evaluate"]
|
|
job["env"].update(INPUT_PR="3621", INPUT_PR_SHA=NEW, COMPARISON_RUN_ID="42")
|
|
job["steps"][-1]["run"] = (
|
|
"set -euo pipefail\narms=(baseline_nomcp baseline)\n"
|
|
'if [[ -n "$INPUT_PR" ]]; then arms=(baseline); fi\n'
|
|
"for runtime in stable candidate; do\n"
|
|
' if [[ -n "$INPUT_PR" && "$runtime" == stable ]]; then continue; fi\n'
|
|
" uv run --locked --extra dev python -m workflow_bench.runner "
|
|
'--arms "${arms[@]}" --runs 3 --include-expensive '
|
|
"--workers 3 --timeout 3600\ndone\n"
|
|
)
|
|
return old, new
|
|
|
|
|
|
def test_changed_workflow_requires_matching_measurement_protocol(monkeypatch, workflow_protocol_pair):
|
|
old, new = workflow_protocol_pair
|
|
monkeypatch.setattr(
|
|
pr_evaluation,
|
|
"_gh_json",
|
|
lambda endpoint: {
|
|
"status": "ahead",
|
|
"files": [{"filename": pr_evaluation.EVALUATION_WORKFLOW}],
|
|
},
|
|
)
|
|
calls = []
|
|
|
|
def api(args):
|
|
calls.append(args)
|
|
return yaml.safe_dump(old if f"ref={OLD}" in args[1] else new)
|
|
|
|
monkeypatch.setattr(pr_evaluation, "_gh", api)
|
|
pr_evaluation.require_comparable_harness(REPO, OLD, HARNESS)
|
|
assert len(calls) == 2 and all("Accept: application/vnd.github.raw+json" in call for call in calls)
|
|
new["jobs"]["evaluate"]["steps"][-1]["run"] += "echo changed measurement\n"
|
|
with pytest.raises(ValueError, match="measurement protocol changed"):
|
|
pr_evaluation.require_comparable_harness(REPO, OLD, HARNESS)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"before,after",
|
|
[
|
|
("--workers 3", "--workers 1"),
|
|
("--timeout 3600", "--timeout 60"),
|
|
("--runs 3", "--runs 2"),
|
|
(" --include-expensive", ""),
|
|
("arms=(baseline);", "arms=(baseline_nomcp);"),
|
|
],
|
|
)
|
|
def test_workflow_protocol_rejects_changed_paid_settings(workflow_protocol_pair, before, after):
|
|
old, new = workflow_protocol_pair
|
|
step = new["jobs"]["evaluate"]["steps"][-1]
|
|
step["run"] = step["run"].replace(before, after)
|
|
assert pr_evaluation.measurement_protocol(yaml.safe_dump(old)) != pr_evaluation.measurement_protocol(
|
|
yaml.safe_dump(new)
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mutation",
|
|
[
|
|
lambda job: job["steps"][0]["with"].update({"node-version": "24"}),
|
|
lambda job: job["steps"][-1].update({"timeout-minutes": 1200}),
|
|
lambda job: job["env"].update(MODEL="another-model"),
|
|
lambda job: job["env"].update(ANTHROPIC_BASE_URL="another-provider"),
|
|
lambda job: job["steps"][1].update(run="uv run prepare --runs 2\n"),
|
|
],
|
|
)
|
|
def test_workflow_protocol_rejects_changed_setup_or_environment(workflow_protocol_pair, mutation):
|
|
old, new = workflow_protocol_pair
|
|
mutation(new["jobs"]["evaluate"])
|
|
assert pr_evaluation.measurement_protocol(yaml.safe_dump(old)) != pr_evaluation.measurement_protocol(
|
|
yaml.safe_dump(new)
|
|
)
|
|
|
|
|
|
def test_workflow_protocol_rejects_extra_paid_invocations(workflow_protocol_pair):
|
|
_, new = workflow_protocol_pair
|
|
new["jobs"]["evaluate"]["steps"].append({"run": "python -m workflow_bench.runner"})
|
|
with pytest.raises(ValueError, match="one paid"):
|
|
pr_evaluation.measurement_protocol(yaml.safe_dump(new))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"comparison",
|
|
[
|
|
{"status": "diverged", "files": []},
|
|
{"status": "ahead"},
|
|
{"status": "ahead", "files": [{"filename": "eval/workflow_bench/runner.py"}]},
|
|
{"status": "ahead", "files": [{"filename": ".github/claude-canary-runtime/package-lock.json"}]},
|
|
{"status": "ahead", "files": [{"filename": "other.py", "previous_filename": "eval/workflow_bench/runner.py"}]},
|
|
{"status": "ahead", "files": [{"filename": "other.py"}] * 300},
|
|
],
|
|
)
|
|
def test_changed_measurement_inputs_or_unknown_history_reject_previous_evidence(monkeypatch, comparison):
|
|
monkeypatch.setattr(pr_evaluation, "_gh_json", lambda endpoint: comparison)
|
|
with pytest.raises(ValueError):
|
|
pr_evaluation.require_comparable_harness(REPO, OLD, HARNESS)
|
|
|
|
|
|
@pytest.fixture
|
|
def github(evidence, monkeypatch):
|
|
from workflow_bench import release_report
|
|
|
|
previous = evidence[0]
|
|
payload = {
|
|
"run": {
|
|
"id": 42,
|
|
"path": ".github/workflows/release-evaluation.yml",
|
|
"conclusion": "success",
|
|
"head_branch": "main",
|
|
"head_sha": OLD,
|
|
"event": "workflow_dispatch",
|
|
"head_repository": {"full_name": REPO},
|
|
},
|
|
"artifacts": {"total_count": 1, "artifacts": [{"name": f"release-agent-evaluation-{OLD}", "expired": False}]},
|
|
"report": previous,
|
|
}
|
|
|
|
def api(endpoint):
|
|
if "/artifacts?" in endpoint:
|
|
return payload["artifacts"]
|
|
if "/compare/" in endpoint:
|
|
return {"status": "ahead", "files": []}
|
|
return payload["run"]
|
|
|
|
def download(arguments):
|
|
from pathlib import Path
|
|
|
|
assert arguments[:4] == ["run", "download", "42", "--repo"]
|
|
assert arguments[4] == REPO
|
|
(Path(arguments[-1]) / "agent-evaluation.json").write_text(json.dumps(payload["report"]))
|
|
return ""
|
|
|
|
monkeypatch.setattr(pr_evaluation, "_gh_json", api)
|
|
monkeypatch.setattr(pr_evaluation, "_gh", download)
|
|
monkeypatch.setattr(release_report, "suite_binding", lambda: ([], previous["task_set_digest"], previous["tasks"]))
|
|
return payload
|
|
|
|
|
|
def test_baseline_download_authenticates_run_artifact_and_recomputes_report(github):
|
|
assert pr_evaluation.fetch_baseline(REPO, 42, HARNESS, "gpt-5.6-sol", "xhigh") == github["report"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mutation",
|
|
[
|
|
lambda g: g["run"].update(conclusion="failure"),
|
|
lambda g: g["run"].update(head_branch="feature"),
|
|
lambda g: g["run"].update(path=".github/workflows/other.yml"),
|
|
lambda g: g["run"].update(id=99),
|
|
lambda g: g["run"]["head_repository"].update(full_name="fork/repo"),
|
|
lambda g: g["artifacts"].update(total_count=101),
|
|
lambda g: g["artifacts"]["artifacts"][0].update(expired=True),
|
|
lambda g: g["artifacts"]["artifacts"][0].update(name=f"pr-cost-comparison-{OLD}"),
|
|
lambda g: g["report"].update(runtime_sha=NEW),
|
|
lambda g: g["report"].update(harness_sha=HARNESS),
|
|
lambda g: g["report"].update(complete=False),
|
|
lambda g: g["report"]["arms"]["baseline"].update(mean_cost_usd=0),
|
|
],
|
|
)
|
|
def test_untrusted_or_tampered_historical_evidence_is_rejected_before_paid_work(github, mutation):
|
|
mutation(github)
|
|
with pytest.raises(ValueError):
|
|
pr_evaluation.fetch_baseline(REPO, 42, HARNESS, "gpt-5.6-sol", "xhigh")
|
|
|
|
|
|
def test_cli_writes_sanitized_candidate_report_and_marks_missing_measurements_incomplete(
|
|
evidence, tmp_path, monkeypatch
|
|
):
|
|
previous, rows, metadata = evidence
|
|
baseline, results, meta, out = (tmp_path / name for name in ("previous.json", "rows.jsonl", "metadata.json", "out"))
|
|
baseline.write_text(json.dumps(previous))
|
|
meta.write_text(json.dumps(metadata))
|
|
results.write_text("\n".join(json.dumps(row) for row in rows))
|
|
monkeypatch.setattr(
|
|
"sys.argv",
|
|
[
|
|
"pr-evaluation",
|
|
"summarize",
|
|
"--results",
|
|
str(results),
|
|
"--metadata",
|
|
str(meta),
|
|
"--baseline",
|
|
str(baseline),
|
|
"--out",
|
|
str(out),
|
|
"--sha",
|
|
NEW,
|
|
"--pr",
|
|
"3621",
|
|
"--run-id",
|
|
"42",
|
|
],
|
|
)
|
|
pr_evaluation.main()
|
|
text = (out / "pr-cost-comparison.json").read_text()
|
|
assert json.loads(text)["improved"]
|
|
assert "/private/transcript" not in text
|
|
results.unlink()
|
|
with pytest.raises(SystemExit) as exc:
|
|
pr_evaluation.main()
|
|
assert exc.value.code == 1
|
|
assert not json.loads((out / "pr-cost-comparison.json").read_text())["complete"]
|
|
assert "Incomplete evidence" in (out / "pr-cost-comparison.md").read_text()
|
|
|
|
|
|
def bindings(previous):
|
|
return [
|
|
{
|
|
"id": task,
|
|
"resolved_sha": pin["sha"],
|
|
"oracle_digest": pin["oracle_digest"],
|
|
"sandbox_dependency_content_digest": "9" * 64,
|
|
}
|
|
for task, pin in previous["tasks"].items()
|
|
]
|
|
|
|
|
|
def test_dependency_preflight_accepts_identical_prepared_task_bytes(evidence):
|
|
previous = evidence[0]
|
|
pr_evaluation.check_dependency_bindings(bindings(previous), previous)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"mutation",
|
|
[
|
|
lambda bs: bs.pop(),
|
|
lambda bs: bs.append(dict(bs[0])),
|
|
lambda bs: bs[0].update(resolved_sha=NEW),
|
|
lambda bs: bs[0].update(oracle_digest="0" * 64),
|
|
lambda bs: bs[0].update(sandbox_dependency_content_digest="0" * 64),
|
|
],
|
|
)
|
|
def test_dependency_preflight_rejects_incompatible_bytes_before_paid_sessions(evidence, mutation):
|
|
previous = evidence[0]
|
|
prepared = bindings(previous)
|
|
mutation(prepared)
|
|
with pytest.raises(ValueError):
|
|
pr_evaluation.check_dependency_bindings(prepared, previous)
|