Files
Jyotisha/scripts/research/midnight_date_anchor_regression.py
T
jesse-ux b85c4a686a
Independent Staging Quality Gate / validate (push) Successful in 13m27s
Independent Staging Quality Gate / publish (push) Failing after 1h0m1s
fix(rectification): anchor candidate windows to civil dates across midnight
Carry explicit local date intervals instead of inferring the day from clock
order. Cluster width, delivery, adoption, and reports keep the actual civil
date; adopted date is stored separately from the reported birth_date.

Algorithm identity is scoring-9 / spec-v5. Scoring weights, confirmation
thresholds, and Skill version are unchanged. Isolated Linux final-3 gates
passed; four pre-existing Python failures remain. This is not a production
release.
2026-09-21 02:55:00 +08:00

109 lines
5.9 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), 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()