fix(site-finder): honest POI-score label + drop duplicate MOI column (audit #1871 P2) #1877

Merged
bot-backend merged 1 commit from audit/1871-p2-invest-moi into main 2026-06-23 07:39:48 +00:00
Collaborator

Summary

Audit-issue #1871 — два 🟠 P2 disclosure-фикса + 3 consistency follow-up (по code-review).

invest_score = взвешенная POI-сумма (distance-decay + center-bonus, max-ref 40), НЕ калиброванный инвест-рейтинг (scorer.py — пустой стаб). Был мислейбл «Инвест-балл». Формулу/SCORE_MAX_REFERENCE не трогаем — только честная подпись:

  • backend score_explanation → «POI-скор (0–40, оценочный)... Не инвест-рейтинг...»
  • KpiCard — новый optional caption prop (backward-compat)
  • Section1ParcelInfo — «Инвест-балл» → «POI-скор · 0–40» + caption «оценочный»
  • legacy site-finder + CompareTable — тот же rename (CompareTable показывал тот же score как «Инвест-балл»)
  • landing app/page.tsx — «Score 0–100» → «POI-скор 0–40» (реальная шкала)
  • Section1 scoreColor — пороги 0–100 → калиброванные 0–40 (_score_label: <5 плохо · 5–15 средне · 15–25 хорошо · ≥25 отлично). Раньше хороший ~30/40 участок рисовался red прямо рядом с честным «0–40» лейблом — видимое противоречие.

MOI (months_of_inventory) математически КОРРЕКТЕН — по определению не зависит от горизонта проекции (MOI = сток / месячный темп). Не баг. Но дублировался колонкой на 4 горизонта в ForecastHorizonsBlock (116.6/116.6/117.6/117.6 — выглядело сломанным). Убрал колонку; MOI остаётся 1 раз в Section6 key_numbers. deficit_index (варьируется — информативен) сохранён.

Test plan

  • backend ruff clean (формула не тронута)
  • frontend 138 vitest passed, tsc/lint clean
  • code-reviewer (follow-up gaps применены в этом же PR)
  • post-deploy: KPI «POI-скор · 0–40 · оценочный», цвет соответствует лейблу; таблица горизонтов без MOI-колонки

Не тронуто

ptica InvestScoreBlock (уже honest — §22 overall_score /10); формула score / SCORE_MAX_REFERENCE.

Refs #1871

🤖 Generated with Claude Code

## Summary Audit-issue #1871 — два 🟠 P2 disclosure-фикса + 3 consistency follow-up (по code-review). **invest_score** = взвешенная POI-сумма (distance-decay + center-bonus, max-ref 40), **НЕ калиброванный инвест-рейтинг** (`scorer.py` — пустой стаб). Был мислейбл «Инвест-балл». Формулу/`SCORE_MAX_REFERENCE` не трогаем — только честная подпись: - backend `score_explanation` → «POI-скор (0–40, оценочный)... Не инвест-рейтинг...» - `KpiCard` — новый optional `caption` prop (backward-compat) - `Section1ParcelInfo` — «Инвест-балл» → «POI-скор · 0–40» + caption «оценочный» - `legacy site-finder` + `CompareTable` — тот же rename (CompareTable показывал тот же score как «Инвест-балл») - landing `app/page.tsx` — «Score 0–100» → «POI-скор 0–40» (реальная шкала) - **`Section1 scoreColor`** — пороги 0–100 → калиброванные 0–40 (`_score_label`: <5 плохо · 5–15 средне · 15–25 хорошо · ≥25 отлично). Раньше хороший ~30/40 участок рисовался **red** прямо рядом с честным «0–40» лейблом — видимое противоречие. **MOI** (months_of_inventory) математически **КОРРЕКТЕН** — по определению не зависит от горизонта проекции (MOI = сток / месячный темп). Не баг. Но дублировался колонкой на 4 горизонта в `ForecastHorizonsBlock` (116.6/116.6/117.6/117.6 — выглядело сломанным). Убрал колонку; MOI остаётся 1 раз в `Section6` key_numbers. `deficit_index` (варьируется — информативен) сохранён. ## Test plan - [x] backend ruff clean (формула не тронута) - [x] frontend 138 vitest passed, tsc/lint clean - [x] code-reviewer ✅ (follow-up gaps применены в этом же PR) - [ ] post-deploy: KPI «POI-скор · 0–40 · оценочный», цвет соответствует лейблу; таблица горизонтов без MOI-колонки ## Не тронуто ptica InvestScoreBlock (уже honest — §22 overall_score /10); формула score / SCORE_MAX_REFERENCE. Refs #1871 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bot-backend added 1 commit 2026-06-23 07:29:24 +00:00
fix(site-finder): honest POI-score label + drop duplicate MOI column (audit #1871 P2)
All checks were successful
CI / frontend-tests (pull_request) Successful in 1m0s
CI / openapi-codegen-check (pull_request) Successful in 1m55s
CI / backend-tests (pull_request) Successful in 9m59s
CI / changes (pull_request) Successful in 6s
589b3bfdc3
Два disclosure-фикса + 3 consistency follow-up (по code-review).

invest_score = взвешенная POI-сумма (distance-decay + center-bonus, max-ref
40), НЕ калиброванный инвест-рейтинг (scorer.py — пустой стаб). Был мислейбл
«Инвест-балл». Формулу/SCORE_MAX_REFERENCE не трогаем — только честная подпись.
- backend parcels.py: score_explanation → «POI-скор (0–40, оценочный)...
  Не инвест-рейтинг...»
- KpiCard: новый optional caption prop (backward-compat).
- Section1ParcelInfo: KPI «Инвест-балл» → «POI-скор · 0–40» + caption «оценочный».
- legacy site-finder: scoreLabel → «POI-скор · {label} · оценочный».
- CompareTable: «Инвест-балл» → «POI-скор · 0–40» (тот же score, был мислейбл).
- landing app/page.tsx: «Score 0–100» → «POI-скор 0–40» (реальная шкала).
- Section1 scoreColor: пороги 0–100 → 0–40 калиброванные (_score_label:
  <5 плохо · 5–15 средне · 15–25 хорошо · ≥25 отлично) — раньше хороший
  ~30/40 участок рисовался red рядом с честным «0–40» лейблом.

MOI (months_of_inventory) математически КОРРЕКТЕН — по определению не зависит
от горизонта проекции (MOI = сток / месячный темп). Не баг. Но дублировался
колонкой на 4 горизонта в ForecastHorizonsBlock (116.6/116.6/117.6/117.6 —
выглядело сломанным). Убрал колонку; MOI остаётся 1 раз в Section6 key_numbers.
deficit_index (варьируется) сохранён. Подчищены unused balanced/DEFICIT_BALANCE_EPS.

138 frontend vitest passed, ruff/tsc/lint clean.

Refs #1871
bot-backend merged commit bfa95e4aee into main 2026-06-23 07:39:48 +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#1877
No description provided.