# System Architecture — Legal Decision Assistant

> עודכן: 2026-04-16 — הוספת ארכיטקטורת Track Changes לעריכת טיוטות

## רכיבי המערכת

```
┌───────────────────────────────────────────────────────────────┐
│                      Nautilus Server                          │
│                      158.178.131.193                          │
│                                                               │
│  ┌──────────────────────────────────────────────────────┐    │
│  │ legal-ai container (Coolify UUID: gyjo0mtw2c42ej3...) │    │
│  │   ┌────────────┐    ┌──────────────────────────┐     │    │
│  │   │ Next.js UI │    │ FastAPI backend           │    │    │
│  │   │  :3000     │◄──►│  :8000 (internal)         │    │    │
│  │   └────────────┘    │  + MCP server             │    │    │
│  │                     └──────────────────────────┘     │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                               │
│  ┌──────────────────┐  ┌──────────────────────────┐           │
│  │ PostgreSQL +     │  │ Redis                     │           │
│  │ pgvector (1024D) │  │ (task queue)              │           │
│  │ legal-ai-postgres│  │ legal-ai-redis            │           │
│  └──────────────────┘  └──────────────────────────┘           │
│                                                               │
│  ┌──────────────┐  ┌──────────────────────────┐               │
│  │ Gitea         │  │ Traefik (SSL + routing)  │               │
│  │ (code + cases)│  │ (*.nautilus.marcusgroup) │               │
│  └──────────────┘  └──────────────────────────┘               │
└───────────────────────────────────────────────────────────────┘

Local (developer machine, pm2):
┌──────────────────────────────────────────────────────────────┐
│  Paperclip — agent orchestrator                              │
│  localhost:3100, DB localhost:54329                          │
│  Runs Claude Code agents: legal-ceo, legal-writer,           │
│  legal-exporter, legal-researcher, legal-qa, legal-proofreader│
└──────────────────────────────────────────────────────────────┘

External:
  ← Claude API (Opus 4.7 for agents)
  ← Voyage AI (voyage-3, 1024-dim embeddings)
  ← Infisical (secret management)
  ← Gmail SMTP (agent notifications)
```

---

## הזרימה המלאה — מהעלאת מסמכים ועד טיוטה סופית

### שלב 1 — יצירת תיק + העלאת מסמכי מקור

**מה קורה:**
1. חיים יוצר תיק דרך UI (`/cases/new`) — מקבל `case_number` (1xxx = CMP, 8xxx/9xxx = CMPA)
2. מעלה PDFs/DOCX: כתב ערר, תשובה, פרוטוקול, תכניות, היתר, פסיקה
3. ה-backend:
   - שומר קובץ ב-`data/cases/{case_number}/documents/originals/`
   - מפעיל OCR (Google Vision) אם PDF ללא טקסט
   - מריץ proofreader להסרת artifacts מ-Nevo
   - מחלץ טקסט ל-`documents.extracted_text`
   - מפצל ל-chunks של ~500 מילים, מחשב embeddings (voyage-3, 1024D), שומר ב-`document_chunks`
4. סטטוס תיק: `new` → `proofread`

### שלב 2 — ניתוח משפטי (legal-researcher + analyst)

**מי רץ:** סוכני Paperclip (מתוזמרים ע"י legal-ceo).

1. **legal-proofreader** — מנקה את המסמכים אחרי OCR
2. **legal-researcher** — מפה תכניות, תקדימים, חקיקה רלוונטית. שומר `research_md`
3. **analyst (legal-researcher pass 1)** — מחלץ טענות (`extract_claims`), ממפה סוגיות, בודק שלמות

סטטוס: `proofread` → `documents_ready` → `analyst_verified`

### שלב 3 — החלטת תוצאה + כיוונים (CEO + חיים)

1. **legal-ceo** מציג סיכום לחיים: סיווג, טענות, פסיקה רלוונטית, שאלות מפתח
2. חיים בוחר תוצאה (דחייה/קבלה חלקית/קבלה מלאה)
3. CEO מציג 2-3 **כיוונים סילוגיסטיים** לנימוק
4. חיים מאשר כיוון

סטטוס: `analyst_verified` → `outcome_set` → `direction_approved`

### שלב 4 — ניתוח מעמיק (analyst pass 2)

legal-researcher (תפקיד analyst) מעמיק בפסיקה ובחקיקה על בסיס הכיוון שאושר, מאמת ציטוטים מדויקים.

סטטוס: `direction_approved` → `analysis_enriched`

### שלב 5 — כתיבת טיוטה (legal-writer)

1. CEO יוצר issue לכותב עם **כל ההקשר**: תוצאה, סוגיות, מבנה סילוגיסטי, מסמכי מקור, תקדימים
2. legal-writer כותב בלוק-אחרי-בלוק (12 בלוקים: א-יב) בסגנון דפנה
3. כל בלוק נשמר ב-DB (`decision_blocks.content`)

סטטוס: `ready_for_writing` → `drafted`

### שלב 6 — QA

legal-qa מריץ 6 בדיקות איכות:
- שלמות (כל 12 הבלוקים מלאים)
- ניטרליות (בלוק ו אין ציטוטים מצדדים)
- אין כפילות (בלוק י מפנה, לא חוזר)
- מספור רציף
- פסיקה מצוטטת במדויק
- תואם `chair_directions` של דפנה

אם עובר → `qa_passed`. אם נכשל → `qa_failed` + issue תיקון לכותב.

### שלב 7 — ייצוא טיוטה ראשונית (legal-exporter)

**מה עשה עד עכשיו:** בונה DOCX מאפס מבלוקים ב-DB.

**מה חדש (2026-04):** הייצוא מזריק **bookmarks** בתחילת וסיום כל בלוק — אנקורים לעריכות עתידיות:
- `<w:bookmarkStart w:name="block-alef">` ... `<w:bookmarkEnd>`
- כך עד `block-yod-bet`

הקובץ: `data/cases/{case_number}/exports/טיוטה-v1.docx` (גופן David, RTL, גודל ~43KB)

**חשוב:** הטיוטה הזו נרשמת ב-`cases.active_draft_path` = **המקור הרשמי של התיק**.

סטטוס: `qa_passed` → `exported`

---

## שלב 8 — לולאת עריכה מול דפנה (החלק החדש)

> זה הלב של ארכיטקטורת Track Changes שנוספה ב-2026-04.

### 8א. חיים מוריד + עורך + מעלה

1. חיים מוריד `טיוטה-v1.docx` מה-UI
2. פותח ב-Word (שולחן עבודה או Word Online)
3. עורך ידנית: תיקוני ניסוח, עיצוב, תוספות של תוכן שהמערכת לא ידעה עליו
4. שומר מחדש בשם שמתחיל ב-`עריכה-`
5. מעלה חזרה דרך ה-UI (`/cases/{case}` → "העלה גרסה מתוקנת")

### 8ב. Backend קולט — אוטומטית

ה-endpoint `POST /api/cases/{case}/exports/upload` ([web/app.py:1991](web/app.py#L1991)) עושה שלושה דברים:

1. **שומר את הקובץ** כ-`עריכה-v{N}.docx` (כאשר N = הגרסה הבאה)
2. **מריץ retrofit** דרך `apply_user_edit` ב-MCP:
   - פותח את ה-DOCX, מזהה גבולות בלוקים לפי heuristic דו-שכבתי:
     - א) מרקרים עבריים בתחילת פסקה: `א.`, `ב.`, ..., `יב.`
     - ב) כותרות סגנון דפנה: "רקע", "תמצית טענות", "דיון והכרעה", "סוף דבר", וכו'
   - מזריק `<w:bookmarkStart>` / `<w:bookmarkEnd>` חסרים
3. **מעדכן את DB**: `cases.active_draft_path = '/data/cases/{case}/exports/עריכה-v{N}.docx'`

התגובה ל-UI כוללת `bookmarks_added`, `missing_blocks`, `apply_status` — ה-UI מציג toast:
- ✓ "הועלה: עריכה-v2.docx — זוהו N בלוקים"
- ⚠ "M בלוקים לא זוהו — ייתכנו בעיות בתיקונים עתידיים"

### 8ג. חיים מבקש תיקון ספציפי מ-CEO

חיים כותב ב-Paperclip comment ל-CEO של החברה:

> "העליתי טיוטה ערוכה. בבקשה הוסף פסק הלכה של בג"ץ 1234/21 בבלוק י' (דיון), ותקן את הניסוח של סוף דבר."

### 8ד. CEO מתזמר — שלב G

[.claude/agents/legal-ceo.md — שלב G](.claude/agents/legal-ceo.md) מפעיל:

1. `list_bookmarks(case_number)` — מקבל את רשימת האנקורים הזמינים
2. אם הבקשה דורשת ניסוח חדש → מפעיל legal-writer במצב **revision**
   - writer מקבל `block_id` + `bookmark_anchor` + הוראת ניסוח
   - מחזיר טקסט נקי בסגנון דפנה
   - **לא שומר ב-DB** (ה-revision חי בקובץ)
3. בונה JSON array של revisions:
   ```json
   [{
     "id": "r1",
     "type": "insert_after",
     "anchor_bookmark": "block-yod",
     "content": "<הטקסט שהכותב ניסח>",
     "style": "body",
     "reason": "הוספת פסק הלכה לפי בקשת חיים"
   }]
   ```
4. קורא ל-`revise_draft(case_number, revisions)`

### 8ה. docx_reviser מבצע XML surgery

[mcp-server/src/legal_mcp/services/docx_reviser.py](mcp-server/src/legal_mcp/services/docx_reviser.py):

1. פותח את `עריכה-v{N}.docx` כ-ZIP + טוען `word/document.xml` עם lxml
2. מוסיף `<w:trackRevisions/>` ב-`word/settings.xml` (אם חסר)
3. לכל revision:
   - מאתר את ה-bookmark בעץ
   - בונה פסקה חדשה עם RTL + David + המילה "מערכת AI" כמחבר
   - עוטף את ה-runs החדשים ב-`<w:ins w:id w:author w:date>`
   - שומר IDs ייחודיים (סורק max קיים)
4. שומר כ-`טיוטה-v{N+1}.docx` — **הקובץ החדש שומר על כל העיצוב המקורי של המשתמש** (הטמפלט, הפונטים, הטבלאות, הכל)
5. מעדכן `cases.active_draft_path` לקובץ החדש

### 8ו. חיים מקבל + מאשר/דוחה

1. UI מציג: "טיוטה v{N+1} (מתוקנת) מוכנה לעיון"
2. חיים מוריד, פותח ב-Word
3. ה-Track Changes מופעל — השינויים מסומנים בצבע, סרגל Review פעיל
4. חיים לוחץ Accept על כל שינוי שהוא מסכים איתו, Reject על מה שלא
5. אם יש עוד שינויים שהוא רוצה לבקש — חוזר לשלב 8א (שומר, מעלה `עריכה-v{N+2}.docx`, מבקש עוד שינוי)

### 8ז. סיום — `final`

כשחיים מרוצה, הוא מסמן בייוויי "סמן כסופי" ב-UI → הקובץ מועתק ל-`סופי-{case}.docx` + ל-`data/training/` ללמידה עתידית של דפוסי סגנון.

סטטוס: `exported` → `final`

---

## סכמת DB — 4 שכבות

### Layer 1: Core
`cases`, `documents`, `document_chunks`

**חדש (2026-04):** `cases.active_draft_path TEXT` — הנתיב המלא ל-DOCX שהוא מקור האמת הנוכחי של התיק. null עד לייצוא הראשון.

### Layer 2: Decision
`decisions`, `decision_blocks`, `decision_paragraphs`, `claims`

### Layer 3: Legal Knowledge
`case_law`, `statutory_provisions`, `transition_phrases`, `lessons_learned`, `style_corpus`, `style_patterns`

### Layer 4: Semantic Search (RAG)
`document_embeddings`, `paragraph_embeddings`, `case_law_embeddings` (pgvector 1024-dim, voyage-3)

### Layer 5 — Multi-tenancy
`companies`, `tag_company_mappings` (appeal_subtype → company_id)

---

## רב-חברתיות (CMP + CMPA)

**חברות:**
- CMP (`42a7acd0-30c5-4cbd-ac97-7424f65df294`) — תיקי 1xxx (רישוי ובניה)
- CMPA (`8639e837-4c9d-47fa-a76b-95788d651896`) — תיקי 8xxx/9xxx (היטלי השבחה, פיצויים ס' 197)

**מה משותף לשתי החברות:**
- DB יחיד, backend יחיד, frontend יחיד
- כל הקוד + agents — פועלים לפי `$PAPERCLIP_COMPANY_ID` בזמן ריצה
- ארכיטקטורת Track Changes (docx_reviser, docx_retrofit, apply_user_edit, revise_draft)

**מה כפול לכל חברה:**
- Paperclip skills (`/home/chaim/.paperclip/instances/default/skills/{company_uuid}/`)
- ניתוח סגנון נפרד (`style_patterns` filtered by appeal_subtype)
- CEO agent משלה (CMP: `752cebdd...`, CMPA: `cdbfa8bc...`)

**סקריפט סנכרון:** [scripts/deploy-track-changes.sh](scripts/deploy-track-changes.sh) — מעתיק skills מ-CMP ל-CMPA.

---

## MCP Tools (חלקי — הרלוונטיים לטיוטות)

| Tool | מה עושה |
|------|----------|
| `export_docx(case)` | ייצוא טיוטה ראשונית מה-DB, עם bookmarks. מעדכן `active_draft_path`. |
| `apply_user_edit(case, filename)` | רישום `עריכה-*.docx` כ-active_draft + הזרקת bookmarks. |
| `list_bookmarks(case)` | רשימת אנקורים זמינים ב-active_draft. |
| `revise_draft(case, revisions_json)` | החלת Track Changes על active_draft → יוצר `טיוטה-v{N+1}.docx`. |
| `write_block`, `save_block_content` | כתיבה/שמירה של בלוקים ב-DB (לשלב הכתיבה הראשוני). |
| `validate_decision` | 6 בדיקות QA. |

---

## API Endpoints (הרלוונטיים לטיוטות)

| Endpoint | שימוש |
|----------|--------|
| `POST /api/cases/{case}/export-docx` | ייצוא טיוטה מה-DB |
| `GET /api/cases/{case}/exports` | רשימת טיוטות + עריכות קיימות |
| `GET /api/cases/{case}/exports/{filename}/download` | הורדת קובץ |
| `POST /api/cases/{case}/exports/upload` | **העלאת עריכה → auto-retrofit + register כ-active_draft** |
| `DELETE /api/cases/{case}/exports/{filename}` | מחיקה |
| `POST /api/cases/{case}/exports/{filename}/mark-final` | סימון כסופי |
| `POST /api/cases/{case}/exports/revise` | החלת revisions (Track Changes) |
| `GET /api/cases/{case}/exports/bookmarks` | רשימת bookmarks ב-active_draft |
| `POST /api/cases/{case}/exports/{filename}/retrofit` | ריצת retrofit ידנית (לקבצים ישנים) |
| `GET /api/cases/{case}/active-draft` | סטטוס active_draft (path + exists) |

---

## טכנולוגיות עיקריות

- **Database**: PostgreSQL 15 + pgvector 0.8.1
- **Embeddings**: Voyage AI (`voyage-3`, 1024-dim) + cross-encoder rerank (`rerank-2`)
  - bi-encoder: voyage-3 לכל chunk (חד-פעמי בעת ingestion)
  - cross-encoder: rerank-2 לכל query (top-50 → top-K), feature flag `VOYAGE_RERANK_ENABLED`
- **Agents**: Claude Opus 4.7 (via Paperclip pm2)
- **DOCX manipulation**: `python-docx` 1.2+ ו-`lxml` 5.2+ (XML surgery)
- **Frontend**: Next.js + TanStack Query + Tailwind
- **Backend**: FastAPI + asyncpg
- **Deployment**: Coolify + Docker + Traefik (SSL ב-Let's Encrypt)
- **Code repo**: Gitea (`gitea.nautilus.marcusgroup.org/ezer-mishpati/legal-ai`)
- **Secret management**: Infisical

---

## מסמכים קשורים

- [`block-schema.md`](block-schema.md) — מבנה 12 הבלוקים, content model, constraints
- [`decision-methodology.md`](decision-methodology.md) — מתודולוגיה אנליטית
- [`legal-decision-lessons.md`](legal-decision-lessons.md) — לקחים מ-3 החלטות
- [`new-company-setup-guide.md`](new-company-setup-guide.md) — הקמת חברה חדשה (CMPA)
- [`product-specification.md`](product-specification.md) — איפיון מוצר מלא (persona, תהליכים עסקיים)
- [`../CLAUDE.md`](../CLAUDE.md) — הנחיות לסוכני AI שעובדים על הקוד
- [`../scripts/SCRIPTS.md`](../scripts/SCRIPTS.md) — כל הסקריפטים והשימוש בהם
