Submatter/plans/Plan-automation-foundation/Epic-model-provider-registry/Epic-model-provider-registry.md
Randall Stillwell e256380671 plan(automation): add mission-control foundation backlog and model-routing ADR
Documents the automation foundation plan (nine epics, Epic 1 taskified) and
the accepted model-provider registry contract. Updates .env.example for backlog
import workspace id and local/cloud AI provider env guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 13:55:03 -05:00

88 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
kind: epic
slug: model-provider-registry
title: Model provider registry and per-role routing
plan_slug: automation-foundation
status: ready
priority: P1
tenant_id: global
cursor_epic_id: null
updated_at: "2026-07-03"
agent_prompt: |
Epic: model provider registry (docs/adr-model-routing.md). Server-only change —
no UI component library inventing; reuse components/ui/. Admin-only mutations.
Filter every DB query by workspace_id. One task per session; claim_task first.
---
# Epic objective
Deliver the workspace-scoped **model provider registry** and **role → alias routing** described in [docs/adr-model-routing.md](../../../docs/adr-model-routing.md): Drizzle schema, zod types in `packages/shared`, `resolveModel()`, tRPC CRUD + `testProvider`, Settings UI, and `agent_runs` model metadata on completion.
This epic is the first shipped piece of the automation-foundation plan and unblocks future orchestrator/worker work.
## In scope / out of scope
**In scope**
- Tables `model_providers`, `role_model_routes`.
- Pure resolver + unit tests.
- tRPC router (workspace admin).
- Settings pages: Providers, Role routing.
- Seed/default routes for nine L2 roles + `gate-copilot` + `chat-default`.
- `complete_task` optional model logging fields.
- `.env.example` env var documentation.
**Out of scope**
- Orchestrator dispatch (consumes resolver later).
- Worker inference loop.
- Parsing `model_policy` from `.convoys/*.md` files (orchestrator reads later).
- Billing/budget enforcement.
## Related tasks
| Task | Link |
|------|------|
| Shared schemas and resolveModel | `./Task-shared-schemas-resolve-model.md` |
| DB schema and migration | `./Task-db-model-providers-migration.md` |
| tRPC models router | `./Task-trpc-models-router.md` |
| Settings — providers UI | `./Task-settings-ai-providers-ui.md` |
| Settings — role routing UI | `./Task-settings-role-routing-ui.md` |
| agent_runs model fields + MCP | `./Task-agent-runs-model-logging.md` |
## Dependencies
- Depends on: existing auth + workspace admin patterns in `apps/web`.
- Blocks: orchestrator epic (needs `resolveModel`), worker epic (needs `ResolvedModel`).
## Acceptance criteria
- [ ] Admin can create `claude-planning` (anthropic) and `qwen-coder` (openai_compatible + base URL) in a workspace.
- [ ] Admin can map `role-implementer` → `qwen-coder`, `role-architect` → `claude-planning`.
- [ ] `testProvider` returns success/failure without exposing API keys.
- [ ] `resolveModel()` unit tests cover override order and missing-alias error.
- [ ] At least one task in this epic completed via `claim_task` → `complete_task` with model metadata.
## Proposed timeline
| Phase | Window | Notes |
|-------|--------|-------|
| Schema + resolver | Session 1–2 | Tasks: shared schemas, migration |
| API | Session 3 | tRPC router |
| UI | Session 4–5 | Both settings pages |
| Logging | Session 6 | agent_runs + MCP |
## Pipeline / convoy mapping
When running via agent-pipeline, architect briefs should align to tasks:
| Brief # | Task slug |
|---------|-----------|
| 1 | `shared-schemas-resolve-model` |
| 2 | `db-model-providers-migration` |
| 3 | `trpc-models-router` |
| 4 | `settings-ai-providers-ui` |
| 5 | `settings-role-routing-ui` |
| 6 | `agent-runs-model-logging` |
Briefs 1–2 serial (schema depends on types); 4–5 can fan out after brief 3 if `files:` are disjoint.