feat(health): טקסונומיית-בריאות לסוכן — zombie/stalled/working/idle (#222)
מוסיף web/agent_health.py — מסווג-טהור classify_issue_health (agent-agnostic, testable) שממפה כל issue פתוח+משויך-סוכן למצב-בריאות אחד, ו-get_agent_health ב-paperclip_client שגוזר את הפרימיטיבים מ-heartbeat_runs (run חי=finished_at null בחלון) + agent_wakeup_requests (total + recovery-markers בחלון). מרכיב על אירועי #219 (אותם reasons של recovery). - zombie = פתוח+משויך-סוכן, אין run חי, יש wakeup-recovery → הstranded-child שאובחן ידנית (reference_recovery_loop_stranded_child) עולה אוטומטית. - stalled = ננער חוזר בלי progress; working = run חי; idle = המתנה בנונית. - Port: pc_get_agent_health (read-only, לא עטוף-טלמטריה לפי הכלל); endpoint GET /api/operations/agents/health (worst-first, +counts). - 7 בדיקות pytest (מסווג-טהור + fetch fake-asyncpg). אומת חי read-only מול Paperclip DB: 6 issues→idle נכון, אפס zombie. Invariants: מקיים G12 (מסווג אגנוסטי; fetch מהמעטפת; המגע מהשער), G2 (מקור-בריאות יחיד). UI ב-/operations = follow-up מגודר-שער-עיצוב (feedback_claude_design_gate). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
13
web/app.py
13
web/app.py
@@ -62,6 +62,7 @@ from web.agent_platform_port import (
|
||||
pc_create_project,
|
||||
pc_create_workflow_issue,
|
||||
pc_escalate_issue,
|
||||
pc_get_agent_health,
|
||||
pc_get_agents,
|
||||
pc_get_agents_for_case,
|
||||
pc_get_case_issues,
|
||||
@@ -7531,6 +7532,18 @@ async def operations_agents():
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/operations/agents/health")
|
||||
async def operations_agent_health():
|
||||
"""Per-issue agent health taxonomy (#222): zombie / stalled / working / idle.
|
||||
|
||||
Read-only. Surfaces the stranded-child / recovery-loop cases (``zombie``)
|
||||
automatically — the ``gt feed --problems`` idea grounded in our failure
|
||||
modes — so they no longer need hand-querying the Paperclip DB. Consumed by
|
||||
the /operations dashboard (UI is design-gated, follow-up).
|
||||
"""
|
||||
return await pc_get_agent_health()
|
||||
|
||||
|
||||
@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."""
|
||||
|
||||
Reference in New Issue
Block a user