fix(rectification): keep compare requests valid after style cards (BUG-577–580)

Engine asked_probe_keys no longer include varga split hashes that 400 the scorer, failed compares become visible and retry, user stop can still deliver a range on a stale snapshot, and holdout no longer reasks domains already in the ledger.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-07 15:46:33 +08:00
parent 3f4d38d485
commit 4e0db55f03
34 changed files with 1079 additions and 156 deletions
+10 -2
View File
@@ -54,6 +54,7 @@ _REQUEST_FIELDS = frozenset({
"birth_date", "start_time", "end_time", "lat", "lon", "tz", "events",
"ayanamsa", "node_mode", "asked_probe_keys", "minute_step", "blocks",
}) | _REQUEST_PROVENANCE_FIELDS
ASKED_PROBE_KEY_MAX_LENGTH = 200
_EVENT_FIELDS = frozenset({"id", "domain", "event_kind", "date_start", "date_end", "precision", "summary"}) | _EVENT_PROVENANCE_FIELDS
_CLOCK = re.compile(r"(?:[01]\d|2[0-3]):[0-5]\d\Z")
_MINUTES_PER_DAY = 24 * 60
@@ -167,6 +168,7 @@ class RectificationRequest(TypedDict):
timezone_source: NotRequired[str | None]
local_time_status: NotRequired[str | None]
asked_probe_keys: NotRequired[list[str]]
dropped_asked_probe_keys: NotRequired[int]
minute_step: NotRequired[int]
blocks: NotRequired[list[dict[str, Any]]]
@@ -335,17 +337,23 @@ def normalize_rectification_request(body: Any, *, today: date | None = None) ->
raise ValueError("asked_probe_keys must contain between 0 and 200 strings")
cleaned_keys: list[str] = []
seen: set[str] = set()
dropped = 0
for index, item in enumerate(asked):
if not isinstance(item, str) or not item.strip() or len(item.strip()) > 120:
if not isinstance(item, str) or not item.strip():
raise ValueError(
f"asked_probe_keys[{index}] must be a non-empty string up to 120 characters"
f"asked_probe_keys[{index}] must be a non-empty string up to {ASKED_PROBE_KEY_MAX_LENGTH} characters"
)
key = item.strip()
if len(key) > ASKED_PROBE_KEY_MAX_LENGTH:
dropped += 1
continue
if key in seen:
continue
seen.add(key)
cleaned_keys.append(key)
cleaned_request["asked_probe_keys"] = cleaned_keys
if dropped:
cleaned_request["dropped_asked_probe_keys"] = dropped
if "minute_step" in body:
minute_step = body.get("minute_step")
if isinstance(minute_step, bool) or not isinstance(minute_step, int) or not 1 <= minute_step <= 15: