[feat-005] Multi-pass research orchestrator + UI integration
Trigger: chat.ts auto-routes to the orchestrator when the user has any
research source selected (sources.legal non-empty OR sources.web=true).
Five-pass pipeline with budget enforcement (≤25 Olava calls, ≤45s wall),
designed fresh for Olava-001 (Qwen3.6 + LoRA) per the SLM-cost-advantage
strategy. work___'s services/{orchestrator,sub_agent,loop_controller}.py
served as architectural reference, not a port.
Backend (new)
- backend/src/lib/research/types.ts - shared event/result types
- backend/src/lib/research/budget.ts - call counter + wall-clock cap
- backend/src/lib/research/queryExpander.ts - pass 1: 1 Olava call → 3-6 specialised queries
- backend/src/lib/research/searchFanOut.ts - pass 2: parallel legal/web searches, dedupe by URL
- backend/src/lib/research/triage.ts - pass 3: 1 Olava call → top-N most relevant
- backend/src/lib/research/extractor.ts - pass 4: N parallel Olava calls → tailored extracts
- backend/src/lib/research/synthesizer.ts - pass 5: streaming Olava call → markdown answer
- backend/src/lib/research/orchestrator.ts - pipeline coordinator + SSE event emission
Backend (modified)
- routes/chat.ts: auto-detect research mode and route to runResearchOrchestrator
- lib/llm/olava.ts: forward delta.reasoning(_content) via onReasoningDelta
so the UI shows a live "Thinking..." indicator during long Olava think-times
(rather than dead air). Persisted as part of chat_messages - same scope as
the response itself.
Frontend (new)
- src/components/chat/onit-status-icon.tsx - Drift Grid 3×3 ripple loader
(ported from work___ UI System UPGRADE/loaders.jsx) cross-fades to the
Onit O logo (#00112c) when streaming stops. Replaces MikeIcon in the
assistant ResponseStatus.
- globals.css: gridPulse keyframe.
Frontend (modified)
- AssistantMessage.tsx
- ResearchStepBlock: dot + label + meta detail (e.g. "top 5 selected"),
rendered inline inside the existing PreResponseWrapper alongside other
tool chatter. Wrapper auto-collapses to "Completed in N steps" once
synthesis content arrives.
- ReferenceBlock: numbered (1. 2. 3.) and indented under "Ranked results",
with a continuous parent-x vertical line drawing through them so they
visually nest under the parent step. No per-reference dots or in-between
connectors. Click opens URL in new tab.
- bug-003 obsoleted: reference_added events now flow through the wrapper
again (single-pass mode no longer fires search tools - that's all
research-mode now where synthesis is reliably non-empty).
- Empty/whitespace-only content events no longer split wrappers (Olava
sometimes emits "\n\n" between reasoning blocks; without this guard the
UI breaks into two separate "Completed in N steps" cards).
- shared/types.ts: AssistantEvent extended with research_step + sources.web.
- hooks/useAssistantChat.ts: research_step SSE handler dedupes by key in
the events array (so reload doesn't show running+done duplicates of the
same step). Transient research.* events are kept out of persistence;
research_step drives the UI.
Process
- backlog.md: full feat-005 design + feat-006 (citation reliability via
add_citation tool - defer per testing notes 2026-05-04) appended.
Smoke-tested end-to-end against real Olava + Brave + CourtListener with
"What is the latest court case where a lawyer had misused AI in court?":
~30s wall, 16 events, 2KB synthesis with inline [Title](URL) citations to
the April 2026 Sullivan & Cromwell case (vs single-pass Olava emitting
just "\n\n" with the same prompt).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Repository | nwhitehouse/mike |
|---|---|
| Author | Nick Whitehouse <nick.whitehouse@mccarthyfinch.com> |
| Authored | |
| Parents | 3785d7f2 |
| Stats | 16 files changed , +1332 , -81 |
| Part of | Multi-pass research orchestrator (feat-005) |
Capture this commit into my fork
Download a Markdown prompt that tells Claude how to port this
exact commit into your working tree. Run it via
claude -p < capture-commit-a4adcbf3.md
from inside the repo you want the change in.