Commit History
-
fix: Round 17 audit — critical/high bug fixes (5 bugs, cross-checked)
- H1: validate_citations regex now matches References:/Reference/Sources (Primary) - H2: _strip_sql_comments rewritten as state machine, preserves --//**/ inside strings - H3: SQL citation count fixed: 1 source per query, not 1 per row - M1: Context budget now accounts for web context size before local allocation - M2: max_context_chars default aligned to 12000 (was 0 in code vs 12000 in docs) 10 agents dispatched: 5 audit + 3 fix + 2 cross-check. 175/175 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>f9f7706 -
fix: Round 14 — 28 Tier 1 + Tier 2 bugs fixed across 17 source files
Anti-hallucination integrity (T1): - #100: Detect verification LLM system failure (all calls fail → refuse) - #101: Fix validate_citations SQL/web source matching (dead code → working) - #102: Citation count uses chunks (citable units) not unique files - #103: Clamp max_iterations to min 1 (can't bypass via iterations=0) Pre-release quality (T2 HIGH): - #104: Add LIKE ESCAPE in all SQL fallback paths - #105: Gemini safety block returns "" (was bypassing stack) - #106: Cap reasoning model budget at 128000 - #107: Handle non-numeric temperature/max_tokens gracefully - #108: Fix clarification history duplication Pre-release quality (T2 MEDIUM): - #109: Anthropic temperature clamp to 1.0 - #110: SQL query 10-second timeout via progress handler - #111: Rich markup escape for user/LLM content - #112: All 6 readers wrapped in try/except (corrupt files don't abort) - #113: Collection cache invalidation after re-ingestion - #114: Web UI message history capped at 200 - #115: Setup wizard confi…f95cdb7 -
fix: pre-release audit round 12 — 33 bugs fixed across all tiers
Tier 1 (ship-blockers): - README/verifier layer count corrected to 7-layer/10-point - SQL keyword regex now strips quoted strings before checking - validate_citations counts unique sources, extracts from body only - Provider-specific error messages for all 3 LLM backends - Missing config error handling in ingest.py entry point Tier 2 (quality): - SQL injection: alphanumeric validation on interpolated values - LIKE wildcard escaping with ESCAPE clause - Fallback builds fresh keyword query instead of re-running failed SQL - NaN/NaT/inf filtering across all tabular readers - Merged docx table cells deduplicated via element identity - .env double-escaping fix in setup wizard - Verification LLM exceptions skip correction instead of triggering it - References check handles SQL and web sources - Dead pre-loop validate_citations removed - KB meta extension detection uses Path.suffix - QU prompt omits SQL fields when no schema available - Redundant collection.count() eliminated - Row padding f…fbd18c8
-
fix: try alternate TEXT columns before word-level fuzzy matching
When phrase-level fuzzy fails on the original column (e.g. Country), now tries phrase-level LIKE on other TEXT columns in the same table before falling back to word-level fuzzy. This fixes South Korea queries returning 98 rows (both Koreas via LIKE '%Korea%') instead of 49 rows (just South Korea via Country_OLD LIKE '%South Korea%'). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>b71f629 -
fix: add word-level fuzzy SQL matching for country name variants
Country names like Korea, Republic of do not contain South Korea as a substring, so phrase-level LIKE fails. Word-level fuzzy extracts significant content words (dropping directional/geopolitical qualifiers) and matches individually: WHERE Country LIKE %Korea%. Three-step strategy: exact -> phrase fuzzy -> word-level fuzzy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>d4a1a18 -
fix: SQL fuzzy matching fallback for country names with alternate forms
Exact match (=) tried first; if 0 rows, auto-retries with LIKE '%...%'. Match type (exact/fuzzy) transparently reported in UI source summaries. Fixes queries like "South Korea" matching "South Korea (Republic of Korea)". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>6b689a5 -
fix: strip trailing semicolons from LLM-generated SQL and add SQL-route fallback
Two bugs prevented SQL retrieval from working: 1. LLMs append trailing semicolons to SQL (~90%% of the time). _validate_sql() rejected these as potential injection attacks. Fix: rstrip(';') before validation (internal semicolons still blocked). 2. When route=sql and the LLM SQL query failed, the keyword-based SQL fallback never triggered (condition excluded route=sql). Fix: expanded fallback to build fresh keyword query for route=sql. Verified end-to-end: China PTS scores now returns 49 rows (was 0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>f97b9fe -
fix: Round 8 audit — 15 bugs fixed across 10 files (1 CRITICAL, 7 HIGH, 3 MEDIUM, 4 LOW)
Security fixes: - CRITICAL: execute comment-stripped SQL query (not original) to prevent injection bypass - HIGH: iterative comment stripping to handle nested comment attacks - HIGH: expand dangerous SQL keyword blocklist from 11 to 23 entries - HIGH: data loss prevention — deferred clear only on first successful embed Robustness fixes: - HIGH: parse_verification_result(None) crash guard - HIGH: try/except on all verification loop generate() calls - HIGH: empty rows guard in Excel reader - MEDIUM: strict boolean normalization for verification pass/fail - MEDIUM: R-style "na" added to null string detection - MEDIUM: broad exception handling for Gemini API errors Minor fixes: - LOW: distinct error message for empty LLM response vs no sources - LOW: bounds check on setup wizard model selection - LOW: route/sql_query keys in CLI and web fallback dicts - LOW: SQL fallback extended to route="both" Cross-checked by 2 verification agents — all fixes confirmed correct. 165/165 tests passing,…9093d8f -
fix: 10 bugs (4 HIGH + 6 MEDIUM) from comprehensive codebase audit
HIGH fixes: - H1: Gemini blocked-response detection in verifier (safety filter short-circuit) - H2: Config load crash guard in app_web.py (st.stop instead of traceback) - H3: Brace-escape user text in kb_meta.py prompts (prevent KeyError) - H4: Web UI clarification state tracking (pending_clarification_question) MEDIUM fixes: - M1: Preserve leading zeros as TEXT in sql_ingest type inference - M2: Deferred clearing in ingest.py prevents data loss on total failure - M3: Strip markdown fences from LLM-generated SQL in sql_retriever - M4: max_iterations=0 guard in verifier (skip verification, do not refuse) - M5: Add clarification QA to conversation history for pronoun resolution - M6: Remove hardcoded knowledge_base/ prefix in retriever source paths Also adds CLAUDE.md, docs/plans/, full test suite (162 tests, 17 files), and updates WORKLOG.md with audit results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>1330e5c -
fix: 7 bugs from multi-agent debug review of SQL layer
- Column name deduplication after sanitization (Score-A/Score_A collision) - _safe_str() preserves None in Stata/SPSS/R data loaders - Reject inf/Infinity in column type inference - Guard against n=1 in _get_sample_values (ZeroDivisionError) - NULL values render as "N/A" in SQL context (not "None") - Defensive .get() in build_schema_summary for malformed schema - Backtick-quoted table names in _extract_table_from_query regex Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>d6a01c7 -
feat: add LLM-powered column descriptions with codebook detection
During SQL ingestion, each table columns are now described by the LLM: 1. Search same directory for codebook/documentation files (PDF, DOCX, TXT, MD) 2. If codebook found, pass its text + column metadata to LLM for descriptions 3. If no codebook, LLM infers column meanings from names, types, samples 4. Descriptions stored in sql_schemas.json alongside existing column metadata Column descriptions are always visible to the chatbot: - build_schema_summary() includes descriptions in the QU prompt - format_sql_results_as_context() includes descriptions with SQL results - Graceful degradation: LLM failure is non-fatal Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>3d1d5b4
-
fix: fallback to KB meta overview when vector search returns no results
When all chunks exceed the distance threshold, the retriever now fetches the KB meta overview chunk directly as a fallback. This fixes meta-questions like "do you have any dataset?" returning empty results when the embedding similarity didn't match closely enough. Also adds a system prompt instruction to use the KB overview to describe what IS available when it's the only local source. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>2317f6c -
feat: add SQL routing, fallback, and context merging to retriever
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>7758af3 -
fix: harden codebase against format injection, empty responses, and unsafe config access
- Add _escape_braces() to all prompt builders to prevent str.format() crash when user documents contain {placeholder} patterns - Fix app_web.py display_query fallback to preserve clarification context - Add empty-response guards to all 3 LLM providers (openai, anthropic, gemini) - Replace all remaining direct dict access with .get() + defaults - Add 2 regression tests for curly-brace format injection - Expand query engine tests with display_query coverage - 62 tests pass across 13 test files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>9815e49 -
feat: retrieve all relevant chunks using distance threshold
Instead of a fixed top_k count, retrieval now uses a distance threshold (max_distance=0.55). Queries up to 50 candidates from ChromaDB, then keeps only chunks with cosine distance below the threshold. This means: - Broad queries with lots of relevant docs get many chunks - Narrow queries with few matches get only the relevant ones - Irrelevant chunks are filtered out regardless of top_k New config field: retrieval.max_distance (default 0.55) top_k now acts as the candidate pool cap (default 50) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>0bb6123 -
fix: increase top_k to 10 and remove last [N] from verification prompt
Two fixes: 1. Increased default top_k from 5 to 10. With top_k=5, short queries like "China in 2024?" missed the relevant page (e.g., page 410) because generic intro pages ranked higher. More chunks = better chance of retrieving the right content. 2. Removed the last literal [N] from the verification prompt template (checklist item 1) to prevent any residual [N] in output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>ca19369 -
Initial commit: RAG Research Chatbot Template
Citation-verified research assistant with 6-layer anti-hallucination stack, 15 file format readers, 3 LLM providers, and dual CLI/Web interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>0017280