feat: תיקון-ציטוט בדלי-החילוץ + קישור-לתור מדף-פרט (#133 follow-ups)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s

אושר ב-Claude Design (כרטיס 20-halacha-followups).

א׳ תיקון-חילוץ אמיתי ל-quote_unverified:
- `update_halacha` מקבל `supporting_quote`; בעדכונו מריץ `_verify_quote`
  הקיים מול `case_law.full_text` השמור (דטרמיניסטי — בלי OCR/LLM מחדש,
  feedback_no_reocr_retrofit) ומסנכרן `quote_verified` + מוסיף/מסיר את
  הדגל `quote_unverified`. יו"ר שמדביק את הנוסח הנכון מהמקור → הדגל נמחק
  → ההלכה עוזבת את דלי-החילוץ. `HalachaUpdateRequest`+handler מעבירים את
  השדה; `HalachaPatch` + מצב-העריכה ב-HalachaCard כוללים textarea-ציטוט
  (נשלח רק כששונה) + hint.

ב׳ דף-פרט פסיקה — ביטול כפילות-המשטח:
- הלכה pending ב-`ExtractedHalachotSection` מציגה קישור "עבור לתור הלכות"
  במקום כפתורי אשר/דחה כפולים (שער-אישור יחיד, INV-IA/G10).
- `/precedents` Tabs הפך נשלט וקורא `?tab=review` (post-mount, בלי
  hydration-mismatch) כדי שהקישור ינחת על טאב-התור.

display-only ל-G10 (האימות מסנכרן מטא-איכות, לא review_status). ולידציה:
py_compile + tsc + eslint נקיים.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 09:03:29 +00:00
parent 99fe16a43d
commit 2962538c09
6 changed files with 96 additions and 25 deletions

View File

@@ -4658,12 +4658,40 @@ async def update_halacha(
reasoning_summary: str | None = None,
subject_tags: list[str] | None = None,
practice_areas: list[str] | None = None,
supporting_quote: str | None = None,
) -> dict | None:
"""Update a halacha — used by the chair to approve/reject/edit."""
"""Update a halacha — used by the chair to approve/reject/edit.
#133 follow-up — extraction repair: when ``supporting_quote`` is edited it is
RE-VERIFIED against the stored source text (deterministic; no re-OCR / no LLM —
see feedback_no_reocr_retrofit) and ``quote_verified`` + the ``quote_unverified``
quality flag are synced. A chair who pastes the correct quote from the source
clears the flag, and the item leaves the 'fix' bucket."""
pool = await get_pool()
set_parts: list[str] = []
params: list = [halacha_id]
idx = 2
if supporting_quote is not None:
set_parts.append(f"supporting_quote = ${idx}")
params.append(supporting_quote)
idx += 1
# re-verify against the stored full_text, sync quote_verified + the flag
src = await pool.fetchrow(
"SELECT cl.full_text, h.quality_flags FROM halachot h "
"JOIN case_law cl ON cl.id = h.case_law_id WHERE h.id = $1", halacha_id)
if src is not None:
from legal_mcp.services.halacha_extractor import _verify_quote
verified = _verify_quote(supporting_quote, src["full_text"] or "")
set_parts.append(f"quote_verified = ${idx}")
params.append(verified)
idx += 1
flags = [f for f in (src["quality_flags"] or [])
if f != halacha_quality.FLAG_QUOTE_UNVERIFIED]
if not verified:
flags.append(halacha_quality.FLAG_QUOTE_UNVERIFIED)
set_parts.append(f"quality_flags = ${idx}")
params.append(flags)
idx += 1
if review_status is not None:
set_parts.append(f"review_status = ${idx}")
params.append(review_status)