feat(analysis): סיכום-מנהלים מזוקק של טענות הצדדים — מסמך הכנה לדיון (#202, WS3)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s

מסמך פרוזה נפרד מטיוטת-הביניים (החלטת-יו"ר): תמצית מוקפדת של טענות+תשובות
להכנת היו"ר לדיון. נגזר מ-legal_arguments/claims הקיימים — אותו מקור-אמת,
ללא חילוץ-מחדש (G2). מתוחם לטענות-התיק בלבד (INV-AH).

- כלי-MCP חדש summarize_party_claims (drafting.py + server.py); ייצור עובר
  claude_session נעוץ Opus 4.8 + effort=high (זיקוק/סינתזה); local-only.
- שירות party_claims_summary.py: בחירת-מקור arguments→claims, פרומפט מעוגן-מקור,
  שמירה ל-data/cases/{n}/documents/research/ (git + S3).
- ייצוא DOCX בסגנון-תבנית דפנה (build_party_claims_summary_docx) + endpoints
  read/download/export-docx ב-web/app.py (מגישים בלבד — אין claude CLI בקונטיינר).
- _next_version הוכלל ל-prefix-scoped (תאימות-לאחור) למניעת התנגשות-גרסאות.
- ספ 04-analysis-writing.md §1.3 + 8 בדיקות אופליין (מקור/נעיצת-מודל/markdown→docx).

Invariants: G2 (מקור-אמת יחיד, בלי מסלול מקביל) · X9 TOOL1/TOOL4 (envelope +
extract↔serve) · INV-AH (עיגון-מקור, abstention על טענה לא-ברורה) ·
claude_session local-only · G9 (provenance — נשמר durably + git/S3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-30 11:22:20 +00:00
parent 61e6be4b90
commit aa2548ff5d
7 changed files with 605 additions and 3 deletions

View File

@@ -3063,6 +3063,58 @@ async def api_research_analysis_export_docx(case_number: str):
)
# ── Party-claims executive summary (party-claims-summary.md) — #202 ─
# A distilled prose document of the parties' claims, SEPARATE from the interim
# draft, to prepare the chair for the hearing. Generation is local-only (the
# summarize_party_claims MCP tool via claude_session); these endpoints only
# SERVE the saved file — they never generate (the container has no claude CLI).
@app.get("/api/cases/{case_number}/research/party-claims-summary")
async def api_party_claims_summary(case_number: str):
"""Return the raw markdown of the party-claims executive summary."""
from legal_mcp.services import party_claims_summary as pcs
path = pcs.summary_file_path(case_number)
if not path.exists():
raise HTTPException(404, "טרם הופק סיכום-מנהלים לטענות הצדדים לתיק זה")
return {"markdown": path.read_text(encoding="utf-8")}
@app.get("/api/cases/{case_number}/research/party-claims-summary/download")
async def api_party_claims_summary_download(case_number: str):
"""Download the raw party-claims-summary.md file."""
from legal_mcp.services import party_claims_summary as pcs
path = pcs.summary_file_path(case_number)
if not path.exists():
raise HTTPException(404, "טרם הופק סיכום-מנהלים לטענות הצדדים לתיק זה")
return await serve_blob(
path,
media_type="text/markdown; charset=utf-8",
filename=f"party-claims-summary-{case_number}.md",
)
@app.get("/api/cases/{case_number}/research/party-claims-summary/export-docx")
async def api_party_claims_summary_export_docx(case_number: str):
"""Export the party-claims summary as a DOCX using דפנה's template styles."""
from legal_mcp.services.analysis_docx_exporter import build_party_claims_summary_docx
try:
path = await build_party_claims_summary_docx(case_number)
except FileNotFoundError as e:
raise HTTPException(404, str(e))
except Exception as e:
logger.exception("Failed to export party-claims summary DOCX for %s", case_number)
raise HTTPException(500, f"שגיאה בייצוא: {e}")
case_dir = config.find_case_dir(case_number)
if case_dir.exists():
commit_and_push(case_dir, f"סיכום-מנהלים: {path.name}")
return await serve_blob(
path,
media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
filename=path.name,
)
@app.put("/api/cases/{case_number}/research/analysis/upload")
async def api_research_analysis_upload(
case_number: str,