gendesign/backend/app/services/forecasting
Light1YT dcccebf2c2
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Successful in 1m17s
CI / openapi-codegen-check (pull_request) Successful in 2m11s
CI / backend-tests (pull_request) Successful in 10m19s
fix(forecasting): honest scenarios collapse when β rate-sensitivity gate fails (audit #1871 P1)
Когда demand_normalization honesty-gate отбивает β rate-sensitivity
(`sensitivity.confidence=='low'`, ЕКБ-регрессия не проходит n≥30/R²≥0.1/slope<0),
все 393 прод-отчёта получают coefficient=1.0 для всех трёх сценариев
conservative/base/aggressive. По дизайну backend честно деградирует, но фронт
рисует 3 разноцветные карточки/линии одинаковых чисел без caveat.

Backend (scenarios.py, report.py, report_assembler.py, orchestrator.py):
- compute_scenarios теперь возвращает (list, collapsed: bool, reason: str|None)
- _detect_collapsed(): math.isclose(rel_tol=1e-9, abs_tol=1e-6) сравнивает
  projected_demand_units И deficit_index на всех горизонтах между
  conservative и aggressive — расхождение в любой метрике на любом h → False
- _COLLAPSE_REASON_LOW_BETA — единственный источник истины каноничного
  русского предложения
- ReportScenarios получает поля scenarios_collapsed + scenarios_collapse_reason
- demand_normalization.py НЕ ТРОНУТ — поведение корректно по контракту

Backend экспортёры (report_pdf.py, excel.py):
- PDF: при collapse — тёмная плашка-параграф вместо таблицы трёх столбцов
- Excel: ОДНА строка «base» + caveat-ячейка вместо трёх идентичных столбцов

Frontend (forecast.ts, ScenariosBlock, ScenarioCards, ScenarioCompareTable,
ForecastChart, Section6Forecast, ptica.module.css):
- Тип ReportScenarios расширен двумя optional-полями
- ScenariosBlock (light): headline-bar + одна grid-карточка base + caveat
- ScenarioCards (ptica dark): sub-component ScenarioBaseCard, одна карточка
  + collapse-note, ScenarioCompareTable return null
- ForecastChart: effectiveScenarios filter — одна линия viz-1 «Базовый»
  вместо трёх перекрывающихся
- Section6Forecast: caveat выше графика, читается ТОЛЬКО из
  scenarios_collapse_reason (источник истины — backend constant)

Тесты: +18 новых (TestMetricsEqual×6, TestDetectCollapsed×7,
TestComputeScenariosCollapseDetection×4 + 1 проверка graceful + corner).
102 forecasting passed, 88 cross-module passed.

Refs #1871
2026-06-22 19:06:22 +05:00
..
__init__.py feat(forecasting): §13 report assembler (#988, 955-A2) (#1021) 2026-06-03 08:51:23 +00:00
affordability.py fix(week-review): backend-аудит v2 — 82 фиксов (#1660) 2026-06-17 17:13:38 +00:00
confidence_engine.py Merge remote-tracking branch 'forgejo-backend/main' into fix/sf-feedback-batch 2026-06-18 10:01:43 +03:00
demand_normalization.py perf(forecast): per-request memoization cache for §22 cold build (#1129) 2026-06-08 05:26:27 +00:00
demand_supply_forecast.py fix(forecasting): propagate confounded flag DemandSupplyForecast → §15 (#1222) 2026-06-13 15:02:50 +05:00
macro_coefficient.py feat(macro): CBR inflation (ИПЦ YoY) -> macro_indicator + activate §9.5 channel (#946) 2026-06-08 11:41:14 +05:00
macro_series.py feat(macro): CBR inflation (ИПЦ YoY) -> macro_indicator + activate §9.5 channel (#946) 2026-06-08 11:41:14 +05:00
normalize.py fix(forecasting): count non-zero observations in normalize guard, not zero-filled buckets (#1638) 2026-06-17 20:39:00 +03:00
orchestrator.py fix(forecasting): honest scenarios collapse when β rate-sensitivity gate fails (audit #1871 P1) 2026-06-22 19:06:22 +05:00
product_scoring.py merge: resolve conflicts with main (#1660) into week-review-finish 2026-06-17 20:21:06 +03:00
rate_sensitivity.py feat(forecasting): seasonal (month-of-year) demand normalization (#979) 2026-06-04 11:19:50 +05:00
recommendation.py Merge pull request 'feat(site-finder): продуктовые решения по фидбеку analyze (#1741-1745)' (#1749) from fix/sf-product-decisions into main 2026-06-18 08:43:43 +00:00
regression.py fix(week-review): backend-аудит v2 — 82 фиксов (#1660) 2026-06-17 17:13:38 +00:00
report.py fix(forecasting): honest scenarios collapse when β rate-sensitivity gate fails (audit #1871 P1) 2026-06-22 19:06:22 +05:00
report_assembler.py fix(forecasting): honest scenarios collapse when β rate-sensitivity gate fails (audit #1871 P1) 2026-06-22 19:06:22 +05:00
sales_series.py perf(forecast): per-request memoization cache for §22 cold build (#1129) 2026-06-08 05:26:27 +00:00
scenarios.py fix(forecasting): honest scenarios collapse when β rate-sensitivity gate fails (audit #1871 P1) 2026-06-22 19:06:22 +05:00
special_indices.py fix(forecasting): correct _geo_weight decay/floor so far projects get low weight (#1633) 2026-06-17 20:44:00 +03:00
what_to_build.py feat(site-finder): продуктовые решения по фидбеку analyze (#1741 #1742 #1743 #1744 #1745) 2026-06-18 12:18:04 +05:00