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>
This commit is contained in:
Ahmet Guzererler 2026-03-25 21:05:04 +01:00
parent 728ae69eab
commit 4e8e6c237e
3 changed files with 12 additions and 2 deletions

View File

@ -694,9 +694,9 @@ class LangGraphEngine:
date = params.get("date", time.strftime("%Y-%m-%d"))
portfolio_id = params.get("portfolio_id", "main_portfolio")
store = create_report_store()
flow_id = params.get("flow_id") or generate_flow_id()
store = create_report_store(flow_id=flow_id)
writer_store = store
writer_store = create_report_store(flow_id=flow_id)
if phase == "analysts":
# Full re-run

View File

@ -72,6 +72,11 @@ class DualReportStore:
"""The flow identifier set on this store, if any."""
return self._local.flow_id
@property
def flow_id(self) -> str | None:
"""The flow identifier set on this store, if any."""
return self._local.flow_id
@property
def run_id(self) -> str | None:
"""The run/flow identifier (flow_id takes precedence)."""

View File

@ -101,6 +101,11 @@ class MongoReportStore:
"""The flow identifier set on this store, if any."""
return self._flow_id
@property
def flow_id(self) -> str | None:
"""The flow identifier set on this store, if any."""
return self._flow_id
@property
def run_id(self) -> str | None:
"""The run/flow identifier (flow_id takes precedence for backward compat)."""