feat(case-ui): כרטיס "הפקת מסמכים" עם 3 כפתורי-הפק דטרמיניסטיים (#214)
מוסיף כרטיס "הפקת מסמכים" בראש טאב "טיוטות והערות" (mockup 26 — תוספת ל-18h),
תוספת לעמוד הקיים, כל הסקשנים נשמרים.
- כפתור 1 "הפק סיכום מנהלים" → endpoint חדש POST /generate/party-claims-summary
→ CEO wakeup סטרוקטורלי action="party_claims_summary" (שלב H2, host-side).
Polling: GET /research/party-claims-summary (200=מוכן → פתח/DOCX).
- כפתור 2 "הפק טיוטה של טענות הצדדים" → endpoint חדש POST /generate/interim-draft
→ CEO wakeup action="interim_draft" (שלב H, host-side).
Polling: רשימת ה-exports עד שמופיע טיוטת-ביניים-{case}-vN.docx.
- כפתור 3 "הפק טיוטת החלטה מלאה" → ה-useExportDocx הקיים (in-container, ללא LLM);
הועבר מהבאנר (כפתור "הפק DOCX" הוסר משם — אין כפילות). disabled+title כשאין
בלוקים כתובים (isDraftReady).
מסלול-עירור יחיד דרך ה-Platform Port (pc_wake_ceo_for_action) → API helper
/api/agents/{id}/wakeup, לעולם לא DB insert. Israel-time + cache-invalidation.
Invariants: G12 (מגע-Paperclip רק ב-paperclip_client + agent_platform_port;
leak-guard ירוק) · G2 (אין מסלול-עירור מקביל — שימוש חוזר ב-pc_request הקיים) ·
G10 (הפקה מגודרת-יו"ר/CEO) · INV-UI9 (Asia/Jerusalem) · X6 (UI↔API contract).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
46
web/app.py
46
web/app.py
@@ -79,6 +79,7 @@ from web.agent_platform_port import (
|
||||
pc_wake_analyst_for_argument_aggregation,
|
||||
rename_case_project,
|
||||
pc_wake_ceo,
|
||||
pc_wake_ceo_for_action,
|
||||
pc_wake_ceo_for_feedback_fold,
|
||||
pc_wake_curator_for_final,
|
||||
pc_wake_for_precedent_extraction,
|
||||
@@ -3090,6 +3091,51 @@ async def api_party_claims_summary(case_number: str):
|
||||
return {"markdown": path.read_text(encoding="utf-8")}
|
||||
|
||||
|
||||
# ── Deterministic document generation triggers (TaskMaster #214) ─────
|
||||
# The "הפקת מסמכים" buttons in the case "טיוטות והערות" tab. Generation for the
|
||||
# executive summary + interim draft runs HOST-SIDE (claude_session → claude -p,
|
||||
# not in the container), so these endpoints fire a *structured-action* CEO wakeup
|
||||
# (the CEO reads payload.action and routes to שלב H2 / שלב H — legal-ceo.md).
|
||||
# Wakeup goes through the Paperclip API helper (pc_wake_ceo_for_action → the
|
||||
# platform Port → POST /api/agents/{id}/wakeup), NEVER a direct DB insert.
|
||||
# Polling for completion uses the existing read endpoints (research/party-claims-
|
||||
# summary for the summary; the exports list for the טיוטת-ביניים-*.docx file).
|
||||
|
||||
|
||||
async def _wake_ceo_action(case_number: str, action: str) -> dict:
|
||||
"""Resolve the case's company + fire a structured-action CEO wakeup (#214)."""
|
||||
case = await db.get_case_by_number(case_number)
|
||||
if not case:
|
||||
raise HTTPException(404, f"תיק {case_number} לא נמצא")
|
||||
prefix = case_number[:1]
|
||||
company_id = (
|
||||
PAPERCLIP_COMPANIES["licensing"] if prefix == "1"
|
||||
else PAPERCLIP_COMPANIES["betterment"] if prefix in ("8", "9")
|
||||
else ""
|
||||
)
|
||||
try:
|
||||
return await pc_wake_ceo_for_action(case_number, action, company_id=company_id)
|
||||
except Exception as e:
|
||||
logger.warning("CEO action %s wakeup failed for %s: %s", action, case_number, e)
|
||||
return {"status": "error", "error": str(e)}
|
||||
|
||||
|
||||
@app.post("/api/cases/{case_number}/generate/party-claims-summary", status_code=202)
|
||||
async def api_generate_party_claims_summary(case_number: str):
|
||||
"""Fire-and-accept: wake the CEO to generate the party-claims executive summary
|
||||
(שלב H2 → summarize_party_claims). Runs host-side; poll
|
||||
GET /api/cases/{n}/research/party-claims-summary for completion."""
|
||||
return await _wake_ceo_action(case_number, "party_claims_summary")
|
||||
|
||||
|
||||
@app.post("/api/cases/{case_number}/generate/interim-draft", status_code=202)
|
||||
async def api_generate_interim_draft(case_number: str):
|
||||
"""Fire-and-accept: wake the CEO to generate the partial "party-claims" draft
|
||||
(שלב H → write_interim_draft + export_interim_draft). Runs host-side; poll the
|
||||
exports list for the new טיוטת-ביניים-{case}-vN.docx."""
|
||||
return await _wake_ceo_action(case_number, "interim_draft")
|
||||
|
||||
|
||||
@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."""
|
||||
|
||||
Reference in New Issue
Block a user