Merge pull request 'fix(block-zayin): הפרדת-משיבים בבלוק ז' (טענות הצדדים) — השלמת #224 לשכבת-הכתיבה' (#401) from worktree-block-zayin-respondent-split into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m33s
G12 Leak-Guard / leak-guard (push) Successful in 4s
Lint — undefined names / undefined-names (push) Successful in 15s

This commit was merged in pull request #401.
This commit is contained in:
2026-07-06 12:47:16 +00:00

View File

@@ -192,16 +192,16 @@ BLOCK_PROMPTS = {
## כללים קריטיים: ## כללים קריטיים:
- **סנתז טענות דומות** — אל תרשום כל טענה בנפרד. קבץ טענות דומות לנושא אחד. למשל: כל הטענות על הודעות → סעיף אחד, כל הטענות על רכוש משותף → סעיף אחד. - **סנתז טענות דומות** — אל תרשום כל טענה בנפרד. קבץ טענות דומות לנושא אחד. למשל: כל הטענות על הודעות → סעיף אחד, כל הטענות על רכוש משותף → סעיף אחד.
- גוף שלישי: "העוררים טוענים כי...", "הוועדה המקומית ציינה כי..." - גוף שלישי: "העוררים טוענים כי...", "הוועדה המקומית ציינה כי..."
- **מבנה קבוע עם 3 חלקים:** - **מבנה: חלק (סעיף עם כותרת-משנה) לכל צד שמופיע בטענות שחולצו למטה** — לפי הכותרות שם (### ...). אל תמציא צדדים שאינם מופיעים ואל תשמיט צד שמופיע.
1. "טענות העוררים" — 8-12 סעיפים מקובצים לפי נושא - "טענות העוררים" — 8-12 סעיפים מקובצים לפי נושא.
2. "עמדת הוועדה המקומית" — 5-8 סעיפים - **צד-משיב/מתנגד: כתוב חלק נפרד לכל כתב-תשובה** שמופיע (למשל "עמדת משיבות 2-3" ו-"עמדת משיבים 4-6" בנפרד) — 5-10 סעיפים לכל אחד. **אל תמזג משיבים שונים לסעיף אחד**, ואם עמדותיהם מנוגדות — שקף זאת.
3. "עמדת מבקשי ההיתר" (אם יש) — 5-10 סעיפים - "עמדת הוועדה המקומית" / "עמדת מבקשי ההיתר" (אם מופיעים) — 5-8 סעיפים.
- כותרת: "תמצית טענות הצדדים" - כותרת: "תמצית טענות הצדדים"
- נאמנות למקור — לא להמציא טענות, אבל כן לאחד ולסכם טענות חוזרות - נאמנות למקור — לא להמציא טענות, אבל כן לאחד ולסכם טענות חוזרות
- אין ניתוח, אין מסקנות, אין הערכה ("טענה חלשה/חזקה") - אין ניתוח, אין מסקנות, אין הערכה ("טענה חלשה/חזקה")
- רק מכתבי טענות מקוריים (לא השלמות טיעון) - רק מכתבי טענות מקוריים (לא השלמות טיעון)
- מספור רציף - מספור רציף
- **יעד אורך: 800-1500 מילים** - **יעד אורך: 800-1500 מילים** (יותר כשיש כמה כתבי-תשובה נפרדים — כל צד מקבל את מלוא ההתייחסות)
## טענות שחולצו (קבץ טענות דומות לנושאים): ## טענות שחולצו (קבץ טענות דומות לנושאים):
{claims_context} {claims_context}
@@ -629,18 +629,44 @@ async def _build_claims_context(case_id: UUID) -> str:
# Fallback to all non-block-zayin claims if no source claims exist. # Fallback to all non-block-zayin claims if no source claims exist.
source_claims = [c for c in claims if c.get("source_document", "") != "block-zayin"] or claims source_claims = [c for c in claims if c.get("source_document", "") != "block-zayin"] or claims
lines = [] # Group by (party_role, brief) so a multi-litigant side (respondent /
current_role = "" # permit_applicant) whose claims come from distinct pleadings reads as
# SEPARATE positions — e.g. "כתב תשובה משיבות 2-3" vs "משיבים 4-6" — instead
# of one merged "טענות המשיבים" (#224). The brief label is the source
# pleading, and which sides split is SPLIT_PARTIES — the SAME rule the
# argument aggregator uses, so block ז and the arguments panel agree (G2).
from legal_mcp.services.argument_aggregator import SPLIT_PARTIES
role_heb = {"appellant": "טענות העוררים", "respondent": "טענות המשיבים", role_heb = {"appellant": "טענות העוררים", "respondent": "טענות המשיבים",
"committee": "עמדת הוועדה המקומית", "permit_applicant": "עמדת מבקשי ההיתר"} "committee": "עמדת הוועדה המקומית", "permit_applicant": "עמדת מבקשי ההיתר"}
claim_num = 0 role_order = ["appellant", "committee", "respondent", "permit_applicant"]
groups: dict[tuple[str, str], list[dict]] = {}
for c in source_claims: for c in source_claims:
if c["party_role"] != current_role: role = c.get("party_role", "") or ""
current_role = c["party_role"] brief = (c.get("source_document", "") or "").strip() if role in SPLIT_PARTIES else ""
lines.append(f"\n### {role_heb.get(current_role, current_role)}") groups.setdefault((role, brief), []).append(c)
claim_num += 1
lines.append(f"טענה #{claim_num}: {c['claim_text'][:400]}") def _sort_key(k: tuple[str, str]) -> tuple[int, str]:
lines.append(f"\n**סה\"כ {claim_num} טענות. ענה על כל טענה מהותית; טענות [bundle] — אגד; טענות [skip] — ציון קצר בלבד.**") role, brief = k
idx = role_order.index(role) if role in role_order else len(role_order)
return (idx, brief)
lines: list[str] = []
claim_num = 0
for role, brief in sorted(groups.keys(), key=_sort_key):
header = role_heb.get(role, role or "טענות נוספות")
if brief:
header = f"{header}{brief}"
lines.append(f"\n### {header}")
for c in groups[(role, brief)]:
claim_num += 1
lines.append(f"טענה #{claim_num}: {c['claim_text'][:400]}")
lines.append(
f"\n**סה\"כ {claim_num} טענות. שמור על ההפרדה בין הצדדים לעיל — "
f"לכל צד/כתב-תשובה עמדה נפרדת (אל תמזג משיבים שונים). ענה על כל טענה "
f"מהותית; טענות [bundle] — אגד; טענות [skip] — ציון קצר בלבד.**"
)
return "\n".join(lines) return "\n".join(lines)