From a2236363d4c40f6880212e41255fef76238a95b0 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 6 Jun 2026 18:57:02 +0000 Subject: [PATCH] =?UTF-8?q?feat(mcp):=20FU-14=20GAP-50=20=E2=80=94=20depre?= =?UTF-8?q?cate=20draft=5Fsection=20=D7=9C=D7=98=D7=95=D7=91=D7=AA=20get?= =?UTF-8?q?=5Fblock=5Fcontext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit INV-TOOL2. מיפוי הראה ש-6 כלי-הבלוק אינם כפילות מיותרת: write_block/ write_all_blocks/save_block_content/write_interim_draft משרתים זרימות שונות (CLI/initial-draft מול תהליך-ה-writer "התיקון בקובץ, לא ב-DB"). הכפילות האמיתית היחידה — draft_section (הקשר לפי-סעיף, granularity ישן) חופף ל- get_block_context (לפי-בלוק, תואם 12-הבלוקים הקנוני). הכרעת-יו"ר: draft_section סומן deprecated (docstring ב-server.py + drafting.py מפנה ל-get_block_context; draft-decision.md עודכן). ללא הסרה, ללא מיזוג כלי- הכתיבה — שמירת תהליך-הכתיבה המכוון. בדיקות: 182/182 עוברים. GAP-49+50 סגורים. Invariants: מקדם INV-TOOL2 + G2. מתועד ב-X9 (נסגר) + gap-audit פרוסה 9. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/commands/draft-decision.md | 2 +- docs/spec/X9-mcp-tool-contract.md | 3 ++- docs/spec/gap-audit.md | 3 ++- mcp-server/src/legal_mcp/server.py | 4 +++- mcp-server/src/legal_mcp/tools/drafting.py | 6 +++++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.claude/commands/draft-decision.md b/.claude/commands/draft-decision.md index 348e0db..76787df 100644 --- a/.claude/commands/draft-decision.md +++ b/.claude/commands/draft-decision.md @@ -9,7 +9,7 @@ 3. שלוף את תבנית ההחלטה עם get_decision_template לכל סעיף: -4. השתמש ב-draft_section כדי לקבל הקשר מלא (מסמכי התיק + תקדימים + סגנון) +4. השתמש ב-get_block_context(case_number, block_id) כדי לקבל הקשר מלא לבלוק (מסמכי התיק + תקדימים + סגנון). [draft_section הישן deprecated — GAP-50] 5. נסח את הסעיף בסגנון דפנה על בסיס ההקשר 6. הצג למשתמש ובקש אישור/עריכה לפני המשך לסעיף הבא diff --git a/docs/spec/X9-mcp-tool-contract.md b/docs/spec/X9-mcp-tool-contract.md index 8b25cad..bf6b736 100644 --- a/docs/spec/X9-mcp-tool-contract.md +++ b/docs/spec/X9-mcp-tool-contract.md @@ -49,7 +49,8 @@ JSON-RPC 2.0 (result/error envelope) (https://www.jsonrpc.org/specification) · Google *API Design Guide* (naming) (https://cloud.google.com/apis/design/naming_convention) · Zalando *RESTful API Guidelines* | סטטוס: verified **אכיפה:** איחוד/מיזוג כלי-חיפוש + כלי-בלוק; rename של שמות-מטעים. **GAP-49 (חלק קריטי) ✅ נסגר (2026-06-06):** הכלי המטעה `precedent_search_library` (חיפוש ציטוטים מצורפים-לתיק) שונה ל-**`search_case_precedents`** — מבטל את ההיפוך המסוכן מול `search_precedent_library` (הספרייה הסמכותית); הישן נשמר כ-alias deprecated לתאימות. docstrings של שני הכלים הובהרו (case-attached מול authoritative). 5 כלי-החיפוש הנותרים (search_decisions=סגנון-דפנה · search_case_documents=תיק · find_similar_cases=cross-case · search_internal_decisions=ועדות-ערר · search_precedent_library=פסיקה-סמכותית) מחפשים קורפוסים מובחנים עם שמות סבירים. -**הפרה ידועה:** 6 כלי-בלוק חופפים ([gap-audit GAP-50](gap-audit.md)) — בטיפול נפרד. +**GAP-50 ✅ נסגר (2026-06-06, הכרעת-יו"ר):** הכפילות האמיתית היחידה — `draft_section` (הקשר לפי-סעיף, ישן) — סומנה **deprecated** לטובת `get_block_context` (הקשר לפי-בלוק, תואם 12-הבלוקים). שאר כלי-הכתיבה (`write_block`/`write_all_blocks`/`save_block_content`/`write_interim_draft`) **מובחנים בכוונה** — משרתים זרימות שונות (CLI/initial-draft מול תהליך-ה-writer שבו "התיקון חי בקובץ, לא ב-DB"), ולא מוזגו במכוון. +**הפרה ידועה:** — (נסגר) ### INV-TOOL3: idempotency בכל כלי-מוטציה **כלל:** כלי שמשנה-מצב הוא **idempotent על מפתח דטרמיניסטי** — קריאה חוזרת אינה יוצרת כפילות. מופע של diff --git a/docs/spec/gap-audit.md b/docs/spec/gap-audit.md index 8688284..d73e80f 100644 --- a/docs/spec/gap-audit.md +++ b/docs/spec/gap-audit.md @@ -84,7 +84,7 @@ | GAP-47 | `draft_section` ללא provenance (chunk→document/page); הנחיות-יו"ר ב-md ולא DB | INV-TOOL4, G9 | Medium | `mcp-server/.../drafting.py` | provenance בפלט + DB ל-directions | | GAP-48 | envelope-תשובה לא-עקבי (71 כלים: string/JSON/{error}) | INV-TOOL1, G2 | Medium | `mcp-server/.../server.py`, tools/ | wrapper `{status,data,message}` | | GAP-49 | 6 כלי-חיפוש חופפים + `precedent_search_library` שם-מטעה | INV-TOOL2, G2 | Medium | `server.py` (search_*), `precedents.py:81` | ✅ **שם-מטעה תוקן** (`precedent_search_library`→`search_case_precedents`, alias deprecated); 5 הנותרים = קורפוסים מובחנים בשמות סבירים | -| GAP-50 | 6 כלי-כתיבת-בלוק חופפים (draft_section/get_block_context/write_*/save_*) | INV-TOOL2, G2 | Medium | `server.py:500-616` | מיזוג context↔write | +| GAP-50 | 6 כלי-כתיבת-בלוק חופפים (draft_section/get_block_context/write_*/save_*) | INV-TOOL2, G2 | Medium | `server.py:500-616` | ✅ **draft_section deprecated→get_block_context** (הכרעת-יו"ר); write_*/save_* מובחנים בכוונה (זרימות שונות), לא מוזגו | | GAP-51 | `set_outcome` enum-mismatch (3≠4); אוצרות-מילים סותרות | INV-TOOL1/UI1 | Medium | `block_writer.py:442` מול `lessons.py:11`, `workflow.py:145` | SSoT יחיד ל-outcome | | GAP-52 | רוב הכלים לא-idempotent (case_create/document_upload/precedent_attach) | INV-TOOL3, G3 | Medium | `server.py`, tools/ | upsert/ON CONFLICT | | GAP-53 | אין limit-caps (precedent_library_list/search_*/list_chair_feedback) | INV-TOOL5 | Low | tools/ | clamp ל-max | @@ -206,6 +206,7 @@ - **סטטוס חלקי (פרוסה 6, 2026-06-06):** 🔄 **GAP-48 — מיגרציה רוחבית.** הומרו 10 משפחות נוספות ל-envelope: `precedent_library` (14), `citations` (3), `internal_decisions` (1), `missing_precedents` (4), `training_enrichment` (2), `precedents` (4), `legal_arguments` (2), `cases` (7), `documents` (8), `workflow` (9). בוטלו 5 עותקי `_ok`/`_err` משוכפלים (alias ל-SSoT, G2). עיקרון: envelope-`status` = הצלחת-הקריאה; תוצאה-עסקית (idempotent_existing/noop/...) ב-`data`. צרכני-app.py של cases/workflow/precedents חוּוטו דרך `envelope_unwrap` + בדיקת `status=="error"`→4xx, לשמירת חוזה-ה-API. כל הטסטים עוברים (182/182; `test_corpus_constraints` עודכן לחוזה). **נותר:** משפחת `drafting` (18 כלים — מסלול הפקת-ההחלטה) בפרוסה נפרדת. - **פרוסה 7, 2026-06-06 — ✅ GAP-48 הושלם.** משפחת `drafting` (18 כלים) הומרה ל-envelope. export_docx/revise_draft/apply_user_edit משתמשים ב-`err`-לכשל (כך שהסוכן והמשתמש רואים את הכשל ברמת-המעטפת), כש-`failed_gates` רוכב ב-`data`; 6 צרכני-app.py (get_decision_template/apply_user_edit×2/revise_draft/list_bookmarks/export_docx) חוּוטו עם בדיקת envelope-status; `test_export_qa_gate` עודכן לחוזה (182/182 עוברים). **GAP-48 סגור — כל ~12 המשפחות אחידות.** - **פרוסה 8, 2026-06-06 — ✅ GAP-49 (החלק הקריטי).** השם המטעה `precedent_search_library` (ציטוטים מצורפים-לתיק) שונה ל-`search_case_precedents` ובכך בוטל ההיפוך המסוכן מול `search_precedent_library` (ספרייה סמכותית — מקור CREAC). הישן נשמר כ-alias deprecated (ב-server.py) → אפס שבירה לסוכנים חיים. docstrings הובהרו; עודכנו app.py (typeahead) + legal-researcher/legal-writer docs + precedent_library docstring. 5 כלי-החיפוש הנותרים מחפשים קורפוסים מובחנים בשמות סבירים — לא בוצע rename-המוני (churn גבוה, ערך נמוך). 182/182 עוברים. **⚠ אחרי merge+deploy:** סנכרון cross-company של doc-הסוכן (frontmatter `search_case_precedents`). נותר ב-FU-14: GAP-50 (מיזוג כלי-בלוק — נוגע בתהליך-הכתיבה, דורש הכרעת-יו"ר), GAP-54, GAP-47-חלק-ב. +- **פרוסה 9, 2026-06-06 — ✅ GAP-50 (הכרעת-יו"ר).** מיפוי הראה שכלי-הבלוק אינם "כפילות מיותרת": `write_block`/`write_all_blocks`/`save_block_content`/`write_interim_draft` משרתים זרימות שונות (CLI/initial-draft מול תהליך-ה-writer "התיקון בקובץ, לא ב-DB"). הכפילות האמיתית היחידה — `draft_section` (הקשר לפי-סעיף, כמעט-נטוש) חופף ל-`get_block_context` (לפי-בלוק, קנוני). הוחלט (יו"ר): **draft_section deprecated** (docstring ב-server.py+drafting.py מפנה ל-get_block_context; draft-decision.md עודכן) — בלי הסרה, בלי מיזוג כלי-הכתיבה (שמירת תהליך-הכתיבה המכוון). 182/182 עוברים. **GAP-49+50 סגורים.** נותר ב-FU-14: GAP-54 (איחוד קליטת-פסיקה), GAP-47-חלק-ב (הנחיות-יו"ר→DB). ### FU-15 — deploy/env/secrets - **מכסה:** GAP-55..62 · **invariants:** INV-ENV1–ENV5 · **effort:** M · **תלויות:** — diff --git a/mcp-server/src/legal_mcp/server.py b/mcp-server/src/legal_mcp/server.py index e3a4279..1b600fa 100644 --- a/mcp-server/src/legal_mcp/server.py +++ b/mcp-server/src/legal_mcp/server.py @@ -564,7 +564,9 @@ async def draft_section( section: str, instructions: str = "", ) -> str: - """הרכבת הקשר מלא לניסוח סעיף (עובדות + תקדימים + סגנון).""" + """DEPRECATED (GAP-50/INV-TOOL2) — הרכבת הקשר לניסוח לפי **סעיף** (granularity ישן). + העדף את `get_block_context(case_number, block_id)` — הקשר לפי-בלוק, התואם + לארכיטקטורת 12-הבלוקים הקנונית. נשמר זמנית לתאימות-לאחור.""" return await drafting.draft_section(case_number, section, instructions) diff --git a/mcp-server/src/legal_mcp/tools/drafting.py b/mcp-server/src/legal_mcp/tools/drafting.py index 46c4dd1..89db307 100644 --- a/mcp-server/src/legal_mcp/tools/drafting.py +++ b/mcp-server/src/legal_mcp/tools/drafting.py @@ -194,7 +194,11 @@ async def draft_section( section: str, instructions: str = "", ) -> str: - """הרכבת הקשר מלא לניסוח סעיף בהחלטה - כולל עובדות מהמסמכים, תקדימים רלוונטיים ודפוסי סגנון. + """DEPRECATED (GAP-50/INV-TOOL2): העדף את get_block_context — הקשר לפי-בלוק, + התואם לארכיטקטורת 12-הבלוקים הקנונית. כלי זה מרכיב הקשר לפי "סעיף" + (granularity ישן וחופף ל-get_block_context) ונשמר זמנית לתאימות-לאחור. + + הרכבת הקשר מלא לניסוח סעיף בהחלטה - כולל עובדות מהמסמכים, תקדימים רלוונטיים ודפוסי סגנון. Args: case_number: מספר תיק הערר