2.0 KiB
2.0 KiB
| type | status | date | agent_author | tags | related_files | |||
|---|---|---|---|---|---|---|---|---|
| decision | active | 2026-03-17 | claude |
|
Context
Documented bugs and wrong assumptions encountered during scanner pipeline development. These lessons prevent repeating the same mistakes.
The Decision
Codify all lessons learned as actionable rules for future development.
Constraints
None — these are universal rules for this project.
Actionable Rules
Tool Execution
- When an LLM has
bind_tools, there MUST be a tool execution mechanism — either graph-levelToolNoderouting or inlinerun_tool_loop(). Always verify the tool execution path exists.
yfinance DataFrames
top_companieshas ticker as INDEX, not column. Always use.iterrows()or check.index.Sector.overviewreturns only metadata — no performance data. Use ETF proxies.- Always inspect DataFrame structure with
.head(),.columns,.indexbefore writing access code.
Vendor Fallback
- Functions inside
route_to_vendormust RAISE on failure, not embed errors in return values. - Catch
(AlphaVantageError, FinnhubError, ConnectionError, TimeoutError), not just specific subtypes. - Fallback is opt-in: only methods in
FALLBACK_ALLOWEDget cross-vendor fallback. All others fail-fast (ADR 011).
LangGraph
- Any state field written by parallel nodes MUST have a reducer (
Annotated[str, reducer_fn]).
Configuration
- Never hardcode URLs. Always use configured values with sensible defaults.
llm_providerandbackend_urlmust always exist at top level as fallbacks.- When refactoring config, grep for all references before removing keys.
Environment
- When creating
.envfiles, always verify they have real values, not placeholders. - When debugging auth errors, first check
os.environ.get('KEY')to see what's actually loaded. load_dotenv()runs at module level indefault_config.py— import-order-independent.
Threading
- Never hold a lock during
sleep()or IO. Release, sleep, re-acquire.