Add decision-writing methodology based on FJC, Garner, Posner sources
"בית ספר להחלטות" Phase 2 — the system now has formal analytical
methodology for building quasi-judicial decisions, separate from
Dafna's writing style (SKILL.md) and content checklists.
What was done:
- Downloaded 5 authoritative sources (~341K words): FJC Judicial
Writing Manual (1991+2020), Garner Legal Writing in Plain English,
Posner How Judges Think, Scalia/Garner Making Your Case
- Extracted principles from all sources into intermediate docs
- Synthesized into docs/decision-methodology.md (3,400 words,
12 sections, 10 guiding principles)
- Integrated methodology into block-yod prompt via {methodology_guidance}
- Restructured legal-writer agent workflow to follow analytical stages
- Made "answer all claims" flexible (bundle/skip via chair_directions)
- Added methodology compliance check (#7) to legal-qa agent
- Updated all knowledge files (CLAUDE.md, SKILL.md, lessons, corpus)
Three-layer architecture:
1. Methodology (decision-methodology.md) — universal, how to think
2. Content checklists (lessons.py) — specific per appeal subtype
3. Style (SKILL.md) — Dafna's personal writing patterns
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ from uuid import UUID
|
||||
|
||||
from legal_mcp import config
|
||||
from legal_mcp.services import db, embeddings, claude_session
|
||||
from legal_mcp.services.lessons import get_content_checklist
|
||||
from legal_mcp.services.lessons import get_content_checklist, get_methodology_summary
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -201,30 +201,22 @@ BLOCK_PROMPTS = {
|
||||
## זהו הבלוק הקריטי ביותר — ליבת ההחלטה (ratio decidendi).
|
||||
## אורך נדרש: **2,000-4,000 מילים לפחות**. זהו הבלוק הארוך ביותר בהחלטה (35-50%).
|
||||
|
||||
## מתודולוגיה — CREAC:
|
||||
1. **C** (Conclusion) — פתח במסקנה: "לאחר שעיינו... מצאנו כי הערר [נדחה/מתקבל]"
|
||||
2. **R** (Rule) — הצג את הכלל המשפטי הרלוונטי עם ציטוט פסיקה
|
||||
3. **E** (Explanation) — צטט פסיקה שמסבירה את הכלל (200-600 מילים לכל ציטוט)
|
||||
4. **A** (Application) — יישם על העובדות הספציפיות של התיק
|
||||
5. **C** (Conclusion) — מסקנת ביניים
|
||||
|
||||
## כללים קריטיים:
|
||||
- **מסקנה בפתיחה** — לא בסוף
|
||||
- **מענה פרטני לכל טענה** שהוצגה בבלוק ז — עבור על כל טענה ברשימה והתייחס אליה בנפרד. אל תדלג על שום טענה.
|
||||
- **ציטוטי פסיקה** — צטט לפחות 3-5 פסקי דין רלוונטיים. כל ציטוט עם שם התיק המלא.
|
||||
- **ללא כפילות** — הפנה לבלוקים קודמים: "כאמור בסעיף X לעיל"
|
||||
- **ללא כותרות משנה** (חריג: נושאים נפרדים לחלוטין)
|
||||
- מספור רציף
|
||||
{methodology_guidance}
|
||||
|
||||
{content_checklist}
|
||||
|
||||
## כללים נוספים:
|
||||
- **ללא כפילות** — הפנה לבלוקים קודמים: "כאמור בסעיף X לעיל"
|
||||
- **מספור רציף** — המשך מספור מהבלוק הקודם
|
||||
- מותרות כותרות-משנה כשיש נושאים נפרדים לחלוטין
|
||||
|
||||
## כיוון מאושר (חובה):
|
||||
{direction_context}
|
||||
|
||||
## מבנה לפי תוצאה:
|
||||
{structure_guidance}
|
||||
|
||||
## טענות שצריך לענות עליהן (חובה — כל טענה חייבת מענה):
|
||||
## טענות:
|
||||
{claims_context}
|
||||
|
||||
## חומרי מקור:
|
||||
@@ -315,12 +307,15 @@ async def write_block(
|
||||
|
||||
# Content checklist — tells block-yod WHAT topics to cover
|
||||
content_checklist = ""
|
||||
methodology_guidance = ""
|
||||
if block_id == "block-yod":
|
||||
content_checklist = get_content_checklist(
|
||||
appeal_type=case.get("appeal_type", ""),
|
||||
subject=case.get("subject", ""),
|
||||
subject_categories=case.get("subject_categories", []),
|
||||
)
|
||||
# Methodology guidance — tells block-yod HOW to reason (universal, not case-specific)
|
||||
methodology_guidance = get_methodology_summary()
|
||||
|
||||
# Format prompt — per Anthropic long-context best practices:
|
||||
# Place source documents FIRST (top of prompt), instructions LAST.
|
||||
@@ -336,6 +331,7 @@ async def write_block(
|
||||
discussion_context=discussion_context,
|
||||
structure_guidance=structure_guidance,
|
||||
content_checklist=content_checklist,
|
||||
methodology_guidance=methodology_guidance,
|
||||
)
|
||||
|
||||
# Restructure: sources first, then instructions
|
||||
@@ -431,7 +427,7 @@ async def _build_claims_context(case_id: UUID) -> str:
|
||||
lines.append(f"\n### {role_heb.get(current_role, current_role)}")
|
||||
claim_num += 1
|
||||
lines.append(f"טענה #{claim_num}: {c['claim_text'][:400]}")
|
||||
lines.append(f"\n**סה\"כ {claim_num} טענות — חובה לענות על כל אחת.**")
|
||||
lines.append(f"\n**סה\"כ {claim_num} טענות. ענה על כל טענה מהותית; טענות [bundle] — אגד; טענות [skip] — ציון קצר בלבד.**")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
@@ -662,6 +658,17 @@ async def get_block_context(case_id: UUID, block_id: str, instructions: str = ""
|
||||
outcome = (decision or {}).get("outcome", "rejected")
|
||||
structure_guidance = STRUCTURE_GUIDANCE.get(outcome, "")
|
||||
|
||||
# Content checklist + methodology for block-yod
|
||||
content_checklist = ""
|
||||
methodology_guidance = ""
|
||||
if block_id == "block-yod":
|
||||
content_checklist = get_content_checklist(
|
||||
appeal_type=case.get("appeal_type", ""),
|
||||
subject=case.get("subject", ""),
|
||||
subject_categories=case.get("subject_categories", []),
|
||||
)
|
||||
methodology_guidance = get_methodology_summary()
|
||||
|
||||
formatted_prompt = prompt_template.format(
|
||||
case_context=case_context,
|
||||
source_context=source_context,
|
||||
@@ -672,6 +679,8 @@ async def get_block_context(case_id: UUID, block_id: str, instructions: str = ""
|
||||
style_context=style_context,
|
||||
discussion_context=discussion_context,
|
||||
structure_guidance=structure_guidance,
|
||||
content_checklist=content_checklist,
|
||||
methodology_guidance=methodology_guidance,
|
||||
)
|
||||
|
||||
if instructions:
|
||||
|
||||
@@ -519,3 +519,65 @@ def get_content_checklist(
|
||||
|
||||
# Default: substantive licensing
|
||||
return CONTENT_CHECKLISTS["licensing_substantive"]
|
||||
|
||||
|
||||
# ── Methodology guidance (condensed from decision-methodology.md) ──
|
||||
|
||||
_METHODOLOGY_CORE = """## מתודולוגיה אנליטית — עקרונות מנחים לכתיבת הדיון
|
||||
|
||||
### מבנה סילוגיסטי לכל סוגיה
|
||||
כל סוגיה נבנית כסילוגיזם: (1) הנחה עליונה = הכלל (הוראת תכנית, חוק, הלכה); (2) הנחה תחתונה = העובדות הספציפיות; (3) מסקנה. אם לא ניתן לזהות את הכלל — ההנמקה אינה מספקת. אם לא ניתן לזהות כיצד העובדות מקיימות את הכלל — ההנמקה קריפטית.
|
||||
|
||||
### התחל מלשון הטקסט
|
||||
כשהמקרה נשלט על ידי הוראת תכנית או סעיף חוק — פתח בציטוט ההוראה. פרש מילים במשמעותן הרגילה. תן תוקף לכל מילה. אם יש עמימות — השתמש בכלי פרשנות.
|
||||
|
||||
### הפרד ממצא עובדתי ממסקנה משפטית
|
||||
"הבניה במרחק 1.5 מטרים מגבול המגרש" = ממצא עובדתי. "חריגה זו עולה כדי סטייה ניכרת" = מסקנה משפטית. אל תערבב.
|
||||
|
||||
### CREAC לכל סוגיה
|
||||
1. מסקנה — פתח בתשובה ("הבקשה אינה תואמת...")
|
||||
2. כלל — ציטוט ההוראה
|
||||
3. הרחבה — תקדים רלוונטי אחד (אם נדרש)
|
||||
4. יישום — החלת הכלל על העובדות (לב ההנמקה)
|
||||
5. מסקנה חוזרת — סגירה תמציתית
|
||||
|
||||
### Steel-Man — הצג טענה בחוזקתה לפני דחייה
|
||||
לפני שדוחים טענה — הצג אותה בגרסה החזקה ביותר: "אמנם צודק העורר כי [נקודה לטובתו], אולם [הנימוק לדחייה]." טענת קש קלה להפריך אך לא משכנעת.
|
||||
|
||||
### טכניקת סנדוויץ' לציטוטים
|
||||
כל ציטוט עטוף: משפט הקדמה (מודיע על התוכן) → ציטוט → ניתוח (מסביר כיצד רלוונטי למקרה). אל תניח שהקורא יקרא ציטוט ארוך ויפיק ממנו מסקנות בעצמו.
|
||||
|
||||
### נתונים, לא תיאורים
|
||||
"הבקשה חורגת ב-1.5 מטרים מקו הבניין" — לא "הבקשה חורגת באופן משמעותי." מספרים, מידות, אחוזים.
|
||||
|
||||
### כנות לגבי קושי
|
||||
כשהמקרה קשה — אמור זאת: "הדבר אינו נקי מספקות, אולם..." אל תעמיד פנים שמקרה קשה הוא קל.
|
||||
|
||||
### כל מילה עובדת
|
||||
"לאחר ששקלנו את כלל השיקולים" — ריק, מחק. מבחן: אם מוחקים את המשפט וההחלטה לא מאבדת מידע — המשפט מיותר.
|
||||
|
||||
### איזון ומידתיות (כשהכלל לא נותן תשובה חד-משמעית)
|
||||
כשנדרש איזון:
|
||||
1. זהה אינטרסים קונקרטיים (לא "אינטרס הציבור" אלא "שמירה על אופי מגורים צמודי קרקע")
|
||||
2. בחן השלכות לכל כיוון: מה קורה אם מקבלים? אם דוחים?
|
||||
3. שקול השלכות מערכתיות: מה הסיגנל שנשלח למערכת?
|
||||
4. ציין מה מכריע את הכף ולמה
|
||||
כשמטילים מגבלה/תנאי — מבחן מידתיות: (1) תכלית ראויה?; (2) אמצעי פוגע פחות?; (3) פגיעה מידתית ביחס לתועלת?
|
||||
|
||||
### טיפול בטענות
|
||||
- ההחלטה מנתחת שאלות — לא מתווכחת עם עו"ד. מבנה: שאלה→כלל→עובדות→מסקנה
|
||||
- טענות שסומנו [bundle] ב-chair_directions: קבץ ודון יחד
|
||||
- טענות שסומנו [skip] ב-chair_directions: ציון קצר בלבד
|
||||
- טענות ללא סימון: ענה בנפרד עם מענה מנומק
|
||||
- טענה מרכזית של הצד המפסיד חייבת מענה Steel-Man
|
||||
- מיקום ההתמודדות עם טענות נגדיות: באמצע הדיון בסוגיה (לא בהתחלה ולא בסוף)
|
||||
"""
|
||||
|
||||
def get_methodology_summary() -> str:
|
||||
"""Return the condensed methodology guidance — always the same, always complete.
|
||||
|
||||
The methodology is universal: it teaches HOW to think, not WHAT to discuss.
|
||||
Case-specific content (parking, building lines, significant deviation) belongs
|
||||
in the content checklists, not here.
|
||||
"""
|
||||
return _METHODOLOGY_CORE
|
||||
|
||||
Reference in New Issue
Block a user