From 911c797eb2b948176b00874f107ff68c45f7fc06 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 4 Apr 2026 14:27:07 +0000 Subject: [PATCH] Reorganize: skills/ directory + move memory to docs/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skill-legal-decision/ → skills/decision/ skill-legal-assistant/ → skills/assistant/ skill-legal-docx/ → skills/docx/ memory/*.md → docs/ Also removed: TASKS.md (use TaskMaster), classifier.py (replaced by local_classifier.py) Updated all references in CLAUDE.md, scripts, PRDs, docs. Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 1 - .taskmaster/docs/prd.txt | 4 +- CLAUDE.md | 41 ++- TASKS.md | 38 --- docs/legal-decision-lessons.md | 163 ++++++++++++ docs/memory.md | 39 +++ docs/migration-plan.md | 2 +- .../src/legal_mcp/services/classifier.py | 248 ------------------ scripts/export-decision-docx.py | 2 +- scripts/seed-knowledge.py | 2 +- .../assistant}/SKILL.md | 0 .../decision}/SKILL.md | 0 .../decision}/references/block-schema.md | 0 .../references/decision-template.json | 0 .../references/israeli-planning-law-basics.md | 0 .../scripts/create-decision-structure.cjs | 0 .../decision}/scripts/package-lock.json | 0 .../decision}/scripts/package.json | 0 {skill-legal-docx => skills/docx}/SKILL.md | 0 .../docx}/references/document-types.md | 0 .../docx}/scripts/create-legal-doc.js | 0 21 files changed, 224 insertions(+), 316 deletions(-) delete mode 100644 TASKS.md create mode 100644 docs/legal-decision-lessons.md create mode 100644 docs/memory.md delete mode 100644 mcp-server/src/legal_mcp/services/classifier.py rename {skill-legal-assistant => skills/assistant}/SKILL.md (100%) rename {skill-legal-decision => skills/decision}/SKILL.md (100%) rename {skill-legal-decision => skills/decision}/references/block-schema.md (100%) rename {skill-legal-decision => skills/decision}/references/decision-template.json (100%) rename {skill-legal-decision => skills/decision}/references/israeli-planning-law-basics.md (100%) rename {skill-legal-decision => skills/decision}/scripts/create-decision-structure.cjs (100%) rename {skill-legal-decision => skills/decision}/scripts/package-lock.json (100%) rename {skill-legal-decision => skills/decision}/scripts/package.json (100%) rename {skill-legal-docx => skills/docx}/SKILL.md (100%) rename {skill-legal-docx => skills/docx}/references/document-types.md (100%) rename {skill-legal-docx => skills/docx}/scripts/create-legal-doc.js (100%) diff --git a/.gitignore b/.gitignore index 1ff6093..23dc552 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,4 @@ __pycache__/ legacy/ kiryat-yearim/ continuation-prompt.md -memory/ node_modules/ diff --git a/.taskmaster/docs/prd.txt b/.taskmaster/docs/prd.txt index d7f1a17..c754aa4 100644 --- a/.taskmaster/docs/prd.txt +++ b/.taskmaster/docs/prd.txt @@ -128,5 +128,5 @@ Layer 4 (RAG): paragraph_embeddings, case_law_embeddings - MCP server: mcp-server/src/legal_mcp/ - Documentation: docs/ (architecture.md, block-schema.md, migration-plan.md) - Scripts: scripts/ (seed-knowledge.py, seed-appeals.py) -- Style guide: skill-legal-decision/SKILL.md -- Lessons: memory/legal-decision-lessons.md +- Style guide: skills/decision/SKILL.md +- Lessons: docs/legal-decision-lessons.md diff --git a/CLAUDE.md b/CLAUDE.md index aa9a355..65d7b46 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,10 +41,9 @@ | [`docs/architecture.md`](docs/architecture.md) | ארכיטקטורת המערכת, תרשים רכיבים, זרימת נתונים, 4 שכבות DB | לפני עבודה על תשתית | | [`docs/block-schema.md`](docs/block-schema.md) | הגדרת 12 בלוקים — content model, constraints, processing params | **לפני כל כתיבת החלטה** | | [`docs/migration-plan.md`](docs/migration-plan.md) | תוכנית מעבר vault → DB — טבלאות, עדיפויות, כמויות | לפני ייבוא נתונים | -| [`memory/legal-decision-lessons.md`](memory/legal-decision-lessons.md) | לקחים מ-3 החלטות — מה עבד, מה השתנה, ביטויי מעבר חדשים | **לפני כל כתיבת החלטה** | -| [`memory/MEMORY.md`](memory/MEMORY.md) | הקשר כללי — skills, פרויקטים שהושלמו, מבנה vault | להתמצאות כללית | -| [`skill-legal-decision/SKILL.md`](skill-legal-decision/SKILL.md) | מדריך סגנון מלא של דפנה — טון, מבנה, ביטויים, מתודולוגיה | **לפני כל כתיבת החלטה** | -| [`TASKS.md`](TASKS.md) | רשימת משימות המעבר לפי שלבים | מעקב התקדמות | +| [`docs/legal-decision-lessons.md`](docs/legal-decision-lessons.md) | לקחים מ-3 החלטות — מה עבד, מה השתנה, ביטויי מעבר חדשים | **לפני כל כתיבת החלטה** | +| [`docs/memory.md`](docs/memory.md) | הקשר כללי — skills, פרויקטים שהושלמו, מבנה vault | להתמצאות כללית | +| [`skills/decision/SKILL.md`](skills/decision/SKILL.md) | מדריך סגנון מלא של דפנה — טון, מבנה, ביטויים, מתודולוגיה | **לפני כל כתיבת החלטה** | --- @@ -67,29 +66,24 @@ ``` /home/chaim/legal-ai/ ├── CLAUDE.md ← הקובץ הזה -├── TASKS.md ← משימות המעבר -├── docs/ ← תיעוד המערכת +├── Dockerfile ← Docker build +├── docs/ ← תיעוד + לקחים │ ├── architecture.md ארכיטקטורה │ ├── block-schema.md 12 בלוקים (המסמך החשוב ביותר) -│ └── migration-plan.md תוכנית מעבר vault → DB -├── legacy/dafna-tamir/ ← vault מקורי (קריאה בלבד) -│ ├── .claude/skills/ skills מקוריים -│ ├── 01_Projects/ תיקים פעילים + חומרי מקור -│ └── 04_Archive/ תיקים שהושלמו -├── memory/ ← ידע מצטבר מהמערכת הקודמת -│ ├── MEMORY.md אינדקס -│ └── legal-decision-lessons.md לקחים מ-3 החלטות -├── skill-legal-decision/ ← מדריך סגנון + references -├── skill-legal-docx/ ← עיצוב DOCX -├── skill-legal-assistant/ ← קטלוג מסמכים +│ ├── migration-plan.md תוכנית מעבר vault → DB +│ ├── legal-decision-lessons.md לקחים מ-3 החלטות +│ └── memory.md הקשר כללי — skills, פרויקטים +├── skills/ ← כלי עבודה ומדריכים +│ ├── decision/ מדריך סגנון + references + 12 בלוקים +│ ├── assistant/ קטלוג מסמכים +│ └── docx/ עיצוב DOCX ├── data/ │ ├── training/ ← 4 החלטות לאימון (DOCX) │ ├── uploads/ ← קבצים מ-web UI -│ └── cases/ ← תיקי עררים -├── web/ ← קוד ezer-mishpati-web -├── mcp-server/ ← MCP server -├── scripts/ ← סקריפטים -└── docker/ ← Docker configs +│ └── cases/{new,in-progress,completed}/ ← תיקי עררים +├── web/ ← UI + API + integration clients +├── mcp-server/ ← MCP server + services + tools +└── scripts/ ← סקריפטים וכלי עזר ``` --- @@ -115,5 +109,4 @@ 5. **ארכיטקטורת 12 בלוקים** — ראה `docs/block-schema.md` ## יו"ר: עו"ד דפנה תמיר -- מדריך סגנון מלא: `skill-legal-decision/SKILL.md` -- סגנון מקורי (vault): `legacy/dafna-tamir/.claude/skills/legal-decision/SKILL.md` +- מדריך סגנון מלא: `skills/decision/SKILL.md` diff --git a/TASKS.md b/TASKS.md deleted file mode 100644 index 47e2c43..0000000 --- a/TASKS.md +++ /dev/null @@ -1,38 +0,0 @@ -# משימות הקמת המערכת - -## שלב 1: תשתית (Infrastructure) -- [x] יצירת סכמת DB ב-PostgreSQL (4 שכבות, 16 טבלאות) ✅ 2026-03-31 -- [x] אימות pgvector עם embedding — 323 embeddings קיימים, Voyage API מוגדר ✅ 2026-03-31 -- [ ] הגדרת Gitea repository לקוד הפרויקט -- [ ] הגדרת n8n עם workflow בסיסי - -## שלב 2: ייבוא ידע (Knowledge Transfer) -- [x] ייבוא lessons_learned — 15 לקחים מ-3 תיקים ✅ 2026-03-31 -- [x] ייבוא transition_phrases — 44 ביטויי מעבר ✅ 2026-03-31 -- [x] ייבוא case_law — 9 תקדימים ✅ 2026-03-31 -- [x] ייבוא statutory_provisions — 7 הוראות חוק ✅ 2026-03-31 - -## שלב 3: ייבוא תיקים (Appeals Import) -- [x] ייבוא מטאדטה של עררים — 19 תיקים (3 פעילים, 16 ארכיון) ✅ 2026-03-31 -- [ ] ייבוא קטלוג מסמכים (נתיבים, סוגים, תאריכים) -- [ ] ייבוא טענות (לפי צד, לפי ערר) -- [ ] ייבוא בלוקי החלטה (לתיקים שהושלמו: הכט, בית הכרם) - -## שלב 4: RAG & Embeddings -- [x] בחירת מודל embedding — Voyage voyage-3-large (dim=1024) ✅ כבר מוגדר -- [x] יצירת chunks ממסמכי אימון — 323 chunks מ-4 החלטות ✅ כבר קיים -- [ ] הפקת embeddings לפסיקה חדשה ב-case_law -- [ ] בניית חיפוש סמנטי לפסיקה -- [ ] בניית חיפוש סמנטי להחלטות תקדימיות - -## שלב 5: אוטומציה (n8n) -- [ ] workflow: העלאת מסמך → סיווג → אחסון ב-DB -- [ ] workflow: ערר חדש → יצירת מבנה → DOCX -- [ ] workflow: חיפוש תקדימים → RAG → תוצאות -- [ ] workflow: בדיקת טיוטה מול block-schema - -## שלב 6: ממשק משתמש -- [ ] הרחבת ezer-mishpati-web עם ניהול תיקים -- [ ] ממשק כתיבת החלטה -- [ ] ממשק חיפוש תקדימים -- [ ] דשבורד מעקב סטטוס תיקים diff --git a/docs/legal-decision-lessons.md b/docs/legal-decision-lessons.md new file mode 100644 index 0000000..3cfc8cc --- /dev/null +++ b/docs/legal-decision-lessons.md @@ -0,0 +1,163 @@ +# Legal Decision Writing - Lessons Learned + +Lessons extracted by comparing our planning/drafts against Dafna's published final versions. + +## Source +- Published decision: `01_Projects/כתיבת החלטות משפטיות/ערר 1180-1181 הכט/החלטה/הכט 1180-1181.pdf` +- Our draft: `01_Projects/כתיבת החלטות משפטיות/ערר 1180-1181 הכט/החלטה/דיון-והכרעה-טיוטה.md` +- Date: February 2026 + +## What Our Draft Got Right +- Section numbering continuity (no resets) +- "להלן" definitions with bold formatting +- Overall arguments structure (appellants > local committee > permit applicants) +- Citation of relevant case law (שפר, הימנותא, דסטגר) +- Clear separation between parties' arguments + +## What the Published Version Changed + +### 1. Discussion Section Structure +- **Draft:** 6 sub-headers (H2) breaking the discussion into topics +- **Published:** ZERO sub-headers. One continuous flow of numbered paragraphs +- **Lesson:** The discussion reads as a legal essay, not a structured outline + +### 2. Citation Technique +- **Draft:** Each case cited in its own paragraph (7 separate paragraphs for the proprietary claims section) +- **Published:** One massive paragraph (~600 words) citing through ערר נגאח 1011-03-25, which itself consolidated all the case law +- **Lesson:** "Citation through consolidating decision" technique + +### 3. Paragraph Length in Discussion +- **Draft:** Uniform 50-70 words per paragraph +- **Published:** Ranges from 20 to 600+ words. Key citation paragraphs are very long. +- **Lesson:** Don't fragment long legal arguments into tiny chunks + +### 4. Opening Formula +- **Draft:** "לאחר שבחנו את טענות הצדדים... החלטנו שיש לדחות את הערר על הסף" +- **Published:** "לאחר שבחנו... החלטנו בשלב ראשון כי... **אך יחד עם זאת ועל מנת לא לצאת בחסר**... מצאנו להוסיף מספר הערות" +- **Lesson:** The opening promises both conclusion AND elaboration + +### 5. Summary Section +- **Draft:** "סיכום והכרעה" with 5 items (א-ה) +- **Published:** "סיכום" with 6 items (א-ו), more specific language +- **Lesson:** Title is "סיכום", not "סיכום והכרעה" or "סוף דבר" + +### 6. Transition Phrases (new ones discovered) +- "ועל מנת לא לצאת בחסר" - for obiter dicta +- "נציין כי טענות אלו נטענו בלשון רפה" - acknowledging weak claims +- "עינינו הרואות" - summary after long quote +- "נוסיף." - ultra-short transition (one word!) +- "אם כך, לעת הזו" - drawing conclusion from citations +- "למיטב הבנתנו" - cautious position on pending matter +- "נשלים ונציין" - last point before summary + +### 7. New Case Law References (not in our draft) +- ערר (מרכז) 1011-03-25 נגאח עבד אל קאדר (consolidating decision on proprietary claims) +- עע"מ 3975/22 ב. קרן-נכסים (Supreme Court on proprietary feasibility - extensive quote) +- ערר 1071/25 מינץ (own previous decision) +- סעיף 71ב(א)(1) לחוק המקרקעין (majority required for common property changes) + +### 8. Substantive Changes +- Added response from local committee on parking (columns) and tree (sections 29-30) +- Added "על החלטת רשות רישוי מיום 30.11.25" in opening (specific decision date) +- Changed expenses from "no order" to "appellants shall bear expenses" +- Added "ניתנה פה אחד" (unanimous decision) + +## Applied To +- Updated `.claude/skills/legal-decision/SKILL.md` - added Section 7 (Discussion methodology), updated Section 4 (transitions), updated Section 1.3 (structure), updated Section 2.1 (paragraph lengths), updated Section 6 (checklist), updated case law references + +--- + +## Lessons from בית הכרם 1126/25 + 1141/25 + +### Source +- Final version (Draft 9): `04_Archive/ערר-1126-25-תמא-38-בית-הכרם/החלטה/בית הכרם-טיוטת החלטה-9.pdf` +- Our planning: `04_Archive/ערר-1126-25-תמא-38-בית-הכרם/סטטוס-תכנון.md` +- Date: March 2026 +- Result: Partial acceptance (קבלה חלקית) + +### What Our Planning Got Right +- Overall result prediction (partial acceptance, same operational directives) +- Identification of key issues (parking, setback lines, preservation) +- Basic structure (background → arguments → discussion → summary) +- Content of parties' arguments section +- Citation through consolidating decision technique (ערר אדלר) + +### What the Final Version Changed — Critical Gaps + +#### 1. Threshold Question Skipped Entirely +- **Planning:** "שכבה 1 — קריטית: אין זכות ערר לפי ס' 152" +- **Final:** Zero discussion of right to appeal. Straight to substantive analysis. +- **Lesson:** The threshold question (6.1 in skill) is a STRATEGIC TOOL, not mandatory. When the case has strong substantive questions (parking, setback, preservation), Dafna prefers engaging with substance over procedural blocking. This also strengthens the decision against judicial review. + +#### 2. Concentric Circles Model Not Used +- **Planning:** 5 defined layers (threshold → merit → parking → setback → specific claims) +- **Final:** Different structure — context → tension mapping → issue-by-issue analysis → operational conclusions +- **Lesson:** Concentric circles fit REJECTED appeals (like הכט). For partial acceptance, Dafna uses flexible issue-by-issue analysis. The skill's 6.3 is one tool among several, not THE framework. + +#### 3. New Opening Type: "Tension Mapping" +- **Final ס' 39:** Lists 6 specific tensions in bullet points before analysis begins +- **Pattern:** "בערר דנן עולות שאלות כיצד והאם..." → bulleted list of tensions → "כל הנקודות לעיל עומדות לפנינו ולשם כך..." +- **When:** Partial acceptance or cases with multiple complex intersecting issues +- **Not in skill:** This is a new opening type distinct from "broad context" (rejected) or "direct conclusion" (accepted) + +#### 4. "Single Building" Weakens TAMA 38 Interest +- **Final ס' 41:** "עסקינן בחיזוק בית בודד ועל כן... לא קיים באופן מלא אינטרס חיזוק כזה המצדיק את אישור מלוא הזכויות" +- **Not in skill or planning.** New analytical pattern: when TAMA 38 applies to a single house (vs. large apartment building), earthquake protection interest is weaker → more cautious approval of rights, especially setback lines and parking. + +#### 5. Master Plan as "Shield" Against Ad-Hoc Planning Concern +- **Final ס' 42:** "קיימת תכנית אב אשר מקלה על בחינת הבקשה... החשש לאישור היתר מכח תכנית 10038 על מגרש בודד ללא ראיה כללית אינו קיים" +- **Pattern:** When a master plan exists → cite it to validate individual permit → conclusion: permit "integrates with existing comprehensive vision" rather than creating ad-hoc precedent. + +#### 6. Depth of Plan Provision Citations +- **Planning:** Expected general parking analysis +- **Final:** Extensive direct quotes from plan provisions (6.8(4), 6.8(9), traffic appendix, 5166b) — 400+ words of plan citations with interleaved analysis +- **Lesson:** For parking/infrastructure issues, Dafna goes very deep into plan provisions with direct quotes, not summaries. + +#### 7. Ultra-Minimal Summary for Partial Acceptance +- **Planning:** ~1,000 words, 8 reasons, expenses, warm closing +- **Final:** 3 short sections (ס' 84-86) — conclusion + 2 operational directives. No expenses. No warm closing. +- **Lesson:** In partial acceptance, all reasoning is already in the discussion. Summary = operational directives only. + +#### 8. Precedents — Planned vs. Actually Used +| Planned but dropped | Added unexpectedly | +|---|---| +| חנין, נחמיאס (right to appeal) | ערר 1192/18 אילן (preservation + nuisance) | +| הלכת שפר (deviation from plan) | ערר מובשוביץ 1009-02-24 (urban renewal — ~400 word quote) | +| ערר כהן (no delaying permit) | ערר ארד 1156/18 (construction nuisance) | +| עניין שיק (neighborhood change) | ערר זוהר 1169/19 (same topic) | + +#### 9. New Transition Phrases Discovered +- "הדברים משליכים על שיקול הדעת ב..." — linking finding to conclusion +- "רוצה לומר כי" — alternative phrasing/explanation +- "נוצר מצב בו" — presenting factual situation/problem +- "לכך נוסיף כי" — adding another layer +- "יש אולי להצר על כך ש..." — gentle critical remark +- "עם ההבנה לטענה זו של העוררים, אין בידנו לקבלה" — soft acknowledge-reject + +### Meta-Lesson +Our skill was "over-indexed" on one case type (הכט = rejected appeal). The concentric circles model, threshold question as mandatory, and warm closing were all patterns from that single case. Beit HaKerem (partial acceptance) reveals that Dafna's approach is more flexible than we captured. We now have two data points — need to distinguish between patterns that are universal vs. result-dependent. + +### Applied To +- Updated `.claude/skills/legal-decision/SKILL.md` — added partial acceptance track (7.2, 7.3, 8.4), caveats to 6.1/6.3, new analytical patterns (6.10, 6.11), new golden ratios (3.2), new transition phrases (5.2) + +--- + +## Lessons from קרית יערים-1 Structure Building (March 2026) + +### Source +- Structure draft: `01_Projects/כתיבת החלטות משפטיות/ערר קרית יערים-1/החלטה/החלטה-ערר-1130-25-מבנה.docx` +- Reference decisions: בית הכרם (Dafna), ARAR-24-1078-44 (Arieli) +- Date: March 2026 + +### 10. "Neutral Background" Rule +- **Problem:** First draft put detailed 2017 district committee quotes ("נולד חטא", "חריג לסביבתו", "לא בדיוק המקום הזה") in the Background section. +- **Chaim's correction:** These are parties' arguments disguised as background. The background was "revealing cards" before the parties spoke — effectively summarizing the case before presenting it. +- **Rule:** Background (Block ו) = objective facts only. Test: "Does this sentence contain a direct quote from a party, or value/judgment words (חריג, חטא, בעייתי)?" If yes → belongs in Claims (Block ז) or Discussion (Block י), not Background. Prior decisions cited as dry fact ("rejected on date X") — reasoning, quotes, and interpretations appear only in claims/discussion. +- **Applied to:** SKILL.md section 11.2 Block ו, added "⚠️ כלל רקע ניטרלי" + +### 11. New 12-Block Decision Structure +- Created formal 12-block structure based on analysis of Beit HaKerem + Arieli decisions +- Added mandatory "pre-discussion draft" step (Block 12 in SKILL.md) +- Created `create-decision-structure.cjs` script for generating structure DOCX +- Key innovation from Arieli: "ההליכים בפני ועדת הערר" as separate section (Block ח) +- "Judge Test": every block written as if administrative court judge reads cold diff --git a/docs/memory.md b/docs/memory.md new file mode 100644 index 0000000..1ecc0f5 --- /dev/null +++ b/docs/memory.md @@ -0,0 +1,39 @@ +# Memory - Dafna Tamir Vault + +## Project Context +- This is an **Obsidian vault** for legal work - writing decisions for planning appeals committee (ועדת ערר לתכנון ובניה, מחוז ירושלים) +- Chair: Adv. Dafna Tamir +- Three areas: **היטל השבחה** (betterment levy), **רישוי ובנייה** (licensing/building permits), and **פיצויים** (compensation under section 197) + +## Key Skills (2 active, consolidated 2026-02-07) +- `legal-decision` - Main skill: style guide + analytical methodology + workflow. Updated 2026-03-21 with Beit HaKerem lessons: partial acceptance track (7.2/7.3/8.4), threshold question caveat (6.1), concentric circles flexibility (6.3), single-building analysis (6.10), master plan shield (6.11), new transition phrases, golden ratios for partial acceptance. +- `legal-assistant` - For cataloging case files and creating timelines +- Pipeline: **legal-assistant** (prep) → **legal-decision** (write) +- 5 analysis skills archived in `.claude/skills/_archive/` (ניתוח-סגנון, ניתוח-רטוריקה, ניתוח-מבנה, גישה-שיפוטית, קטלוג-החלטות) +- 4 duplicate/obsolete skills deleted (כותב-החלטות-תמיר, עוזר-כתיבת-החלטות, עוזר-תכנון-החלטות, docx-exporter) + +## Critical Lessons Learned +See [legal-decision-lessons.md](legal-decision-lessons.md) for full details (הכט + בית הכרם). + +### From הכט 1180-1181 (rejected, 02.2026): +1. **DO NOT use sub-headers in Discussion** - continuous essay +2. **DO NOT split long citations** - 200-600 word blocks OK +3. **Summary title is "סיכום"** +4. **"Citation Through Consolidating Decision"** pattern + +### From בית הכרם 1126/25 (partial acceptance, 03.2026): +1. **Threshold question (ס' 152) is OPTIONAL** - skip when strong substantive issues exist +2. **Concentric circles = rejected appeals only** — partial acceptance uses issue-by-issue analysis +3. **New opening type: "tension mapping"** — list 4-6 tensions before analysis +4. **"Single building" weakens TAMA 38 interest** — more cautious approval +5. **Summary = ultra-minimal** (2-3 operational directives, no reasoning repetition, no expenses) + +## Current/Next Projects +- **Active:** ערר קרית יערים-1 (בתיקיית כתיבת החלטות משפטיות) + +## Archived Projects +- **Completed:** ערר הכט 1180-1181 (published 05.02.2026). דחייה. +- **Completed:** ערר בית הכרם 1126/25 + 1141/25 תמ"א 38 (גרסה סופית - טיוטה 9, מרץ 2026). קבלה חלקית. +- **Archived:** ערר 8107-25 אבו זאהריה (היטל השבחה) - archived 24.03.2026. החלטה מאחדת: ערר גפני. +- **Archived:** ערר רמת שלמה 9005-24 (פיצויים ס' 197) - archived 24.03.2026. החלטה מאחדת: ערר ורדי 9003-23. +- **Archived:** ערר רישוי 1184-25, ערר 1200-25, ערר 8070-25, ערר 1195-25 (archived 24.03.2026) diff --git a/docs/migration-plan.md b/docs/migration-plan.md index 8386dcd..ba42f0e 100644 --- a/docs/migration-plan.md +++ b/docs/migration-plan.md @@ -15,7 +15,7 @@ ### Knowledge (Priority 1 — enables RAG immediately) | Source | Target Table | Records | |--------|-------------|---------| -| memory/legal-decision-lessons.md | lessons_learned | ~12 lessons | +| docs/legal-decision-lessons.md | lessons_learned | ~12 lessons | | SKILL.md section 5.2 | transition_phrases | ~30 phrases | | Published decisions (citations) | case_law | ~20 cases | | SKILL.md section 6.9 | statutory_provisions | ~10 statutes | diff --git a/mcp-server/src/legal_mcp/services/classifier.py b/mcp-server/src/legal_mcp/services/classifier.py deleted file mode 100644 index 8707d0d..0000000 --- a/mcp-server/src/legal_mcp/services/classifier.py +++ /dev/null @@ -1,248 +0,0 @@ -"""סיווג אוטומטי של מסמכים וזיהוי צדדים. - -שלוש פונקציות: -1. classify_document — סיווג סוג מסמך (ערר/תשובה/פרוטוקול/...) -2. identify_parties — זיהוי צדדים (עוררים, משיבים, ועדה, מבקשי היתר) -3. detect_appeal_type — זיהוי סוג ערר לפי מספר תיק -""" - -from __future__ import annotations - -import logging -import re - -import anthropic - -from legal_mcp import config -from legal_mcp.config import parse_llm_json - -logger = logging.getLogger(__name__) - -_anthropic_client: anthropic.Anthropic | None = None - - -def _get_anthropic() -> anthropic.Anthropic: - global _anthropic_client - if _anthropic_client is None: - _anthropic_client = anthropic.Anthropic(api_key=config.ANTHROPIC_API_KEY) - return _anthropic_client - - -# ── סיווג סוג מסמך ────────────────────────────────────────────────── - -DOC_TYPES = { - "appeal": "כתב ערר", - "response": "תשובה / כתב תשובה", - "protocol": "פרוטוקול דיון", - "plan": "תכנית (תב\"ע)", - "permit": "היתר בנייה", - "court_decision": "פסק דין / החלטת בית משפט", - "decision": "החלטת ועדה", - "appraisal": "שומה / חוות דעת שמאית", - "objection": "התנגדות", - "exhibit": "נספח / מסמך תומך", - "reference": "מסמך עזר אחר", -} - -CLASSIFY_PROMPT = """אתה מסווג מסמכים משפטיים בתחום תכנון ובניה. - -קרא את תחילת המסמך וסווג אותו לאחד מהסוגים הבאים: -- appeal — כתב ערר (מוגש לוועדת ערר) -- response — כתב תשובה (תגובת הצד שכנגד או הוועדה המקומית) -- protocol — פרוטוקול דיון (רישום מדיון שהתקיים) -- plan — תכנית (תב"ע, תכנית מתאר, תכנית מפורטת) -- permit — היתר בנייה (או בקשה להיתר) -- court_decision — פסק דין או החלטה של בית משפט -- decision — החלטת ועדה מקומית או ועדת ערר -- appraisal — שומה או חוות דעת שמאית -- objection — התנגדות (לתכנית, להיתר) -- exhibit — נספח או מסמך תומך -- reference — מסמך עזר אחר - -החזר JSON בלבד בפורמט: -{"doc_type": "...", "confidence": 0.0-1.0, "reasoning": "הסבר קצר"} -""" - -PARTIES_PROMPT = """אתה מנתח מסמכים משפטיים בתחום תכנון ובניה. - -קרא את המסמך וזהה את הצדדים המעורבים. חפש: -- עוררים (appellants) — מי שמגיש את הערר -- משיבים (respondents) — הצד שכנגד (לרוב ועדה מקומית, או מבקש היתר) -- ועדה מקומית (committee) — שם הוועדה המקומית -- מבקשי היתר (permit_applicants) — מי שביקש את ההיתר (אם שונה מהעוררים/משיבים) - -החזר JSON בלבד בפורמט: -{ - "appellants": ["שם1", "שם2"], - "respondents": ["שם1", "שם2"], - "committee": "שם הוועדה המקומית (אם מצוין)", - "permit_applicants": ["שם1"], - "confidence": 0.0-1.0 -} - -אם לא ניתן לזהות צד מסוים, החזר רשימה ריקה. אל תמציא שמות. -""" - - -async def classify_document(text: str) -> dict: - """סיווג סוג מסמך על בסיס הטקסט. - - Args: - text: טקסט המסמך (מספיק 3000 תווים ראשונים) - - Returns: - dict עם doc_type, confidence, reasoning - """ - # Use first 3000 chars — usually enough for headers and intro - sample = text[:3000] - - client = _get_anthropic() - message = client.messages.create( - model="claude-sonnet-4-20250514", - max_tokens=512, - messages=[ - { - "role": "user", - "content": f"{CLASSIFY_PROMPT}\n\n--- תחילת מסמך ---\n{sample}\n--- סוף דגימה ---", - } - ], - ) - - raw = message.content[0].text.strip() - result = parse_llm_json(raw) - if result is None: - logger.warning("Failed to parse classification response: %s", raw) - return {"doc_type": "reference", "confidence": 0.0, "reasoning": "סיווג נכשל"} - - # Validate doc_type - if result.get("doc_type") not in DOC_TYPES: - result["doc_type"] = "reference" - result["confidence"] = 0.0 - - return result - - -async def identify_parties(text: str) -> dict: - """זיהוי צדדים מתוך טקסט מסמך. - - Args: - text: טקסט המסמך (מספיק 5000 תווים ראשונים) - - Returns: - dict עם appellants, respondents, committee, permit_applicants, confidence - """ - # Use first 5000 chars — parties usually in header/intro - sample = text[:5000] - - client = _get_anthropic() - message = client.messages.create( - model="claude-sonnet-4-20250514", - max_tokens=512, - messages=[ - { - "role": "user", - "content": f"{PARTIES_PROMPT}\n\n--- תחילת מסמך ---\n{sample}\n--- סוף דגימה ---", - } - ], - ) - - raw = message.content[0].text.strip() - result = parse_llm_json(raw) - if result is None: - logger.warning("Failed to parse parties response: %s", raw) - return { - "appellants": [], - "respondents": [], - "committee": "", - "permit_applicants": [], - "confidence": 0.0, - } - - # Normalize structure - return { - "appellants": result.get("appellants", []), - "respondents": result.get("respondents", []), - "committee": result.get("committee", ""), - "permit_applicants": result.get("permit_applicants", []), - "confidence": result.get("confidence", 0.0), - } - - -# ── זיהוי סוג ערר לפי מספר תיק ───────────────────────────────────── - -APPEAL_TYPES = { - "licensing": "רישוי ובנייה", # 1xxx - "betterment": "היטל השבחה", # 8xxx - "compensation": "פיצויים (ס' 197)", # 9xxx -} - - -def detect_appeal_type(case_number: str) -> dict: - """זיהוי סוג ערר לפי מספר תיק. - - Convention: - 1xxx = רישוי ובנייה - 8xxx = היטל השבחה - 9xxx = פיצויים (ס' 197) - - Args: - case_number: מספר תיק (e.g. "1078-24", "8042-23", "9015-22") - - Returns: - dict עם appeal_type, appeal_type_hebrew, confidence - """ - # Extract the numeric prefix before any dash/slash - match = re.match(r"(\d+)", case_number.strip()) - if not match: - return { - "appeal_type": "", - "appeal_type_hebrew": "", - "confidence": 0.0, - } - - num = int(match.group(1)) - first_digit = str(num)[0] if num > 0 else "" - - if first_digit == "1": - appeal_type = "licensing" - elif first_digit == "8": - appeal_type = "betterment" - elif first_digit == "9": - appeal_type = "compensation" - else: - return { - "appeal_type": "", - "appeal_type_hebrew": "", - "confidence": 0.5, - } - - return { - "appeal_type": appeal_type, - "appeal_type_hebrew": APPEAL_TYPES[appeal_type], - "confidence": 1.0, - } - - -async def classify_and_identify(text: str, case_number: str = "") -> dict: - """סיווג מלא: סוג מסמך + צדדים + סוג ערר. - - Args: - text: טקסט המסמך - case_number: מספר תיק (אופציונלי, לזיהוי סוג ערר) - - Returns: - dict עם classification, parties, appeal_type - """ - classification = await classify_document(text) - parties = await identify_parties(text) - appeal_type = detect_appeal_type(case_number) if case_number else { - "appeal_type": "", - "appeal_type_hebrew": "", - "confidence": 0.0, - } - - return { - "classification": classification, - "parties": parties, - "appeal_type": appeal_type, - } diff --git a/scripts/export-decision-docx.py b/scripts/export-decision-docx.py index 2fef2bd..e4c48d3 100644 --- a/scripts/export-decision-docx.py +++ b/scripts/export-decision-docx.py @@ -17,7 +17,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent / "mcp-server" / "src")) from legal_mcp.services.db import get_pool, init_schema, close_pool -CJS_SCRIPT = Path(__file__).parent.parent / "skill-legal-decision" / "scripts" / "create-decision-structure.cjs" +CJS_SCRIPT = Path(__file__).parent.parent / "skills" / "decision" / "scripts" / "create-decision-structure.cjs" def block_id_to_hebrew(block_id: str) -> str: diff --git a/scripts/seed-knowledge.py b/scripts/seed-knowledge.py index 67a171b..93a8784 100644 --- a/scripts/seed-knowledge.py +++ b/scripts/seed-knowledge.py @@ -2,7 +2,7 @@ """Seed knowledge tables from legacy vault data. Imports: lessons_learned, transition_phrases, case_law, statutory_provisions. -Sources: memory/legal-decision-lessons.md, skill-legal-decision/SKILL.md +Sources: docs/legal-decision-lessons.md, skills/decision/SKILL.md """ import asyncio diff --git a/skill-legal-assistant/SKILL.md b/skills/assistant/SKILL.md similarity index 100% rename from skill-legal-assistant/SKILL.md rename to skills/assistant/SKILL.md diff --git a/skill-legal-decision/SKILL.md b/skills/decision/SKILL.md similarity index 100% rename from skill-legal-decision/SKILL.md rename to skills/decision/SKILL.md diff --git a/skill-legal-decision/references/block-schema.md b/skills/decision/references/block-schema.md similarity index 100% rename from skill-legal-decision/references/block-schema.md rename to skills/decision/references/block-schema.md diff --git a/skill-legal-decision/references/decision-template.json b/skills/decision/references/decision-template.json similarity index 100% rename from skill-legal-decision/references/decision-template.json rename to skills/decision/references/decision-template.json diff --git a/skill-legal-decision/references/israeli-planning-law-basics.md b/skills/decision/references/israeli-planning-law-basics.md similarity index 100% rename from skill-legal-decision/references/israeli-planning-law-basics.md rename to skills/decision/references/israeli-planning-law-basics.md diff --git a/skill-legal-decision/scripts/create-decision-structure.cjs b/skills/decision/scripts/create-decision-structure.cjs similarity index 100% rename from skill-legal-decision/scripts/create-decision-structure.cjs rename to skills/decision/scripts/create-decision-structure.cjs diff --git a/skill-legal-decision/scripts/package-lock.json b/skills/decision/scripts/package-lock.json similarity index 100% rename from skill-legal-decision/scripts/package-lock.json rename to skills/decision/scripts/package-lock.json diff --git a/skill-legal-decision/scripts/package.json b/skills/decision/scripts/package.json similarity index 100% rename from skill-legal-decision/scripts/package.json rename to skills/decision/scripts/package.json diff --git a/skill-legal-docx/SKILL.md b/skills/docx/SKILL.md similarity index 100% rename from skill-legal-docx/SKILL.md rename to skills/docx/SKILL.md diff --git a/skill-legal-docx/references/document-types.md b/skills/docx/references/document-types.md similarity index 100% rename from skill-legal-docx/references/document-types.md rename to skills/docx/references/document-types.md diff --git a/skill-legal-docx/scripts/create-legal-doc.js b/skills/docx/scripts/create-legal-doc.js similarity index 100% rename from skill-legal-docx/scripts/create-legal-doc.js rename to skills/docx/scripts/create-legal-doc.js