# 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 [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).