Validate first. Five AI judges when you're ready. Zero sugarcoating.
A founder workbench for stress-testing startup ideas. Capture a structured Pitch (Idea Validation Worksheet), log proof work on Case, and start a Review only when a readiness gate says the pitch is specific enough to critique (not the same as evidence-ready). Five judges — VC, engineer, product manager, customer, and competitor — debate, then a moderator delivers a structured GO / ITERATE / NO-GO call with a proof step and recommended experiment first. Numeric scores stay in the API for evaluation and sit behind Advanced model output in the web UI. Verdicts hand off into Case as concrete next steps. Disagree? Appeal with evidence and make them reconsider.
| Ideas | Per-idea workspaces at /workspaces: lifecycle, linked reviews, and next action |
| Pitch | Guided worksheet (audience, problem, solution, pricing, risks) or paste-to-draft AI |
| Case | Proof ledger: assumptions, evidence, experiments, interviews, belief updates, staged checklist |
| Readiness gate | Deterministic pre-review checks; optional override with an AI readiness briefing |
| Review panel | Five parallel verdicts: concern → fix → proof ask first (critique last; wire key may remain roast) |
| Debate | Default one dissent pass (configurable 1–5) with token streaming and every judge on the record |
| Re-vote | Post-debate re-score; UI shows argument changed/unchanged, not score theater |
| Synthesis | Structured GO / ITERATE / NO-GO with highest priority, proof asks, and recommended experiment first |
| Handoff | Selected review outputs become Case work: assumptions, evidence targets, experiments |
| Belief updates | Cited belief changes (strengthened / weakened / reframed) grounded in evidence or experiments |
| Review eligibility | Deterministic “why review now” signals after new evidence, completed experiments, or pitch changes |
| Appeal | Per-judge evidence coaching with experiment context; outcomes include Ask matched when artifacts overlap proof asks, otherwise judge changed/unchanged |
| Iteration | Pitch versions plus linked runs (parent_run_id); concern diffs vs prior versions (scores demoted) |
| Memory | Past ideas inform future reviews (recency by default; optional semantic when ENABLE_SEMANTIC_MEMORY=true) |
| Web app | Next.js workbench: Landing → Ideas → Case / Pitch / Reviews → live SSE Run |
| Web research | Optional Tavily lookup with cited sources in the run view (API + Streamlit) |
| Run metrics | Per-phase latency (roast, debate, re-vote), token usage, and estimated cost (advanced view) |
Core loop: Draft Pitch → Case (one next validation step) → log assumptions / evidence / experiments → pass readiness → Reviews → decision + proof step + experiment → handoff into Case → run the experiment / log proof → revise Pitch → re-run → see concern changes vs prior version.
Authoritative unfinished work lives on Case. Run and Reviews route there; they do not host a second weekly experiment workbench. Founder-facing copy prefers review over roast; schema / SSE wire keys may still say roast.
Requirements: Python 3.11+ · Ollama (local) or DeepSeek API (cloud)
git clone https://github.com/notsubash/Gavel.git
cd Gavel
python -m venv .venv
# Windows: .venv\Scripts\activate | macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt
ollama pull qwen3.5:9b # default chat model; override in .env
ollama pull nomic-embed-text # only if ENABLE_SEMANTIC_MEMORY=true
cp .env.example .env # optional: DeepSeek, Tavily, LangSmith, semantic memoryThe web/ frontend is the primary product UI. Landing lives at /. Create an idea at /workspaces/new (guided Pitch wizard or paste notes for AI draft), then work Case → Pitch → Reviews inside the workspace. Log evidence and experiments on Case, pass the readiness gate, start a review, watch judges debate, read the decision with proof step first, hand off into Case, and optionally appeal with experiment context. Browse ideas at /workspaces (/history redirects there).
Requirements: Node.js 20+ · API on port 8000
# Terminal 1 — API (use the venv python so optional LLM deps resolve)
python -m uvicorn api.app:app --app-dir src --reload --port 8000
# Terminal 2 — frontend
cd web
npm install
cp .env.example .env.local
npm run devOpen http://localhost:3000. See web/README.md for OpenAPI type generation and frontend scripts.
streamlit run src/app.pyMaintainer reference only: paste a pitch and hit Roast It! It has no Case / Pitch workbench. Use the Next.js app for the founder product. Streamlit also hosts the experimental DeepAgents flow; the web app and streaming API use the deterministic pipeline only.
The FastAPI backend powers the Next.js app and any custom frontend:
python -m uvicorn api.app:app --app-dir src --reload --port 8000Endpoints:
Runs (review pipeline)
| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Liveness check |
POST |
/api/runs |
Create a run (workspace_id required; parent_run_id optional), returns run_id immediately |
GET |
/api/runs |
Paginated run history (limit, offset) |
GET |
/api/runs/{run_id} |
Poll run status |
GET |
/api/runs/{run_id}/similar |
Similar past reviews (semantic or recency) |
GET |
/api/runs/{run_id}/events |
SSE stream of roast/debate events |
GET |
/api/runs/{run_id}/handoff |
Post-review Case tasks (assumptions, evidence targets, experiments) |
POST |
/api/runs/{run_id}/cancel |
Cooperatively stop a run (emits run_cancelled) |
POST |
/api/runs/{run_id}/appeal |
Founder appeal (one per run; optional target_judges); returns revised panel |
Workspaces (Case workbench; prefix /api/workspaces)
| Method | Path | Purpose |
|---|---|---|
POST |
/api/workspaces |
Create workspace + initial Pitch version |
GET |
/api/workspaces |
List ideas |
GET |
/api/workspaces/{id} |
Workspace detail + current Pitch |
GET |
/api/workspaces/{id}/overview |
Case progress, confidence, next action |
GET |
/api/workspaces/{id}/readiness |
Pre-review readiness checks |
GET |
/api/workspaces/{id}/checklist |
Staged validation checklist |
GET |
/api/workspaces/{id}/review-eligibility |
Deterministic “why review now” signals |
GET/PUT |
/api/workspaces/{id}/founder-constraints |
Opt-in prefs (effort/method); never auto-applied to Case |
POST |
/api/workspaces/{id}/versions |
Save a new Pitch version |
GET |
/api/workspaces/{id}/runs |
Reviews linked to this idea |
| CRUD | /api/workspaces/{id}/assumptions |
Track testable assumptions |
| CRUD | /api/workspaces/{id}/evidence |
Log interviews, metrics, LOIs, research |
| CRUD | /api/workspaces/{id}/experiments |
Plan and record validation experiments |
| CRUD | /api/workspaces/{id}/interviews |
Customer discovery notes |
| CRUD | /api/workspaces/{id}/belief-updates |
Cited belief changes grounded in proof |
POST |
/api/workspaces/{id}/assist/* |
AI assists: draft, clarify, coach, falsification plan, weekly review, competitor scan, and more |
GET |
/api/workspaces/{id}/export/markdown |
Export workspace as Markdown |
GET |
/api/workspaces/{id}/export/judge-brief |
Export a judge-ready pitch brief |
Create a run with workspace_id (and optional parent_run_id / readiness_override), then open an EventSource (or equivalent) on /api/runs/{run_id}/events. The pitch text is compiled from the workspace worksheet. When web research is enabled, the stream may emit research_findings before roast events. The stream then emits ordered pipeline envelopes: roast and debate phases, optional revote_started / revote_judge_completed events, debate_completed (includes structured_synthesis and initial vs revised verdicts when re-vote ran), run_metrics (roast/debate/re-vote latency, token counts, estimated cost), then run_completed, run_cancelled, or run_failed. After completion, handoff items are available via GET /api/runs/{run_id}/handoff. After a successful appeal, an appeal_completed event is appended to the log (appeal itself is a REST call, not streamed).
The run engine is decoupled from the HTTP connection: RunManager drives the pipeline once into a durable SQLite event log (data/runs.db). Multiple tabs can watch the same run; disconnect and reconnect with the SSE Last-Event-ID header to resume without gaps. Heartbeat comment frames keep idle connections alive (SSE_HEARTBEAT_SECONDS, default 15s).
Set ROAST_CORS_ORIGINS in .env for your frontend origin (comma-separated). Default includes http://localhost:3000 and http://127.0.0.1:3000 (plus :3001 variants in .env.example).
Run uvicorn with a single worker per machine; background tasks and in-process subscribers are not coordinated across workers yet. Compose publishes the API without auth on purpose (local/self-host); put a reverse-proxy auth layer in front if you expose it beyond your LAN.
Rate limits: POST /api/runs and POST /api/runs/{run_id}/appeal are token-bucket limited per client IP (RATE_LIMIT_* and RATE_LIMIT_APPEAL_* in .env). Returns 429 when exceeded. Disable with RATE_LIMIT_ENABLED=false. Set TRUST_PROXY=true only when the API sits behind a reverse proxy that sets X-Forwarded-For (Fly, Render, nginx). Otherwise clients could spoof that header to bypass limits.
Run budget: MAX_RUN_SECONDS (default 600) fails long runs cleanly between roast/debate boundaries and debate turns. In-flight judge LLM calls during roast may still finish after cancel/budget. Set 0 to disable.
Cancel: POST /api/runs/{run_id}/cancel is cooperative and asynchronous for running runs — the HTTP response may still show status: "running". Poll GET /api/runs/{run_id} or watch SSE for the terminal run_cancelled event. Cancelling a created run (before SSE connect) is immediate.
cp .env.example .env # set DEEPSEEK_API_KEY and/or point LOCAL_MODEL at host Ollama
# Keep E2E_TEST_MODE unset/false — stub reviews must never ship as “real”
docker compose up --build- API: http://localhost:8000/health →
{"status":"ok"} - Web: http://localhost:3000
Compose binds 127.0.0.1 only — the API has no auth. Do not republish 0.0.0.0:8000 without a reverse-proxy auth layer.
SQLite files (runs.db, workspaces.db, ideas.db) persist in the gavel-data volume under /data. API only: docker compose up --build api.
For local Ollama from inside the container, point LOCAL_MODEL at host.docker.internal (compose sets extra_hosts for Linux). Or run the API on the host and skip Docker. Behind nginx or a PaaS load balancer, set TRUST_PROXY=true in .env.
| Phase | What happens |
|---|---|
| Pitch | Structured idea capture: audience, problem, workaround, solution, pricing, competitors, top risky assumption |
| Case | Track assumptions, evidence, experiments, interviews, and cited belief updates; staged checklist and confidence |
| Readiness | Deterministic gate before reviews (specificity, human evidence, worksheet completeness); optional override |
| Review panel | Five judges (VC, Engineer, PM, Customer, Competitor) evaluate in parallel |
| Debate | LangGraph runs configurable multi-round debate with fixed turn order and live token streaming |
| Re-vote | Each judge re-scores against the full debate transcript (optional; ENABLE_REVOTE) |
| Synthesis | Moderator returns structured GO / ITERATE / NO-GO with strengths, risks, and biggest disagreement |
| Handoff | Verdict fields become Case tasks: assumptions to test, evidence targets, experiment suggestions |
| Appeal (optional) | Per-judge evidence coaching → founder rebuttal (optional judge targeting) → revised panel |
| Iteration (optional) | New Pitch versions and linked reviews; compare concerns and fixes vs prior versions |
| Memory | Prior ideas summarized into future judge prompts (SQLite; optional semantic retrieval) |
| Web research | Optional Tavily search with cited sources when judges need factual context |
| Metrics | Wall-clock per phase (including re-vote), token counts, and estimated API cost (run_metrics event) |
Each judge returns structured output prioritized as: key concern, recommended fix, evidence that would change their verdict, then a short critique. The UI renders a decision card, judge cards with proof bars, re-vote argument changes, debate transcript, version comparison, Case handoff, and Markdown export.
| Ideas | Case |
|---|---|
![]() |
![]() |
| Case validation | Pitch |
|---|---|
![]() |
![]() |
| Reviews | Review complete |
|---|---|
![]() |
![]() |
| Ideas list | Observability |
|---|---|
![]() |
![]() |
Built with LangGraph, LangChain, Ollama, and the DeepAgents SDK. Two execution paths exist; only one is production-ready.
Pitch (Idea Validation Worksheet)
→ Case loop: assumptions, evidence, experiments, interviews, belief updates
→ Readiness gate (+ optional review-eligibility signals)
→ Phase 1: parallel structured judge calls (review panel)
→ Phase 2: LangGraph debate graph
→ Phase 2b: post-debate re-vote (optional)
→ Moderator structured synthesis
→ Handoff → Case tasks (founder-confirmed)
→ Optional appeal re-evaluation (against post-revote panel when present)
→ Pitch revision → next version
→ Persist compact idea memory (with optional parent/version lineage)
Deterministic pipeline (src/pipeline.py): Direct model calls plus LangGraph guarantee all five judges speak, debate rounds advance predictably, and Pydantic validates every boundary. Debate streams token deltas (DebateTokenDelta) for live UI updates; re-vote streams RevoteJudgeCompleted with score deltas. At completion the pipeline emits RunMetrics (roast/debate/re-vote seconds, tokens, estimated cost) before PipelineCompleted.
Decision-ready verdict (src/judges/synthesis.py, extended Verdict schema): Judges return recommended_fix and evidence_to_change_verdict. The moderator returns a structured Synthesis (GO / ITERATE / NO-GO, confidence, top strengths/risks, biggest disagreement) with prose fallback. assess_verdict_output_quality flags degraded local-model output in the UI.
Post-debate re-vote (src/debate/revote.py): After debate, each judge revises their verdict against the full transcript. Guardrails cap score movement (MAX_REVOTE_SCORE_DELTA); assess_revote_quality detects herding and unexplained deltas. Appeal re-evaluates against the post-revote panel when present (appeal_baseline_panel).
Pitch iteration (src/memory/lineage.py, src/validation/versioning.py): Workspaces carry versioned worksheets (WorksheetVersion with parent_version_id). Reviews link to a workspace and worksheet version. Parent-linked runs can show a compact “Since last review” summary; full comparison stays available.
Case handoff (src/validation/ingest.py): After a run completes, judge fixes, proof asks, and synthesis problems become RunHandoffItem records. Founder confirmation writes them into Case; Run’s primary CTA is Continue on Case.
Case workbench (src/validation/): Deterministic readiness, confidence, checklist, staged progress, belief updates (cited only), review eligibility, AI provenance stamps on founder-confirmed assist writeback, and stage-aware assist context. CRUD for assumptions, evidence, experiments, interviews, and belief updates in data/workspaces.db. LLM assists for Pitch draft/clarify, validation coach, falsification plan, readiness briefing, weekly review, competitor scan, interview questions, and experiment suggestions.
Appeal coaching (src/appeal/coaching.py, mirrored in web/src/lib/appeal/coaching.ts): Surfaces per-judge evidence asks above the appeal form. API accepts optional target_judges; response includes per-judge evidence outcomes.
Run engine (src/api/run_manager.py): Background task per run, durable event log in SQLite, subscriber-based SSE with reconnect support. Structured run_metrics JSON is logged once per API run (with run_id). API runs require a workspace_id, compile pitch text from the worksheet, persist to idea memory under a stable local user id, and support appeal, run history, similar-review lookup, and Case handoff ingest.
Web frontend (web/): Next.js App Router workbench with Landing, Ideas list, Case shell, Pitch wizard/editor, Reviews launch with readiness gate, live SSE Run view, structured synthesis cards, handoff into Case, appeal coaching, related reviews, and Settings. Brand visual world: Precision Workbench (see PRODUCT.md / DESIGN.md).
Verification (src/verification/): Shared invariants and quality checks (score/verdict alignment, degenerate panels/fixes, re-vote quality) used by guardrails, eval scorers, and UI degradation hints.
DeepAgents orchestrator (src/orchestrator/deep_agent.py): Agent harness that dispatches subagents via task() with stronger tool-calling models. Streamlit-only; not exposed via the streaming API.
- Case is the ledger of truth: reviews diagnose; Case records learning. Unfinished proof work does not live on Run.
- Orchestration over autonomy: the debate is a workflow, not a free-form agent task. LangGraph owns state and routing.
- Structured output at boundaries: verdict and synthesis schemas in
src/judges/schemas.pyandsrc/judges/synthesis.pyare the contract between phases, charts, memory, and exports. Post-validation guardrails insrc/judges/guardrails.pyand shared checks insrc/verification/reject score/verdict mismatches, degenerate panels, and weak re-vote movement. - Untrusted user input: startup idea, memory, research, and appeal text are wrapped in tagged blocks with delimiter escaping (
src/idea_context.py); prompts treat that content as data, not instructions. - Compact memory: SQLite stores full records, but prompts receive only short summaries (scores, concerns, synthesis). Full transcripts are never injected into judge prompts; local models drift under long context. Optional semantic retrieval (
sqlite-vector) surfaces similar past ideas instead of only the most recent. - Appeal as a third phase: re-evaluates judges against founder evidence (post-revote baseline when re-vote ran). Does not rerun the multi-round debate. Coaching surfaces what evidence each judge needs before the founder writes.
- Proof before grades: completed reviews lead with highest priority, proof bar, and recommended experiment; scores sit under Advanced model output.
- Cited belief only: belief updates must cite evidence, experiment, worksheet version, or run (
src/validation/belief.py).
Copy .env.example to .env. Key variables:
LOCAL_MODEL=ollama:qwen3.5:9b
DEEPSEEK_MODEL=deepseek-v4-pro
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_API_KEY=your_deepseek_api_key
MAX_DEBATE_ROUNDS=1
ENABLE_WEB_SEARCH=false
WEB_SEARCH_MAX_RESULTS=3
TAVILY_API_KEY=your_tavily_api_key
ROAST_CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
SSE_HEARTBEAT_SECONDS=15
STALE_RUN_MINUTES=30
RUNS_DB_PATH=data/runs.db
WORKSPACES_DB_PATH=data/workspaces.db
IDEAS_DB_PATH=data/ideas.db
RATE_LIMIT_ENABLED=true
RATE_LIMIT_REQUESTS=30
RATE_LIMIT_BURST=10
RATE_LIMIT_WINDOW_SECONDS=60
RATE_LIMIT_APPEAL_REQUESTS=5
RATE_LIMIT_APPEAL_BURST=2
RATE_LIMIT_APPEAL_WINDOW_SECONDS=60
LIST_RUNS_DEFAULT_LIMIT=20
LIST_RUNS_MAX_LIMIT=100
ENABLE_SEMANTIC_MEMORY=false
EMBEDDING_MODEL=ollama:nomic-embed-text
EMBEDDING_DIMENSION=768
ENABLE_REVOTE=true
MAX_REVOTE_SCORE_DELTA=3
MAX_RUN_SECONDS=600| Runtime | When to use |
|---|---|
local |
Default. Ollama via LOCAL_MODEL. |
deepseek |
Cloud API via DEEPSEEK_API_KEY and langchain_deepseek. |
Pick a model with solid instruction-following and structured output. If verdict validation fails, try a stronger instruct or tool-calling model.
Web research: optional Tavily search, gated by a model policy prompt (not keyword matching).
Semantic memory: set ENABLE_SEMANTIC_MEMORY=true and pull the embedding model (ollama pull nomic-embed-text by default). When enabled, similar past ideas are retrieved via sqlite-vector; otherwise memory falls back to recency.
Re-vote: set ENABLE_REVOTE=false to skip post-debate re-scoring (rollback to pre-revote behavior). MAX_REVOTE_SCORE_DELTA caps how far each judge can move their score in one re-vote (default 3).
Debate rounds: default is one dissent pass (MAX_DEBATE_ROUNDS=1). Raise only when you want longer multi-round argument (still capped in the UI/settings).
Tracing is opt-in. Set credentials in .env:
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=your_langsmith_api_key
LANGSMITH_PROJECT=gavelLegacy LANGCHAIN_TRACING_V2, LANGCHAIN_API_KEY, and LANGCHAIN_PROJECT are also supported.
Traces cover roast panel calls, LangGraph debate, re-vote, appeal flows, and experimental DeepAgents runs. Metadata includes execution flow, app version, and a privacy-safe idea_fingerprint (SHA-256 hash + 80-char preview). Full startup text is never sent.
Filter by tags such as phase:roast, phase:debate, phase:revote, phase:appeal, or flow:deterministic.
Run metrics (in-app): the deterministic Streamlit path and API SSE stream surface per-run cost and latency without opening LangSmith — roast, debate, and re-vote wall-clock, token totals, and a static DeepSeek/local cost estimate from src/observability/metrics.py. Token counts use provider metadata when available, otherwise a chars÷4 fallback. Assist funnel events are also logged for Case AI assists (src/observability/assist_events.py).
- Open http://localhost:3000 — Landing. Start free goes to
/workspaces/new. - Create an idea via the Pitch wizard: fill guided fields step-by-step, or paste rough notes and use Draft from notes AI. Sharpen individual fields with Clarify.
- On Case, follow the primary next proof step: plan interviews, add evidence, start or continue an experiment, or update assumptions / beliefs.
- Edit the pitch under Pitch; each save creates a new version with a diff summary.
- When readiness passes (and optionally when review eligibility signals “why now”), open Reviews, check the readiness briefing, and Start review. Advanced settings (model runtime, debate rounds, web research) live under Settings.
- Watch the live run at
/run/{runId}: review panel, debate transcript, re-vote argument changes, structured synthesis, and sources when research ran. - After completion, Continue on Case for the next proof step. Pull additional handoff items into Case from Reviews when needed. Use Appeal with experiment context when you have results, or Revise pitch and re-run.
- Re-run with
parent_run_idlinked to the prior completed review; concern diffs show what moved.
- Enter a startup idea (optionally expand Optional details for target customer, pricing, traction, and competitors).
- Choose execution flow: Deterministic (production) or DeepAgents (experimental).
- Choose model runtime: local or deepseek.
- Optionally enable Web research (Tavily).
- Review verdicts (including recommended fixes), radar chart, debate transcript, re-vote deltas, structured synthesis card, and the run metrics footer on deterministic runs.
- Use Refine this idea to iterate on a pitch and see version-to-version score and concern deltas.
- Use Appeal Mode with the per-judge evidence checklist (LOIs, pilots, buyer persona, not persuasion alone).
- Download the Markdown transcript if needed (includes run metrics when available).
Stored at data/ideas.db. Streamlit uses a stable local user id (data/local_user_id via src/memory/identity.py); API runs use the same id so memory and similar-review lookup work across both UIs. Retrieval (src/memory/retrieval.py) prefers semantically similar past ideas when ENABLE_SEMANTIC_MEMORY=true; otherwise it uses the most recent entries. Context builder (src/memory/context.py) injects compact summaries (idea text, average score, top concerns, previous synthesis, appeal outcome). Full transcripts are never injected. The web app surfaces similar past reviews on the run page via GET /api/runs/{run_id}/similar. Founder constraints can quarantine memory ids without mutating Case rows.
Founder appeal is sent to all five judges with the original idea, their baseline verdict (post-revote panel when re-vote ran), moderator synthesis, optional memory context, and appeal text. Optional target_judges labels which evidence asks the founder is answering; every judge still re-scores. Appeal coaching surfaces each judge's evidence ask before submission. Each judge returns a fresh validated Verdict; the UI shows whether targeted evidence moved the argument.
Workspaces version the Idea Validation Worksheet (POST /api/workspaces/{id}/versions). Reviews link to a workspace and worksheet version via workspace_id and worksheet_version_id. Optional parent_run_id chains refined reviews within a workspace. The UI compares concerns and recommended-fix status against prior versions and derives the next Case or review action from staged progress.
Migrating legacy runs: if you have pre-workspace runs in data/runs.db, run python scripts/migrate_runs_to_workspaces.py to group them into workspaces (use --dry-run first).
src/
app.py Streamlit entry point (direct-submit reference UI)
api/ FastAPI streaming API (RunManager, WorkspaceStore, durable SSE log)
pipeline.py Frontend-agnostic production pipeline
config.py Model and app settings
events.py Frontend-agnostic pipeline event types
idea_context.py Untrusted user-input wrapping for prompts
judges/ Schemas, guardrails, synthesis, single-judge service, panel
debate/ LangGraph graph, nodes, router, revote, state
memory/ SQLite store, semantic retrieval, lineage, prompt context
appeal/ Re-evaluation, synthesis, coaching hints
validation/ Case workbench: readiness, checklist, belief, eligibility, provenance, assists, handoff
verification/ Shared invariants and panel/re-vote quality checks
research/ Tavily web search (model-gated policy)
orchestrator/deep_agent.py Experimental DeepAgents path (Streamlit only)
observability/ LangSmith bootstrap; run metrics; assist funnel events
ui/streamlit_runner.py Streamlit pipeline adapter + metrics footer
utils/ Parser fallback, radar chart, transcript export
web/ Next.js workbench (see web/README.md)
scripts/ One-off utilities (e.g. migrate_runs_to_workspaces.py)
docs/ Loop contract, product docs, design system, specs
tests/ Unit tests (unittest, fake models, no Ollama required)
evals/ Regression evals and monthly audit (see evals/README.md)
pip install -r requirements-dev.txt
pre-commit install # Ruff on every commit
python -m unittest discover -s tests
python -m compileall src
ruff check src tests evals
ruff format src tests evalsWeb frontend (web/): npm run lint, npm run test:unit (reducer, coaching, synthesis, copy/UX lints, Case helpers, and more), npm run test:e2e:core, and npm run build (see web/README.md). Regenerate API types with npm run gen:types when backend schemas change.
CI (.github/workflows/ci.yml) runs on push/PR to main: Ruff lint and format, pinned deps, version resolution check, unit tests on Python 3.11-3.13, compile check.
Evals: see evals/README.md.
| Tier | When | Command |
|---|---|---|
| 0 (CI) | Every PR | python -m unittest discover -s tests |
| 1 (Local) | Before prompt/model changes | python -m evals.run_eval --runtime local --full |
| 2 (DeepSeek audit) | Monthly (1st) or manual | python -m evals.run_audit --no-reuse-last-local --baseline-only |
Tier 1 checks structural reliability ($0, Ollama). Tier 2 uses one DeepSeek LLM-as-judge call per idea (~$0.50-2/month on committed baselines).
Version lives in pyproject.toml ([project].version); runtime reads it via src/version.py. Product positioning and surface ownership live in PRODUCT.md and docs/loop-contract.md.
Honest boundaries, not bugs. Current design:
- Case-first Next.js workbench + FastAPI deterministic review pipeline
- Local Ollama and/or DeepSeek; optional Tavily research
- Single-box SQLite persistence (workspaces, runs, ideas)
-
Accounts / multi-user auth (local identity only)
-
Multi-worker API coordination
-
Streamlit as product UI (reference/dev only)
-
Cloud multi-tenant hosting defaults (Compose binds 127.0.0.1)
-
Case-first web app: Next.js is the primary UI (Landing, Ideas, Case, Pitch, Reviews, Run, Settings). Streamlit remains a direct-submit reference UI without Case support.
-
/historyredirects to/workspaces(Ideas list); there is no separate history surface. -
Memory identity is local-only, not account-based. A stable id in
data/local_user_idis shared by Streamlit and the API. -
Semantic retrieval and similar-review lookup are optional and local-only (
ENABLE_SEMANTIC_MEMORY=true). -
Readiness gate blocks reviews until the Pitch is specific enough; founders can override with
readiness_overrideafter reviewing checks. -
Appeal re-evaluates judges against the post-revote baseline when re-vote ran; it does not run a second multi-round debate. API runs allow one appeal per run.
-
Re-vote quality depends on model instruction-following; weak local models may produce herded or unexplained score moves (the UI surfaces degradation hints).
-
Pitch iteration is explicit (revise Pitch + re-run), not auto-detected via semantic similarity.
-
Belief updates require a citation; they are not free-form “I feel better about this” notes.
-
Founder constraints personalize assist suggestions but are never auto-applied into Case rows.
-
SQLite storage is local-only (
data/workspaces.dbfor Case,data/ideas.dbfor memory,data/runs.dbfor API runs). -
Streamlit supports the experimental DeepAgents flow; the web app and streaming API use the deterministic pipeline only.
-
API runs need a single uvicorn worker per machine; multi-worker coordination is not implemented.
-
DeepAgents is experimental, not the production orchestrator.
data/workspaces.db
data/ideas.db
data/runs.db
data/local_user_id
transcripts/*.md
roast_radar.png
Runtime outputs. Keep out of commits unless you intentionally want samples.








