- vendors/yahoo: ohlcv (loader and cache), market (prices, indicators), fundamentals (profile, statements, insider), news, snapshot
- vendors/alpha_vantage is a package; sec_edgar, fred, polymarket, reddit and stocktwits sit beside it
- the one-method StockstatsUtils class is a function; the duplicate Yahoo host constant is gone
- tests are named after the modules they cover: test_ohlcv_date_column, test_yahoo_snapshot, and the ohlcv and snapshot aliases
- interface -> router; symbol_utils -> symbols, which also takes safe_ticker_component
- utils is split: get_current_date to date_window, the HTTP helpers to net
- dataflows imports are absolute; the NoMarketDataError re-export from symbols is gone
yfinance intermittently returns a year-old partial frame (e.g. June 2025 rows
for a June 2026 request) that still has rows and a Close, so it passed the
empty-check and silently fed a wrong close price and indicators into the report
(#1021). Add a freshness guard that rejects a frame whose latest row is far
older than the requested date, on both the raw OHLCV path and the indicator
path. It raises the existing NoMarketDataError with a stale-specific detail, so
the vendor router's try-next-vendor and single unavailable-signal handling apply
unchanged; the sentinel now surfaces that detail so the agent reports the
specific reason rather than fabricating a value.