docs(ptica): фактор уверенности называл не ту величину (#2464-H) #2878

Merged
bot-backend merged 1 commit from fix/2464-domrf-coverage-fallback into main 2026-08-13 21:21:39 +00:00
Collaborator

Что видел пользователь

В блоке уверенности прогноза:

Известные планировки и площади есть у 40% будущих проектов (средне) — от этого
зависит точность прогноза будущего предложения и конкуренции

Ни «планировки», ни «площади», ни «будущие проекты» к тому, что на самом деле посчитано,
отношения не имеют.

Что посчитано на самом деле

Фактор domrf_coverage берёт значение из двух источников по приоритету. Первый —
supply_layers.domrf_coverage — не исполнялся ни разу
: этот слот никто не заполняет, и
orchestrator._summarize_supply_layers прямо это оговаривает:

domrf_coverage здесь НЕ выводим (нет дешёвого продьюсера в сервисах) — сборщик возьмёт
fallback из analyze.market_data_coverage_pct

Значит всегда работает вторая ветка. А это
market_pulse.coverage_pct = competitors_priced / competitors_total — доля ближних ЖК
(3 км) с ценой из Objective
.

Замер на проде 13.08, analysis_runs:

анализов с market_data_coverage_pct   2074
min 0.0%   медиана 40.0%   среднее 31.7%   max 70.0%

А документация обещала «покрытие маппинга domrf↔objective, главный sparse-риск ~2.5%».
Другая величина другого порядка.

Что правится

Только то, что читает человек:

  • нота фактора: «Цена из Objective известна у 40% ближних ЖК»;
  • докстроки _coverage_factor, _domrf_coverage, шапка confidence_engine, описание
    параметра;
  • у порогов оставлена честная пометка: high=0.6 / low=0.2 подбирались под ожидавшиеся
    ~2.5%, а реальная медиана 40% — пороги стоит пересмотреть замером, отдельным заходом.
    Сейчас не трогаю: это изменило бы выдачу, а обоснования пока нет.

Значение, пороги и ключ domrf_coverage не тронуты. Ключ читает фронт
(ForecastConfidenceBlock, ConfidencePanel) как стабильный контракт — на это добавлен
отдельный тест.

Чего НЕ сделал и почему

Аудит рекомендовал убрать fallback, чтобы значение стало None и появилась честная
нота «неизвестно». Проверил по коду — так делать нельзя:

if domrf_coverage is not None:
    factors.append(_coverage_factor(domrf_coverage))

При None фактор вообще не попадает в список, а агрегат — weakest-link (худший тянет
вниз). То есть удаление fallback не добавило бы честное «низко», а убрало бы фактор и
могло бы уверенность поднять. Плюс выбрасывался бы реальный, парцель-специфичный сигнал
ради формального «неизвестно».

Правильное действие здесь — назвать величину верно, а не выбросить её.

Проверка

Тесты двусторонние. Против confidence_engine.py из main:

1 failed, 5 passed
    FAILED TestCoverageFactor::test_note_names_what_is_actually_measured
после правки: 6 passed
  • pytest tests/services/forecasting/test_confidence_engine.py — 41 passed
  • pytest tests/services/forecasting tests/services/exporters — 1319 passed, 7 skipped
  • ruff check — clean

Старый тест test_low_coverage_percent_in_note требовал "будущ" in f.note — то есть
фиксировал именно неверное утверждение. Убрал эту строку, добавил вместо неё проверку
того, что мерится на самом деле.

Осталось за скобками

Фронт маппит ключ в подпись «Данные по будущим проектам»
(ForecastConfidenceBlock.tsx:24, ConfidencePanel.tsx:21) — та же неточность в коротком
ярлыке. Не трогаю: это видимая формулировка продукта, решение за владельцем. Строка ноты
рядом теперь говорит верно.

Refs #2464

## Что видел пользователь В блоке уверенности прогноза: > Известные планировки и площади есть у **40%** будущих проектов (средне) — от этого > зависит точность прогноза будущего предложения и конкуренции Ни «планировки», ни «площади», ни «будущие проекты» к тому, что на самом деле посчитано, отношения не имеют. ## Что посчитано на самом деле Фактор `domrf_coverage` берёт значение из двух источников по приоритету. **Первый — `supply_layers.domrf_coverage` — не исполнялся ни разу**: этот слот никто не заполняет, и `orchestrator._summarize_supply_layers` прямо это оговаривает: > domrf_coverage здесь НЕ выводим (нет дешёвого продьюсера в сервисах) — сборщик возьмёт > fallback из `analyze.market_data_coverage_pct` Значит всегда работает вторая ветка. А это `market_pulse.coverage_pct = competitors_priced / competitors_total` — доля **ближних ЖК (3 км) с ценой из Objective**. Замер на проде 13.08, `analysis_runs`: ``` анализов с market_data_coverage_pct 2074 min 0.0% медиана 40.0% среднее 31.7% max 70.0% ``` А документация обещала «покрытие маппинга domrf↔objective, главный sparse-риск ~2.5%». Другая величина другого порядка. ## Что правится Только то, что читает человек: - нота фактора: «Цена из Objective известна у 40% ближних ЖК»; - докстроки `_coverage_factor`, `_domrf_coverage`, шапка `confidence_engine`, описание параметра; - у порогов оставлена честная пометка: `high=0.6 / low=0.2` подбирались под ожидавшиеся ~2.5%, а реальная медиана 40% — **пороги стоит пересмотреть замером**, отдельным заходом. Сейчас не трогаю: это изменило бы выдачу, а обоснования пока нет. **Значение, пороги и ключ `domrf_coverage` не тронуты.** Ключ читает фронт (`ForecastConfidenceBlock`, `ConfidencePanel`) как стабильный контракт — на это добавлен отдельный тест. ## Чего НЕ сделал и почему Аудит рекомендовал **убрать fallback**, чтобы значение стало `None` и появилась честная нота «неизвестно». Проверил по коду — так делать нельзя: ```python if domrf_coverage is not None: factors.append(_coverage_factor(domrf_coverage)) ``` При `None` фактор **вообще не попадает в список**, а агрегат — weakest-link (худший тянет вниз). То есть удаление fallback не добавило бы честное «низко», а **убрало бы фактор** и могло бы уверенность поднять. Плюс выбрасывался бы реальный, парцель-специфичный сигнал ради формального «неизвестно». Правильное действие здесь — назвать величину верно, а не выбросить её. ## Проверка Тесты двусторонние. Против `confidence_engine.py` из main: ``` 1 failed, 5 passed FAILED TestCoverageFactor::test_note_names_what_is_actually_measured после правки: 6 passed ``` - [x] `pytest tests/services/forecasting/test_confidence_engine.py` — 41 passed - [x] `pytest tests/services/forecasting tests/services/exporters` — 1319 passed, 7 skipped - [x] `ruff check` — clean Старый тест `test_low_coverage_percent_in_note` требовал `"будущ" in f.note` — то есть фиксировал именно неверное утверждение. Убрал эту строку, добавил вместо неё проверку того, что мерится на самом деле. ## Осталось за скобками Фронт маппит ключ в подпись «Данные по будущим проектам» (`ForecastConfidenceBlock.tsx:24`, `ConfidencePanel.tsx:21`) — та же неточность в коротком ярлыке. Не трогаю: это видимая формулировка продукта, решение за владельцем. Строка ноты рядом теперь говорит верно. Refs #2464
bot-backend added 1 commit 2026-08-13 17:45:16 +00:00
docs(ptica): фактор уверенности называл не ту величину
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 11s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m47s
CI / backend-tests (pull_request) Successful in 16m39s
ed7e9f32a1
Фактор `domrf_coverage` в §15-движке уверенности описан как «покрытие
маппинга domrf↔objective, главный sparse-риск проекта ~2.5%». Продьюсера
для этой величины НЕТ и не было: слот `supply_layers.domrf_coverage`
никто не заполняет — `orchestrator._summarize_supply_layers` это прямо
оговаривает («нет дешёвого продьюсера»).

Значение всегда приходит из второй ветки: `analyze.market_data_coverage_pct`
= competitors_priced / competitors_total, то есть доля БЛИЖНИХ ЖК (3 км)
с ценой из Objective. Замер на проде 13.08 по 2074 анализам: min 0%,
медиана 40%, среднее 31.7%, max 70% — другая величина другого порядка.

Пользователь при этом читал «Известные планировки и площади есть у 40%
будущих проектов». Ни «планировки», ни «будущих» к тому, что измерено,
отношения не имеют.

Правится ТОЛЬКО то, что читает человек: нота фактора и докстроки.
Значение, пороги и ключ `domrf_coverage` не тронуты — ключ читает фронт
(ForecastConfidenceBlock, ConfidencePanel) как стабильный контракт,
и тест это фиксирует.

Отдельно записал в комментарии у порогов: high=0.6 / low=0.2 подбирались
под ожидавшиеся ~2.5%, а реальная медиана 40% — пороги стоит пересмотреть
замером, отдельным заходом.

Чего НЕ сделал и почему: аудит предлагал убрать fallback, чтобы значение
стало None. Проверил — так нельзя: на None фактор вообще не добавляется
в список (guard `if domrf_coverage is not None`), а агрегат weakest-link,
то есть исчезновение фактора МОЖЕТ поднять уверенность. Выбросить реальный
сигнал ради «честного неизвестно» здесь было бы хуже, чем назвать его верно.

Тесты двусторонние: против confidence_engine из main падает ровно новый
test_note_names_what_is_actually_measured.

Хунки форматирования — не мои: pre-commit ruff v0.7.4 против 0.15.12 (#2864).

Refs #2464
bot-backend merged commit f600663aa0 into main 2026-08-13 21:21:39 +00:00
bot-backend deleted branch fix/2464-domrf-coverage-fallback 2026-08-13 21:21:39 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2878
No description provided.