* feat: add macro scanner feedback loop and lessons memory
- Implements `LessonStore` to persist JSON screening lessons
- Adds `selection_reflector.py` to fetch performance and news, and generate LLM lessons
- Adds `memory_loader.py` to filter negative lessons into `FinancialSituationMemory`
- Integrates a rejection gate in `candidate_prioritizer.py` based on past negative lessons
- Adds `reflect` command to CLI
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* feat: update macro scanner feedback loop for dual-lesson output (Trend DNA)
- Update `selection_reflector.py` to calculate exact terminal returns, `mfe_pct`, `mae_pct`, and `days_to_peak`.
- Update LLM prompt to generate distinct `screening_advice` and `exit_advice`.
- Update `lesson_store` tests to reflect new schema.
- Update `memory_loader.py` to use `screening_advice` for negative selection filtering.
- Update `micro_summary_agent.py` to inject `exit_advice` into PM context for current holdings.
- Update `cli/main.py` default horizons to `30,90` and print dual-advice columns.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* fix: resolve bugs in macro scanner feedback loop
- Address Key mismatch (stock_return_pct vs terminal_return_pct)
- Fix missing persistence of mfe_pct and mae_pct
- Use create_report_store() instead of raw ReportStore() in load_scan_candidates
- Clean up unused imports in fetch_news_summary
- Ensure default horizons match code in cli description
- Create isolated `_local_safe_pct` to remove cross-module dependency
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* fix: address PR 124 feedback on macro scanner memory feedback loop
- Use `l.get('screening_advice')` gracefully in `memory_loader` to prevent KeyErrors.
- Properly instantiate `selection_memory` inside the graph in `portfolio_setup.py` and pass it to the prioriziation rejection gate.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* feat: introduce flow_id with timestamp-based report versioning
Replace run_id with flow_id as the primary grouping concept (one flow =
one user analysis intent spanning scan + pipeline + portfolio). Reports
are now written as {timestamp}_{name}.json so load methods always return
the latest version by lexicographic sort, eliminating the latest.json
pointer pattern for new flows.
Key changes:
- report_paths.py: add generate_flow_id(), ts_now() (ms precision),
flow_id kwarg on all path helpers; keep run_id / pointer helpers for
backward compatibility
- ReportStore: dual-mode save/load — flow_id uses timestamped layout,
run_id uses legacy runs/{id}/ layout with latest.json
- MongoReportStore: add flow_id field and index; run_id stays for compat
- DualReportStore: expose flow_id property
- store_factory: accept flow_id as primary param, run_id as alias
- runs.py / langgraph_engine.py: generate and thread flow_id through all
trigger endpoints and run methods
- Tests: add flow_id coverage for all layers; 905 tests pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: PM brain upgrade — macro/micro summary agents, memory split, forensic dashboard
Replaces the PM's raw-JSON context (~6,800 tokens on deep_think) with a
MAP-REDUCE compression layer using two parallel mid_think summary agents,
achieving ~70% cost reduction at the PM tier.
Architecture:
- MacroMemory: new regime-level memory class (MongoDB/JSON, separate from
per-ticker reflexion memory) with record_macro_state/build_macro_context
- ReflexionMemory: extended with collection_name param to isolate
micro_reflexion from the pipeline reflexion collection (with distinct
local JSON fallback path to prevent file collision)
- Macro_Summary_Agent (mid_think): compresses scan_summary into a 1-page
regime brief with memory injection; sentinel guard prevents LLM call on
empty/error scan data ("NO DATA AVAILABLE - ABORT MACRO")
- Micro_Summary_Agent (mid_think): compresses holding_reviews + candidates
into a markdown table brief with per-ticker memory injection
- Portfolio graph: parallel fan-out (prioritize_candidates → macro_summary
‖ micro_summary → make_pm_decision) using _last_value reducers for safe
concurrent state writes (ADR-005 pattern)
- PM refactor: Pydantic PMDecisionSchema enforces Forensic Execution
Dashboard output (macro_regime, forensic_report, per-trade
macro_alignment/memory_note/position_sizing_logic); with_structured_output
as primary path, extract_json fallback for non-conforming providers
- PM sentinel handling: "NO DATA AVAILABLE" in macro_brief substituted
with actionable conservative guidance before LLM sees it
62 new unit tests across 4 test files covering all new components.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address code review — relaxed error guard, ticker_analyses, PM memory wiring
1. macro_summary_agent: relaxed error guard to only abort when scan_summary's
sole key is "error" (partial failures with real data are now processed)
2. micro_summary_agent: now reads ticker_analyses from state and enriches
the per-ticker table with trading graph analysis data
3. portfolio_graph: wires macro_memory and micro_memory to PM factory call
4. test_empty_state: updated test for new partial-failure behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>