Spaces:
Sleeping
CourtMitra MissionOS
Citizen-side grievance/legal-action autopilot for India. A user describes a problem once (WhatsApp / Telegram / browser); the system turns it into a mission, builds the evidence file, grounds it in Indian law/procedure, picks an official route, drafts + sends approved actions, follows up, and records the outcome.
Prime directive
Complete the entire loop, automatically and honestly. Intake → evidence → facts → cited route → consented action → real send → public case page → follow-up → reply → resolution → ledger. The reliability spine and safety gates exist to make that automated loop trustworthy — never polish a subsystem while the loop is broken. A demo that closes one real loop beats ten half-built modules.
Deep specs live in (read on demand, do not load wholesale):
courtmitra_missionos_full_idea.md— product, UX, issue adapters.courtmitra_missionos_architecture_plan_v0_2_third_audit.md— full architecture, data model (§9, §30), endpoints (§10, §30.15), state machine (§30.6).- Phase build specs (
PHASE_1_*.md,PHASE_2_*.md) — scope fence; build Phase 1 only until told otherwise.
Non-negotiable invariants (these prevent regressions)
- Hexagonal.
packages/domainimports NO framework/SDK (openai,@nestjs/*,playwright, qdrant, supabase, google/meta clients). It depends only onpackages/portsinterfaces. Adapters implement ports;apps/apiwires them. - Everything external is an Action. Workflows NEVER call Gmail/WhatsApp/Telegram/Meta/Playwright directly. They create/execute an
Action. TheActionExecutoris the only place side-effects happen, and it checks — in order — consent, idempotency key, adapter capability, rate limit, then setsproof_state. - No fake submissions.
proof_statemust reflect reality (draft_only,ready_for_user_submission,sent_by_email,posted_to_social,user_confirmed_external_submission,receipt_verified,failed). The UI must never imply more thanproof_statesupports. Indian gov portals have no citizen write API → packet + supervised browser + user-confirmed receipt only. - No legal claim without a cited source. Generated legal/route text must carry
cited_chunk_ids+ quote spans that literally exist in the source (exact substring check, not the model's self-report). No Tier-1/2 source → neutral admin language only, never presented as law. - No public output without redaction + consent. Run Presidio redaction before any share/publish. Consent is gated by a canonical
action_preview_hash; if a regenerated payload's hash ≠ the approved hash, block and re-request approval. - Contracts-first. All LLM/API I/O is Zod schemas in
packages/contracts(single source of truth). API routes and the frontend import these schemas — never redefine DTOs. OpenAPI is generated, not hand-written. - Idempotent writes + webhooks. Every write endpoint accepts
Idempotency-Key; every provider webhook is deduped by provider event ID inwebhook_eventsbefore processing. - Every schema change is a Drizzle migration. No ad-hoc DB edits. Seed route rules + curated citations.
Locked tech stack — use these, not the alternatives
| Layer | Use | Do NOT use |
|---|---|---|
| Monorepo | pnpm + Turborepo | — |
| Web | Next.js (App Router) | — |
| API | NestJS + Fastify | (don't mix in Express) |
| DB / ORM | Postgres + Drizzle (Neon or local Docker; Supabase only with keep-alive) | raw SQL clients |
| AI layer | Vercel AI SDK 6 (ToolLoopAgent, tool-approval, structured outputs) behind LlmPort; Mastra optional |
OpenAI Agents SDK (TS support lags — Python-first) |
| RAG/search | pgvector + Postgres FTS + curated citations | Qdrant (Phase 2 upgrade) |
| Evidence extraction | vision-LLM on screenshots/PDF images | Docling/Tesseract (Phase 2) |
| Workflows | Inngest (durable sleeps + event fns). Payload ≤256KB → pass refs, not blobs | — |
| Resend (DKIM/SPF/DMARC) + reply token | raw SMTP; Gmail restricted scopes (CASA cost) | |
| Channels | WhatsApp Cloud API + Telegram Bot API + browser, all behind ChannelPort |
single-channel coupling |
| Auth | ONE of Supabase Auth / Better Auth + Google OAuth; channel identity first, browser merge via magic-link | SMS OTP |
| Redaction | Microsoft Presidio + custom Aadhaar/PAN/UPI/IFSC recognizers | regex-only |
| Storage / Obs | R2 or Supabase Storage / OpenTelemetry + Langfuse | — |
Repo structure
apps/{web, api, worker}
packages/{domain, ports, adapters, db, contracts, prompts, ui}
domain = entities/use-cases/policies (pure). ports = interfaces only. adapters = openai/whatsapp/telegram/resend/storage/meta. contracts = Zod + OpenAPI. prompts = versioned prompts + evals (no inline prompts in controllers).
Commands (scaffolding must expose these; keep them green)
pnpm dev # web + api + worker
pnpm build # turbo build all
pnpm typecheck # tsc --noEmit across packages
pnpm lint # eslint incl. dependency-boundary rules
pnpm test # vitest (unit + integration via Testcontainers)
pnpm db:migrate # drizzle migrations
pnpm db:seed # route rules + curated citations
pnpm test:contracts # zod/openapi contract tests — MUST pass before UI work
Run pnpm typecheck && pnpm lint && pnpm test:contracts before considering any task done.
Conventions
- TypeScript strict; no
anyin domain/contracts. Validate every LLM output against its Zod schema; on failure, retry/repair, never pass through. - Errors: typed Result/exception at adapter edge; domain throws domain errors. Log with the trace ID that links message → mission → workflow → LLM call → action.
- Naming follows the data model in architecture §9/§30 (snake_case tables, the documented state/event enums). Don't invent parallel names.
- Append to
mission_events; read UI state frommission_status_snapshots(don't recompute). - Money/dates in evidence: preserve original text + extracted value; never lose original-language proof.
- Timezone:
Asia/Kolkatafor all deadlines.
Safety & compliance (hard gates)
- Approval-first: no send/post/share without a recorded consent grant whose hash matches the outgoing payload.
- Public case pages are private-link only in Phase 1 (no live social, no indexing) — contains defamation/intermediary risk. Never label an entity "fraud/scam/criminal"; use "user reports / unresolved / alleged".
- Stop-and-refer (emergency, criminal, domestic violence, child safety, active fraud) →
human_review_items, halt automation, surface helpline guidance. - "Legal information & workflow assistance, not a lawyer-client relationship" disclaimer on legal outputs. Never guarantee outcomes.
- DPDP: deliver consent notice at first contact; support data export + erasure; cross-user aggregation (swarm, Phase 2) needs its own consent basis.
Model & delegation policy
Default to the cheapest model that will not regress the task. Reserve expensive reasoning for where it matters.
- Haiku (or the read-only Explore agent): file discovery, grep/lookups, mechanical transforms, dependency tracing, log scanning.
- Sonnet: implementation — CRUD endpoints, adapters, UI components, tests, migrations, boilerplate from a clear spec.
- Opus (main/advisor): architecture, data-model & schema design, the Action/consent/proof spine, RAG/legal-grounding logic, safety policies, ambiguous tradeoffs, and reviewing the above before merge.
How to delegate: spawn subagents with explicit model: frontmatter (haiku/sonnet), or pass model to the Task tool. Keep menial, well-specified work off the main reasoning model. Escalate to Opus only when a task touches an invariant above or the spec is ambiguous. Always run an Opus/advisor review pass on anything touching consent, proof_state, redaction, or legal grounding.
Scope fence
Build Phase 1 only. Do NOT start: complaint swarm, live social publishing, company resolver portal, Qdrant/rerank RAG upgrade, ASR/voice, Indic translation services, supervised Playwright portal automation, eCourts/CNR, or the AI-run public account. These are Phase 2 — see PHASE_2_*.md.