feat(seance): predecessor by-case לצריכת-סוכן דרך ה-plugin (#220 המשך)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s

מוסיף get_predecessor_for_case(case_number) — האח case-scoped של
get_predecessor_context (by-issue). סוכנים חושבים ב-case_number (לא issue-UUID),
לכן זהו הנתיב שכלי-ה-plugin legal_predecessor_context (PR נפרד ב-plugin-legal-ai)
יקרא. מחזיר מסקנות (summary) של ריצות-heartbeat שהסתיימו על-פני issues של התיק,
newest-first, עם summary בלבד (ריצות cancelled ריקות מסוננות).

- shaper משותף _shape_predecessor_run (G2 — נתיב-shaping יחיד ל-by-issue+by-case).
- join בטוח i.id::text = payload->>'issueId' (לא cast של payload חופשי ל-uuid).
- Port pc_get_predecessor_for_case (read-only); endpoint
  GET /api/operations/cases/{case_number}/predecessor.
- 2 בדיקות (shaping+identifier, case-לא-נמצא). אומת חי: 1043-02-26/8125-09-24
  מחזירים מסקנות-דיספוזיציה אמיתיות.

Invariants: G12 (fetch מהמעטפת, המגע מהשער; הכלי יחיה ב-plugin=מעטפת מוצהרת, לא
ב-mcp-server), G2 (shaper יחיד). המשך: PR ב-plugin-legal-ai (כלי) + הוראת-HEARTBEAT.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 05:07:44 +00:00
parent 8d0f8ad17b
commit ad04291d39
4 changed files with 124 additions and 13 deletions

View File

@@ -65,6 +65,7 @@ from web.agent_platform_port import (
pc_get_agent_health,
pc_get_recent_escalations,
pc_get_predecessor_context,
pc_get_predecessor_for_case,
pc_get_agents,
pc_get_agents_for_case,
pc_get_case_issues,
@@ -7615,6 +7616,17 @@ async def operations_issue_predecessor(issue_id: str, limit: int = 3):
return await pc_get_predecessor_context(issue_id, limit)
@app.get("/api/operations/cases/{case_number}/predecessor")
async def operations_case_predecessor(case_number: str, limit: int = 5):
"""Recent finished runs across a case's issues (#220, agent-facing "seance").
Case-scoped sibling of the by-issue endpoint — the plugin tool
``legal_predecessor_context`` calls this so a resuming agent reads what prior
sessions on the case concluded (agents key on case_number, not issue UUID).
"""
return await pc_get_predecessor_for_case(case_number, limit)
@app.get("/api/operations/agents/runs/{run_id}/log")
async def operations_agent_run_log(run_id: str):
"""Full output log (NDJSON stream) of one heartbeat run."""