Spaces:
Sleeping
Sleeping
Commit History
-
fix: Cache-hit whitelist and LangGraph-dropped gate stateβ
- Cache-hit path rebuilt the result from a hardcoded field list that predated metric_reference/recommendations/quality_notes; cache-served views therefore fell back to positional table refs misaligned with the SWOT text citations (the reported UI wonkiness). Full cached dict now passes through with only data_source/provider overridden. - data_gaps/suspect_metrics were not declared in AgentState, so LangGraph dropped them between researcher and analyzer - the gate's DATA NOT PROVIDED table section, scrubbing, and quality-notes surfacing were silently inert. Declared in the schema.096df90 -
fix: Margin-consistency gate check and final-evaluation labelβ
- data_gate cross-checks net_margin against net_income/revenue; a disagreement (period mixing upstream) quarantines the pair so a wrong margin can never be cited (companion to the Researcher-side duration fix in fundamentals extraction) - Critic's 4th evaluation after max revisions now labeled 'final evaluation' instead of the confusing 'iteration 4/3'c90d619 -
feat: Surface data-gate findings in result quality notesβ
Gaps and quarantined values were visible only in the activity log; they now appear in quality_notes.gaps_or_stale so report consumers see which required metrics were unavailable.43a46f6 -
feat: Deterministic data gate on the Researcher->Analyzer edgeβ
Applies the AgentAsk edge-contract principle deterministically (no LLM): - DG: per-category required-metric rules audited on the exact extracted view the Analyzer consumes; gaps render as an explicit MISSING section in the reference table instructing 'DATA NOT PROVIDED' - the silent empty-valuation case can no longer pass unflagged, and the Critic's existing constraint rule finally has something to enforce - SC: sanity bounds quarantine impossible magnitudes (decimal/unit slips) before they can enter the reference table and be cited; bounds reject the impossible, not the unusual (Boeing's real 9.92 D/E passes) - Both findings logged to the activity stream; 7 gate tests added7abf8e9 -
fix: Gateway resilience to Researcher restarts at submit timeβ
Observed live: a transient Researcher outage returned a non-JSON error page at submission, crashing the workflow with a raw JSONDecodeError. Non-JSON responses now surface as ResearchGatewayError with the HTTP status, and a failed submission retries once after 10s (mirroring the existing lost-task resubmission).8a1264b -
fix: Boeing-run findings β canonical refs, edge contracts, guardrailsβ
1. Canonical [M##] alignment: final result now carries metric_reference (the analyzer's own numbered list); the Quantitative Data table renders from it so table refs match SWOT text citations exactly (was: positional row numbering that diverged from the analyzer's 16-item list) 2. Numeric validator: accept citations exact at displayed precision ("$2.2B" for 2.237e9); mismatch messages now include raw values 3. Parser edge contract: only [M##]-cited lines enter the quadrants; uncited action lines route to a new Recommendations block, data-quality prose to quality notes; markdown headers can no longer leak as rows 4. Interpretation guardrails in analyzer prompts (VIX bands, margin benchmarks, internal-W/external-T classification) and a critic rubric line penalizing misclassification and W/T metric duplication 5. Citation coverage counts distinct cited metrics (no more 125%); provider failure logs deduped to one line per provider Contract tests added (tests/tesβ¦e961a43 -
fix: Resubmit research task once when the service loses it mid-runβ
The Researcher's task store is in-memory, so an HF Space deploy or restart between task submission and completion drops in-flight tasks and polling fails with 'Task not found' (-32001). Observed live when a push rebuilt the Space during an analysis. One resubmission converts that into a short delay; the emitted-metrics dedup set is shared across the retry so the UI does not double-log metrics.8d71395 -
feat: JSON-mode structured outputs for critic scoringβ
- llm_client.query gains json_mode: response_format json_object on Groq/OpenRouter, responseMimeType application/json on Gemini; validated against all three live providers - Critic evaluation now requests JSON mode; existing brace-slice parsing retained as fallback - Fix stale LANGCHAIN_PROJECT name in .env.example04accf1 -
feat: Vite 7 + React 19 upgrade and SSE status streamingβ
- Frontend majors: vite 5->7.3.6, react 18->19.2.7, plugin-react-swc 3->4; Docker frontend builder node:20 -> node:22-slim (Vite 7 floor) - SSE: GET /workflow/{id}/events streams status snapshots on change (1s cadence, 15min connection cap); frontend uses EventSource first and falls back to the original 700ms polling on stream failure - Rewrite stale ActivityLog tests against the current component API (old tests targeted a removed 'entries' prop); add missing @testing-library/dom peer dep - suite now 10/10 - Fix two shadcn empty-interface lint errors; eslint now 0 errorsf7d988e -
fix: Handle gpt-oss reasoning-token budget in Groq calls and deep healthβ
gpt-oss models spend max_tokens on hidden reasoning before emitting content; tiny budgets return empty content that reads as provider failure and triggers needless fallback. Set reasoning_effort=low for gpt-oss on Groq and give /health/deep a 512-token budget.96a9373 -
feat: Harden API, pin dependencies, and enable pytest CI gateβ
- /health/deep: 1-token ping per configured LLM provider (key presence no longer masquerades as a working model) - Abuse guards on POST /analyze: per-IP rate limit (10/h), concurrent workflow cap (3), and 1h TTL eviction for the in-memory store - CORS: hf.space subdomains via allow_origin_regex (literal wildcard was a no-op); drop unused allow_credentials - Lifespan handler replaces deprecated @app.on_event startup hook - Cache-Control: immutable for hashed /assets, no-cache for the shell - Dependencies: requirements.in + uv-compiled fully pinned requirements.txt (captures the exact resolution validated by today's live canary); Dockerfile uses npm ci for the frontend - Tests: replace live-integration test (needed API keys, imported deleted graph_cyclic) with unit tests for loop routing; pytest added to CIe926e7e -
chore: Remove AWS deployment, dead code, and unused dependenciesβ
- Remove awsDeployment/ (backend torn down 2026-07-17; HF Spaces is canonical) - Remove dead src/graph_cyclic.py (superseded by src/workflow/graph.py) - Drop unused deps: langchain-groq, google-generativeai, tavily-python, mcp - Rewrite stale pyproject.toml (was ai-strategy-copilot with Streamlit deps and a broken console script) - Align README/CLAUDE.md with the real workflow: Analyzer self-revises (no Editor node), exit threshold is score >= 6 - Document PIPELINE_SUPABASE_URL and A2A vars in .env.example and CLAUDE.md182dc1c
-
fix: Migrate to living LLM models and defuse stale production configβ
- Default models updated: Groq llama-3.1-8b-instant (deprecated 2026-06-17) -> openai/gpt-oss-20b; Gemini gemini-2.0-flash (shut down 2026-06-01) -> gemini-flash-lite-latest; OpenRouter delisted gemma-3n free model -> openai/gpt-oss-20b:free - Remove frontend/.env.production pointing at the torn-down AWS API Gateway (would have been baked into the next HF Space build) - Fix stale A2A researcher URL in .env.example - Cap langchain/langgraph/langchain-core below 1.0 to match the known-good deployed build until proper lockfile pinning lands - Add docs/audit_checklist.md from the 2026-07 technical auditf26a13c
-
debug: Add detailed logging for numeric mismatches in criticβ
Shows exact mismatch details (cited vs expected) to help identify why validation is failing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>0e30a8c -
fix: Align analyzer field names with MCP data structureβ
Valuation: - Use pb_ratio/ps_ratio instead of price_to_book/price_to_sales - Check both yahoo_finance and alpha_vantage sources (fallback) Macro: - Use interest_rate instead of fed_funds_rate - Use cpi_inflation instead of cpi_yoy - Use unemployment instead of unemployment_rate Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>2db41a2
-
fix: Improve SWOT output formattingβ
- Format large numbers with B/M suffixes ($177.6B instead of $177,556,000,000) - Fix SWOT line parsing to require spaces around separator ( - not just -) - Prevents dates like 2024-12-31 from being split across columns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>1f4f8e3 -
fix: Add MCP 'executing' state for process flow visualizationβ
- Add set_mcp_executing() to workflow_store.py - Call it at start of research phase in researcher.py - MCP containers now show 'executing' while fetching data Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>dc70069 -
fix: Handle temporal dict format for revenue_cagr_3yr in analyzerβ
The metric was being passed as {value: X, end_date: Y} dict but the formatter expected a scalar float. Added proper type checking. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>dd14be4 -
fix: Clean company name suffixes in stock listingsβ
- Strip "- Common Stock", "- Class A/B/C", etc. when parsing NASDAQ files - Refreshed cache with 5274 stocks with clean names - Prevents polluted search queries downstream Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>f72c58e -
fix: Update analyzer to handle new MCP source-keyed structureβ
- Add _extract_valuation_metric() for temporal wrappers with as_of - Update valuation extraction to use new structure - Update volatility extraction for fred/yahoo_finance sources - Update macro extraction for bea/bls/fred sources - Update news extraction for tavily/nyt/newsapi arrays - Update sentiment extraction for finnhub/reddit arrays Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>1492943 -
fix: Handle 'sources' wrapper in fundamentals data structureβ
The Researcher-Agent returns fundamentals wrapped in a "sources" key: {"sources": {"sec_edgar": {"data": {...}}, "yahoo_finance": {...}}} But analyzer expected flat structure: {"sec_edgar": {"data": {...}}, "yahoo_finance": {...}} This caused fundamentals (revenue, net_income, margins, etc.) to be silently missing from SWOT analysis. Fixed in 3 places: - _extract_company_profile() - for company profile extraction - _generate_data_report() - for Data Report tables - _extract_key_metrics() - for metric reference table Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>146876d -
fix: Only validate SWOT section for uncited numbersβ
The uncited number detection was scanning the entire draft_report including the Data Report tables (raw MCP metrics). This caused 18+ false positives since Data Report tables don't have [M##] citations. Now extracts just the "## SWOT Analysis" section before validation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>a8d1079 -
fix: Update citation patterns to match new SWOT output formatβ
The SWOT output format changed from VALUE [M##] to [M##] Metric: Value but the citation validator patterns weren't updated, causing: - 0% citation coverage (pattern didn't match) - 25+ "uncited" values flagged (all values appeared uncited) - Score capped at 4.5/10 Changes: - Added CITATION_PATTERN_NEW for [M##] Metric: Value format - Kept CITATION_PATTERN_OLD for backwards compatibility - Added CITATION_REF_PATTERN for simple [M##] counting - Updated extract_citations() to try both patterns - Updated find_uncited_numbers() to exclude both patterns - Updated get_citation_count() to use ref pattern Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>e3b7287 -
feat: SWOT output as structured text parsed into HTML tablesβ
- Backend: Updated analyzer prompt OUTPUT FORMAT to use structured text format: [M##] Metric: Value - Insight - Backend: Updated revision prompt to match the same format - Frontend: Added parseSwotLine() parser to extract ref, metric, insight - Frontend: Replaced SWOT list display with HTML tables (3 columns) - Frontend: Removed unused icon imports (Zap, AlertCircle) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>6fd7fcd -
Fix revision loop exit: change > 3 to >= 3, handle ESCALATEβ
Bug: Loop didn't exit after 3 revisions because: 1. revision_count > 3 was False when count = 3 2. ESCALATE status wasn't checked in should_continue Fix: - Change revision_count > 3 to >= 3 - Add check for critique_details.status == "ESCALATE" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>6ab9879 -
Fix revision loop: add critique_details to AgentStateβ
Bug: critique_details was not defined in AgentState TypedDict, causing LangGraph to drop it between nodes. Revisions never triggered because analyzer couldn't see critic's REJECTED status. - Add critique_details: Optional[dict] to AgentState - Add analyzer_revision_skipped: Optional[bool] to AgentState - Add debug logging to trace state flow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>95ae0b4 -
Reformat SWOT output: concise 3-column table formatβ
Backend: - Update analyzer prompt to output SWOT as tables - Format: | Ref | Metric | Insight | - Update revision prompt to use same table format Frontend: - Add cleanMarkdown() to strip asterisks and bold markers - Apply to all SWOT item displays and copy text Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>0fb19bd -
Remove duplicate Company Details from markdown outputβ
Company profile info is already displayed in frontend's Company Profile section - no need to duplicate in backend markdown. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>69cd30e -
UI improvements: metric refs, company details, remove status labelsβ
- Add M01/M02 metric reference format in data table - Add Company Details section (sector, industry, HQ, employees) - Capitalize acronyms (GDP, VIX, P/B, P/S, EPS, etc.) - Remove status labels (REJECTED, Acceptable, Board-ready, PASSED) - Use human-readable metric names in data quality notes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>86951ae -
Decrease quality threshold from 7 to 6β
- Weighted score threshold: 7.0 β 6.0 - Evidence grounding hard floor: 7 β 6 - Updated conditions.py, graph_cyclic.py, critic.py Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>07bfcf6 -
Change OpenRouter model to Gemma 3n E4B ITβ
google/gemma-3n-e4b-it:free - optimized for efficient execution, supports 32K context, multimodal inputs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>6a70bab -
Fix OpenRouter model: use deepseek-chat-v3 (was invalid model)β
The previous model openai/gpt-oss-120b:free doesn't exist (404). Changed to deepseek/deepseek-chat-v3-0324:free which is a valid free model on OpenRouter. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>784089a -
Rotate between LLM providers instead of consecutive retriesβ
Before: Groq β Groq β Groq β Gemini β Gemini β Gemini After: Groq β Gemini β OpenRouter β Groq β Gemini β OpenRouter - 3 rounds of rotation through all providers - 10s delay between each attempt - Gives each provider time to recover from rate limits Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>494ea7a -
Increase LLM retry delays and add fallback delay for all errorsβ
- Exponential backoff: 10s, 20s, 40s (was 5s, 10s, 20s) - Provider fallback: 10s delay on ANY error (was only on 429) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>8d5bad3 -
Update default models: Gemini stable + OpenRouter GPT fallbackβ
- Gemini: gemini-2.0-flash (stable instead of experimental) - OpenRouter: openai/gpt-oss-120b:free (different model for true fallback diversity) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>87e16be -
Add 10s delay between provider fallbacks after rate limit (429)β
When a provider returns 429 rate limit error, wait 10 seconds before trying the next provider in the cascade. This prevents rapid-fire requests that trigger rate limits on all providers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>59c9b47
-
Fix: Metric extraction to match MCP data structureβ
- Fix fundamentals to use sec_edgar/yahoo_finance structure - Fix valuation to use yahoo_finance.data structure - Fix volatility to use yahoo_finance.data + market_volatility_context - Fix macro to use bea_bls/fred structure - Reduce critic source_data truncation to 4000 chars (was 8000) - Fallback to multi_source if metrics path empty Fixes "No metrics extracted" error and 413 Payload Too Large. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>b3daac3 -
Increase exponential backoff from 3s to 5s baseβ
Backoffs now: 5s, 10s, 20s (was 3s, 6s, 12s) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>6810cb2 -
Increase LLM rate limit delays from 5s to 10sβ
Prevents 429 errors when Critic rejects and Analyzer retries. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>df1355a -
Fix: Handle temporal dict structure in _format_metrics_for_promptβ
- Add _get_val helper to extract value from dict or plain value - Fix operator precedence in date extraction (add parentheses) - Prevents TypeError when formatting temporal metrics Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>f80bf1d -
Fix: Temporal data extraction and frontend date displayβ
Backend: - Extract dates for valuation/volatility/macro in analyzer.py - Fix workflow_store.py to use regular_market_time for valuation - Fix workflow_store.py to use generated_at for volatility - Add Layer 2 (minimum citation count) to numeric_validator.py - Add Layer 3 (uncited number detection) to numeric_validator.py - Integrate Layers 2/3 in critic.py Frontend: - Add normalizeDate() for YYYY-MM-DD format (2025Q3β2025-09-30) - Add inferDataType() "Spot" for valuation metrics - Add extractDate() with multiple field fallbacks for news Fixes issues 2, 3, 5, 6, 8 from frontend data display audit. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>09c3333 -
Add SWOT output enhancementsβ
1. Display business_address below company header 2. Replace Quality Evaluation with DATA QUALITY NOTES section - High confidence metrics - Data gaps or staleness (>30 days) - Assumptions made 3. Add toast notifications on completion/error using Sonner Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>faf1006 -
Add VADER sentiment analysis for news and redditβ
- Add VADER helper functions (_get_vader, _compute_vader_sentiment) - Extract VADER scores from news headlines in _extract_key_metrics - Extract VADER scores from reddit post titles - Update metric reference table to include sentiment metrics (M##) - Display VADER breakdown in formatted prompt output Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>4ec98e2 -
Layer 4: Add deterministic numeric validation in Criticβ
Enforces machine-verifiable numeric accuracy: 1. Prompt changes (analyzer.py): - Require [M##] citations for all metric values - Example: "Revenue of $394.3B [M01] demonstrates..." - Clear warning that citations are auto-verified 2. New validator (numeric_validator.py): - Extract [M##] citations from SWOT output - Normalize values ($394.3B -> 394300000000) - Compare against metric_reference with tolerance - Return specific mismatch descriptions 3. Critic integration (critic.py): - Validate citations after LLM evaluation - If mismatches: cap evidence_grounding at 4, force rejection - Add specific feedback for revision - Log validation results to activity log Tested with Ford hallucination case: - Detects: market_cap $43.4B vs expected $56.6B - Detects: pe_trailing 21.3 vs expected 12.14 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>a2c9702 -
Add compact activity log for Analyzer reference valuesβ
- Log metric reference values in compact format for manual verification - Format: revenue=$394.3B, net_margin=25.3%, pe_trailing=32.5, beta=1.23 - Shortens large numbers (B/M) and removes dates for readability - Creates audit trail: MCP data β Analyzer reference β SWOT output Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>484a7a7 -
Layer 1: Add metric reference table to prevent LLM hallucinationβ
- Add immutable metric reference table at top of analyzer prompts - Use exact 'as of' dates (e.g., 2024-09-28) instead of ambiguous FY labels - Store metric_reference dict and SHA256 hash in state for integrity verification - Include reference table in both initial and revision prompts - Instruct LLM to copy values verbatim, not round or estimate New functions: - _format_metric_for_reference(): Format single metric with as-of date - _generate_metric_reference_table(): Build numbered reference table - _compute_reference_hash(): SHA256 hash for integrity check - _verify_reference_integrity(): Verify dict hasn't been corrupted Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>d2df6b8 -
Fix: Increase rate limit delays and fix revision detectionβ
1. Increase pre-call delays: 2s β 5s 2. Increase backoff times: 2s,4s,8s β 3s,6s,12s 3. Fix revision mode detection: check critique_details.status instead of revision_count (which was still 0 on first loop) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>efcfc92 -
Fix: Add rate limit handling with retry and delaysβ
1. LLM client: Add exponential backoff retry on 429 errors - MAX_RETRIES=3, delays of 2s, 4s, 8s - New _request_with_retry() helper method 2. Critic: Add 2s delay before LLM call - Avoids hitting rate limit after Analyzer's call 3. Analyzer: Add 2s delay before revision LLM call - Avoids hitting rate limit after Critic's call This prevents 429 errors from cascading through the workflow. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>de66f3b -
Fix: Critic LLM failure now triggers graceful exitβ
When Critic's LLM evaluation fails (e.g., 429 rate limit), it was returning score=5.0 without setting an error flag, causing should_continue() to return "retry" and creating an infinite loop. Now sets analyzer_revision_skipped=True on LLM error to trigger graceful exit with current draft instead of retrying. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>379f970 -
Fix: Track actual data source (SEC vs Yahoo) for fundamentals metricsβ
Backend: _extract_metrics_from_raw_data() now tracks which source (sec_edgar or yahoo_finance) each metric came from via new data_source field. Frontend: inferDataSource() uses explicit data_source if available, with fallback to form-based inference for backward compatibility. This ensures SEC EDGAR data displays correctly even when form field is missing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>33d2228