Add backlog audit and task update command

- agents/prompts/backlog_audit.md: QA analyst prompt for checking
  which pending tasks are already implemented in the codebase
- agents/runner.py: run_audit() — project-level agent that reads
  all pending tasks, inspects code, returns classification
- cli/main.py: kin audit <project_id> — runs audit, offers to mark
  done tasks; kin task update <id> --status --priority
- web/api.py: POST /api/projects/{id}/audit (runs audit inline),
  POST /api/projects/{id}/audit/apply (batch mark as done)
- Frontend: "Audit backlog" button on ProjectView with results
  modal showing already_done/still_pending/unclear categories

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gros Frumos 2026-03-15 17:44:16 +02:00
parent e755a19633
commit 96509dcafc
9 changed files with 548 additions and 2 deletions

View file

@ -385,6 +385,47 @@ def list_tickets(project: str | None = None, status: str | None = None):
return tickets
# ---------------------------------------------------------------------------
# Audit
# ---------------------------------------------------------------------------
@app.post("/api/projects/{project_id}/audit")
def audit_project(project_id: str):
"""Run backlog audit — check which pending tasks are already done."""
from agents.runner import run_audit
conn = get_conn()
p = models.get_project(conn, project_id)
if not p:
conn.close()
raise HTTPException(404, f"Project '{project_id}' not found")
result = run_audit(conn, project_id, noninteractive=True)
conn.close()
return result
class AuditApply(BaseModel):
task_ids: list[str]
@app.post("/api/projects/{project_id}/audit/apply")
def audit_apply(project_id: str, body: AuditApply):
"""Mark tasks as done after audit confirmation."""
conn = get_conn()
p = models.get_project(conn, project_id)
if not p:
conn.close()
raise HTTPException(404, f"Project '{project_id}' not found")
updated = []
for tid in body.task_ids:
t = models.get_task(conn, tid)
if t and t["project_id"] == project_id:
models.update_task(conn, tid, status="done")
updated.append(tid)
conn.close()
return {"updated": updated, "count": len(updated)}
# ---------------------------------------------------------------------------
# Bootstrap
# ---------------------------------------------------------------------------