The deliberate scope, milestone plan, and trade-offs behind explAIn. The authoritative version lives in docs/roadmap.md and docs/architecture.md.

Roadmap

v0.1 — “Two humans, an advisor each, one Moderator”

Goal: validate the core advisor + mediator loop end-to-end, with one persona, one provider, on the web. In scope:

  • Email magic-link auth.
  • 1:1 conversations with an invite-link join flow.
  • Real-time send/receive via Supabase Realtime.
  • Per-user advisor (DeepSeek, streaming, accept/edit/discard UI).
  • Moderator persona only (annotation pills below each message).
  • The transparency “show your work” panel (original draft / advisor suggestion / sent text / mediator annotation).
  • Per-call llm_calls ledger (data only, no UI).
  • A soft daily token ceiling per user (dogfood guardrail).
  • Expo web build deployed to Vercel.

v0.2 — “Pick a persona”

Add the remaining four personas with their distinct behaviors (Arbiter, Judge, Chronicler, DM), the persona-switching propose/accept/reject UI, plus OpenAI and Google adapters and a per-conversation model picker.

v0.3 — “Native”

iOS and Android builds via EAS, push notifications (Expo Notifications + Supabase webhook), and mobile-specific UX polish.

v0.4 — “Hosted tier”

Stripe subscriptions, quota enforcement from llm_calls aggregates, a user-facing usage dashboard, and an invite-only beta gate.

v1 — “Public”

Open the BYO-key open-source variant (extract packages/llm into a public repo with a self-hosted setup guide), a marketing site, and public launch.

Out of scope (deliberately)

  • Group chats (more than 2 humans). The product hinges on a 1:1 mediation contract; the active-participant cap allows a small structured group, but mass group chat is not the goal.
  • Voice and video. Text first.
  • Message edit/delete in v0.1. A re-edit would force the mediator to re-run, and the right semantics are not yet obvious.
  • Model fine-tuning.

Notable trade-offs

  • Observers vs muted participants. explAIn chose a hard active / observer role split over “everyone active, some muted,” because the LLM-visibility boundary is the load-bearing asymmetry. An observer is never fed into the mediator’s context; a muted-but-active participant would be. See Product Vision.
  • mediator_action='external' for non-mediated rows. Structural and cross-chat-quote rows that bypass the mediator are tagged 'external' (or 'passthrough' for kind='system') so audit queries keep real mediator decisions distinct from structural insertions.
  • Cascade on cross-chat tags. cross_chat_tags rows cascade-delete with their parents; the durable record is the message ledger (the system notice and the external_quote row), so losing the ephemeral coordination row is acceptable for v0.1/v0.2.
  • Notification banner before web push. A pending_notifications table plus an in-app banner ships first; real push (v0.3) will INSERT the same rows for backgrounded clients, so banner and push share one data plane and the v0.2 window avoids service-worker / VAPID infrastructure.
  • Sentry + soft auth fallback. When useSession() is used outside its provider in production, it logs to Sentry and returns an unauthenticated sentinel (routing to login) rather than crashing; dev still throws.

Open questions parked for later

  • DM cadence: time-based vs message-count vs LLM-decides (different infrastructure each).
  • Judge rule format: free-text charter vs preset templates vs LLM-judged natural language; v0.2 starts free-text.
  • Advisor opt-out per conversation: affects advisor_suggestion nullability; currently nullable, revisit on usage data.
  • Message edit/delete semantics: does the mediator re-run? Default is “no edits” until dogfood demand appears.
  • Brand / wordmark: ship the stylized explAIn capitalization in product UI or only on the wordmark.