feat(plans): הרשאות-סוכנים + dedup/merge/edit + API לתור-אישור תכניות (backend)
Follow-ups למרשם-התכניות (PR #252), חלק ה-backend (ללא-UI): - סוכנים: הוספת extract_plans/plan_get/plan_search/plan_list ל-CEO ול-חוקר (+ plan_upsert לחוקר); plan_review נשאר אנושי בלבד (G10). .claude/agents/*.md. - db: _plan_core_token + find_similar_plans (הצפת כפילות-וריאנט לאישור ידני, בלי מיזוג-אוטומטי), update_plan (עריכה+renumber, guard התנגשות→merge), merge_plans (איחוד aliases, מילוי-חוסר, סתירות→discrepancies, מחיקת מקור). - plans_extractor: צירוף possible_duplicates לפלט החילוץ. - web/app.py: GET /api/plans(+/{id},/{id}/duplicates) · POST /api/plans · PATCH /api/plans/{id} · POST /api/plans/{id}/review · POST /api/plans/merge; +קטגוריית "תכניות הממתינות לאישור" ב-/api/chair/pending. תיקון-נתונים (DB, מחוץ ל-PR): הל/מח/250 ד' → 7.1.2002, י"פ 5045. ה-UI (טאב /precedents + מונה /approvals) ב-PR נפרד אחרי שער Claude Design. Invariants: G1 (נרמול בכתיבה/עריכה) · G2 · G3 · G10 (review_status + מיזוג ידני, אישור אנושי) · INV-DM2/DM5 · INV-AH · X9 · אין בליעה שקטה (discrepancies). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -182,12 +182,25 @@ async def extract_plans_for_case(case_id: UUID) -> dict:
|
||||
"status": "completed", "candidates": len(cands),
|
||||
})
|
||||
|
||||
# Surface near-duplicates for the chair to merge manually (G10) — never
|
||||
# auto-merged. A variant of an existing plan written differently won't share
|
||||
# the normalized key, so flag it here instead of silently creating a dup.
|
||||
plans_out = list(seen_numbers.values())
|
||||
dup_hits = 0
|
||||
for p in plans_out:
|
||||
sims = await db.find_similar_plans(
|
||||
p["plan_number"], p.get("display_name", ""), exclude_id=UUID(p["id"]),
|
||||
)
|
||||
p["possible_duplicates"] = sims
|
||||
dup_hits += len(sims)
|
||||
|
||||
return {
|
||||
"status": "completed",
|
||||
"case_number": source_case_number,
|
||||
"documents_scanned": len(by_doc),
|
||||
"total_candidates": total_candidates,
|
||||
"distinct_plans": len(seen_numbers),
|
||||
"plans": list(seen_numbers.values()),
|
||||
"distinct_plans": len(plans_out),
|
||||
"possible_duplicate_hits": dup_hits,
|
||||
"plans": plans_out,
|
||||
"by_document": by_doc,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user