Spaces:
Sleeping
Sleeping
Commit History
-
feat: The Brief renders as the published research noteβ
The Brief was a stack of ~20 cards. It is now one document, reproduced from the note published on 2026-09-02: masthead, ten sections in a fixed order, sticky contents bar, sticky data rail, sourced footer. Same palette, same typography, same placements. The reproduction is asserted, not asserted-to-be. tests/test_note_fidelity.py compares against tests/fixtures/published_note.html and passes only if the stylesheet matches declaration for declaration (117 rules, no additions) and each of the three figures is byte-identical -- coordinates, order, attributes. Two encodings are allowed to differ and both are pinned by that test: the .rt-note selector prefix, and xmlns on every <svg>. The palette is the app's now, not the document's. Every hardcoded colour across 19 modules -- 330 of them -- was remapped onto the note's thirteen tokens, config.toml was repointed, and Inter gave way to the note's three families. A light document inside a dark shell would have been two designs. What the fiβ¦93f9cc0
-
feat: the guidance record fills the half of Track Record that never workedβ
The panel already asked two questions and answered one. Its right half scored the consensus record; its left half read brief["guidance_history"], where verdict is always None, so it showed "no scoreable guidance found" for every company while the ranges sat unused in metrics one table away. The left half now scores from those ranges and uses the same two devices as the right -- score card and verdict strip -- so the two halves finally read alike: did they keep their own word, did they clear the street's bar. Beneath them sits the one device this dashboard did not have. A verdict strip can say a streak happened; it cannot say the cushion behind it fell from +20.4% to +3.7%. history_table() shows the figures per row, right-aligned and tabular, in its own horizontal scroller so a wide table never makes the page scroll sideways. Two things were removed rather than added. The Beat / In-line / Missed / Pending counters in the guidance bridge read the same empty verdict field and so displaβ¦da30423
-
feat: link The Brief's sourced facts to their filings, guard the URL schemeβ
The spec claimed changing meta_row's signature would make every fact traceable at once. It did not: meta_row's three callers never passed evidence_ref, and The Brief's two highest-volume fact renderers (_render_what_changed, _asym_line) hand-build their own meta_bits and never call meta_row at all. Net user-visible traceability from the branch was the KPI footnote and nothing else. Wire the four call sites the spec's goal names -- _render_standout_number, _render_what_changed, _asym_line and _tension_body. Each inherits evidence_link's fail-closed "" when no URL exists, so no new gate is needed and no fact without a source_url changes byte for byte. signal_card stays unwired: it would need Signal to carry the ref, which signal_feed drops in _evidence_fields. Ship the URL-scheme allowlist in the same commit. escape(url, quote=True) blocks attribute breakout but leaves the scheme intact, so javascript: survives escaping unchanged -- and the wiring above is exactly what starts feeding β¦24d7b8c
-
feat: make every sourced fact traceable via meta_row evidence links
6ae694a
-
feat: add compact mode to section headers for half-width grid cells
00fa796 -
feat: add weighted_grid layout helper for multi-column card sectionsβ
Implement pure list-chunking helper _chunk and thin Streamlit wrapper weighted_grid to arrange cards into configurable columns with special handling for trailing partial rows. Callers pre-filter cards to only those with content, keeping content decisions in verdict.py per established pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>1596598
-
feat: analyst-edge screens for events, wording, Q&A and earnings qualityβ
Surface the research a retail investor cannot assemble by hand, and explain every panel in plain language before it shows a number. What Changed becomes four readings of the same quarter instead of one undifferentiated stream: what the company filed (8-K item codes as a dated event log), what it rewrote (grouped by meaning rather than by which analyser found it), what analysts kept pressing on, then the full signal feed. Financials gains the management track record, whether beating the published estimate actually moves the stock, GAAP versus adjusted profit, and the balance-sheet ratios that lead the income statement β including whether buybacks really shrank the share count or merely offset employee stock. dashboard/explain.py carries the comprehension layer: each block states what it is, how to read it, where the figure came from and what it does not prove. Panels that come back empty say why, so a genuine absence cannot read as a broken feature. Three defects surfaced and were fβ¦5b9b478 -
feat: dark mode, market and quarter context on The Brief, faster cold startβ
UI - Migrate the whole app to a dark palette driven by dashboard/theme.py tokens rather than an overlay, including a registered Plotly template so charts theme globally. Streamlit base set to dark in config.toml. - The Brief now opens with what a memo about a listed company must show: a market band (price and move, market cap, 52-week range with position marker, dividend yield) and the quarter's reported figures (revenue, EPS, gross and operating margin, FCF with deltas). Rows come from the same masked view Financials uses, so a hidden figure stays hidden. - Surface what_changed on The Brief itself; it was only reachable from another screen although it is the first thing the brief promises. - Warn when most facts are unverified instead of showing a thin brief with no explanation. - Landing page explaining each destination, with saved briefs as entry points, for visitors arriving with no ticker. - Company Primer: prose sections rendered as cards rather than dataframes,β¦3cd8872
-
feat: multi-provider LLM support, prominent chat, design pass, and new analyticsβ
- Add agent/llm.py provider factory (Anthropic/OpenAI) with a sidebar model picker so visitors can paste their own API key instead of relying solely on the server's; thread the resulting config through generation, chat, and translation. - Promote Chat to primary nav (was buried under a secondary "Evidence tool" heading) with suggested-question chips and a "sources searched" line. - Fix a pre-existing bug where every nav/CTA color accent silently no-oped (Streamlit exposes st.button(key=...) as a `st-key-{key}` wrapper class, not a `key` attribute) and tighten the palette to three families (emerald brand, violet AI, semantic bull/bear). - Add a "Sources analyzed" provenance card, quarter/annual basis split on the financials grid, and cross-category signal dedup. - Add valuation + peer comparison, next-catalysts, brief-vs-brief delta, and one-page PDF export. - Rename the product from Primer to Amplegest across the app, docs, and the Hugging Face Space (old URL redireβ¦7880373
-
feat: add section_header component with accent tick + semibold labelβ
Replaces section_divider visual (faint 0.68rem gray label) with a stronger header: 4px colored accent bar, 0.78rem dark semibold label, hairline rule. section_divider kept as backward-compat delegate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>f464da5
-
feat: Decision Stack redesign - 9 routes collapse into 4 (Verdict / Signals / Financials / Chat)β
Every datum now has exactly one home; everywhere else references, never re-renders. - Verdict: one-screen decision view - thesis, reconciled Print panel (actual vs consensus EPS/rev, D1/D5, revisions, surprise+streak, sentiment - one source of truth per number with provenance), top-2 bull/bear asymmetry, The Tell, top-3 watch items, reasoning trace. - Signals (new): all qualitative content (tells, tensions, language deltas, changes, risks, quality, points, commentary, notes, news) normalized by signal_feed.py into one ranked stream, filtered with st.pills (type/stance/source/significance), rendered by a single signal_card component; one global semantic search replaces the three per-tab boxes; on-demand news moved here. - Financials (new): KPI snapshot, 5 chart tabs (adds Capital Allocation: capex/dividends/buybacks vs FCF, share count, tax rate), guidance bridge (scorecard + prior guide -> actual -> new guide; removes the detected-by-rule regex implementation leaβ¦bd2c14a -
chore: checkpoint sidebar nav + i18n work-in-progress before Decision Stack redesignβ
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>e6496c0
-
refactor: extract shared between_the_lines helper, fix section numberingβ
- Add render_between_the_lines() to dashboard/components.py β single source of truth for the 'Lecture entre les lignes' section divider + subtext_card loop - dashboard/verdict.py: delegate _render_between_the_lines to shared helper; neutralise docstring; remove '3b' sub-number from render() comment - dashboard/quality_tone.py: replace inline btl block with render_between_the_lines(brief); renumber sections 4β7 to fix the duplicate '3.' after inserting section 2 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>0376cd9 -
fix: use TEXT color for implication body in subtext_card
e7400fb -
feat: add subtext_card component for between_the_lines displayβ
Adds _SIGNAL_TYPE_LABELS (FR labels + indigo/red/amber/gray/sky palette) and subtext_card(item) rendering observation β reading β implication with signal-type chip, AI badge, collapsible evidence quote, and meta row. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>402936a
-
fix: polish components.py β LOW marker, separator spacing, label, readabilityβ
- importance_marker LOW: use filled β at slate-400 (#94a3b8) instead of β hollow circle; filled dot is legible at low contrast, hollow was not - meta_row separator: remove extra margin:0 2px (flex gap=4px already provides even spacing; margin was double-spacing around the dot) - _RELIABILITY_LABELS MEDIUM: 'Confidence med.' β 'Med. confidence' (parallel word order with 'High/Low confidence') - tension_card: pre-compute evidence fields before HTML f-strings (replaces three deeply-nested inline ternaries per side with named vars) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>39c3837 -
feat: add eyebrow_label/importance_marker/meta_row/sort_by_impact helpers; neutralize card surfaces (Task 2)β
- Add FS_BODY, FS_META, FS_EYEBROW to imports from dashboard.theme - New eyebrow_label(): centralises uppercase micro-label pattern using FS_EYEBROW - New importance_marker(): monochrome HIGH/MEDIUM/LOW dot+word, no green/red - New meta_row(): single attribution line replacing 3-badge stacks (reliability/source/impact) - New sort_by_impact(): stable HIGHβMEDIUMβLOWβunknown sort on lists of dicts - interpretation_card: background AI_BGβBG (white), keep violet left edge + ai_badge - fact_card: replace 3-badge div with meta_row(); apply FS_BODY; add max-width:680px - tension_card: outer BG white + amber left edge; inner panels BG_MUTED + BORDER; move ai_badge to outer header (one, not two); replace badge rows with meta_row() - earnings_quality_card: background always BG (white); drop ai_badge("AI assessment"); replace 3-badge row with meta_row() - delta_card: background BG (white), keep kind-colored left edge + existing pill row - numbered_list: apply FS_BODY to item text; add max-widβ¦67da450 -
fix: add AI badge to earnings_quality_card; update test from deleted quality_signal_chipβ
quality_signal_chip was removed in Lot 4 (dead code with no call sites), but its test was missed. earnings_quality_card is the live replacement and now correctly shows an β¦ AI assessment badge before the rationale. Test renamed accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>963a3c8 -
refactor: global disclaimer, section_divider to components, numbered_list helper (Lot 5)β
- Remove 6 per-tab footers (verdict, numbers, mda, risks, earnings_call, catalysts) - Add one global data disclaimer in app.py after all routing elif blocks - Move _section_divider to components.py as public section_divider; remove private copies from verdict.py and quality_tone.py - Add numbered_list helper to components.py; replace inline loop in verdict.py and for-loop in catalysts.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>2ee5d17 -
refactor: visual system normalization β violetβIA only, glyph unification, token hygiene (Lot 4)β
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>1843630 -
feat: redesign Verdict tab for senior equity research / PM audienceβ
- Promote Executive Summary to top position (verdict in 5 s) - Add QoQ Watch-Outs section: consolidates cautionary deltas (risk_added, reworded, kpi_dropped, guidance more cautious, term freq up), concerning earnings quality signals, bearish tension readings, and sentiment panel β all deterministic, no LLM, each alert retaining source + significance - Earnings Quality signals now always-expanded cards (2-col grid) instead of collapsed <details> chips - Promote Market Expectations out of expander into main body - Bull/Bear moved directly under exec summary (explicit request) - Reorder: snapshot strip β exec summary β strengths/concerns β watch-outs β earnings quality β market expectations β tensions β changes/catalysts - Add earnings_quality_card() component to dashboard/components.py - Integrate dashboard/agent_graph.py live SVG into generation trace view Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>947b6dd -
feat: Analyst Edge layer β deterministic text delta signals (Phase 0+1)β
Adds a signal engine that computes verbatim filing text changes across consecutive periods and injects them into the LangGraph pipeline before the LLM loop, so the agent investigates signals and the synthesis cites exact beforeβafter fragments rather than summarizing what it already knows. Phase 0 β foundation: - storage/sections_db.py: persist raw MD&A, Risk Factors, and transcript text keyed by (ticker, period, section); populated at ingest time - ingest.py: call upsert_section for each text block after edgar fetch - analysis/signals.py: QuarterDelta Pydantic model (kind, before_text, after_text, computed_metric, significance) shared across all modules - agent/graph.py: signals_node as new entry point; edge_signals state key; attach_edge_signals() called in synthesis_node after apply_reliability() - agent/post_synthesis.py: attach_edge_signals() writes authoritative computed data β LLM cannot fabricate signal numbers - agent/schemas.py: BriefOutput.quarter_deltas optional fiβ¦559c2ff
-
fix: nav group label alignment + impact badge bubble dotsβ
Replace HIGH/MED/LOW text on impact badge with filled dot indicators (βββ / βββ / βββ) to avoid confusion with source reliability labels. Fix sidebar nav group headers misaligned with radio circles by switching ::before from display:block to flex:0 0 100% with flex-wrap on parent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>fd1e2da -
fix: verdict layout, N/A market pulse, impact badge colorsβ
- agent/tools.py: get_analyst_expectations now emits exact schema field names (consensus_rev_est_bn, revision_30d_pct, d1/d5_price_reaction_pct) so the LLM copies values verbatim instead of renaming β eliminates silent null drops via Pydantic extra="ignore" - agent/prompts.py: MarketExpectations instruction now explicitly lists each field name and forbids renaming - dashboard/verdict.py: - Market Pulse chips hidden when value is None (no more "N/A" display) - AI Deeper Band moved directly after AI Synthesis (all AI interpretation grouped before sourced facts) - Bull/Bear rendered as paired rows (st.columns per pair) so cards align horizontally regardless of count asymmetry - dashboard/theme.py: IMPACT_COLOR/BG/BORDER replaced by per-level slate tokens (HIGH=slate-900, MED=slate-500, LOW=outline slate-300) - dashboard/components.py: impact_badge() rewritten β compact tier labels (HIGH/MED/LOW) with severity colors, drops dots and "Impact" word Co-Authored-By: β¦d42057a -
feat: add impact badge to all sourced factsβ
Each fact now carries a third badge (βββ/βββ/βββ in teal) indicating materiality to the investment thesis β HIGH, MEDIUM, or LOW β alongside the existing reliability and source badges. - schemas.py: Optional impact field on SourcedFact, CategorizedRisk, ManagementCommentaryTopic, GuidancePoint (+ reliability added to GuidancePoint which lacked it) - prompts.py: impact rubric + field in every fact dict of the JSON template so the synthesis LLM assigns it consistently - theme.py: IMPACT_COLOR/BG/BORDER tokens in teal (distinct from reliability green/amber/gray and AI purple) - components.py: impact_badge(), updated fact_card, tension_card, quality_signal_chip - verdict/risks/mda/catalysts/earnings_call: impact_badge wired into every fact rendering site Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>21359be
-
fix: use AI_BORDER in interpretation_card, use ai_badge in quality_signal_chip
040f6a5 -
feat: mark earnings quality signal rationale as AI interpretationβ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>474b520 -
feat: mark tension card readings as AI interpretationβ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>eef20d7 -
feat: add ai_badge and interpretation_card helpersβ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b46b0ef -
feat: analytical edge section + fix HF Spaces fragment polling raceβ
- Replace run_every=0.4 fragment with server-side sleep loop to eliminate browser-timer/proxy race causing 'SessionInfo before initialized' on HF Spaces - Add analytical_tensions, earnings_quality_signals, non_obvious_takeaway to BriefOutput schema and synthesis prompt - Render Analytical Edge section on Verdict tab (tension cards, quality signal chips, non-obvious takeaway) - Prune analytical_tensions that duplicate bull/bear point evidence (Jaccard) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>05d403b -
deploy: Primer app for HF Spaces β clean orphan historyβ
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>35676b4