coreci 702d3aae71 chore(milestone): clear checkpoint — v0.2-mvp complete
---ci---
phase: 5
milestone: v0.2
status: complete
message: >-
  Milestone v0.2-mvp COMPLETE and APPROVED. Checkpoint cleared per
  the run workflow: the next /ci-run starts milestone v0.3 at
  phase 0 (pre-execution: specify, clarify, research, plan,
  grill, mvp/ux check), which config.json now points at (tag line
  v0.3.x). v0.3 scope is pending owner direction: live-bound
  library/settings/suggestions/refine surfaces (G-009 ratified
  scope), backend hosting for the LXC deployment, and the remaining
  6 methodologies from the locked catalog.
requirements:
  covered: [REQ-01, REQ-02, REQ-03, REQ-04, REQ-05, REQ-06, REQ-07, REQ-08, REQ-09, REQ-10, REQ-11, REQ-12, REQ-13, REQ-14, REQ-15, REQ-16, REQ-17, REQ-18, REQ-19, REQ-20, REQ-21, REQ-22, REQ-23, REQ-24, REQ-25, REQ-26, REQ-31, REQ-32, REQ-33, REQ-34]
  partial: []
---/ci---

Milestone branch will be deleted (local + remote); tags
v0.2.0-v0.2.5 and the main merge (b11b202) preserve the full
history. v0.3 unblocked.
2026-09-29 15:28:52 +00:00

ResearchX

A deep-research studio where you bring your own model, storage, and memory; choose a research methodology before a single query fires; and every claim in the final report is anchored to a visited, verified, quotable source.

Status: MVP shipped (v0.2.5, owner-approved 2026-09-27) — the full research engine (FastAPI + asyncio state machine + adapter layer + attack-proven trust loop) behind the v0.1 frontend. Live mode covers the core research loop (G-002/G-009): the engine runs locally per the quickstart; library/settings/suggestions/refine stay mock-backed until v0.3+.

Quickstart

# frontend (prototype, mock-backed — works today)
cd frontend
corepack pnpm install
corepack pnpm dev          # http://localhost:3000

# backend (MVP — uv manages Python 3.12 and the venv)
cd backend
uv sync                    # installs deps + editable researchx package
uv run uvicorn researchx.api.app:app --reload --port 8000
uv run pytest              # full suite, zero API keys

Three clicks from cold start to initiated research.

Monorepo command map

Layer Install Dev Gates
backend (uv, Python 3.12) uv sync uv run uvicorn researchx.api.app:app --reload --port 8000 uv run ruff check src tests · uv run mypy src · uv run pytest
frontend (pnpm 12.6) corepack pnpm install corepack pnpm dev corepack pnpm typecheck · corepack pnpm lint · corepack pnpm test · corepack pnpm build

Engine architecture (v0.2 P2)

The research engine is a hand-rolled asyncio state machine:

PLANNING → AWAITING_APPROVAL → SEARCHING → EXTRACTING → REFLECTING ─┐
                (halt until             ↑ depth loop (dials.depth)  │
                 approved)              └────────────────────────────┘
→ SYNTHESIZING → VERIFYING → DONE  (+ CANCELLED / FAILED terminals)
  • Durable state: runs/<id>/state.json rewritten atomically after every transition; resume re-enters at the recorded cursor with the persisted plan
  • Event bus: typed events (run_started, query_fired, source_visited, passage_extracted, state_changed, run_done, run_error) — trace per run
  • Visited-only constraint: the writer's context is the evidence store and nothing else
  • Trust loop: SSRF-guarded liveness (live/stale/dead), quote anchoring (normalize + fuzzy ≥ 0.85, weak matches flagged), citation ledger JSON, exportable verification checklist, single-source vs corroborated confidence labels

Run artifacts per run: state.json, report.md, ledger.json, checklist.md.

Try it on fakes (no keys): uv run python -m researchx.engine.demo

Adversarial guarantees (v0.2 P4)

Every trust-loop claim is attacked by the adversarial suite (backend/tests/test_adversarial.py) — these are tests that try to fool the verifier, and their passing proves the defenses:

Attack Defense (proven)
Writer hallucinates a citation to a passage that was never stored Unknown passage IDs count as unanchored claims in the ledger; the export gate fails the report
Fabricated quote (matches nothing) Anchoring verdict: no match, flagged — never silently accepted
Near-miss quote (0.80–0.85 similarity) Flagged weak_match in the ledger — surfaced, not accepted
Liveness probe redirected to a private/metadata IP Per-hop redirect re-guarding classifies it dead (SSRF refusal)
Redirect chain ending at a gone page (410) Classified dead
Oversized page (5MB) response 2MB read cap — classifies without unbounded memory
Pause during the depth loop Durable state persists; resume completes the run over the HTTP API
Cancel mid-loop Terminal CANCELLED state persisted, never swallowed

REQ-23 (≥99% citation liveness) is a per-run export gate enforced by the verification checklist, plus an opt-in keyed live tier (cd backend && uv run pytest -m live) — the zero-key CI suite never asserts it vacuously.

The E2E happy path (≤3 clicks: ask, choose, approve) is validated against the real FastAPI + engine stack, defaults only — not the mock (frontend/src/lib/api/e2e-real-stack.test.ts).

Adapter configuration (v0.2)

All keys resolve from env files only (.env, .env.secrets, .env.* — never the shell environment, never git):

Variable Scope Used by
OLLAMA_API_KEY model (cloud) Ollama cloud endpoint https://ollama.com/v1; absent/keyless falls back to http://localhost:11434/v1 automatically
OLLAMA_BASE_URL model Overrides the default cloud base URL
TAVILY_API_KEY search Tavily default search; absent falls back to the keyless DuckDuckGo adapter (degraded mode — surfaced in the run trace)

The test suite needs no keys: fake model/search adapters (REQ-31) drive every engine test.

Live mode (v0.2 P3)

The frontend runs mock-backed by default (works standalone, zero keys). To run the core research loop against the real backend:

# terminal 1 — backend (fake adapters by default; real Ollama/Tavily adapters
# are used by the engine in v0.2.5+ wiring — the served API currently ships
# fake-adapter runs for demos and tests; see Adapter configuration below)
cd backend && uv run uvicorn researchx.api.app:app --reload --port 8000

# terminal 2 — frontend in live mode
cd frontend && NEXT_PUBLIC_RESEARCHX_API_MODE=live corepack pnpm dev

Live mode covers the core loop (Ask → Choose → approve plan → live trace → report + ledger); the library, settings persistence, suggestions, refine, and graph surfaces stay mock-backed until v0.3. The API surface: POST /api/runs, GET /api/methodologies, run lifecycle (approve/pause/cancel/resume), GET /api/runs/{id}/events (SSE), GET /api/config, report + ledger artifacts.

What's in the prototype

Screen What it does
/ask One question box + one optional context box — plus two opt-in helpers below and beside them: open-question suggestions (follow-ups from your past runs, one click fills the box) and the Refine question dialogue (a few clarifying answers → a composed, sharper question). Neither ever auto-starts.
/choose All 8 locked methodology cards — mock ETA, cost estimate, why-recommended, and the 12 methodology dials behind each card's Advanced drawer.
/run/[id] Plan & Run: approve the research plan (sub-questions, source universe, outline), watch the live trace stream, pause/resume or cancel.
/run/[id]/report Reading Room: the report with page-anchored citations — hover or focus any [n] marker for the exact quoted passage — plus the citation ledger and Markdown/JSON exports.
/library Stored reports filed into auto-categorized folders (sortable, links into the Reading Room), the Connections panel (shared sources ⇄, related topics →), plus v2-preview project graph and task inbox.
/settings API-key status (masked, never raw), the reports storage directory, methodology defaults with the resolved 12 dials, appearance, and about/version.

The persistent shell (every screen): sidebar nav + adapter connection-status dots, top bar with the ⌘K navigation palette (screens + stored reports) and the avatar menu (local profile, Settings, About).

All data flows through a typed ApiClient interface backed by MockApiClient — the same components will talk to the FastAPI backend via the OpenAPI-generated client in the MVP milestone, with zero rewrites.

Scripts

Run inside frontend/:

Command Purpose
pnpm dev Dev server on :3000
pnpm build Production build
pnpm lint ESLint (flat config)
pnpm typecheck tsc --noEmit (strict)
pnpm test Vitest + Testing Library (jsdom)

Repository layout

frontend/   Next.js 15 App Router, TypeScript strict, Tailwind v4, Vitest
.ciagent/   Pipeline state (roadmap, requirements, plans, checkpoints)

Milestone v0.2 (MVP: FastAPI backend, research engine, adapter layer, trust loop) begins only after this prototype is approved.

S
Description
ResearchX — deep-research studio: BYO model/storage/memory, methodology-first, visited-only verified citations
Readme 2.2 MiB
2026-09-30 14:23:14 +00:00
Languages
TypeScript 58.4%
Python 38%
Shell 2.2%
CSS 1.1%
Dockerfile 0.2%
Other 0.1%