build_site_finder_report (§22) takes ~30-180s → runs in a background Celery task,
not inline on the sync /analyze endpoint.
- repository: latest_run_for gains keyword-only schema_version (default None keeps
v_analysis_runs_latest behavior, backward-compat); when given, reads base
analysis_runs filtered by schema_version ORDER BY created_at DESC LIMIT 1 — fetches
the latest analyze-1.0 site-analysis run even when newer 1.0 (§22) rows exist on top
(index-served via 127's (cad_num, created_at DESC)).
- new workers/tasks/forecast.py::forecast_site_finder_report: reads latest analyze-1.0,
runs the §22 orchestrator, persists SiteFinderReport.as_dict() as a 1.0 run via
persist_analysis_run. Graceful: no base run / compute error → logger + return None
(worker not crashed). time_limit=900/soft=840 (no global limit). Registered in include.
Prod-confirmed: analyze-1.0 result carries the full analyze dict (competitors+district)
→ orchestrator input valid. Endpoint trigger (3b-ii) + §9.x untouched. 943 tests pass;
code-review APPROVE (contracts verified vs real as_dict(); status done→complete normalized,
no IntegrityError). Refs #994#961.