Spaces:
Sleeping
Sleeping
feat: mark tension card readings as AI interpretation
Browse filesCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- dashboard/components.py +10 -4
- tests/test_dashboard_components.py +23 -0
dashboard/components.py
CHANGED
|
@@ -164,8 +164,11 @@ def tension_card(tension: dict) -> None:
|
|
| 164 |
bull_side = (
|
| 165 |
f'<div style="flex:1;padding:12px 14px;background:{BULL_BG};border:1px solid {BULL_BORDER};'
|
| 166 |
f'border-radius:8px;min-width:0;">'
|
| 167 |
-
f'<div style="
|
| 168 |
-
f'
|
|
|
|
|
|
|
|
|
|
| 169 |
f'<div style="font-size:0.82rem;line-height:1.5;color:{TEXT};margin-bottom:8px;">'
|
| 170 |
f'{bullish_reading}</div>'
|
| 171 |
f'{evidence_quote(bull_ev.get("evidence_snippet","") if isinstance(bull_ev, dict) else "", bg=BG, border_color=BULL_BORDER)}'
|
|
@@ -178,8 +181,11 @@ def tension_card(tension: dict) -> None:
|
|
| 178 |
bear_side = (
|
| 179 |
f'<div style="flex:1;padding:12px 14px;background:{BEAR_BG};border:1px solid {BEAR_BORDER};'
|
| 180 |
f'border-radius:8px;min-width:0;">'
|
| 181 |
-
f'<div style="
|
| 182 |
-
f'
|
|
|
|
|
|
|
|
|
|
| 183 |
f'<div style="font-size:0.82rem;line-height:1.5;color:{TEXT};margin-bottom:8px;">'
|
| 184 |
f'{bearish_reading}</div>'
|
| 185 |
f'{evidence_quote(bear_ev.get("evidence_snippet","") if isinstance(bear_ev, dict) else "", bg=BG, border_color=BEAR_BORDER)}'
|
|
|
|
| 164 |
bull_side = (
|
| 165 |
f'<div style="flex:1;padding:12px 14px;background:{BULL_BG};border:1px solid {BULL_BORDER};'
|
| 166 |
f'border-radius:8px;min-width:0;">'
|
| 167 |
+
f'<div style="display:flex;align-items:center;gap:5px;margin-bottom:6px;">'
|
| 168 |
+
f'<span style="font-size:0.58rem;font-weight:700;text-transform:uppercase;'
|
| 169 |
+
f'letter-spacing:0.09em;color:#059669;">Surface reading</span>'
|
| 170 |
+
f'{ai_badge("AI")}'
|
| 171 |
+
f'</div>'
|
| 172 |
f'<div style="font-size:0.82rem;line-height:1.5;color:{TEXT};margin-bottom:8px;">'
|
| 173 |
f'{bullish_reading}</div>'
|
| 174 |
f'{evidence_quote(bull_ev.get("evidence_snippet","") if isinstance(bull_ev, dict) else "", bg=BG, border_color=BULL_BORDER)}'
|
|
|
|
| 181 |
bear_side = (
|
| 182 |
f'<div style="flex:1;padding:12px 14px;background:{BEAR_BG};border:1px solid {BEAR_BORDER};'
|
| 183 |
f'border-radius:8px;min-width:0;">'
|
| 184 |
+
f'<div style="display:flex;align-items:center;gap:5px;margin-bottom:6px;">'
|
| 185 |
+
f'<span style="font-size:0.58rem;font-weight:700;text-transform:uppercase;'
|
| 186 |
+
f'letter-spacing:0.09em;color:#dc2626;">Deeper reading</span>'
|
| 187 |
+
f'{ai_badge("AI")}'
|
| 188 |
+
f'</div>'
|
| 189 |
f'<div style="font-size:0.82rem;line-height:1.5;color:{TEXT};margin-bottom:8px;">'
|
| 190 |
f'{bearish_reading}</div>'
|
| 191 |
f'{evidence_quote(bear_ev.get("evidence_snippet","") if isinstance(bear_ev, dict) else "", bg=BG, border_color=BEAR_BORDER)}'
|
tests/test_dashboard_components.py
CHANGED
|
@@ -34,3 +34,26 @@ def test_interpretation_card_custom_badge_label():
|
|
| 34 |
html = interpretation_card("Language shift", "<p>tone changed</p>", badge_label="AI")
|
| 35 |
assert "✦ AI" in html
|
| 36 |
assert "Language shift" in html
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
html = interpretation_card("Language shift", "<p>tone changed</p>", badge_label="AI")
|
| 35 |
assert "✦ AI" in html
|
| 36 |
assert "Language shift" in html
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_tension_card_reading_panels_have_ai_badge():
|
| 40 |
+
"""tension_card must add ✦ AI badge next to both reading labels."""
|
| 41 |
+
import streamlit as st
|
| 42 |
+
from unittest.mock import patch
|
| 43 |
+
from dashboard.components import tension_card
|
| 44 |
+
|
| 45 |
+
tension = {
|
| 46 |
+
"headline": "Revenue beat hides quality decline",
|
| 47 |
+
"weight": "material",
|
| 48 |
+
"bullish_reading": "Strong top-line momentum",
|
| 49 |
+
"bearish_reading": "One-time item inflated result",
|
| 50 |
+
"bullish_evidence": {"evidence_snippet": "q1", "reliability": "HIGH", "source": "10-Q"},
|
| 51 |
+
"bearish_evidence": {"evidence_snippet": "q2", "reliability": "HIGH", "source": "10-Q"},
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
with patch.object(st, "markdown") as mock_md:
|
| 55 |
+
tension_card(tension)
|
| 56 |
+
rendered = mock_md.call_args[0][0]
|
| 57 |
+
|
| 58 |
+
assert "✦ AI" in rendered
|
| 59 |
+
assert rendered.count("✦ AI") >= 2 # once per reading panel
|