fix(precedents): נרמול case_number עמיד-להתנגשות — מדלג ומתעד, לא קורס (#145)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 11s

ה-backfill של citation_formatted חשף קריסה ב-apply_to_record: כשפסק-דין
חיצוני מכיל docket שכבר שייך לרשומה כפולה אחרת, נרמול case_number → docket-נקי
נתקל ב-uq_case_law_external_number ומפיל את כל המיזוג (כולל הציטוט).
דוגמה: 'ע"א 3213/97' → '3213/97' שכבר קיים (כפילות נקר).

- db.case_number_collides(case_number, exclude_id) — בודק אם docket כבר שייך
  לרשומה לא-internal אחרת (האינדקס החלקי).
- apply_to_record — מדלג על נרמול ה-case_number כשיש התנגשות (כפילות לדדופ
  בהמשך, לא ענייננו כאן) וממשיך לכתוב את הציטוט. no-silent-swallow: מתעד warning.
- scripts/backfill_precedent_citations.py — try/except per-row + מונה שגיאות,
  כך ששורה אחת לא מפילה את האצווה.

אומת: ריצה-מחדש מלאה ללא קריסה (0 שגיאות); ההתנגשות תועדה ודולגה כצפוי;
פסיקת בית-משפט: 224/228 מולאו, 4 נמנעו (חסר צדדים/תאריך — abstention, INV-AH).
test_fu2b_reconcile ✓.

Invariants: INV-AH (abstention) · G1 (נרמול-בכתיבה נשמר, רק לא קורס) ·
חוקה §6 (אין בליעה שקטה — דילוג מתועד).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 04:17:07 +00:00
parent 7043de0ac2
commit a02b929b5c
3 changed files with 38 additions and 4 deletions

View File

@@ -364,7 +364,21 @@ async def apply_to_record(
and cn_clean != cur_cn
and (overwrite_case_number or citation_shaped)
):
fields_to_update["case_number"] = cn_clean
# Skip (don't crash) when the clean docket already belongs to ANOTHER
# non-internal row — a duplicate to dedupe later, not this run's concern.
# Writing it would hit uq_case_law_external_number and abort the whole merge
# (including the citation). No-silent-swallow: log the skip.
if (
record.get("source_kind") != "internal_committee"
and await db.case_number_collides(cn_clean, case_law_id)
):
logger.warning(
"metadata_extractor: case_number normalization %r%r skipped — docket "
"already owned by another non-internal row (likely duplicate)",
cur_cn, cn_clean,
)
else:
fields_to_update["case_number"] = cn_clean
# parties — store the extracted "עורר נ' משיב" line (the re-derivable basis for
# the deterministic citation). Only fill when empty; chair edits are preserved.