Commit graph

3748 commits

Author SHA1 Message Date
85d455e387 Merge pull request 'Красный main: тесты коридора читали настройки, которые стали константами' (#3572) from fix/main-red-corridor-settings-tests into main
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 31s
Deploy Trade-In / build-browser (push) Successful in 1m10s
Deploy Trade-In / build-frontend (push) Successful in 4m40s
Deploy Trade-In / test (push) Successful in 5m52s
Deploy Trade-In / build-backend (push) Has been cancelled
2026-09-17 09:55:42 +00:00
635381f7b8 fix(tests): красный main — тесты #3466 читали настройки, которые #3556 перевёл в константы
All checks were successful
CI Trade-In / backend-tests (pull_request) Successful in 8m23s
CI Trade-In / changes (pull_request) Successful in 14s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 20s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Семантический конфликт двух PR, смерженных 17.09 подряд. Текстового конфликта не
было, CI каждого PR был зелёным на своей голове, а объединённое дерево падало:

  test_3466_corridor_tier_a.py (2), test_estimator_radius_floor.py (2)
  AttributeError: 'Settings' object has no attribute 'estimate_corridor_clamp_slack'
  TypeError: _run_estimate() got an unexpected keyword argument 'radius_floor_factor'

#3554 (Tier A и advisory_only) писал тесты против settings.estimate_corridor_clamp_*,
а #3556 (#2380) убрал эти поля из Settings в константы CORRIDOR_CLAMP_SLACK
(estimator) и CORRIDOR_CLAMP_MIN_N (app.core.config) и снял параметр
radius_floor_factor у хелпера. Продуктовый код не затронут: в app/ старые имена
остались только в комментарии, на проде AttributeError не было. Но красный test
блокировал деплой МЕРЫ: на проде до сих пор образ до второй пачки мержей.

Тесты переведены на константы, значения прежние (0.40, 10, 0.8).
pytest tests/ — 6374 passed, 44 skipped, rc=0; ruff check/format — rc=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 14:45:54 +05:00
a130303cc9 Merge pull request 'Сайдкар МЕРЫ: зона браузера по IP узла, якорь Домклика без Яндекса, автологин Циана через пул, время навигации в логах' (#3563) from fix/browser-sidecar into main
Some checks failed
Deploy Trade-In / build-browser (push) Successful in 2m54s
Deploy Trade-In / build-frontend (push) Successful in 3m49s
Deploy Trade-In / test (push) Failing after 5m1s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Deploy Trade-In / perimeter-smoke (push) Has been skipped
Deploy Trade-In / deploy-status (push) Failing after 2s
Deploy Trade-In / changes (push) Successful in 15s
2026-09-17 09:24:11 +00:00
10c80e9e1d Merge pull request 'Скрапер: newbuilding-провайдеры без config больше не уходят мимо пула прокси, IMV Авито строит сессию общей фабрикой' (#3562) from fix/kit-providers-config into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:23:57 +00:00
1e99d91afe Merge pull request 'Сбор МЕРА: упавший прогон не висит zombie 6 часов, провалившаяся фаза не попадает в чекпоинт, проверка отмены не держит транзакцию часами' (#3561) from fix/kit-orchestration into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:23:42 +00:00
e52057e66d Merge pull request 'Авито: добор карточек больше не сжигает 1600 попыток на упавшем сайдкаре и везде ходит браузером' (#3560) from fix/avito-detail-backfill into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:23:20 +00:00
a672178bcb Merge pull request 'Оценка: дедуп склеивает улицы вида «40-летия Комсомола», пороги Tier H — в настройки для бэктеста' (#3552) from fix/estimator-analog-quality into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:23:05 +00:00
a9e5322b7a Merge pull request 'Оценка: при якоре того же дома видно, что коридор сделок цену не ограничивал' (#3554) from fix/corridor-advisory-tier-a into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:22:46 +00:00
0be4d91d30 Merge pull request 'МЕРА: настройки оценщика, которые никогда не менялись, стали кодом — 4 кластера флагов #1970' (#3556) from fix/estimator-flag-collapse into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:22:26 +00:00
6a6fc7031d Merge pull request 'Алерты GlitchTip: медленный отказ Telegram отвечает 502 и уходит в фон, а не обрывается на 10-й секунде' (#3555) from fix/glitchtip-delivery into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:22:08 +00:00
99f8525b1c Merge pull request 'Мера: о новой заявке узнаёт ответственный, а на дашборде видно, сколько оценок доходит до заявки' (#3551) from fix/lead-funnel into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
Deploy Metrics / server (push) Successful in 1m12s
Deploy Metrics / agent-apps (push) Successful in 36s
Deploy Metrics / agent-infra (push) Successful in 33s
2026-09-17 09:21:44 +00:00
57b03092ea Merge pull request 'Витрина лендинга: пустой пересчёт больше не считается успешным, а итог игры «Проверьте себя» говорит, что квартиры отобраны' (#3550) from fix/landing-showcase-and-game into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-09-17 09:21:02 +00:00
2b3602364a Merge pull request 'МЕРА: в истории цен Яндекса больше нет выдуманных «прошлых цен» в 10 и 1000 раз ниже' (#3564) from fix/yandex-price-decimal-slip into main
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / perimeter-smoke (push) Blocked by required conditions
Deploy Trade-In / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 27s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-09-17 09:17:27 +00:00
404b583682 Merge pull request 'МЕРА v2: клик по «Предыдущим оценкам» после отправки открывает выбранную оценку' (#3549) from fix/v2-history-click into main
Some checks failed
Deploy Trade-In / build-backend (push) Has been cancelled
Deploy Trade-In / build-frontend (push) Has been cancelled
Deploy Trade-In / build-browser (push) Has been cancelled
Deploy Trade-In / deploy (push) Has been cancelled
Deploy Trade-In / test (push) Has been cancelled
Deploy Trade-In / perimeter-smoke (push) Has been cancelled
Deploy Trade-In / deploy-status (push) Has been cancelled
Deploy Trade-In / changes (push) Successful in 23s
2026-09-17 09:17:00 +00:00
af5eed19f9 Merge pull request 'Бэкапы: образцы настроек ведут алерты в тему «Metrics», неработавший сторож доступности удалён' (#3559) from fix/backup-notify-topic into main
All checks were successful
Deploy / build-backend (push) Successful in 3m27s
Deploy / build-worker (push) Successful in 5m9s
Deploy / build-frontend (push) Successful in 6m7s
Deploy Infra Host / sync-infra-host (push) Successful in 7s
Deploy / deploy (push) Successful in 1m42s
Deploy / deploy-status (push) Successful in 5s
Deploy / changes (push) Successful in 17s
Deploy / perimeter-smoke (push) Successful in 1m51s
Deploy / deploy-caddy (push) Has been skipped
2026-09-17 09:16:45 +00:00
d9a5bfe71f Merge pull request 'ПТИЦА: у изъятий на участке появляется номер постановления, а таблица не удваивается' (#3568) from fix/ptica-reservation-act-number into main
Some checks failed
Deploy / deploy (push) Blocked by required conditions
Deploy / perimeter-smoke (push) Blocked by required conditions
Deploy / deploy-status (push) Blocked by required conditions
Deploy / changes (push) Successful in 14s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
2026-09-17 09:16:07 +00:00
b2394b0a0f Merge pull request 'Каталог DOM.РФ в beat: вместо обещания «вернуть после cooldown» — факт о блокировке StormWall и тест, который не даст включить молча' (#3566) from fix/ptica-domrf-waf-probe into main
Some checks failed
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 / deploy-caddy (push) Blocked by required conditions
Deploy / perimeter-smoke (push) Blocked by required conditions
Deploy / deploy-status (push) Blocked by required conditions
Deploy / changes (push) Has been cancelled
2026-09-17 09:15:47 +00:00
1812a1ed18 Merge pull request 'Метрики: правки prometheus.yml, конфига Loki, датасорсов Grafana и запросов postgres-экспортёров вступают в силу после деплоя' (#3557) from fix/metrics-deploy-reload into main
Some checks failed
Deploy / deploy (push) Blocked by required conditions
Deploy / perimeter-smoke (push) Blocked by required conditions
Deploy / deploy-status (push) Blocked by required conditions
Deploy / changes (push) Successful in 17s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Has been cancelled
Deploy / build-worker (push) Has been cancelled
Deploy Metrics / server (push) Successful in 44s
Deploy Metrics / agent-infra (push) Successful in 28s
Deploy Metrics / agent-apps (push) Successful in 31s
2026-09-17 09:15:18 +00:00
d087e3076d Merge pull request 'Мера: тревога, когда бэкенд лёг, а лэндинг ещё открывается из кэша' (#3553) from fix/mera-observability into main
Some checks failed
Deploy Metrics / agent-apps (push) Blocked by required conditions
Deploy Metrics / agent-infra (push) Blocked by required conditions
Deploy Metrics / server (push) Has been cancelled
2026-09-17 09:15:04 +00:00
2639d2a7e7 Merge remote-tracking branch 'origin/main' into fix/kit-orchestration
All checks were successful
CI Trade-In / changes (pull_request) Successful in 20s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 25s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 6m11s
2026-09-17 13:59:43 +05:00
0327af6fab Merge remote-tracking branch 'origin/main' into fix/ptica-domrf-waf-probe
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
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 / changes (pull_request) Successful in 13s
CI / frontend-tests (pull_request) Successful in 2m1s
CI / openapi-codegen-check (pull_request) Successful in 4m0s
CI / backend-tests (pull_request) Successful in 8m21s
2026-09-17 13:59:43 +05:00
69e7047398 Тесты гейта чекпоинта: частичный отказ фазы, порог в одну попытку, упавший запрос домов (#3415)
Ревью PR #3561: три мутации гейта оставались зелёными — порог `attempted >= 2`,
жадный гейт `failed >= 1` и снятый `houses_attempted += len(nb_id_list)` в ветке
«houses DB query failed». Добавлены проверки по чекпоинту:
- 1 из 2 домов отказал в каждом якоре — оба якоря в чекпоинте (контроль жадности);
- единственный дом якоря отказал — якорь не в чекпоинте (порог);
- упал запрос домов — якоря не в чекпоинте, houses_attempted == houses_failed == 2.

Код не менялся.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:58:43 +05:00
7cd15aab71 Отказ ручного сбора каталога DOM.РФ больше не советует ждать cooldown (#2443)
Ревью PR #3566: обещание таймера, убранное из beat, осталось в тексте
HTTP 400 эндпоинтов /admin/scrape/kn-catalog-objects и /kn-catalog-flats.
Отказ предлагал передать i_understand_waf_risk=true, «если WAF cooldown
прошёл», то есть подсказывал оператору обойти блокировку, которую ожидание
не снимает (зонды 20.08-01.09: StormWall, «Доступ заблокирован [403]»).

Теперь отказ называет StormWall и реальное условие: прокси и kn-прогон,
принятый по числу строк (#3307). Константа переименована в
_DOMRF_BLOCK_GUARD_MSG. Докстринги эндпоинтов и задач
scrape_kn_catalog_flats/objects больше не говорят про WAF cooldown и про
«вторник 04:00 UTC» у выключенной записи с расписанием в МСК.
api-types.ts перегенерирован как в CI-гейте openapi-codegen-check,
изменились только два докстринга.

Тесты отказа проверяют значение detail: #3307 есть, cooldown нет.
Поведение guard'а (400 без флага, задача не ставится) не менялось.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:58:31 +05:00
2e4a82dd46 Упавший прогон финализирует общий runs.mark_crashed: и ручные запуски из админки, и без дубля алерта (#1940)
Ревью PR #3561, две находки.

1. Ручные запуски из админки (avito/cian city sweep, cian_full_load,
   yandex_full_load, yandex_city_sweep) идут мимо scheduler._dispatch: в except
   был только logger.exception, и отказ «пул пуст» до try-финализатора пайплайна
   оставлял строку running до zombie. Логика финализации переехала из
   планировщика в runs.mark_crashed; её зовут планировщик и все пять ручек.

2. Обычный путь пайплайна — mark_failed и raise; планировщик звал mark_failed
   второй раз. UPDATE — no-op, но _alert_on_run_id срабатывал снова с тем же
   стриком, и на вехе лестницы в Sentry уходил дубль (+ WARNING «no-op»).
   mark_crashed сначала читает статус и финализирует только running.

Тесты по значению над двойником строки scrape_runs и боевыми mark_*:
статус banned/infra или failed после планировщика и после каждой из пяти ручек,
одна отправка в Sentry на неудаче пайплайна.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:57:34 +05:00
f48a510e94 Merge remote-tracking branch 'origin/main' into fix/estimator-flag-collapse
All checks were successful
CI Trade-In / changes (pull_request) Successful in 15s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 27s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 6m36s
2026-09-17 13:57:23 +05:00
91a075bc81 МЕРА: снимок фикстуры бэктеста снова знает пороги движка (#1970)
Ревью #3556: settings_at_capture в _write_fixture писал только поля estimate_*
из Settings. После переноса 31 порога в константы estimator.py будущая фикстура
не знала бы, с какими порогами её захватили. Теперь в снимок попадают и
числовые константы модуля (63 штуки, CORRIDOR_CLAMP_MIN_N в том числе).
replay_fixture снимок по-прежнему не читает.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:57:07 +05:00
228c5f58f9 МЕРА: тест якоря «тот же дом» проверяет веса на месте вызова (#2381)
Ревью #3556: подмена rooms_boost=1.0 на месте вызова _compute_same_building_anchor
проходила весь сьют — тест значений держит только число в константе. Новый тест
оборачивает расчёт якоря и требует боевые sigma/rooms_boost/floor_sigma/min_comps/
mad_k (прод 17.09.2026). SB_GUARDRAIL_TOL, FSD_K, SB_GATE_MAX_FSD и сдвиг
ANCHOR_TIER_C_CORRIDOR_MULT вниз по-прежнему без поведенческих тестов.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:57:05 +05:00
bc7fe9b0b9 МЕРА: тесты квартального индекса ловят пороги на месте использования (#2379)
Ревью #3556: тест значений держит число в константе, но не то, что код её читает.
Подмена min_n_deals=5 на обоих местах вызова проходила весь сьют. Хуже: Guard-2 и
bimodal-гард снимались целиком (`if False:`) при зелёном test_estimator_quarter_index —
оба теста были пустыми. Guard-2: заглушка отдавала аналогам индекс цели, factor=1.0.
Bimodal: аналоги без кадастра, поправку гасил Guard-5 (#2583) независимо от гарда.

- оба теста получили аналоги с известным уровнем 1.0 — без гарда цена сдвигается;
- границы: доля ровно 0.6 поправку даёт, индекс ровно 2.0 даёт, 2.01 — нет;
- заглушки lookup'ов пишут min_n_deals, тест требует 10 на обоих вызовах.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:57:04 +05:00
2cfc2eda08 МЕРА: переименования порогов во фронте откачены — деплой без пересборки фронта (#1970)
Три правки в комментариях tradein-mvp/frontend (имена estimate_corridor_clamp_min_n
и estimate_imv_blend_weight → константы) кода не меняли, но фильтр deploy-tradein
по tradein-mvp/frontend/** пересобирал и пересоздавал tradein-frontend ради
комментариев. Комментарии переименуются вместе с ближайшей правкой фронта
(в #3554 фронт и так пересобирается — переименование приложено к нему патчем).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:56:48 +05:00
c7a03495e2 Свип ДомКлика: корзина без сохранённых строк не попадает в чекпоинт (#2406)
Ревью PR #3561: тест таймаута фазы закреплял как контракт done_buckets == ['st'].
Лоты ДомКлика копятся в памяти и пишутся одним save_listings после всех корзин,
поэтому снятая watchdog'ом (или упавшая на save) фаза не сохраняет ничего, а
чекпоинт всё равно получал completed_buckets живого скрейпера — следующий прогон
пропускал корзину навсегда (механизм миграции 308).

Чекпоинт пополняется только если фаза дошла до конца (флаг _saved после save).
Тест развёрнут: при таймауте fetch_city и при падении save_listings
done_buckets == [], статус failed. Контроль «полный проход несёт
унаследованное ∪ пройденное» — test_3369.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:54:55 +05:00
3992d7546f Merge origin/main в fix/estimator-analog-quality
All checks were successful
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m24s
CI Trade-In / changes (pull_request) Successful in 15s
CI / changes (pull_request) Successful in 17s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:51:04 +05:00
cbf0f6dec6 docs(mera/estimator): ручки Tier H временные — вернуть в константы после бэктеста (#3234)
Ревью #3552: направление расходится с #3556/#1970, где неменявшиеся
estimate_*-настройки переводят в константы движка. Две новые ручки нужны
только для бэктеста вариантов; условие возврата записано рядом с полями,
чтобы его увидел тот, кто будет делать шаг 4 #3234.

Refs #3234

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:50:49 +05:00
45017d2535 fix(mera/estimator): дедуп различает порядковые улицы «2-я Синичкина» во всех трёх форматах (#2291, класс 4)
Что было. После «40-летия Комсомола» остались однобуквенные порядковые:
регексы требовали после «N-» минимум две буквы. Одна улица в трёх форматах
разбиралась по-разному: cian «улица 2-я Синичкина» давал ('', ''),
avito/yandex «2-я ул. Синичкина» и domklik «2-я Синичкина улица» теряли номер
('синичкина'). Потеря номера — это ложная склейка: «9-я Парковая, 5» и
«12-я Парковая, 5» получали один ключ ('парковая', '5').

Что сделано. В обоих регексах названия улицы добавлен необязательный
порядковый «N-x » перед (нумерованным) именем; формат «номер тип имя»
переставляется в «тип номер имя» до разбора. Номер дома с дефисом не тронут.

Замер на проде (tradein-postgres, SELECT, 17.09): 12 848 разных адресов с
шаблоном «цифра-дефис/пробел-буква», 29 959 объявлений. Разбор изменился у
8 713 объявлений; ни один адрес не потерял токен. Межисточниковых групп
(улица, дом) 1305 -> 1473. Из 81 прежней группы, которая распалась, 60 —
разные порядковые улицы, 3 — ложный mkr-ключ, 18 — голая и порядковая
улица в разных городах (одна — источник сам потерял номер). Гейт бэктеста
без изменений baseline.

Refs #2291

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:50:31 +05:00
8bcb025c0d Merge origin/main в fix/corridor-advisory-tier-a
All checks were successful
CI Trade-In / backend-tests (pull_request) Successful in 5m36s
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 13s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m38s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:46:11 +05:00
1a9a612a82 test(mera/estimator): тесты дедупа #2291 не трогают флаг, который #3556 удаляет
Два новых теста класса 4 ставили monkeypatch.setattr(settings,
"estimate_dedup_analogs_enabled", True). PR #3556 (#2378) удаляет это поле из
Settings, и setattr по несуществующему атрибуту падает AttributeError. CI
гоняет голову ветки, а не merge-ref, поэтому второй смерженный PR пришёл бы
зелёным и уронил main. На main флаг и так ON по умолчанию
(test_dedup_default_is_on), так что строки лишние при любом порядке мержа.

Проверено: дифф PR, наложенный на голову #3556 (31c31f8f), до правки
2 failed / 144 passed (AttributeError), после 146 passed. Тесты не стали
пустыми: откат префиксного регекса без флага даёт assert 4 == 1 и 1 == 2.

Refs #2291

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:44:45 +05:00
803ea2217b test(tradein-front): подпись коридора в v1 HeroSummary стережётся рендером (#3466)
Ревью #3554: вызов corridorAdvisoryNote в HeroSummary (корневая /trade-in)
тестом не покрывался — мутация F2 убирала аргумент estimate.analog_tier,
vitest оставался зелёным (305 passed). Покрыт был только v2 mappers.

Рендер HeroSummary по образцу thinMarketBadge.test.tsx: n=20,
advisory_only=false; same_building → подпись про дом в тексте hero,
micro_radius → подписи нет. Мутант F2 краснеет: «expected 'Секция 1 ·
Сводка…' to contain 'справочно: цена посчитана по аналогам…'».

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:44:36 +05:00
49bcfdacd6 test(tradein): граница radius-floor при n == порогу стережётся (#3466)
Ревью #3554: замена `>=` на `>` в гейте radius-floor оставляла
test_estimator_radius_floor.py зелёным — в тестах были только count=15 и
count=min_n−1. При n == min_n витрина не пишет «справочно»
(advisory_only=False), значит floor обязан поднять цену.

Новый тест: n = estimate_corridor_clamp_min_n, медиана 80k → ровно 120k,
плюс проверка, что DkpCorridor на той же границе не справочный. Мутант
`>` краснеет: «коридор из 10 сделок (ровно порог) должен поднять цену
ровно до floor=120000».

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:42:57 +05:00
7501fef5c3 fix(ptica): номер акта в land_reservation извлекается у постановлений Администрации ЕКБ (#2982)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 14s
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 2m31s
CI / backend-tests (pull_request) Successful in 6m44s
Регекс номера требовал суффикс областных актов (-ПП/-ПА/-РП/-ПГ/-ГП/-МО),
а у постановлений Администрации Екатеринбурга его нет: на проде act_number
пуст у всех 27 строк (17.09.2026).

- izyatie_ocr: номер берётся у того же акта, чью дату выбирает
  _extract_act_date (вплотную после «от DD.MM.YYYY», иначе перед ней).
  Первое «№» в теле — «Решение Думы № 60/1» или «Приказ № 746-П».
- page_reservation_parser: суффикс необязателен; номер с суффиксом не из
  списка («218-ФЗ», «746-П», «60/1») отбрасывается целиком, а не обрезается.
- izyatie_ocr_ingest: перед записью удаляется прежний разбор того же
  участка из того же документа с другим номером. act_number в ключе
  конфликта, без этого прогон положил бы 27 строк с номером рядом с 27
  строками без номера.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:24:06 +05:00
9cc23c6698 Выключить домклик-свипы 77/50 до инкрементального сохранения (#3567)
All checks were successful
Deploy Trade-In / changes (push) Successful in 16s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 4m5s
Deploy Trade-In / build-backend (push) Successful in 54s
Deploy Trade-In / deploy (push) Successful in 7m52s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 1m43s
2026-09-17 08:23:05 +00:00
b2ff92afbb beat: каталог DOM.РФ выключен из-за блокировки StormWall, а не «до cooldown» (#2443)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 13s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 17s
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 2m45s
CI / backend-tests (pull_request) Successful in 6m59s
Комментарии у закомментированных записей scrape-kn-catalog-objects-weekly и
scrape-kn-catalog-flats-weekly обещали «возврат после cooldown 24-48h
(проверить через targeted test)». Тест проведён 20.08, 27.08 и 01.09:
кулдауна нет (kn-прогоны 29-33 шли в июне, уже после «бана» 24.05), с 01.09
наш.дом.рф за StormWall отдаёт IP Poincare «Доступ заблокирован [403]».
Комментарии теперь называют факт и условие включения (прокси и принятый
kn-прогон, #3307).

Решение больше не живёт только в комментарии: тест проверяет по значению
(по task, не по ключу), что ни одна из двух задач не попала в собранное
beat-расписание, и в тексте падения ведёт в #3307.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:09:44 +05:00
e83742ac41 МЕРА: yandex-история больше не сеет цену на порядок ниже/выше текущей (#3385)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 15s
CI / changes (pull_request) Successful in 21s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m40s
Все 7 скачков ×10 в yandex-истории цен на проде (17.09) — не «сдвиг на следующем
наблюдении», как предполагал issue, а синтетический посев из gate-поля
price.previous: нижняя точка стоит ровно на 24 ч раньше второй и записана тем же
батчем. Ошибочна нижняя цена (13–37 тыс/м² против 133–375 у верхней). Ещё 4 посева
того же рода — ×175…×1000 (цена в тысячах). Ветка писателя «история есть» на проде
не записала ни одной строки: смену цены раньше неё пишет триггер
record_listing_price_change, поэтому отлов «на следующем наблюдении» там поймал бы 0.

- yandex_price_history: price.previous, отличающаяся от текущей цены в 9.5 раза и
  больше в любую сторону (или не > 0), не сеется; счётчик seed_rejected в логе.
- миграция 310: удаляет yandex-посевы по подписи батча (recorded_at совпадает,
  change_time второй точки ровно +24 ч) с тем же порогом; lock_timeout 5s,
  остановка при > 30 строк; на проде ровно 11 кандидатов, повторный прогон — 0.
- тесты по значению: посев отвергнут/сохранён на прод-ценах; настоящий файл
  миграции на живом Postgres через временную таблицу.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:04:02 +05:00
1a773554db Сайдкар: в логах /fetch появилось время целевой навигации — замер хвоста Циана (#3419)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 17s
CI / changes (pull_request) Successful in 18s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Successful in 1m47s
CI Trade-In / backend-tests (pull_request) Successful in 5m54s
Порог BROWSER_NAV_TIMEOUT_MS=60000 не с чем было сравнить: «fetch OK» писался
на DEBUG и без длительности, «fetch error» — тоже без неё, а время из
access-лога включает пейсинг (18 с у cian) и ожидание лока. За сутки до 17.09
у cian 54 TimeoutError на ~1350 страниц (90 recycle × 15), ~4 %.

Теперь _fetch_once меряет только целевую page.goto (monotonic, в finally —
и на таймауте), обе строки несут nav_ms, «fetch OK» переведён на INFO.
nav_ms=None — до цели не дошли (упал прогрев origin), прошлое число не
наследуется. Решение по порогу — после 48 ч данных, это отдельный шаг.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:00:23 +05:00
4549311720 Автологин в Циан идёт через узел пула, а не через мёртвый env-узел сайдкара (#3410)
/login сайдкара не принимал proxy из тела (_no_live_proxy(provider, None),
_ensure_browser без override), BrowserFetcher.login его не клал, а ручка
cian auto-login сознательно не брала провайдер. Итог: логин всегда шёл с
SCRAPER_PROXY_URL сайдкара — на проде это выключенный узел 9 (InvalidIP),
то есть ручка восстановления cian-сессии не работала вовсе.

- сайдкар: /login берёт proxy из тела, как /fetch (guard и _ensure_browser
  с override; crash-relaunch в _do_login сохраняет _launched_proxy);
- scraper-kit: login() кладёт в тело узел текущей аренды, как _post_fetch;
- backend: ручка передаёт _kit_proxy_provider(), как debug-карточка DomClick;
  пустой пул на проде — 503 «нет свободного узла для cian», а не 502.

Тесты #3197 про «логин без пула» переписаны на обратные утверждения.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:58:03 +05:00
808a4fb4cb refactor(tradein): IMV Авито строит curl-сессию общей фабрикой, а не своей копией (#2386)
All checks were successful
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m55s
CI Trade-In / changes (pull_request) Successful in 13s
CI / changes (pull_request) Successful in 15s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
avito/imv.py сам собирал curl_cffi AsyncSession с третьей копией
document-заголовков (_DOC_HEADERS) — из-за того, что parity-тесты патчили
curl_cffi.requests.AsyncSession, а _base импортирует класс на уровне модуля и
такой патч до него не долетает. Взят вариант B из issue: в кодовой базе уже
принят патч scraper_kit.providers._base.AsyncSession (test_scraper_proxy.py,
test_pipeline_browser_routing.py, test_kit_serp_proxy_pool.py), а вариант A
(живой lookup в _base) сломал бы эти тесты — атрибута _base.AsyncSession не стало бы.

Сессия теперь build_document_session(proxy_url, timeout=25); _DOC_HEADERS
удалён (идентичен DOCUMENT_HEADERS, проверено до правки), мёртвый
try/except ImportError убран — curl_cffi и так импортируется через _base.
Тесты патчат _base.AsyncSession; ассерт с config дополнительно фиксирует
impersonate, timeout=25 и заголовки — параметры сессии не изменились.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:57:29 +05:00
d2a31dff08 Тесты kit-свипов: таймаут якоря, дрейн и отмена посреди обхода у всех свипов, а не только у Авито (#2406)
All checks were successful
CI Trade-In / backend-tests (pull_request) Successful in 5m21s
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 15s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
После удаления legacy-пайплайна эти сценарии были заассерчены только у avito
(test_3319) и дрейн до первого якоря у yandex/cian (test_3333). Добавлено:
- таймаут якоря у cian и yandex: якорь не в чекпоинте, следующий обработан,
  errors_count растёт; таймаут фазы у domclick: завершённые корзины в чекпоинте,
  статус failed, а не done;
- SIGTERM-дрейн после первого якоря у cian и yandex: interrupted=1, в
  чекпоинте ровно первый якорь, второй не посещён;
- пользовательская отмена (is_cancelled=True) после первого якоря у avito,
  cian и yandex: второй якорь не посещён, чекпоинт на месте, без mark_done.

Проверка по строке прогона: фейковая БД мержит counters всех записей, как
jsonb-мерж в runs.py. Мутации (снятый continue/return/interrupted/errors_count
в pipeline.py) роняют ровно свой тест, 6 из 6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:57:13 +05:00
eade88bc66 fix(tradein): config обязателен в newbuilding-провайдерах Циана и Яндекса (#2385)
fetch_newbuilding, resolve_cian_zhk_url_via_search, YandexNewbuildingScraper и
resolve_yandex_jk_slug принимали config=None и в этом случае строили
BrowserFetcher(endpoint=None) мимо фабрики, а резолвер Циана — сессию без прокси.
Все боевые вызовы config уже передают, но новый вызывающий без config молча ушёл бы
на env-узел сайдкара мимо пула — именно так потеряли 8 суток в #2767 и сломались
в #3197. Теперь config обязателен по сигнатуре, запасные ветки удалены, фетчер
строит только build_browser_fetcher.

Тесты: кейсы *_without_config (ждали endpoint=None) заменены одним — без config
TypeError до сети, фетчер и сессия не строятся; остальные тестовые вызовы
получили config.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:55:32 +05:00
6be2bf9aaa fix(tradein/avito): серия отказов нашего тракта обрывает detail-добор статусом failed (#3439)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 17s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 19s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m12s
Прод: 7193, 7218, 7264, 7302 (15-16.09) и 6608/6631/6643/6662 (10.09) — по
1600 попыток, 1-10 карточек, ~1599 блоков, status='done', по 70+ минут
каждый. В те же окна в логах tradein-browser шторм «browser launch failed …
InvalidIP» и «/fetch 503». 6885 (13.09) — те же 1600 попыток при
ban_kinds {"infra": 1591}, но 'banned'.

Корень — регресс #3288/#3367: record_block(kind != platform) уходит в
record_failure(), то есть только в знаменатель окна. Числитель доли растёт
лишь на platform, safety-net смотрит на platform-серию, счётчика серии
infra нет вовсе. Серия отказов сайдкара любой длины не рвала прогон ничем,
а финализатор #3367 при одной карточке ставил 'done'.

- BlockRatioBreaker: infra_streak_limit и счётчик серии infra. Серию гасит
  любой ответ площадки — успех, её блок, 404. abort_reason() -> "infra_streak"
  (проверяется первым), abort_explanation() называет эту величину.
- avito_detail_backfill: порог = max_consecutive_failures (дефолт 25) — тот же
  разряд «отказ нашей стороны», что и отказы-не-блоки. На обрыве — mark_failed
  «тракт недоступен: N отказов … подряд без единого ответа площадки», в
  counters abort_reason=infra_streak и ban_kinds. Не 'banned' — площадка
  молчала; не через mark_backfill_finished — там одна карточка даёт 'done'.

Тесты по значению: 1 успех + 1599 отказов сайдкара -> attempted=26,
mark_failed, abort_reason=infra_streak, ban_kinds {"infra": 25}; обрыв ровно
на 25-м (24 — нет); 24 infra + ответ площадки (успех/блок/404) + 24 — не
обрыв; 24 infra + ответ, трижды — снапшот пройден; 25% настоящих блоков —
не обрыв; прежний контроль #3367 (20 infra + 10 успехов -> done) зелёный.

Фальсификация: без проводки порога — «assert (1600, 1600) == (26, 26)»; без
сброса серии на блоке площадки — «abort_reason='infra_streak': 24 + ответ
площадки (platform) + 24»; без ветки финала — «прогон ушёл в
backfill-honest-status: там 1 карточка превращает шторм в 'done'».

Пункт 3 задачи (browser_unfit узлу, на котором сайдкар не поднял браузер)
не сделан: это вердикт пула прокси и протокол сайдкара, отдельная задача.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:54:18 +05:00
fb02e41d77 Проверка отмены закрывает свою транзакцию: свип ДомКлика больше не держит горизонт vacuum на весь обход (#3480)
Виновник по живому снимку pg_stat_activity 17.09 07:48 UTC: pid 1933154 из
tradein-scraper, 'idle in transaction' 1 ч 35 мин, последний запрос
`SELECT status FROM scrape_runs WHERE id = $1` (runs.is_cancelled),
xact_start через 30 мс после старта domclick_city_sweep_moskva 7344.
По Prometheus за 03-17.09 10 из 12 окон «транзакция > 1 ч» совпадают по
началу и концу со свипами ДомКлика.

is_cancelled делал SELECT без commit, а вызывающие сразу уходят в сетевую
фазу (у ДомКлика — весь fetch_city, до 3 ч). Теперь commit после чтения —
в общей точке для всех 12 вызовов; незакоммиченных записей, рассчитанных на
откат, перед вызовами нет (перед каждым — update_heartbeat/save_listings с
commit или чтения).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:54:04 +05:00
6c5f327acd Сайдкар: якорь Домклика открывает свою выдачу напрямую, без захода через поиск Яндекса (#3263)
Выдача Яндекса капчит конкретные выходные узлы пула (замер владельца 29.08:
узлы 1/10/11 — капча, 9 и домашний IP — выдача), поэтому путь через поиск
срабатывал ~2 раза из 9 и стоил ~15 с на подъём якоря. В логах tradein-browser
15-16.09 все 7 попыток — капча, и все 7 через 0,2 с заканчивались «якорная
вкладка не поднялась (Error)». Referer карточке и так даёт переход с выдачи
площадки (detail.py: referer=origin).

Дефолт BROWSER_ANCHOR_VIA_SEARCH теперь пустой: путь через поиск остаётся,
но только по явному env. Тесты яндекс-пути включают его явно; новый тест
грузит модуль без env и проверяет, что якорь идёт прямым goto(origin).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:53:04 +05:00
a6c86e88ea fix(tradein/avito): диагноз блоков ложится в counters любого финала добора, не только 'banned' (#3288)
Пункт 5 из комментария 05.09: ban_kind пишется только у banned-прогонов, у
done/failed диагноза в БД нет. Прод: 7193, 7218, 7264, 7302 — по 1600
попыток, ~1599 блоков, status='done', counters без ban_kinds; что это были
отказы сайдкара, а не площадки, видно лишь по косвенному признаку (мелкая
block_streak_histogram считает только platform-серии). mark_backfill_finished
кладёт перепись в counters только на ветке бана.

Задача теперь кладёт counters.ban_kinds сама перед любым финализатором
(mark_backfill_finished / mark_failed пустого пула). Статусы и колонка
ban_kind не тронуты — контракты #3196/#2764 как были.

Тест по значению: 20 отказов сайдкара + 10 успехов — counters, уходящие в
финализатор, несут {"infra": 20}. Фальсификация: без строки —
«assert None == {'infra': 20}».

Стоп-кран для infra-серии (вторая половина п.5) — отдельным коммитом #3439.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:51:44 +05:00