courtmitra / CLAUDE.md
hetanshwaghela's picture
Day 1–2: monorepo scaffold + ingestion→intake→evidence loop
170b9b6
|
Raw
History Blame Contribute Delete
8.33 kB

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)

  1. Hexagonal. packages/domain imports NO framework/SDK (openai, @nestjs/*, playwright, qdrant, supabase, google/meta clients). It depends only on packages/ports interfaces. Adapters implement ports; apps/api wires them.
  2. Everything external is an Action. Workflows NEVER call Gmail/WhatsApp/Telegram/Meta/Playwright directly. They create/execute an Action. The ActionExecutor is the only place side-effects happen, and it checks — in order — consent, idempotency key, adapter capability, rate limit, then sets proof_state.
  3. No fake submissions. proof_state must 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 than proof_state supports. Indian gov portals have no citizen write API → packet + supervised browser + user-confirmed receipt only.
  4. 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.
  5. 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.
  6. 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.
  7. Idempotent writes + webhooks. Every write endpoint accepts Idempotency-Key; every provider webhook is deduped by provider event ID in webhook_events before processing.
  8. 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
Email 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 any in 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 from mission_status_snapshots (don't recompute).
  • Money/dates in evidence: preserve original text + extracted value; never lose original-language proof.
  • Timezone: Asia/Kolkata for 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.