OPER-178
/qa/live-fixes canvas + /qa/triage-log page in Operant Studio
Band
MEDIUM
Suggested
Justin Cooke
Body
feature_id: FEAT-studio-qa ## Context PDT memo v5 ([REDACTED-DOB]) approved two Studio UI surfaces to make the AI-triage auto-dispatch loop observable and manually overridable without becoming a required gate: 1. `/qa/live-fixes` — real-time canvas of in-flight auto-dispatched fixes. Each row shows Task id, fix_class, tier, dispatch time, current PR status, and a Cancel button. Not a gate — nobody has to watch. Anyone who chooses to can click Cancel on a specific row, which flips the ticket to AWAITING_HUMAN and writes an AiTriageLog kind=CANCEL row. 2. `/qa/triage-log` — filterable retrospective view of the AiTriageLog table (created in OPER-177). Filters by fix_class, tier, kind, actor, date range. This is the picture Justin or any team member checks when they want to see what auto-dispatch has been doing, review demoted classes, or investigate a specific incident. Replaces the Slack-channel notification originally proposed and rejected. ## Acceptance Criteria - New page in `apps/web/src/app/qa/live-fixes/page.tsx` — server component reads Task rows where dispatch_mode=AUTO AND status IN (IN_PROGRESS, IN_REVIEW). Client component polls every 15s. Row columns: identifier, fix_class, tier (badge colored per tier), dispatched_at (relative time), current status, Cancel button. - Cancel button calls existing endpoint from OPER-177: POST /api/studio/qa/live-fixes/:taskId/cancel. Optimistic UI update, error toast on failure. Only visible to members with team writer role (existing RBAC helper). - New page in `apps/web/src/app/qa/triage-log/page.tsx` — filterable table over AiTriageLog. Server-side pagination (50 rows/page). Filters as URL params so views are shareable. Columns: created_at, kind (badge), fix_class, tier, task_id (link to ticket), test_run_id (link to run), actor, payload_json (collapsible detail row). - Empty states for both pages: /qa/live-fixes shows 'No auto-dispatched fixes in flight' with link to /qa/triage-log for history. /qa/triage-log shows 'No triage events match your filters' with clear-filters button. - No new backend queries — both pages read through existing Studio DB access patterns with getOrgScopedDb + Postgres RLS per multi-tenant-rls.md rules. - Accessibility: keyboard navigable, screen reader labels on all badges and interactive elements. Cancel button has aria-label including the ticket identifier. - Component tests for both pages covering: renders in empty state, renders with mock data, Cancel button gated to writer role, filter URL params round-trip correctly. ## Risk classification Sandbox (Risk 3 / Reach 4). Internal-only UI, no PHI, no writes except the Cancel button (which delegates to OPER-177's audited endpoint). Happy-path tests + component tests sufficient per Build Risk Matrix. ## Depends on - OPER-177 (AI triage writer) — creates the AiTriageClassPolicy + AiTriageLog tables + Cancel endpoint this UI reads from and calls. ## Blocks - No downstream tickets. ## Splitting note If the PR grows past the 800-line size budget (per pr-size-budget.md), split into two tickets: one for /qa/live-fixes canvas, one for /qa/triage-log page. Both are independent and shippable separately once OPER-177 lands.
Attachments
Loading attachments…
Comments
Loading comments…