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>
196 lines
9.5 KiB
Markdown
196 lines
9.5 KiB
Markdown
# HEARTBEAT.md — רשימת ביצוע לכל ריצה (Project-Specific)
|
||
|
||
> **🎯 קובץ זה — Project-specific only.** ה-skill הרשמי `paperclipai/paperclip/paperclip` (טעון אוטומטית בכל heartbeat דרך `paperclipSkillSync`) מכיל את כל ה-API patterns הגנריים: identity (`/api/agents/me`), `PAPERCLIP_WAKE_PAYLOAD_JSON`, `APPROVAL_ID`, inbox, comments, checkout, status updates, וכו'. **קובץ זה מתעד רק התאמות שלנו** — סינון חברה, helpers, workarounds, ו-quirks.
|
||
>
|
||
> **בקונפליקט:** קובץ זה גובר על ה-skill (project-specific מנצח default).
|
||
|
||
---
|
||
|
||
## שפה — כלל עליון
|
||
|
||
**כל הפלט שלך חייב להיות בעברית בלבד.** כולל: comments, סטטוס, שגיאות, סיכומים, ו-thinking פנימי. אין יוצאים מן הכלל. גם שמות tools, פקודות, ונתיבי קבצים — ההסבר סביבם בעברית. ה-skill הרשמי באנגלית — תרגם אם נדרש.
|
||
|
||
---
|
||
|
||
## §0. כל קריאה ל-Paperclip API — דרך `pc.sh` בלבד
|
||
|
||
**ה-skill הרשמי משתמש ב-`curl` ישיר. אצלנו אסור.** משתמשים ב-helper שלנו:
|
||
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh <METHOD> <PATH> [BODY_JSON] [extra curl args...]
|
||
```
|
||
|
||
מוסיף אוטומטית: `Authorization`, `X-Paperclip-Run-Id` (audit), `Content-Type`, base URL.
|
||
|
||
**דוגמאות:**
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh GET "/api/agents/me/inbox-lite"
|
||
~/legal-ai/scripts/pc.sh POST "/api/issues/$ISSUE_ID/checkout"
|
||
~/legal-ai/scripts/pc.sh PATCH "/api/issues/$ISSUE_ID" '{"status":"done"}'
|
||
```
|
||
|
||
**ל-body גדול עם backticks** — `Write` ל-temp file, אז `pc.sh ... "" -H "Content-Type: application/json" -d @/tmp/comment.json`. ראה §דיווח למה.
|
||
|
||
---
|
||
|
||
## §1. זיהוי וסינון חברה — כלל ברזל ⚠️
|
||
|
||
| חברה | COMPANY_ID | סוגי תיקים | טווח מספרים | CEO Agent ID |
|
||
|------|------------|-------------|---------------|---------------|
|
||
| ועדת ערר רישוי ובניה (CMP) | `42a7acd0-30c5-4cbd-ac97-7424f65df294` | רישוי ובניה | **1xxx** | `752cebdd-6748-4a04-aacd-c7ab0294ef33` |
|
||
| ועדת ערר היטלי השבחה (CMPA) | `8639e837-4c9d-47fa-a76b-95788d651896` | היטל השבחה + פיצויים ס' 197 | **8xxx, 9xxx** | `cdbfa8bc-3d61-41a4-a2e7-677ec7d34562` |
|
||
|
||
- אם `$PAPERCLIP_COMPANY_ID` = `42a7acd0...` → רק תיקים ש-**1xxx**
|
||
- אם `$PAPERCLIP_COMPANY_ID` = `8639e837...` → רק תיקים ש-**8xxx/9xxx**
|
||
- **אסור** ליצור פרויקט/issue/תוכן לתיק שלא בטווח שלך
|
||
- אם issue שהוקצה לך מכוון לתיק שלא בטווח — סרב בנימוס ב-comment, והעֵר את ה-CEO של החברה הנכונה
|
||
|
||
---
|
||
|
||
## §1.5. טיפול ב-wake (skill הרשמי + תוספות שלנו)
|
||
|
||
ה-skill מסביר `PAPERCLIP_WAKE_PAYLOAD_JSON`, `APPROVAL_ID`, ו-`heartbeat-context` (Step 6). הוסף עליו:
|
||
|
||
**1.5א. אם `$PAPERCLIP_WAKE_PAYLOAD_JSON` מכיל comment חדש מחיים** — התייחס אליו ב-comment הראשון שלך ("ראיתי שביקשת X — מבצע Y") **לפני** עבודה רחבה. זה מבטיח שחיים יודע שקלטת.
|
||
|
||
**1.5ב. תמיד לקרוא `heartbeat-context`** — לא רק מה ש-skill ממליץ ("Prefer"). אצלנו ה-`attachments` המוחזרים חיוניים (חיים מעלה DOCX/PDF דרך comments). ראה §2.
|
||
|
||
```bash
|
||
CONTEXT=$(~/legal-ai/scripts/pc.sh GET "/api/issues/$ISSUE_ID/heartbeat-context?wakeCommentId=$LATEST_COMMENT_ID")
|
||
ATTACHMENTS=$(echo "$CONTEXT" | jq '.attachments')
|
||
```
|
||
|
||
**1.5ג. APPROVAL_ID flow** — אם חיים ענה על interaction (ראה `legal-ceo.md` §B/§C/§D), קרא תשובה דרך:
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh GET "/api/issues/$PAPERCLIP_TASK_ID/interactions/$PAPERCLIP_APPROVAL_ID" | jq '{status, kind, response}'
|
||
```
|
||
**אסור** לפענח טקסט מ-comment חופשי כשיש APPROVAL_ID — זה הקלט הסטרוקטורלי.
|
||
|
||
---
|
||
|
||
## §2. קבצים מצורפים — דרך `heartbeat-context`, **לא psql**
|
||
|
||
ה-attachments זמינים ב-`$CONTEXT.attachments` (מ-§1.5ב):
|
||
|
||
```bash
|
||
echo "$CONTEXT" | jq '.attachments[] | {filename, contentPath, contentType, byteSize}'
|
||
|
||
# נתיב מלא לקובץ:
|
||
CONTENT_PATH=$(echo "$CONTEXT" | jq -r '.attachments[0].contentPath')
|
||
FULL_PATH="/home/chaim/.paperclip/instances/default/data/storage/$CONTENT_PATH"
|
||
```
|
||
|
||
קבצי DOCX/PDF — קרא עם `Read` tool ב-`$FULL_PATH`.
|
||
|
||
⚠️ **`psql` ישיר ל-`issue_attachments` — אסור.** ה-API הוא ה-source of truth (Gap #21).
|
||
|
||
---
|
||
|
||
## §3. self-recovery — `issue.released` bug
|
||
|
||
⚠️ **Paperclip quirk ידוע**: לאחר ש-issue מסומן `done`, מנגנון `issue.released` עלול להחזיר אותו ל-`todo` תוך ~30s, וגורם ל-wakeup חוזר על משימה שכבר בוצעה (תועד ב-`docs/paperclip-quirks.md §1`).
|
||
|
||
**לפני שמתחילים עבודה — בדוק שלא בוצעה כבר:**
|
||
|
||
1. **תוצרים בדיסק**: `Glob` על תיקיות output הצפויות (`{case_dir}/documents/research/*.md` לחוקר, `analysis-and-research.md` למנתח, וכו')
|
||
2. **תוצרים ב-DB**: דרך MCP — `precedent_list`, `get_claims`, `extract_appraiser_facts` (status=completed)
|
||
3. **comments קודמים** — חפש "הושלם בהצלחה" מסוף-מצב
|
||
|
||
**אם הכל קיים ותקין:** פרסם comment קצר ("אין שינוי — תוצרים קיימים מהריצה הקודמת"), `PATCH status=done`, צא נקי. **לא לעבוד פעמיים.**
|
||
|
||
**אם משהו חסר/שונה:** עבוד רק על מה שחסר.
|
||
|
||
---
|
||
|
||
## §4. דיווח — חובה!
|
||
|
||
**כל heartbeat שמסיים משימה:** comment + status + wake CEO. הסעיף הזה מתעד רק workarounds שלנו לא ב-skill.
|
||
|
||
### §4א. dual-comment workaround ל-`backtick trap`
|
||
|
||
**ל-body קצר (<500 תווים, בלי backticks/קוד/נתיבים)** — pattern רגיל:
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh POST "/api/issues/{issue-id}/comments" '{"body": "סיכום..."}'
|
||
```
|
||
|
||
**ל-body ארוך עם markdown/backticks/נתיבים — חובה שתי פעולות נפרדות:**
|
||
|
||
1. כתוב את ה-JSON לקובץ זמני דרך **Write tool** (לא bash heredoc):
|
||
```
|
||
Write(file_path="/tmp/comment-{issue-id}.json",
|
||
content=json.dumps({"body": markdown_body}, ensure_ascii=False))
|
||
```
|
||
|
||
2. אז `pc.sh` עם `-d @file` שקורא את הקובץ ישירות:
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh POST "/api/issues/{issue-id}/comments" "" \
|
||
-H "Content-Type: application/json" -d @/tmp/comment-{issue-id}.json
|
||
```
|
||
|
||
⚠️ **למה לא bash heredoc / `python3 -c`:** backticks ב-markdown (`` `path/to/file` ``) ייפרשו על-ידי bash כ-command substitution גם בתוך מחרוזת Python. תקבל `Permission denied` מטעה. תועד ב-`docs/paperclip-quirks.md §2`.
|
||
|
||
### §4ב. סטטוס: `done` או `blocked` — לא ביניים
|
||
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh PATCH "/api/issues/{issue-id}" '{"status": "done"}' # הצליח
|
||
~/legal-ai/scripts/pc.sh PATCH "/api/issues/{issue-id}" '{"status": "blocked"}' # נכשל / חסום
|
||
```
|
||
|
||
**אסור** `done` עם כשל שלא טופל. אם משהו נכשל → `blocked` + comment עם פירוט.
|
||
|
||
### §4ג. wake CEO לפי חברה
|
||
|
||
**⚠️ CEO שונה לכל חברה** (ראה §1). UUID hardcoded **אסור** — תמיד דרך `$PAPERCLIP_COMPANY_ID`:
|
||
|
||
```bash
|
||
if [ "$PAPERCLIP_COMPANY_ID" = "8639e837-4c9d-47fa-a76b-95788d651896" ]; then
|
||
CEO_ID="cdbfa8bc-3d61-41a4-a2e7-677ec7d34562" # CMPA
|
||
else
|
||
CEO_ID="752cebdd-6748-4a04-aacd-c7ab0294ef33" # CMP
|
||
fi
|
||
|
||
~/legal-ai/scripts/pc.sh POST "/api/agents/$CEO_ID/wakeup" \
|
||
'{"source":"automation","triggerDetail":"system","reason":"סוכן [שם] סיים [issue-id] בסטטוס [done/blocked]","payload":{"issueId":"[issue-id]","mutation":"agent_completion"}}'
|
||
```
|
||
|
||
⚠️ **חובה `payload.issueId`** — בלי זה הסוכן מתעורר בלי הקשר (בלי תיק, בלי cwd).
|
||
⚠️ **wakeup לחברה אחרת נדחה** — `Agent key cannot access another company`.
|
||
⚠️ **אסור** `INSERT INTO agent_wakeup_requests` ישיר — לא יוצר heartbeat_run, הסוכן לא מתעורר.
|
||
|
||
---
|
||
|
||
## §5. התראת מייל — כשנדרשת תשובה אנושית
|
||
|
||
```bash
|
||
python3 /home/chaim/legal-ai/scripts/notify.py \
|
||
"נדרשת תשובתך — [תיאור קצר]" \
|
||
"תוכן ההודעה עם סיכום מה נדרש"
|
||
```
|
||
|
||
**מתי לשלוח (תמיד):** סיום כל משימה (סיכום קצר), בקשת תוצאה/כיוון, QA fail, החלטה מוכנה לדפנה, מצב שדורש פעולה אנושית, שגיאה לא פתירה.
|
||
|
||
**מתי לא:** עדכוני סטטוס ביניים, שגיאות טכניות שאפשר לפתור לבד.
|
||
|
||
---
|
||
|
||
## §6. Release
|
||
|
||
```bash
|
||
~/legal-ai/scripts/pc.sh POST "/api/issues/{issue-id}/release"
|
||
```
|
||
|
||
---
|
||
|
||
## נתיבי API — הפניה ל-skill הרשמי
|
||
|
||
| פעולה | איפה ב-skill |
|
||
|--------|---------------|
|
||
| Identity, inbox, pick work | Step 1, 3, 4 |
|
||
| Wake payload + APPROVAL handling | Authentication + Step 2 |
|
||
| Heartbeat-context, comments, attachments | Step 6 |
|
||
| Checkout (with the `checkedOutByHarness` skip) | Step 5 |
|
||
| Comment, status update, exit | Step 7-8 |
|
||
| Routines, workflows, references | `references/` ב-skill |
|
||
|
||
**שינויים project-specific מה-skill:** תועדו בקובץ זה (§0 pc.sh, §1 חברה, §2 attachments, §3 quirk, §4 dual-comment + CEO wakeup, §5 notify).
|