[medium] _score_label игнорирует порог 'хорошо'=25 — участки со score 15..25 помечены 'хорошо' вместо 'средне' #1357

Closed
opened 2026-06-14 18:09:04 +00:00 by bot-backend · 1 comment
Collaborator

Описание

SCORE_THRESHOLDS определяет 4 порога {плохо:5, средне:15, хорошо:25, отлично:40}, но _score_label использует только 5, 15 и 40. Ветка после первого if сразу возвращает 'хорошо' для всего диапазона [15,40), порог 'хорошо'=25.0 — мёртвый код. По комментарию (parcels.py:129) типичный городской score 15-30, то есть БОЛЬШИНСТВО реальных участков ЕКБ попадает в [15,25) и получает завышенную метку 'хорошо' вместо ожидаемой 'средне'. score_label идёт в ответ и в persisted run.

Корень

Функция реализует 3 ветки вместо 4 — порог 25 нигде не сравнивается. Границы не приведены в соответствие со словарём порогов.

Evidence

parcels.py:130, 144-148:

SCORE_THRESHOLDS = {"плохо": 5.0, "средне": 15.0, "хорошо": 25.0, "отлично": 40.0}

def _score_label(s: float) -> str:
    if s < SCORE_THRESHOLDS["средне"]:
        return "плохо" if s < SCORE_THRESHOLDS["плохо"] else "средне"
    return "хорошо" if s < SCORE_THRESHOLDS["отлично"] else "отлично"
# порог 'хорошо'=25.0 нигде не сравнивается

Suggested fix

Учесть порог 'хорошо', разбив на 4 ветки и зафиксировав намерение границ:

if s < SCORE_THRESHOLDS["плохо"]: return "плохо"
elif s < SCORE_THRESHOLDS["средне"]: return "средне"
elif s < SCORE_THRESHOLDS["хорошо"]: return "средне"  # или иное — явно зафиксировать
elif s < SCORE_THRESHOLDS["отлично"]: return "хорошо"
else: return "отлично"

Устранить мёртвый порог 25, привести границы в соответствие со значениями словаря.

Обоснование severity (medium)

Данные не теряются, но user-facing интерпретация score искажена для большей части входных данных (типичный ЕКБ-диапазон). Метка идёт в ответ и в persisted run. Confidence 0.97.


week ревью 1 · multi-agent аудит 2026-06-14 · severity=medium · category=logic

Затронутые файлы:

  • /Users/anton/Птица/gendesign/backend/app/api/v1/parcels.py
## Описание `SCORE_THRESHOLDS` определяет 4 порога `{плохо:5, средне:15, хорошо:25, отлично:40}`, но `_score_label` использует только 5, 15 и 40. Ветка после первого `if` сразу возвращает 'хорошо' для всего диапазона [15,40), порог 'хорошо'=25.0 — мёртвый код. По комментарию (parcels.py:129) типичный городской score 15-30, то есть БОЛЬШИНСТВО реальных участков ЕКБ попадает в [15,25) и получает завышенную метку 'хорошо' вместо ожидаемой 'средне'. `score_label` идёт в ответ и в persisted run. ## Корень Функция реализует 3 ветки вместо 4 — порог 25 нигде не сравнивается. Границы не приведены в соответствие со словарём порогов. ## Evidence `parcels.py:130, 144-148`: ```python SCORE_THRESHOLDS = {"плохо": 5.0, "средне": 15.0, "хорошо": 25.0, "отлично": 40.0} def _score_label(s: float) -> str: if s < SCORE_THRESHOLDS["средне"]: return "плохо" if s < SCORE_THRESHOLDS["плохо"] else "средне" return "хорошо" if s < SCORE_THRESHOLDS["отлично"] else "отлично" # порог 'хорошо'=25.0 нигде не сравнивается ``` ## Suggested fix Учесть порог 'хорошо', разбив на 4 ветки и зафиксировав намерение границ: ```python if s < SCORE_THRESHOLDS["плохо"]: return "плохо" elif s < SCORE_THRESHOLDS["средне"]: return "средне" elif s < SCORE_THRESHOLDS["хорошо"]: return "средне" # или иное — явно зафиксировать elif s < SCORE_THRESHOLDS["отлично"]: return "хорошо" else: return "отлично" ``` Устранить мёртвый порог 25, привести границы в соответствие со значениями словаря. ## Обоснование severity (medium) Данные не теряются, но user-facing интерпретация score искажена для большей части входных данных (типичный ЕКБ-диапазон). Метка идёт в ответ и в persisted run. Confidence 0.97. --- _week ревью 1 · multi-agent аудит 2026-06-14 · severity=**medium** · category=`logic`_ Затронутые файлы: - `/Users/anton/Птица/gendesign/backend/app/api/v1/parcels.py`
bot-backend added the
week ревью 1
label 2026-06-14 18:09:04 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:01:52 +00:00
Owner

🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)

Текущее состояние кода: backend/app/api/v1/parcels.py:126 SCORE_THRESHOLDS = {"плохо": 5.0, "средне": 15.0, "хорошо": 25.0, "отлично": 40.0}. _score_label (140-144):

def _score_label(s: float) -> str:
    if s < SCORE_THRESHOLDS["средне"]:        # < 15
        return "плохо" if s < SCORE_THRESHOLDS["плохо"] else "средне"
    return "хорошо" if s < SCORE_THRESHOLDS["отлично"] else "отлично"   # [15,40) → "хорошо"

Порог "хорошо"=25.0 нигде не сравнивается — мёртвый код. Весь диапазон [15,40) сразу получает "хорошо". _score_label(score_final) идёт в ответ и в persisted run (parcels.py:2676 "score_label": _score_label(score_final)). (Идентично на forgejo/main и в рабочей ветке.)

Корень: Функция реализует 3 ветки вместо 4 порогов словаря. Типичный городской score ЕКБ 15-30 (комментарий рядом) → большинство участков в [15,25) метятся «хорошо» вместо ожидаемой «средне».

Что править:

  • Разбить на 4 ветки с явным сравнением порога 25, например:
if s < SCORE_THRESHOLDS["плохо"]: return "плохо"
if s < SCORE_THRESHOLDS["средне"]: return "средне"
if s < SCORE_THRESHOLDS["хорошо"]: return "средне"   # [15,25) — зафиксировать намерение
if s < SCORE_THRESHOLDS["отлично"]: return "хорошо"  # [25,40)
return "отлично"

Семантику границы [15,25) («средне» vs «хорошо») подтвердить у владельца — issue предлагает «средне».

Что посмотреть:

  • Код: backend/app/api/v1/parcels.py:140-144 (_score_label), 126 (SCORE_THRESHOLDS), 2676 (call site → ответ + persist). Тест: параметризованный на границах 5/15/25/40.
  • Vault: релевантных заметок не найдено.
**🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)** **Текущее состояние кода:** `backend/app/api/v1/parcels.py:126` `SCORE_THRESHOLDS = {"плохо": 5.0, "средне": 15.0, "хорошо": 25.0, "отлично": 40.0}`. `_score_label` (140-144): ```python def _score_label(s: float) -> str: if s < SCORE_THRESHOLDS["средне"]: # < 15 return "плохо" if s < SCORE_THRESHOLDS["плохо"] else "средне" return "хорошо" if s < SCORE_THRESHOLDS["отлично"] else "отлично" # [15,40) → "хорошо" ``` Порог `"хорошо"=25.0` нигде не сравнивается — мёртвый код. Весь диапазон [15,40) сразу получает `"хорошо"`. `_score_label(score_final)` идёт в ответ и в persisted run (`parcels.py:2676` `"score_label": _score_label(score_final)`). (Идентично на `forgejo/main` и в рабочей ветке.) **Корень:** Функция реализует 3 ветки вместо 4 порогов словаря. Типичный городской score ЕКБ 15-30 (комментарий рядом) → большинство участков в [15,25) метятся «хорошо» вместо ожидаемой «средне». **Что править:** - Разбить на 4 ветки с явным сравнением порога 25, например: ```python if s < SCORE_THRESHOLDS["плохо"]: return "плохо" if s < SCORE_THRESHOLDS["средне"]: return "средне" if s < SCORE_THRESHOLDS["хорошо"]: return "средне" # [15,25) — зафиксировать намерение if s < SCORE_THRESHOLDS["отлично"]: return "хорошо" # [25,40) return "отлично" ``` Семантику границы [15,25) («средне» vs «хорошо») подтвердить у владельца — issue предлагает «средне». **Что посмотреть:** - Код: `backend/app/api/v1/parcels.py:140-144` (`_score_label`), 126 (`SCORE_THRESHOLDS`), 2676 (call site → ответ + persist). Тест: параметризованный на границах 5/15/25/40. - Vault: релевантных заметок не найдено.
bot-backend added the
needs-human
label 2026-06-15 16:44:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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#1357
No description provided.