Rewrite architecture.md — add Track Changes edit flow + 8 stages
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 6s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 6s
The old architecture.md was out of date (mentioned n8n which isn't used,
wrong embedding dimensions, missing multi-tenancy, no edit loop).
The rewrite documents the full process end-to-end:
1. Document upload + OCR + embedding
2. Analysis (proofreader, researcher)
3. Outcome + direction decision (CEO + human)
4. Deep analysis (pass 2)
5. Drafting (writer writes 12 blocks)
6. QA
7. Initial DOCX export (with bookmarks for future revisions)
8. Edit loop with Track Changes — the new architecture:
a. User downloads + edits in Word + uploads עריכה-v{N}.docx
b. Backend auto-retrofits bookmarks + registers as active_draft
c. User asks CEO for specific change in Paperclip comment
d. CEO stage G: calls writer in revision mode → builds revisions JSON
e. docx_reviser applies <w:ins>/<w:del> preserving user's template
f. User Accept/Reject from Word Review tab
g. Repeat until marked final
Plus MCP tool reference, API endpoints, DB schema, multi-tenancy,
technology stack.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,82 +1,305 @@
|
||||
# System Architecture — Legal Decision Assistant
|
||||
|
||||
## Components
|
||||
> עודכן: 2026-04-16 — הוספת ארכיטקטורת Track Changes לעריכת טיוטות
|
||||
|
||||
## רכיבי המערכת
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
┌───────────────────────────────────────────────────────────────┐
|
||||
│ Nautilus Server │
|
||||
│ 158.178.131.193 │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ Coolify │ │ Traefik │ │ ezer-mishpati-web│ │
|
||||
│ │ (manage) │ │ (proxy) │ │ (upload UI) │ │
|
||||
│ └──────────┘ └──────────┘ └──────────────────┘ │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ legal-ai container (Coolify UUID: gyjo0mtw2c42ej3...) │ │
|
||||
│ │ ┌────────────┐ ┌──────────────────────────┐ │ │
|
||||
│ │ │ Next.js UI │ │ FastAPI backend │ │ │
|
||||
│ │ │ :3000 │◄──►│ :8000 (internal) │ │ │
|
||||
│ │ └────────────┘ │ + MCP server │ │ │
|
||||
│ │ └──────────────────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────────────┐ │
|
||||
│ │ PostgreSQL │ │ Redis │ │
|
||||
│ │ + pgvector │ │ (task queue) │ │
|
||||
│ │ (legal-ai-postgres│ │ (legal-ai-redis) │ │
|
||||
│ │ PostgreSQL + │ │ Redis │ │
|
||||
│ │ pgvector (1024D) │ │ (task queue) │ │
|
||||
│ │ legal-ai-postgres│ │ legal-ai-redis │ │
|
||||
│ └──────────────────┘ └──────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Gitea │ │ n8n │ │
|
||||
│ │ (code) │ │ (automate│ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ Claude Code (via SSH or API) │ │
|
||||
│ │ — Skills: legal-decision, legal-docx │ │
|
||||
│ │ — MCP: postgres, n8n, cloudflare, chrome │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
│ ┌──────────────┐ ┌──────────────────────────┐ │
|
||||
│ │ 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 (embeddings, analysis)
|
||||
← Cloudflare DNS (*.nautilus.marcusgroup.org)
|
||||
← User (Putty SSH / Browser)
|
||||
← Claude API (Opus 4.7 for agents)
|
||||
← Voyage AI (voyage-3-large, 1024-dim embeddings)
|
||||
← Infisical (secret management)
|
||||
← Gmail SMTP (agent notifications)
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
---
|
||||
|
||||
```
|
||||
1. Document Upload
|
||||
User → ezer-mishpati-web → file storage → n8n trigger
|
||||
→ classify document → store metadata in PostgreSQL
|
||||
→ generate embeddings → store in pgvector
|
||||
## הזרימה המלאה — מהעלאת מסמכים ועד טיוטה סופית
|
||||
|
||||
2. Decision Writing
|
||||
Claude Code → read source materials from DB
|
||||
→ generate structure DOCX (12 blocks)
|
||||
→ write each block with appropriate model/parameters
|
||||
→ validate against block-schema
|
||||
→ export final DOCX
|
||||
### שלב 1 — יצירת תיק + העלאת מסמכי מקור
|
||||
|
||||
3. Precedent Search (RAG)
|
||||
Query → generate embedding → pgvector similarity search
|
||||
→ return relevant paragraphs/decisions
|
||||
→ Claude analyzes relevance → present to user
|
||||
```
|
||||
**מה קורה:**
|
||||
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-large, 1024D), שומר ב-`document_chunks`
|
||||
4. סטטוס תיק: `new` → `proofread`
|
||||
|
||||
## Database Schema — 4 Layers
|
||||
### שלב 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
|
||||
appeals, parties, panels, documents
|
||||
`cases`, `documents`, `document_chunks`
|
||||
|
||||
**חדש (2026-04):** `cases.active_draft_path TEXT` — הנתיב המלא ל-DOCX שהוא מקור האמת הנוכחי של התיק. null עד לייצוא הראשון.
|
||||
|
||||
### Layer 2: Decision
|
||||
decisions, decision_blocks, decision_paragraphs, claims
|
||||
`decisions`, `decision_blocks`, `decision_paragraphs`, `claims`
|
||||
|
||||
### Layer 3: Legal Knowledge
|
||||
case_law, case_law_citations, statutory_provisions, transition_phrases, lessons_learned
|
||||
`case_law`, `statutory_provisions`, `transition_phrases`, `lessons_learned`, `style_corpus`, `style_patterns`
|
||||
|
||||
### Layer 4: Semantic Search (RAG)
|
||||
document_embeddings, paragraph_embeddings, case_law_embeddings
|
||||
(all using pgvector vector(1536) columns)
|
||||
`document_embeddings`, `paragraph_embeddings`, `case_law_embeddings` (pgvector 1024-dim, voyage-3-large)
|
||||
|
||||
### 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) |
|
||||
|
||||
---
|
||||
|
||||
## טכנולוגיות עיקריות
|
||||
|
||||
## Technology Choices
|
||||
- **Database**: PostgreSQL 15 + pgvector 0.8.1
|
||||
- **Embedding model**: TBD (Claude/OpenAI ada-002/local)
|
||||
- **Automation**: n8n (workflow engine)
|
||||
- **Code repository**: Gitea (self-hosted)
|
||||
- **Deployment**: Coolify (Docker management)
|
||||
- **Proxy**: Traefik v3.6 (auto-SSL)
|
||||
- **Frontend**: ezer-mishpati-web (static HTML + API)
|
||||
- **Embeddings**: Voyage AI (`voyage-3-large`, 1024-dim)
|
||||
- **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) — כל הסקריפטים והשימוש בהם
|
||||
|
||||
Reference in New Issue
Block a user