#!/usr/bin/env python3 """Benchmark one synthetic async job in an isolated loopback API before rollout. Uses the installed pinned CLI/account and scoped synthetic credential. Accepts only built-in synthetic fixtures, never an input file or real job identifier. HTTP requests retain the ordinary 45-second timeout. No service configuration or live job database is modified by this probe. """ import argparse from http.server import ThreadingHTTPServer import json import os from pathlib import Path import sys import tempfile import threading import time from urllib.error import HTTPError from urllib.request import ProxyHandler, Request, build_opener sys.path.insert(0, os.environ.get("SUITE_PROBE_MODULE_DIR", "/opt/planner")) from suite_api import Handler from suite_contract import EXECUTION_REVISION, PROMPT_REVISION, REVISION, encoded, validate_result from suite_jobs import Jobs from suite_synthetic import fixture, score def main(): """Submit once, poll safely, and report measured metadata and independent scores.""" parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--size", type=int, choices=(14, 75, 363), default=75) parser.add_argument("--max-seconds", type=int, default=3600) args = parser.parse_args() request, expected = fixture(args.size) request["routing"] = {"allow_external": True, "allowed_external_providers": ["claude"]} request["execution"] = {"strategy": "whole_suite", "max_seconds": args.max_seconds, "max_cost_usd": 30} token = Path("/vault/secrets/synthetic-token").read_text().strip() opener = build_opener(ProxyHandler({})) with tempfile.TemporaryDirectory(prefix="suite-budget-probe-", dir="/jobs") as directory: server = ThreadingHTTPServer(("127.0.0.1", 0), Handler) server.jobs = Jobs(Path(directory) / "jobs.sqlite") threading.Thread(target=server.serve_forever, daemon=True).start() def http(path, value=None, key=None): headers = {"Authorization": "Bearer " + token, "X-Forwarded-For": "192.168.22.8", "Content-Type": "application/json"} if key: headers["Idempotency-Key"] = key call = Request("http://127.0.0.1:" + str(server.server_port) + path, data=encoded(value) if value is not None else None, headers=headers) try: with opener.open(call, timeout=45) as response: return response.status, json.load(response) except HTTPError as exc: with exc: return exc.code, json.load(exc) started, last_report = time.monotonic(), 0.0 report = {"test": "isolated_async_synthetic_budget_benchmark", "case_count": args.size, "request_bytes": len(encoded(request)), "configuration_revision": REVISION, "execution_revision": EXECUTION_REVISION, "prompt_revision": PROMPT_REVISION, "http_timeout_seconds": 45, "automatic_job_retries": 0} try: status, capabilities = http("/v1/capabilities") assert status == 200 and capabilities["max_seconds"] == 3600 assert capabilities["default_max_seconds"] == 1800 invalid = {**request, "execution": {**request["execution"], "max_seconds": 3601}} status, rejected = http("/v1/preflight", invalid) assert status == 400 and rejected["error"]["code"] == "invalid_timeout" status, checked = http("/v1/preflight", request) assert status == 200 and checked["execution"]["max_seconds"] == args.max_seconds report.update(capabilities_limits={k: capabilities[k] for k in ( "max_seconds", "default_max_seconds", "max_cost_usd")}, preflight=checked) status, job = http("/v1/jobs", request, "synthetic-long-budget-probe") assert status == 202 and job["execution"]["max_seconds"] == args.max_seconds path = "/v1/jobs/" + job["job_id"] replay_status, replay = http("/v1/jobs", request, "synthetic-long-budget-probe") assert replay_status == 200 and replay["job_id"] == job["job_id"] report["idempotent_replay_verified"] = True while job["status"] in {"accepted", "running", "cancelling"}: if time.monotonic() - last_report >= 20: progress = job.get("execution_progress", {}) print(json.dumps({k: progress.get(k) for k in ( "current_pass", "completed_model_passes", "job_elapsed_seconds", "job_remaining_seconds", "cost_used_usd_estimate")}), file=sys.stderr, flush=True) last_report = time.monotonic() time.sleep(2) _, job = http(path) report["status"] = job["status"] report["job_metadata"] = job if job["status"] == "completed": status, result = http(path + "/result") assert status == 200 validate_result(result["result"], request) natural = {"groups": result["review_summary"]["natural_families"]} report.update(natural_quality=score(natural, expected), counts=result["review_summary"]["counts"], exact_final_coverage=True) allocations = [p["allocated_seconds"] for p in job["passes"]] assert allocations[0] > 1800 assert all(a > b for a, b in zip(allocations, allocations[1:])) assert job["cli_diagnostics"]["subprocess_timeout_seconds"] == allocations[-1] report["wall_seconds"] = round(time.monotonic() - started, 3) print(json.dumps(report, sort_keys=True), flush=True) return 0 if report["status"] == "completed" else 1 finally: server.shutdown() if __name__ == "__main__": raise SystemExit(main())