fix(precedents): נרמול case_number עמיד-להתנגשות — מדלג ומתעד, לא קורס (#145)
ה-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:
@@ -67,7 +67,7 @@ async def main() -> None:
|
||||
rows = await _empty_citation_rows(args.limit)
|
||||
print(f"רשומות עם citation_formatted ריק: {len(rows)}\n")
|
||||
|
||||
n_pass1 = n_pass2 = n_abstain = 0
|
||||
n_pass1 = n_pass2 = n_abstain = n_errors = 0
|
||||
for r in rows:
|
||||
cid = r["id"]
|
||||
# Pass 1 — deterministic from the stored row (no LLM).
|
||||
@@ -92,7 +92,13 @@ async def main() -> None:
|
||||
print(f" ? [llm?] {r['case_number']} — would run extractor (dry-run)")
|
||||
continue
|
||||
|
||||
res = await precedent_metadata_extractor.extract_and_apply(cid)
|
||||
# One bad row must never abort the batch — log and move on.
|
||||
try:
|
||||
res = await precedent_metadata_extractor.extract_and_apply(cid)
|
||||
except Exception as e: # noqa: BLE001 — best-effort backfill, reported per-row
|
||||
n_errors += 1
|
||||
print(f" ✗ [error] {r['case_number']}: {type(e).__name__}: {e}")
|
||||
continue
|
||||
record2 = await db.get_case_law(cid)
|
||||
new_cit = (record2.get("citation_formatted") or "").strip()
|
||||
if new_cit:
|
||||
@@ -109,7 +115,7 @@ async def main() -> None:
|
||||
|
||||
print(
|
||||
f"\nסיכום: דטרמיניסטי={n_pass1} · LLM={n_pass2} · "
|
||||
f"נמנע (חסר רכיב)={n_abstain}"
|
||||
f"נמנע (חסר רכיב)={n_abstain} · שגיאות={n_errors}"
|
||||
+ ("" if args.apply else " (dry-run — לא נכתב)")
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user