(medium) compare/page.tsx handleResult: дедуп по подмножеству полей теряет обновления district/цены/scoreLabel/errorMsg → стейл-данные в таблице сравнения #1472

Closed
opened 2026-06-15 05:56:53 +00:00 by bot-backend · 1 comment
Collaborator

Severity: medium · Категория: data-integrity · Файл: frontend/src/app/site-finder/compare/page.tsx:40-57

compare/page.tsx:44-54 — guard в handleResult сравнивает старую и новую CompareColumn только по 6 полям (status, score, verdictLabel, velocityScore, pipeline24mo, confidenceValue) и при их равенстве делает return prev, отбрасывая обновление. Поля districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg в сравнении НЕ участвуют. Дедуп идёт по одному cad (prev[col.cad] vs col), т.е. сравниваются последовательные состояния одного столбца. Импакт: (1) поздний district-enrichment (median_price_per_m2 / district_name доезжают позже, скоринговые числа не меняются) → строка «Медиана ₽/м²» и подпись района под кадастром остаются пустыми/старыми, хотя данные пришли; (2) две подряд error-эмиссии с разным errorMsg: status==='error' равны, остальные метрики undefined===undefined → return prev, новый текст ошибки в title (CompareTable.tsx:279) не попадёт. medianPricePerM2 и districtName — видимые в сравнении значения, рассинхрон = неверные данные на экране. Чинить: добавить в guard все рендерящиеся поля (districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg) либо сравнивать по shallow-equal всех ключей CompareColumn.

Почему баг: Дедуп идёт по одному и тому же cad (prev[col.cad] vs col), т.е. сравнивает последовательные состояния одного столбца. Реальные триггеры: (1) повторный resolve того же analyze-запроса, где скоринговые числа не изменились, но district.median_price_per_m2 / district_name доехали позже (district enrichment, B1-follow-up) — строки «Медиана ₽/м²» и подпись района под кадастром останутся пустыми/старыми, хотя данные пришли; (2) две подряд error-эмиссии с разным errorMsg: status==='error' равны, а score/verdictLabel/velocityScore/pipeline24mo/confidenceValue все undefined===undefined → return prev, новый текст ошибки в title не попадёт. medianPricePerM2 и districtName — это видимые в клиентском сравнении величины, их рассинхрон = неверные данные на экране.

Как чинить: Либо сравнивать ВСЕ поля CompareColumn (включая districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg), либо убрать ручной дедуп и полагаться на то, что setState с тем же объектным содержимым не вызывает лишних ре-рендеров (или сравнивать через shallow-equal по всем ключам).


deep-audit «армия ботов 2» · verify+harden, confidence 0.9 · unit U101

**Severity:** medium · **Категория:** data-integrity · **Файл:** `frontend/src/app/site-finder/compare/page.tsx:40-57` compare/page.tsx:44-54 — guard в handleResult сравнивает старую и новую CompareColumn только по 6 полям (status, score, verdictLabel, velocityScore, pipeline24mo, confidenceValue) и при их равенстве делает `return prev`, отбрасывая обновление. Поля districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg в сравнении НЕ участвуют. Дедуп идёт по одному cad (prev[col.cad] vs col), т.е. сравниваются последовательные состояния одного столбца. Импакт: (1) поздний district-enrichment (median_price_per_m2 / district_name доезжают позже, скоринговые числа не меняются) → строка «Медиана ₽/м²» и подпись района под кадастром остаются пустыми/старыми, хотя данные пришли; (2) две подряд error-эмиссии с разным errorMsg: status==='error' равны, остальные метрики undefined===undefined → return prev, новый текст ошибки в title (CompareTable.tsx:279) не попадёт. medianPricePerM2 и districtName — видимые в сравнении значения, рассинхрон = неверные данные на экране. Чинить: добавить в guard все рендерящиеся поля (districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg) либо сравнивать по shallow-equal всех ключей CompareColumn. **Почему баг:** Дедуп идёт по одному и тому же cad (prev[col.cad] vs col), т.е. сравнивает последовательные состояния одного столбца. Реальные триггеры: (1) повторный resolve того же analyze-запроса, где скоринговые числа не изменились, но district.median_price_per_m2 / district_name доехали позже (district enrichment, B1-follow-up) — строки «Медиана ₽/м²» и подпись района под кадастром останутся пустыми/старыми, хотя данные пришли; (2) две подряд error-эмиссии с разным errorMsg: status==='error' равны, а score/verdictLabel/velocityScore/pipeline24mo/confidenceValue все undefined===undefined → return prev, новый текст ошибки в title не попадёт. medianPricePerM2 и districtName — это видимые в клиентском сравнении величины, их рассинхрон = неверные данные на экране. **Как чинить:** Либо сравнивать ВСЕ поля CompareColumn (включая districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg), либо убрать ручной дедуп и полагаться на то, что setState с тем же объектным содержимым не вызывает лишних ре-рендеров (или сравнивать через shallow-equal по всем ключам). --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.9 · unit U101</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:56:53 +00:00
bot-backend added the
scope/frontend
label 2026-06-15 11:02:10 +00:00
Owner

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

Примечание: верифицировано против forgejo/main (canonical prod). В локальной ветке feat/cian-city-sweep-schedule файла compare/page.tsx нет — он есть в main.

Текущее состояние кода (forgejo/main): frontend/src/app/site-finder/compare/page.tsx, handleResult (≈стр. 40-57): guard сравнивает старую и новую CompareColumn только по 6 полям — status, score, verdictLabel, velocityScore, pipeline24mo, confidenceValue — и при равенстве делает return prev, отбрасывая обновление. Поля districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg в сравнении НЕ участвуют. Дедуп по одному cad (prev[col.cad] vs col).

Эти 5 опущенных полей реально рендерятся (frontend/src/components/site-finder/compare/CompareTable.tsx): medianPricePerM2 стр. 140/143, scoreLabel стр. 107-110, confidenceLabel стр. 165-170, districtName стр. 240-249, errorMsg в title стр. 279 — и присутствуют в типе CompareColumn (стр. 17-28).

Корень: (1) поздний district-enrichment (median_price_per_m2/district_name доезжают позже, скоринговые числа не меняются) → строка «Медиана ₽/м²» и подпись района остаются старыми/пустыми; (2) две подряд error-эмиссии с разным errorMsg (status==='error' равны, остальные метрики undefined===undefined) → return prev, новый текст ошибки в title не попадёт.

Что править:

  • Добавить в guard все рендерящиеся поля: districtName, scoreLabel, medianPricePerM2, confidenceLabel, errorMsg (в дополнение к 6 текущим).
  • Либо заменить ручной guard shallow-equal по всем ключам CompareColumn; либо убрать дедуп и полагаться на то, что React не ре-рендерит при идентичном объектном содержимом (но тут объект всегда новый — нужен shallow-equal).

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

  • Код: compare/page.tsx:40-57 (handleResult); CompareTable.tsx:17-28 (тип), :107-110/140-143/165-170/240-249/279 (рендер опущенных полей); ParcelCompareLoader (источник эмиссий handleResult).
  • Vault: релевантных заметок не найдено.
**🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)** _Примечание: верифицировано против `forgejo/main` (canonical prod). В локальной ветке `feat/cian-city-sweep-schedule` файла `compare/page.tsx` нет — он есть в main._ **Текущее состояние кода (forgejo/main):** `frontend/src/app/site-finder/compare/page.tsx`, `handleResult` (≈стр. 40-57): guard сравнивает старую и новую `CompareColumn` только по 6 полям — `status`, `score`, `verdictLabel`, `velocityScore`, `pipeline24mo`, `confidenceValue` — и при равенстве делает `return prev`, отбрасывая обновление. Поля `districtName`, `scoreLabel`, `medianPricePerM2`, `confidenceLabel`, `errorMsg` в сравнении НЕ участвуют. Дедуп по одному `cad` (`prev[col.cad]` vs `col`). Эти 5 опущенных полей реально рендерятся (`frontend/src/components/site-finder/compare/CompareTable.tsx`): `medianPricePerM2` стр. 140/143, `scoreLabel` стр. 107-110, `confidenceLabel` стр. 165-170, `districtName` стр. 240-249, `errorMsg` в `title` стр. 279 — и присутствуют в типе `CompareColumn` (стр. 17-28). **Корень:** (1) поздний district-enrichment (`median_price_per_m2`/`district_name` доезжают позже, скоринговые числа не меняются) → строка «Медиана ₽/м²» и подпись района остаются старыми/пустыми; (2) две подряд error-эмиссии с разным `errorMsg` (status==='error' равны, остальные метрики undefined===undefined) → `return prev`, новый текст ошибки в `title` не попадёт. **Что править:** - Добавить в guard все рендерящиеся поля: `districtName`, `scoreLabel`, `medianPricePerM2`, `confidenceLabel`, `errorMsg` (в дополнение к 6 текущим). - Либо заменить ручной guard shallow-equal по всем ключам `CompareColumn`; либо убрать дедуп и полагаться на то, что React не ре-рендерит при идентичном объектном содержимом (но тут объект всегда новый — нужен shallow-equal). **Что посмотреть:** - Код: `compare/page.tsx:40-57` (`handleResult`); `CompareTable.tsx:17-28` (тип), `:107-110/140-143/165-170/240-249/279` (рендер опущенных полей); `ParcelCompareLoader` (источник эмиссий `handleResult`). - Vault: релевантных заметок не найдено.
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#1472
No description provided.