Files
Chaim cf5f6fe274 feat(paperclip): close 11 integration gaps (#16-#28)
Brings the legal-ai ↔ Paperclip integration in line with the official
Paperclip skill. Net effect: HEARTBEAT.md -47% (370→195 lines), all 14
agents on uniform runtime_config + budget + instructionsBundleMode, and
two cross-company helpers replacing manual SQL.

Highlights:
- HEARTBEAT.md refactor: project-specific only, delegates to the official
  paperclipai/paperclip skill (loaded per agent). Adds heartbeat-context
  fast-path (§1.7) and PAPERCLIP_WAKE_PAYLOAD_JSON shortcut (§1.5).
- Issue Thread Interactions API: legal-ceo.md now uses
  ask_user_questions / request_confirmation / suggest_tasks instead of
  free-text comments — gives chair structured UI with idempotency keys.
- pc.sh + paperclip_api.pc_request: every API call goes through helpers
  that inject Authorization + X-Paperclip-Run-Id (audit trail).
- sync_agents_across_companies.py: master(CMP)→mirror(CMPA) sync via
  Paperclip API, idempotent, with --verify and --apply modes.
- skills/new-company-setup: 11-step blueprint distilling all 11 gaps
  into a single onboarding runbook for the next company.
- .taskmaster: 12 tasks covering each gap (one already closed: #29).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 17:25:45 +00:00

317 lines
14 KiB
Markdown
Raw Permalink 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.
---
name: new-company-setup
description: מדריך מלא להוספת חברה (board) חדשה במערכת legal-ai + Paperclip — יוצר את כל הרכיבים הנדרשים: companies row ב-Paperclip, 7 סוכנים (CEO + 6 specialists), runtime/adapter config, paperclipSkillSync, instructionsBundleMode, budget, plugin_state mappings, ועדכון קוד legal-ai. השתמש ב-skill זה כאשר המשתמש מבקש להוסיף סוג ערר חדש (למשל 5xxx, 7xxx) או להפריד תחום קיים לחברה משלו. ה-skill מכיל את כל ההגדרות שנקבעו ב-Gaps #16, #17, #19, #21, #22, #24, #25, #28 — אסור להחסיר שלב.
---
# הקמת חברה חדשה — Blueprint מלא
> **קונטקסט**: עד 2026-05-04 יש לנו 2 חברות (CMP=1xxx רישוי, CMPA=8xxx היטל השבחה + 9xxx פיצויים). הוספת חברה שלישית (לדוגמה 5xxx, 7xxx) דורשת 11 שלבים בסדר מסוים. ה-skill הזה מכיל את כל הלקחים מ-Gap analysis ועדכוני 2026-04 → 2026-05.
## רקע — ארכיטקטורה דו-חברתית
מקור החברות: Paperclip מחייב `agents.company_id NOT NULL` — אין shared agents. לכן כל סוג ערר מקבל company משלו ב-Paperclip, עם סט מלא של 7 סוכנים. החברה הראשונה (CMP) היא **master** — שינויים בה מסונכרנים אוטומטית ל-mirrors דרך `scripts/sync_agents_across_companies.py`.
**מודל מומלץ לחברה חדשה**: להפוך אותה ל-mirror של CMP במבנה — כל הסוכנים זהים, רק `company_id`, `id`, `reports_to` שונים. ככה הסקריפט הקיים יסנכרן אוטומטית.
---
## ⚠️ לפני שמתחילים — checklist הבנה
לפני שמרצים אף פקודה, ודא שאתה יודע:
- [ ] **מספרי תיקים** של החברה החדשה (לדוגמה: 5xxx, 7xxx) — חייב להיות disjoint מ-1xxx/8xxx/9xxx
- [ ] **שם בעברית** של הוועדה (לדוגמה: "ועדת ערר לתכנון ובניה צפון")
- [ ] **prefix לidentifiers** של issues (לדוגמה: `CMPN`)
- [ ] **`appeal_type` tag** — מחרוזת קצרה לניתוב (לדוגמה: `licensing_north`)
- [ ] **המודלים והעלויות** — האם זהה ל-CMP (Opus opus-4-6 ל-CEO+writer, Sonnet sonnet-4-6 לאחרים)?
- [ ] **גישה ל-Infisical** ל-`PAPERCLIP_BOARD_API_KEY` (`/paperclip` ב-nautilus env)
- [ ] **PostgreSQL access** ל-Paperclip DB (`localhost:54329`, user `paperclip`)
---
## שלב 1 — יצירת `companies` row ב-Paperclip DB
```sql
INSERT INTO companies (
id, name, issue_prefix, status,
attachment_max_bytes,
require_board_approval_for_new_agents,
hire_approval_required
) VALUES (
gen_random_uuid(),
'ועדת ערר {שם}', -- בעברית
'CMPN', -- 4 תווים אנגלית, ייחודי
'active',
10485760, -- 10MB default
false, -- ברירת מחדל מ-2026.428.0 (Gap docs)
false
)
RETURNING id;
```
**שמור את ה-UUID** — תצטרך אותו ב-כל השלבים הבאים. נקרא לו `$NEW_COMPANY_ID`.
⚠️ אל תיצור project ראשוני ידנית — Paperclip יוצר אוטומטית כשהחברה נשמרת.
---
## שלב 2 — יצירת 7 סוכנים
צור את הסוכנים בסדר הבא (ה-CEO ראשון, כי בכל הסוכנים `reports_to = CEO_id`):
| # | name (עברית) | role | model | budget_cents |
|---|---------------|------|-------|---------------|
| 1 | עוזר משפטי | `ceo` | claude-opus-4-6 | 1500 |
| 2 | מנתח משפטי | `researcher` | claude-opus-4-6 | 1500 |
| 3 | חוקר תקדימים | `researcher` | claude-sonnet-4-6 | 1500 |
| 4 | כותב החלטה | `engineer` | claude-opus-4-6 | 1500 |
| 5 | בודק איכות | `qa` | claude-sonnet-4-6 | 1500 |
| 6 | מייצא טיוטה | `engineer` | claude-sonnet-4-6 | 1500 |
| 7 | הגהת מסמכים | `engineer` | claude-opus-4-6 | 1500 |
### דרך 1 — sync from master (מומלץ)
הדרך הקלה ביותר: צור 7 סוכנים ב-CMPN עם **שמות זהים** ל-CMP, ואז הרץ `sync_agents_across_companies.py` שיעתיק את כל ההגדרות.
```sql
-- לכל אחד מ-7 הסוכנים (שנה את name ו-role בכל פעם):
INSERT INTO agents (
id, company_id, name, role, adapter_type,
adapter_config, runtime_config, budget_monthly_cents,
permissions, status
) VALUES (
gen_random_uuid(),
'{NEW_COMPANY_ID}'::uuid,
'עוזר משפטי', -- שנה ב-7 שורות
'ceo', -- שנה לפי הטבלה למעלה
'claude_local',
'{}'::jsonb, -- ייטען בשלב 4
'{}'::jsonb, -- ייטען בשלב 4
1500,
'{}'::jsonb,
'idle'
)
RETURNING id, name;
```
שמור את 7 ה-UUIDs לטבלה לעיון מהיר.
### עדכון `reports_to` (אחרי שיש לך CEO_id)
```sql
UPDATE agents
SET reports_to = '{CEO_id}'::uuid
WHERE company_id = '{NEW_COMPANY_ID}'::uuid
AND name <> 'עוזר משפטי';
```
---
## שלב 3 — סנכרון מ-CMP (master) דרך הסקריפט
```bash
PAPERCLIP_BOARD_API_KEY=$(mcp__infisical__get-secret \
projectId=9a77b161-f70c-4dd3-9d67-b7ab850cef51 \
environmentSlug=nautilus secretPath=/ \
secretName=PAPERCLIP_BOARD_API_KEY) \
python ~/legal-ai/scripts/sync_agents_across_companies.py --verify
```
**אם הסקריפט לא תומך ב-mirror החדש**, יש לעדכן אותו:
1. פתח `scripts/sync_agents_across_companies.py`
2. השתמש בdict structure: master_company → list of mirrors. או הוסף flag `--target-company`
3. הרץ `--apply` להעתיק את כל ההגדרות מ-CMP ל-CMPN
**מה הסקריפט מסנכרן** (אוטומטית):
- `adapter_config`: model, effort, timeoutSec=3600, maxTurnsPerRun=500, instructionsBundleMode=external, instructionsRootPath/EntryFile, dangerouslySkipPermissions, extraArgs (`--agent legal-{role}`), cwd
- `runtime_config.heartbeat`: graceSec=60, cooldownSec=10, wakeOnDemand=true, maxConcurrentRuns (CEO=2, others=1)
- `budget_monthly_cents` (1500)
- `metadata`, `icon`, `title`
**מה לא מסונכרן** (חייב לעשות ידנית בהמשך):
- `paperclipSkillSync.desiredSkills` — ראה שלב 4
- `permissions` — לפי policy של החברה
- local skills (אם החברה החדשה צריכה custom skills)
---
## שלב 4 — Paperclip Skills
הסקריפט מ-שלב 3 כולל כבר את ה-`paperclipSkillSync.desiredSkills` (מסונן לפי skills זמינים ב-mirror). אבל ה-mirror החדש **לא יקבל local skills** של CMP אם הם לא קיימים גם בו.
### 4א. יצירת company_skills ל-CMPN
```sql
-- העתק את 6 ה-paperclip skills הסטנדרטיים מ-CMP ל-CMPN
INSERT INTO company_skills (company_id, key, slug, name, description, markdown, source_type, trust_level, compatibility, file_inventory)
SELECT
'{NEW_COMPANY_ID}'::uuid,
key, slug, name, description, markdown, source_type, trust_level, compatibility, file_inventory
FROM company_skills
WHERE company_id = '42a7acd0-30c5-4cbd-ac97-7424f65df294' -- CMP
AND key LIKE 'paperclipai/paperclip/%';
```
### 4ב. אם החברה צריכה local skills
החלט אילו local skills (`local/.../legal-decision`, `local/.../attach-precedents`) רלוונטיות — תלוי בסוג הערר.
לדוגמה, חברה ל-"היטלי השבחה צפון" כנראה לא תצריך `attach-precedents` של CMP אלא local skill משלה.
### 4ג. הפעלת skills/sync לכל סוכן
הרץ `scripts/sync_missing_agent_skills.py` עם adaptation לחברה החדשה (העתק את הקובץ ושנה את `CMPA_COMPANY_ID` ל-NEW_COMPANY_ID + רשימת ה-skills הרצויה).
⚠️ **חובה דרך API** (`POST /api/agents/{id}/skills/sync`) — לא דרך SQL ישיר! ה-API יוצר revision מסוג `skill-sync` שנדרש לlogging. SQL ישיר לא יוצר revision.
---
## שלב 5 — Symlinks ל-instructions (managed by Paperclip)
לכל סוכן Paperclip צופה לקבצי הוראות בנתיב:
`~/.paperclip/instances/default/companies/{COMPANY_ID}/agents/{AGENT_ID}/instructions/`
```bash
NEW_COMPANY_ID="..."
LEGAL_AI_AGENTS=/home/chaim/legal-ai/.claude/agents
for ROW in \
"ceo:legal-ceo.md" \
"analyst:legal-analyst.md" \
"researcher:legal-researcher.md" \
"writer:legal-writer.md" \
"qa:legal-qa.md" \
"exporter:legal-exporter.md" \
"proofreader:legal-proofreader.md"; do
ROLE="${ROW%%:*}"
FILE="${ROW##*:}"
AGENT_ID=$(PGPASSWORD=paperclip psql -h 127.0.0.1 -p 54329 -U paperclip -d paperclip -tAc \
"SELECT id FROM agents WHERE company_id='$NEW_COMPANY_ID'::uuid AND adapter_config->>'extraArgs' LIKE '%legal-$ROLE%' LIMIT 1")
DEST=~/.paperclip/instances/default/companies/$NEW_COMPANY_ID/agents/$AGENT_ID/instructions/
mkdir -p $DEST
ln -sf "$LEGAL_AI_AGENTS/$FILE" "$DEST/AGENTS.md"
ln -sf "$LEGAL_AI_AGENTS/HEARTBEAT.md" "$DEST/HEARTBEAT.md"
done
```
**אימות:** `ls -la ~/.paperclip/instances/default/companies/$NEW_COMPANY_ID/agents/*/instructions/` — צריך לראות 14 symlinks (7 agents × 2 קבצים).
---
## שלב 6 — עדכון `web/paperclip_client.py`
הקובץ מכיל 3 dicts שצריכים את החברה החדשה:
```python
# COMPANIES dict
COMPANIES = {
"licensing": "42a7acd0-30c5-4cbd-ac97-7424f65df294",
"betterment": "8639e837-4c9d-47fa-a76b-95788d651896",
"{appeal_type_new}": "{NEW_COMPANY_ID}", # ← חדש
}
# CEO_AGENTS dict — נדרש ל-wakeup routing
CEO_AGENTS = {
COMPANIES["licensing"]: "752cebdd-...",
COMPANIES["betterment"]: "cdbfa8bc-...",
COMPANIES["{appeal_type_new}"]: "{CEO_ID_NEW}", # ← חדש
}
# _FALLBACK_APPEAL_TYPE_TO_COMPANY — ניתוב לפי tag עברי/אנגלי
_FALLBACK_APPEAL_TYPE_TO_COMPANY = {
# קיימים...
"{שם בעברית}": COMPANIES["{appeal_type_new}"],
"{english_tag}": COMPANIES["{appeal_type_new}"],
}
```
⚠️ אחרי השינוי — **deploy** ל-Coolify (FastAPI container חי במכולה — שינוי קוד דורש rebuild). ראה `legal-ai/CLAUDE.md`.
---
## שלב 7 — `tag_company_mappings` ב-legal-ai DB
ה-FastAPI ראשית מנסה לקרוא ניתוב מ-DB, רק אז fallback ל-dict הקבוע (שלב 6). הוסף mapping:
```sql
-- ב-legal-ai DB (port 5433)
INSERT INTO tag_company_mappings (tag, company_id) VALUES
('{שם עברי}', '{NEW_COMPANY_ID}'),
('{english_tag}', '{NEW_COMPANY_ID}');
```
---
## שלב 8 — עדכון `HEARTBEAT.md` §1
הסעיף §1 מכיל טבלה של חברות + CEO IDs. הוסף שורה חדשה:
```markdown
| ועדת ערר {שם} (CMPN) | `{NEW_COMPANY_ID}` | {סוג} | **{Nxxx}** | `{CEO_ID_NEW}` |
```
ובסעיף §4ג (CEO wakeup), עדכן את ה-`if` להוסיף אופציה שלישית לחברה החדשה.
---
## שלב 9 — עדכון `legal-ai/CLAUDE.md`
הקובץ מכיל את אותה טבלה. עדכן בקטעים:
- "סוגי עררים" (אם קיים)
- "Paperclip — כללי אינטגרציה קריטיים" → "ניתוב comments דרך CEO"
---
## שלב 10 — Hebrew translation (אם נדרש)
אם שם החברה מופיע ב-UI, ייתכן שצריך תרגום ב-`~/.paperclip/hebrew/translate-he.js`. בד"כ לא נדרש — שמות בעברית כבר.
```bash
# אחרי שינויים בHebrew file:
~/.paperclip/hebrew/apply-hebrew.sh
# ⚠️ לא דורש pm2 restart — UI client-side fix.
```
---
## שלב 11 — בדיקה end-to-end
1. **CEO מתעורר על comment**: צור issue test בחברה החדשה, פרסם comment, ודא ש-CEO רץ.
2. **plugin marcusgroup.legal-ai רואה את החברה**: ב-Paperclip UI → Settings → Plugins → marcusgroup.legal-ai → ודא שהחברה החדשה ב-installed companies.
3. **MCP tools פועלים**: דרך Claude Code, הרץ `mcp__legal-ai__case_create` עם appeal_type של החברה החדשה.
4. **Sync script עובד**: `python scripts/sync_agents_across_companies.py --verify` — לא צריך drift.
5. **Budget enforcement**: צור cost_event מבחן, ודא ש-spent_monthly_cents מתעדכן.
---
## ⚠️ מלכודות מתועדות (מ-Gap analysis 2026-04 → 2026-05)
מבחן בכל שלב מאפשר תפיסת issues שתועדו בעבר:
| # | מלכודת | פתרון |
|---|---------|--------|
| 1 | סוכנים בלי `paperclipSkillSync` | ראה שלב 4ג (POST /api/agents/{id}/skills/sync, לא SQL) |
| 2 | `runtime_config = '{}'` (default → graceSec=1ms!) | ראה שלב 3 (סקריפט מסנכרן `heartbeat.graceSec=60`) |
| 3 | `budget_monthly_cents = 0` | ראה שלב 2 (insert עם 1500) |
| 4 | `instructionsBundleMode` חסר | ראה שלב 3 (סקריפט מסנכרן `external` + Root + EntryFile) |
| 5 | `bootstrapPromptTemplate` deprecated | אין אצלנו — דלג |
| 6 | drift בין חברות | ראה שלב 3 — סנכרון אוטומטי כל שינוי הגדרות |
| 7 | CEO לא מתעורר על comment | ודא ש-`reports_to` עודכן ושיש symlinks ל-AGENTS.md (שלב 5) |
| 8 | `psql` ישיר ל-`issue_attachments` | אסור — ראה `HEARTBEAT.md §2` (heartbeat-context API) |
| 9 | curl ישיר ל-Paperclip API | אסור — תמיד `pc.sh` (`HEARTBEAT.md §0`) |
| 10 | "@chaim — ענה 1/2/3 בcomment" | אסור — interactions API (`legal-ceo.md §B/§C/§D`) |
---
## רפרנסים
- [`docs/new-company-setup-guide.md`](../../docs/new-company-setup-guide.md) — היסטוריית הקמת CMPA (חברה שנייה, 2026-04)
- [`scripts/sync_agents_across_companies.py`](../../scripts/sync_agents_across_companies.py) — אוטומציה לסנכרון
- [`scripts/sync_missing_agent_skills.py`](../../scripts/sync_missing_agent_skills.py) — תבנית להפעלת skills/sync
- [`~/.paperclip/CUSTOMIZATIONS.md`](../../../.paperclip/CUSTOMIZATIONS.md) — כל ההתאמות הפעילות (סעיפים: agents runtime, instructions, budgets, interactions, skill-sync)
- [`HEARTBEAT.md`](../../.claude/agents/HEARTBEAT.md) — §1 טבלת חברות (לעדכן בשלב 8)
- [`legal-ai/CLAUDE.md`](../../CLAUDE.md) — Paperclip integration rules
---
## גרסה
- 2026-05-04 — גרסה ראשונה (אחרי Gap #16-#28)