"""סיעור מוחות לגיבוש כיוון ההחלטה. שלב 4א באיפיון המוצר: 1. הצגת טענות מרכזיות 2. הצעת 2-3 כיוונים אפשריים לנימוק 3. שיח אינטראקטיבי עד לכיוון מוסכם 4. יצירת מסמך כיוון """ from __future__ import annotations import logging from uuid import UUID from legal_mcp import config from legal_mcp.config import parse_llm_json from legal_mcp.services import db, claude_session logger = logging.getLogger(__name__) BRAINSTORM_PROMPT = """אתה יועץ משפטי מומחה בתכנון ובניה. תפקידך לסייע בגיבוש כיוון להחלטת ועדת ערר. ## הנחיות: 1. **הצג את הטענות המרכזיות** מכל הצדדים — 3-5 טענות עיקריות 2. **הצע 2-3 כיוונים אפשריים** לנימוק ההחלטה. כל כיוון כולל: - שם הכיוון (שורה אחת) - נימוקים מרכזיים (2-3 נקודות) - פסיקה רלוונטית (אם יש) - חוזקות וחולשות 3. **אל תמליץ** על כיוון אחד — הצג אותם באופן ניטרלי 4. **סוג הערר** משפיע על הטון: רישוי = חם יחסית, השבחה/פיצויים = קר ומקצועי ## תוצאה שנקבעה: {outcome_hebrew} {reasoning_context} ## פלט: החזר JSON בפורמט: {{ "key_claims": [ {{"party": "עוררים/משיבים", "claim": "טענה מרכזית", "strength": "חזקה/בינונית/חלשה"}} ], "directions": [ {{ "name": "שם הכיוון", "reasoning": ["נימוק 1", "נימוק 2"], "precedents": ["פסיקה רלוונטית"], "strengths": ["חוזקה"], "weaknesses": ["חולשה"] }} ], "recommended_order": "סדר מומלץ של נימוקים בדיון" }} """ OUTCOME_HEBREW = { "rejected": "דחייה", "accepted": "קבלה", "partial": "קבלה חלקית", } APPEAL_TYPE_TONE = { "licensing": "טון חם יחסית — יש הקשר תכנוני רחב ואלמנטים אנושיים", "betterment": "טון קר ומקצועי — יבש, ללא רגשות", "compensation": "טון קר ומקצועי — דומה להיטל השבחה", } async def generate_directions( case_id: UUID, outcome: str, reasoning: str = "", ) -> dict: """סיעור מוחות — הצגת טענות מרכזיות והצעת כיוונים. Args: case_id: מזהה התיק outcome: תוצאה (rejected/accepted/partial) reasoning: נימוק ראשוני (אם יש) Returns: dict עם key_claims, directions, recommended_order """ # Gather context case = await db.get_case(case_id) if not case: raise ValueError(f"Case {case_id} not found") claims = await db.get_claims(case_id) docs = await db.list_documents(case_id) # Build claims summary claims_text = "" if claims: for c in claims: role_heb = {"appellant": "עוררים", "respondent": "משיבים", "committee": "ועדה מקומית", "permit_applicant": "מבקשי היתר"}.get(c["party_role"], c["party_role"]) claims_text += f"- [{role_heb}] {c['claim_text'][:200]}\n" # Get document excerpts for context doc_context = "" for doc in docs[:5]: text = await db.get_document_text(UUID(doc["id"])) if text: doc_context += f"\n--- {doc['title']} ({doc['doc_type']}) ---\n{text[:3000]}\n" # Determine appeal type tone appeal_type = case.get("appeal_type", "") tone_hint = APPEAL_TYPE_TONE.get(appeal_type, "") outcome_hebrew = OUTCOME_HEBREW.get(outcome, outcome) reasoning_context = f"נימוק ראשוני: {reasoning}" if reasoning else "לא סופק נימוק — יש להציע כיוונים." prompt = BRAINSTORM_PROMPT.format( outcome_hebrew=outcome_hebrew, reasoning_context=reasoning_context, ) if tone_hint: prompt += f"\n\n## טון: {tone_hint}" user_content = f"""{prompt} ## פרטי התיק: - מספר: {case['case_number']} - נושא: {case.get('subject', '')} - עוררים: {', '.join(case.get('appellants', []))} - משיבים: {', '.join(case.get('respondents', []))} ## טענות שחולצו: {claims_text or '(לא חולצו טענות עדיין)'} ## חומרי המקור: {doc_context or '(אין מסמכים בתיק)'} """ result = await claude_session.query_json(user_content) if result is None: logger.warning("Failed to parse brainstorm response") return { "key_claims": [], "directions": [], "recommended_order": "", "raw_response": "", } return result def build_direction_doc( outcome: str, reasoning: str, directions_result: dict, selected_direction: int | None = None, additional_notes: str = "", ) -> dict: """בניית מסמך כיוון מתוצאות סיעור המוחות. Args: outcome: תוצאה שנקבעה reasoning: נימוק directions_result: תוצאות מ-generate_directions selected_direction: אינדקס הכיוון שנבחר (0-based) additional_notes: הערות נוספות מהמשתמש """ direction = None if selected_direction is not None and directions_result.get("directions"): directions = directions_result["directions"] if 0 <= selected_direction < len(directions): direction = directions[selected_direction] return { "outcome": outcome, "outcome_hebrew": OUTCOME_HEBREW.get(outcome, outcome), "reasoning": reasoning, "selected_direction": direction, "key_claims": directions_result.get("key_claims", []), "recommended_order": directions_result.get("recommended_order", ""), "additional_notes": additional_notes, "approved": True, }