fix(rectification): anchor candidate windows to civil dates across midnight
Independent Staging Quality Gate / validate (push) Successful in 13m27s
Independent Staging Quality Gate / publish (push) Failing after 1h0m1s

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.
This commit is contained in:
jesse-ux
2026-09-21 02:55:00 +08:00
parent 3be740f84d
commit b85c4a686a
115 changed files with 106484 additions and 315 deletions
@@ -0,0 +1,108 @@
#!/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()
+2 -2
View File
@@ -30,8 +30,8 @@ from scripts.research.sealed_holdout_rerun import (
OFFSETS = (-30, -20, -15, -10, -8, -5, -3, 0, 3, 5, 8, 10, 15, 20, 30)
RADII = (15, 30, 60)
MINUTE_STEP = 1
FREEZE = ROOT / "docs/research/reported_offset_cross_midnight_2026_09_20.final.freeze.json"
REPORT = ROOT / "docs/research/reported_offset_cross_midnight_2026_09_20.json"
FREEZE = ROOT / "docs/research/reported_offset_midnight_anchor_2026_09_21.freeze.json"
REPORT = ROOT / "docs/research/reported_offset_midnight_anchor_2026_09_21.json"
LEGACY_REPORT = ROOT / "docs/research/reported_offset_2026_09_20.json"
+6 -2
View File
@@ -27,8 +27,8 @@ from scripts.minute_rectification_feature_facts_v4 import build_feature_fact_row
from scripts.minute_rectification_holdout_validator import validate
DATASET = ROOT / "references/real_case_calibration/minute_rectification_holdout_v3.json"
FREEZE = ROOT / "docs/research/sealed_holdout_rerun_cross_midnight_2026_09_20.final.freeze.json"
REPORT = ROOT / "docs/research/sealed_holdout_rerun_cross_midnight_2026_09_20.json"
FREEZE = ROOT / "docs/research/sealed_holdout_rerun_midnight_anchor_2026_09_21.freeze.json"
REPORT = ROOT / "docs/research/sealed_holdout_rerun_midnight_anchor_2026_09_21.json"
LEGACY_REPORT = ROOT / "docs/research/sealed_holdout_rerun_2026_09_20.json"
ARCHIVE = ROOT / "docs/research/history/rectification_pre_cross_midnight_2026_09_20"
PRODUCTION_FILES = [
@@ -38,6 +38,10 @@ PRODUCTION_FILES = [
"scripts/rectification/case_holdout.py",
"scripts/rectification/contracts.py",
"scripts/rectification/event_probes.py",
"scripts/rectification/candidate_window.py",
"scripts/rectification/decision_policy.py",
"scripts/rectification/refinement_packet.py",
"scripts/rectification/api_service.py",
]
RESEARCH_FILES = [
"scripts/research/reported_offset_sweep.py",