feat(feedback): חיבור פידבק יו"ר לסוכנים — סימון "יושם" מקפל לקח לקובץ הידע #58

Merged
chaim merged 2 commits from feat/chair-feedback-fold into main 2026-06-06 13:09:29 +00:00
11 changed files with 619 additions and 319 deletions

View File

@@ -212,6 +212,7 @@ Paperclip חוסם אוטומטית כל issue ב-`in_progress` שאין לו ru
- אם ה-reason מכיל `agent_completion` → דלג לשלב E/F בהתאם לסוכן שסיים
- אם ה-reason מכיל `precedent_extraction_`**דלג לסעיף "חילוץ פסיקה אוטומטי"**. אל תיגע בתיקים — זו עבודת ספרייה.
- אם ה-reason מכיל `weekly-feedback-job`**דלג לסעיף "ניתוח פידבק שבועי"**. אל תיגע בתיקים פעילים.
- אם ה-reason מכיל `feedback_fold_`**דלג לסעיף "קיפול הערת יו\"ר"**. אל תיגע בתיקים — זו משימת תחזוקת ידע.
- אחרת → המשך לשלב A (heartbeat רגיל)
### חילוץ פסיקה אוטומטי
@@ -270,6 +271,29 @@ Paperclip חוסם אוטומטית כל issue ב-`in_progress` שאין לו ru
**כלל:** אל תגע בתיקים פעילים, אל תעיר סוכנים אחרים, אל תבצע heartbeat רגיל — זו משימת תחזוקה בלבד.
### קיפול הערת יו"ר (feedback_fold)
**מתי:** `$PAPERCLIP_WAKE_REASON` מכיל `feedback_fold_`
מופעל כשהיו"ר סימנה הערת פידבק בודדת כ"יושמה" בדף `/feedback`. נוצר issue בפרויקט "ספריית פסיקה" המשויך אליך, ו**תיאור ה-issue מכיל את כל מה שצריך**: טקסט ההערה, הלקח שהופק, הקטגוריה, ויעד הקיפול לפי הקטגוריה.
**⚠️ MCP startup race** — חל גם כאן (ראה אזהרת חילוץ פסיקה). אם הכלי הראשון מחזיר "No such tool available" — המתן 3 שניות ונסה שוב.
**מה לעשות:**
1. **קרא את תיאור ה-issue** (`$PAPERCLIP_TASK_ID`) — הוא מכיל את ההערה, הלקח, הקטגוריה, ושדה **"יעד קיפול"**.
2. **rubric ניתוב לפי קטגוריה** (מופיע גם בתיאור ה-issue — זה מקור האמת):
| קטגוריה | קובץ יעד |
|---------|----------|
| `style` | `skills/decision/SKILL.md` |
| `wrong_structure` | `docs/block-schema.md` + `docs/legal-decision-lessons.md` |
| `missing_content` / `factual_error` / `wrong_tone` | `docs/legal-decision-lessons.md` |
| `other` | שיקול דעת — אם זה באג מערכת ולא לקח כתיבה → **אל תוסיף לקובץ**, פתח/עדכן משימת TaskMaster |
3. **קרא את קובץ היעד** והבן מה כבר מתועד שם.
4. **הוסף את הלקח רק אם אינו קיים** (לא כפל). פורמט: משפט עברי ברור + שורת **Rule** באנגלית, בעקבות הסגנון הקיים בקובץ.
5. **סגור את ה-issue** (`status=done`) עם comment קצר בעברית: לאיזה קובץ קופל ומה נוסף (או "כבר קיים — לא נוסף").
**כלל:** אל תגע בתיקים פעילים, אל תעיר סוכנים אחרים. משימת תחזוקת ידע בלבד.
### שלב A: בדיקת מצב — שלמות, בדיקות שליליות, תאימות מתודולוגיה
בכל heartbeat **רגיל** (לא comment routing):

View File

@@ -978,7 +978,7 @@
"legal-ai": {
"tasks": [
{
"id": "1",
"id": 1,
"title": "V7 schema: precedent library + halachot tables",
"description": "Add SCHEMA_V7_SQL to db.py: extend case_law with source_kind/document_id/extraction_status/halacha_extraction_status/practice_area (CHECK constraint for 3 areas)/appeal_subtype/headnote. Create precedent_chunks table with vector(1024). Create halachot table with vector(1024), review_status, practice_areas array. Add IVFFlat indexes. Register V7 in init_schema().",
"details": "",
@@ -990,7 +990,7 @@
"updatedAt": "2026-05-03T08:17:59.928Z"
},
{
"id": "2",
"id": 2,
"title": "Chunker: add court ruling section patterns",
"description": "Extend services/chunker.py SECTION_PATTERNS with 4 patterns for external court rulings: פסק דין→ruling, נימוקים→legal_analysis, סוף דבר→conclusion, העובדות הצריכות לעניין→facts",
"details": "",
@@ -1004,7 +1004,7 @@
"updatedAt": "2026-05-03T08:18:33.239Z"
},
{
"id": "3",
"id": 3,
"title": "Service: halacha_extractor.py",
"description": "New service that runs claude_session.query_json() over chunks where section_type IN (legal_analysis, ruling, conclusion). Concurrency=3, retry=1. Validates supporting_quote with substring check after Hebrew normalization. All halachot inserted with review_status=pending_review (no auto-publish). Embeds rule_statement+reasoning_summary via Voyage. Uses Hebrew prompt from plan appendix א. Idempotent on case_law_id.",
"details": "",
@@ -1019,7 +1019,7 @@
"updatedAt": "2026-05-03T08:22:12.392Z"
},
{
"id": "4",
"id": 4,
"title": "Service: precedent_library.py orchestrator",
"description": "New service with ingest_precedent(file_path, citation, court, decision_date, source_type, precedent_level, practice_area, appeal_subtype, subject_tags, case_name, task_id) that orchestrates: extract_text → proofread → INSERT case_law (source_kind=external_upload) → chunk → embed → store precedent_chunks → halacha_extractor.extract → embed halachot → publish progress. Plus delete_precedent (cascading), list_precedents(filters), get_precedent(id), search_library(query, filters, limit) merging chunks+approved-halachot ranked.",
"details": "",
@@ -1035,7 +1035,7 @@
"updatedAt": "2026-05-03T08:23:33.235Z"
},
{
"id": "5",
"id": 5,
"title": "MCP tools: precedent_library + halacha_review",
"description": "Create mcp-server/src/legal_mcp/tools/precedent_library.py with tools: precedent_library_upload, precedent_library_list, precedent_library_get, precedent_library_delete, precedent_extract_halachot, search_precedent_library (semantic, returns merged halachot+chunks), halacha_review (approve/reject). Register all in server.py. Do NOT modify existing precedent_search_library or search_decisions.",
"details": "",
@@ -1049,7 +1049,7 @@
"updatedAt": "2026-05-03T08:25:07.439Z"
},
{
"id": "6",
"id": 6,
"title": "FastAPI endpoints under /api/precedent-library",
"description": "Add to web/app.py: POST /api/precedent-library/upload (multipart), GET /api/precedent-library (filters), GET /api/precedent-library/{id}, PATCH /api/precedent-library/{id}, DELETE /api/precedent-library/{id}, POST /api/precedent-library/{id}/extract-halachot, GET /api/precedent-library/search, GET /api/halachot?status=pending_review, PATCH /api/halachot/{id}, GET /api/precedent-library/stats. Reuse existing /api/progress/{task_id} SSE.",
"details": "",
@@ -1063,7 +1063,7 @@
"updatedAt": "2026-05-03T08:26:21.860Z"
},
{
"id": "7",
"id": 7,
"title": "UI: /precedents page with 4 tabs",
"description": "New web-ui/src/app/precedents/page.tsx with tabs: Library (table+filters+upload), Semantic Search, Pending Review (PRIMARY - bulk approval UX with J/K nav, A/R/E shortcuts, side-by-side rule_statement vs supporting_quote, badge count), Stats. New components in web-ui/src/components/precedents/: precedent-upload-sheet, precedent-list-table, precedent-search-panel, precedent-detail-panel, halacha-review-card. New hooks in web-ui/src/lib/api/precedent-library.ts. Add nav link in app-shell.tsx.",
"details": "",
@@ -1077,7 +1077,7 @@
"updatedAt": "2026-05-03T08:34:00.548Z"
},
{
"id": "8",
"id": 8,
"title": "Agent integration: legal-writer + 3 others",
"description": "Update .claude/agents/legal-writer.md (PRIMARY) — add mcp__legal-ai__search_precedent_library to tools and prompt section explaining when to use it for CREAC rule+explanation in block י. Update legal-researcher.md, legal-analyst.md, legal-ceo.md, legal-qa.md to add the tool. Update skills/decision/SKILL.md with section explaining the 3 corpora (style_corpus, case_precedents, precedent_library).",
"details": "",
@@ -1091,7 +1091,7 @@
"updatedAt": "2026-05-03T08:36:24.711Z"
},
{
"id": "9",
"id": 9,
"title": "Service: precedent_metadata_extractor.py",
"description": "LLM-based extractor that auto-fills empty metadata fields after upload: short case_name (e.g. 'אהרון ברק' from long citation), summary (2-3 sentences), headnote, key_quote, subject_tags array, appeal_subtype. Reuses claude_session.query_json. Returns dict; caller decides which empty fields to merge (never overrides user values).",
"details": "",
@@ -1103,7 +1103,7 @@
"updatedAt": "2026-05-03T10:19:15.105Z"
},
{
"id": "10",
"id": 10,
"title": "Halacha extractor: dual mode (binding vs persuasive)",
"description": "Update halacha_extractor.py prompt to branch on is_binding: binding=true → strict halacha extraction (current). binding=false → extract reasoning principles, applications of established halachot, persuasive conclusions. New rule_types: 'application' (applying known rule to facts), 'persuasive' (committee's reasoning citable as authority). Schema unchanged (rule_type already TEXT).",
"details": "",
@@ -1115,7 +1115,7 @@
"updatedAt": "2026-05-03T10:19:15.117Z"
},
{
"id": "11",
"id": 11,
"title": "Ingest pipeline: add metadata extraction stage",
"description": "In services/precedent_library.py:ingest_precedent, after halacha extraction, run metadata_extractor and PATCH the case_law row with auto-filled fields (only those left empty by user). Publish progress 'extracting_metadata'.",
"details": "",
@@ -1129,7 +1129,7 @@
"updatedAt": "2026-05-03T10:19:15.128Z"
},
{
"id": "12",
"id": 12,
"title": "UI: precedent edit sheet",
"description": "Add edit button to library-list-panel rows that opens a Sheet with all editable fields (case_name, citation, court, date, practice_area, appeal_subtype, subject_tags, summary, headnote, key_quote, source_type, precedent_level, is_binding). Pre-populated from current values. Submit calls PATCH /api/precedent-library/{id} via useUpdatePrecedent. After save, invalidate library list query.",
"details": "",
@@ -1141,7 +1141,7 @@
"updatedAt": "2026-05-03T10:19:15.134Z"
},
{
"id": "13",
"id": 13,
"title": "Test on 403-17: fix metadata + re-extract",
"description": "After deploy: PATCH 403-17 to set case_name='ערר 403/17', then trigger precedent_extract_halachot to test the dual-mode extraction on a non-binding committee decision.",
"details": "",
@@ -1158,7 +1158,7 @@
"updatedAt": "2026-05-26T10:38:07.071897Z"
},
{
"id": "14",
"id": 14,
"title": "Upgrade: speed up halacha+metadata extraction",
"description": "Halacha extraction on long rulings is slow (5-15 min for typical court ruling, 30-50 min for a 207-chunk appeals committee decision). Root cause: each chunk spawns a separate `claude -p` subprocess (5-10 sec startup overhead each), Hebrew prompts on cold cache run 30-90 sec, and there's no prompt-cache sharing between chunks. Acceleration options to evaluate later when speed becomes a real blocker.\n\nOptions (each can be combined):\n\n1. Concurrency 3 -> 6 in halacha_extractor.CHUNK_CONCURRENCY. ~2x faster wall-clock. Cost: 6x ~300MB RSS = 1.8GB peak — verify on Nautilus headroom.\n\n2. Larger chunks 12K -> 18-25K chars (CHUNK_TARGET_CHARS in claims_extractor.py / halacha_extractor.py). Fewer waves. Risk: timeout on cold cache (currently 1800s ceiling), and may degrade extraction precision for very long sections.\n\n3. Anthropic SDK direct with 5-min ephemeral prompt caching on the static instruction prefix (already wired the parameter as system= in claude_session.query). Estimated 5-10x faster because cache reads are ~10% of cold cost. Costs ~$0.30-2 per long ruling on Sonnet 4.6. Chair previously rejected this path for ALL traffic ('we work only with claude session'). Compromise: SDK only for the precedent-library corpus build (static, one-time), claude session for live decision drafting (interactive, frequent).\n\n4. Two-tier prompt: a short 'classification' pass with claude -p deciding which chunks contain halachot, then deep extraction only on positive chunks. Could cut total LLM time by 40-60% on rulings with lots of factual chapters.\n\n5. Already implemented (Apr 3, 2026): skip non-extractable sections — only run on chunks where section_type IN (legal_analysis, ruling, conclusion); fallback to all chunks when chunker labels nothing. So that win is already banked.\n\nRe-evaluate when: a chair drops a 200K+ char ruling into the queue and the wait becomes painful, OR when the precedent-library has 50+ pending entries and bulk processing matters.",
"details": "נסקר 2026-06-03 — אין blocker נוכחי. הרצתי reindex ל-73 תקדימים + חילוצים מרובים בלי שמהירות הייתה כאב. YAGNI: לא מבצעים אופטימיזציה מוקדמת. נשאר deferred עם trigger ברור: פסק-דין 200K+ תווים שתוקע את התור, או 50+ פריטים ממתינים. ה-win הזול (concurrency 3→6) דורש אימות headroom של 1.8GB RSS ב-Nautilus לפני — לא עכשיו.",
@@ -1170,7 +1170,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "15",
"id": 15,
"title": "Multimodal — כיוונון MULTIMODAL_TEXT_WEIGHT (A/B) + הכרעה על backfill",
"description": "נסגר 2026-06-03 לאחר A/B אובייקטיבי על gold-set (86 שאילתות, eval_retrieval.py). הנחת היסוד התיישנה: multimodal כבר ברירת-מחדל בייצור (110 מסמכים מוטמעים אוטומטית בהעלאה), לא רק 2 תיקי A/B. ממצא: ה-weight 0.5 (ברירת-מחדל) היה mis-tuned — צד-התמונה כבד מדי וחתך recall של precedent_library (0.971→0.885). sweep 0.5→0.75: במשקל 0.65 multimodal מנצח את text-only בכל מדד ובכל corpus (R@5 0.994 מול 0.989; nDCG@5 0.960 מול 0.944; MRR 0.954 מול 0.936; precedent_library R@5 0.983, internal_decisions nDCG 0.978). כיסוי: 28/79 מסמכי gold-set מוטמעים multimodal (35% — אות אמיתי). דפנה אישרה.",
"details": "בוצע: MULTIMODAL_TEXT_WEIGHT=0.65 הוגדר ב-Coolify env של legal-ai (runtime) + redeploy; baseline (data/eval/baseline.json) עודכן לקונפיג 0.65. ה-backfill היקר ל-140 התיקים ה-legacy *לא* בוצע — אין הצדקת-אחזור לשאלות טקסט, וערך ה-image-answer לא נבדק. מומר ל-#80 (מותנה). ראיות: data/eval/eval-report-20260603T08*.md, project_multimodal_stage_c.",
@@ -1182,7 +1182,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "16",
"id": 16,
"title": "[Paperclip Gap 1] runtime_config ריק — חסרים graceSec/cooldownSec/maxConcurrentRuns",
"description": "runtime_config = '{}' לכל 14 הסוכנים. מסתבר שעיקר ההגדרות החשובות (timeoutSec=3600, maxTurnsPerRun=500) יושבות ב-adapter_config ולא ב-runtime_config — אז המצב פחות חמור. אבל graceSec/cooldownSec/maxConcurrentRuns עדיין חסרים.",
"details": "תיקון לניתוח המקורי שגוי בעקבות בדיקה ב-DB:\n\nמה שכן יש לנו (ב-adapter_config, לא runtime_config):\n- timeoutSec: 3600 (לכל הסוכנים)\n- maxTurnsPerRun: 500 (לכל הסוכנים)\n- model + effort=high (לכל הסוכנים)\n- paperclipSkillSync.desiredSkills (5/7 סוכנים — חסר אצל הגהת מסמכים ומנתח משפטי)\n\nמה שבאמת חסר ב-runtime_config:\n- heartbeat.graceSec — זמן grace לפני SIGKILL אחרי timeout. מהקוד: Math.max(1, graceSec)*1000. אם לא מוגדר → 1ms grace. בעיה אם הסוכן נחתך באמצע commit ל-DB.\n- heartbeat.cooldownSec — default ביצירה חדשה: 10. אצלנו לא מוגדר.\n- heartbeat.maxConcurrentRuns — default מ-AGENT_DEFAULT_MAX_CONCURRENT_RUNS (כנראה 1).\n- heartbeat.wakeOnDemand — default=true בקוד. אצלנו לא מוגדר אבל בפועל true.\n- heartbeat.enabled — default=false (timer off). זה הרצוי אצלנו.\n\nפעולה (Phase 1):\n1. עדכון runtime_config של כל סוכן: { heartbeat: { graceSec: 60, cooldownSec: 10, maxConcurrentRuns: 1, wakeOnDemand: true } }\n2. בעיקר graceSec — בלעדיו commit באמצע יכול להיכשל\n3. cooldownSec=10 (זהה לdefault ב-UI ליצירת agent חדש)\n\nהשפעה: minimal — רוב המקרים עובדים עם defaults. graceSec הוא העיקר.",
@@ -1194,7 +1194,7 @@
"updatedAt": "2026-05-04T07:47:02.008Z"
},
{
"id": "17",
"id": 17,
"title": "[Paperclip Gap 2] תקציבים = 0 לכל הסוכנים — אין budget enforcement",
"description": "budget_monthly_cents = 0 ו-spent_monthly_cents = 0 לכל 14 הסוכנים. Paperclip מציע cost control מובנה — אנחנו מתעלמים.",
"details": "ממצא: SELECT name, budget_monthly_cents, spent_monthly_cents FROM agents → הכל אפס.\n\nסיכון: לולאה חבויה יכולה לשרוף מאות $. אין auto-pause ב-80% spend (דפוס ש-CEO HEARTBEAT הרשמי מצפה לו).\n\nפעולה (Phase 3):\n1. מדידה: כמה כל סוכן באמת מוציא בחודש כיום (דרך לוגי claude-code, או Anthropic dashboard).\n2. הגדרת budget_monthly_cents סביר לכל סוכן (כותב Opus ≫ מנתח Sonnet).\n3. בדיקה שהמנגנון מפסיק כשמגיעים ל-100%.\n\nשאלה לחיים לפני ביצוע: באיזו רזולוציה למדוד? לפי Anthropic invoice, או לפי טוקנים בלוגים של claude_session?",
@@ -1206,7 +1206,7 @@
"updatedAt": "2026-05-04T10:18:08.046Z"
},
{
"id": "18",
"id": 18,
"title": "[Paperclip Gap 3] חסר X-Paperclip-Run-Id header בקריאות API",
"description": "ה-skill הרשמי קובע: 'You MUST include -H X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID on ALL API requests that modify issues'. ב-HEARTBEAT.md שלנו אין זכר לכך.",
"details": "ממצא: grep -n 'X-Paperclip-Run-Id' .claude/agents/ → 0 hits. כל curl ב-checkout/comments/PATCH issues — בלי הheader.\n\nסיכון: audit trail שבור. שאלה 'איזו ריצה שינתה את ה-issue X?' אין לה תשובה ב-DB.\n\nפעולה (Phase 1):\n1. עדכון .claude/agents/HEARTBEAT.md — דוגמאות ה-curl יכללו את הheader\n2. עדכון 6 קבצי הסוכנים (legal-ceo.md, legal-analyst.md, legal-researcher.md, legal-writer.md, legal-qa.md, legal-exporter.md) — כל מקום שיש curl POST/PATCH\n3. בדיקה שיש env var $PAPERCLIP_RUN_ID זמין בכל heartbeat",
@@ -1218,7 +1218,7 @@
"updatedAt": "2026-05-04T08:49:44.646Z"
},
{
"id": "19",
"id": 19,
"title": "[Paperclip Gap 4] לא משתמשים ב-/api/issues/{id}/interactions לאישורים",
"description": "Paperclip מציע API מובנה לאישור/שאלות (request_confirmation, ask_user_questions, suggest_tasks) עם idempotency keys ו-auto-wake. אנחנו עדיין כותבים 'חיים, מה לעשות?' כ-comment חופשי.",
"details": "סוגי interaction:\n- ask_user_questions — שאלות מובנות\n- request_confirmation — yes/no עם idempotency key (confirmation:{issueId}:plan:{revisionId})\n- suggest_tasks — הצעת עץ משימות\n- continuationPolicy: wake_assignee — wake אוטומטי על מענה\n- supersedeOnUserComment: true — בטל אם חיים עונה\n\nסיכון: אין UI מובנה לחיים (כפתורים), רק טקסט. אם הסוכן מתעורר פעמיים — שתי שאלות זהות.\n\nפעולה (Phase 2):\n1. בlegal-ceo.md — להחליף 'אם חיים לא הגדיר outcome: שאל בcomment' ב-request_confirmation\n2. בbrainstorm_directions — suggest_tasks במקום רשימת bullet\n3. בlegal-qa.md — request_confirmation לאישור export\n\nשאלה לחיים: האם תרצה לראות UI חדש או להישאר ב-Markdown comments?",
@@ -1234,7 +1234,7 @@
"updatedAt": "2026-05-04T11:18:59.050Z"
},
{
"id": "20",
"id": 20,
"title": "[Paperclip Gap 5] לא משתמשים ב-PAPERCLIP_WAKE_PAYLOAD_JSON fast-path",
"description": "בwake שמכוון ל-issue ספציפי, ה-env var מכיל כבר issue summary + comments חדשים דחוסים. ה-skill הרשמי אומר 'skip Steps 1-4 entirely'. שלנו תמיד fetcher גם ה-API.",
"details": "ממצא: HEARTBEAT.md סעיפים 2-2c תמיד פונים ל-API גם אם ה-payload כבר מכיל את הכל.\n\nתועלת: חיסכון 3-4 קריאות API לכל ריצה. בwakeups תכופים (CEO על comments) — חיסכון ניכר.\n\nפעולה (Phase 2):\n1. הוספה ל-HEARTBEAT.md בראש הסעיפים: 'אם $PAPERCLIP_WAKE_PAYLOAD_JSON קיים — קרא אותו ראשון. רק אם fallbackFetchNeeded:true או חסר הקשר רחב — fetch'.\n2. דוגמה לפענוח JSON: jq עם key paths\n3. בדיקה איזה wake reasons בכלל מקבלים payload (כנראה comment-driven בלבד)",
@@ -1248,7 +1248,7 @@
"updatedAt": "2026-05-04T09:15:46.339Z"
},
{
"id": "21",
"id": 21,
"title": "[Paperclip Gap 6] שאילתות psql ישירות ל-issue_attachments — שובר אבסטרקציה",
"description": "HEARTBEAT.md סעיף 2c משתמש ב-psql ישיר ל-issue_attachments + assets. אם schema ישתנה (כפי שצפוי בעדכוני Paperclip) — כל הסוכנים נשברים.",
"details": "ממצא: 6 קבצי סוכן + HEARTBEAT.md מכילים PGPASSWORD=paperclip psql ... FROM issue_attachments ia JOIN assets a.\n\nסיכון: breakage בעדכון Paperclip. כפילות לוגיקה (copy-paste בכל סוכן).\n\nפעולה (Phase 2):\n1. בדיקה אם קיים endpoint רשמי /api/issues/{id}/attachments (curl + grep ב-server/src/routes)\n2. אם כן — להחליף את כל ה-psql\n3. אם לא — להעביר את ה-psql למקום יחיד: helper ב-mcp-server (mcp__legal-ai__list_issue_attachments tool)\n4. אופציה ג: לפתוח issue ב-paperclipai/paperclip לבקש endpoint\n\nתלוי במחקר API.",
@@ -1262,7 +1262,7 @@
"updatedAt": "2026-05-04T09:28:18.058Z"
},
{
"id": "22",
"id": 22,
"title": "[Paperclip Gap 7] לא משתמשים ב-/api/issues/{id}/heartbeat-context",
"description": "Endpoint רשמי שמחזיר issue + ancestors + goal/project + comment cursor בקריאה אחת. אנחנו עושים 3 קריאות נפרדות.",
"details": "ה-skill הרשמי: 'Prefer GET /api/issues/{issueId}/heartbeat-context first. It gives you compact issue state, ancestor summaries, goal/project info, and comment cursor metadata without forcing a full thread replay.'\n\nשלנו: HEARTBEAT.md סעיפים 2 + 2b → שלוש קריאות (inbox-lite, issue, comments).\n\nפעולה (Phase 2):\n1. הוספת endpoint כצעד 6 ב-HEARTBEAT.md לפני 'Do the work'\n2. הסרת קריאות מיותרות שכבר ב-context\n3. שמירת comment cursor (after={last-seen-id}) לקריאות עוקבות",
@@ -1276,7 +1276,7 @@
"updatedAt": "2026-05-04T09:28:14.247Z"
},
{
"id": "23",
"id": 23,
"title": "[Paperclip Gap 8+11] HEARTBEAT.md ארוך + אין שימוש ב-skills של Paperclip",
"description": "HEARTBEAT.md שלנו 220 שורות (vs upstream 85). Paperclip מציע 8 skills מוכנים (paperclip, paperclip-create-agent, וכו') שאנחנו לא משתמשים באף אחד.",
"details": "תיקון לניתוח: מסתבר ש-CEO + 4 סוכנים אחרים כן משתמשים ב-paperclipSkillSync עם 4 paperclip skills (paperclip, paperclip-create-agent, paperclip-create-plugin, para-memory-files). חסר אצל: הגהת מסמכים ומנתח משפטי (skills_count=0).\n\nממצא: ls skills/ ב-paperclip repo → 8 skills. שלנו: 0 skills של Paperclip בשימוש.\n\nרלוונטיים לנו:\n- paperclip — API patterns + heartbeat checklist (יכול להחליף חלק מ-HEARTBEAT.md)\n- paperclip-create-agent — אם נוסיף סוכן\n- paperclip-create-plugin — לעדכוני plugin-legal-ai\n- paperclip-converting-plans-to-tasks — יכול להחליף brainstorm_directions\n- diagnose-why-work-stopped — לתחזוקה\n\nפעולה (Phase 3):\n1. קריאת skills/paperclip/SKILL.md מלא\n2. הזרקת skill לסביבת הסוכנים (כנראה דרך CLI: paperclipai agent local-cli)\n3. שכתוב HEARTBEAT.md לפי הדפוס: project-specific only, delegation לskill הרשמי לכלל ה-API\n4. יעד: ~120 שורות ב-HEARTBEAT.md שלנו\n\nשאלה לחיים: האם להזריק skills כסימלינקים ל-symlinks קיימים, או דרך paperclipai CLI?",
@@ -1296,7 +1296,7 @@
"updatedAt": "2026-05-04T16:44:27.553Z"
},
{
"id": "24",
"id": 24,
"title": "[Paperclip Gap 9] לבדוק bootstrapPromptTemplate deprecated באף סוכן",
"description": "מ-docs/agents-runtime.md: 'bootstrapPromptTemplate is deprecated... should be migrated to the managed instructions bundle system.' לבדוק האם adapter_config שלנו משתמש בזה.",
"details": "פעולה (Phase 1):\n1. SELECT name, adapter_config->'promptTemplate' as pt, adapter_config->'bootstrapPromptTemplate' as bpt FROM agents WHERE adapter_type = 'claude_local';\n2. אם בשימוש אצל סוכן כלשהו — מיגרציה למבנה החדש\n3. ייעוד: לבדוק תיעוד managed instructions bundle ב-paperclip docs\n\nהערה: זה כנראה לא ישפיע אצלנו (אנחנו משתמשים ב-symlinks ל-AGENTS.md/HEARTBEAT.md ישירות) — אבל חובה לוודא.",
@@ -1308,7 +1308,7 @@
"updatedAt": "2026-05-04T08:19:27.766Z"
},
{
"id": "25",
"id": 25,
"title": "[Paperclip Gap 10] סוכנים מוכפלים בין 2 חברות — אין סנכרון",
"description": "14 שורות = 7 סוכנים × 2 חברות (1xxx, 8xxx). כל שינוי בהגדרות הסוכן צריך להיעשות פעמיים. אין מנגנון סנכרון או הורשה.",
"details": "ממצא: SELECT name, COUNT(*) FROM agents GROUP BY name → 2 לכל אחד.\n\nסיכון: drift בין החברות. שינוי runtime_config ל-CEO של 1xxx יכול לפספס את CEO של 8xxx.\n\nפעולה (Phase 3):\n1. בדיקה: האם Paperclip תומך ב-shared agents או chainOfCommand? (לקרוא docs/companies/)\n2. אם כן — מיגרציה למבנה משותף\n3. אם לא — סקריפט סנכרון: scripts/sync_agents_across_companies.py שמעתיק כל שינוי מחברה לחברה\n\nשאלה לחיים: בעתיד אם יהיו עוד סוגי ערר (10xxx?) — להוסיף עוד חברה או להשאיר 2?",
@@ -1322,7 +1322,7 @@
"updatedAt": "2026-05-04T09:52:14.263Z"
},
{
"id": "26",
"id": 26,
"title": "[Paperclip Gap 12] עדכון @paperclipai/plugin-sdk + capabilities חדשות",
"description": "ה-plugin שלנו: @paperclipai/plugin-sdk@^2026.325.0, apiVersion: 1, minimumHostVersion: 2026.325.0. ה-host: 2026.428.0. ייתכן capabilities חדשות (issue.interactions.create, וכו').",
"details": "פעולה (Phase 4 — אחרי שדרוג Paperclip stable):\n1. cd /home/chaim/plugin-legal-ai && npm view @paperclipai/plugin-sdk version\n2. אם חדשה: npm install @paperclipai/plugin-sdk@latest\n3. קריאת adapter-plugin.md המעודכן ב-paperclip repo\n4. בדיקה אם apiVersion: 2 קיים\n5. הוספת capabilities חדשות אם רלוונטי (בעיקר issue.interactions.create אחרי gap #4)\n6. npm run build && reinstall plugin\n\nתלוי בgap #19 (interactions API) — אם אנחנו רוצים שהplugin יוכל ליצור interactions, חייב capability חדש.",
@@ -1337,7 +1337,7 @@
"updatedAt": "2026-05-26T12:19:16.180163Z"
},
{
"id": "27",
"id": 27,
"title": "[Paperclip Phase 4] שדרוג Paperclip לגרסה stable הבאה (לא 2026.428.0)",
"description": "כרגע אנחנו על 2026.428.0 — הגרסה היציבה האחרונה. כשיופיע stable חדש (כנראה 2026.5xx.x), לבצע שדרוג מבוקר.",
"details": "טריגר: npm view paperclipai dist-tags.latest מחזיר משהו ≠ 2026.428.0.\n\nפעולה:\n1. קריאת releases/v2026.5xx.x.md ב-GitHub\n2. בדיקת שינויים שעלולים להשפיע (CUSTOMIZATIONS.md סעיפים: hebrew, RTL, plugin driver, heartbeat)\n3. גיבוי: pg_dump של paperclip DB + cp -r ~/.npm/_npx/43414d9b790239bb /tmp/\n4. pm2 stop paperclip\n5. rm -rf ~/.npm/_npx/43414d9b790239bb\n6. npx paperclipai@latest run (יוריד גרסה חדשה)\n7. הרצה מחדש: ~/.paperclip/hebrew/apply-hebrew.sh && ~/.paperclip/issue-link-fix/apply-issue-link-fix.sh\n8. pm2 restart paperclip\n9. בדיקה ב-pc.nautilus.marcusgroup.org: עברית + plugin פעיל + סוכן מתעורר על comment\n\nתלוי בלי dependencies (יכול להיות מבוצע בכל עת אחרי שיש stable חדש).",
@@ -1349,7 +1349,7 @@
"updatedAt": "2026-05-26T12:19:16.180163Z"
},
{
"id": "28",
"id": 28,
"title": "[Paperclip Auxiliary] להפעיל skill-sync ל-2 סוכנים שפיספסו",
"description": "הגהת מסמכים ומנתח משפטי לא קיבלו אף פעם revision מסוג skill-sync (לעומת 5 האחרים שכן). לבצע sync.",
"details": "ממצא: בדיקה ב-agent_config_revisions:\n- עוזר משפטי: 3 skill-sync revisions (יש 7 skills)\n- חוקר תקדימים: 3 (יש 5)\n- מייצא טיוטה: 5 (יש 5)\n- בודק איכות: 1 (יש 5)\n- כותב החלטה: 1 (יש 5)\n- הגהת מסמכים: 0 (יש 0) ❌\n- מנתח משפטי: 0 (יש 0) ❌\n\nאופציות:\n1. UI: agent settings → 'sync skills'\n2. API: POST /api/agents/{id}/skills-sync (לאתר)\n3. CLI: paperclipai agent skill-sync (לבדוק אם קיים)\n4. SQL ידני (לא מומלץ — דורף revision tracking)\n\nSkills להעתקה (לפי בודק איכות):\n- paperclipai/paperclip/paperclip\n- paperclipai/paperclip/paperclip-create-agent\n- paperclipai/paperclip/paperclip-create-plugin\n- paperclipai/paperclip/para-memory-files\n- (אופציונלי) local/eba6210d5a/legal-decision",
@@ -1361,7 +1361,7 @@
"updatedAt": "2026-05-04T09:46:32.092Z"
},
{
"id": "29",
"id": 29,
"title": "[legal-ai UI] מסך הגדרות סוכנים — הצגה + עריכה + שמירה",
"description": "מסך אדמין ב-legal-ai UI שמציג את כל הגדרות הסוכנים (model, timeout, runtime_config, skills, budget) ומאפשר עריכה ושמירה. מונע SQL ישיר.",
"details": "מטרה: ממשק אדמין מרכזי במקום שעריכה תהיה רק ב-UI של Paperclip + SQL ישיר + CUSTOMIZATIONS.md.\n\nשדות (לכל סוכן × 2 חברות):\n1. adapter_config: model, effort, timeoutSec, maxTurnsPerRun, extraArgs[], paperclipSkillSync.desiredSkills[]\n2. runtime_config.heartbeat: graceSec, cooldownSec, wakeOnDemand, maxConcurrentRuns, enabled, intervalSec\n3. budget_monthly_cents (לקראת gap #2)\n4. status / pause_reason (קריאה + כפתור pause/resume)\n\nאופציות מימוש:\nA. עמוד חדש ב-legal-ai/web-ui (Next.js 16) — קורא Paperclip DB דרך FastAPI endpoint חדש (/api/admin/paperclip-agents)\nB. קריאה ל-Paperclip API (/api/companies/{id}/agents) — REST טהור, פחות שדות זמינים\nC. iframe ל-Paperclip UI — שטחי\n\nהמלצה: A. שולט מלא + ולידציה משפטית (timeoutSec >= 1800 כי OCR).\n\nתלוי ב: gap #25 (סוכנים מוכפלים) — אם נעבור לshared, המסך יתאים.\n\nשאלות פתוחות לחיים:\n- auth: מי יכול לגשת? (כיום אין auth ב-legal-ai)\n- bulk edit ל-2 חברות יחד או נפרד?\n- חשיפת skill marketplace (להוסיף/להוריד skills) או רק קריאה?",
@@ -1377,7 +1377,7 @@
"updatedAt": "2026-05-04T17:29:25.686Z"
},
{
"id": "30",
"id": 30,
"title": "תיקון 3 baגים בקטלוג (practice_area + source_kind + upload route)",
"description": "CRITICAL: 3 sub-bugs. (א) יצירת תיקים מתייגת practice_area='appeals_committee' במקום rishuy_uvniya/betterment_levy/compensation_197 לפי קידומת מספר התיק (1xxx/8xxx/9xxx) — audit + migration לכל התיקים הקיימים + תיקון נתיב היצירה. (ב) כל החלטה של ועדת ערר שהועלתה ל-case_law מסומנת כ-source_kind='external_upload' במקום 'internal_committee' — audit ל-case_law עם case_number שמתחיל ב'ערר' → reclassify + מילוי chair_name + district רטרואקטיבית. (ג) POST /api/precedent-library/upload לא מבחין — תיקון: ניתוב לפי תחילית הציטוט (ערר/ועדות ערר → internal_committee, אחרת → external_upload).",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #1. Pre-requirement: השתמש במחיקה+rerun של halachot אחרי שינוי source_kind. השתמש בpattern של internal_decisions.py (dry_run+log_action).",
@@ -1447,7 +1447,7 @@
"updatedAt": "2026-05-26T08:35:22.762800Z"
},
{
"id": "31",
"id": 31,
"title": "מיצוי chair_name + district בהעלאת ועדת ערר",
"description": "תוספת לטופס + חילוץ אוטומטי מהציטוט/text הפסיקה. רטרואקטיבי לכל הרשומות הקיימות עם source_kind='internal_committee' שהשדות בהן ריקים.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #2. תלוי במשימה #30 (sub-bug ב).",
@@ -1483,7 +1483,7 @@
"updatedAt": "2026-05-26T08:35:22.762800Z"
},
{
"id": "32",
"id": 32,
"title": "UI — דף עריכת פסיקה ייפתח רחב-במרכז (לא צר-בצד)",
"description": "חוסר נוחות בעריכה. שינוי ה-Dialog/Sheet ל-Modal רחב מרכזי. רלוונטי גם להוספת שדות chair_name + district מהמשימה #31.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #3.",
@@ -1495,7 +1495,7 @@
"updatedAt": "2026-05-26T10:38:07.071897Z"
},
{
"id": "33",
"id": 33,
"title": "UI — הסתרת עמודת 'שם' (case_name) בדף רשימת פסיקה",
"description": "רוב הערכים זהים למספר התיק. להסתיר את העמודה ב-UI, לשמור עמודה ב-DB לשימוש עתידי.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #4.",
@@ -1507,7 +1507,7 @@
"updatedAt": "2026-05-26T11:27:09.039154Z"
},
{
"id": "34",
"id": 34,
"title": "חילוץ ציטוטי-פנים מהחלטות דפנה (internal_committee + ירושלים)",
"description": "פאטרן: 'ונפנה להחלטות של ועדת ערר זו...', 'כפי שקבעתי בערר X', 'בדומה לעמדתי בהחלטה Y'. חילוץ אוטומטי + שמירה ב-precedent_internal_citations table שיאפשר ל-search_internal_decisions להחזיר גם את הפסיקה המוזכרת.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #5. תלוי במשימה #30 (sub-bug ב) ובמשימה #31.",
@@ -1522,7 +1522,7 @@
"updatedAt": "2026-05-26T10:38:07.071897Z"
},
{
"id": "35",
"id": 35,
"title": "דף/דוח 'פסיקה חסרה בקורפוס' — פיצ'ר מלא",
"description": "טבלת DB missing_precedents (id, citation, case_name, cited_in_case_id, cited_in_document_id, cited_by_party, legal_topic, legal_issue, claim_quote, status, linked_case_law_id, closed_at, created_at), API endpoints (POST/GET/upload/PATCH), MCP tools (missing_precedent_create/list/close), דף Next.js /missing-precedents, הוק אוטומטי במחקר ע\"י legal-researcher.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #6.",
@@ -1571,7 +1571,7 @@
"updatedAt": "2026-05-26T08:35:22.762800Z"
},
{
"id": "36",
"id": 36,
"title": "כינוס פרופוזיציות לטיעונים משפטיים אמיתיים (de-dup/aggregation)",
"description": "extract_claims מחזיר ~60 פרופוזיציות לתיק, צריך לאגד ל-~10 טיעונים משפטיים אמיתיים. טבלה חדשה legal_arguments + טבלת קישור legal_argument_propositions (M:M ל-case_claims). LLM aggregation job (Hermes/DeepSeek). API + MCP + UI display שמציג 'X טיעונים משפטיים' במקום 'Y טענות'.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #7.",
@@ -1614,7 +1614,7 @@
"updatedAt": "2026-05-26T08:35:22.762800Z"
},
{
"id": "37",
"id": 37,
"title": "הפרדת תתי-סוגי בל\"מ לפי practice_area",
"description": "3 ערכי appeal_subtype חדשים: extension_request_building_permit (1xxx, ס'152 - 30 ימים), extension_request_betterment_levy (8xxx, ס'14 לתוספת ג' - 45 ימים), extension_request_compensation (9xxx, ס'198(ד) - 30 ימים). 3 templates מתודולוגיים נפרדים. אוטו-זיהוי מהsubject. UI badge + filter.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #8. Pre-requirement: עדכון mcp-server/src/legal_mcp/services/practice_area.py APPEALS_COMMITTEE_SUBTYPES + עדכון web/paperclip_client.py mapping appeal_subtype → company.",
@@ -1657,7 +1657,7 @@
"updatedAt": "2026-05-26T08:35:22.762800Z"
},
{
"id": "38",
"id": 38,
"title": "שדרוג סוכני Paperclip להכרת השינויים מ-#30-#37",
"description": "עדכון 7 הגדרות סוכן (CEO/analyst/researcher/writer/QA/proofreader/exporter) + HEARTBEAT.md לזיהוי המבנים החדשים. בלי זה כל הפיצ'רים נשארים זמינים אבל הסוכנים לא יודעים להשתמש בהם. כולל הוספת research_complete כ-valid case_status.",
"details": "ראה תוכנית /home/chaim/.claude/plans/3-glimmering-oasis.md חלק א משימה #9. תלוי במשימות #30-#37.",
@@ -1740,7 +1740,7 @@
"updatedAt": "2026-05-26T07:41:47.880478Z"
},
{
"id": "39",
"id": 39,
"title": "[ROOT CAUSE] MCP tool חדש: internal_decision_upload",
"description": "הוספת @mcp.tool() עם chair_name+district חובה ו-source_kind='internal_committee' אוטומטי. סוגר את ה-root cause של Bug (ב) ב-#30. בלעדיו 44 רשומות חדשות יחזרו כ-external_upload תוך חודש.",
"details": "מיקום: mcp-server/src/legal_mcp/tools/internal_decisions.py (אם לא קיים — ליצור). רישום ב-server.py סביב שורה 169 (ליד precedent_library_upload). הקריאה מנותבת ל-int_decisions_service.ingest_internal_decision (קיים ב-internal_decisions.py).",
@@ -1754,7 +1754,7 @@
"updatedAt": "2026-05-26T07:41:37.260868Z"
},
{
"id": "40",
"id": 40,
"title": "[שלב B - ROI מיידי] הפעלת VOYAGE_RERANK_ENABLED=true ב-Coolify",
"description": "Cross-encoder rerank-2 ממומש ב-mcp-server/src/legal_mcp/services/rerank.py אבל כבוי בייצור (default=false). POC הוכיח +4.5% mean@3 ו-+11.6% practical queries (latency +702ms acceptable לזרימה האסינכרונית). 5 דקות עבודה — env change ב-Coolify.",
"details": "mcp__coolify__env_vars set VOYAGE_RERANK_ENABLED=true. ראה web/mcp_env_catalog.py:71-72 לdescription. אופציה: rampup רק על search_precedent_library (לא על find_similar_cases — latency-sensitive).",
@@ -1766,7 +1766,7 @@
"updatedAt": "2026-05-26T08:08:27.953285Z"
},
{
"id": "41",
"id": 41,
"title": "[שלב B] BM25/tsvector hybrid retrieval על precedent_chunks + halachot",
"description": "כיום כל החיפוש הוא 100% dense (cosine). ציטוטים מספריים ('עע\"מ 1461/20') נכשלים כי semantic לא מצליח בהם. הוספת tsvector GIN + RRF merge dense+lexical = +15-25% recall על ציטוטים — קריטי לאימות פסיקה ב-3-glimmering-oasis שלב 3.",
"details": "ALTER TABLE precedent_chunks ADD COLUMN content_tsv tsvector GENERATED ALWAYS AS (to_tsvector('simple', content)) STORED; CREATE INDEX ... USING gin (content_tsv). באותו אופן על halachot.rule_statement. ב-db.py:2357 (search_precedent_library_semantic) — להוסיף שאילתה מקבילה של websearch_to_tsquery → RRF merge עם cosine. אזהרה: postgres אינו תומך ב-'hebrew' config — simple config יעבוד אבל בלי stemming.",
@@ -1780,7 +1780,7 @@
"updatedAt": "2026-05-26T08:08:27.953285Z"
},
{
"id": "42",
"id": 42,
"title": "[שלב B] Query expansion via Claude Haiku — 2-3 variants per query",
"description": "שאילתות עם abbreviations משפטיות ('בל\"מ'/'בקשה להארכת מועד') חוטפות recall. LLM expansion: שאילתה → 2-3 variants → union retrieval. +10-15% recall.",
"details": "בוטל 2026-06-03 — obviated. BM25_HYBRID_ENABLED=true כבר פעיל ותופס קיצורים לקסיקלית (בל\"מ כ-token). ב-gold-set (86 שאילתות) 0 שאילתות-קיצורים, ו-recall כללי ≈0.99 — אין gap נמדד. Query-expansion דרך LLM מוסיף latency+עלות לכל שאילתה ללא צורך מוכח (YAGNI). re-open trigger: אם eval ייעודי על שאילתות-קיצורים יראה recall<0.9.",
@@ -1794,7 +1794,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "43",
"id": 43,
"title": "[שלב B] MMR / diversity penalty — limit 2 chunks per case_law_id",
"description": "תוצאות חיפוש דומות מאוד זו לזו (אותה פסיקה, chunks סמוכים) — פסיקות חוזרות תופסות slots → diversity@10 נמוך. הוספת cap per case_law_id (2-3 max) או MMR אמיתי.",
"details": "פתרון קל: SQL DISTINCT ON (case_law_id) + 2 בpost-processing. פתרון איכותי: MMR — לכל candidate, score = λ*relevance - (1-λ)*max_similarity_to_selected. λ=0.7 דיפולט.",
@@ -1808,7 +1808,7 @@
"updatedAt": "2026-05-26T08:08:27.953285Z"
},
{
"id": "44",
"id": 44,
"title": "[שלב B] HNSW migration (or lists=68 IVFFlat) + REINDEX",
"description": "IVFFlat lists=50 עם 4,595 vectors — sub-optimal. sqrt(4595)≈68. HNSW עדיף ל-recall (אבל יותר זיכרון). שיפור +3-5% recall@10.",
"details": "אופציה 1: REINDEX עם lists=68 (פשוט, idempotent). אופציה 2: DROP+CREATE עם HNSW (m=16, ef_construction=64) — דורש pgvector ≥0.5 ובדיקת זמן build. בדוק SELECT extversion FROM pg_extension WHERE extname='vector'.",
@@ -1820,7 +1820,7 @@
"updatedAt": "2026-05-26T08:08:27.953285Z"
},
{
"id": "45",
"id": 45,
"title": "[שלב B] Halacha auto-approve sweep — בדיקת 219 pending + הורדת סף ל-0.78",
"description": "219 halachot pending review (17%) חסומות מ-search. אם dafna לא מסקר ידנית — הם מתבזבזים. dashboard batch + הורדת auto-approve threshold.",
"details": "1. בדוק 20 דגימות אקראיות של pending — אם רובן ראויות לאישור, הורד HALACHA_AUTO_APPROVE_THRESHOLD מ-0.80 ל-0.78. 2. הוסף UI batch approval ב-/halachot עם filter pending+confidence>0.75. 3. one-shot SQL לאישור 200 halachot שעמדו בקריטריונים החדשים.",
@@ -1832,7 +1832,7 @@
"updatedAt": "2026-05-26T08:08:27.953285Z"
},
{
"id": "46",
"id": 46,
"title": "[שלב B] Dynamic halacha boost — לפי query-rule similarity",
"description": "כיום halacha boost = +0.05 קבוע. דינמי לפי query similarity ירוץ דייקנות (5% precision על שאילתות ספציפיות).",
"details": "ב-db.py:2479 — score = float(d['score']) + 0.05. החלף ב-boost = 0.10 * d['score'] (proportional). או — אם rerank ON, השתמש בrerank score כbaseline (אין צורך ב-boost כלל).",
@@ -1846,7 +1846,7 @@
"updatedAt": "2026-05-26T08:08:27.953285Z"
},
{
"id": "47",
"id": 47,
"title": "[שלב C - prevention] Audit script periodic: detect new external_upload עם case_number של ערר",
"description": "Drift detection: שגיאה דומה ל-Bug (ב) יכולה לחזור בעתיד. periodic check (יומי?) + alert ל-Slack/comment.",
"details": "scripts/audit_corpus_consistency.py — בודק: 1. case_law WHERE source_kind='external_upload' AND case_number ~ '^ערר|^ARAR'. 2. case_law WHERE source_kind='internal_committee' AND chair_name IS NULL. הרצה דרך cron או scheduled task ב-Paperclip.",
@@ -1861,7 +1861,7 @@
"updatedAt": "2026-05-26T11:27:09.039154Z"
},
{
"id": "48",
"id": 48,
"title": "[שלב C] Parent-doc retrieval (child=300, parent=1500 tokens)",
"description": "chunk_size=600 חותך חלק מהלכות ארוכות. parent-doc: חיפוש על child קטן (300 tokens), החזרת parent גדול (1500 tokens) ל-LLM context.",
"details": "מיגרציה DB: precedent_chunks.parent_chunk_id (FK self). chunking pipeline משתנה ל-2 רמות. retrieval: SELECT distinct parent_chunk WHERE child_chunk matches.",
@@ -1875,7 +1875,7 @@
"updatedAt": "2026-05-26T11:27:09.039154Z"
},
{
"id": "49",
"id": 49,
"title": "[שלב C] Multimodal backfill ל-77 רשומות שנותרו",
"description": "כיום 40/117 precedent_image_embeddings (34%). 77 רשומות נותרו ללא image embeddings. ערך נמוך כשהמסמכים digital-native, אבל קריטי לscanned PDFs.",
"details": "scripts/multimodal_backfill.py כבר קיים. להריץ עם batch size 10 כדי לא לדפוק את Voyage rate limits. אומדן: 77×~10K tokens = ~770K tokens ($10-15).",
@@ -1887,7 +1887,7 @@
"updatedAt": "2026-05-26T11:27:09.039154Z"
},
{
"id": "50",
"id": 50,
"title": "[שלב C] Closed-loop retrieval feedback + ndcg dashboard",
"description": "אין tracking של 'what was retrieved → what writer cited'. בלי זה — אי אפשר לעדכן את ה-RAG בצורה מדודה לאורך זמן.",
"details": "טבלה חדשה retrieval_feedback (query, candidates_retrieved JSONB, cited_in_final_decision UUID[], created_at). hooks ב-writer לדווח. dashboard חודשי עם ndcg@10.",
@@ -1899,7 +1899,7 @@
"updatedAt": "2026-05-26T11:27:09.039154Z"
},
{
"id": "51",
"id": 51,
"title": "[שלב C] Halacha quality monitoring — confidence drift, alert",
"description": "אם prompt או model משתנה — confidence distribution יכול לזוז. בלי monitoring — דרדור איכות עובר תחת הראדר.",
"details": "scheduled job: weekly mean confidence per practice_area. אם זז ביותר מ-0.05 — alert. dashboard ב-/halachot עם histogram.",
@@ -1911,7 +1911,7 @@
"updatedAt": "2026-05-26T11:27:09.039154Z"
},
{
"id": "52",
"id": 52,
"title": "[Retrieval RC-A] הוספת case_name + case_number ל-tsvector הלקסיקלי",
"description": "השורש האמיתי לכך שסוכן לא מאתר החלטה לפי שם (אגסי). ה-tsvector הלקסיקלי (SCHEMA_V12_SQL ב-db.py) בנוי רק מ-precedent_chunks.content ומ-halachot rule/quote/reasoning — לא משם התיק/הצד או ממספר התיק. לכן שאילתת-שם מחזירה את מי שמצטט את ההחלטה, לא את ההחלטה עצמה. לשלב את case_law.case_name + case_number באינדקס הלקסיקלי (tsvector ייעודי על case_law או setweight) כך שחיפוש לפי שם יפגע ברשומה עצמה.",
"status": "done",
@@ -1923,7 +1923,7 @@
"updatedAt": "2026-05-30T11:05:36.307Z"
},
{
"id": "53",
"id": 53,
"title": "[Retrieval RC-B] חיפוש/רשימה מאוחדים — לא לחתוך internal_committee",
"description": "החלטות ערר/בל\"מ שמועלות נשמרות source_kind='internal_committee'. precedent_library_list ברירת מחדל external_upload ומסתיר אותן; כלי ה-MCP precedent_library_list אפילו לא חושף פרמטר source_kind, כך שסוכן לעולם לא יכול לדפדף בהן. לחשוף source_kind/all_committees בכלי ה-MCP ובמידת הצורך לאחד את שכבת ה-list/search.",
"status": "done",
@@ -1937,7 +1937,7 @@
"updatedAt": "2026-05-30T11:09:44.511Z"
},
{
"id": "54",
"id": 54,
"title": "[Retrieval RC-3] הנחיית סוכנים — איתור לפי שם + שני קורפוסים",
"description": "לעדכן הנחיות legal-analyst/researcher/writer: לאיתור החלטה ספציפית לפי שם להוסיף מונחי תוכן או מספר תיק, ולחפש בשני הקורפוסים (search_internal_decisions + search_precedent_library) לפני שמסיקים 'לא קיים בקורפוס'. כולל יצירת missing_precedent רק אחרי חיפוש כפול.",
"status": "done",
@@ -1951,7 +1951,7 @@
"updatedAt": "2026-05-30T11:12:44.727Z"
},
{
"id": "55",
"id": 55,
"title": "[Retrieval RC-4] תיקון chunking — פרגמנטים זעירים",
"description": "בתוצאות החיפוש מופיעים chunks של מילה-שתיים ('דיון','דיון וב','סיכום ו') כתוצאות מובילות. מציפים תוצאות ומורידים דירוג תוכן אמיתי. לחקור את chunker.py (פיצול לפי כותרת-סעיף שיוצר chunks ריקים) ולתקן: מינימום אורך chunk / מיזוג כותרת לגוף.",
"status": "done",
@@ -1965,7 +1965,7 @@
"updatedAt": "2026-05-30T11:19:23.923Z"
},
{
"id": "56",
"id": 56,
"title": "[Retrieval finding] halacha_filters לא מסננים source_kind — דליפה חוצת-קורפוסים",
"description": "התגלה תוך כדי משימה 53. ב-search_precedent_library_semantic וב-search_precedent_library_lexical (db.py): chunk_filters כוללים cl.source_kind=$sk אבל halacha_filters כוללים רק review_status. תוצאה: search_precedent_library(external) מחזיר גם הלכות internal_committee, ו-search_internal_decisions(internal) מחזיר גם הלכות external. אי-עקביות: chunks מסוננים, halachot לא. כרגע זה דווקא מסייע למציאוּת (לכן לא רגרסיה), אבל לא עקבי. דורש החלטת מדיניות: או לסנן halachot גם לפי source_kind (עקבי, אך 'מסתיר' שכבות), או להשאיר מאוחד במכוון + לתעד. אם משאירים מאוחד — לעדכן docstrings של שני הכלים שזה לא 'corpus נפרד'.",
"status": "cancelled",
@@ -1977,7 +1977,7 @@
"updatedAt": "2026-05-30T11:09:30.257989+00:00"
},
{
"id": "57",
"id": 57,
"title": "[Retrieval #55 follow-up] re-chunk+re-embed של פסיקה שהוטמעה לפני תיקון ה-chunker",
"description": "משימה 55 תיקנה את ה-chunker (עיגון כותרות + מיזוג) ומסננת את 484 הפרגמנטים בזמן query. הרמדיאציה המלאה: re-chunk מ-full_text השמור (ללא re-OCR — תואם feedback_no_reocr_retrofit) + re-embed, כדי שהתוכן יהיה נכון ולא רק מוסתר. נדחה כי זו מיגרציית-נתונים עם עלות Voyage API על ~13+ תיקים — דורש אישור עלות מ-chaim לפני הרצה. לבדוק כמה תיקים מושפעים (יש להם chunk<50) ולהריץ בקבוצות.",
"status": "done",
@@ -1991,7 +1991,7 @@
"updatedAt": "2026-06-03T07:56:21.688Z"
},
{
"id": "58",
"id": 58,
"title": "[Case access] get_case_by_number שביר לפורמט — סוכן 'עיוור' למסמכי תיק",
"description": "דווח ע\"י chaim: סוכן כתב שחסרים מסמכי תיק כי document_list החזיר ריק, אך המסמכים קיימים. שורש: get_case_by_number (db.py) עושה 'WHERE case_number=$1' התאמה מדויקת בלבד. אומת — 8137-24 מחזיר 9 מסמכים, אבל 8137/24 / 'ערר 8137-24' / רווחים / zero-pad → 'תיק לא נמצא'. הסוכן מקבל את המספר בפורמט שונה (כותרת issue, לוכסן, תחילית ערר/בל\"מ) → התאמה נכשלת → 'אין מסמכים'. משפיע על כל הכלים מבוססי case_number (document_list, extract_references, search_case_documents, get_claims, draft, וכו'). תיקון: נורמליזציה (strip prefix לתחילת ספרה, trim, '/'→'-') + fallback בשאילתה. תיקון נקודה-אחת מתקן את כל הכלים.",
"status": "done",
@@ -2003,7 +2003,7 @@
"updatedAt": "2026-05-30T11:54:34.291Z"
},
{
"id": "59",
"id": 59,
"title": "[FU-1] איחוד מסלול ה-ingest למסלול קנוני אחד",
"description": "מאחד את ingest_precedent ו-ingest_internal_decision למסלול קנוני יחיד; מבטל את האסימטריות.",
"details": "מכסה GAP-01,02,04,05. מספק INV-ING1/ING3/G2/G4. severity: Critical. סוג: קוד. יסוד — FU-2/FU-3/FU-7 תלויים בו. מקור: docs/spec/gap-audit.md + 01-ingest.md.",
@@ -2056,7 +2056,7 @@
"updatedAt": "2026-05-30T17:37:34.741136+00:00"
},
{
"id": "60",
"id": 60,
"title": "[FU-2a] ingest idempotent + נרמול-בכתיבה + searchable (pure-code)",
"description": "upsert ON CONFLICT על מפתח קנוני + נרמול case_number בכתיבה (type-aware) + דגל searchable מפורש. אפס מיגרציית-נתונים.",
"details": "מכסה GAP-03,06,13. מספק INV-ING2/G3/G1/ID1/DM1. severity: Critical. סוג: pure-code (schema-additive). תלוי ב-FU-1 (#59). FU-2b (#67) מטפל ב-GAP-07/08 בנפרד.",
@@ -2101,7 +2101,7 @@
"updatedAt": "2026-05-30T17:37:34.741136+00:00"
},
{
"id": "61",
"id": 61,
"title": "[FU-3] re-index בשינוי תוכן",
"description": "embedding מתעדכן אוטומטית בשינוי תוכן (כיום trigger-dependent, לא GENERATED).",
"details": "מכסה GAP-09. מספק INV-DM3/G6. severity: High. סוג: קוד + מיגרציה (re-embed). תלוי ב-FU-1.",
@@ -2138,7 +2138,7 @@
"updatedAt": "2026-05-30T17:37:34.741136+00:00"
},
{
"id": "62",
"id": 62,
"title": "[FU-4] בידוד-קורפוס בכל מסלול query",
"description": "אכיפת source_kind בכל פילטר (כולל halacha_filters); חסימת חיפוש ללא תחום.",
"details": "מכסה GAP-10,12. מספק INV-RET1/G5. severity: Critical. סוג: קוד. ללא תלות — דחוף (דליפה פעילה).",
@@ -2173,7 +2173,7 @@
"updatedAt": "2026-05-30T18:30:11.503Z"
},
{
"id": "63",
"id": 63,
"title": "[FU-5] eval-harness + נראות backlog",
"description": "מדידת precision/recall על gold-set + חשיפת backlog הלכות בבדיקת-בריאות.",
"details": "מכסה GAP-11,14. מספק INV-RET4/G8/QA1/G10. severity: High. סוג: קוד + החלטת-יו\"ר (בניית gold-set). תלוי ב-FU-2. | DONE 2026-05-31: Unit B (GAP-14) — halacha_backlog נחשף ב-metrics.get_dashboard + /api/system/diagnostics (גילה 178 pending_review מתוך 1552, הישן 3.5.26). Unit A (GAP-11) — scripts/eval_gold_bootstrap.py (citations+known_item) + scripts/eval_retrieval.py (P/R/MRR/nDCG@5,10, self-test, baseline+config). gold-set=77 known-item queries (citation-source ריק: 0 ציטוטים בהחלטות). baseline בייצור: R@10=0.987 MRR=0.837; ממצא: MULTIMODAL=true מוריד known-item recall קלות (relevant ל-#15). gold-set=provisional עד סקירת דפנה (chair-gate; הדומיין). spec: docs/superpowers/specs/2026-05-31-fu5-eval-harness-design.md",
@@ -2210,7 +2210,7 @@
"updatedAt": "2026-05-31T14:55:38.295Z"
},
{
"id": "64",
"id": 64,
"title": "[FU-6] שערי-QA נאכפים בקוד",
"description": "export חוסם בקוד על כשל-QA קריטי; תיקון neutral_background critical-but-passes.",
"details": "מכסה GAP-15,16. מספק INV-QA3/EX3/G10. severity: Critical. סוג: קוד. ללא תלות — מהיר.",
@@ -2245,7 +2245,7 @@
"updatedAt": "2026-05-30T18:30:11.521Z"
},
{
"id": "65",
"id": 65,
"title": "[FU-7] audit-trail + provenance",
"description": "כתיבת audit_log בכל פעולה; קישור בלוק→קטעי-מקור; סנכרון DB אחרי עריכה; אימות citation→corpus.",
"details": "מכסה GAP-17,18,19,20. מספק INV-AUD1/2/3/EX1/G9. severity: High. סוג: קוד + backfill קל. תלוי ב-FU-1. (זרע לתת-פרויקט 3/audit-provenance.)",
@@ -2300,7 +2300,7 @@
"updatedAt": "2026-05-30T17:37:34.741136+00:00"
},
{
"id": "66",
"id": 66,
"title": "[FU-8a] מחסומי-תהליך→קוד: enforce sync + Paperclip-access guard (pure-code)",
"description": "אכיפת cross-company sync (--verify יוצא non-zero על drift; adapter_type mismatch = drift לא silent skip) + fitness-function שחוסם גישת-Paperclip לא-מאושרת (raw http / INSERT agent_wakeup_requests).",
"details": "מכסה GAP-21,22. מספק INV-MC1/INT1/INT3. severity: High. סוג: pure-code. GAP-23 (חיווט ספ→סוכנים) הופרד ל-#69 (משנה התנהגות-ייצור). | DONE 2026-05-31 PR#16: --verify drift-gate (exit≠0) + Paperclip-access fitness function. GAP-23→#69.",
@@ -2333,7 +2333,7 @@
"updatedAt": "2026-05-30T17:37:34.741136+00:00"
},
{
"id": "67",
"id": 67,
"title": "[FU-2b] תיאום מזהים קנוניים + ניקוי ציטוט-כמזהה (data-migration, chair)",
"description": "מיגרציה חד-פעמית של ~52+ רשומות case_law עם ציטוט-מלא ב-case_number → מספר-בסיס מנורמל; dedup (למשל 8047-23 כפול); הכרעת צורה קנונית per-record.",
"details": "מכסה GAP-07,08. מספק INV-ID1/ID2/DM2. severity: High. סוג: DATA-MIGRATION + chair-decision (מספר רשמי per-record, with-month canonical). דורש: גיבוי, dry-run, סקירת-יו\"ר, reversibility. תלוי ב-FU-2a (#60, לצורך פונקציית הנרמול). מקור: בדיקת DB 2026-05-30 — internal_committee ~52/56 ציטוט-מלא, ≥1 dup (8047-23), 1 בלתי-פתיר (ערר אדלר/cited_only). | APPLIED 2026-05-31: 55 internal rows normalized to bare case_number; corrupted 8047 dup (מטודלה) deleted; חלוואני 1028-20 proc→בל\"מ. Backups in data/audit/fu2b-*. external→#68.",
@@ -2367,7 +2367,7 @@
]
},
{
"id": "68",
"id": 68,
"title": "[FU-2c] תיאום מזהי external_upload (case_number↔citation_formatted)",
"description": "פסיקה חיצונית: case_number מחזיק ציטוט מלא; citation_formatted לא תמיד תואם (נמצאה סתירה 25226-04-25 מול 1975/24). דורש קודם תיקון סתירות citation_formatted↔case_number, ואז הכרעה אם docket מחולץ הופך ל-case_number או שהציטוט נשאר המזהה.",
"details": "מקור: בדיקת DB 2026-05-31 (FU-2b scoping). 22/24 external עם ציטוט ב-case_number; citation_formatted נוצר בנפרד (LLM) ולא אמין כ-ground truth. שונה מ-internal (שם 0 סתירות). דורש סקירת-יו\"ר פר-רשומה. severity: Medium. סוג: data-migration + chair. תלוי בהחלטה: האם זהות external = ציטוט (FU-1) או docket מנורמל (INV-ID2). מופרד מ-FU-2b לפי החלטת chaim 2026-05-31. | APPLIED 2026-05-31: chair decision Option A (designator+docket, '/' kept). 21 external_upload case_number normalized + 3 citation_formatted fixed (D=לויתן/קלמנוביץ consolidated→25226-04-25; 2×C empty-citation composed). אהוד שפר עע\"מ 317/10 deferred (cross-source dup w/ cited_only → #70). collision-guard: 0. Backups data/audit/fu2c-backup-20260531T140943Z.csv. cited_only(49)→#70.",
@@ -2381,7 +2381,7 @@
"updatedAt": "2026-05-31T14:11:37.689Z"
},
{
"id": "69",
"id": 69,
"title": "[FU-8b] חיווט הספ לסוכני-Paperclip (GAP-23)",
"description": "HEARTBEAT/agent docs דורשים קריאת 00-constitution + ספ-תחום רלוונטי לפני פעולה. משנה התנהגות-סוכן בייצור; prereq לתת-פרויקט 5.",
"details": "מכסה GAP-23. מספק INV-AG1. severity: High. סוג: docs+chair-decision. דורש ספ יציב (קיים) + החלטה על שילוב בזרימת-הסוכנים. הופרד מ-FU-8a לפי החלטת chaim 2026-05-31 (GAP-21/22 = pure-code עכשיו).",
@@ -2407,7 +2407,7 @@
"updatedAt": "2026-05-31T16:01:42.032Z"
},
{
"id": "70",
"id": 70,
"title": "[FU-2c-b] תיאום + dedup של cited_only (49 רשומות) + אהוד שפר cross-source",
"description": "המשך ל-FU-2c (#68). ה-dry-run של תיאום-המזהים החיצוני חשף 49 רשומות source_kind='cited_only' (הפניות-ציטוט שחולצו מהחלטות) שלא היו בהיקף #68. דורשות נרמול נפרד: צורות-ועדה כמו 'ערר 1093-19' (NNNN-NN) שה-extractor הנוכחי לא תופס (NO_DOCKET), 'בש\"א 2487-14', dups, ו-'ערר אדלר' בלתי-פתיר (ללא מספר). בנוסף: dedup חוצה-source של אהוד שפר — external_upload 'עע\"מ 317/10 אהוד שפר' מול cited_only קיים 'עע\"מ 317/10' (אותו תיק; ה-collision-guard מנע התנגשות ב-uq_case_law_external_number, ה-external_upload נשאר עם case_number מנופח עד הכרעה).",
"details": "[2026-06-03] נרמול מבוסס-מחקר (4 מקורות: ECLI work-level id, Akoma Ntoso FRBR Work/Manifestation, ELI canonical+alias, OpenCitations OMID + Christen data-matching). מדיניות: צורה קנונית אחת + alias; cited_only stub = אותו Work כמו ה-doc → merge על התאמה-מדויקת בלבד; un-resolvable = display+flag, לא למחוק; merge = re-point edges + dedup, שמרני (false-merge בגרף-ציטוט יקר). בוצע: 46 רשומות cited_only סווגו; 3 תיקונים מכניים-דטרמיניסטיים הוחלו (ערר \\n316/10→ערר 316/10; עע\"מ65/13→עע\"מ 65/13; עע\"מ9057/09→עע\"מ 9057/09). 0 malformed (whitespace/no-space) נותרו. **נותר לשיקול יו\"ר (לא ננחש, לפי המשמר)**: (1) 2 garbled — 'ערר 1078/0724' (4a38c202), 'ערר 1083/0724' (6682f9cb); (2) 'ערר אדלר' (863a7bf8) ללא docket → keep+flag; (3) combined 'ערר (ירושלים) 1078+1083/24' (e7f6fd06) → פיצול ל-1078/24+1083/24 מתנגש עם stub קיים 'ערר 1083/24' → entity-resolution ידני. תוספת קוד עתידית: טיפול '+' ב-citation_extractor. הדדאפ הקודם (shafer + stub cleanup) כבר הושלם. אלה chair-domain — לא הכרעת-מהנדס. [2026-06-03 סגירה]: בדיקת-קשתות חשפה ש-4 ה'דו-משמעיים' (+11 נוספים) הם stubs **יתומים מתים** — 0 קשתות בכל 5 מנגנוני-הציטוט, 0 full_text, 0 הלכות, 0 chunks/embeddings. כלומר ניקוי טכני, לא שיפוט-יו\"ר (OpenCitations שומר ישות חסרת-מזהה רק אם מצוטטת — אלה לא). נמחקו 15 יתומים (cited_only 46→31), גיבוי data/audit/fu2b-orphan-stub-cleanup-20260603T093741Z.json. 0 malformed/יתומים נותרו; כל 31 הנותרים מצוטטים. forward-edge ידוע (לא חוסם, ללא משימה): טיפול '+' בציטוט-משולב ב-citation_extractor אם יחזור בחילוץ עתידי. #70 done.",
@@ -2421,7 +2421,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "71",
"id": 71,
"title": "[FU-5 follow-up] כוונון עומק-אחזור/rerank — recall רב-תקדימי לסוגיות רחבות",
"description": "נפתר ע\"י תיקון ה-weight של #15 (multimodal 0.5→0.65). מדידה 2026-06-03: כל 11 השאילתות הרב-תקדים/יו\"ר מחזירות את כל התקדימים הרלוונטיים ב-top-10 (רובם top-6; גרוע ביותר rank 9). השאילתות החלשות מהבייסליין (S2 הבית-שמעוני@16, S4 ב.דייניש@15, S7@15, S8) כולן תוקנו. recall@10≈1.0.",
"details": "החלטה מבוססת-מדידה+מחקר (6 מקורות: Cormack RRF, Drowning-in-Documents 2411.11767, ReFIT, MMR, Elastic, Pinecone). המחקר המליץ להפעיל rerank (fetch_k=50,return_k=10); בדקתי אמפירית — VOYAGE_RERANK_ENABLED=true דווקא הזיק: nDCG@5 0.879 מול 0.960, MRR 0.867 מול 0.954, R@5 0.966 מול 0.994 (כל המדדים שליליים). הסיבה: recall כבר רווי, וה-cross-encoder הכללי מוריד את ההתאמה המדויקת ב-known-item. **המדידה גוברת על התיאוריה — לא מפעילים rerank, לא מעלים limit, RRF_K=60 נשאר.** אין שינוי-קוד נדרש.",
@@ -2435,7 +2435,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "72",
"id": 72,
"title": "[ops] MCP 'No such tool' תחת עומס חילוץ opus-4-8@xhigh — timeout ב-handshake",
"description": "בריצת CMPA-71 (חילוץ הלכות 9002-24, סוכן עוזר משפטי) שרת ה-legal-ai MCP לא נטען — כל קריאות mcp__legal-ai__* החזירו 'No such tool available' אחרי 3 ניסיונות+המתנות; הסוכן עשה fallback ל-.venv ישיר (לפי legal-ceo.md) והחילוץ הצליח על claude-opus-4-8@xhigh.",
"status": "done",
@@ -2446,7 +2446,7 @@
"subtasks": []
},
{
"id": "73",
"id": 73,
"title": "החלטת ועדת ערר: ברירת מחדל is_binding=false (יישור דוקטרינרי)",
"description": "כשמעלים החלטת ועדת ערר דרך מסך העלאת הפסיקה (precedent-upload-sheet, isCommittee=true), הצ'קבוקס 'הלכה מחייבת' (is_binding) כברירת מחדל הוא true — כך שההלכות שמחולצות מהחלטה לא-מחייבת מתויגות rule_type='binding'. זה סותר את ההגדרה הדוקטרינרית שלנו (ועדת ערר = persuasive בלבד, לא binding כמו עליון/מנהלי). התיקון: כש-isCommittee=true ב-precedent-upload-sheet.tsx, להפוך את is_binding ל-false כברירת מחדל (או לנעול/להסתיר את הצ'קבוקס ולתייג אוטומטית persuasive). הערה חשובה: זהו תיקון יישור-דוקטרינרי בלבד — אין השפעה downstream על ranking/injection (rule_type הוא תווית תצוגה; השער הפונקציונלי האמיתי הוא review_status שדפנה שולטת בו ידנית). קבצים: web-ui/src/components/precedents/precedent-upload-sheet.tsx (useState isBinding שורה 47, isCommittee שורה 53); guard clause קיים ב-mcp-server/src/legal_mcp/services/halacha_extractor.py:229-235 שמוריד binding→persuasive רק כאשר is_binding=false.",
"details": "",
@@ -2458,7 +2458,7 @@
"updatedAt": "2026-05-31T20:41:04.160Z"
},
{
"id": "74",
"id": 74,
"title": "ניקוי רטרואקטיבי: rule_type binding→persuasive להלכות ממקור ועדת ערר",
"description": "המשך משימה #73 (PR #29 מנע binding חדש לועדת ערר מכאן והלאה). יש 82 הלכות קיימות ב-DB עם rule_type='binding' שמקורן (case_law) בהחלטת ועדת ערר — בסתירה לדוקטרינה (ועדת ערר = persuasive). פילוח: 75 approved + 7 pending_review. גישה #2 (שמרנית): לתקן רק את ה-binding ל-persuasive, ולהשאיר interpretive/procedural/application/obiter כמות שהם (תקינים גם לועדת ערר). הגדרת 'מקור ועדת ערר': case_law WHERE source_type='appeals_committee' OR precedent_level LIKE 'ועדת%' OR court LIKE '%ועדת%ערר%' OR court LIKE '%ועדות ערר%'. שאילתה: UPDATE halachot SET rule_type='persuasive' WHERE rule_type='binding' AND case_law_id IN (<committee case_law ids>). הערה: rule_type הוא תווית תצוגה בלבד — אין השפעה על ranking/injection (השער הפונקציונלי הוא review_status). DB: legal_ai על Postgres pgvector קונטיינר t84kegpjm5qrttd6nw7bgoxe (פורט 5433). ביצוע דרך docker exec עם trust מקומי. לגבות/לספור לפני ואחרי לאימות (צפוי: 82 שורות מושפעות, 0 binding ממקור ועדת ערר אחרי).",
"details": "",
@@ -2472,7 +2472,7 @@
"updatedAt": "2026-05-31T20:49:28.894Z"
},
{
"id": "75",
"id": 75,
"title": "[X11 Phase 2] חיווט אוטו-אישור מבוסס-ציטוט + backfill",
"description": "Phase 2 של citation-corroboration (X11). Phase 1 (האות) מוזג ב-PR #27. דפנה אימתה את האות ואישרה הפעלה (2026-06-01). Phase 2: (1) חיווט אוטו-אישור — הלכה corroborated (≥2 ציטוטים חיוביים בלתי-תלויים, 0 שליליים) עוברת ל-review_status='approved' עם reviewer='corroborated (…judicial citations)' (INV-COR4/G10); (2) הדחת overruled — הלכה approved שקיבלה טיפול overruled בציטוט מאוחר חוזרת לשער-היו\"ר (INV-COR2); (3) backfill על 12 התקדימים (halachot+ציטוטים-נכנסים); (4) כלי-MCP write להרצת rebuild.",
"details": "דגל: HALACHA_CORROBORATION_AUTO_APPROVE (default true, env-tunable). פונקציית-הכרעה טהורה approval_action(agg, has_overruled)→'approve'/'demote'/None (unit-tested, INV-COR2/COR4). DB: approve_halacha_by_corroboration (רק על pending_review), demote_halacha_overruled (רק על approved→pending_review), list_corroboration_grouped, precedents_with_halachot_and_incoming_citations. שירות: reconcile_approvals מופעל בסוף build_for_precedent; build_all driver. backfill target=12 תקדימים (אומת 2026-06-01). נדחה ל-backlog (proposal-only, מסוכן-תוכן): enrichment של rule_statement, treatment-backfill ל-case_law_citations.citation_type. תוכנית: docs/superpowers/plans/2026-06-01-x11-citation-corroboration-phase2.md. spec: docs/spec/X11-citation-corroboration.md §4-6.",
@@ -2484,7 +2484,7 @@
"updatedAt": "2026-06-01T04:43:40.474Z"
},
{
"id": "76",
"id": 76,
"title": "תיקון כפתור \"צור משימה\" ב-Paperclip — מאופשר אך submit חוזר בשקט",
"description": "בוטל 2026-06-03 — באג upstream של Paperclip, לא ניתן לתיקון בטוח אצלנו (ee=companyId; הכפתור מאופשר לפי כותרת בלבד אך submit דורש חברה שלא אותחלה). אומת ע\"י chaim שעובד מהקשרי-חברה רגילים. Workaround: לבחור חברה במודאל / לפתוח מתוך לוח. מסלול אמין: pc.sh POST /companies/{id}/issues. תיקון יסודי = upstream. #78 מסיר את הצורך בזרימת הפסיקה.",
"details": "אבחנה סופית מתוך הבאנדל (index-BWGhimVr.js): ה-submit הוא `function xi(){const je=m.current.trim();if(!ee||!je||He.isPending)return;...He.mutate({...companyId:ee...})}`. `je`=כותרת (קיים), `He`=mutation. ה-guard שנכשל הוא **`ee`**, ש-`ee` משמש כ-`projects.list(ee)` וכ-`companyId:ee` במוטציה — כלומר **`ee` = מזהה החברה**. השורש: הכפתור מאופשר לפי הכותרת בלבד (`disabled:!b`, b=כותרת), אבל ה-submit דורש גם חברה (`!ee`). כשהמודאל נפתח בהקשר שבו החברה לא אותחלה, המשתמש לוחץ כפתור 'מאופשר' וה-handler חוזר בשקט — בלי POST, בלי שגיאה. בחירת הסוכן (callback Ro) לא מגדירה את החברה — היא נקבעת רק דרך בורר חברה נפרד (pr/oe). ההזרקה שלנו (translate-he.js) זוכתה: reverseComments נוגע רק ב-[id^='comment-'], לא במודאל; isUserContent מדלג על contentEditable. **לא ניתן לתקן בבטחה דרך injection**: אי-אפשר לכתוב ל-state של React מבחוץ; shim שמגרד DOM ויוצר issue דרך API הוא שביר (צריך IDs מה-DOM) ועלול ליצור משימות פגומות — גרוע מהבאג. **Workaround**: לוודא שהחברה נבחרה במודאל (בורר החברה) לפני לחיצה על 'צור משימה'; או לפתוח 'משימה חדשה' מתוך הקשר חברה/לוח. מסלול אמין תמיד: API ישיר `pc.sh POST /companies/{id}/issues`. **תיקון יסודי = upstream Paperclip** (הכפתור צריך להיות disabled כשאין חברה, או החברה צריכה להיגזר מהלוח/סוכן הנבחר). הערה: #78 (חילוץ פסיקה אוטומטי) מסיר את הצורך במודאל הזה בזרימת חילוץ-הפסיקה; הזרימה הרגילה מניעה סוכנים דרך תגובות (CEO מנתב).",
@@ -2496,7 +2496,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "77",
"id": 77,
"title": "תיקון מיפוי שדות בהעלאת פסיקת ועדת-ערר — מראה-מקום נדחס ל-case_number; case_number לא ניתן לעריכה",
"description": "בטופס העלאת פסיקה (precedent-upload-sheet), עבור החלטות ועדת-ערר ה-frontend ממפה את שדה \"מראה המקום\" אל case_number (`case_number: citation.trim()`), כך שהמזהה הייחודי מקבל את המראה-מקום הארוך במקום מספר תיק נקי (למשל '8027-25'). בנוסף case_number כלל לא קיים ב-PrecedentUpdateRequest — אז מסך העריכה לא יכול לתקן אותו בדיעבד. citation_formatted נשאר ריק בהעלאה (מתמלא רק בחילוץ מטא). תוצאה ב-8027-25: case_number=מראה-מקום, case_name=מראה-מקום, מראה-מקום ריק עד החילוץ.",
"details": "קבצים: web-ui/src/components/precedents/precedent-upload-sheet.tsx:121-123 (committee path ממפה citation→case_number); web/app.py:5147-5163 (PrecedentUpdateRequest חסר case_number); mcp-server/.../internal_decisions.py (id_field=case_number, display_name_fallback=case_number); precedent_metadata_extractor.py:247-253 (guard: case_name מתוקן רק אם ריק או ==case_number, לכן לא תיקן). תיקון מוצע: (1) בטופס committee — שדה נפרד \"מספר תיק (מזהה ייחודי)\" שממפה ל-case_number, ולמפות \"מראה המקום\" ל-citation (→citation_formatted), במקום לדחוס הכל ל-case_number; (2) להוסיף case_number ל-PrecedentUpdateRequest כדי שהעריכה תוכל לתקן בדיעבד (update_case_law כבר מתיר אותו); (3) להריץ `npm run api:types`. ראה כללי השם שהוגדרו: מזהה ייחודי = שם הקובץ/מספר תיק; מראה-מקום בשדה שלו; שם קצר = שם הצד.",
@@ -2508,7 +2508,7 @@
"updatedAt": "2026-06-02T12:17:44.302Z"
},
{
"id": "78",
"id": 78,
"title": "כשל שקט ב-wakeup לחילוץ פסיקה — חילוץ אוטומטי לא רץ והתיק נתקע ב-pending",
"description": "אחרי העלאת פסיקה, הבקאנד מסמן metadata+halacha כ-pending וקורא ל-pc_wake_for_precedent_extraction להעיר את ה-CEO. הקריאה נבלעת בשקט (try/except 'non-fatal') — אם PAPERCLIP_BOARD_API_KEY חסר מחזיר {ok:false,skipped:no_api_key}, או שה-wakeup API נכשל — והתוצאה: ה-CEO לא מתעורר, לא רץ חילוץ מטא ולא חילוץ הלכות, וה-UI מציג 'ממתין לחילוץ' לנצח. קרה ב-8027-25 (תוקן ידנית עם precedent_process_pending). זה גם הסיבה ששדות המטא (תקציר/headnote/תגיות/citation) היו ריקים.",
"details": "קבצים: web/app.py:5250-5262 (wakeup best-effort, exception נבלעת); web/paperclip_client.py:816-820 (skip שקט כש-no api key) ו-~905-907 (כשל API נבלע). תיקון מוצע: (1) להציף את הכשל למשתמש — סטטוס מובחן (extraction_wakeup_failed / 'ממתין-לעיבוד-ידני') ב-UI במקום 'pending' אילם; (2) fallback אוטומטי — אם ה-wakeup נכשל, או job מתוזמן (כמו sync-case-status) שמנקז את התור עם precedent_process_pending, או retry; (3) לאמת אם PAPERCLIP_BOARD_API_KEY מוגדר בקונטיינר (Coolify env) — אם לא, להוסיף. עיין reference: project_precedent_auto_extraction. לא לבלוע exceptions בשקט (feedback_silent_swallow).",
@@ -2520,7 +2520,7 @@
"updatedAt": "2026-06-02T12:07:22.194Z"
},
{
"id": "79",
"id": 79,
"title": "[#55 follow-up] chunker — כותרות-סעיף מבודדות נשארות chunks זעירים (<50)",
"description": "ה-chunker ההיררכי הנוכחי (אחרי תיקון #55) עדיין פולט מדי פעם chunk זעיר שהוא כותרת-סעיף בודדת שלא מוזגה קדימה לתוכן שאחריה. התגלה בסגירת #57 (re-chunk legacy): מתוך 73 תקדימים שעברו reindex, נשארו 4 chunks זעירים — כולם כותרות מבודדות: 'דיון' (ע\"א 5138/04, len=4), 'טענות המשיבים' (בג\"ץ 6525/15, len=13), 'העובדות וההליכים' (בר\"מ 2340/02, len=16), ושבר-ציטוט 'כלל התושבים\". (ע' 13 להחלטה)' (403-17, len=32). לא שאריות legacy — אלה פלט דטרמיניסטי של ה-chunker הנוכחי.",
"details": "השפעה: נמוכה — chunks אלה כבר מסוננים ב-query-time (פילטר length>=50 שנוסף ב-#55), אז החיפוש לא מושפע; זו בעיית-איכות-chunking ולא בעיית-אחזור. מיקום: chunker ההיררכי ב-mcp-server (chunk_document_hierarchical / מדיניות מיזוג הכותרות שב-#55). התיקון הצפוי: כשכותרת/heading קצרה (<50, או section_type שמתחיל סעיף) נותרת כ-chunk עצמאי ללא גוף — למזג אותה קדימה אל ה-chunk הבא (anchor-forward), או אחורה אם אין הבא. לשים לב ל-section boundaries: 'דיון'/'טענות המשיבים' הן תחילת סעיף — המיזוג צריך לצרף את הכותרת לראש הסעיף שאחריה, לא לזנב הקודם. אימות: להריץ scripts/rechunk_legacy_precedents.py אחרי התיקון — אמור להגיע ל-0 chunks<50 (או רק שברי-ציטוט לגיטימיים נדירים). תלוי ב-#55. ראה גם feedback_no_reocr_retrofit (re-chunk מ-full_text בלבד).",
@@ -2534,7 +2534,7 @@
"updatedAt": "2026-06-03T08:10:57.844Z"
},
{
"id": "80",
"id": 80,
"title": "[#15 follow-up] בדיקת ערך image-answer ל-multimodal → הכרעה על backfill 140 legacy",
"description": "נסגר 2026-06-03 — ההנחה התבררה שגויה בכל מרכיב (full check). לא '140 מסמכים / 17,700 עמ' / שעתיים / אישור-עלות chaim + תיוג דפנה', אלא: מתוך 140 חסרי-image רק 65 PDF (השאר MD/DOCX — ה-pipeline מרנדר PDF בלבד), ובסך 704 עמ'. תיקי-השמאות (כל ערך ה-multimodal) כבר היו 8/12 מוטמעים — הפער היחיד היה תיק 8070-25 (4 מסמכי שמאות).",
"details": "בוצע: backfill מקומי (multimodal_backfill.py 8070-25, voyage-multimodal-3, ~30 שניות) → כל 14 מסמכי 8070-25 הוטמעו. **כיסוי שמאות עכשיו 12/12 (100%)**. נותרו 51 PDF/649 עמ' ללא multimodal — כולם טקסטואליים (reference/response/appeal), ו-#15 הוכיח ש-multimodal לא עוזר (אף מדלל) על מסמכים טקסטואליים → **מושארים בכוונה** text-only; זו לא חוסר-עקביות אלא הקונפיג הנכון. אין צורך ב-gold-set/דפנה/אישור-עלות — העלות הייתה סנטים והערך הוכח ב-#15 לתיקי ועדה/שמאות. #80 done (טכני, לא human-gated).",
@@ -2548,7 +2548,7 @@
"updatedAt": "2026-06-03T00:00:00.000Z"
},
{
"id": "81",
"id": 81,
"title": "איכות חילוץ הלכות — לוודא שמה שמחולץ הוא הלכה אמיתית ולא ציטוט/אמרת-אגב",
"description": "מנוע חילוץ ההלכות מפיק כיום פריטים שאינם 'הלכות' במובן המהותי: אמרות-אגב שהערכאה לא הכריעה בהן, יישומים ספציפיים-לתיק (rule_type=application), ציטוטים חתוכים, ופירוק-יתר (עד 351 'הלכות' מפסק אחד). המשימה: לחדד את ה-prompt ולהוסיף ולידטורים אוטומטיים כך שרק עיקרון משפטי בר-הכללה ובר-הסתמכות ייכנס למאגר. מבוססת מחקר מקצועי (ratio decidendi מול obiter dictum, holding-extraction בספרות legal-NLP, קריטריונים לאיכות rule_statement). תתי-המשימות יוגדרו לאחר המחקר.",
"details": "רקע מבצעי (ניקוי 2026-06-03): נמחקו 196 רשומות מתוך 1650 (165 כפילויות תוכן + 31 Tier B/C). גיבוי: data/audit/halacha-cleanup-backup-20260603T101747Z.sql ; מניפסט: data/audit/halacha-cleanup-manifest-20260603T101747Z.csv . קוד רלוונטי: mcp-server/src/legal_mcp/services/halacha_extractor.py (prompts BINDING/PERSUASIVE, _coerce_halacha, אימות ציטוט). תחומי בדיקה ידועים: (א) חסימת quote_verified=false מהתור; (ב) הוצאת rule_type=application מהגדרת 'הלכה'; (ג) שמירה על דחיית dicta שלא הוכרעו; (ד) תקרת כמות/גרנולריות לפסק; (ה) הגנה מפני ציטוט חתוך (truncation guard). מפרט מאומת: docs/halacha-strict-rubric.md (הרובריקה האגרסיבית שהנחיתה ניקוי קורפוס 1454→534 ב-2026-06-03, שפר 51→22). להטמיע אותה במחלץ + dedup-on-insert (#82).",
@@ -2584,10 +2584,11 @@
"title": "ולידטור entailment (NLI) בין rule ל-quote (V2)",
"description": "מודל NLI מאמת ש-rule_statement נובע (entailed) מ-supporting_quote; neutral/contradiction → מתחת לסף אישור אוטומטי.",
"details": "מקור: NLI-faithfulness (DeBERTa-NLI / atomic-fact verification). בודק שהכלל אכן נתמך בציטוט ולא הוזה/הורחב מעבר למקור.",
"status": "pending",
"status": "done",
"dependencies": [],
"testStrategy": "על gold-set מתויג, NLI-reject מתאם עם פסילה אנושית ב-AUC ≥0.80.",
"parentId": "81"
"parentId": "81",
"updatedAt": "2026-06-03T14:46:55.318Z"
},
{
"id": 4,
@@ -2605,10 +2606,11 @@
"title": "בקרת over-extraction: clustering + תקרה (V5)",
"description": "embedding+clustering של ה-rule_statements בתוך פסק-דין, נציג אחד לאשכול, ותקרה לכמות לפי מספר מקטעי reasoning/decision (לא לפי מספר משפטים).",
"details": "מקור: SemDeDup + claim-clustering (MultiClaimNet). דוגמה: פסק 403-17 ייצר 351 'הלכות' — over-decomposition.",
"status": "pending",
"status": "done",
"dependencies": [],
"testStrategy": "פסק עם 351 פריטים יורד ל-≤ מספר מקטעי ההנמקה; ירידה כוללת ≥40% בכפילויות.",
"parentId": "81"
"parentId": "81",
"updatedAt": "2026-06-03T16:27:24.755Z"
},
{
"id": 6,
@@ -2643,10 +2645,10 @@
"parentId": "81"
}
],
"updatedAt": "2026-06-03T12:32:19.701Z"
"updatedAt": "2026-06-03T16:27:24.755Z"
},
{
"id": "82",
"id": 82,
"title": "Dedup בזמן הכנסה — מניעת הלכות כמעט-זהות בכתיבה (semantic dedup on insert)",
"description": "store_halachot_for_chunk מבצע INSERT עיוור ללא בדיקת כפילות, ולכן נצברו עשרות הלכות 'אותו עיקרון במילים אחרות'. המשימה: לפני שמירה, לבדוק דמיון סמנטי (embedding) מול הלכות קיימות באותו פסק ולדלג/למזג near-duplicates, וכן לזהות ציטוט-תומך זהה. מבוססת מחקר (ספי near-duplicate ב-embedding-IR, MinHash/LSH מול cosine, בחירת צורה קנונית, merge מול skip). תתי-המשימות יוגדרו לאחר המחקר.",
"details": "ממצא מהניקוי: סף cosine ≥0.90 תוך-פסק זיהה כפילויות אמיתיות בוודאות גבוהה (הרצועה 0.90-0.95 הייתה כמעט כולה 'אותו עיקרון בניסוח שונה'); ≥0.95 = ודאי. ציטוט-תומך זהה = איתות ודאי. להחליט: סף מבצעי, התנהגות (skip/merge/flag-for-review), ובחירת השורד (approved>pending, ביטחון גבוה, quote_verified). קוד: db.store_halachot_for_chunk; קיים idx_halachot_vec (pgvector).",
@@ -2734,7 +2736,7 @@
"updatedAt": "2026-06-03T12:32:19.721Z"
},
{
"id": "83",
"id": 83,
"title": "חוסן pipeline החילוץ — re-run אידמפוטנטי + אינדוקס תקין (תיקון באגים)",
"description": "התגלו שני באגים: (1) halacha_index מוקצה per-chunk ולכן אינו ייחודי לפסק — שני עקרונות שונים מקבלים אותו מספר (לא כפילות, אך שובר dedup/מיון מבוסס-אינדקס); (2) חילוץ רץ פי-2/3 על אותו פסק (למשל 85026-17 שלוש ריצות תוך דקתיים) ומוסיף append במקום להחליף — ה-advisory lock לא מנע. המשימה: אינדוקס ייחודי לפסק, force=True שמוחק לפני re-extract, וחיזוק ה-lock/אידמפוטנטיות. מחקר קצר: דפוסי idempotency/exactly-once ב-pipelines.",
"details": "קוד: halacha_extractor.py (global advisory lock, per-chunk checkpoints ב-precedent_chunks.halacha_extracted_at, force flag), db.store_halachot_for_chunk (הקצאת halacha_index). לשקול unique constraint (case_law_id, halacha_index) אחרי תיקון ההקצאה.",
@@ -2820,7 +2822,7 @@
"updatedAt": "2026-06-03T13:08:10.793Z"
},
{
"id": "84",
"id": 84,
"title": "טריאז' תור אישור ההלכות — אישור יעיל ולא מתיש",
"description": "אישור ההלכות ידני ומתיש: קריאת עקרונות כמעט-זהים שוב ושוב, ללא תיעדוף או קיבוץ. המשימה: לייעל את חוויית האישור — מיון לפי ביטחון/corroboration, קיבוץ near-duplicates יחד, auto-defer/הסתרה של פריטים באיכות נמוכה, ופעולות batch (אישור/דחייה מרובים). מבוססת מחקר (human-in-the-loop review UX, active-learning prioritization, triage queues). תתי-המשימות לאחר המחקר.",
"details": "הקשר: הדחייה כמעט לא בשימוש (1/1650) — התור הוא 'אשר-או-השאר-תלוי'. כלים קיימים: halachot_pending, halacha_review (MCP), דף ביקורת ב-UI. לשלב עם פלט #81 (איכות) ו-#82 (dedup) כדי שהתור יציג רק מועמדים אמיתיים ומקובצים.",
@@ -2916,7 +2918,7 @@
"updatedAt": "2026-06-03T13:43:18.488Z"
},
{
"id": "85",
"id": 85,
"title": "CEO MCP instance: nested claude -p exits 1 in write_interim_draft",
"description": "write_interim_draft נכשל לכל 5 הבלוקים מתוך session ה-CEO עם 'Claude CLI failed (exit 1): unknown error'. אומת: claude CLI תקין מ-bash (exit 0), PATH+HOME של תהליך ה-MCP תקינים (/home/chaim/.local/bin/claude), אין ANTHROPIC_API_KEY ב-.env, הבלוקים נכתבים סדרתית (לא concurrency). סוכני משנה (proofreader/analyst CMPA-73..76) הריצו claude -p בהצלחה באותו יום. ⇒ כשל ספציפי ל-MCP server instance של ה-CEO. עוקף: האצלה ל-writer agent. דרוש: לבדוק מדוע nested claude -p נכשל מ-instance זה (אולי session lock / env stale); שקול restart ל-CEO agent session.",
"details": "",
@@ -2927,12 +2929,12 @@
"subtasks": []
},
{
"id": "86",
"id": 86,
"title": "טיפול ב-preamble/רציו של נבו — anti-contamination + gold-set מהרציו",
"description": "התגלה (2026-06-03) ש-`strip_nevo_preamble` קיים ומחווט ל-ingest, אבל ה-regex `_DECISION_START` מזהה רק פתיחות של ועדת ערר (בפנינו/הערר שבנדון/ועדת הערר לתכנון/רקע עובדתי/עסקינן) — ולא פסקי-דין שנפתחים ב'פסק-דין' (כמו בג\"ץ 1764/05). לכן בפסקי-דין מנבו — בדיוק אלה שיש להם מיני-רציו — ה-preamble/רציו **אינו נחתך**, דולף לצ'אנקים, ועלול לזהם את חילוץ ההלכות (המחלץ קורא את התשובון של נבו) ואת הקורפוס. במקביל — הרציו של נבו הוא gold-set אנושי-מקצועי חינמי לאמידת איכות החילוץ.",
"details": "קוד: mcp-server/src/legal_mcp/services/extractor.py — `strip_nevo_preamble` (~367), `_NEVO_MARKERS` (ספרות:/חקיקה שאוזכרה:/מיני-רציו:/...), `_DECISION_START` (~361). מחווט ב-ingest.py:161 ו-documents.py:152. הוכחה: ב-1764/05 המיני-רציו שרד כ-chunk מסוג intro (לא נחתך) ורק במזל לא חולץ (intro לא ב-EXTRACTABLE_SECTIONS). השוואת benchmark שבוצעה ידנית על 1764/05: 14 הלכות שלנו כיסו 100% מ-4 הלכות-הרציו של נבו + 2 נוספות, בגרנולריות פי ~3.5 (קשור ל-#81.5).",
"testStrategy": "strip_nevo_preamble על טקסט 1764/05 מסיר את בלוק המיני-רציו ומתחיל מ'פסק-דין'; regression: פתיחות ועדת-ערר ממשיכות להיחתך נכון. benchmark מפיק recall/precision/granularity.",
"status": "pending",
"status": "in-progress",
"dependencies": [],
"priority": "high",
"subtasks": [
@@ -2941,10 +2943,11 @@
"title": "הרחבת _DECISION_START לפסקי-דין (anti-contamination)",
"description": "הוספת פתיחות פסק-דין ל-`_DECISION_START` (פסק-דין / פסק דין / 'השופט'/'כב' השופט'/'לפני:') כך ש-strip_nevo_preamble חותך את ה-preamble/רציו גם בפסקי-דין מנבו.",
"details": "קוד: extractor.py `_DECISION_START`. שמירה על תאימות לאחור לפתיחות ועדת-ערר הקיימות.",
"status": "pending",
"status": "done",
"dependencies": [],
"testStrategy": "unit: strip_nevo_preamble(טקסט 1764/05) מסיר את המיני-רציו ומתחיל מ'פסק-דין'; טקסט ועדת-ערר עם בפנינו עדיין נחתך נכון; טקסט ללא preamble חוזר ללא שינוי.",
"parentId": "86"
"parentId": "86",
"updatedAt": "2026-06-03T16:56:13.158Z"
},
{
"id": 2,
@@ -2971,17 +2974,42 @@
"parentId": "86"
}
],
"updatedAt": "2026-06-03T00:00:00.000Z"
"updatedAt": "2026-06-03T16:56:13.158Z"
},
{
"id": 87,
"title": "claims_coverage: להבחין בין טענות כתב-ערר לטענות תכתובת",
"description": "בדיקת claims_coverage מסמנת false-positives: טענות שעלו רק בתכתובות/תגובות בין הצדדים (לא בכתב הערר) מסומנות כ'לא נענו'. יש להבחין בין טענות מכתב הערר (חובה מענה) לטענות מתכתובת (לא חייבות מענה עצמאי, במיוחד כשהערר מתקבל במלואו). מקור: chair_feedback תיק 1033-25.",
"details": "",
"testStrategy": "",
"status": "pending",
"dependencies": [],
"priority": "medium",
"subtasks": []
},
{
"id": 88,
"title": "פער DB↔file: decision_blocks (DB) מול drafts/decision.md (disk)",
"description": "legal-writer מעדכן decision_blocks ב-DB אבל legal-qa קורא drafts/decision.md מהדיסק — שני מקורות אמת לא מסונכרנים גורמים ל-QA להיכשל פעמיים על אותה בעיה. נדרש: או כתיבה אטומית ל-DB+file יחד, או hook אוטומטי regenerate-draft אחרי כל עדכון בלוק. מקור: chair_feedback תיקים 8126-03-25, CMPA-62. ראה legal-decision-lessons.md #35.",
"details": "",
"testStrategy": "",
"status": "pending",
"dependencies": [],
"priority": "high",
"subtasks": []
}
],
"metadata": {
"version": "1.0.0",
"lastModified": "2026-06-03T13:43:18.488Z",
"taskCount": 85,
"lastModified": "2026-06-03T16:56:13.158Z",
"taskCount": 86,
"completedCount": 77,
"tags": [
"legal-ai"
]
],
"created": "2026-06-06T12:53:14.496Z",
"description": "Tasks for legal-ai context",
"updated": "2026-06-06T12:53:30.413Z"
}
}
}

View File

@@ -327,6 +327,7 @@ Conclusion → Rule → Explanation → Application → Conclusion.
- MUST NOT: ניתוח מעמיק (→ block-yod), הכרעה בין פרשנויות
- Dependencies: block-chet (מספור), block-vav (הגדרות תכניות)
- Condition: **אופציונלי** — רק כשיש מורכבות תכנונית (תכניות סותרות, תמ"א 38 + שימור, פרשנות)
- **סדר בתיקי רישוי (1xxx):** בלוק ט מופיע **לפני** בלוק ז (טענות) — הסדר ה→ו→ט→ז→ח→י→יא→יב. הקורא חייב להכיר את המסגרת הנורמטיבית (התכניות) לפני שהוא קורא את טענות הצדדים על פרשנותן. (לקח מ-1200-25 קרית ענבים; ראה legal-decision-lessons.md #41)
**Weight:**

View File

@@ -252,215 +252,281 @@ Total: ~340,000 words of source material.
Intermediate extraction documents also saved:
- `docs/fjc-principles-extraction.md` — 38 principles from FJC
- `docs/garner-methodology-extraction.md` — ~50 principles from Garner/Scalia
---
## Lessons from הר הבשן 1033-25 (April 2026)
### Source
- Final decision: `data/cases/1033-25/exports/עריכה-v2.docx`
- Our draft (v6): `data/cases/1033-25/exports/טיוטה-v6.docx`
- Intermediate edit (v1): `data/cases/1033-25/exports/עריכה-v1.docx`
- Date: April 2026
- Result: Full acceptance (קבלה מלאה)
- Word counts: Draft 2,126 → Final 2,299 (+8%)
- Discussion section: Draft 960 words (19 paras) → Final 1,099 words (23 paras) (+14%)
### What Our Draft Got Right
- **12-block structure preserved** — all blocks in correct order, headings identical
- **Opening formula** — bottom-line opening "מצאנו כי דין הערר להתקבל" (mode A adapted for acceptance) — used and kept
- **Threshold claims treatment** — all 3 threshold claims handled correctly with same reasoning
- **Central argument flow** — committee's own conditions → shadow plan → not feasible → appeal accepted — this was the exact structure Dafna kept
- **Background neutrality** — facts-only background passed final review (no party quotes, no value words)
- **Most paragraphs kept verbatim** — blocks ו (background), ז (claims), and most of ח (procedures) were kept nearly word-for-word
- **Transition phrases** — "ונוסיף", "הנה כי כן", "הדברים מתחדדים שעה שנזכיר כי" — all used correctly and retained
- **Direct quote from licensing rep** — "נכון, אני מסכימה, התבקשו הרחבות..." — kept verbatim
- **"מסקנת ביניים"** technique — used correctly and retained
- **"למען הסדר הטוב"** — correct usage for remaining claims section
### What the Final Version Changed — Critical Gaps
#### 20. Over-Doctrinal: Abstract Legal Framework Removed Entirely
- **Draft:** Had a 101-word "נבאר" paragraph explaining the general legal authority of committees to require uniform building plans, covering advisory vs. mandatory annexes and administrative review processes — pure CREAC doctrine.
- **Final:** Completely deleted. Went straight from conclusion ("מסקנתנו היא שהבקשה אינה עומדת") to factual evidence (shadow plan is theoretical).
- **Lesson:** In "clean acceptance" cases where the committee's OWN conditions provide the anchor for the decision, skip the doctrinal framework. The committee said "show us X", the applicant didn't show X — no need to explain WHY committees can require X. CREAC is for contested legal rules, not for applying a committee's own explicitly-stated conditions. This is the most important lesson from this case: **match doctrinal depth to legal uncertainty**.
#### 21. Background Enhanced with "ודוק" Foreshadowing
- **Draft:** Simple description of the permit application: "ופורסמה כנדרש לפי סעיף 149 לחוק"
- **Final:** Added 2 sentences after the permit description: "ודוק, בהתאם להוראות התכנית נספח הבינוי מחייב לגבי מספר הקומות המירבי ובכל הנוגע לדרישה להכנת תכנית אחידה הרי שזו מכח שלביות הביצוע של התכנית. על מנת לסטות מהוראות אלו התבקשו ההקלות."
- **Lesson:** Dafna plants analytical seeds in the background. This "ודוק" paragraph in the background isn't neutrality-violating — it's explaining how plan provisions work as a matter of technical fact. But it foreshadows the fulcrum of the entire analysis (the reliefs are from MANDATORY provisions, not from advisory guidance). The background reader already understands what's at stake before reaching the discussion. **Rule**: when the decision hinges on a technical planning distinction, explain that distinction in the background (as fact, not as argument).
#### 22. Procedures Section: Specific Dates → Summary Narrative
- **Draft:** Listed specific dates and documents: "ביום 05.02.2026 ניתנה החלטת ביניים... הודעת עמדה מטעם העוררת גלנסקי מיום 23.02.2026, תגובת גבי אינגרם מיום 08.02.2026, ותגובת מבקשת ההיתר מיום 25.02.2026"
- **Final:** Generalized: "לאחר מועד זה הוגשו בקשות, עדכונים ותגובות מטעם הצדדים לגבי ניסיון להגיע לידי הסכמות, וגם בניסיון לתכנן בקשה שונה ומכל מקום ועדת הערר אפשרה מרחב של זמן בתקווה כי ההחלטה תתייתר"
- **Lesson:** For post-hearing procedural history that didn't change the outcome, Dafna prefers summary narrative over chronological detail. The intermediate decisions, update letters, and their specific dates don't matter to the reader — what matters is the narrative arc: "we gave them time to agree, they didn't, now we decide." Also: "ועדת הערר אפשרה מרחב של זמן בתקווה כי ההחלטה תתייתר" — this signals judicial patience and good faith before ruling.
#### 23. Concrete Evidence Added: Specific Permits in Buildings 5, 7, 11
- **Draft:** General statement that expansions were done ("הרחבות אלו, שחלקן כבר בוצעו וחלקן אושרו...")
- **Final:** Added an entire new paragraph: "להלן כדוגמא מתוך היתרי הבניה בבתים מספר 5, 7, ו-11 (בניינים סמוכים ואף צמודים לזה מושא הערר), בהם התבקשו ואושרו תוספות בניה בהתאם להוראות התכנית בקומה ב' (מפלס 5.80+). משזכויות הבניה נוצלו כאמור, הרי שלא תהיה בידם האפשרות לנצל וליישם את הרחבת הבניה באופן דומה לזה המתבקש בענייננו, מה שיגרום לבית 13 להיות חריג לסביבתו" — with accompanying images of the permits.
- **Lesson:** In acceptance decisions where you're overturning a committee, provide specific factual evidence that makes the conclusion inevitable. Not "other buildings already expanded" but "HERE are permits 5, 7, 11 showing exactly what was approved at level +5.80, making it physically impossible for the shadow plan to be implemented." The word "חריג לסביבתו" appears here as factual consequence, not as value judgment.
#### 24. Plan-Provision Integration Paragraphs Added (נחדד + מקל וחומר)
- **Draft:** None of this content existed
- **Final:** Two new paragraphs:
- F13: "נחדד כי בהתאם להוראות התכנית נספח הבינוי מחייב לגבי מספר הקומות, ולכך מתווספת גם הוראת השלביות והדרישה להכנת תכנית אחידה לכל הבניין. ברי כי הכוונה לתכנית הממחישה ומבטיחה כי ההרחבות מושא התכנית יוכלו להתממש לגבי כלל בעלי הזכויות ובאופן המייצר מופע מקובל."
- F14: "הדברים מתחדדים ביתר שאת שעה שמבוקשת הקלה שמשמעותה חריגה מהוראות התכנית שאז בוודאי מקל וחומר נכון להכין תכנית אחידה."
- **Lesson:** Where the draft used abstract doctrine, Dafna uses specific plan provisions. The "מקל וחומר" argument is new and powerful: if a uniform plan is required even for plan-conforming construction, then all the more so for construction that deviates from the plan. This replaces the general legal framework with a specific, irrefutable logical argument anchored in THIS plan's provisions.
#### 25. Counter-Factual Reasoning: "Approved by Mistake" + "Barren Discussion"
- **Draft:** Simple statement: "לאחר שהתברר בדיון בפנינו כי תכנית הצל אינה ישימה" followed by intermediate conclusion
- **Final:** Added entirely new reasoning: "תכנית הצל אושרה מתוך טעות כי הרי לא נוכל להניח כי אושרה למראית עין וברי כי הועדה המקומית ביקשה להבטיח זכויות של אחרים והשתלבות בסביבה. במקום בו התכנית אינה ישימה דיון בה הינו דיון עקר."
- **Lesson:** The "benefit of the doubt" technique — assume the committee acted in good faith (they didn't knowingly approve a hollow document), then show that this good-faith assumption actually STRENGTHENS the reversal (if they thought it was real, and it's not, then they were misled). "דיון עקר" = "barren discussion" — a phrase that shuts down any further argument about the shadow plan's merits. This is a new rhetorical move not seen in previous decisions.
#### 26. Engineer Counter-Factual: "Had He Known..." (Two New Paragraphs)
- **Draft:** Nothing about the engineer after the discussion section
- **Final:** Two new paragraphs (F18-F19) adding meta-reasoning about the engineer's opinion:
- "חוות דעתו של מהנדס הוועדה כי התכנון המבוקש חורג לסביבתו נבחנה לאור תכנית הצל שהוגשה ומשזו הוגשה בחסר חוו"ד הגורם המקצועי נותרה גם היא בחסר."
- "ונציין כי חוו"ד מהנדס הוועדה ניתנה במקום בו היה סבור כי תכנית הצל ישימה ובהינתן כך קבע כי הינה עדיין חורגת לסביבה... היה והייתה מוצגת תכנית צל המאגדת את ההיתרים שאושרו וממחישה את חריגות הבניה במרחב, ניתן לשער כי חוו"ד המהנדס הייתה החלטית יותר"
- **Lesson:** In acceptance decisions where you're overturning a committee that had professional support, explain WHY the professional got it wrong (or rather, why his analysis was based on faulty premises). The counter-factual "had the engineer known the shadow plan was not feasible, his opposition would have been even stronger" turns the committee's own professional opinion into evidence FOR the reversal. This is Dafna's way of being respectful to professionals while still overturning their conclusions.
#### 27. "לא נעלם מעינינו" Acknowledge-Before-Reject Removed
- **Draft:** Had a 66-word paragraph: "לא נעלם מעינינו כי נספח הבינוי הוגדר כ'מנחה' ולא כ'מחייב'... אולם אף בנספח מנחה, סטייה מהותית... אינה עניין טכני אלא שינוי מהותי"
- **Final:** Completely removed
- **Lesson:** The "אכן...אולם" or "לא נעלם מעינינו" pattern is for REJECTING an appeal — you need to show you considered the losing side's best argument. In ACCEPTANCE, the losing side is the committee/permit applicant, and the analysis already shows their conditions weren't met. No need to acknowledge the other side's argument when the factual record speaks for itself. **Rule**: "acknowledge-before-reject" = only in rejection decisions or on specific issues where you rule against a party. Don't use it prophylactically.
#### 28. Committee Response: Personal Circumstances Added
- **Draft:** Missing entirely — no mention of "פסק הלכתי" or "נסיבות אישיות חריגות"
- **Final:** Added new paragraph in committee response section: "בין השיקולים ששקלו חברי הוועדה נלקחו בחשבון גם נסיבות אישיות חריגות של מבקשת ההיתר, ובכללן פסק הלכתי שהוצג בפני הוועדה, שלפיו בנות מתבגרות אינן יכולות להתגורר באותו מפלס עם שאר בני המשפחה"
- **Lesson:** If a committee considered unusual factors (religious rulings, personal hardship), document them in the claims section for completeness, even if they're not addressed in the discussion. Omitting them would create a gap for judicial review — a judge reading the protocol would wonder why the decision doesn't mention them. Including them in the claims section without addressing them in the discussion implicitly signals: "we noted this but it doesn't change the planning analysis."
#### 29. Opening Precision: Permit Number and Phrasing
- **Draft:** "בקשה להיתר שמספרה" (placeholder — number missing!), "בהקלה לתוספת קומה"
- **Final:** "בקשה להיתר מס' 20230614", "בקשה הכוללת הקלות 'הקלה לתוספת קומה ללא תכנית אחידה וללא אדריכלות חוץ'"
- **Lesson:** (a) Never leave placeholders — "שמספרה" without the actual number is a production error. (b) The permit number is a legal identifier that must appear in the opening. (c) The phrasing "בקשה הכוללת הקלות" (application that includes reliefs) is more precise than "בהקלה" (with a relief). Also: the relief description is quoted in quotation marks from the official publication.
#### 30. "ונפרט;" Not "נפרט."
- **Draft:** "נפרט." (period)
- **Final:** "ונפרט;" (ו prefix + semicolon)
- **Lesson:** The transition from conclusion to detail uses "ו" prefix (connecting) and semicolon (flowing into the detail), not a period (which creates a full stop). This was already documented in the voice fingerprint ("מעבר עם נקודה-פסיק") but the draft didn't apply it. This confirms: **semicolons before elaboration are not optional — they are Dafna's standard punctuation for transitions into detail**.
#### 31. Summary: No Forward-Looking Guidance to Losing Party
- **Draft:** Had a forward-looking paragraph: "ככל שמבקשת ההיתר תבקש להגיש בקשה מחודשת עליה לעמוד בדרישות התכנית, לרבות הצגת תכנית אחידה ישימה לכל הבניין כנדרש"
- **Final:** Replaced with simple restatement: "על כן, הבקשה להיתר לא עמדה בתנאים שהוועדה המקומית עצמה קבעה בהחלטתה מיום 8.7.2024."
- **Lesson:** Dafna does NOT give advice to the losing party in the summary. The decision says what was decided, not what the applicant should do next. Forward-looking guidance would be an advisory opinion outside the scope of the decision. Also note: the final added "ולמעשה היא אינה ממחישה את המצב הפיזי והתכנוני 'האמיתי'" — a new phrase capturing the essence of why the shadow plan fails (it doesn't reflect reality).
#### 32. Unit vs. Extension: Deference to Committee, Not Independent Analysis
- **Draft:** "ניתן לקבל בדוחק את עמדת מבקשת ההיתר כי מדובר בתוספת לדירה קיימת" — expressing the committee's own hesitant view
- **Final:** "עולה כי הועדה המקומית דנה בכך וקבעה כי מדובר ביחידת דיור אחת שבנייתה מיועדת לשימוש בן משפחה... אין אנו מוצאים להתערב בכך ראשית כי הדבר מקדים את זמנו... ושנית ככל שתאושר בניה זו יש לוודא כי לא תבנה יח"ד נוספת"
- **Lesson:** When a secondary issue was resolved by the committee and you're not overturning THAT specific finding, use deference ("אין אנו מוצאים להתערב") rather than expressing your own opinion ("ניתן לקבל בדוחק"). The final also adds a CONDITION ("יש לוודא כי לא תבנה יח"ד נוספת") — practical safeguard rather than theoretical analysis.
#### 33. No Expenses in Full Acceptance
- **Draft:** No mention of expenses
- **Final:** No mention of expenses
- **Lesson confirmed:** In full acceptance of an appeal by neighbor-appellants against a permit applicant, Dafna does not award expenses to either side. This contrasts with rejection (הכט: appellants pay expenses). The pattern emerges: expenses = only in rejection. Acceptance or partial acceptance = no expenses order.
### New Transition Phrases Discovered
- **"ונפרט;"** — correct form (ו + semicolon, not "נפרט.")
- **"דיון בה הינו דיון עקר"** — declaring a point moot
- **"אושרה מתוך טעות כי הרי לא נוכל להניח כי אושרה למראית עין"** — benefit-of-the-doubt construction
- **"ונציין כי חוו"ד... ניתנה במקום בו היה סבור כי..."** — counter-factual about professional opinion
- **"להלן כדוגמא מתוך"** — introducing specific documentary evidence
- **"ברי כי הכוונה ל..."** — explaining legislative intent of plan provisions
- **"מה שיגרום לבית 13 להיות חריג לסביבתו"** — factual consequence language
- **"ועדת הערר אפשרה מרחב של זמן בתקווה כי ההחלטה תתייתר"** — explaining judicial patience
### Meta-Lesson
This is the first "clean acceptance" in our training data (הכט = rejection, בית הכרם = partial acceptance). The key insight: **the draft was too careful**. It built a doctrinal framework (CREAC) as if it needed to justify overturning the committee from first principles, when in reality the committee's OWN conditions provided all the justification needed. Dafna's approach to acceptance:
1. **Anchor in the committee's own conditions** — no need for external legal authority
2. **Show concrete evidence** the conditions weren't met (specific permits, images)
3. **Explain WHY the committee was misled** (shadow plan approved by mistake)
4. **Counter-factual reasoning** about what professionals would have said with correct information
5. **No abstract doctrine needed** when the facts are clear
The draft's biggest structural error was adding the "נבאר" doctrinal paragraph and the "לא נעלם מעינינו" acknowledge-before-reject. Both are tools for CONTESTED or REJECTED cases. In a clean acceptance, the facts lead directly to the conclusion.
### Applied To
- [ ] Update SKILL.md: add "clean acceptance" track — skip doctrine, anchor in committee's conditions
- [ ] Update SKILL.md: "acknowledge-before-reject" only in rejection/contested issues
- [ ] Update SKILL.md: no forward-looking guidance in summary
- [ ] Update SKILL.md: "ודוק" foreshadowing in background for technical planning distinctions
- [ ] Update SKILL.md: counter-factual reasoning about professional opinions
- [ ] Update SKILL.md: procedures section — summary narrative for post-hearing history
- [ ] Update voice-fingerprint: add new transition phrases
- [ ] Update architecture-by-outcome: add "clean acceptance" archetype
- [ ] Fix agent opening punctuation: "ונפרט;" not "נפרט."
---
## Lessons from ערר 1200-25 (קרית ענבים — שימוש חורג, דחייה)
### Source
- Our draft: `data/cases/1200-25/exports/טיוטה-v1.docx` (3,181 words)
- Daphna's edit: `data/cases/1200-25/exports/עריכה-v1.docx` (4,313 words, +35%)
- Date: May 2026
### What the Edit Changed
#### 1. Block Order — Plans Before Claims
- **Draft:** ה→ו→ז→ח→ט→י→יא→יב (plans after procedures)
- **Edit:** ה→ו→**ט**→ו.ב→ז→ח→י→יא→יב (plans BEFORE claims)
- **Lesson:** In licensing cases (1xxx), the reader must understand the normative framework (plans) before reading the parties' arguments about those plans. Block ט should precede Block ז. The new order: opening → brief background → **applicable plans** → expanded background (application + committee proceedings) → claims → procedures → discussion.
#### 2. "להלן מתוך" Document Insertion Pattern
- **Draft:** 0 occurrences
- **Edit:** 12 occurrences of "להלן מתוך [document name]:"
- **Lesson:** Every reference to a source document must be accompanied by "להלן מתוך [שם המסמך]:" as a placeholder for a direct quote/image. This is a MANDATORY pattern, not optional. Examples: "להלן מתוך הוראות התכנית:", "להלן מתוך פרוטוקול הדיון:", "להלן מתוך הבקשה להיתר:"
#### 3. Expanded Factual Background (Block ו)
- **Draft:** ~90 words (3%), one paragraph
- **Edit:** ~420 words (10%), covering: (a) the application details, (b) 3 committee meetings with dates and outcomes, (c) the final decision
- **Lesson:** Block ו must tell the full "story" of the case: when the application was filed → when it was published → how many objections → when committee meetings were held → what was decided at each meeting → when the appeal was filed. Each meeting should have date + outcome.
#### 4. Bridge Planning Analysis ("גשר תכנוני")
- **Draft:** Not present
- **Edit:** 249 words — new analytical framework
- **Lesson:** When an applicant for deviation/variance is also promoting a plan for the same land, the decision must analyze: (a) is the pending plan harmonious with the requested use? If yes → the deviation can serve as a "bridge" until the plan is approved (cite כוכבה תורן). If no → the contradiction STRENGTHENS the rejection. The writer must check `search_case_documents` for pending plans and compare them with the requested use.
#### 5. Competing Plans Analysis
- **Draft:** Not present (1,033 words added)
- **Edit:** Detailed comparison of the site-specific plan (151-1382787) vs the comprehensive plan (151-1337534)
- **Lesson:** When there's a site-specific plan AND a comprehensive plan, the decision must: (a) describe each plan's scope, (b) compare the permitted uses, (c) show quantitative contradictions (e.g., "the comprehensive plan allocates 4,404 m² for ALL commerce in the settlement, while the request alone is for 1,425 m² — 32%"), (d) conclude whether there's harmony or contradiction. This is often the STRONGEST argument in the decision.
#### 6. Heading Level — Flat Structure
- **Draft:** Mixed Heading 2 + Heading 3 (nested subsections)
- **Edit:** All Heading 2 (flat structure)
- **Lesson:** Each section stands independently. No nesting. In the discussion, each analytical step is a separate Heading 2 section.
#### 7. Inline Precedent Distinguishing
- **Draft:** Separate section "הבחנה מתקדימי העוררת" (Heading 3)
- **Edit:** Each precedent distinguished inline with "באשר ל-[case name]" → what's different → conclusion
- **Lesson:** Don't create a separate "distinguishing" section. Address each precedent where it naturally comes up in the discussion, using "באשר ל..." as the opener.
### New Transition Phrases Identified
- **"עינינו הרואות"** — introducing a document-based finding ("our eyes see that...")
- **"הנה כי כן"** — therefore/accordingly (more formal than "לפיכך")
- **"נשוב כאן ונבחין"** — returning to distinguish a case
- **"נוסיף ונבהיר"** — adding clarification
- **"מסקנת הדברים"** — concluding a subsection
- **"משכבר קבענו"** — since we already established
### Applied To
- [x] Update legal-decision-lessons.md with lessons 1-7
- [x] Update daphna-voice-fingerprint.md with structural and style findings
- [ ] Update block-schema.md: block order for 1xxx cases (ט before ז)
- [ ] Update daphna-architecture-by-outcome.md: add "bridge planning" analysis for rejections
- [ ] Update writer system prompt: mandatory "להלן מתוך" pattern
---
## Lessons from Weekly Feedback (May 31, 2026)
### Source
- Chair feedback summary for week ending 2026-05-31
- Case: 8126-03-25 (ערר על חבות בהיטל השבחה - יעקב עמיאל), entries from CMPA-62
### 34. Don't Manufacture Doubt About Clear Statutes
- **Lesson:** סעיף 19(ג)(2) לתוספת השלישית קובע באופן חד-משמעי כי תקופת המגורים היא ארבע שנים מגמר הבנייה — אסור להציע "פרשנות חלופית" של שנה אחת או להכניס שאלות פתוחות על נוסח חוק שהוא ברור; הצגת ספק מלאכותי בכלל ברור מערפלת את הניתוח ומחלישה את הכרעה.
- **Rule:** When a statutory provision is unambiguous on its face, the analysis must state it as the binding rule — not as one possible reading among others. Spurious interpretive doubt is a methodology failure, not a sign of intellectual humility.
### 35. Writer/QA Sync Gap — Two Sources of Truth
- **Problem:** legal-writer updates `decision_blocks` in the DB, but legal-qa reads from `drafts/decision.md` on disk. In CMPA-62 the writer reported updating block headers in DB but the file did not re-sync, causing QA-2 to fail on exactly the same issue twice.
- **Lesson:** Single source of truth is mandatory — either the writer must write to BOTH the DB and the decision.md file in one atomic step, or there must be an automatic `regenerate-draft` hook that runs after every block update so the file always reflects the latest DB state. Two unsynchronized sources will keep producing the same false-fail loop.
- **Owner:** Infrastructure task — not a writer/QA prompt fix.
---
## Lessons from הר הבשן 1033-25 (April 2026)
### Source
- Final decision: `data/cases/1033-25/exports/עריכה-v2.docx`
- Our draft (v6): `data/cases/1033-25/exports/טיוטה-v6.docx`
- Intermediate edit (v1): `data/cases/1033-25/exports/עריכה-v1.docx`
- Date: April 2026
- Result: Full acceptance (קבלה מלאה)
- Word counts: Draft 2,126 → Final 2,299 (+8%)
- Discussion section: Draft 960 words (19 paras) → Final 1,099 words (23 paras) (+14%)
### What Our Draft Got Right
- **12-block structure preserved** — all blocks in correct order, headings identical
- **Opening formula** — bottom-line opening "מצאנו כי דין הערר להתקבל" (mode A adapted for acceptance) — used and kept
- **Threshold claims treatment** — all 3 threshold claims handled correctly with same reasoning
- **Central argument flow** — committee's own conditions → shadow plan → not feasible → appeal accepted — this was the exact structure Dafna kept
- **Background neutrality** — facts-only background passed final review (no party quotes, no value words)
- **Most paragraphs kept verbatim** — blocks ו (background), ז (claims), and most of ח (procedures) were kept nearly word-for-word
- **Transition phrases** — "ונוסיף", "הנה כי כן", "הדברים מתחדדים שעה שנזכיר כי" — all used correctly and retained
- **Direct quote from licensing rep** — "נכון, אני מסכימה, התבקשו הרחבות..." — kept verbatim
- **"מסקנת ביניים"** technique — used correctly and retained
- **"למען הסדר הטוב"** — correct usage for remaining claims section
### What the Final Version Changed — Critical Gaps
#### 20. Over-Doctrinal: Abstract Legal Framework Removed Entirely
- **Draft:** Had a 101-word "נבאר" paragraph explaining the general legal authority of committees to require uniform building plans, covering advisory vs. mandatory annexes and administrative review processes — pure CREAC doctrine.
- **Final:** Completely deleted. Went straight from conclusion ("מסקנתנו היא שהבקשה אינה עומדת") to factual evidence (shadow plan is theoretical).
- **Lesson:** In "clean acceptance" cases where the committee's OWN conditions provide the anchor for the decision, skip the doctrinal framework. The committee said "show us X", the applicant didn't show X — no need to explain WHY committees can require X. CREAC is for contested legal rules, not for applying a committee's own explicitly-stated conditions. This is the most important lesson from this case: **match doctrinal depth to legal uncertainty**.
#### 21. Background Enhanced with "ודוק" Foreshadowing
- **Draft:** Simple description of the permit application: "ופורסמה כנדרש לפי סעיף 149 לחוק"
- **Final:** Added 2 sentences after the permit description: "ודוק, בהתאם להוראות התכנית נספח הבינוי מחייב לגבי מספר הקומות המירבי ובכל הנוגע לדרישה להכנת תכנית אחידה הרי שזו מכח שלביות הביצוע של התכנית. על מנת לסטות מהוראות אלו התבקשו ההקלות."
- **Lesson:** Dafna plants analytical seeds in the background. This "ודוק" paragraph in the background isn't neutrality-violating — it's explaining how plan provisions work as a matter of technical fact. But it foreshadows the fulcrum of the entire analysis (the reliefs are from MANDATORY provisions, not from advisory guidance). The background reader already understands what's at stake before reaching the discussion. **Rule**: when the decision hinges on a technical planning distinction, explain that distinction in the background (as fact, not as argument).
#### 22. Procedures Section: Specific Dates → Summary Narrative
- **Draft:** Listed specific dates and documents: "ביום 05.02.2026 ניתנה החלטת ביניים... הודעת עמדה מטעם העוררת גלנסקי מיום 23.02.2026, תגובת גבי אינגרם מיום 08.02.2026, ותגובת מבקשת ההיתר מיום 25.02.2026"
- **Final:** Generalized: "לאחר מועד זה הוגשו בקשות, עדכונים ותגובות מטעם הצדדים לגבי ניסיון להגיע לידי הסכמות, וגם בניסיון לתכנן בקשה שונה ומכל מקום ועדת הערר אפשרה מרחב של זמן בתקווה כי ההחלטה תתייתר"
- **Lesson:** For post-hearing procedural history that didn't change the outcome, Dafna prefers summary narrative over chronological detail. The intermediate decisions, update letters, and their specific dates don't matter to the reader — what matters is the narrative arc: "we gave them time to agree, they didn't, now we decide." Also: "ועדת הערר אפשרה מרחב של זמן בתקווה כי ההחלטה תתייתר" — this signals judicial patience and good faith before ruling.
#### 23. Concrete Evidence Added: Specific Permits in Buildings 5, 7, 11
- **Draft:** General statement that expansions were done ("הרחבות אלו, שחלקן כבר בוצעו וחלקן אושרו...")
- **Final:** Added an entire new paragraph: "להלן כדוגמא מתוך היתרי הבניה בבתים מספר 5, 7, ו-11 (בניינים סמוכים ואף צמודים לזה מושא הערר), בהם התבקשו ואושרו תוספות בניה בהתאם להוראות התכנית בקומה ב' (מפלס 5.80+). משזכויות הבניה נוצלו כאמור, הרי שלא תהיה בידם האפשרות לנצל וליישם את הרחבת הבניה באופן דומה לזה המתבקש בענייננו, מה שיגרום לבית 13 להיות חריג לסביבתו" — with accompanying images of the permits.
- **Lesson:** In acceptance decisions where you're overturning a committee, provide specific factual evidence that makes the conclusion inevitable. Not "other buildings already expanded" but "HERE are permits 5, 7, 11 showing exactly what was approved at level +5.80, making it physically impossible for the shadow plan to be implemented." The word "חריג לסביבתו" appears here as factual consequence, not as value judgment.
#### 24. Plan-Provision Integration Paragraphs Added (נחדד + מקל וחומר)
- **Draft:** None of this content existed
- **Final:** Two new paragraphs:
- F13: "נחדד כי בהתאם להוראות התכנית נספח הבינוי מחייב לגבי מספר הקומות, ולכך מתווספת גם הוראת השלביות והדרישה להכנת תכנית אחידה לכל הבניין. ברי כי הכוונה לתכנית הממחישה ומבטיחה כי ההרחבות מושא התכנית יוכלו להתממש לגבי כלל בעלי הזכויות ובאופן המייצר מופע מקובל."
- F14: "הדברים מתחדדים ביתר שאת שעה שמבוקשת הקלה שמשמעותה חריגה מהוראות התכנית שאז בוודאי מקל וחומר נכון להכין תכנית אחידה."
- **Lesson:** Where the draft used abstract doctrine, Dafna uses specific plan provisions. The "מקל וחומר" argument is new and powerful: if a uniform plan is required even for plan-conforming construction, then all the more so for construction that deviates from the plan. This replaces the general legal framework with a specific, irrefutable logical argument anchored in THIS plan's provisions.
#### 25. Counter-Factual Reasoning: "Approved by Mistake" + "Barren Discussion"
- **Draft:** Simple statement: "לאחר שהתברר בדיון בפנינו כי תכנית הצל אינה ישימה" followed by intermediate conclusion
- **Final:** Added entirely new reasoning: "תכנית הצל אושרה מתוך טעות כי הרי לא נוכל להניח כי אושרה למראית עין וברי כי הועדה המקומית ביקשה להבטיח זכויות של אחרים והשתלבות בסביבה. במקום בו התכנית אינה ישימה דיון בה הינו דיון עקר."
- **Lesson:** The "benefit of the doubt" technique — assume the committee acted in good faith (they didn't knowingly approve a hollow document), then show that this good-faith assumption actually STRENGTHENS the reversal (if they thought it was real, and it's not, then they were misled). "דיון עקר" = "barren discussion" — a phrase that shuts down any further argument about the shadow plan's merits. This is a new rhetorical move not seen in previous decisions.
#### 26. Engineer Counter-Factual: "Had He Known..." (Two New Paragraphs)
- **Draft:** Nothing about the engineer after the discussion section
- **Final:** Two new paragraphs (F18-F19) adding meta-reasoning about the engineer's opinion:
- "חוות דעתו של מהנדס הוועדה כי התכנון המבוקש חורג לסביבתו נבחנה לאור תכנית הצל שהוגשה ומשזו הוגשה בחסר חוו"ד הגורם המקצועי נותרה גם היא בחסר."
- "ונציין כי חוו"ד מהנדס הוועדה ניתנה במקום בו היה סבור כי תכנית הצל ישימה ובהינתן כך קבע כי הינה עדיין חורגת לסביבה... היה והייתה מוצגת תכנית צל המאגדת את ההיתרים שאושרו וממחישה את חריגות הבניה במרחב, ניתן לשער כי חוו"ד המהנדס הייתה החלטית יותר"
- **Lesson:** In acceptance decisions where you're overturning a committee that had professional support, explain WHY the professional got it wrong (or rather, why his analysis was based on faulty premises). The counter-factual "had the engineer known the shadow plan was not feasible, his opposition would have been even stronger" turns the committee's own professional opinion into evidence FOR the reversal. This is Dafna's way of being respectful to professionals while still overturning their conclusions.
#### 27. "לא נעלם מעינינו" Acknowledge-Before-Reject Removed
- **Draft:** Had a 66-word paragraph: "לא נעלם מעינינו כי נספח הבינוי הוגדר כ'מנחה' ולא כ'מחייב'... אולם אף בנספח מנחה, סטייה מהותית... אינה עניין טכני אלא שינוי מהותי"
- **Final:** Completely removed
- **Lesson:** The "אכן...אולם" or "לא נעלם מעינינו" pattern is for REJECTING an appeal — you need to show you considered the losing side's best argument. In ACCEPTANCE, the losing side is the committee/permit applicant, and the analysis already shows their conditions weren't met. No need to acknowledge the other side's argument when the factual record speaks for itself. **Rule**: "acknowledge-before-reject" = only in rejection decisions or on specific issues where you rule against a party. Don't use it prophylactically.
#### 28. Committee Response: Personal Circumstances Added
- **Draft:** Missing entirely — no mention of "פסק הלכתי" or "נסיבות אישיות חריגות"
- **Final:** Added new paragraph in committee response section: "בין השיקולים ששקלו חברי הוועדה נלקחו בחשבון גם נסיבות אישיות חריגות של מבקשת ההיתר, ובכללן פסק הלכתי שהוצג בפני הוועדה, שלפיו בנות מתבגרות אינן יכולות להתגורר באותו מפלס עם שאר בני המשפחה"
- **Lesson:** If a committee considered unusual factors (religious rulings, personal hardship), document them in the claims section for completeness, even if they're not addressed in the discussion. Omitting them would create a gap for judicial review — a judge reading the protocol would wonder why the decision doesn't mention them. Including them in the claims section without addressing them in the discussion implicitly signals: "we noted this but it doesn't change the planning analysis."
#### 29. Opening Precision: Permit Number and Phrasing
- **Draft:** "בקשה להיתר שמספרה" (placeholder — number missing!), "בהקלה לתוספת קומה"
- **Final:** "בקשה להיתר מס' 20230614", "בקשה הכוללת הקלות 'הקלה לתוספת קומה ללא תכנית אחידה וללא אדריכלות חוץ'"
- **Lesson:** (a) Never leave placeholders — "שמספרה" without the actual number is a production error. (b) The permit number is a legal identifier that must appear in the opening. (c) The phrasing "בקשה הכוללת הקלות" (application that includes reliefs) is more precise than "בהקלה" (with a relief). Also: the relief description is quoted in quotation marks from the official publication.
#### 30. "ונפרט;" Not "נפרט."
- **Draft:** "נפרט." (period)
- **Final:** "ונפרט;" (ו prefix + semicolon)
- **Lesson:** The transition from conclusion to detail uses "ו" prefix (connecting) and semicolon (flowing into the detail), not a period (which creates a full stop). This was already documented in the voice fingerprint ("מעבר עם נקודה-פסיק") but the draft didn't apply it. This confirms: **semicolons before elaboration are not optional — they are Dafna's standard punctuation for transitions into detail**.
#### 31. Summary: No Forward-Looking Guidance to Losing Party
- **Draft:** Had a forward-looking paragraph: "ככל שמבקשת ההיתר תבקש להגיש בקשה מחודשת עליה לעמוד בדרישות התכנית, לרבות הצגת תכנית אחידה ישימה לכל הבניין כנדרש"
- **Final:** Replaced with simple restatement: "על כן, הבקשה להיתר לא עמדה בתנאים שהוועדה המקומית עצמה קבעה בהחלטתה מיום 8.7.2024."
- **Lesson:** Dafna does NOT give advice to the losing party in the summary. The decision says what was decided, not what the applicant should do next. Forward-looking guidance would be an advisory opinion outside the scope of the decision. Also note: the final added "ולמעשה היא אינה ממחישה את המצב הפיזי והתכנוני 'האמיתי'" — a new phrase capturing the essence of why the shadow plan fails (it doesn't reflect reality).
#### 32. Unit vs. Extension: Deference to Committee, Not Independent Analysis
- **Draft:** "ניתן לקבל בדוחק את עמדת מבקשת ההיתר כי מדובר בתוספת לדירה קיימת" — expressing the committee's own hesitant view
- **Final:** "עולה כי הועדה המקומית דנה בכך וקבעה כי מדובר ביחידת דיור אחת שבנייתה מיועדת לשימוש בן משפחה... אין אנו מוצאים להתערב בכך ראשית כי הדבר מקדים את זמנו... ושנית ככל שתאושר בניה זו יש לוודא כי לא תבנה יח"ד נוספת"
- **Lesson:** When a secondary issue was resolved by the committee and you're not overturning THAT specific finding, use deference ("אין אנו מוצאים להתערב") rather than expressing your own opinion ("ניתן לקבל בדוחק"). The final also adds a CONDITION ("יש לוודא כי לא תבנה יח"ד נוספת") — practical safeguard rather than theoretical analysis.
#### 33. No Expenses in Full Acceptance
- **Draft:** No mention of expenses
- **Final:** No mention of expenses
- **Lesson confirmed:** In full acceptance of an appeal by neighbor-appellants against a permit applicant, Dafna does not award expenses to either side. This contrasts with rejection (הכט: appellants pay expenses). The pattern emerges: expenses = only in rejection. Acceptance or partial acceptance = no expenses order.
### New Transition Phrases Discovered
- **"ונפרט;"** — correct form (ו + semicolon, not "נפרט.")
- **"דיון בה הינו דיון עקר"** — declaring a point moot
- **"אושרה מתוך טעות כי הרי לא נוכל להניח כי אושרה למראית עין"** — benefit-of-the-doubt construction
- **"ונציין כי חוו"ד... ניתנה במקום בו היה סבור כי..."** — counter-factual about professional opinion
- **"להלן כדוגמא מתוך"** — introducing specific documentary evidence
- **"ברי כי הכוונה ל..."** — explaining legislative intent of plan provisions
- **"מה שיגרום לבית 13 להיות חריג לסביבתו"** — factual consequence language
- **"ועדת הערר אפשרה מרחב של זמן בתקווה כי ההחלטה תתייתר"** — explaining judicial patience
### Meta-Lesson
This is the first "clean acceptance" in our training data (הכט = rejection, בית הכרם = partial acceptance). The key insight: **the draft was too careful**. It built a doctrinal framework (CREAC) as if it needed to justify overturning the committee from first principles, when in reality the committee's OWN conditions provided all the justification needed. Dafna's approach to acceptance:
1. **Anchor in the committee's own conditions** — no need for external legal authority
2. **Show concrete evidence** the conditions weren't met (specific permits, images)
3. **Explain WHY the committee was misled** (shadow plan approved by mistake)
4. **Counter-factual reasoning** about what professionals would have said with correct information
5. **No abstract doctrine needed** when the facts are clear
The draft's biggest structural error was adding the "נבאר" doctrinal paragraph and the "לא נעלם מעינינו" acknowledge-before-reject. Both are tools for CONTESTED or REJECTED cases. In a clean acceptance, the facts lead directly to the conclusion.
### Applied To
- [ ] Update SKILL.md: add "clean acceptance" track — skip doctrine, anchor in committee's conditions
- [ ] Update SKILL.md: "acknowledge-before-reject" only in rejection/contested issues
- [ ] Update SKILL.md: no forward-looking guidance in summary
- [ ] Update SKILL.md: "ודוק" foreshadowing in background for technical planning distinctions
- [ ] Update SKILL.md: counter-factual reasoning about professional opinions
- [ ] Update SKILL.md: procedures section — summary narrative for post-hearing history
- [ ] Update voice-fingerprint: add new transition phrases
- [ ] Update architecture-by-outcome: add "clean acceptance" archetype
- [ ] Fix agent opening punctuation: "ונפרט;" not "נפרט."
---
## Lessons from ערר 1200-25 (קרית ענבים — שימוש חורג, דחייה)
### Source
- Our draft: `data/cases/1200-25/exports/טיוטה-v1.docx` (3,181 words)
- Daphna's edit: `data/cases/1200-25/exports/עריכה-v1.docx` (4,313 words, +35%)
- Date: May 2026
### What the Edit Changed
#### 1. Block Order — Plans Before Claims
- **Draft:** ה→ו→ז→ח→ט→י→יא→יב (plans after procedures)
- **Edit:** ה→ו→**ט**→ו.ב→ז→ח→י→יא→יב (plans BEFORE claims)
- **Lesson:** In licensing cases (1xxx), the reader must understand the normative framework (plans) before reading the parties' arguments about those plans. Block ט should precede Block ז. The new order: opening → brief background → **applicable plans** → expanded background (application + committee proceedings) → claims → procedures → discussion.
#### 2. "להלן מתוך" Document Insertion Pattern
- **Draft:** 0 occurrences
- **Edit:** 12 occurrences of "להלן מתוך [document name]:"
- **Lesson:** Every reference to a source document must be accompanied by "להלן מתוך [שם המסמך]:" as a placeholder for a direct quote/image. This is a MANDATORY pattern, not optional. Examples: "להלן מתוך הוראות התכנית:", "להלן מתוך פרוטוקול הדיון:", "להלן מתוך הבקשה להיתר:"
#### 3. Expanded Factual Background (Block ו)
- **Draft:** ~90 words (3%), one paragraph
- **Edit:** ~420 words (10%), covering: (a) the application details, (b) 3 committee meetings with dates and outcomes, (c) the final decision
- **Lesson:** Block ו must tell the full "story" of the case: when the application was filed → when it was published → how many objections → when committee meetings were held → what was decided at each meeting → when the appeal was filed. Each meeting should have date + outcome.
#### 4. Bridge Planning Analysis ("גשר תכנוני")
- **Draft:** Not present
- **Edit:** 249 words — new analytical framework
- **Lesson:** When an applicant for deviation/variance is also promoting a plan for the same land, the decision must analyze: (a) is the pending plan harmonious with the requested use? If yes → the deviation can serve as a "bridge" until the plan is approved (cite כוכבה תורן). If no → the contradiction STRENGTHENS the rejection. The writer must check `search_case_documents` for pending plans and compare them with the requested use.
#### 5. Competing Plans Analysis
- **Draft:** Not present (1,033 words added)
- **Edit:** Detailed comparison of the site-specific plan (151-1382787) vs the comprehensive plan (151-1337534)
- **Lesson:** When there's a site-specific plan AND a comprehensive plan, the decision must: (a) describe each plan's scope, (b) compare the permitted uses, (c) show quantitative contradictions (e.g., "the comprehensive plan allocates 4,404 m² for ALL commerce in the settlement, while the request alone is for 1,425 m² — 32%"), (d) conclude whether there's harmony or contradiction. This is often the STRONGEST argument in the decision.
#### 6. Heading Level — Flat Structure
- **Draft:** Mixed Heading 2 + Heading 3 (nested subsections)
- **Edit:** All Heading 2 (flat structure)
- **Lesson:** Each section stands independently. No nesting. In the discussion, each analytical step is a separate Heading 2 section.
#### 7. Inline Precedent Distinguishing
- **Draft:** Separate section "הבחנה מתקדימי העוררת" (Heading 3)
- **Edit:** Each precedent distinguished inline with "באשר ל-[case name]" → what's different → conclusion
- **Lesson:** Don't create a separate "distinguishing" section. Address each precedent where it naturally comes up in the discussion, using "באשר ל..." as the opener.
### New Transition Phrases Identified
- **"עינינו הרואות"** — introducing a document-based finding ("our eyes see that...")
- **"הנה כי כן"** — therefore/accordingly (more formal than "לפיכך")
- **"נשוב כאן ונבחין"** — returning to distinguish a case
- **"נוסיף ונבהיר"** — adding clarification
- **"מסקנת הדברים"** — concluding a subsection
- **"משכבר קבענו"** — since we already established
### Applied To
- [x] Update legal-decision-lessons.md with lessons 1-7
- [x] Update daphna-voice-fingerprint.md with structural and style findings
- [ ] Update block-schema.md: block order for 1xxx cases (ט before ז)
- [ ] Update daphna-architecture-by-outcome.md: add "bridge planning" analysis for rejections
- [ ] Update writer system prompt: mandatory "להלן מתוך" pattern
---
## Lessons from Weekly Feedback (May 31, 2026)
### Source
- Chair feedback summary for week ending 2026-05-31
- Case: 8126-03-25 (ערר על חבות בהיטל השבחה - יעקב עמיאל), entries from CMPA-62
### 34. Don't Manufacture Doubt About Clear Statutes
- **Lesson:** סעיף 19(ג)(2) לתוספת השלישית קובע באופן חד-משמעי כי תקופת המגורים היא ארבע שנים מגמר הבנייה — אסור להציע "פרשנות חלופית" של שנה אחת או להכניס שאלות פתוחות על נוסח חוק שהוא ברור; הצגת ספק מלאכותי בכלל ברור מערפלת את הניתוח ומחלישה את הכרעה.
- **Rule:** When a statutory provision is unambiguous on its face, the analysis must state it as the binding rule — not as one possible reading among others. Spurious interpretive doubt is a methodology failure, not a sign of intellectual humility.
### 35. Writer/QA Sync Gap — Two Sources of Truth
- **Problem:** legal-writer updates `decision_blocks` in the DB, but legal-qa reads from `drafts/decision.md` on disk. In CMPA-62 the writer reported updating block headers in DB but the file did not re-sync, causing QA-2 to fail on exactly the same issue twice.
- **Lesson:** Single source of truth is mandatory — either the writer must write to BOTH the DB and the decision.md file in one atomic step, or there must be an automatic `regenerate-draft` hook that runs after every block update so the file always reflects the latest DB state. Two unsynchronized sources will keep producing the same false-fail loop.
- **Owner:** Infrastructure task — not a writer/QA prompt fix.
---
## Lessons from Chair Feedback Backlog (June 6, 2026)
### Source
- Consolidation of all unresolved `chair_feedback` entries (21 items) from cases
1033-25, 1130-25 (קרית יערים), 1200-25 (קרית ענבים), 8126-03-25, 8137-24.
- Folded manually as part of closing the feedback→agent-knowledge loop. Some
overlap with earlier sections (1200-25, weekly-feedback) is intentional — this
section is the authoritative roll-up of the backlog.
### 36. Planning Background Is Argumentation, Not "General Info" (1130-25)
- **Lesson:** רקע תכנוני בהחלטה אינו "מידע כללי" — הוא משרת סוגיה ספציפית ומנוסח כחלק מהארגומנטציה הסילוגיסטית. בניתוח שינוי נסיבות, היסטוריית התכנון מראש ועד הפסקה האחרונה חיונית: היא ההנחה התחתונה (עובדות) של הסילוגיזם, לא רקע ניטרלי.
- **Rule:** When the discussion turns on change-of-circumstances, write the full planning history (every plan, every amendment, with years) as the factual premise of the argument — not as background filler.
### 37. Detail the Content of Another Body's Actions When Cited as Evidence (1130-25)
- **Lesson:** כשעמדת ועדת הערר מסתמכת על פעולות של גוף אחר (ועדה מחוזית) כראיה לשינוי נסיבות — חובה לפרט את **תוכן** אותן פעולות (מה התבקש, מה אושר, אילו תנאים), לא רק לציין שהתרחשו.
- **Rule:** "The district committee approved similar plans in 2023 and 2024" is insufficient — specify what each plan requested and what was approved, so the reader can judge whether it's truly comparable.
### 38. Map/GIS Images Are Visual Evidence, Not Decoration (1130-25)
- **Lesson:** תמונות מפה/GIS בהחלטות תכנון ובניה הן חלק מהארגומנטציה — ראיה ויזואלית שמשלימה את הניתוח הטקסטואלי (מיקום חלקות, סמיכות גיאוגרפית, כבישים ותשתיות מתוכננות). הכותב יסמן placeholder `[תמונה: <תיאור>]` והיו"ר תכניס בעריכה הסופית.
- **Rule:** When geographic proximity or planned infrastructure matters to the analysis, insert an image placeholder in the discussion — it is evidence, treated like any other.
### 39. Address Parallel Appeals in the Same Area Explicitly (1130-25)
- **Lesson:** כשיש עררים מקבילים באותו אזור (למשל ערר 1194-25 בחלקה סמוכה) — ההחלטה צריכה להתייחס לכך במפורש, לציין את ההבחנה בין התיקים, ולהבהיר שכל בקשה נבחנת לגופה. "אפקט דומינו" שהתממש הוא עובדה תכנונית, לא חשש תיאורטי.
- **Rule:** Name the parallel appeal, state how the present case differs, and reaffirm case-by-case examination.
### 40. The Chair's Text Skeleton Is a Structural Directive (1130-25)
- **Lesson:** שלד טקסט שהיו"ר מספקת (זרימה נרטיבית + נקודות מפתח ממוספרות) הוא הנחיה מבנית מחייבת — הכותב צריך לעקוב אחרי המבנה ולמלא בתוכן מלא, לא לנסח מחדש את הסדר. ה-placeholder "..." מסמן מעבר שצריך להשלים.
- **Rule:** When `get_chair_directions` / analysis-and-research.md contains a narrative skeleton, follow it step-by-step; treat each numbered point as a required paragraph.
### 41. Block Order in Licensing (1xxx): ט Before ז (1200-25)
- **Lesson:** בתיקי רישוי (1xxx) — בלוק ט (תכניות חלות) צריך להופיע **לפני** בלוק ז (טענות), לא אחריו. הסדר הנכון: ה→ו→ט→ז→ח→י→יא→יב. הרציונל: הקורא צריך להכיר את המסגרת הנורמטיבית (התכניות) לפני שהוא קורא את טענות הצדדים על פרשנותן.
- **Rule:** For 1xxx cases, emit applicable plans (ט) before the parties' claims (ז). See `docs/block-schema.md`.
### 42. "להלן מתוך [מסמך]:" Is Mandatory (1200-25)
- **Lesson:** תבנית "להלן מתוך [שם המסמך]:" היא חובה בכל מקום שמתייחסים למסמך מקור — placeholder להכנסת ציטוט ישיר/תמונה. דוגמאות: "להלן מתוך הוראות התכנית:", "להלן מתוך פרוטוקול הדיון:", "להלן מתוך הבקשה להיתר:". See `skills/decision/SKILL.md`.
- **Rule:** Every reference to a source document gets a "להלן מתוך [exact doc name]:" placeholder.
### 43. Block ו Must Contain a Full Timeline (1200-25)
- **Lesson:** בלוק ו חייב לספר את "הסיפור" המלא של התיק עם ציר זמן: מתי הוגשה הבקשה, מתי פורסמה, כמה התנגדויות הוגשו, מתי התקיימו דיונים בוועדה מקומית ומה הוחלט בכל אחד, ומתי הוגש הערר. כל ישיבה עם תאריך + תוצאה.
- **Rule:** Block ו is a dated narrative, not a one-liner.
### 44. Point-Plan vs. Comprehensive-Plan Harmony (1200-25)
- **Lesson:** בתיק רישוי שבו המבקש מקדם גם תכנית — חובה לנתח האם התכנית הנקודתית תואמת את התכנית הכוללנית. אם יש סתירה (למשל השוואה כמותית: הכוללנית מקצה 4,404 מ"ר לכל המסחר ביישוב, מול 1,425 מ"ר בבקשה אחת) — זה **מחזק** את הדחייה. מסגרת "גשר תכנוני": שימוש חורג יכול לגשר על פער תכנוני רק אם התכנית המקודמת תואמת את הכיוון הכולל (כוכבה תורן).
- **Rule:** Check `search_case_documents` for pending plans; compare point-plan to comprehensive-plan; a contradiction strengthens rejection.
### 45. Don't Skip the "Non-Profit Institution" Threshold in s.19(ב)(4) (8137-24)
- **Lesson:** כשמסמכי יסוד של מוסד מוגשים, אין לדלג על תנאי "המוסד שאין עיסוקו לשם קבלת רווחים" בס' 19(ב)(4) — זהו התנאי **הראשון** ויש לבססו על ציטוט פסקאות ספציפיות מתעודות היסוד (חוקה, תקנון, הסכמים), לא על רישום מלכ"ר בלבד. רישום ≠ ראיה חלוטה (תקדים הלפרן, ערר מרכז 8013-03-21). יש לתחם: הפרק מכריע בתנאי הזהות+אי-רווח בלבד; תנאי השימוש לפרק נפרד.
- **Rule:** In betterment-levy exemption cases, the non-profit-identity condition is condition #1 — prove it via specific cited paragraphs of the foundational documents, never via registration status alone.
### 46. Distinguish Appeal-Letter Claims from Correspondence Claims (1033-25)
- **Lesson:** בדיקת כיסוי הטענות (claims_coverage) צריכה להבחין בין טענות שעלו בכתב הערר (חובה לענות) לבין טענות שעלו בתכתובות/תגובות בין הצדדים (לא חייבות מענה עצמאי, במיוחד כשהערר מתקבל במלואו וההחלטה בוטלה). סימון טענות-תכתובת כ"לא נענו" הוא false-positive.
- **Rule:** Only claims raised in the appeal letter itself require a dedicated answer; correspondence-only claims do not, especially when the appeal is fully accepted. (Also tracked as a system task — the automated check needs this distinction.)
### System/Infrastructure Items (NOT writer lessons)
These two entries are technical gaps, not decision-writing lessons — captured in TaskMaster, not consumed by the writer:
- **claims_coverage check** (1033-25): the automated coverage check must distinguish appeal-letter claims from correspondence claims (see #46).
- **DB↔file sync gap** (8126-03-25): see #35 above — writer writes to `decision_blocks` (DB) while QA reads `drafts/decision.md` (disk). Infrastructure fix.
### Note on case-specific issue-ordering entries
Two 1200-25 entries recorded a case-specific issue order (threshold → plan interpretation
→ ancillary-vs-primary → significant-deviation → comprehensive-plan → grouped: reasoning,
traffic) with no generalizable rule. They are case artifacts, captured in that case's
analysis-and-research.md — no general lesson folded.

View File

@@ -2455,6 +2455,20 @@ async def list_chair_feedback(
return [dict(r) for r in rows]
async def get_chair_feedback(feedback_id: UUID) -> dict | None:
"""Return a single chair_feedback row by id (with case_number), or None."""
pool = await get_pool()
async with pool.acquire() as conn:
row = await conn.fetchrow(
"""SELECT cf.*, c.case_number, c.appeal_type AS case_appeal_type
FROM chair_feedback cf
LEFT JOIN cases c ON c.id = cf.case_id
WHERE cf.id = $1""",
feedback_id,
)
return dict(row) if row else None
async def resolve_chair_feedback(
feedback_id: UUID,
applied_to: list[str],

View File

@@ -72,6 +72,8 @@ description: This skill should be used when writing legal decisions (החלטו
תמונות ותשריטים משולבים בטקסט עם הפניה מילולית: "להלן מתוך נספח האדריכלות והבקשה להיתר שם ניתן לראות את הדברים:", "להלן תמונת המגרשים הרלוונטיים מתוך מערכת ה-GIS של הוועדה המקומית", "להלן מתוך נספח הבינוי המצורף להוראות התכנית". העיצוב הטכני נעשה בשלב הוורד.
**תבנית "להלן מתוך [שם המסמך]:" — חובה.** בכל מקום שמתייחסים למסמך מקור (הוראות תכנית, פרוטוקול דיון, בקשה להיתר, נספח, חוות דעת) — יש להוסיף placeholder "להלן מתוך [שם המסמך המדויק]:" לפני ציטוט ישיר או תמונה. זו תבנית מחייבת, לא אופציונלית. דוגמאות: "להלן מתוך הוראות התכנית:", "להלן מתוך פרוטוקול הדיון:", "להלן מתוך הבקשה להיתר:". (לקח מ-1200-25 קרית ענבים; ראה legal-decision-lessons.md #42)
### 3.6 קיצורים משפטיים
עו"ד (עורך דין), ב"כ (בא כוח), עוה"ד (עורך הדין), יח"ד (יחידת דיור), מ"ר (מטר רבוע), תב"ע (תכנית בניין עיר), רמ"י (רשות מקרקעי ישראל), ר"ר / בר"ר (רשות רישוי), סה"כ (סך הכל).

View File

@@ -42,9 +42,14 @@ function FeedbackCard({ fb }: { fb: ChairFeedback }) {
const onResolve = () => {
resolve.mutate(
{ feedbackId: fb.id, applied_to: [] },
{ feedbackId: fb.id, applied_to: [], fold: true },
{
onSuccess: () => toast.success("ההערה סומנה כיושמה"),
onSuccess: (res) =>
toast.success(
res.fold_queued
? "סומנה כיושמה — הלקח נשלח ל-CEO לקיפול לקובץ הידע"
: "ההערה סומנה כיושמה",
),
onError: (e) =>
toast.error(e instanceof Error ? e.message : "שגיאה בסימון"),
},

View File

@@ -153,8 +153,10 @@ export function DraftsPanel({
}
function handleResolve(id: string) {
// fold=false: resolving from the per-case panel is bookkeeping only.
// Folding the lesson into the knowledge files is driven from /feedback.
resolveMutation.mutate(
{ feedbackId: id, applied_to: [] },
{ feedbackId: id, applied_to: [], fold: false },
{
onSuccess: () => toast.success("ההערה סומנה כמטופלת"),
onError: () => toast.error("שגיאה בעדכון"),

View File

@@ -89,13 +89,17 @@ export function useResolveFeedback() {
mutationFn: ({
feedbackId,
applied_to,
fold,
}: {
feedbackId: string;
applied_to: string[];
/** When true (default server-side), wakes the CEO to fold the lesson
* into the right knowledge file. Pass false for pure bookkeeping. */
fold?: boolean;
}) =>
apiRequest<{ status: string }>(
apiRequest<{ status: string; fold_queued: boolean }>(
`/api/feedback/${feedbackId}/resolve`,
{ method: "PATCH", body: { applied_to } },
{ method: "PATCH", body: { applied_to, ...(fold === undefined ? {} : { fold }) } },
),
onSuccess: () => {
qc.invalidateQueries({ queryKey: feedbackKeys.all });

View File

@@ -64,6 +64,7 @@ from web.paperclip_client import (
restore_project as pc_restore_project,
wake_analyst_for_appraiser_facts as pc_wake_analyst_for_appraiser_facts,
wake_ceo_agent as pc_wake_ceo,
wake_ceo_for_feedback_fold as pc_wake_ceo_for_feedback_fold,
wake_curator_for_final as pc_wake_curator_for_final,
wake_for_precedent_extraction as pc_wake_for_precedent_extraction,
)
@@ -4972,13 +4973,53 @@ async def api_create_feedback_json(body: dict):
@app.patch("/api/feedback/{feedback_id}/resolve")
async def api_resolve_feedback(feedback_id: str, body: dict):
"""Mark feedback as resolved."""
async def api_resolve_feedback(
feedback_id: str,
body: dict,
background_tasks: BackgroundTasks,
):
"""Mark feedback as resolved. When ``fold`` is true (default) and the entry
has an extracted lesson, also wake the CEO to fold that lesson into the
right knowledge file (the feedback→agent-knowledge loop).
The fold is fire-and-forget (BackgroundTask) and best-effort — resolving
never fails because Paperclip is down. Pass ``fold=false`` for pure
bookkeeping resolves (e.g. from the per-case drafts panel) to avoid
spawning a CEO run per click."""
fid = UUID(feedback_id)
fold = body.get("fold", True)
fb = await db.get_chair_feedback(fid)
if not fb:
raise HTTPException(404, "הערה לא נמצאה")
await db.resolve_chair_feedback(
feedback_id=UUID(feedback_id),
feedback_id=fid,
applied_to=body.get("applied_to", []),
)
return {"status": "resolved"}
# Guard: only fold a real, lesson-bearing entry, and only when asked.
lesson = (fb.get("lesson_extracted") or "").strip()
fold_queued = False
if fold and lesson:
async def _fold():
try:
await pc_wake_ceo_for_feedback_fold(
feedback_id=str(fid),
feedback_text=fb.get("feedback_text") or "",
lesson_extracted=lesson,
category=fb.get("category") or "other",
block_id=fb.get("block_id") or "",
case_number=fb.get("case_number") or "",
practice_area=fb.get("case_appeal_type") or "",
)
except Exception:
logger.exception("feedback-fold wakeup failed (non-fatal) for %s", fid)
background_tasks.add_task(_fold)
fold_queued = True
return {"status": "resolved", "fold_queued": fold_queued}
@app.get("/api/chair-feedback/weekly-summary")

View File

@@ -907,6 +907,119 @@ async def wake_for_precedent_extraction(
return {"ok": False, "error": f"wakeup: {e}", "issue_id": issue_id, "identifier": identifier}
async def wake_ceo_for_feedback_fold(
*,
feedback_id: str,
feedback_text: str,
lesson_extracted: str,
category: str,
block_id: str = "",
case_number: str = "",
practice_area: str = "",
) -> dict:
"""Wake the CEO to fold one resolved chair-feedback lesson into the right
knowledge file (the feedback→agent-knowledge loop).
Mirrors ``wake_for_precedent_extraction``: creates a Paperclip issue under
the library project carrying the lesson + a category→file routing rubric,
then wakes the CEO (reason ``feedback_fold_<identifier>``). The CEO folds
the lesson per the rubric and closes the issue.
Best-effort: any failure is logged and returned as ``{"ok": False, ...}``
so resolving the feedback never fails because Paperclip is down.
"""
if not PAPERCLIP_BOARD_API_KEY:
logger.warning("PAPERCLIP_BOARD_API_KEY not set — skipping feedback-fold wakeup")
return {"ok": False, "skipped": "no_api_key"}
# decision-lessons.md is shared across companies → either CEO works; route
# by the case's practice area when known, else default to licensing.
company_id = await _get_company_id(practice_area)
ceo_id = CEO_AGENTS.get(company_id, CEO_AGENT_ID)
# category → target file routing rubric (embedded in the issue so the CEO
# has it even if its prompt is trimmed). Keep in sync with legal-ceo.md.
routing = {
"style": "skills/decision/SKILL.md",
"wrong_structure": "docs/block-schema.md + docs/legal-decision-lessons.md",
"missing_content": "docs/legal-decision-lessons.md",
"factual_error": "docs/legal-decision-lessons.md",
"wrong_tone": "docs/legal-decision-lessons.md",
"other": "שיקול דעת — לרוב באג מערכת → משימת TaskMaster, לא לקח",
}
target = routing.get(category, "docs/legal-decision-lessons.md")
try:
conn = await asyncpg.connect(PAPERCLIP_DB_URL)
try:
project_id = await _get_or_create_library_project(conn, company_id)
row = await conn.fetchrow(
"UPDATE companies SET issue_counter = issue_counter + 1 "
"WHERE id = $1::uuid RETURNING issue_counter",
company_id,
)
issue_number = row["issue_counter"]
prefix = "CMP" if company_id == COMPANIES["licensing"] else "CMPA"
identifier = f"{prefix}-{issue_number}"
issue_id = str(uuid.uuid4())
short = (feedback_text[:90] + "") if len(feedback_text) > 90 else feedback_text
description = (
f"היו\"ר סימנה הערת פידבק כ\"יושמה\" — יש לקפל את הלקח לקובץ הידע הנכון.\n\n"
f"**feedback_id:** `{feedback_id}`\n"
f"**קטגוריה:** {category}\n"
f"**בלוק:** {block_id or ''}\n"
f"**תיק:** {case_number or ''}\n\n"
f"**ההערה:**\n{feedback_text}\n\n"
f"**הלקח שהופק:**\n{lesson_extracted or '(אין — הפק לקח מההערה)'}\n\n"
f"---\n\n"
f"**יעד קיפול לפי הקטגוריה:** `{target}`\n\n"
f"**משימה:**\n"
f"1. קרא את קובץ היעד והבן מה כבר מתועד שם.\n"
f"2. הוסף את הלקח **רק אם אינו קיים** (לא כפל). משפט אחד ברור + Rule באנגלית.\n"
f"3. אם הקטגוריה היא `other` והלקח הוא באג מערכת ולא לקח כתיבה — "
f"אל תוסיף לקובץ; פתח/עדכן משימת TaskMaster במקום.\n"
f"4. סמן את ה-issue כ-done ופתח comment קצר: לאיזה קובץ קופל ומה נוסף.\n"
)
await conn.execute(
"""INSERT INTO issues
(id, company_id, project_id, title, description,
status, priority, issue_number, identifier, assignee_agent_id)
VALUES ($1, $2::uuid, $3::uuid, $4, $5, 'todo', 'low',
$6, $7, $8::uuid)""",
issue_id, company_id, project_id,
f"[לקח] קיפול הערת יו\"ר: {short}"[:200],
description,
issue_number, identifier, ceo_id,
)
finally:
await conn.close()
except Exception as e:
logger.exception("wake_ceo_for_feedback_fold: DB step failed: %s", e)
return {"ok": False, "error": f"db: {e}"}
payload = {
"source": "automation",
"triggerDetail": "feedback_resolved",
"reason": f"feedback_fold_{identifier}",
"payload": {
"issueId": issue_id,
"mutation": "feedback_fold",
"feedbackId": feedback_id,
},
}
try:
resp = await pc_request(
"POST", f"/api/agents/{ceo_id}/wakeup",
json=payload, raise_on_error=True,
)
logger.info("feedback-fold wakeup queued: issue=%s feedback=%s", identifier, feedback_id)
return {"ok": True, "issue_id": issue_id, "identifier": identifier, "wakeup": resp.json()}
except Exception as e:
logger.exception("wake_ceo_for_feedback_fold: wakeup API failed: %s", e)
return {"ok": False, "error": f"wakeup: {e}", "issue_id": issue_id, "identifier": identifier}
async def wake_ceo_agent(issue_id: str, case_number: str, company_id: str = "") -> dict:
"""Wake the CEO agent via Paperclip's wakeup API.