# 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 הרשמי באנגלית — תרגם אם נדרש.

---

## קריאת-ספ — קודם החוקה (00), אז ספ-התחום — לפני פעולה מהותית (INV-AG1) ⚠️

**לפני העבודה המהותית בכל ריצה** — קרא תחילה את חוקת המערכת, ואז את ספ-התחום הרלוונטי לתפקידך. הסוכן **אינו פועל "מהזיכרון"**: המקור הקנוני להתנהגות הוא החוקה + ספ-התחום, לא הרגלים מריצות קודמות. שלב זה **קודם** ל-§0–§8 התפעוליים שמתחתיו (הם ה-checklist של ההפעלה; קריאת-הספ קודמת לעבודה המהותית).

1. **תמיד ראשון:** [`~/legal-ai/docs/spec/00-constitution.md`](../../docs/spec/00-constitution.md) — ייעוד, עקרונות-עבודה, ה-invariants הגלובליים G1–G11, ואינדקס-הספ (§7).
2. **אז ספ-התחום לפי תפקידך** (מ-frontmatter `name`):

| סוכן (`name`) | ספ-תחום לקרוא לפני פעולה |
|---------------|---------------------------|
| `legal-ceo` | **00 + כל הספ** (מתזמר → צריך תמונה מלאה); ניתוב comments → `X3-integration-deploy.md §1ב` |
| `legal-proofreader` | `01-ingest.md` (קליטה / טקסט-מחולץ) |
| `legal-researcher` | `03-retrieval.md` (3 קורפוסים, hybrid/RRF, attribution); קליטת-פסיקה → `01-ingest.md` |
| `legal-analyst` | `02-data-model.md` + `03-retrieval.md` + `04-analysis-writing.md` |
| `legal-writer` | `04-analysis-writing.md` + `05-qa-review.md` (כותב מול שערי-QA) |
| `legal-qa` | `05-qa-review.md` (שערי QA + שערים אנושיים) |
| `legal-exporter` | `06-export.md` (ייצוא DOCX לפי תבנית דפנה) |
| `hermes-curator` | `07-learning.md` (Hermes · לקחים · לולאת פידבק) |

> כל הקבצים תחת [`~/legal-ai/docs/spec/`](../../docs/spec/). המפה המלאה (תפקיד→ספ, frontmatter, שערי-אישור) ב-[`X4-agents.md`](../../docs/spec/X4-agents.md). זהו מופע של **G10** (המערכת מסייעת תחת שערים אנושיים) — הסוכן פועל בגבולות שהחוקה מגדירה. קובץ-הסוכן שלך חוזר על ההפניה הזו בראשו ("קרא לפני פעולה").

---

## שער anti-hallucination — קודם המקור, אז הציטוט (INV-AH) ⚠️

**חל על כל סוכן נוגע-מהות.** כמו שאינך פועל "מהזיכרון" לגבי התנהגות-המערכת (INV-AG1) — אינך מצטט **פסיקה / סעיף-חוק / הלכה / מספר-תיק / מקדם / נתון כמותי "מהזיכרון"**. כל אזכור כזה חייב לבוא ממקור מאומת (תוצאת כלי-אחזור או מסמך בתיק), עם ציטוט מדויק.

**קרא וקיים** את חמש הטכניקות ב-[`~/legal-ai/docs/anti-hallucination-gate.md`](../../docs/anti-hallucination-gate.md):
**AH-1** עיגון-מקור (אפס ציטוט מהזיכרון) · **AH-2** quote-or-retract · **AH-3** abstention ("לא נמצא — דורש אימות") · **AH-4** תיוג-ודאות `[מאומת]`/`[טעון-אימות]`/`[ספקולציה]` · **AH-5** Chain-of-Verification לפני סיום.

> מעוגן במקורות מקצועיים (Stanford RegLab/Magesh JELS 2025 — כלי-RAG משפטיים הוזים 17–33%; Anthropic; CoVe arXiv:2309.11495; RAGAS; NIST AI RMF). **"פער" מותר ("אזכרתי X, לא נמצא בקורפוס — לאמת"); "המצאה" אסורה ("הנה תקדים Y" ללא מקור).**

---

## §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א2. פעולות סטרוקטורליות (כפתורי-UI עתידיים, CEO בלבד).** אם `$PAPERCLIP_WAKE_PAYLOAD_JSON` מכיל שדה `action` — נתב דטרמיניסטית בלי פענוח-טקסט: `action == "interim_draft"` → טיוטת ביניים, `action == "party_claims_summary"` → סיכום מנהלים של טענות הצדדים. פירוט: `legal-ceo.md` שלב 0 + שלבים H/H2.

**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 עם פירוט.

> **⚠️ שער קריאת-הערות לפני סגירה (חובה).** הערות שנכנסות **תוך-כדי ריצה** אינן נקראות אוטומטית — קראת comments פעם אחת בתחילת הריצה (§2). **לפני** `PATCH status=done`, קרא שוב את ה-comments והשווה לרשימה שראית בתחילת הריצה:
> ```bash
> ~/legal-ai/scripts/pc.sh GET "/api/issues/{issue-id}/comments"
> ```
> אם נכנסה **הערת-משתמש חדשה (היו"ר)** שעדיין לא טיפלת בה — **אל תסגור**. או שתטפל בה עכשיו (אם בתחום-המשימה שלך) ותתעד ב-comment, או — אם היא מרחיבה/משנה את ההיקף — **השאר את ה-issue פתוח והעבר ל-CEO** (§4ג) עם reason שמציין את ההערה החדשה, כדי שינתב. **לעולם אל תסמן `done` בעוד הערת-יו"ר ממתינה ללא-מענה** — כך הערה "נופלת". (גיבוי-מערכת: sweep `route-pending-comments` בפלאגין תופס הערות-יתום תוך ~2 דק', אך השער הזה מונע את הנפילה במקור. רקע: legal-ai #164.)

### §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"
```

---

## §7. סטטוסי תיק (case status flow)

**מקור-האמת היחיד** למודל-הסטטוסים: `mcp-server/src/legal_mcp/case_status_model.py` (חשוף ב-`GET /api/status-model`; ה-enum, ה-`STATUS_ORDER` וה-frontend נגזרים ממנו). 12 הסטטוסים הקנוניים, לפי 5 השלבים:

```
קליטה          : new · processing
הכנה           : documents_ready
ניתוח וכיוון    : analyst_verified · research_complete · outcome_set · direction_approved
   → [שער שטן-מליץ: red-team אוטומטי → עצירת-אישור לידים ע"י היו"ר]
כתיבת טיוטה     : qa_review · drafted
סגירה          : exported · reviewed · final
```

`analyst_verified` ו-`research_complete` הם **סטטוסים קנוניים מהמעלה הראשונה** (לא legacy) — המנתח/חוקר מציבים אותם, ומקומם בשלב "ניתוח וכיוון". `research_complete` מנותב ע"י `legal-researcher.md` שלב 5 כשמחקר תקדימים רץ בנפרד מהמנתח; ה-CEO מטפל בו כמו `analyst_verified`.

> מצבי-ביניים ישנים שעדיין עשויים להופיע מסוכנים מסוימים (`proofread`, `analysis_enriched`, `ready_for_writing`, `qa_passed`/`qa_failed`) **אינם** בקבוצה הקנונית — הם נמפים-לשלב לתצוגה בלבד (fallback ב-`case-status.ts`) ואינם ניתנים-לבחירה ידנית. אם נדרש לקבע אחד מהם — להוסיף ל-`case_status_model.py` (המקור-היחיד).

> **שער שטן-מליץ (red-team) — שער-קבע אחרי הניתוח (ל-CEO).** ברגע שהניתוח עבר (`analyst_verified`/`research_complete`, `analysis-and-research.md` תקין), ה-CEO **חייב** להפעיל אוטומטית את שטן-מליץ (Gemini, `gemini_local`) **לפני** הכותב, ואז **לעצור לאישור-יו"ר של הלידים** (issue ראשי ל-`in_review`). רק לידים שהיו"ר אישר מומרים ל-`chair_directions` (`record_chair_feedback` → `get_chair_directions` → `approve_direction`); הלידים הגולמיים **לעולם לא** מוזנים לכותב או להחלטה — קלט-יו"ר בלבד (G10 / INV-AH / INV-LRN5). זרימה מלאה: `legal-ceo.md` "שלב A2"/"שלב A3". זה שער-קבע, לא on-demand.

---

## §8. ניתוב upload פסיקה לקורפוס — flowchart מהיר

```
חיים העלה PDF פסיקה לתיק → ה-citation הוא:
├── "ערר NNNN/YY" או "בל"מ NNNN/YY"
│   → internal_decision_upload (חובה chair_name + district)
├── "עע"מ / בר"מ / עמ"נ / בג"ץ / ע"א / ע"פ / רע"א / רע"פ / ת"א / ת"מ"
│   → precedent_library_upload (external_upload)
└── PDF יומון "כל יום" (סיכום-משני של עפר טויסטר, עמוד אחד)
    → digest_upload (קורפוס-גילוי; לא קורפוס-ציטוט — X12)
```

- **`internal_decision_upload`** דורש: `file_path`, `case_number`, `chair_name`, `district`. district מתוך הרשימה: ירושלים / מרכז / תל אביב / צפון / דרום / חיפה / ארצי.
- **`precedent_library_upload`** לא מקבל chair_name/district. אם תנסה להעלות "ערר ..." דרכו — citation guard ידחה.
- **`digest_upload`** — ליומון "כל יום" בלבד (מקור-משני שמצביע על פסק; INV-DIG1/2). אינו מצוטט בהחלטה ואינו מחלץ הלכות. **אל** תעלה יומון דרך precedent/internal — ואל תעלה פסק-דין דרך digest.
- פירוט מלא: `legal-researcher.md` סעיף "איזה כלי upload להשתמש".

---

## נתיבי 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).
