operator-plane: wire research reader into standalone dashboard (sparklines)

DashboardState.bars() short-circuits to [] unless a research_con is attached; the
embedded orchestrator passed one but the standalone dashboard_api.py never built
it, so production sparklines were permanently dead. The missing wire was purely
the entrypoint (DATABASE_URL already reaches the market schema) — now it opens
open_research_db("market") read-only and passes it, degrading to None (charts
show "no research db") if it can't connect. Verified live: bars() returns real
minute rows through the standalone reader.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
momentum devandClaude Fable 5 committed 2026-07-14 00:21:37 -04:00
1 parent cb206e45cb
commit 21687c97ff
2 files changed
+51 -1

No files matched your search

@@ -0,0 +1,38 @@
"""Standalone dashboard sparklines: the fix is a NON-None research reader
(plan 007 step 5). Without it bars() short-circuits; with one it runs the query
(an empty array on a bare DB is still a PASS)."""
import pandas as pd
from api.main import DashboardState
class _FakeResult:
def df(self):
return pd.DataFrame()
def fetchone(self):
return [None]
class _FakeResearchCon:
def execute(self, *args, **kwargs):
return _FakeResult()
def test_bars_without_reader_reports_missing_db():
out = DashboardState("momentum", research_con=None).bars("AAPL")
assert out["bars"] == []
assert out.get("reason") == "no research db attached"
def test_bars_with_reader_runs_query():
out = DashboardState("momentum", research_con=_FakeResearchCon()).bars("AAPL")
# the reader path ran (empty DB -> empty array, but NOT the "no db" short-circuit)
assert out["bars"] == []
assert "reason" not in out
if __name__ == "__main__": # pragma: no cover
import pytest
pytest.main([__file__, "-q"])