Cache work that depends only on the candidate minute, drop unread response fields, and reject windows above 241 candidates before any chart is built. Eleven canonical scenario hashes match 77057a819. Sealed and reported-offset replays match the 2026-10-08 records (changed_trial_count 8 and 581) and are stored as scoring_perf_2026_10_13.
Co-Authored-By: Grok (agent loop)
109 lines
6.0 KiB
Python
109 lines
6.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Independent-process native A/B and dated-window goldens; not an accuracy benchmark."""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import importlib
|
|
import json
|
|
import sys
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def load(root: Path):
|
|
for name in list(sys.modules):
|
|
if name == "scripts" or name.startswith("scripts."):
|
|
del sys.modules[name]
|
|
sys.path.insert(0, str(root))
|
|
importlib.invalidate_caches()
|
|
from scripts.rectification.api_service import score_candidates
|
|
from scripts.research.probe_supply_after_six import request_from_case
|
|
from scripts.rectification.decision_policy import indistinguishable_width_minutes
|
|
return score_candidates, request_from_case, indistinguishable_width_minutes
|
|
|
|
|
|
def canonical(value):
|
|
return json.dumps(value, sort_keys=True, ensure_ascii=True, separators=(",", ":")).encode()
|
|
|
|
|
|
def projection(result, width):
|
|
new_fields = {"candidate_id", "candidate_date", "window_index", "window_offset_minutes", "segment_index", "cluster_intervals"}
|
|
return {
|
|
"candidate_scores": result["candidate_scores"],
|
|
"matrix": result["event_contribution_matrix"],
|
|
"decisions": [{key: value for key, value in row.items() if key not in new_fields} for row in result["candidate_decisions"]],
|
|
"width": width(result["candidate_decisions"]),
|
|
"confirmation_allowed": result["confirmation_allowed"],
|
|
"selection_allowed": result["selection_allowed"],
|
|
"representative_time": result["decision_receipt"]["representative_time"],
|
|
}
|
|
|
|
|
|
def worker(root: Path, dated: bool):
|
|
score, make_request, width = load(root)
|
|
dataset = ROOT / "references/real_case_calibration/minute_rectification_holdout_v3.json"
|
|
result = []
|
|
for case in json.loads(dataset.read_text(encoding="utf-8"))["cases"][:3]:
|
|
request = make_request(case)
|
|
if dated:
|
|
request["candidate_intervals"] = [{"start_at": f'{request["birth_date"]}T{request["start_time"]}', "end_at": f'{request["birth_date"]}T{request["end_time"]}'}]
|
|
result.append(projection(score(request, include_internal=True), width))
|
|
print(json.dumps(result))
|
|
|
|
|
|
def independent(root: Path, dated: bool):
|
|
completed = subprocess.run([sys.executable, str(Path(__file__).resolve()), "--worker", str(root), *( ["--dated"] if dated else [])],
|
|
cwd=root, check=True, capture_output=True, text=True, encoding="utf-8")
|
|
return json.loads(completed.stdout)
|
|
|
|
|
|
def main():
|
|
if "--worker" in sys.argv:
|
|
worker(Path(sys.argv[sys.argv.index("--worker") + 1]), "--dated" in sys.argv)
|
|
return
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--baseline", type=Path, required=True)
|
|
parser.add_argument("--output", type=Path, default=ROOT / "artifacts/midnight-date-anchor")
|
|
parser.add_argument("--golden", action="store_true")
|
|
parser.add_argument("--golden-path", type=Path, default=ROOT / "frontend/tests/fixtures/rectification-midnight-date-anchor.native.json")
|
|
args = parser.parse_args()
|
|
args.output.mkdir(parents=True, exist_ok=True)
|
|
dataset = ROOT / "references/real_case_calibration/minute_rectification_holdout_v3.json"
|
|
cases = json.loads(dataset.read_text(encoding="utf-8"))["cases"][:3]
|
|
assert all(case["birth"]["source"]["rodden_rating"] == "AA" for case in cases)
|
|
old = independent(args.baseline, False)
|
|
current = independent(ROOT, True)
|
|
comparisons = []
|
|
for case, before, after in zip(cases, old, current):
|
|
fields = {key: canonical(before[key]) == canonical(after[key]) for key in before}
|
|
comparisons.append({"case_id": case["case_id"], "source": case["birth"]["source"], "fields": fields,
|
|
"before_sha256": hashlib.sha256(canonical(before)).hexdigest(), "after_sha256": hashlib.sha256(canonical(after)).hexdigest(),
|
|
"candidate_minutes": len(after["candidate_scores"]), "public_clusters": len(after["decisions"]), "width": after["width"]})
|
|
print("current", case["case_id"], fields, flush=True)
|
|
report = {"baseline": str(args.baseline), "dataset_sha256": hashlib.sha256(dataset.read_bytes()).hexdigest(),
|
|
"same_machine_independent_processes": True, "python_executable": sys.executable, "numeric_tolerance": 0, "comparisons": comparisons,
|
|
"excluded_fields": "new date/ordinal metadata; result/candidate IDs intentionally change with algorithm identity"}
|
|
with (args.output / "independent-process-aa-ab.json").open("x", encoding="utf-8") as stream:
|
|
json.dump(report, stream, indent=2)
|
|
assert all(all(row["fields"].values()) for row in comparisons), "same-day native A/B changed"
|
|
if args.golden:
|
|
score, _, _ = load(ROOT)
|
|
# Explicitly fictional birth/event facts; response is produced only by the unmocked native engine.
|
|
request = {"birth_date": "2000-03-01", "start_time": "23:58", "end_time": "00:02", "lat": 0.0, "lon": 0.0, "tz": 0.0,
|
|
"candidate_intervals": [{"start_at": "2000-02-29T23:58", "end_at": "2000-03-01T00:02"}],
|
|
"events": [{"id": "00000000-0000-4000-8000-000000000001", "domain": "career", "event_kind": "career_entry",
|
|
"date_start": "2020-01-01", "date_end": "2020-01-01", "precision": "day", "summary": "Fictional career entry for date-contract testing"}]}
|
|
from scripts.rectification.contracts import normalize_rectification_request
|
|
response = score(normalize_rectification_request(request))
|
|
target = args.golden_path
|
|
with target.open("x", encoding="utf-8") as stream:
|
|
json.dump({"provenance": {"kind": "unmocked_native_engine", "facts": "explicitly_fictional", "generator": "scripts/research/midnight_date_anchor_regression.py --baseline <baseline-worktree> --golden", "algorithm": response["algorithm_version"]}, "request": request, "response": response}, stream, ensure_ascii=False, indent=2)
|
|
print("golden", target, flush=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|