fix(graph): normalize case_law subject_tags to underscore convention at write chokepoint #311
Reference in New Issue
Block a user
Delete Branch "worktree-subject-tag-normalize"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
רקע
צמתי-הנושא ב-
/graphנבנים מ-case_law.subject_tags. נמצאו תגים שנראים ככפילות בגרף, שנבדלים רק בקיום/היעדר מקף-תחתון בין המילים (למשלהיטל השבחהמולהיטל_השבחה). חקירה העלתה:precedent_library:קווי_בניין,מועד_קביעת_שומה), ו-892 מתוך 1011 התגים הייחודיים (~99%) פועלים לפיה.היטל השבחה↔היטל_השבחה,הארכת מועד↔הארכת_מועד).pa:betterment_levy(תווית "היטל השבחה" עם רווח) מול צומת-הנושאtag:היטל_השבחה— אינה באג: אלו שתי שכבות-גרף שונות (תחום מול נושא). לא נגענו בה.הנתונים נורמלו בנפרד (תיק יעקב עמיאל → מקף-תחתון). PR זה אוכף את המוסכמה במקור כדי שאף נתיב-כתיבה לא יחזיר את הפיצול.
השינוי
_normalize_subject_tags()חדש ב-db.py, נקרא בשלוש (וכל) נקודות-הכתיבה שלcase_law.subject_tags:create_external_case_lawcreate_internal_committee_decisionupdate_case_lawכך הכלל לא ניתן-לעקיפה מאף נתיב. הכלל שמרני: רק ביטוי עברי פשוט רב-מילים (
[א-ת]+מופרד ברווח) מומר למקף-תחתון; תגים עם פיסוק/מספרים/מקפים (פטור מותנה — סעיף 19(ג)) נשארים. בנוסף — dedup לאחר הנרמול.digests.subject_tags(TEXT[], שכבת-גרף אחרת) ו-canonical_halachot— מחוץ להיקף בכוונה.Invariants
graph_api(היה מסתיר את אי-העקביות במסך אחד בעוד החיפוש מציג מקף → drift).graph_apiנשאר היטל-קריאה טהור; אין נרמול מקביל שם.בדיקות
py_compileעובר.None— כולן עוברות.🤖 Generated with Claude Code
Topic hubs in /graph are built from case_law.subject_tags. The documented extraction contract (precedent_library tool examples: קווי_בניין, מועד_קביעת_שומה) and ~99% of the corpus store plain multi-word Hebrew tags with underscores between words ("היטל_השבחה"). A single case (8126-03-25, יעקב עמיאל) was tagged with spaces ("היטל השבחה"), which the graph renders as a SECOND, distinct topic hub — a duplicate of the underscore form. The data was normalized separately; this enforces the convention at the source so no write path can re-introduce the split. _normalize_subject_tags() is applied at the three (and only) case_law write chokepoints in db.py — create_external_case_law, create_internal_committee_decision, update_case_law — so the rule cannot be bypassed (G1: normalize at source, not in the read/graph path). Tags carrying punctuation/digits/dashes (e.g. "פטור מותנה — סעיף 19(ג)") are left untouched; only plain Hebrew word phrases ([א-ת]+ separated by spaces) are converted. Also dedups post-normalize. digests.subject_tags (TEXT[], a different graph layer) and canonical_halachot are intentionally out of scope. Invariants: maintains G1 (fix at source, not in the read projection), G2 (graph_api stays a pure read projection — no parallel normalization there). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>