5408466905
chore(frontend): regen api-types for snapshot exclude_dev param
CI / changes (pull_request) Successful in 5s
CI / frontend-tests (pull_request) Successful in 1m1s
CI / openapi-codegen-check (pull_request) Successful in 1m50s
CI / backend-tests (pull_request) Successful in 8m50s
2026-06-18 15:51:56 +03:00
2b4f80e39f
Merge pull request 'feat(site-finder): карта точек подключения (НСПД) в секции «Сети» ( #1746 part)' ( #1751 ) from fix/1746-networks-section-map into main
...
Deploy / changes (push) Successful in 9s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m45s
Deploy / deploy (push) Successful in 1m23s
Reviewed-on: #1751
2026-06-18 08:44:16 +00:00
6fe72d2374
Merge pull request 'feat(site-finder): продуктовые решения по фидбеку analyze (#1741-1745)' ( #1749 ) from fix/sf-product-decisions into main
...
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
Deploy / build-frontend (push) Has been cancelled
Reviewed-on: #1749
2026-06-18 08:43:43 +00:00
e89fd66639
feat(site-finder): карта точек подключения (НСПД) в секции «Сети» ( #1746 , доступная часть)
...
CI / changes (pull_request) Successful in 7s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 48s
CI / openapi-codegen-check (pull_request) Successful in 1m40s
Section2 «Сети и точки подключения» был только таблицей расстояний без карты — пользователь не видел ГДЕ точка. Добавлена карта (dynamic SiteMap ssr:false + useConnectionPoints + ConnectionPointsLayer/CpLayerControlPanel), label «Точки подключения и охранные зоны сетей (НСПД)», empty-state при отсутствии дампа квартала. Таблица расстояний не тронута. Frontend-only.
Полное обогащение 191-ФЗ (владелец/диаметр/мощность, единый источник истины) — остаётся за датасетом Минстроя (#1746 не закрыт целиком).
2026-06-18 12:48:23 +05:00
d93553c489
fix(site-finder): перенумеровать под-подписи Section3 4.1/4.2/4.3 под новый порядок + doc-хедеры ( #1741 хвост)
CI / changes (push) Successful in 8s
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (push) Successful in 1m17s
CI / frontend-tests (pull_request) Successful in 1m20s
CI / openapi-codegen-check (push) Successful in 2m13s
CI / openapi-codegen-check (pull_request) Successful in 1m40s
CI / backend-tests (pull_request) Successful in 9m0s
CI / backend-tests (push) Successful in 9m4s
2026-06-18 12:38:54 +05:00
8cd0620543
feat(site-finder): продуктовые решения по фидбеку analyze ( #1741 #1742 #1743 #1744 #1745 )
...
CI / changes (pull_request) Successful in 8s
CI / changes (push) Successful in 9s
CI / frontend-tests (push) Successful in 1m43s
CI / frontend-tests (pull_request) Successful in 1m59s
CI / openapi-codegen-check (push) Successful in 2m43s
CI / openapi-codegen-check (pull_request) Successful in 1m55s
CI / backend-tests (push) Successful in 9m28s
CI / backend-tests (pull_request) Successful in 9m28s
После ролевой дискуссии (аналитик×комдир×собственник):
- #1741 секции в 2 группы «Участок»→«Стройка и рынок» (Section1→4→2→3→5→6), gate-баннер вынесен НАД группой (убран дубль из Section4Estimate), nav-группы
- #1742 объяснение выбора класса: фраза-причина + мини-таблица 3 классов по deficit_index («+1 острый дефицит, −1 затоварка»). POI «обеспеченность»/market-overstock relabel — N/A (в UI не выводятся)
- #1743 «Остатки и скорость»→«Как продаётся рынок рядом» + headline-вердикт + «Темп продаж»/«Будущее предложение конкурентов (24 мес)» (убран англицизм Velocity-score/Pipeline) + интерпретированные единицы
- #1744 горизонт: caption+tooltip «пересчёт ~10-30с» + статус «Пересчитываем…»; колонки прогноза «…, квартир» + caveat advisory
- #1745 фаза1: таблица «Прогноз по всем форматам» (студия/1-5к × индекс дефицита/прогноз спроса/сигнал); backend пробросил per-format projected_demand_units + signal. Слайдеры/рубли — фаза2 после бэктеста #951
Verify: tsc 0 ошибок; py_compile; what_to_build/recommendation/report/exporter тесты pass.
Closes #1741
Closes #1742
Closes #1743
Closes #1744
Closes #1745
2026-06-18 12:18:04 +05:00
3280859170
Merge remote fix/sf-feedback-batch ( #1736 minimap test) into local
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Successful in 1m39s
CI / openapi-codegen-check (pull_request) Successful in 3m30s
CI / backend-tests (pull_request) Successful in 9m35s
2026-06-18 10:05:56 +03:00
0f9babb7ff
test(site-finder): wrap MiniMap test render in QueryClientProvider ( #1736 )
...
CI / changes (pull_request) Successful in 11s
CI / changes (push) Successful in 15s
CI / frontend-tests (push) Successful in 1m31s
CI / frontend-tests (pull_request) Successful in 1m17s
CI / openapi-codegen-check (push) Successful in 2m28s
CI / openapi-codegen-check (pull_request) Successful in 2m37s
CI / backend-tests (push) Successful in 10m32s
CI / backend-tests (pull_request) Successful in 10m34s
#1736 added useConnectionPoints (useQuery) to MiniMap, but MiniMap.test.tsx
rendered without a QueryClient -> 'No QueryClient set' (2 failing tests in CI
frontend-tests). Wrap renders in a QueryClientProvider (retry:false).
2026-06-18 10:03:48 +03:00
bcd24923b8
Merge remote-tracking branch 'forgejo-backend/main' into fix/sf-feedback-batch
2026-06-18 10:01:43 +03:00
e7342d9f98
chore(frontend): regenerate api-types.ts for forecast pdf export ( #1739 )
...
CI / changes (pull_request) Successful in 8s
CI / changes (push) Successful in 10s
CI / frontend-tests (pull_request) Failing after 1m47s
CI / frontend-tests (push) Failing after 1m55s
CI / openapi-codegen-check (pull_request) Successful in 3m11s
CI / openapi-codegen-check (push) Successful in 3m1s
CI / backend-tests (pull_request) Successful in 10m29s
CI / backend-tests (push) Successful in 10m41s
#1748 added format=pdf to the forecast export endpoint but didn't regenerate
the frontend OpenAPI types, failing CI openapi-codegen-check. Regenerated via
the CI recipe (app.openapi() dump -> openapi-typescript -> prettier).
2026-06-18 10:00:26 +03:00
b1c0ea1268
fix(site-finder): 5 дефектов из боевого фидбека analyze ( #1736 #1737 #1738 #1739 #1740 )
...
CI / changes (push) Successful in 9s
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (push) Failing after 1m50s
CI / frontend-tests (pull_request) Failing after 1m48s
CI / openapi-codegen-check (pull_request) Failing after 2m39s
CI / openapi-codegen-check (push) Failing after 2m46s
CI / backend-tests (pull_request) Successful in 9m25s
CI / backend-tests (push) Successful in 9m30s
- #1736 MiniMap: проброс useConnectionPoints → точки подключения на карте analyze (были только в /legacy)
- #1737 confidence: пронесено имя сервиса → RU-ярлык (Рынок/Будущее предложение/…) вместо «Компонент вкладывающий сервис»
- #1738 pipeline: self-exclusion субъекта (ST_DWithin 80м) — проект не считает сам себя будущим конкурентом
- #1739 PDF: snapshot_pdf обёрнут в try/except+logger.exception (причина 500 видна) + format=pdf в forecast export + font_url fallback
- #1740 gate↔recommendation: при can_build_mkd=False — gate_caveat на обоих рекомендаторах (противоречие явное, не молчит)
Verify: py_compile 5/5, tsc 0, ruff clean, pytest confidence/forecast 95 passed.
Closes #1736
Closes #1737
Closes #1738
Closes #1739
Closes #1740
2026-06-18 11:47:21 +05:00
d44f78c33e
fix(frontend): regen api-types.ts — add POI-score fields ( #1709 )
...
CI / changes (pull_request) Successful in 6s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 47s
CI / openapi-codegen-check (pull_request) Successful in 3m7s
openapi-codegen-check падал СИСТЕМНО на каждом backend-PR: committed
frontend/src/lib/api-types.ts отставал от backend OpenAPI на 2 поля,
добавленных в POI-score схемы (PR ~#1486 normalize POI weighted score),
но не перегенерённых:
- PoiScoreItem.score_contribution
- PoiScoreResponse.poi_weighted_score
Контент взят 1:1 из authoritative CI-диффа (openapi-typescript + prettier).
Возвращает gate openapi-codegen-check в зелёное для всех PR.
Refs #1709
2026-06-17 22:22:02 +03:00
7d5962e7b4
Merge pull request 'fix(site-finder): normalize POI weighted score to 0..100 on backend ( #1486 )' ( #1674 ) from fix/poi-score-scale-1486 into main
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
2026-06-17 17:54:52 +00:00
b534579e1b
fix(site-finder): correct POI-score mock shape+values, routing empty assert ( #1486 review)
...
CI / changes (pull_request) Successful in 8s
CI / changes (push) Successful in 9s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Has been skipped
CI / openapi-codegen-check (push) Has been skipped
CI / frontend-tests (pull_request) Successful in 49s
CI / openapi-codegen-check (pull_request) Failing after 1m35s
CI / backend-tests (pull_request) Failing after 8m47s
- Rename top_poi → items in poi-score.json to match PoiScoreResponse TS type
(mock was cast as PoiScoreResponse but had wrong field name → items undefined
at runtime in MOCK_POI_SCORE mode → PoiList2Gis crashed at [...items].sort)
- Recompute all score_contribution values using backend formula
(weight / _MAX_STRAIGHT_SCORE * 100, _MAX_STRAIGHT_SCORE=0.315) and
poi_weighted_score=19.9 (was 72, which was inconsistent with the new normalization)
- Add assert result.poi_weighted_score == 0.0 to test_routing_decay_empty_db
to match the straight-line empty-db assertion
- Remove stale comment in PoiList2Gis.tsx saying normalization needs fixing in
site-finder-api.ts (already done backend-side in this PR)
2026-06-17 20:47:01 +03:00
3ffba9f8a8
Merge pull request 'fix(analytics): align portfolio series to area buckets in quartirography ( #1406 )' ( #1675 ) from fix/quartirography-area-bucket-1406 into main
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
2026-06-17 17:44:58 +00:00
79c5068e96
Merge pull request 'fix(analytics): drop false market verdict from per-object Sold % KpiCard ( #1407 )' ( #1672 ) from fix/sold-pct-market-verdict-1407 into main
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
2026-06-17 17:44:47 +00:00
68eb6ded89
fix(site-finder): normalize POI weighted score to 0..100 on backend ( #1486 )
...
CI / changes (push) Successful in 10s
CI / changes (pull_request) Successful in 12s
CI / frontend-tests (push) Successful in 49s
CI / openapi-codegen-check (push) Failing after 1m45s
CI / backend-tests (push) Failing after 8m57s
CI / frontend-tests (pull_request) Successful in 45s
CI / openapi-codegen-check (pull_request) Failing after 1m37s
CI / backend-tests (pull_request) Failing after 8m53s
Backend now computes poi_weighted_score and per-POI score_contribution in
0..100 range. Normalization denominator = sum of top-7 category weights / 100
(straight-line mode) or sum of top-7 category weights (routing-decay mode).
Frontend stops reconstructing score from raw weight × 100.
2026-06-17 20:26:35 +03:00
26ae507c11
fix(analytics): align portfolio series to area buckets in quartirography ( #1406 )
...
CI / changes (push) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI / frontend-tests (push) Successful in 1m1s
CI / openapi-codegen-check (push) Successful in 1m50s
CI / backend-tests (push) Failing after 9m8s
CI / frontend-tests (pull_request) Successful in 54s
CI / openapi-codegen-check (pull_request) Successful in 1m59s
CI / backend-tests (pull_request) Failing after 8m56s
Switch portfolio source from domrf_region_aggregates (room_count_type ONE/TWO/THREE/FOUR)
to domrf_flat_area_distribution (area_bucket FROM_0_TO_25…FROM_100), aggregated into the
same 5 area buckets as the deals series. Both series now share the same axis and are
directly comparable. Frontend portfolioMap simplified to direct bucket key lookup.
2026-06-17 20:25:17 +03:00
66afac8bb3
fix(analytics): drop false market verdict from per-object Sold % KpiCard ( #1407 )
CI / changes (push) Successful in 8s
CI / openapi-codegen-check (push) Successful in 1m47s
CI / changes (pull_request) Successful in 6s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Successful in 50s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 1m4s
CI / openapi-codegen-check (pull_request) Successful in 2m19s
2026-06-17 20:22:29 +03:00
249182b678
fix(week-review): дожим ревью — #1569 , #1590 , #1642 + feat #801 MSW-preview
...
CI / frontend-tests (pull_request) Successful in 1m2s
CI / openapi-codegen-check (push) Successful in 2m13s
CI / openapi-codegen-check (pull_request) Successful in 1m45s
CI / backend-tests (push) Successful in 9m29s
CI / backend-tests (pull_request) Successful in 9m29s
CI / changes (push) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (push) Successful in 1m7s
Финиш-волна по cross-file/partial остаткам аудита + a11y-харнесс.
Полностью (4): #1569 alembic регистрирует все ORM-модели (+убран фантомный Parcel) ·
#1590 «Индекс дефицита» больше не лжёт на fallback-горизонте (report_pdf+report_md) ·
#1642 thumbs mtime-freshness (нет устаревшей миниатюры) ·
#801 /__preview/estimate mock-render для axe/lighthouse (env-gated bypass).
Частично (остаток cross-file/домен, открыты): #1593 #1635 #1640 .
needs-leha (открыт): #1650 (нужна новая миграция вьюхи supply-слоёв).
Verify: tsc --noEmit 0; py_compile OK.
Closes #1569
Closes #1590
Closes #1642
Closes #801
2026-06-17 11:24:34 +05:00
edfdd04923
fix(frontend): regen api-types.ts — rate_ms в BulkGeoEnqueueRequest
...
CI / changes (push) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (push) Successful in 59s
CI / frontend-tests (pull_request) Successful in 55s
CI / openapi-codegen-check (push) Successful in 2m5s
CI / openapi-codegen-check (pull_request) Successful in 1m32s
CI / backend-tests (push) Failing after 8m53s
CI / backend-tests (pull_request) Failing after 8m50s
Бэкенд-схема BulkGeoEnqueueRequest получила поле rate_ms (int, default 600),
но api-types.ts не был перегенерён → CI openapi-codegen-check (drift-gate) RED.
Добавлено сгенерированное поле (проверено: openapi-typescript 7.13.0 + prettier
defaults даёт байт-идентичный результат).
2026-06-15 22:32:21 +03:00
479f01ae1a
Merge remote-tracking branch 'forgejo/main' into HEAD
...
CI / changes (push) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (push) Successful in 1m7s
CI / openapi-codegen-check (push) Failing after 2m9s
CI / frontend-tests (pull_request) Successful in 1m4s
CI / openapi-codegen-check (pull_request) Failing after 1m37s
CI / backend-tests (pull_request) Failing after 9m7s
CI / backend-tests (push) Failing after 9m11s
# Conflicts:
# backend/app/services/site_finder/gate_verdict.py
2026-06-15 21:07:05 +03:00
7fd69e90cd
fix(site-finder/compare): thread velocityDataAvailable into compare columns ( #1422 )
CI / changes (push) Successful in 7s
CI / frontend-tests (push) Successful in 1m4s
CI / changes (pull_request) Successful in 15s
CI / openapi-codegen-check (push) Failing after 2m9s
CI / frontend-tests (pull_request) Successful in 1m12s
CI / openapi-codegen-check (pull_request) Failing after 1m46s
CI / backend-tests (push) Failing after 9m1s
CI / backend-tests (pull_request) Failing after 9m2s
2026-06-15 21:33:10 +05:00
8279b0ee1f
fix(week-review): cross-file добивка код-ревью ( #1338 , #1363 , #1419 , #1421 , #1424 , #1480 )
...
- #1338 concepts.py: geometry.generate вынесен в run_in_threadpool (не блокирует event loop)
- #1363 house_imv_backfill.py + scrape_pipeline.py: периодический heartbeat в долгих IMV-фазах (reap_zombies не помечает живой sweep zombie)
- #1419 site-finder-api.ts: placeholderData keepPreviousData для bbox-запроса (KPI не мигает «0/0» при пане/зуме)
- #1421 site-finder-api.ts: area_ha nullable + адаптер не подставляет 0; null-гейт потребителей EntryMap.tsx, ParcelDrawer.tsx
- #1424/#1480 EstimateResult.tsx: блок «Параметры объекта» скрыт при восстановлении по shared-ссылке (нет мусора «0 м²/Студия/Этаж 0 из 0»)
Верификация: tsc --noEmit 0 ошибок; py_compile OK.
2026-06-15 20:29:00 +05:00
86e9ea2937
fix(week-review): автофиксы код-ревью — 169 issue (label «week ревью 1»)
...
Многоагентный аудит + имплементация: один воркер на файл, точечные правки.
Верификация: py_compile (47/47 .py) + tsc --noEmit (0 ошибок). Unit-тесты
не прогонялись (окружение не поднято: rollup native dep / нет pytest-venv).
Полностью исправлено (169): #1336 , #1337 , #1339 , #1340 , #1341 , #1342 , #1343 , #1345 , #1346 , #1348 , #1349 , #1350 , #1351 , #1354 , #1356 , #1358 , #1359 , #1360 , #1362 , #1364 , #1365 , #1366 , #1367 , #1368 , #1369 , #1370 , #1371 , #1372 , #1373 , #1374 , #1375 , #1376 , #1377 , #1378 , #1379 , #1380 , #1381 , #1382 , #1384 , #1385 , #1386 , #1387 , #1388 , #1389 , #1390 , #1391 , #1392 , #1394 , #1395 , #1396 , #1397 , #1399 , #1400 , #1401 , #1402 , #1403 , #1404 , #1408 , #1409 , #1410 , #1411 , #1412 , #1413 , #1414 , #1415 , #1416 , #1417 , #1418 , #1420 , #1423 , #1425 , #1426 , #1427 , #1428 , #1429 , #1430 , #1431 , #1432 , #1433 , #1434 , #1435 , #1437 , #1438 , #1439 , #1440 , #1441 , #1442 , #1443 , #1444 , #1445 , #1446 , #1447 , #1448 , #1449 , #1450 , #1451 , #1452 , #1453 , #1454 , #1455 , #1456 , #1457 , #1458 , #1459 , #1460 , #1461 , #1462 , #1463 , #1464 , #1465 , #1466 , #1467 , #1468 , #1469 , #1471 , #1472 , #1473 , #1474 , #1476 , #1478 , #1479 , #1481 , #1482 , #1483 , #1484 , #1485 , #1487 , #1488 , #1489 , #1490 , #1491 , #1492 , #1493 , #1494 , #1495 , #1496 , #1497 , #1499 , #1500 , #1501 , #1502 , #1504 , #1505 , #1506 , #1507 , #1510 , #1514 , #1515 , #1516 , #1517 , #1518 , #1519 , #1521 , #1522 , #1523 , #1524 , #1525 , #1526 , #1527 , #1528 , #1529 , #1531 , #1532 , #1533 , #1534 , #1535 , #1536 , #1537 , #1538
Частично (9, in-file часть, остаток cross-file): #1361 , #1419 , #1422 , #1424 , #1470 , #1475 , #1477 , #1480 , #1498
Требуют cross-file (3, не тронуты): #1338 , #1363 , #1421
Пропущено (1): #1539
Не входило в партию: 22 needs-Leha issue (нужны решения владельца).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 20:21:11 +05:00
b405ae291d
feat(site-finder): additive objective_lots price fallback for competitors ( #307 OBJ-3) ( #1332 )
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 1m57s
Deploy / build-worker (push) Successful in 2m51s
Deploy / build-frontend (push) Successful in 3m6s
Deploy / deploy (push) Successful in 1m12s
2026-06-14 16:10:02 +00:00
5507bbc1a4
feat(site-finder): domrf→cad geom-match + parking_ratio конкурентов ( #96 ) ( #1327 )
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / changes (push) Has been cancelled
2026-06-14 14:49:28 +00:00
eb251ba7e7
ci(infra): coverage-gate ( #68 ) + OpenAPI codegen-assert ( #69 ) + uptime monitoring ( #75 )
...
CI / changes (push) Successful in 13s
CI / changes (pull_request) Successful in 12s
CI / frontend-tests (push) Successful in 53s
CI / openapi-codegen-check (push) Successful in 1m58s
CI / frontend-tests (pull_request) Successful in 47s
CI / openapi-codegen-check (pull_request) Successful in 1m50s
CI / backend-tests (push) Successful in 8m54s
CI / backend-tests (pull_request) Successful in 8m45s
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 2m50s
Deploy / build-frontend (push) Successful in 3m11s
Deploy / build-worker (push) Successful in 4m38s
Deploy / deploy (push) Successful in 2m1s
#68 : pytest-cov + [tool.coverage] fail_under=65 (baseline 71%), backend-tests --cov + xml.
#69 : openapi-codegen-check job (dump app.openapi() → openapi-typescript → git diff).
Job использует node_modules-pinned openapi-typescript/prettier (НЕ npx --yes latest —
иначе version-mismatch ложный diff). + regenerated api-types.ts из СВЕЖЕГО main openapi
(8288 строк, включая #73 /freshness — синхронен).
#75 : Uptime Kuma isolated stack + status.gendsgn.ru Caddy + external Telegram watchdog.
#77 : no change — build cache достаточен.
Closes #68
Closes #69
Closes #75
Closes #77
2026-06-13 23:28:06 +05:00
8107c23f18
feat(frontend): mobile responsiveness ( #66 ) + data-sources страница ( #80 )
...
CI / changes (push) Successful in 8s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Successful in 1m3s
CI / changes (pull_request) Successful in 6s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 50s
Deploy / changes (push) Has been cancelled
Deploy / build-frontend (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
#66 : responsive CSS-layer в globals.css (3-контекста <768/768-1280/>1280, не Tailwind
sm/md/lg) + ResizeObserver в ChartShell (единственный echarts импортёр → все charts
рефлоу) + class-применение (grid-collapse, nav horizontal-scroll, map-stack) на
site-finder/analytics. overflow-x guard.
#80 : /data-sources attribution-страница (OSM ODbL/ДОМ.РФ/Объектив/Open-Meteo/Росреестр/
НСПД, server component, tokens) + footer-link.
Closes #66
Closes #80
2026-06-13 23:12:31 +05:00
0b20d98b45
feat(site-finder): ЗОУИТ visual layer на Leaflet карте ( #255 )
...
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m49s
Deploy / deploy (push) Successful in 1m6s
ZouitLayer (GeoJSON-полигоны из geom_geojson, severity blocker/warning/info по keyword,
popup тип+имя) + ZouitLayerControlPanel (collapsible toggle per-severity, счётчик mappable)
+ SiteMap integration (default blocker+warning ON, info OFF, фон под POI). Graceful: нет
geom_geojson → слой/панель скрыты, текстовый NspdZouitOverlapsBlock остаётся. 10 vitest.
Closes #255
2026-06-13 17:41:08 +00:00
adc6dde015
feat(site-finder): multi-cad сравнение ( #50 ) + analytics поиск/cross-links ( #65 )
...
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m59s
Deploy / deploy (push) Successful in 1m7s
#50 : /site-finder/compare — shortlist (localStorage, SSR-guard, cap 2-5) + CompareTable
(per-row winner-highlight, reuse useParcelAnalyzeQuery per cad, hook-order stable в .map,
cache-shared). Cross-link с site-finder.
#65 : debounced search (300ms, client-side filter top-15) в DeveloperLeaderboard +
cross-link объект→Site Finder analyze. Existing developers compare не дублирован.
Closes #50
Closes #65
2026-06-13 17:14:15 +00:00
3bbbf25412
feat(concept): concept-компоненты (DrawMap/ParamsForm/VariantsResult/ResultMap/ExportButtons) ( #57 )
...
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m45s
Deploy / deploy (push) Successful in 1m3s
Дополняет UI: 5 компонентов которые импортит page.tsx (Leaflet draw, форма ConceptInput,
табы вариантов, placement-карта, экспорт). Не вошли в предыдущий commit (untracked-dir).
ConceptResultMap: Leaflet stroke #D1D5DB (CSS var не резолвится в SVG).
2026-06-13 16:42:19 +00:00
750d34d5cb
feat(concept): Concept UI Stage 1d — ввод участка + варианты ( #57 )
...
Заменяет concept/page.tsx TODO-stubs полным generative-флоу: draw-полигон или
кадастр→geom ввод участка, форма параметров ConceptInput, POST /concepts через
useMutation, табы вариантов с placement-картой + ТЭП KPI + финмодель + экспорт
(GeoJSON/CSV client-side, DXF/PDF на /concepts/export graceful 404). Типы зеркалят
concept.py; переиспользует site-finder Leaflet + analytics Section/KpiCard паттерны.
tsc + lint + build clean.
Closes #57
2026-06-13 16:42:19 +00:00
d737307022
feat(site-finder): НСПД verify deep-links + landing GenDesign vs НСПД таблица ( #97 #100 )
...
Deploy / changes (push) Successful in 5s
Deploy / build-frontend (push) Successful in 4m29s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 1m5s
#97 : nspdLinks helper (nspdMapUrl/pkkSearchUrl, encodeURIComponent) + NspdVerifyLink
компонент (var(--accent), rel=noopener) → одноклик-сверка с НСПД/ПКК в Section1
(кадастр/ЕГРН) + Section2 (инж.сети) карточках analyze.
#100 : landing — сравнительная секция «GenDesign и НСПД» (7-row таблица value-prop:
цены ДДУ/остатки/скорость/инвест-балл/прогноз/квартирография/экспорт сверх бесплатной
гос-карты) + footer deep-links.
Closes #97
Closes #100
2026-06-13 15:53:02 +00:00
84d08940c6
fix(analytics): свежая ипотечная ставка + recommend last_updated + drop dead route ( #236 #237 #251 )
...
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Successful in 3m9s
Deploy / build-backend (push) Successful in 4m12s
Deploy / build-worker (push) Successful in 5m31s
Deploy / deploy (push) Successful in 1m19s
#236 : _current_mortgage_rate сортировал cbr_mortgage_series по TEXT-полю period
лексикографически ('Январь'>'Февраль') → возвращал stale-точку. Сортировка по
parsed (year, month) + regex-guard на malformed period-строки. Остаётся на
subsidized weighted series (НЕ domrf market — иная метрика). Verified prod:
Февраль 2026 (было Январь 2026).
#237 : scope.last_updated = MAX(snapshot_date) domrf_kn_objects в recommend_mix +
подпись «данные на <дата>» в recommend page.
#251 : удалён never-implemented GET /parcels/{parcel_id} (501) + ParcelDetail схема
(frontend bare 1-сегментный route не зовёт).
Closes #236
Closes #237
Closes #251
2026-06-13 15:22:22 +00:00
414601c1d2
test(analytics): vitest для ObjectSaleChart union-months alignment ( #1246 )
...
CI / changes (push) Successful in 7s
CI / backend-tests (push) Has been skipped
CI / changes (pull_request) Successful in 6s
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 1m6s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (push) Successful in 56s
CI / frontend-tests (pull_request) Successful in 58s
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m37s
union axis sorted, per-month alignment с nulls, регрессия-guard (хвост позднего
типа не клипается), happy-path unchanged, empty-state. 5 кейсов.
2026-06-13 18:20:41 +05:00
e2c8c0e97b
fix(analytics): выровнять ObjectSaleChart серии по union месяцев всех типов ( #1246 )
...
CI / changes (push) Successful in 7s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Has been cancelled
ObjectSaleChart строил ось X из месяцев ТОЛЬКО первого типа и привязывал серии
позиционно. domrf_kn_sale_graph фетчится per-type независимо от DOM.РФ → типы
могут нести разные наборы месяцев — позиционная привязка тогда смещает бары/
линию цены и молча клипает лишние точки. Текущие prod-данные выровнены (457/457
объектов, идентичные месяцы), поэтому live-поломки нет, но код полагался на
coincidence, не invariant. Ось из union всех месяцев + маппинг значений каждого
типа по месяцу через Map (null где отсутствует), как PrinzipVelocityChart. +vitest.
Closes #1246
2026-06-13 18:20:25 +05:00
16e505326d
perf(site-finder): honour AbortSignal в poll-цикле useParcelAnalyzeQuery ( #1248 )
...
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Has been cancelled
queryFn игнорировал TanStack v5 AbortSignal: first POST /analyze, poll GET
/fetch-status и re-POST не передавали signal, цикл спал на non-abortable
setTimeout без проверки signal.aborted. При unmount / смене cad|horizon цикл
жил до 2-мин кэпа, дёргая GET /fetch-status каждые 2с + POST /analyze на каждый
ready — зомби-поллинг. Проброс signal во все 3 fetch, sleep через shared
abortableSleep (extracted из useSiteAnalysis #1242 ), throw AbortError перед
итерацией. +3 vitest (abort + happy-path).
Closes #1248
2026-06-13 13:19:50 +00:00
99c9a130bc
feat(forecast): расширить горизонт прогноза до 24 мес (ТЗ §12.1)
...
CI / changes (push) Successful in 6s
CI / frontend-tests (push) Successful in 46s
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (pull_request) Successful in 46s
CI / backend-tests (push) Successful in 6m35s
CI / backend-tests (pull_request) Successful in 6m30s
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 2m14s
Deploy / build-frontend (push) Successful in 2m55s
Deploy / build-worker (push) Successful in 4m6s
Deploy / deploy (push) Successful in 1m40s
API отвергал ?horizon=24 (422), хотя ТЗ §12.1 называет 6/12/18/24, а движок
УЖЕ считает 24 на каждом ране: _DEFAULT_HORIZONS=(6,12,18,24) во всех 6 точках
стека (orchestrator/forecast-task/demand_supply_forecast/scenarios/
special_indices/report_assembler), PIPELINE_HORIZON_MONTHS=24.
_hidden_release_fraction клампит h/18→1.0 на 24 (без переполнения),
future_supply._horizon_weight расширяет окно чисто — скрытых ≤18 потолков нет.
Чистое расширение валидатора-enum, не новая математика.
Backend: _ALLOWED_FORECAST_HORIZONS → {6,12,18,24}, Query/docstring/error-msg.
Frontend: HorizonSelector HORIZONS=[6,12,18,24] (тип horizon=number, union не нужен;
прочие потребители data-driven через meta.horizons/forecasts_by_horizon).
Тесты: API принимает 24/отвергает 30; движок-тесты доказывают h=24 осмыслен
(поля посчитаны, demand(24)>demand(18), hidden созрел, индексы в диапазонах).
Closes #944 (Q1 горизонт 24)
2026-06-13 17:27:35 +05:00
d8a2ad7854
fix(auth): отобразить роль analyst в UserMenu, расширить Role union в useMe ( #1237 )
2026-06-13 15:03:15 +05:00
fbafb1bf68
fix(landing): mirror Pydantic schema в PilotRequestModal validation ( #1240 )
...
Backend PilotRequestInput требует name min_length=2 и др., но modal
проверял только !form.name.trim(). 1-char name ('Я') проходил, backend
возвращал 422, apiFetch клал raw FastAPI JSON в Error.message, modal
рендерил его буквально для public lead form.
Patch: PILOT_LIMITS + PILOT_EMAIL_RE константы (синхр с backend),
per-field onBlur+live валидация с RU-сообщениями, minLength/maxLength
+ aria-invalid/aria-describedby, submit disabled при ошибках,
formatSubmitError → 4xx/5xx → human text. 26 vitest кейсов.
Closes #1240
2026-06-13 15:02:50 +05:00
1e2fa35c8e
fix(admin): persist JSON extra_config при свёрнутой textarea ( #1239 )
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Has been cancelled
2026-06-13 08:20:25 +00:00
01d00ec183
fix(custom-pois): invalidate canonical parcel-analyze + parcel-poi-score keys ( #1241 )
...
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Has been cancelled
useCustomPois mutations инвалидировали ['analyze', cad], а такой key
ни один useQuery не регистрирует. Canonical keys: ['parcel-analyze', cad,
horizon] и ['parcel-poi-score', cad]. Все 3 onSuccess были silent no-ops
→ скор+breakdown stale после правок кастомных POI.
Patch: analyzeKey → ['parcel-analyze', parcelCad] (prefix-only, TanStack
covers all horizons), добавлен poiScoreKey, оба инвалидируются вместе.
82/82 frontend тестов зелёные.
Closes #1241
2026-06-13 08:15:05 +00:00
67d24e9bf7
fix(analytics): ObjectSaleChart tooltip показывает полный ₽/м², не /1000 ( #1238 )
...
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Серия price делила data на 1000 без valueFormatter в tooltip → ось говорила
'тыс ₽/м²' но точки рисовались как 'обычные числа', tooltip показывал
'146' вместо '146 250 ₽/м²' (×1000 underreporting). Patch: убрал /1000
делитель, ось 'тыс ₽/м²' → '₽/м²', добавлен tooltip valueFormatter
'146 250 ₽/м²' через toLocaleString('ru'). 82/82 frontend тестов зелёные.
Closes #1238
2026-06-13 08:10:38 +00:00
931273628a
fix(site-analysis): per-call AbortController, не shared cancelledRef ( #1242 )
...
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m9s
Deploy / deploy (push) Successful in 1m10s
Конкурентные analyze делили один cancelledRef: новая мутация ставила
ref=false и воскрешала спящий poll-цикл предыдущей — лишние fetch-status/
POST analyze и setFetchingState(null) затирали баннер активного запроса.
Patch: shared boolean ref → per-call AbortController, signal проброшен
в apiFetch/apiFetchWithStatus, добавлен abortableSleep чтобы цикл
просыпался мгновенно на cancel. setFetchingState(null) guarded
signal.aborted — зомби-цикл не может перезаписать состояние актуальной
мутации. 82/82 frontend тестов зелёные.
Closes #1242
2026-06-13 07:54:10 +00:00
0a8785d548
fix(site-finder): MiniMap не клипает layer-controls — рыночные слои доступны ( #1218 )
...
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Has been cancelled
Section 1 mini-map (/site-finder/analysis/[cad] — единственная карта
страницы) оборачивал SiteMap в height:320 + overflow:hidden. SiteMap
рендерит карту фиксированной высотой 420px + ПОД ней (flow) кнопку
"Добавить POI", легенду и CpLayerControlPanel с тумблерами
competitors/pipeline/risk/opportunity/redlines. Нижние 100px карты и
ВСЕ контролы обрезались clip-обёрткой → недостижимы кликом.
visibleMarketLayers init = {"competitors"} — единственный способ
включить остальные слои (#999 zone-of-risk, #958 §12.1-13 opportunity
parcels / red lines) — те самые скрытые чекбоксы → слои физически
невозможно было включить на странице анализа, хотя данные пробрасывались
props'ами ради них.
Patch (Вариант A из issue):
- SiteMap.tsx: новый prop mapHeight?: number (default 420 — backward-
compat для /site-finder/[cad]).
- MiniMap.tsx: снято height:320 + overflow:hidden; передаём mapHeight=280
(компактнее но не клипает); только width-constraint (maxWidth 400)
на обёртке.
2 новых vitest: mapHeight=280 пробрасывается в SiteMap (mocked stub),
clipping-стили отсутствуют. 82/82 frontend тестов зелёные. tsc + lint clean.
Closes #1218
2026-06-13 05:59:42 +00:00
03e5d07907
fix(site-finder): adapt backend egrn_block → frontend ParcelEgrn ( #1217 )
...
Deploy / deploy (push) Blocked by required conditions
Deploy / build-worker (push) Has been skipped
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-frontend (push) Has been cancelled
Бэкенд /analyze отдаёт egrn_block c snake_case-ключами
permitted_use_text/land_category/ownership_type/parcel_status/
last_egrn_update_date (parcels.py:2151-2171), фронт ждёт ParcelEgrn с
vri/category/owner_type/status/last_updated (site-finder-api.ts:255).
Section1ParcelInfo делал `data.egrn as ParcelEgrn` — каст глушит TS;
6 из 10 строк таблицы ЕГРН в prod пустые. ExportButtons тем же кастом
писал пустые ячейки в CSV. egrn={} (truthy) глушил buildFallbackEgrn.
Mock-фикстура была в старой фронт-форме — маскировала баг в dev.
Patch:
- `adaptEgrn(raw, cad)` в site-finder-api.ts: маппит backend-ключи →
frontend, пустой `{}` → null. Тестируется в изоляции.
- AnalyzeResponse.egrn: ParcelEgrn|null → unknown (wire-shape).
- Section1ParcelInfo: `adaptEgrn(data.egrn, cad) ?? buildFallbackEgrn(cad)`.
- ExportButtons: пропс `egrn` (адаптированный) вместо bad-cast'а.
- mock parcel-analyze.json — на реальную backend-форму.
- 7 vitest-кейсов: backend→frontend mapping, {}→null, null/scalar→null,
partial nullable→em-dash, threading cad, пустые строки=missing.
80/80 frontend тестов зелёные. tsc + lint clean.
Closes #1217
2026-06-13 05:36:52 +00:00
9a2cf32787
fix(api): handle 204 No Content в apiFetch ( #1219 )
...
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been cancelled
apiFetch безусловно звал response.json() после !response.ok-check, что
падало SyntaxError'ом на пустом теле 204. DELETE /custom-pois/{id} и
DELETE /admin/site-finder/weight-profiles/{id} объявлены status_code=204
→ mutation promise реджектился → onSuccess/invalidateQueries не срабатывали
→ POI/профиль виден в UI до случайного рефетча, хотя реально удалён на
сервере. Silent fail для DELETE кастомных POI на SiteMap (#1219 , P2).
Fix: на 204 или пустом теле resolve'имся с undefined (аналог семантики
apiFetchWithStatus). Сигнатура Promise<T> сохранена — 80 не-204 callers
backward-compatible; два DELETE-хука уже типизированы <unknown>/<void>
и корректно игнорируют возврат.
6 новых vitest кейсов (api.test.ts): 204, empty-body-200, 200+JSON, 404,
500, regression guard. 73/73 frontend тестов зелёные, lint+tsc clean.
Closes #1219
2026-06-13 05:13:44 +00:00
df9d54b532
feat(site-finder): add opportunity-ЗУ + red-line map layers (§12.1-13, #958 )
...
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m40s
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 1m4s
Render the §12.1-13 geometry already exposed on /analyze but previously
dropped by the MiniMap adapter:
- Перспективные ЗУ (nspd_opportunity_parcels.geom_wkt) — viz-3 polygons
- Красные линии застройки (nspd_red_lines.geom_wkt) — warn dashed lines
Wired as toggles in the existing CpLayerControlPanel (Рынок group),
reusing wkt.ts (extended with LINESTRING/MULTILINESTRING for red lines).
Empty/invalid geometry renders nothing gracefully; popups RU plain-text.
§22 forecast (future_market/special_indices), ППТ-ПМТ planning polygons
and future-ЖК points carry no map-able geometry on the frontend yet — left
as backend follow-ups, not faked.
Refs #958
2026-06-09 07:19:53 +00:00
4adfef2ad0
feat(site-finder): grounded parcel-chat panel UI ( #958 )
...
CI / changes (push) Successful in 6s
CI / backend-tests (push) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (push) Successful in 45s
CI / frontend-tests (pull_request) Successful in 42s
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m43s
Deploy / deploy (push) Successful in 1m4s
CI / changes (pull_request) Successful in 6s
Chat panel on the analysis screen consuming POST /api/v1/chat/ask:
preset-intent quick-buttons (summary/what_to_build/why_forecast/risks/
scenarios), history-aware turns (cap 10), advisory badge + grounded_in
provenance + llm_used marker. Plain-text answer rendering (no HTML
injection); loading/pending/error states with retry. TanStack useMutation
(no useEffect-for-HTTP), tokens-only, Lucide icons, TS strict. Types inline
(codegen backend unreachable in env); no new dependency.
Refs #958
2026-06-08 18:08:01 +05:00