fix(appraiser-facts): route extraction through analyst wakeup (was silent 0)
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m38s

The "חלץ עובדות שמאיות" UI button hit POST /api/cases/{n}/extract-appraiser-facts
which called appraiser_facts_extractor inline — that shells out to the local
`claude` CLI, which is absent in the Coolify container, so every doc errored,
the per-doc try/except swallowed it, and the response was "completed, 0 facts".

Refactored the endpoint to wake the legal-analyst of the correct company via
Paperclip (same pattern as wake_curator_for_final), and surface
extraction_failed instead of "completed" when every doc errored.
This commit is contained in:
2026-05-26 11:02:55 +00:00
parent 7ad995aade
commit 3a05e30c8d
5 changed files with 221 additions and 13 deletions

View File

@@ -269,6 +269,26 @@ function PostSaveView({
</div>
)}
{extractResult?.status === "queued" && (
<div className="rounded-md border border-info/30 bg-info-bg px-2.5 py-2 text-[0.72rem] text-ink space-y-0.5">
<p>
<strong>נשלח לאנליטיקאי.</strong> ה-issue נפתח ב-Paperclip והחילוץ
ירוץ ברקע. תראה comment בעברית עם התוצאה כשהוא יסיים לרוב כמה
דקות.
</p>
</div>
)}
{extractResult?.status === "skipped" && (
<div className="rounded-md border border-warn/40 bg-warn-bg px-2.5 py-2 text-[0.72rem] text-ink space-y-0.5">
<p>
<strong>לא ניתן להפעיל אוטומטית</strong> ({extractResult.reason}).
הפעל ידנית מ-Claude Code:
<code className="ms-1 select-all">mcp__legal-ai__extract_appraiser_facts</code>
</p>
</div>
)}
{extractResult?.status === "no_appraisals" && (
<p className="text-[0.72rem] text-ink-muted">
אין בתיק מסמכים מתויגים כ-שומה.
@@ -320,8 +340,8 @@ function PostSaveView({
{pending && (
<p className="text-[0.68rem] text-ink-muted leading-tight">
החילוץ יכול להימשך כמה דקות שומות ארוכות עוברות ניתוח פסקה אחר
פסקה ע"י המודל.
שולח לאנליטיקאי דרך Paperclip לוקח שנייה. החילוץ עצמו ירוץ אצל
האנליטיקאי וייתן comment כשיסיים.
</p>
)}
</div>

View File

@@ -160,6 +160,23 @@ export type ExtractAppraiserFactsResponse =
appraisal_count: number;
missing: { document_id: string; title: string; current_side: string }[];
message: string;
}
| {
// The chair clicked the button; backend created a child Paperclip
// issue assigned to the legal-analyst, which will run the MCP tool
// on the host (where the Claude CLI lives) and post results back.
status: "queued";
sub_issue_id: string;
analyst_id: string;
main_issue_id: string;
}
| {
// No analyst route was available (no API key / no analyst configured /
// no Paperclip issue linked to the case). Non-fatal — the chair can
// still trigger extraction manually from Claude Code.
status: "skipped";
reason: "no_api_key" | "no_analyst" | "no_issue" | string;
company_id?: string;
};
async function extractAppraiserFacts(