fix(sync): מיפוי-הסטטוסים נגזר מ-/api/status-model, וסריקה בכל החברות (legal-ai #604)
שלושה כשלים בג'וב sync-case-status, שהשביתו אותו בשקט מאז 22.7: 1. המפה הקשיחה CASE_STATUS_TO_ISSUE_STATUS נותקה מ-case_status_model.py (מקור-האמת בצד legal-ai): חסרו analyst_verified ו-research_complete שנוספו ב-851a4fb, ונשארו בה 3 מפתחות מתים (uploading/brainstorming/drafting). סטטוס חסר נפל ל-`continue` — בלי לוג ובלי שגיאה. כעת המיפוי נגזר מ- GET /api/status-model דרך resolveIssueStatus/labelFor: terminal→done, הסטטוס הראשון בסדר→todo, השאר→in_progress. סטטוס חדש בצד legal-ai לא דורש עוד עריכה כאן (G2 — מקור-אמת אחד). 2. companies[0] בלבד — מתוך שתי החברות, אחת מעולם לא נסרקה (נמדד: 135 מול 67 issues מקושרי-תיק). כעת נסרקות כל החברות, וה-companyId של המועמד שנבחר הוא זה שנכתב אליו — לא החברה הראשונה גורפת. 3. דילוג שקט על סטטוס לא-מוכר → ctx.logger.warn עם שם-הסטטוס ומספר-התיק. אימות מול השרת החי: 0 סטיות מול המפה הישנה על כל 10 הסטטוסים שכיסתה, +2 שכוסו לראשונה. סימולציה על הנתונים החיים: דילוג-שקט 3→0, שורות-לוג 3→6, כתיבות בפועל 0→0 — כלומר אין נסיגה ל-flip-flop של #446. לוגיקת בחירת-היעד (#446) לא שונתה: pickSyncTargetIssue, isWritableStatus, CLOSED_ISSUE_STATUSES ו-NON_WRITABLE_STATUSES זהות; ל-SyncCandidate נוסף שדה companyId בלבד (passthrough). 8 הטסטים הקיימים עוברים ללא שינוי באסרשנים, +7 חדשים. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,9 +7,12 @@
|
||||
*
|
||||
* המודול הזה טהור בכוונה — בלי import מה-SDK ובלי side effects — כדי שאפשר
|
||||
* יהיה לייבא אותו ישירות בטסט בלי להריץ את `runWorker(plugin, import.meta.url)`
|
||||
* שקורה בזמן import של worker.ts.
|
||||
* שקורה בזמן import של worker.ts. ה-import היחיד למטה הוא type-only (`import
|
||||
* type`), כך שהוא לא נדרס בזמן ריצה ולא שובר את הטוהר הזה.
|
||||
*/
|
||||
|
||||
import type { StatusModelEntry } from "./legal-api.ts";
|
||||
|
||||
/** "סגור" — ההגדרה היחידה. מראה של web/paperclip_client.py:561 ב-legal-ai. */
|
||||
export const CLOSED_ISSUE_STATUSES: ReadonlySet<string> = new Set([
|
||||
"done",
|
||||
@@ -33,6 +36,7 @@ export interface SyncCandidate {
|
||||
id: string;
|
||||
status: string;
|
||||
parentId: string | null;
|
||||
companyId: string;
|
||||
}
|
||||
|
||||
export type SyncTargetReason =
|
||||
@@ -77,3 +81,32 @@ export function pickSyncTargetIssue(
|
||||
writableRoots: roots.length,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the coarse Paperclip issue status for a legal-ai case status, using
|
||||
* only generic fields already returned by legal-ai's `/api/status-model`
|
||||
* (the canonical `case_status_model.py` registry) — never a hardcoded list of
|
||||
* case-status keys. This is what makes a new case status "just work" without
|
||||
* editing this plugin: `terminal: true` → done; the very first status in the
|
||||
* ordered list → todo (nothing has started yet); everything else → in_progress.
|
||||
* Returns `null` when `caseStatus` is not present in `statuses` at all (a
|
||||
* genuinely unknown status — the caller must log this loudly, never swallow
|
||||
* it silently; see legal-ai issue #604).
|
||||
*/
|
||||
export function resolveIssueStatus(
|
||||
statuses: readonly StatusModelEntry[],
|
||||
caseStatus: string,
|
||||
): "todo" | "in_progress" | "done" | null {
|
||||
const index = statuses.findIndex((s) => s.key === caseStatus);
|
||||
if (index === -1) return null;
|
||||
if (statuses[index].terminal) return "done";
|
||||
return index === 0 ? "todo" : "in_progress";
|
||||
}
|
||||
|
||||
/** Hebrew label for a case status from the canonical model, or null if unknown. */
|
||||
export function labelFor(
|
||||
statuses: readonly StatusModelEntry[],
|
||||
caseStatus: string,
|
||||
): string | null {
|
||||
return statuses.find((s) => s.key === caseStatus)?.label ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user