The staging publish job built the web image without frontend/tests, and next build type-checks every .ts under frontend/, so the harness importing ../tests/helpers/postgres-fixture.ts failed with TS2307. The harness depends on the test fixture, so it now lives in frontend/tests/research; the Python driver points there. A new test fails if src/ or scripts/ import tests/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
81 lines
3.8 KiB
Python
81 lines
3.8 KiB
Python
"""Public holdout replay through live API and production PostgreSQL answer paths.
|
|
|
|
Explicit fictional Case seeds are not successful product opening. No turn,
|
|
evidence, focus or answer is seeded: a refused production RPC stops that row.
|
|
Off is the default; on changes only segment ordering. Truth is oracle-only.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
import threading
|
|
from http.server import ThreadingHTTPServer
|
|
from pathlib import Path
|
|
|
|
from scripts.jyotish_api_server import DEFAULT_ALLOWED_HOSTS, DEFAULT_ALLOWED_ORIGINS, JyotishAPIHandler
|
|
from scripts.research import varga_resolution_lib as vr
|
|
from scripts.research.minute_resolution_sweep import scoring_request_for
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--dataset", default=str(vr.HOLDOUT_V5))
|
|
parser.add_argument("--output", required=True)
|
|
parser.add_argument("--limit", type=int, default=10)
|
|
parser.add_argument("--radii", default="10,30,60")
|
|
args = parser.parse_args()
|
|
target = Path(args.output)
|
|
if target.exists():
|
|
parser.error("--output already exists; retain prior evidence and choose a unique label")
|
|
cases = vr.load_cases(Path(args.dataset))
|
|
if args.limit:
|
|
cases = cases[:args.limit]
|
|
rows = []
|
|
for case in cases:
|
|
birth = case["birth"]
|
|
for radius in map(int, args.radii.split(",")):
|
|
request = scoring_request_for(case, radius)
|
|
rows.append({"case_key": case["case_id"], "radius": radius,
|
|
"snapshot": {"birth_date": birth["date"], "reported_birth_time": str(birth["time"])[:5],
|
|
"birth_time_source": "approximate", "active_birth_time": None,
|
|
"uncertainty_before_minutes": radius, "uncertainty_after_minutes": radius,
|
|
"latitude": request["lat"], "longitude": request["lon"],
|
|
"timezone_offset": request["tz"], "timezone_id": birth.get("timezone_id")},
|
|
"range": {"start_time": request["start_time"], "end_time": request["end_time"]},
|
|
"events": request["events"], "oracle_truth_minute": str(birth["time"])[:5]})
|
|
server = ThreadingHTTPServer(("127.0.0.1", 0), JyotishAPIHandler)
|
|
server.daemon_threads = True
|
|
origin = f"http://127.0.0.1:{server.server_port}"
|
|
server.allowed_hosts = set(DEFAULT_ALLOWED_HOSTS)
|
|
server.allowed_origins = set(DEFAULT_ALLOWED_ORIGINS) | {origin}
|
|
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
|
thread.start()
|
|
try:
|
|
env = {**os.environ, "JYOTISH_API_BASE": origin}
|
|
result = subprocess.run(["node", "--import", "tsx", "tests/research/rectification-segment-persisted-replay.ts"],
|
|
cwd=ROOT / "frontend", env=env, input=json.dumps({"rows": rows}),
|
|
text=True, encoding="utf-8", stdout=subprocess.PIPE, check=False)
|
|
payload = json.loads(result.stdout)
|
|
payload.update({"python_version": platform.python_version(),
|
|
"dataset_sha256": hashlib.sha256(Path(args.dataset).read_bytes()).hexdigest(),
|
|
"runner_exit": result.returncode})
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
with target.open("x", encoding="utf-8") as stream:
|
|
stream.write(json.dumps(payload, ensure_ascii=False, sort_keys=True, indent=2) + "\n")
|
|
print(f"persisted replay rows={len(payload.get('records', []))}; runner_exit={result.returncode}", flush=True)
|
|
return result.returncode
|
|
finally:
|
|
server.shutdown()
|
|
thread.join(timeout=10)
|
|
server.server_close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|