ubiquitous-invention/plans/Plan-daily-driver-finish/Epic-shipping-the-shell/Task-wire-ai-chat-to-trpc.md
Randall Stillwell 778fe1d321 plans: scaffold daily-driver-finish, saas-hardening, agent-coordination
Three new plan trees that fill in the gaps surfaced during repo review.
Together they map out what remains between the current scaffold-with-stubs
state and a daily-usable, multitenant, agent-coordinated app.

* Plan-daily-driver-finish (P0): turn stubs into real data. Five tasks
  covering the lint/shared-types breakage, hardcoded dashboard mocks,
  AI-page setTimeout placeholder, post-signin landing decision, and a
  cross-browser collab smoke test against the deployed Hocuspocus
  instance.

* Plan-multitenant-saas-hardening (P1): everything multitenant needs
  beyond what Plan-multitenant-cursor-sync already covers. Invites and
  role management, soft-delete + append-only audit log, rate limits on
  the auth + mutation hot paths, and a Vitest + GitHub Actions test
  foundation so PRs can't ship red.

* Plan-agent-coordination (P2): the layer that makes a Task-*.md
  runnable, not just readable. Adds workflow_prompt with task -> epic
  -> plan inheritance, an agent_runs table for auditable sessions, and
  two new MCP tools (claim_task / complete_task) that replace the
  freeform update_object composition agents do today. Includes an
  intentionally-deferred Epic-optional-orchestrator that captures the
  Symphony-shaped runner as a decision point rather than an immediate
  build.

Each task is bead-scale (one focused Cursor session) with explicit
in-scope, out-of-scope, and anti-goal sections so a future agent can
pick up a single Task-*.md and start without scrollback context.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 23:52:22 -05:00

3.6 KiB

kind slug title plan_slug epic_slug status priority tenant_id owner cursor_todo_id updated_at
task wire-ai-chat-to-trpc Replace AI chat setTimeout placeholder with a real provider call daily-driver-finish shipping-the-shell ready P0 global unassigned null 2026-06-01

Task summary

apps/web/app/(app)/[workspaceSlug]/ai/page.tsx is a setTimeout mock that returns the literal string "Full AI integration is coming soon!". Replace with a real call through apps/web/server/routers/ai.ts and packages/ai.

Description

The page already manages local chat state — message list, input ref, auto-scroll, loading state. All it's missing is the network call.

Approach

  1. Inspect routers/ai.ts to see what procedures exist. If there's already a chat / complete procedure, use it. Otherwise add one:

    • Input: { messages: Array<{ role: "user" | "assistant" | "system", content: string }>, workspaceSlug: string }
    • Output: streaming text (use the Vercel AI SDK's streamText from @tasks/ai).
    • Wrap with workspaceProcedure so workspace membership is checked.
  2. Use streaming, not request/response. The Vercel AI SDK's useChat hook is the natural fit, but it expects a /api/chat HTTP endpoint, not tRPC. Two options:

    • (a) Add a Next.js route handler at apps/web/app/api/chat/route.ts that calls into the same provider abstraction in packages/ai. Keep auth in the route handler (auth() from apps/web/lib/auth.ts). Use useChat() on the client.
    • (b) Stream through tRPC v11's subscription support. More work; only choose this if you specifically want a single API style.
    • Recommendation: (a). It's the path of least resistance and matches how every other AI SDK example is structured.
  3. Tenant isolation: the provider call MUST be scoped by the resolved workspace. Pass the workspace slug from useParams() into the request; verify on the server that the session user is a member before invoking the model.

  4. Provider selection comes from env (packages/ai already supports this — OpenAI, Anthropic, or Ollama on CT 108 via OPENAI_BASE_URL). Don't hardcode a provider in the route handler.

  5. Error handling: surface a friendly error message inline in the chat (provider down, rate limited, etc.) rather than crashing the page. Show "AI is unavailable" if no provider env is set.

  6. Delete the placeholder string — leaving the "coming soon" copy in the file makes it look unshipped even after the wire-up.

Out of scope

  • Tool-calling, retrieval, or letting the AI mutate workspace objects. That's Plan-agent-coordination work.
  • Conversation persistence (storing chats in DB). Keep messages in component state for now; persistence is a follow-up.

Subtasks

  • Audit apps/web/server/routers/ai.ts and packages/ai/src/ for existing primitives.
  • Add apps/web/app/api/chat/route.ts route handler with auth() check and workspace_id scoping.
  • Replace the setTimeout block in [workspaceSlug]/ai/page.tsx with useChat() from @ai-sdk/react.
  • Add inline error state and unavailable state.
  • Verify against at least one provider (whichever is configured in your .env).

Owner or assignee

Unassigned

Status

ready

Estimation

M

Acceptance criteria

  • No setTimeout mock remains in [workspaceSlug]/ai/page.tsx.
  • Sending a message produces a streamed response from a real provider.
  • Server route validates session and workspace membership before calling the provider.
  • Error and unavailable states render gracefully.
  • Epic: ./Epic-shipping-the-shell.md
  • Plan: ../Plan-daily-driver-finish.md