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>
This commit is contained in:
316
skills/new-company-setup/SKILL.md
Normal file
316
skills/new-company-setup/SKILL.md
Normal file
@@ -0,0 +1,316 @@
|
||||
---
|
||||
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)
|
||||
Reference in New Issue
Block a user