13 KiB
X2 — מודל רב-החברתי וכללי ה-Sync (Multi-Company & Sync)
קובץ-תחום זה כפוף ל-חוקת המערכת והוא ה-deep-dive על המבנה הרב-חברתי של עוזר משפטי — שתי החברות (CMP/CMPA), 14 הסוכנים, ואיך שינוי-הגדרות מפושט מ-Master ל-Mirror. הוא אוכף את G2 (מקור-אמת יחיד — אין מסלולים מקבילים מתפצלים) בהקשר של תצורת-סוכנים: שתי החברות הן שתי העתקות של אותה מערכת, ואסור להן להתפצל (drift).
invariant פרויקטלי-תפעולי. ה-invariants כאן הם עובדות על איך המערכת הזו מנוהלת רב-חברתית — לא תאוריה הנדסית כללית ולא תוכן משפטי. אין סמכות חיצונית ל"איך מסנכרנים CMP↔CMPA"; לכן הם נושאים שדה
מקור-סמכות= הראנבוקים והקוד של הפרויקט עצמו (CLAUDE.md, HEARTBEAT.md, scripts/sync_agents_across_companies.py) — לא ≥3 מקורות חיצוניים וללא סטטוס verified/UNVERIFIED. אבל כל invariant נקשר לעיקרון הגלובלי שהוא משרת: כלל אי-ה-drift הוא מופע של G2.
1. שתי החברות: Master מול Mirror
Paperclip מחייב agents.company_id NOT NULL — אין סוכנים משותפים. כדי לשרת את שני סוגי
העררים, המערכת מורצת כשתי חברות נפרדות, כל אחת עם מערך-סוכנים מלא משלה:
| ממד | CMP — Master | CMPA — Mirror |
|---|---|---|
| תפקיד | מקור-האמת לתצורת-סוכנים | העתקה מסונכרנת מ-Master |
| COMPANY_ID | 42a7acd0-30c5-4cbd-ac97-7424f65df294 |
8639e837-4c9d-47fa-a76b-95788d651896 |
| סוגי תיקים | רישוי ובנייה | היטל השבחה + פיצויים ס'197 |
| טווח-מספרים | 1xxx | 8xxx, 9xxx |
| CEO Agent ID | 752cebdd-6748-4a04-aacd-c7ab0294ef33 |
cdbfa8bc-3d61-41a4-a2e7-677ec7d34562 |
(המקור: HEARTBEAT.md §1, שורות 38–44; מזהי-החברות מקודדים גם ב-sync_agents_across_companies.py:62-63.)
14 סוכנים = 7 × 2. כל חברה מחזיקה את אותם 7 תפקידי-סוכן (CEO, writer, analyst, researcher,
qa, proofreader, exporter — ראה X4-agents.md). מאחר ש-company_id הוא NOT NULL,
כל תפקיד מיוצג בשתי רשומות-סוכן נפרדות — אחת ל-CMP, אחת ל-CMPA. אין רשומה משותפת.
Master = CMP, Mirror = CMPA. התצורה נכתבת ומתוחזקת בחברת ה-Master (CMP, 1xxx), והסנכרון הוא חד-כיווני CMP → CMPA (sync...py:1-7,361-362).
2. ניתוב לפי חברה — סינון ב-company_id
הזרימה התפעולית נאכפת לפי $PAPERCLIP_COMPANY_ID של הסוכן הפועל (HEARTBEAT.md §1):
42a7acd0…→ הסוכן מטפל רק בתיקי 1xxx;8639e837…→ רק בתיקי 8xxx/9xxx (שורות 43–44).- אסור ליצור פרויקט/issue/תוכן לתיק מחוץ לטווח-החברה (שורה 45); issue שמכוון לתיק מחוץ לטווח → סירוב מנומס ב-comment + העֵרת ה-CEO של החברה הנכונה (שורה 46).
- CEO שונה לכל חברה — בחירת ה-CEO ל-wakeup נגזרת מ-
$PAPERCLIP_COMPANY_ID, לעולם לא UUID hardcoded (HEARTBEAT.md §4ג, שורות 143–150). - גבול-חברה נאכף בצד-Paperclip: wakeup לחברה אחרת נדחה —
Agent key cannot access another company(HEARTBEAT.md §4ג, שורה 157).
3. כלל ה-Sync — אחרי כל שינוי-הגדרות ב-Master
טריגר: כל שינוי ב-
adapter_config,runtime_config,budget_monthly_cents, או skills של סוכן ב-Master (UI / SQL / API). מקור: סעיף "Cross-company agent sync" ב-legal-ai/CLAUDE.md וב-root CLAUDE.md.
הפעולה החובה — קודם בדיקה, אז החלה:
PAPERCLIP_BOARD_API_KEY=$(…infisical…) \
python ~/legal-ai/scripts/sync_agents_across_companies.py --verify # drift report
PAPERCLIP_BOARD_API_KEY=$(…) \
python ~/legal-ai/scripts/sync_agents_across_companies.py --apply # backup + apply
מה הסקריפט עושה (מאומת מול הקוד):
- חד-כיווני CMP → CMPA, סינכרון של שדות-תצורה מוגדרים: top-level (
budget_monthly_cents,metadata,icon,title,role), מפתחותadapter_configנבחרים (model,effort,timeoutSec,maxTurnsPerRun, נתיבי-instructions,cwd…), ו-runtime_configכ-full-replace (sync...py:66-75,124-160). שדות פר-חברה (id,company_id,adapter_type,agent_api_keys,status,spent_monthly_cents,permissions) אינם מסונכרנים (sync...py:24-29). - מבוסס-API, לא DB ישיר. ה-PATCH דרך
PATCH /api/agents/{id}וה-skills דרךPOST /api/agents/{id}/skills/syncעםAuthorization: Bearer(sync...py:204-237). - מסנן skills מקומיים שלא קיימים ב-Mirror.
desiredSkillsמושוות כ-subset; skills מקומיים של CMP (למשלlocal/eba6210d5a/legal-decision) שלא קיימים ב-CMPA נשמטים עם אזהרה (sync...py:138-154,194-195). - יוצר revisions. סנכרון skills עובר דרך endpoint ייעודי שמייצר
skill-syncrevision (sync...py:277-284). - idempotent + אל-כשל.
--verify/--dry-runכברירת-מחדל, גיבויpg_dumpלפני--apply, pre-flight על קבצי-instructions, ו-re-verify אוטומטי אחרי ההחלה (sync...py:9,163-173,408-465). - מדלג על סוכן עם
adapter_typeשונה בין החברות. אם ל-Master ול-Mirroradapter_typeשונה →SKIPPING, ללא סנכרון (sync...py:387-389). זו המלכודת ב-INV-MC1 (להלן).
4. Invariants של התחום (פרויקטלי-תפעולי)
INV-MC1: תצורת-סוכן ב-Master מפושטת ל-Mirror — אין drift בין החברות
כלל: כל שינוי ב-adapter_config / runtime_config / budget_monthly_cents / skills של
סוכן בחברת ה-Master (CMP) חייב להיות מפושט ל-Mirror (CMPA) דרך סקריפט ה-Sync המבוסס-API
(--verify ואז --apply). שתי החברות לא מתפצלות — הן שתי העתקות מסונכרנות של אותה תצורה
(מופע של G2 — מקור-אמת
יחיד, אין מסלולים מקבילים מתפצלים; וכלל-ההנדסה "סימטריה", חוקה §6).
מקור-סמכות: סעיף "Cross-company agent sync" ב-legal-ai/CLAUDE.md +
ב-root CLAUDE.md +
scripts/sync_agents_across_companies.py +
HEARTBEAT.md §1, §4ג. (invariant פרויקטלי-תפעולי — ללא
פרוטוקול ≥3-המקורות; משרת את העיקרון הגלובלי G2.)
אכיפה: סקריפט ה-Sync (idempotent, מבוסס-API, גיבוי+re-verify) — מורץ ידנית אחרי כל
שינוי-תצורה ב-Master. אין אכיפה אוטומטית (ראה §5).
הפרה ידועה: הסקריפט מדלג על סוכן ש-adapter_type שונה בין CMP ל-CMPA
(sync...py:387-389). כשמעבירים סוכן ל-deepseek_local
ב-Master, ה-Mirror נשאר על ה-adapter הישן והסנכרון מדלג עליו — חובה להחיל את שינוי ה-adapter_type
ידנית בשתי החברות לפני הרצת ה-Sync (CLAUDE.md "External adapters — deepseek_local"),
אחרת נוצר drift שקט באותו סוכן.
INV-MC2: אין סוכן משותף — רשומה נפרדת לכל חברה
כלל: סוכן לעולם אינו רשומה משותפת בין החברות. כל אחד מ-7 התפקידים מיוצג בשתי
רשומות-סוכן נפרדות (CMP + CMPA), שכן Paperclip מחייב agents.company_id NOT NULL. הסנכרון
מעתיק ערכי-תצורה בין שתי רשומות — לא ממזג אותן לרשומה אחת (תואם G2:
מקור-אמת יחיד לתצורה, גם כשהיא משוכפלת על פני רשומות).
מקור-סמכות: סעיף "Cross-company agent sync" ב-legal-ai/CLAUDE.md (14 agents = 7 × 2;
agents.company_id NOT NULL) + sync...py:4-7,83-103
(שולף מערכי-סוכן נפרדים לכל company_id) + HEARTBEAT.md §1.
(invariant פרויקטלי-תפעולי.)
אכיפה: אילוץ company_id NOT NULL בצד-Paperclip; הסקריפט מתאים סוכנים בין החברות לפי
name ולעולם לא יוצר רשומה משותפת (sync...py:372,383-385
— "we never auto-create").
הפרה ידועה: —
5. מצב קיים מול יעד — פער אכיפה
ה-Sync הוא ידני ולא-נאכף. הסקריפט עצמו בנוי "אל-כשל" (dry-run כברירת-מחדל, גיבוי, re-verify), אך שום מנגנון לא מכריח הרצה אחרי שינוי-תצורה ב-Master:
- drift אם שוכחים. שינוי
adapter_config/runtime_config/budget/skills ב-CMP בלי הרצת--applyמשאיר את CMPA מאחור — שתי החברות מתפצלות בשקט, בניגוד ל-INV-MC1. יעד: טריגר/ בדיקת-בריאות תקופתית שמריצה--verifyומדווחת drift (היום ההרצה תלויה בזיכרון המפעיל). - מלכודת
adapter_type-skip. סוכן עםadapter_typeשונה בין החברות נשמט מהסנכרון (sync...py:387-389) — ה---verifyידווחSKIPPING, אך אם המפעיל לא יחיל את שינוי ה-adapter ידנית בשתי החברות, הסוכן יישאר drifted. יעד: אזהרת-SKIPPING שמתבלטת ב-report + צ'קליסט-ידני (כבר מתועד ב-CLAUDE.md).
6. הפניות-אחיות
- 00-constitution.md — G2 (מקור-אמת יחיד, אין מסלולים מקבילים מתפצלים) + כלל-ההנדסה "סימטריה" (§6).
- X4-agents.md — מפת 7 תפקידי-הסוכן שמשוכפלים על פני שתי החברות.
- X3-integration-deploy.md — Paperclip (wakeup, ניתוב comments) ו-deploy; ה-wakeup-per-company משלים את הניתוב כאן.
- scripts/sync_agents_across_companies.py — מימוש ה-Sync.
- legal-ai/CLAUDE.md + root CLAUDE.md — סעיף "Cross-company agent sync" + "External adapters — deepseek_local" (מלכודת ה-adapter_type).
- .claude/agents/HEARTBEAT.md — §1 (סינון-חברה) + §4ג (wake CEO לפי חברה).