Files
legal-ai/docs/operations-runbook.md
Chaim 471cd37fc8 docs(claude-md): לרזות CLAUDE.md מ-11.3k ל-~7k טוקן (TaskMaster #107.1)
מעביר עומק תפעולי ל-docs/operations-runbook.md חדש כדי לצמצם את ההקשר
שנטען אוטומטית בכל סשן. CLAUDE.md נשאר אינדקס דק עם כל הכללים הקריטיים.

הועבר ל-runbook: טבלת Nautilus, פירוט Deploy (Coolify/pm2/legal-chat-service),
עץ-תיקיות מלא, Paperclip deep-ops (wakeup payload, cross-company sync,
webhook flow, scheduled jobs, deepseek_local + hermes curator adapters),
Chair-Feedback, TaskMaster מפורט.

נשמר inline (קריטי): spec-first protocol, worktree isolation, יעד-העל
Style-Acquisition, טבלת מסמכי-ייחוס, עקרונות-כתיבה G11, וכללי-Paperclip
הקריטיים בתמצית (wakeup-via-API, helper-not-curl, comment routing).

344→159 שורות; ~4.3k טוקן/סשן נחסכים. כל התוכן נשאר ב-repo ונגיש דרך קישור.

Invariants: G2 (אין מסלול מקביל — תוכן הועבר, לא שוכפל), G11 (עקרונות-כתיבה
נשמרו inline). תיעוד בלבד, אין נגיעה בקוד.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:14:52 +00:00

204 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Operations Runbook — עוזר משפטי
> תוכן תפעולי-עומק שהוצא מ-[`CLAUDE.md`](../CLAUDE.md) כדי לרזות את ההקשר הנטען בכל סשן (TaskMaster #107.1).
> ה-CLAUDE.md מחזיק את **הכללים הקריטיים בקצרה**; כאן נמצאים הפרטים המלאים, הפקודות, וטבלאות-הייחוס.
> כשעובדים על Deploy, Paperplip-ops, או adapters — לקרוא את הסעיף הרלוונטי כאן.
---
## שרת Nautilus (158.178.131.193)
| שירות | תפקיד | כתובת |
|-------|--------|-------|
| Coolify | ניהול containers | `http://158.178.131.193:8000` |
| PostgreSQL + pgvector | בסיס נתונים ראשי | `legal-ai-postgres` (`localhost:5433`, user `legal_ai`) |
| Redis | תור משימות | `legal-ai-redis` |
| Gitea | מאגר קוד | `gitea.nautilus.marcusgroup.org/ezer-mishpati` |
| ezer-mishpati-web | ממשק העלאת מסמכים (Docker/Coolify) | `legal-ai.nautilus.marcusgroup.org` |
| Paperclip | סוכן AI — מריץ Claude Code agents (pm2, מקומי) | `localhost:3100` |
| legal-chat-service | גשר claude CLI לטאב הצ'אט ב-/training (pm2, loopback) | `127.0.0.1:8770` |
| Infisical | ניהול סודות | `secret.dev.marcus-law.co.il` |
---
## ארכיטקטורת Deploy — חובה לקרוא
שלושה מודלי-הרצה דרים יחד. ערבוב ביניהם הוא הטעות הנפוצה ביותר.
### עוזר משפטי (Legal-AI) — Docker container דרך Coolify
- UUID: `gyjo0mtw2c42ej3xxvbz8zio` (build_pack: `dockerimage`, **לא** `dockerfile`)
- שינוי קוד ב-`web/` או `web-ui/` **לא נכנס לתוקף** עד ש:
1. עושים `git commit` + `git push origin main`
2. Gitea Actions בונה image → דוחף ל-registry → מפעיל redeploy ב-Coolify (`mcp__coolify__deploy`)
3. ממתינים ~2-4 דקות לבנייה
- **אסור** לנסות להריץ uvicorn / `next dev` מקומית — אין סביבת Python על המכונה
- ה-container מריץ Next.js (`:3000`, חשוף) + FastAPI (`:8000`, פנימי)
- בדיקה: `curl https://legal-ai.nautilus.marcusgroup.org/api/health`
- runbook מלא של ה-pipeline: `~/CI-CD-MIGRATION-GUIDE.md`
### Paperclip — מקומית דרך pm2
- פורט: `localhost:3100`, DB: `localhost:54329` (Postgres embedded)
- שינויי קוד נכנסים לתוקף אחרי `pm2 restart paperclip`
- **אין צורך ב-Docker או Coolify** (מיגרציה ל-Coolify נוסתה 2026-04-04 והוחזרה 2026-04-08)
- תרגום/RTL: `~/.paperclip/hebrew/``bash ~/.paperclip/hebrew/apply-hebrew.sh && pm2 restart paperclip`
### legal-chat-service — מקומית דרך pm2 (מאפריל 2026)
- פורט: `127.0.0.1:8770` (loopback בלבד)
- שירות aiohttp קצר שעוטף את `claude` CLI ב-streaming + session continuation, ומשרת את הטאב "שיחה" בדף `/training`. הקונטיינר משדל אליו proxy דרך `host.docker.internal:8770`.
- קוד: [`mcp-server/src/legal_mcp/chat_service/`](../mcp-server/src/legal_mcp/chat_service/)
- התקנה: `pm2 start /home/chaim/legal-ai/scripts/legal-chat-service.config.cjs && pm2 save`
- בריאות: `curl http://127.0.0.1:8770/health``{"ok":true,...}`
- שינויי קוד: `pm2 restart legal-chat-service`
- **אפס עלות API** — claude CLI משתמש ב-claude.ai subscription של chaim. הנחת היסוד של `claude_session.py` (claude CLI מקומי בלבד) נשמרת.
- Coolify dependency: ה-Service Definition של legal-ai חייב להכיל `extra_hosts: host.docker.internal:host-gateway` (אחרת ה-proxy יקבל ConnectError).
---
## מבנה תיקיות
```
/home/chaim/legal-ai/
├── CLAUDE.md ← אינדקס דק (כללים קריטיים + מצביעים)
├── docs/operations-runbook.md ← הקובץ הזה (עומק תפעולי)
├── Dockerfile ← Docker build
├── docs/ ← תיעוד + לקחים
│ ├── architecture.md ארכיטקטורה
│ ├── block-schema.md 12 בלוקים (המסמך החשוב ביותר)
│ ├── migration-plan.md תוכנית מעבר vault → DB
│ ├── legal-decision-lessons.md לקחים מ-3 החלטות
│ └── memory.md הקשר כללי — skills, פרויקטים
├── skills/ ← כלי עבודה ומדריכים
│ ├── decision/ מדריך סגנון + references + 12 בלוקים
│ ├── assistant/ קטלוג מסמכים
│ ├── docx/ עיצוב DOCX
│ ├── dafna-decision-template/ export DOCX לפי תבנית Word של דפנה
│ └── new-company-setup/ blueprint הוספת חברה חדשה
├── .claude/
│ └── agents/ ← הוראות סוכנים + HEARTBEAT.md (symlinks ב-Paperclip)
│ ├── HEARTBEAT.md checklist הפעלה משותף לכל הסוכנים
│ ├── legal-ceo.md תזמורן + בקרת זרימה
│ ├── legal-writer.md כתיבת בלוקים בסגנון דפנה
│ ├── legal-analyst.md ניתוח משפטי + חילוץ טענות
│ ├── legal-researcher.md חיפוש תקדימים
│ ├── legal-qa.md 7 שערי איכות
│ ├── legal-proofreader.md תיקון OCR
│ ├── legal-exporter.md ייצוא DOCX סופי
│ └── hermes-curator.md סוכן Hermes לניתוח סגנון post-export
├── data/
│ ├── training/ ← 4 החלטות לאימון (DOCX)
│ ├── exports/ ← טיוטות DOCX מיוצאות
│ └── cases/{case-number}/ ← תיקי עררים (מבנה שטוח, סטטוס ב-DB)
├── web/ ← FastAPI backend (Python): 75+ API endpoints
│ ├── app.py ← API ראשי
│ ├── paperclip_api.py ← אינטגרציית Paperclip: `pc_request()` + `emit_case_status_webhook()`
│ ├── paperclip_client.py ← legacy client (ישן — השתמש ב-paperclip_api.py)
│ └── gitea_client.py ← אינטגרציית Gitea
├── web-ui/ ← Next.js frontend (TypeScript/React): ממשק המשתמש
│ └── next.config.ts ← proxy: /api/* → FastAPI :8000
├── mcp-server/ ← MCP server + services + tools
├── adapters/ ← Paperclip external adapters
│ └── deepseek-paperclip-adapter/ ← `deepseek_local` (Hermes-pinned ל-DeepSeek profile)
└── scripts/ ← סקריפטים וכלי עזר (ראה scripts/SCRIPTS.md)
└── .archive/ ← סקריפטים שהושלמו (לא להריץ)
```
---
## Paperclip — כללי אינטגרציה (פירוט מלא)
> הכללים הקריטיים בתמצית נמצאים ב-[`CLAUDE.md`](../CLAUDE.md). כאן הפירוט המלא, הדוגמאות, וה-"למה".
### Wakeup API — תמיד דרך API, לעולם לא דרך DB
- **הנתיב הנכון**: `POST /api/agents/{agent-id}/wakeup` (לא `/wake`!)
- **⚠️ אסור**: `INSERT INTO agent_wakeup_requests` ישירות — זה יוצר רק רשומה בלי `heartbeat_run`, והסוכן **לא יתעורר לעולם**
- **⚠️ חובה לשלוח `payload` עם `issueId`** — בלי זה הסוכן מתעורר בלי הקשר (בלי תיק, בלי issue, בלי cwd נכון)
- דוגמה נכונה:
```json
{"source": "automation", "triggerDetail": "system", "reason": "...",
"payload": {"issueId": "...", "mutation": "comment", "commentId": "..."}}
```
- **Board API Key**: שמור ב-DB (`board_api_keys`), auth: `Authorization: Bearer pbk_...`
### ניתוב comments דרך CEO
- כשמשתמש כותב תגובה על issue ב-Paperclip, הפלאגין (`plugin-legal-ai`) מעיר את ה-CEO דרך `ctx.agents.invoke()`
- ה-CEO קורא את ה-comment, מחליט על ניתוב, ויוצר issue לסוכן המתאים
- כל הסוכנים חייבים לקרוא comments אחרונים לפני שהם מתחילים לעבוד (HEARTBEAT שלבים 2b-2c)
### קריאות API — תמיד דרך helper, לעולם לא `curl` ישיר
- **bash (סוכנים):** `~/legal-ai/scripts/pc.sh <METHOD> <PATH> [BODY_JSON]` — מוסיף Authorization, X-Paperclip-Run-Id, Content-Type, base URL. ראה `HEARTBEAT.md §0`.
- **Python (FastAPI):** `from web.paperclip_api import pc_request; await pc_request("POST", "/api/...", json={...})` — שימוש ב-board API key.
- **אסור** `curl ... $PAPERCLIP_API_URL` ישיר ב-bash; **אסור** `httpx.AsyncClient` ישיר ל-Paperclip ב-Python.
- **למה:** ה-skill הרשמי דורש `X-Paperclip-Run-Id` בכל קריאה משנה issue. אצלנו ה-audit trail עבד ממילא דרך JWT claims (`runId: runIdHeader || claims.run_id`), אבל ה-helper מבטיח עקביות + תאימות ל-board API keys (long-lived) שלא נושאות JWT claims.
### Cross-company agent sync — אחרי כל שינוי הגדרות
- יש 14 סוכנים = 7 × 2 חברות (CMP=1xxx, CMPA=8xxx). Paperclip מחייב `agents.company_id NOT NULL` — אין shared agents.
- **Master = CMP (1xxx)**, **Mirror = CMPA (8xxx)**.
- אחרי כל שינוי ב-`adapter_config`, `runtime_config`, `budget_monthly_cents`, או skills של סוכן ב-master (UI, SQL, או API), **חובה להריץ:**
```bash
PAPERCLIP_BOARD_API_KEY=$(...infisical...) \
python ~/legal-ai/scripts/sync_agents_across_companies.py --verify # לבדיקה
PAPERCLIP_BOARD_API_KEY=$(...) \
python ~/legal-ai/scripts/sync_agents_across_companies.py --apply # לסנכרן
```
- הסקריפט מסנן local skills שלא קיימים ב-CMPA (מציג אזהרה), משתמש ב-API (לא DB ישיר), יוצר revisions, idempotent.
- שאלות ה-skill הרשמי של Paperclip — `paperclip` skill תחת `paperclipai/paperclip`.
### Webhook יוצא — עדכון סטטוס תיק לפלאגין
כשסטטוס תיק משתנה דרך `PUT /api/cases/{case_number}`, הבקאנד שולח webhook אסינכרוני לפלאגין:
```
PUT /api/cases/{case_number} → emit_case_status_webhook() [BackgroundTask]
→ POST /api/plugins/marcusgroup.legal-ai/webhooks/case-status
→ plugin-legal-ai/onWebhook()
→ comment בעברית על issue + CEO wakeup (כשסטטוס = qa_failed)
```
- הקוד ב-`web/paperclip_api.py` (`emit_case_status_webhook`), fire-and-forget, timeout 5s
- הפלאגין שומר idempotency key ב-state עם TTL 5 דקות למניעת spam על retry
- `GET /api/cases/stale?days=N` — תיקים שלא עודכנו N ימים; מוחרגים: `new`, `final`, `exported`
- `GET /api/chair-feedback/weekly-summary` — סיכום פידבק YU"R לשבוע האחרון
### Scheduled Jobs (plugin-legal-ai)
| Job | לוח זמנים | מה עושה |
|-----|-----------|---------|
| `stale-case-reminder` | יומי 08:00 | שולח comment אזהרה על תיקים תקועים >3 ימים |
| `weekly-feedback-analysis` | ראשון 19:00 | מעיר CEO לניתוח פידבק YU"R ועדכון `docs/legal-decision-lessons.md` |
| `sync-case-status` | כל 30 דק' | מסנכרן סטטוסי תיקים בין legal-ai ל-Paperclip |
CEO שמתעורר מ-`weekly-feedback-job` כותב לקובץ בלבד — **אין לו issueId, אל תנסה לפרסם comment או לסגור issue**.
### External adapters — `deepseek_local`
- מיקום ה-package: [`adapters/deepseek-paperclip-adapter/`](../adapters/deepseek-paperclip-adapter/) (לא ב-`node_modules`).
- רישום ב-Paperclip: רשומה ב-`~/.paperclip/adapter-plugins.json` (נטען אוטומטית ב-startup דרך `buildExternalAdapters`). אין צורך בעריכת `node_modules`.
- **מה ה-adapter עושה**: spawnל-`hermes chat` עם `HERMES_HOME=/home/chaim/.hermes/profiles/deepseek` כך שה-CLI טוען את `config.yaml` (`base_url=https://api.deepseek.com/v1`, `provider=custom`, `key_env=DEEPSEEK_API_KEY`) ואת `.env` (שמכיל את ה-key).
- **מודלים זמינים** (lookup ב-DeepSeek `/v1/models`): `deepseek-v4-pro` (default), `deepseek-v4-flash`. יופיעו כדרופ-דאון ב-UI.
- **התקנה מחדש / עדכון**: `curl -X POST -H "Authorization: Bearer pcapi_legal_install_key_2026" -H "Content-Type: application/json" -d '{"packageName":"/home/chaim/legal-ai/adapters/deepseek-paperclip-adapter","isLocalPath":true}' http://localhost:3100/api/adapters/install`. לעדכון hot — `POST /api/adapters/deepseek_local/reload`.
- **⚠ Cross-company sync**: `sync_agents_across_companies.py` **מדלג** על סוכנים עם `adapter_type` שונה בין CMP ל-CMPA. כשעוברים סוכן ל-`deepseek_local` חובה להחיל ידנית בשתי החברות לפני sync.
- **תוספת adapters עתידיים** (OpenAI ישיר, Anthropic ישיר, וכו'): אותו דפוס. ה-package הראשי חייב לייצא `createServerAdapter()` שמחזיר `{ type, label, models, agentConfigurationDoc, execute, testEnvironment, sessionCodec, listSkills, syncSkills, ... }`. ראה את [`adapters/deepseek-paperclip-adapter/dist/index.js`](../adapters/deepseek-paperclip-adapter/dist/index.js) כתבנית.
### External adapters — Hermes Curator (`curator-cmp` / `curator-cmpa`)
- פרופילי Hermes נפרדים לסוכן `hermes-curator` — מנתח החלטות סופיות ומציע עדכוני SKILL.md/lessons.md
- מיקום: `~/.hermes/profiles/curator-cmp/` + `~/.hermes/profiles/curator-cmpa/`
- מופעל אחרי export סופי; אינו מעדכן קבצים ישירות
- **תהליך אישור הצעות:** הצעות ה-curator מגיעות כ-comment ב-Paperclip → חיים בוחן ומאשר ידנית → commits ל-`SKILL.md` ו-`docs/legal-decision-lessons.md`
---
## הערות יו"ר (Chair Feedback)
מנגנון לתיעוד הערות דפנה על טיוטות:
- **DB**: טבלת `chair_feedback` (case_id, block_id, feedback_text, category, lesson_extracted)
- **API**: `GET/POST /api/feedback`, `PATCH /api/feedback/{id}/resolve`
- **MCP tools**: `record_chair_feedback`, `list_chair_feedback`
- **UI**: דף ניהול ב-`/feedback` (ב-Next.js)
- **קטגוריות**: missing_content, wrong_tone, wrong_structure, factual_error, style, other
---
## ניהול משימות — TaskMaster AI (פירוט)
- קובץ המשימות הקנוני: `~/legal-ai/.taskmaster/tasks/tasks.json` (יחסי ל-project root, **לא** `~/.taskmaster/tasks/tasks.json`). מכיל את כל ה-tags של legal-ai (`master`, `legal-ai`).
- פקודות עיקריות: `get_tasks`, `next_task`, `add_task`, `update_task`, `expand_task`
- לפני התחלת עבודה → `next_task`; אחרי סיום → `update_task` עם status=done; משימה מורכבת → `expand_task`
- **⚠️ מלכוד cwd ב-CLI:** הדגל `--tag` בוחר קבוצה לוגית *בתוך* הקובץ — הוא **לא** בוחר לאיזה `tasks.json` לכתוב. ה-CLI מאתר את הקובץ לפי ה-cwd. תמיד `cd ~/legal-ai` לפני `task-master add-task` או כל פקודה משנה, ואז אמת ב-MCP `get_tasks`. כשלא בטוחים — לערוך את `~/legal-ai/.taskmaster/tasks/tasks.json` ישירות.