Task Routing panel, read-only
Epic 12251, child C3c. Needs C3a's `routing_decisions` table.
## Original requirement (verbatim, epic ask 4 part)
"Auto dispatches on it inside org policy, every decision visible and overridable on the task."
Ask 1: "Routing decision record: `routing_decisions`, one per dispatch — candidates with features and scores, the chosen configuration, mode, the human's final pick when it differed, a plain-language reason."
## Settled decisions
A10: the Recommend surfaces are the task form and a "Routing" panel on the task detail page showing what dispatch will use for this task. Quality floor (PRD §7): reasons are full sentences a non-specialist understands, no raw slugs or enum names; candidates show display names; ui-style-guide (list → tabbed detail) + ui-copy-standards; phone width without page-level horizontal scroll.
## Approach (Architect §4.5)
- `GET /api/tasks/{id}/routing` in new `apps/api/app/routes/routing.py`: the live pending/locked row plus the final history, read-only, org-scoped with the same access as the task.
- `apps/web/src/components/routing/RoutingPanel` as a tab on task detail (`TaskDetailTabs.tsx:326`) for EVERY task and mode: mode and why (plan feature / org max / project mode in words), the full reason sentence, candidates with display names and tier labels (eligible/excluded with excluded reason in words, score or "Insufficient data"), router pick vs default, actual dispatch, Recommend response, history per attempt. Reasons wrap and are never truncated. Empty state when no decision yet. (C4 adds the action buttons; C7 adds "Review lanes used".)
Credentials & reach:
- Dev UI (AC1 panel): `me/jaah/debug/main/operator-login` and `org/console/dev-login` — verified.
- API/vitest tests: the worktree only — verified.
Out of scope: changing account quota semantics or spillover; training a model from scratch; routing analysis personas before coder tasks have data; public marketplace billing; any ledger metric definition (owned by the outcome ledger epic). No writes from this route; no accept/override actions (C4); no scoreboard (C5).
Done means:
- AC1 Shadow row on every dispatch. → Verify: on dev, dispatch any task in a project with mode off. Open the task page's Routing panel and observe the decision with mode `shadow`, the candidates, chosen = actual, and a readable reason sentence.
- API test: route returns live row + history, 404 to a user without access to the task.
- Component test: renders display names (no config_key, provider slug or enum in visible text), long reason wraps without truncation; e2e or viewport check at 390px with no page-level horizontal scroll.
- Gates (AC16): `./dc check quick` green; changed-area suites green; merge lane `./dc check full` green.
Activity
- Draft
- Ready