feat(learning): מסלול נקי להעלאת החלטה סופית + פאנל-סגנון דו-סוכני (DeepSeek+Gemini)
מוסיף מסלול ייעודי לקליטת ההחלטה החתומה של היו"ר, ומפעיל אותו דרך שני
שלבים אוטומטיים מדורגים עם פאנלי-סוכנים (אוטו-אישור + אסקלציה ליו"ר).
Backend (web/):
- POST /api/cases/{case}/final/upload — קליטת final חיצוני: שמירה קנונית
(סופי-{case}.docx + עותק קורפוס-סגנון תחת case_number מלא כדי שבל"מ לא
יתנגש עם ערר באותו מספר), פתיחת draft_final_pairs (final_received). לא נוגע
ב-active_draft ולא מריץ retrofit (נבדל מ-exports/upload ו-mark-final → לא G2).
- POST .../final/run-learning + .../final/run-halacha — שלבים מדורגים שמעירים
worker מקומי (claude/DeepSeek/Gemini מקומיים בלבד) דרך הרחבת
wake_curator_for_final עם param task=learning|halacha.
פאנל-סגנון חדש (scripts/style_lesson_panel.py): שני שופטים (DeepSeek+Gemini)
על-גבי דיסטילציית-ה-Opus; הסכמה 2/2-keep → decision_lesson
(source=panel:deepseek+gemini); substance מדולג (INV-LRN5); הפיך + גיבוי CSV.
פאנל-הלכות: docstring/SCRIPTS.md עודכנו (--apply מחווט).
Frontend (web-ui/): כפתור "העלאת החלטה סופית של היו"ר" + שני כפתורים מדורגים
"הרץ למידת-קול"/"הרץ אימות-הלכות" ב-drafts-panel; כל התוויות בעברית
(badge מקור-לקח: "פאנל: דיפסיק+גמיני", "הרמס (סקירה)"...).
Spec: docs/spec/07-learning.md §0.6. Invariants: INV-LRN1/LRN4/LRN5, G10
(שער-יו"ר ידני להטמעה ל-SKILL.md/lessons.md — הפאנלים יוצרים הצעות בלבד);
G2 (מסלול-סופי הוא יכולת חסרה, לא מסלול-מקביל).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1050,17 +1050,75 @@ async def wake_ceo_agent(issue_id: str, case_number: str, company_id: str = "")
|
||||
return result
|
||||
|
||||
|
||||
def _curator_task_brief(task: str, case_number: str, final_filename: str) -> tuple[str, str]:
|
||||
"""Build the (sub-issue title, description) for a staged final-decision task.
|
||||
|
||||
task='learning' — draft↔final voice distillation + the 2-judge style panel.
|
||||
task='halacha' — extract the halachot CITED in the final + corroboration + the
|
||||
3-judge halacha panel.
|
||||
The curator (Hermes) has Bash + MCP tools, so it both calls MCP tools and runs the
|
||||
local panel scripts. Panels write only reversible, CSV-backed proposals (INV-G10).
|
||||
"""
|
||||
if task == "halacha":
|
||||
title = f"[ערר {case_number}] אימות-הלכות — פאנל 3-סוכנים"
|
||||
description = (
|
||||
f"אימות ההלכות שצוטטו בהחלטה הסופית של תיק {case_number} "
|
||||
f"(`{final_filename}`).\n\n"
|
||||
f"**שלב 1 — ציטוטים:** הרץ "
|
||||
f"`mcp__legal-ai__extract_internal_citations(chair_name=\"דפנה תמיר\")` "
|
||||
f"כדי למפות לאילו תקדימים ההחלטה מפנה.\n"
|
||||
f"**שלב 2 — חילוץ הלכות:** לכל תקדים מצוטט שקיים בספרייה הרץ "
|
||||
f"`mcp__legal-ai__precedent_extract_halachot(case_law_id=...)` (idempotent). "
|
||||
f"תקדים מצוטט שחסר — `mcp__legal-ai__missing_precedent_create`.\n"
|
||||
f"**שלב 3 — corroboration:** `mcp__legal-ai__corroboration_rebuild` לבניית "
|
||||
f"אות-התיקוף (treatment) ומדיניות.\n"
|
||||
f"**שלב 4 — פאנל-הלכות (אוטו-אישור + אסקלציה):** הרץ "
|
||||
f"`cd ~/legal-ai/mcp-server && .venv/bin/python ../scripts/halacha_panel_approve.py --apply`. "
|
||||
f"הסכמה 2/3+ → approved/rejected (הפיך, מגובה ל-CSV); פיצול → נשאר pending_review "
|
||||
f"ליו\"ר. **אל תקבע סמכות binding/persuasive — היא נגזרת מ-precedent_level (INV-DM7).**\n"
|
||||
f"**שלב 5:** כתוב comment בעברית עם סיכום (כמה אושרו/נדחו/הוסלמו), סגור issue (done)."
|
||||
)
|
||||
return title, description
|
||||
|
||||
# default: learning (voice distillation + style panel)
|
||||
title = f"[ערר {case_number}] סקירת ידע — Knowledge Curator"
|
||||
description = (
|
||||
f"דפנה סימנה את ההחלטה הסופית של תיק {case_number} כסופית.\n"
|
||||
f"קובץ סופי: `{final_filename}`\n\n"
|
||||
f"**שלב 1 — דיסטילציה (חובה, draft↔final):** הרץ "
|
||||
f"`mcp__legal-ai__ingest_final_version(case_number=\"{case_number}\")`. "
|
||||
f"הוא משווה את הטיוטה (snapshot מפנקס-ההתאמה) לסופי, מסווג כל שינוי "
|
||||
f"style_method מול substance (INV-LRN5), ושומר את ההצעה ב-draft_final_pairs "
|
||||
f"(status→analyzed). **אל תקבע לקח לבד — זו הצעה לאישור.**\n"
|
||||
f"**שלב 2 — פאנל-סגנון דו-סוכני (DeepSeek+Gemini, אוטו-אישור + אסקלציה):** הרץ "
|
||||
f"`cd ~/legal-ai/mcp-server && .venv/bin/python ../scripts/style_lesson_panel.py "
|
||||
f"--case {case_number} --apply`. הסכמה 2/2 → נכתב כ-decision_lesson "
|
||||
f"(source=panel:deepseek+gemini); פיצול → מוסלם ליו\"ר. רק לקחי style_method "
|
||||
f"נשקלים (substance מדולג, INV-LRN5).\n"
|
||||
f"**שלב 3 — הצעה:** מתוך לקחי-הסגנון שאושרו בפאנל, בחר 3-5 דפוסים שלא תועדו "
|
||||
f"ב-skills/decision/SKILL.md / docs/legal-decision-lessons.md / "
|
||||
f"daphna-voice-fingerprint.md (אל תציע מה שכבר שם). כתוב comment בעברית, ניטרלי, ממוספר.\n"
|
||||
f"**שלב 4:** עדכן MEMORY.md, סגור issue (status=done). הטמעה ל-SKILL.md/lessons.md "
|
||||
f"נשארת אישור-יו\"ר ידני (INV-G10)."
|
||||
)
|
||||
return title, description
|
||||
|
||||
|
||||
async def wake_curator_for_final(
|
||||
case_number: str,
|
||||
final_filename: str,
|
||||
company_id: str = "",
|
||||
task: str = "learning",
|
||||
) -> dict:
|
||||
"""Wake the Knowledge Curator (Hermes) when a case is marked final.
|
||||
"""Wake the Knowledge Curator (Hermes) for a staged final-decision task.
|
||||
|
||||
Creates a child issue under the main case issue, assigns it to the
|
||||
curator, and triggers wakeup. Best-effort — silently skips if no
|
||||
curator is configured for the company or no main issue is found.
|
||||
|
||||
``task`` selects the brief: 'learning' (voice distillation + style panel) or
|
||||
'halacha' (cited-halacha extraction + corroboration + halacha panel).
|
||||
|
||||
Returns ``{"status": "ok"|"skipped", ...}``.
|
||||
"""
|
||||
if not PAPERCLIP_BOARD_API_KEY:
|
||||
@@ -1080,25 +1138,12 @@ async def wake_curator_for_final(
|
||||
main_issue = next((i for i in issues if i.get("status") == "in_progress"), None) or issues[0]
|
||||
main_issue_id = main_issue["id"]
|
||||
|
||||
description = (
|
||||
f"דפנה סימנה את ההחלטה הסופית של תיק {case_number} כסופית.\n"
|
||||
f"קובץ סופי: `{final_filename}`\n\n"
|
||||
f"**שלב 1 — דיסטילציה (חובה, draft↔final):** הרץ "
|
||||
f"`mcp__legal-ai__ingest_final_version(case_number=\"{case_number}\")`. "
|
||||
f"הוא משווה את הטיוטה (snapshot מפנקס-ההתאמה) לסופי, מסווג כל שינוי "
|
||||
f"style_method מול substance (INV-LRN5), ושומר את ההצעה ב-draft_final_pairs "
|
||||
f"(status→analyzed). **אל תקבע לקח לבד — זו הצעה לאישור.**\n"
|
||||
f"**שלב 2 — הצעה:** מתוך השינויים מסוג style_method בלבד, בחר 3-5 דפוסי "
|
||||
f"סגנון/שיטה שלא תועדו ב-skills/decision/SKILL.md / docs/legal-decision-lessons.md / "
|
||||
f"daphna-voice-fingerprint.md (אל תציע מה שכבר שם). כתוב comment בעברית, ניטרלי, ממוספר.\n"
|
||||
f"**שלב 3:** עדכן MEMORY.md, סגור issue (status=done). substance (הלכות/עובדות) — "
|
||||
f"לא נכנס לקול; אם זוהתה הלכה חדשה הפנה למסלול precedent."
|
||||
)
|
||||
title, description = _curator_task_brief(task, case_number, final_filename)
|
||||
child_resp = await pc_request(
|
||||
"POST",
|
||||
f"/api/issues/{main_issue_id}/children",
|
||||
json={
|
||||
"title": f"[ערר {case_number}] סקירת ידע — Knowledge Curator",
|
||||
"title": title,
|
||||
"description": description,
|
||||
"status": "in_progress",
|
||||
"priority": "low",
|
||||
@@ -1126,7 +1171,7 @@ async def wake_curator_for_final(
|
||||
json={
|
||||
"source": "on_demand",
|
||||
"triggerDetail": "manual",
|
||||
"reason": f"final_marked_{case_number}",
|
||||
"reason": f"final_{task}_{case_number}",
|
||||
"payload": {
|
||||
"issueId": sub_issue_id,
|
||||
"mutation": "assignment",
|
||||
|
||||
Reference in New Issue
Block a user