Repository navigation
Releases: fhdmrddev-dotcom/Agentic-RAG
Release list
v2.9 β Workflow Studio
Agentic RAG v2.9 β Workflow Studio
v2.9 turns the v2.8 harness engine into something a domain expert can actually use: describe a workflow in plain English, bind it to your project's knowledge base and skills, and run it to produce a real, cited, integrity-checked deliverable. This release adds project-scoped retrieval governance the model cannot widen, workflowβskill composition with locked version snapshots, ephemeral template upload with guaranteed-cited template-fill, a reusable validation-gate library topped by an LLM-judge output-quality hard wall, and a built Workflows page where natural-language authoring meets an 8-stage publish gauntlet β with project management shipped as the flagship demo, authored entirely on the generic primitives with zero hardcoded PM logic. The whole milestone is ~80-90% composition of shipped harness primitives, and Deep Mode stayed byte-identical across all nine phases.
Highlights
- Project = folder binding + server-side KB governance β a workflow binds to a project (a folder + its subtree); retrieval scope is resolved server-side from your RLS context at run start and bound to every retrieval call as a parameter the model cannot override or widen.
- Workflow β skill composition with locked snapshots β a phase can reference a project skill; its instructions and files compose into the phase framing, and the skill version is snapshotted into the published definition so a later edit or delete can never change a published run.
- Ephemeral template upload + guaranteed-cited template-fill + integrity gates β hand a workflow a
.docx/.pptx/.xlsxtemplate for one run; the model is forced to emit a cited field-map that a deterministic, no-model-code driver renders into a real deliverable, then re-opens to verify integrity β a corrupt file can never reach you as "done." - Reusable validation-gate library + LLM-judge output-quality hard wall β a closed registry of 9 validator kinds any phase can attach, plus an LLM-judge gate and a publish-time golden run that form a hard publish blocker: a lint-clean workflow that produces bad output cannot publish.
- Workflows page + natural-language authoring + read-only graph + 8-stage publish gauntlet β describe a workflow in natural language and get a valid, KB-grounded draft; view it as a read-only phase-spine graph; browse a project-filtered library; run it from a thread; publish it only by clearing an ordered server-side gauntlet ending in the judge wall.
- PM flagship content pack β charter, weekly-status-report, and risk-register templates plus two published workflow definitions and a synthetic project corpus, authored entirely on the generic primitives, with the headline single template-fill status-report demo green across a 7-model cross-provider sweep.
What's New in Detail
Project binding + server-side KB scope governance (098)
A workflow can now bind to a project via an additive-optional project_folder_id β old unbound workflows still validate and run with zero migration. A bound workflow defaults its retrieval to the project-folder subtree, with an optional per-phase folder_scope to narrow further; the scope comes from the binding, never from a prompt hint. At run start the scope is resolved server-side from the user's RLS context and bound to every retrieval call as a parameter the model cannot widen. Retrieved folder_ids are asserted to be a subset of scope (RLS as backstop), and any out-of-scope attempt is clipped and surfaced as an observable scope_violation run-log event. The subset assert is a None-gated no-op when scope is absent, so the shared search_documents path stays Deep byte-identical.
Workflow β skill composition (099)
An llm_agent or llm_single phase can reference a project skill via optional skill_ref. The skill's instructions and attached files compose directly into the phase framing, with read_skill_file auto-whitelisted for that phase. Critically, the skill version is snapshotted into the locked definition (migration 067 sibling column + CAS) at first kickoff, so a later edit or delete can't break a published workflow. Composition was proven across 6+ providers, and snapshot immutability was proven live.
Ephemeral template upload + template-fill + integrity (100 / 101 / 101.1)
A user can hand a workflow a .docx/.pptx/.xlsx template for exactly one run β workspace-only (kind=template_input), TTL + cron-swept, RLS-scoped, and never KB-ingested, embedded, or searchable (which also closes the upload-injection vector). The shared guaranteed-structured-emission llm_emit layer then forces the model to emit a cited field-map against a strict Pydantic schema β each field nullable and carrying its source chunk/page β which a pinned, deterministic, no-model-code driver renders into a real deliverable using docxtpl/python-docx inside the sandbox (a Jinja SandboxedEnvironment with autoescape for SSTI containment). Citation policy (strict/flag/partial/draft) and an integrity policy enforce that uncited values are marked or blanked, never silently filled, and the filled file is re-opened with the same library to assert integrity before delivery. Capability-tiered forcing at the gateway boundary plus native narrated-JSON recovery make this reliable across the native-7.
Reusable validation-gate library + output-quality judge hard-wall (102)
A closed validator registry of 9 gate kinds β json_schema, regex_match, workspace_file_exists, programmatic, citations_required, freshness, structure_check, output_file_valid, and llm_judge_rubric β lets any phase attach validation that rides the existing gate + bounded-retry loop (on_failure: fail_run / retry / skip_to_phase / ask_user). Every gate's pass/fail is driven by a schema-bound boolean, never a regex over prose, so a narrated verdict can't game the gate. A workflow declares exactly one business_requirement, and an llm_judge_rubric gate plus a publish-time golden run form a hard publish blocker (QUAL-01): a structurally-lint-clean workflow that produces bad output cannot publish. The judge works cross-provider and grades both prose and template-fill.
Workflows page + authoring API + NL authoring + publish gauntlet (103)
POST /workflows/generate turns a plain-English description into one model_validate-clean, KB-grounded WorkflowDefinition draft via a single forced emit over the strict schema β grounded on the project folder tree, the tool/skill registry, and any uploaded template placeholders, with one retry against the validation error then an honest structured failure (never a partial draft). A built Workflows page hosts a project-filtered library, a Builder with a read-only vertical phase-spine graph (view, not drag-to-build β a deliberate anti-feature for the domain-expert buyer) plus side-panel forms, and the publish gauntlet. Publishing runs an ordered server-side gauntlet β owner-check, already-published, definition validation, business_requirement present, structural lint, interactive-phase pre-run block, a real golden run on the project KB (no mocks), structural gate, the judge verdict (hard blocker), then the flip β returning a structured verdict with the blocking stage and named failures, and writing publish_attempted/blocked/succeeded receipts. Run forks a new chat thread and kicks off a real server-side run; Deep is the resting default. The whole path is ~90% reuse of the shipped forced_emit substrate plus the 092.5 gateway force_tool_name.
PM flagship content pack (104)
The project-management flagship β charter / weekly-status-report / risk-register templates, two published workflow definitions, register schemas, and a synthetic "Project Meridian" corpus β was authored entirely on the generic primitives, domain-author-driven with zero PM-hardcoded engine logic. The headline demo runs green live: a single template-fill status report drawn from the project KB, cited and integrity-checked, across a 7-model cross-provider sweep with honesty on all 7.
Requirements shipped
- PROJ-01 β workflow bound to a project folder via optional
project_folder_id; old unbound workflows still validate and run (zero-migration, additive). [098] - PROJ-02 β bound workflow defaults retrieval to its project-folder subtree; optional per-phase
folder_scopenarrows it; scope comes from the binding, not a prompt hint. [098] - GOV-01 β retrieval scope resolved server-side from the user's RLS context at run start, bound as a parameter the model cannot override; retrieved
folder_idsasserted subset of scope; out-of-scope attempts clipped + observable. [098] - WFSKILL-01 β
llm_agent/llm_singlephase references a skill via optionalskill_ref; skill version snapshotted into the locked definition; Deep-mode chat byte-identical. [099] - TMPL-01 β ephemeral template upload:
.docx/.pptx/.xlsxinto a thread for one run (workspace-only,kind=template_input, RLS-scoped), never ingested/embedded/searchable, expires via TTL + cron sweep. [100] - TMPL-02 β fill that exact template from project-KB content via a cited Pydantic field-map (each field nullable, carrying source chunk/page), rendered deterministically by pinned sandbox code. [101 / 101.1]
- TMPL-03 β filled template re-opened with the same library to assert integrity before delivery; a corrupt/unopenable file is caught and never delivered; SSTI contained via
SandboxedEnvironment. [101 / 101.1] - GATE-01 β reusable library of validator kinds (citations_required, freshness, structure_check, output_file_valid, llm_judge_rubric) any phase can attach, riding the existing gate + bounded-retry loop. [102]
- QUAL-01 β workflow declares exactly one
business_requirement; an LLM-judge output-quality gate + a publish-time golden run are a hard publish blocker β lint-clean-but-bad-output cannot publish. [102] - WFAUTH-01 β create/edit a workf...
v2.8 β Harness Engine & Workflow Mode
Agentic RAG v2.8 β Harness Engine & Workflow Mode
v2.8 gave the agent a deterministic, auditable workflow runtime: locked, ordered phases the LLM cannot escape, dispatcher-enforced per-phase tool whitelists, and validation gates between steps β plus a per-thread Deep β Harness dual-mode toggle and a live phase timeline in the workspace panel. It was built almost entirely by composing shipped v2.7 primitives (tool dispatcher, task/ask_user, run-backed Redis streaming) with zero new dependencies, and Deep Mode stayed the unchanged, byte-identical default throughout (the red line). This is the engine that v2.9 Workflow Studio is authored on top of.
Highlights
- Harness Engine β a hand-rolled, deterministic locked-workflow runtime with 5 phase types, validation gates, bounded retry, and step/wall-clock caps. ~80% composition of shipped substrate, zero new dependencies.
- Per-phase tool whitelist + tool budget β enforced at the single dispatch guard, a literal no-op when no workflow is active, so Deep Mode is byte-identical. Definitions are versioned + immutable-on-publish with an INSERT-only audit trail.
- Agent-loop + provider-gateway extraction β the agent loop was lifted out of the
threads.pygod file, then per-provider streaming was extracted into one sharedprovider_gateway/that both Deep and the harness consume β the structural fix that brought the harness to cross-provider parity. - Dual-mode wiring + cross-provider parity β a per-thread Deep/Harness toggle with a server-enforced workflow lock and a Continue affordance; the harness reached native-7 parity by consuming the gateway (live re-UAT 8/8).
- Legibility + run honesty β a live WCAG 2.1 AA phase timeline + RunCard in the panel; failed runs render as failed with a reason (no fake "done"); unified chat tool-cards; deterministic activity-derived panel fill; true reload timer; provider/model attribution.
- Eval gate + concurrency + resumability β a cross-provider eval harness wired as the CI regression gate (which caught a live security gap on its first run), restart-mid-workflow resumability verified at 3 kill points, bounded parallel fan-out, and an 8-provider model curation pass.
What's New in Detail
Harness Engine + phase types + gates (091)
harness_engine.run_workflow is a hand-rolled async transition loop that drives a published WorkflowDefinition through phase_index order, with a strict 2-phase write (mark-active β execute β atomic complete-with-output) and publish-time reachability lint. A PHASE_TYPE_REGISTRY dispatch seam is filled by 5 thin executors β programmatic, llm_single, llm_agent, llm_batch_agents, llm_human_input β that call the existing task_service / ask_user_service / tool_dispatcher, never re-implementing loops. Validation gates (4 kinds, closed registries) ride a bounded-retry loop (β€3, with consecutive-identical short-circuit) and on_failure routing (fail_run / retry / skip_to_phase), plus per-phase step and wall-clock caps.
Per-phase tool whitelist + immutable, audited definitions (091)
The per-phase tool whitelist + tool-count budget are enforced at the single dispatch_tool() guard and the get_tools() composition site β both literal no-ops when no workflow is active, so Deep Mode is byte-identical. Workflow definitions are versioned and immutable-on-publish (UNIQUE(slug, version) + a BEFORE-UPDATE trigger + FK ON DELETE RESTRICT), with FK-chain RLS and an INSERT-only harness_audit trail (migrations 056β062). A run-claim lease (CAS) means WORKER_COUNT=2 workers never double-execute a run.
Agent-loop + provider-gateway extraction (089 + 092.5)
The agent loop was lifted out of the threads.py god file into a clean agent_loop.py (proven byte-identical across the native-7), then its per-provider dispatch + chunk normalization was extracted into a shared provider_gateway/ package β canonical events, a dispatcher open_stream, three verbatim provider adapters, and one unified _on_chunk consumer β that Deep and the harness both consume. Surfacing calling_mode through this seam was the structural fix for the "harness only worked on OpenAI" bug. Deep was proven byte-identical in isolation: this is the red line.
Dual-mode wiring + native-7 parity (092 + 093)
A per-thread Deep/Harness toggle keyed on threads.active_workflow_run_id, a server-enforced workflow lock (HTTP 409 on an illegal switch, cleared in the terminal-status transaction), and the Continue affordance (resume past a step cap, consume-not-drop). The harness reached native-7 parity by consuming the gateway: a shared model-resolver (resolve, never mutate saved settings), a fixed ask_user round-trip, the three never-run phase types completed (split_topic β a real N-way llm_batch_agents fan-out), and provider-specific round-trips fixed for Google (thought_signature), Moonshot (reasoning_content), and GLM (max_steps). Live re-UAT: 8/8.
Legibility + run honesty (094 + 095 + 095.1)
A live, WCAG 2.1 AA phase timeline + a harness RunCard in the v2.7 workspace panel, demuxed into a dedicated phasesByThread store (zero chat re-renders). Failed and gate-failed runs render as failed with a reason β no done-sentinel lie. Chat tool-cards were unified into one frame (auto-scroll, details-on-demand, no duplicates, working downloads). And cross-provider run honesty: deterministic activity-derived panel fill (works even for providers that never call write_todos), 429-vs-billing classified at the gateway boundary on structured status codes, a true completed_at β started_at reload timer, model/provider attribution, and a deliverable-aware Resume gate.
Eval gate + concurrency + resumability (096)
scripts/eval_cross_provider.py was extended to drive multi-phase workflows per provider and wired as a CI regression gate β which caught and fixed a live phase_whitelist-not-propagated security gap on its very first run. Restart-mid-workflow resumability was verified live at 3 kill points (programmatic / llm_agent / ask_user) including graceful-shutdown; llm_batch_agents fan-out is bounded by max_parallel_agents composing with the global Redis-Lua cap; a StreamsProvider thread-keyed LRU-3 live-stream pool closed the thread-switch saturation hang; and an 8-provider, newest-first model curation pass landed.
By the numbers
- 10 phases (089β096, including the inserted provider-gateway refactor 092.5 and the inserted live-UAT phase 095.1) Β· 67 plans
- 9 days (2026-05-30 β 2026-06-07) Β· 498 commits (121
feat) - 578 files changed (+107,662 / β6,187 lines)
- Migrations 056β066 (additive β harness tables, dual-mode, audit trail, eval seed)
Architectural decisions locked
- D-v2.8-01 β v2.8 is Harness Engine + dual-mode only; the 6-type Plugin Contract and the operator/admin role tier defer to a later milestone (lock them on real harness telemetry).
- GATEWAY-01 β one shared provider gateway is the single home for all provider logic; the harness reaches parity by consuming it, never re-implementing. Deep byte-identical is the red line.
- PARITY-02 over PARITY-01 β the parity the milestone needed was the harness path, not Deep-mode Anthropic polish (Deep is already provider-robust on all 7).
- D-094-UNIFY β the workspace panel is the single live-execution surface for both Deep and Harness.
- D-095.1 β run honesty is projection/classification over data that already exists (no migration, no new SSE event); provider-specific handling stays at the gateway boundary, never the shared path.
Quality & verification
Milestone audit (tech_debt): 24/25 requirements satisfied + 1 partial (CONC-01 β SEED-065-B), 10/10 phases verified & closed, 6/6 E2E flows. Every streaming / agent-loop / provider-routing / UI-state phase carried the SC#10 4-axis cross-provider UAT (cross-provider Γ multi-tool Γ parallel-thread Γ long-message). Full audit: milestones/v2.8-MILESTONE-AUDIT.md.
Deferred / known at close
43 items acknowledged (operator-approved accept-as-tech-debt). Headline: CONC-01 partial β SEED-065-B (cross-tab GET p95 β 2,958 ms, ~2.9Γ better; residual ~3 s from a synchronous stream-create). Plus dormant forward seeds (SEED-002/003/004/005/040β046), pre-GSD micro-tickets, and the carried-forward Plugin Contract, llm_judge, and visual builder β all of which became v2.9 Workflow Studio.
Upgrade & migration notes
- No breaking changes to Deep Mode β it stayed byte-identical; the harness is additive (new tables, new optional fields, no-op guards when no workflow is active).
- New migrations 056β066 apply additively (new harness tables + audit trail + dual-mode columns + eval seed).
- This release introduced no new runtime and no new dependencies β it composes the shipped agent loop, tool dispatcher, and run-backed streaming.
Full changelog
See CHANGELOG.md for the complete history, and .planning/MILESTONES.md / milestones/v2.8-ROADMAP.md for the full close-out record.
v2.7 β Agent Workspace & Panel
Agent Workspace & Panel β the agent now keeps a persistent per-thread workspace of versioned files, manages a todo list, spawns sub-agents, and can pause to ask the user a question, all surfaced live in a collapsible right-side panel.
6 phases (083β088) Β· 28 plans Β· 226 commits Β· +52K / β3K LOC
Highlights
- Per-thread workspace filesystem β write/read/list/delete/version/diff; hybrid inline-Postgres (β€256 KB) / Supabase Storage; FK-chain RLS; SSE write/delete events
- 3 new agent tools β
write_todos,task(sub-agent spawning with nesting + concurrency caps),ask_user(the codebase's first Redis pub/sub, cross-worker pause/resume) - Right-side workspace panel β todos Β· file browser with per-type preview Β· client-side version-diff viewer Β· ask_user seam; open/rail/hidden state machine + mobile bottom-sheet
- Tool-dispatch extraction β registry-pattern
tool_dispatcher.py(G-5); 4 carried v2.6 bugs closed - WCAG 2.1 AA on all panel surfaces (vitest-axe gate, contrast fixed both themes, keyboard-navigable)
- Cross-provider verified β live 4-axis UAT 6/6 (OpenAI Β· Anthropic Β· Google Β· OpenRouter Β· DeepSeek Β· Moonshot); SEED-034 universal tool-use directive folded; D-17 gemini-3 thought_signature closed
Carry-forwards to v2.8
title-gen live-verify (BUG-260527-01), Google secondary-model 404, per-provider tool-use gaps, chat-tool-card unification (BUG-260529-02).
Full details: .planning/MILESTONES.md Β· Release branch: release/v2.7
π€ Generated with Claude Code
v2.6 Foundation: RAG Quality + Multi-Worker + Polish
v2.6 Foundation: RAG Quality + Multi-Worker + Polish
Shipped: 2026-05-27 | 35 phases | 91 plans | 846 commits | 16 days
Overview
v2.6 builds the production-ready substrate for the next four milestones. It closes the user-observed PDFβDOCX extraction inconsistency, lifts the single-worker concurrency ceiling, modernizes the frontend streaming architecture, integrates 9 LLM providers, and ships a live-execution UX that matches Claude.ai quality.
Highlights
π¬ Per-Aspect Extraction Dispatcher β Every extraction engine (text, tables, images, equations) is independently swappable via app_settings or per-call hint. Camelot (MIT) replaces Docling as the default table engine after a 5-engine benchmark (14.3x improvement on thesis PDFs).
β‘ Multi-Worker Production β uvicorn --workers 2 enabled with full validation: asyncpg connection pool in hot paths, 50-parallel-run synthetic load test, cross-worker cancel via Redis, sandbox session stickiness. D-PRD-12 ADR documents the singleton audit.
π¨ Live-Execution UX β RunCard + ToolCallPanel refactor with editor-inset code panels (Shiki syntax highlighting), streaming tool_args_progress across all providers, Focus Mode composition under long-run stress, per-step result summaries.
π 9 LLM Providers β OpenAI, Anthropic, Google (native SDK), DeepSeek (with thinking mode), Kimi/Moonshot, MiniMax, GLM/Zhipu, OpenRouter, Ollama. Per-provider sub-agent defaults, timeout profiles, and pattern-based inference for unknown models.
π StreamsProvider Lift β useMessages.ts reduced from 1,229 LOC to < 100 LOC thin reader. All run-stream subscriptions owned by a top-level <StreamsProvider> Context. Chat surface paints cached messages instantly on thread switch.
π§ Settings Architecture β settings_override.json eliminated. All 36+ keys migrated to DB-backed app_settings with 30s TTL hot-reload cache. model_capabilities_overrides table enables runtime model registration. 4-tier resolution: DB > env CSV > static dict > defaults.
Migrations (14)
| Migration | Purpose |
|---|---|
| 039-042 | Extraction telemetry + document columns |
| 043 | Concurrent-upload dedup unique index |
| 044 | Multimodal admin-tunable ceilings |
| 045 | Per-aspect extraction engine defaults |
| 046-047 | Table engine defaults (camelot) |
| 048 | System warning events + iteration cap |
| 049 | tool_args_progress emit boundary |
| 050 | DeepSeek reasoning_content column |
| 051 | Protected context overrun + dedup CAS |
| 052 | runs.spawned_by_worker debug column |
| 053 | Settings unification (app_settings JSONB + model_capabilities_overrides) |
Requirements Verified
All 24 v2.6 REQ-IDs validated across 6 themes (RAG Quality, Multi-Worker, Streams Provider, Polish, Code Quality, Token Telemetry, Settings Unification). Cross-cutting verification gate (Phase 082): 5/5 success criteria GREEN.
Known Issues
- Title generation broken on DeepSeek/Moonshot, partial on Google (BUG-260527-01)
- System prompt needs cross-provider tool use revision (SEED-034)
- Error Handler Foundation deferred to v2.7 (Phase 082.5)
What's Next
v2.7 Agent Workspace + Harness Engine + Plugin Contract β Per-thread workspace filesystem, state-machine harness, right-side panel UI, formal Plugin Contract for vertical packs.
v2.5 β Deployment Strategy
v2.5 β Deployment Strategy
Shipped: 2026-05-09 (10 days, 445 commits, 16 phases, 64 plans, ~104K LOC delta across 531 files)
Run-backed streaming + adaptive timeouts + UX polish. Agent generation lifetime is fully decoupled from any single HTTP request, multi-tab sync / refresh-mid-stream / navigate-away survive without manual refresh, complex tool-calling agents no longer cut off mid-iteration, and the skills test foundation is green for the next milestone.
What's new
Backend SSE concurrency unblocked (Phase 058)
Shared aexec(query) async wrapper around supabase .execute() plus AnyIO 200-token default thread limiter set in lifespan startup. Every Supabase .execute() reachable from event_stream (and the pre-stream user-message INSERT) is now wrapped in await aexec(...), plus 13 in-scope helpers and 6 cascade-forced kb.py helpers are now async def β the asyncio loop is no longer blocked by sync DB round-trips on the SSE path. Cross-tab GET drops from ~30s queued to <1s during streaming (CONCUR-01 binding pytest gate, measured ~15ms on green).
Run-backed streaming architecture (Phases 059 β 063 + 063.1)
- Phase 059 β
asyncio.Queue+ agent_runner producer +EventSourceResponse(ping=15)replaces in-handler async generator and customSSEStreamingResponse. Singletask.cancel()signal with shielded partial-response persist. - Phase 061 β Redis Streams
run:{run_id}durable buffer; producer XADDs, consumer two-mode XREADs from the same stream. Producer lifetime fully decoupled from the SSE consumer (D-061-03 contract inversion). Newpublic.runsPostgres table for durable lifecycle counterpart. - Phase 062 β
GET /threads/{tid}/active-runsandGET /runs/{rid}/stream?since={offset}HTTP endpoints. Replay-then-tail across all three sub-paths (live, already-terminal, TTL-expired). Cross-user 404 + Redis-down 503 best-effort degradation.DELETE /runs/{rid}server-side cancel. - Phase 063 β
POST /threads/{tid}/messagesreturns HTTP 201 JSON{message_id, run_id}synchronously; legacy SSE-on-POST generator deleted. FrontendstreamMessageorchestrator split intopostMessage+subscribeToRun+getActiveRuns+cancelRun.useMessagesrewired withreconcile(threadId)+resumeFromFailed(message)for mount/visibilitychange/focus/pageshow recovery. - Phase 063.1 β Closed 5 gaps from 063's live UAT (duplicate-bubble flicker, blank-window-on-thread-switch, hard-coded
since="0", concurrent-reconcile race, Resume-button data flow).
Multi-tab sync, refresh-mid-stream, and navigate-away all work as a side-effect.
Adaptive run timeouts + lifecycle states (Phase 066)
Per-LLM-call budget that resets on tool-call boundaries replaces the 120s total-deadline. The agent loop has no hard total cap (matches ChatGPT/Claude UX); only individual LLM calls have per-call budgets. When a budget IS exceeded, the run terminates as timed_out (distinct from user-initiated cancelled), captures a clear runs.error = "timed_out after Ns at iteration N" row, and the UI surfaces an "Agent reached time limit" banner with a Resume button. Closes Gap-006, verified by a live 9-minute multi-step run.
Streaming UX polish (Phases 067 + 067.1)
- Phase 067 β UX-067-01..05 closed: empty-paint, "Saving responseβ¦" thrash, refresh-required first-paint, redis-consumer log noise on tab cycle, tool-call iteration boundary surfacing.
- Phase 067.1 β Track A drain-into-queue helper neutralizes langsmith trace noise on per-call timeout (closes Gap-007 / D-066-11). Context-aware in-flight copy ("Searching knowledge baseβ¦", "Setting up agentβ¦", "Spinning up sandboxβ¦") driven by
iteration_start+tool_preparingevent payloads. Multi-step-intent system prompt redesign for clear pipeline execution. Skill-load tool-card copy clarity.
Streaming render & storage fixes (Phases 067.2 β 067.5, cross-phase chain)
- Per-thread message store β
messagesByThread: Map<string, Message[]>(LRU N=5) replaces single-buffer pattern. Cross-thread switch mid-stream now preserves the streamed-into thread's render. - Sandbox download via JS blob fetch β
frontend/src/lib/api.ts:downloadSandboxOutputfollows 302 redirect, downloads as Blob, triggers programmatic<a download>click. No more 401 on browser anchor click. - Modelβprovider router β
threads.py:949honorsMODEL_CAPABILITIES[model]['provider']overuser_settings.active_provider. Anthropic models actually route through the Anthropic SDK; Claude / OpenRouter / Google models work end-to-end. - Suggestions emit fix β Always-emit-empty + reordered before
doneso SSE-replay readers can actually receive it.max_completion_tokens=2000+run_in_threadpoolwrap. - Code-execution heartbeat β
code_executingSSE event ~every 1s during sandbox execution carryingtool_index + elapsed_seconds. Frontend renders a live elapsed counter next to the existing spinner. - Empty-thread-until-refresh fix (Phase 067.5 Branch D-3) β
clearMessages()now refuses to wipe a bucket whose thread is still streaming. 5/5 lived-experience cycles GREEN at user-driven UAT.
Skills test infrastructure repair (Phase 065)
- 11 patch sites renamed from
create_streaming_chatβcreate_adaptive_streaming_chat+ 19 fakes tuple-wrapped to match the new(stream, calling_mode)return contract (065-01). - 3 export-test assertion drifts fixed against slug-prefixed bundle layout (065-02).
- 11 tests migrated to canonical Phase 063 POSTβGET-stream pattern using
_build_mock_supabase()+ per-testthread_idfixture (065-03). - Combined skills test run: 26/26 pass. Foundation for Skill Studio milestone.
Architectural decisions locked
| Decision | What it locks |
|---|---|
| D-v2.5-01 | Blocking I/O in async handlers must be wrapped via run_in_threadpool / aexec |
| D-v2.5-02 | Single uvicorn worker (multi-worker masks concurrency bugs) |
| D-v2.5-03 | Realtime is best-effort hint, not source of truth β always reconcile via fetch on (re)connect |
| D-v2.5-08/09/10 | STREAM-04 run-backed streaming architecture (Redis Streams + replay-and-tail) |
| D-v2.5-11 | 061 + 062 + 063 ship as a single feature branch β no feature flags, no dual code paths |
| D-066-11 | stream.close() invariant under synthetic-timeout |
| D-067.3-N01 | Modelβprovider router resolution chain |
Stack changes
- New runtime dependency: Redis (via
docker-compose.dev.ymlat repo root) β durable per-run stream buffer; configured to auto-start on Docker Desktop boot. - Local-vs-cloud switch: env vars only.
SUPABASE_URL+REDIS_URLinbackend/.envpoint at local containers by default; switch to cloud (Supabase project URL, Upstashrediss://...) without code changes. - New tables:
public.runs(run lifecycle);runs:active+runs_by_thread:{tid}Redis sorted sets.
Carry-forward seeds (NOT v2.5 scope)
- SEED-009 β
claude-haiku-4-5max_tokens=65536 > 64000cap mismatch (surfaced during 067.5 cycle 5; Resume worked; needs per-model cap awareness) - SEED-010 β NR-067.2-11/12 OpenRouter Kimi 2.5 + MiniMax 2.7 synthetic-timeout protocol (creds present; ~30 min UAT to verify timeout machinery on OpenRouter-routed models)
- SEED-011 β
test_059_disconnect.py::test_normal_stream_unchangedEvent-loop-closed fixture-teardown bug (pre-existing onfa1e327base; needs_reset_redis_singletonautouse fixture analog)
Forward-looking strategic seeds
- SEED-012 β Admin / Operator UI Completeness (control everything from UI; sane fallback when not)
- SEED-013 β External Integrations (public REST API + MCP server + webhooks + service accounts)
- SEED-014 β Automations & Routines (scheduled / triggered / reactive agent runs built on the existing skills + run-backed streaming substrate)
Deferred items
31 items acknowledged at close (10 UAT status fields not flipped after cross-phase closure β cosmetic only, all show 0 pending scenarios; 4 verification gaps marked human_needed β project-level approved per Phase 063 precedent; 11 historical micro-tickets predating GSD; 6 dormant seeds intentional future work). See .planning/STATE.md ## Deferred Items for the full inventory.
Phase 064 (Validation Harness) is intentionally deferred β scenarios E + F + H were validated organically by Phases 067.3 / 067.4 / 067.5 user-driven UAT (5/5 GREEN cycles for empty-thread-until-refresh + cross-thread switch).
See also
- Full phase details:
.planning/milestones/v2.5-ROADMAP.md - Curated milestone summary:
.planning/MILESTONES.md - Retrospective (what worked, what was inefficient, lessons):
.planning/RETROSPECTIVE.md - Project state:
.planning/STATE.md - Strategic roadmap (next-milestone candidates):
.planning/seeds/
π€ Generated with Claude Code
v2.4 Stability, Polish & UX Fixes
v2.4 Stability, Polish & UX Fixes
Shipped: 2026-04-30 | 8 days | 278 commits | 72 files changed
What's New
π€ AI & Multi-Provider Reliability
- Cross-provider tool calling β
MODEL_CAPABILITIESregistry routes models to native or structured tool calling mode;tool_parser.pyprovides deterministic JSON extraction for non-native models; 32+ tests - Anthropic native SDK β
anthropic_service.pywith prompt caching; removed erroneous 20% token reduction - PROMPT-01 fix β Generation mode now only activates on explicit file-creation verbs (
create,generate,build,make); eliminates false-positiveexecute_codeon Q&A queries - Multi-provider model routing β Full user control over main, sub-agent, title, and follow-up model roles; 404 fallback with
fallback_modelSSE event and UI toast
β‘ Context Window Management
- Sub-agent keyword routing escalates generation tasks to capable model tier (32k ceiling)
- Per-model info cards in the model selector with context size, output tokens, cost tier, and best-use label
tiktoken(cl100k_base) for accurate OpenAI token estimation- Settings sliders for context history depth and sub-agent output tokens
π§ Real-Time Agent Feedback
tool_preparingSSE event β emitted as soon as the tool name is known, eliminating 30β120s silence window during tool argument streaming- ElapsedTimer β live elapsed counter (250ms tick) for running tool calls
- Step N counter β
iteration_startSSE shows which agent loop iteration is active - Ingestion step badges on document status indicators
π Document Management
- Version-aware delete dialog β choose "Delete this version" or "Delete all versions" with full chunk/storage cleanup
- Root-folder documents visible in document list with clear root badge
- Upload errors show specific reasons (duplicate, unsupported type, empty file, 50 MB size limit)
π¬ Chat UX
- Thread delete confirmation dialog (no more accidental deletes)
- No ghost content after thread delete + new chat
- Folder selector when creating a new chat
βοΈ Settings & Navigation
- Web search explicit on/off toggle in Settings (independent of API key)
- Sidebar icon labels properly adjacent to icons; logo visible when sidebar collapsed
- OpenRouter tool strategy dropdown (quality / native / xml)
π Library Health
- Server-side pagination for all health dashboard tabs
- Low confidence panel now explains query-document relevance, not document quality
- Actionable empty states with guidance
Deferred to v2.5
- STREAM-02: Tab-switch and F5 reconnect β Supabase Realtime INSERT timing unreliable; polling approach planned
- SKILL-01/02: Smart skill dispatch (relevance-based filtering) β deferred to Skills Studio milestone
Known Issues
- KI-001: In-flight LLM call runs to completion after user-initiated stop (GeneratorExit only fires at yield points)
Full changelog: .planning/milestones/v2.4-ROADMAP.md
Release: v1.0.0 β Knowledge Base Explorer
Tag: v1.0.0
Branch: master
What's new
This release completes the full Knowledge Base Explorer milestone, turning the RAG chat assistant into an agent that navigates your document library the way Claude Code navigates a codebase.
Explorer Sub-Agent (Phase 7)
- New Explorer mode in the chat toolbar β switch between General and Explorer with a single click.
- Dedicated sub-agent activates with a focused system prompt and KB-only tools (no web search, no SQL).
- Automatic reset to General mode when switching threads or opening a new chat.
- Backend branching: Sends
agent_modein the POST body to select tools and system prompt.
Knowledge Base Navigation Tools (Phases 1β6)
lsβ list immediate folder contents by path.treeβ recursive folder hierarchy with depth limiting.grepβ regex search over extracted document markdown.globβ filename pattern matching with**recursive support.read_documentβ read full document or a specific line range by document ID.- Security: All tools respect RLS β users see only their own + global folders.
Folder System (Phases 1β3)
- Hierarchical folder tree with adjacency list, cascade deletes, and RLS.
- Documents can be assigned to folders on upload or moved after ingestion.
- Folder tree UI in the ingestion page with Realtime sync.
- Global folders visible to all users; per-user folders are private.
Bug Fixes
- Agent mode now resets to General when opening a new chat or switching threads.
- Fixed stale closure in auto-naming: thread titles now generate correctly when starting a new chat in any mode.
Modules included in this build
| Module | Description |
|---|---|
| 1 | App shell β auth, threads, streaming chat |
| 2 | BYO retrieval β embeddings, pgvector, agentic tool loop |
| 3 | Record manager β SHA-256 dedup, replace-stale logic |
| 4 | Metadata extraction β structured LLM output per document |
| 5 | Multi-format support β PDF, DOCX, HTML, Markdown |
| 6 | Hybrid search & reranking β RRF fusion, Cohere/local reranker |
| 6.1 | Settings UI β read-only dashboard for LLM, embedding, retrieval config |
| 6.2 | Settings architecture β global app_settings table, env-driven config |
| 7 | Additional tools β Text-to-SQL, web search (Tavily), multi-file upload |
| 8 | Sub-agents β analyze_document tool with live streaming preview |
| KB Explorer | Folder system, navigation tools, search tools, read tool, explorer mode |
Stack
React Β· Vite Β· Tailwind Β· shadcn/ui Β· FastAPI Β· Supabase (Postgres + pgvector + Auth + Realtime) Β· OpenRouter Β· LangSmith
Release v0.2.0 β Module 7: Additional Tools & Multi-File Upload
π Release v0.2.0 β Module 7: Additional Tools & Multi-File Upload
Date: 2026-03-19
This release focuses on expanding the LLM's capabilities through advanced tool-calling (SQL and Web Search) and improving the file ingestion workflow with concurrent multi-file uploads.
β¨ New Features
- Text-to-SQL Tool (
query_documents): Ask structured questions about your metadata (e.g., "How many PDFs do I have?"). Executes via Supabase RPC with Row-Level Security (RLS) enforced. - Web Search Tool (
web_search): Powered by Tavily. Enables the LLM to access real-time data and general knowledge outside the document library. - Multi-Tool Dispatch Loop: Support for sequential and parallel tool calling in a single turn with enhanced error handling.
- Smart Tool Routing: Updated system prompts to help the LLM distinguish between metadata queries (
query_documents), content searches (search_documents), and open-web searches (web_search). - Improved Ingestion: Multi-file drag-and-drop with concurrent upload progress and graceful duplicate skipping.
π Setup & Migration
Important
Database changes are required for this release.
- Database: Run the migration script
012_query_documents_fn.sqlin your Supabase SQL editor to enable the SQL tool. - Environment Variables: To enable Web Search, add your API key to
backend/.env:Note: The tool will be automatically excluded from the LLM if this key is missing.TAVILY_API_KEY=tvly-your-key-here
π Files Changed
| Area | Files |
|---|---|
| Backend | threads.py, config.py, openai_service.py, sql_service.py, web_search_service.py |
| Frontend | DocumentUpload.tsx, useDocuments.ts, IngestionPage.tsx |
| Database | 012_query_documents_fn.sql |
| Tests | test_module7_tools.py, test_sql_service.py, test_web_search_service.py |
π Branch Info
- Source:
module-7-tools-final - Target:
master - Commit:
72239d0
v0.1.0: chore: bump version to 0.1.0
π v0.1.0 β UI Redesign
π¬ Chat UI
Full-width Message Layout: Assistant messages now expand to full width, while user messages are kept in clean, right-aligned bubbles.
Integrated Model Selector: Moved inside the message input box with a sleek dropdown, active status badge, and smart truncation for long model names.
Unified Input Box: Added a functional bottom toolbar featuring the model selector on the left, with keyboard hints and the send button on the right.
Enhanced Empty State: New icon card and descriptive subtitle for a more welcoming first-run experience.
Input Handling: Fixed a bug where the input height would not reset correctly after sending a message.
π Sidebar
New Branding: Added the official logo with a "Sparkles" icon and "Agentic RAG / Powered by AI" branding in the top-left corner.
Refined Thread List: Introduced a "Recent" section label and improved highlighting for the currently active thread.
Theming Support: Implemented a dedicated sidebar background color token (--sidebar) for seamless light and dark mode support.
π οΈ Bug Fixes
API Connectivity: Corrected VITE_API_BASE_URL port mapping (8002 β 8000), restoring functionality for message history and settings loading.
v0.1 - Module 1: App Shell + Observability
What's included
- Auth β Supabase sign in / sign up
- Chat UI β Streaming responses via SSE, thread management
- OpenAI integration
- Responses API with file search (vector store)
- LangSmith tracing β Full observability on every chat request
- UX polish
- Thinking indicator with spinner, user/assistant avatars