--- name: dafna-decision-template description: > ייצוא מסמכי DOCX עבור ועדת ערר לתכנון ובניה מחוז ירושלים (יו"ר עו"ד דפנה תמיר), באמצעות שימוש בסגנונות המוגדרים בטמפלט Word של דפנה (`טיוטת החלטה.dotx`). הסקיל מחיל את סגנונות הטמפלט (Normal/Heading 1/Heading 2/Quote/List Paragraph) על תוכן שנכתב מתוכנתית — בלי להגדיר פונט/גודל/RTL/שוליים ידנית. טריגרים: "ייצוא החלטה", "ייצוא ניתוח משפטי", "DOCX של דפנה", "טמפלט החלטה", "סגנונות החלטה", "Word עם David", "מסמך ועדת ערר", "הורדת החלטה", "פסקה ממוספרת בעברית", "(א) (ב) (ג)", כל בקשה להוציא מסמך Word המבוסס על טמפלט דפנה. --- # Dafna Decision Template — ייצוא DOCX מסגנונות טמפלט ## מה זה עושה סקיל זה הוא **layer דק מעל `python-docx`** שמטעין את הטמפלט של דפנה ([skills/docx/decision_template.docx](../docx/decision_template.docx) — מומר מ-`data/training/טיוטת החלטה.dotx`) וכותב תוכן חדש על בסיסו, **על ידי שיוך שמות סגנונות בלבד** (`paragraph.style = "Heading 2"`). העיצוב — פונט David, RTL, גדלים, הזחות, מספור אוטומטי — מגיע מה-`styles.xml` של הטמפלט. השירות המעשי נמצא ב- [`mcp-server/src/legal_mcp/services/analysis_docx_exporter.py`](../../mcp-server/src/legal_mcp/services/analysis_docx_exporter.py). הסקיל מתעד את **הכללים** שה-service מיישם, כך שניתן לשחזר/להרחיב אותם בסקריפטים אחרים ללא צורך לגלות הכל מחדש. --- ## 🔴 קריטי — 5 עקרונות שחייבים לזכור ### 1. **לא להגדיר font/size/indent ידנית** — תמיד style ```python # ❌ אל run.font.name = "David"; run.font.size = Pt(13) paragraph.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.RIGHT # ✅ כן paragraph = doc.add_paragraph(style="Normal") # כל השאר מגיע מהטמפלט ``` ### 2. **RTL חייב דגלים ב-paragraph וב-run — גם אם הסגנון כולל bidi** ```python # ❌ אל — עברית תצא ב-Times New Roman כי Word לא יודע שזה complex-script p = doc.add_paragraph(style="Normal") p.add_run("טקסט בעברית") # ✅ כן — מסמנים את ה-run כ-RTL p = doc.add_paragraph(style="Normal") _mark_paragraph_rtl(p) run = p.add_run("טקסט בעברית") _mark_run_rtl(run) # ← מוסיף ל-rPr ``` בלי הדגל הזה, Word נופל בחזרה ל-`ascii` font (Times New Roman) במקום ל-`cs` font (David). זו הסיבה הנפוצה ביותר לתוצאה "עברית ב-Times New Roman". ראה [references/rtl-runs.md](references/rtl-runs.md) לפרטים מלאים. ### 3. **`.dotx` לא נטען ישירות** — יש להמיר ל-`.docx` פעם אחת python-docx פותח רק `.docx`. להמרה: `scripts/convert_decision_template.py` (בשורש הפרויקט). יש להסיר: - `word/glossary/*` parts - Override entries שמצביעים אליהם ב-`[Content_Types].xml` - Relationship `glossaryDocument` ב-`word/_rels/document.xml.rels` - להחליף content-type מ-`...template.main+xml` ל-`...document.main+xml` ראה [references/dotx-to-docx.md](references/dotx-to-docx.md). ### 4. **Title לא טוב ככותרת עברית** — השתמש ב-Heading 1 הסגנון `Title` בטמפלט מפנה ל-theme fonts (`majorFont`). ב-theme1.xml: `majorFont.latin = "Aptos Display"`, `majorFont.cs = ""` (ריק). לכן עברית תרונדר ב-Latin fallback. `Heading 1` יורש cs="David" מ-`Normal` — השתמש בו לכותרת ראשית. ### 5. **מספור אוטומטי רק ב-`List Paragraph`** — decimal בלבד `List Paragraph` (styleId `a0`) מקושר ל-`numId=1 → numFmt=decimal`. כלומר Word יוסיף אוטומטית "1.", "2.", "3." לכל פסקה עם הסגנון הזה. - שורות שמתחילות ב-`N.` → הסר את המספר מהטקסט, החל `List Paragraph`. - שורות שמתחילות ב-`(א)` `(ב)` → השתמש ב-`List Paragraph` **עם הסרת ``**, כי המספור בעברית נכתב בעצמו על ידי המחבר. - Bullets (`- `, `• `) → הסר את הסימן, השאר `Normal`. ראה [references/style-mapping.md](references/style-mapping.md). --- ## הטמפלט — מיפוי סגנונות מיפוי מלא של הסגנונות בטמפלט ל-content type. זה ה"חוזה" של הסקיל — כל שינוי דרך השירות צריך להיצמד אליו. | תוכן | style name | הערה | |------|-----------|------| | כותרת מסמך ("ניתוח משפטי וכתיבת עמדה בערר X") | `Heading 1` | יורש cs="David" | | כותרת מקטע ראשי (רקע דיוני, פסיקה כללית, סוגיות להכרעה, מסקנות) | `Heading 2` | bold + underline | | כותרת משנה בתוך סוגיה (טענה (claim), תשובה, ניתוח, נקודות פתוחות, …) | `Heading 2` | | | שם subsection (טענת סף 1, סוגיה 2) | `Normal` + bold run | | | פסקת רקע רגילה | `Normal` | David 13pt, justify, RTL | | פסקת רשימה ממוספרת (1., 2., 3.) | `List Paragraph` | Word ימספר | | פסקת רשימה בעברית ((א), (ב)) | `List Paragraph` + `_strip_numpr()` | המספור נשאר בטקסט | | ציטוט פסיקה | `Quote` | bold + הזחה | | citation / מקור | `Normal` + italic | | ראה [references/style-mapping.md](references/style-mapping.md) לטבלה מורחבת עם ה-XML של כל סגנון. --- ## תוכן המקור — `analysis-and-research.md` הקובץ נכתב על ידי `legal-analyst` agent. מבנה מצופה: ```markdown # ניתוח משפטי וכתיבת עמדה — ערר {case_number} תאריך: DD.MM.YYYY ## רקע דיוני {prose content} ## עובדות מוסכמות 1. ... ## עובדות שנויות במחלוקת 1. ... ## טענות סף ### טענה {n}: {title} **עמדת המבקשת:** ... **עמדת ועדת הערר:** [ימולא ע"י יו"ר הוועדה] ## סוגיות להכרעה ### סוגיה {n}: {title} **ממצאים עובדתיים:** ... **טענה (claim):** העורר טוען כי: (א) ... (ב) ... **ניתוח:** ... - **נקודות פתוחות:** 1. ... - **הערכה ראשונית:** {prose} **עמדת ועדת הערר:** [ימולא ע"י יו"ר הוועדה] ## מסקנות ... ``` ה-parser (`research_md.py`) חולק את זה ל-`threshold_claims[]`, `issues[]`, prose sections, ו-`conclusions`. חשוב: **שמות sections חייבים להכיל את המילים המופתח** (`רקע דיוני`, `טענות סף`, …) — ה-parser עובד לפי matching של keywords, לא לפי מספר ה-H2. --- ## זרימת הייצוא סדר המקטעים ב-DOCX (גם אם סדר ה-H2 ב-MD שונה): 1. **כותרת** (Heading 1) + שורת תאריך 2. **רקע** (Heading 2) — `represented_party`, `procedural_background`, `agreed_facts`, `disputed_facts` (אם קיימים) 3. **פסיקה כללית** (Heading 2) — `case_precedents` עם `section_id=NULL` 4. **טענות סף** (Heading 2) — לכל subsection: title, fields, chair_position, precedents 5. **סוגיות להכרעה** (Heading 2) — אותה חלוקה 6. **מסקנות** (Heading 2) — בסוף הסיבה: בקריאה משפטית נכון להציג תחילה רקע ועובדות, ואז את הדיון. פסיקה כללית מופיעה לפני הסוגיות כי היא רוחבית. --- ## עיבוד שורות — `_classify_line()` ה-service מפרש כל שורה של content לאחת מ-6 קטגוריות: | kind | דוגמה | מה קורה | |------|--------|---------| | `label_heading` | `**נקודות פתוחות:**` (שורה שלמה, כולל `- **X:**`) | Heading 2 | | `label_heading` (plain) | `העורר טוען כי:` (שורה קצרה שמסתיימת ב-`:`) | Heading 2 | | `inline_label` | `**שאלה עקרונית:** מה...` | Normal עם label bold inline | | `numbered` | `1. הנספח אינו מחייב` | List Paragraph, המספר מוסר | | `bullet` | `- nevo (קלאסי)...` | Normal, הסימן מוסר | | `heb_letter` | `(א) הנספח אינו...` | List Paragraph + strip numPr | | `plain` | רגיל | Normal | בנוסף, **inline `**...**`** מעובד בכל ריצה דרך `_add_runs_with_inline_bold` — כל `**word**` הופך ל-run נפרד עם `bold=True`. ראה [references/line-classification.md](references/line-classification.md). --- ## מקפים — מדיניות המשתמש (דפנה) ביקשה: **"לא רוצה מקפים בכלל"**. הסקיל מסיר: - `—` (em-dash, U+2014) - `–` (en-dash, U+2013) מכל טקסט שהקוד כותב למסמך (גם תוכן מהמקור). מקפים רגילים (`-`) נשמרים. הפונקציה: `_no_dash()`. --- ## שדות ריקים — placeholder שדה `chair_position` (עמדת ועדת הערר) שמכיל אחד מהסימנים הריקים (`[ימולא ע"י יו"ר הוועדה]`, `[טרם מולא]`, וכד') → מוחלף ב- `[טרם מולאה עמדת ועדת הערר]` בסגנון italic. זה סימן ויזואלי ברור שנשאר עדיין להשלים. --- ## שימוש — API ```python from legal_mcp.services.analysis_docx_exporter import build_analysis_docx path = await build_analysis_docx("8070-25") # → data/cases/8070-25/exports/ניתוח-משפטי-v{N}.docx ``` Endpoint ציבורי: `GET /api/cases/{case_number}/research/analysis/export-docx` --- ## התמודדות עם בעיות נפוצות ### "עברית יוצאת ב-Times New Roman" - חסר `` ב-run. הוסף `_mark_run_rtl(run)` אחרי כל `add_run`. - בדוק: הסגנון שאתה משתמש בו יש בו `cs="David"` (או יורש מ-Normal שיש לו)? ### "המספור כפול: '1. (א) ...'" - אתה משתמש ב-`List Paragraph` על שורה עם `(א)`. צריך `_strip_numpr(para)`. ### "כוכביות `**...**` מופיעות במסמך" - הקפד להעביר תוכן דרך `_add_runs_with_inline_bold()`, לא `paragraph.add_run()`. ### "התבנית לא נטענת" - הרץ מחדש `python scripts/convert_decision_template.py`. בדוק שה-docx שנוצר פותחיb ב-Word ללא שגיאות. ### "המספור ברשימה השנייה ממשיך מהראשונה (4,5,6 במקום 1,2,3)" - ידוע. הפתרון: להוסיף override של `numId` ברמת ה-paragraph הראשון של הרשימה החדשה. עדיין לא מיושם — ראה "שיפורים עתידיים". --- ## שיפורים עתידיים (TODO) - [ ] Reset של מספור List Paragraph בין רשימות נפרדות (לא רציף). - [ ] תמיכה ב-`פיסקת רשימה - ללא מספור` (styleId `-`) לbullets. - [ ] עיצוב מותאם לסוג הערר (1xxx/8xxx/9xxx) — כרגע אחיד. - [ ] אפשרות להוריד רק מקטעים נבחרים (רק טענות סף, רק מסקנות, וכו'). --- ## מבנה קבצים ``` skills/dafna-decision-template/ ├── SKILL.md ← הקובץ הזה └── references/ ├── dotx-to-docx.md ← איך ממירים .dotx ל-.docx ├── rtl-runs.md ← למה `` חשוב בכל run ├── style-mapping.md ← מיפוי מלא של סגנונות הטמפלט └── line-classification.md ← לוגיקת _classify_line() mcp-server/src/legal_mcp/services/ └── analysis_docx_exporter.py ← המימוש המעשי scripts/ └── convert_decision_template.py ← המרת dotx → docx (חד-פעמי) skills/docx/ └── decision_template.docx ← הטמפלט המומר (artifact) ``` --- ## היסטוריה | גרסה | תאריך | שינוי | |-------|-------|-------| | v1.0 | 2026-04-16 | יצירת הסקיל. מיפוי ראשוני של סגנונות, תמיכה ב-RTL runs, inline bold, (א)(ב), Heading 1/2, מקטעי רקע. |