OPER-61
NEEDS_RESCOPE panel in Ledger triage UI
Body
# OPER-61 — NEEDS_RESCOPE panel in Ledger triage UI Ship the human-facing surface for the `NEEDS_RESCOPE` state that OPER-60 introduces. Without this UI, rejected tasks pile up invisibly and the admission gate becomes a silent bottleneck. ## Scope Add a `NEEDS_RESCOPE` panel to the Ledger triage view at `apps/web/src/app/studio/[team]/triage/`. Panel shows: 1. **Queue depth** at the top — the metric OPER-58 will eventually arm `pipeline_throughput_below_target` against. 2. **List of NEEDS_RESCOPE tasks** — one row per task, sorted by `updatedAt` desc. 3. **Per-row: rejection reasons badge** — pulls from the most recent `PlanningRejection` row for that task, displays each reason as a color-coded chip. Fixed vocabulary (from OPER-60): `missing_size` = amber, `missing_writesets` = amber, `writesets_unresolved` = blue, `missing_verify_cmd` = amber, `missing_module` = amber, `body_too_short` = red, `missing_acceptance_criteria` = red, `phi_no_reviewer` = purple. 4. **PHI flag prominence** — any row where `phiInScope = true` displays a `PHI` badge on the left rail, visible without scroll (Devi non-negotiable). PHI badge is not conditional on rejection reasons — it's always visible when the flag is true. 5. **Per-row action buttons**: "Patch fields" (opens edit modal), "Send back to READY_FOR_PLANNING" (only enabled once all rejection reasons are addressed), "Cancel" (opens confirm dialog with reason free-text). ## Non-goals - Auto-CANCEL after N weeks — explicitly rejected by Justin 2026-07-29. Cancel action requires human click every time. - Bulk operations across multiple NEEDS_RESCOPE rows — v0.2 concern, not shipping in v0.1. - Concept card UI — separate work (2B in the memo). - Risk-tier display — descoped from v0.1 (DOC memo 2026-07-29). ## Acceptance Criteria - [ ] New panel visible at `/studio/operant/triage` with heading "NEEDS_RESCOPE queue" and current depth count. - [ ] Task rows render with title, identifier, `updatedAt`, rejection-reason chips. - [ ] Reason chips accurately reflect the most-recent `PlanningRejection.reasons` array for each task using the fixed vocabulary from OPER-60. - [ ] PHI badge renders on any row with `phiInScope = true`, always visible on the left rail without scroll. - [ ] "Patch fields" opens the standard task edit modal with focus on the first missing field. - [ ] "Send back to READY_FOR_PLANNING" transitions status via PATCH and shows a toast; disabled if any rejection reason still applies (validated client-side against current task fields). - [ ] "Cancel" opens confirm dialog; on confirm transitions to `CANCELED` with an audit note. - [ ] No auto-transition, no bulk actions, no scheduled cleanup — every state change requires an explicit human click. - [ ] Panel data query is a single SQL statement — no JSONB unpacking (matches Priya's non-negotiable in OPER-60). - [ ] Playwright test covers the "patch → send back" happy path end-to-end. - [ ] Storybook stories for empty queue, single-item queue, 20-item queue, mixed-reason queue, PHI-flagged row. ## Verification Run `pnpm test apps/web/src/app/studio` — all green. Run `pnpm playwright test triage-needs-rescope` — happy path passes. Visit `/studio/operant/triage` in preview deploy, verify panel renders and depth count matches `SELECT COUNT(*) FROM "Task" WHERE status = 'NEEDS_RESCOPE'`. ## Dependencies - **Blocks on OPER-60** — the `NEEDS_RESCOPE` enum value and `PlanningRejection` table must exist before this UI can render. ## Reasoning references - Ratification memo: `docs/pdt/2026-07-28-admission-gate-v0.1.md` (PR #171) - DOC descope memo: `docs/doc/2026-07-29-admission-gate-risk-classifier.md` - State machine: `docs/task-state-machine.md` - Related: OPER-60 (backend implementation)
Attachments
Loading attachments…
Comments
Loading comments…