feat(precedents): auto-trigger Claude extraction via Paperclip wakeup
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 7s

When a precedent is uploaded to the library, the FastAPI container now
fires a Paperclip wakeup so Claude (running locally as the CEO agent)
picks up the new row and runs `precedent_process_pending` for both
metadata and halacha extraction. The user no longer has to remember to
trigger it manually.

Mechanics:
- New `wake_for_precedent_extraction()` in paperclip_client.py creates
  (or reuses) a per-company "ספריית פסיקה — תור חילוץ" project, opens
  a fresh issue assigned to the company CEO with the case_law_id +
  citation in the description, and pings the Board API wakeup endpoint
  with `triggerDetail=precedent_library_upload`.
- ingest_precedent's _run() in app.py captures the returned case_law_id
  and best-effort calls the wake function (failures are logged, not
  surfaced — the upload itself stays clean).
- legal-ceo.md adds the precedent_process_pending tool family and a
  new "חילוץ פסיקה אוטומטי" section that tells the CEO to short-circuit
  past the heartbeat scan when woken with this trigger.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 16:49:25 +00:00
parent da0a385d9c
commit 923903217c
3 changed files with 183 additions and 1 deletions

View File

@@ -48,6 +48,7 @@ from web.paperclip_client import (
post_comment as pc_post_comment,
restore_project as pc_restore_project,
wake_ceo_agent as pc_wake_ceo,
wake_for_precedent_extraction as pc_wake_for_precedent_extraction,
)
@@ -3625,7 +3626,7 @@ async def precedent_library_upload(
async def _run():
try:
await plib_service.ingest_precedent(
result = await plib_service.ingest_precedent(
file_path=staged,
citation=citation.strip(),
case_name=case_name.strip(),
@@ -3641,6 +3642,19 @@ async def precedent_library_upload(
summary=summary.strip(),
progress=publish,
)
# Auto-trigger Claude (via Paperclip) to extract halachot+metadata.
# Best-effort — failures are logged but don't surface to the user;
# `precedent_process_pending` can always be run manually.
case_law_id = result.get("case_law_id") if isinstance(result, dict) else None
if case_law_id:
try:
await pc_wake_for_precedent_extraction(
case_law_id=case_law_id,
citation=citation.strip(),
practice_area=practice_area,
)
except Exception:
logger.exception("precedent-extraction wakeup failed (non-fatal)")
except Exception as e:
logger.exception("precedent-library upload failed")
await _progress.set(task_id, {