Домклик: число собственников снова читается, жилая площадь и балконы не стираются переобходом, нули в площадях — не площадь #3569

Merged
bot-backend merged 3 commits from fix/domclick-card-fields into main 2026-09-17 10:05:10 +00:00
Collaborator

#3252 — что карточка Домклика отдаёт и что мы теряем

Как проверял. 17.09 браузером снял window.__SSR_STATE__ целиком с трёх живых карточек ЕКБ (2078784457, 2078257603, 2074362051) и сравнил с тем, что парсер читает и что лежит на проде у этих же объявлений (listings 10546614, 10546608, 10819282, обогащены 14.09). Прод — только SELECT в read-only транзакции.

Дыра 1. Число собственников не читалось никогда с 29.08

  • Было: в живом стейте egrnData.owners_count = {"status": "success", "value": 2} — обёртка, а не число. Парсер делал int() от словаря и молча получал None.
  • Улики: на проде owners_count заполнен у 5075 из 6296 карточек ручного прогона 18.07 (там обёртку разворачивали, scripts/domclick_local_runner.py::_extract_owners_count) и у 0 из ~2970 карточек, обогащённых с 29.08. Той же обёрткой приходят area и floor: raw_payload.egrn_area у 2156 строк лежит как {"value": 78.1, "status": "success"}.
  • Сделано: _egrn_value() берёт value при любом статусе. Статус — это сверка с объявлением (у 2078257603 area: {status: error, value: 65.3} при площади объявления 67.4), а значение — сам факт из ЕГРН. Ключ egrnData.area подтверждён, гадания rosreestrArea/object_area удалены. В raw_payload.egrn_area обёртка остаётся как есть.
  • В tests/scrapers/test_domclick_detail.py фикстура «ground truth» держала egrnData скалярами — вот тест и не замечал. Поправил на живую форму.

Дыра 2. Ноль вместо «не указано» в площадях

  • Было: у 2078257603 в стейте kitchenArea: 0, livingArea: 0 (ремонт пустой, так Домклик пишет «не указано»). Парсер клал 0.00 в колонку, а COALESCE(:new, old) ещё и затирал нулём ранее известную площадь.
  • Улики (прод): kitchen_area_m2 = 0 — 303 строки, living_area_m2 = 0 — 84, только domklik, все обогащены 26.08–14.09. У avito/cian/yandex/n1 нулей нет. У прогона 18.07 нулей тоже нет: там стоял _pos_float.
  • Сделано: _pos_float для обеих площадей. Миграция 320: у domklik нулевые площади → NULL, ожидаемо 303 + 84 строки, при повторном запуске ничего не меняет. Проверил на локальной схеме: domklik 0/0 → NULL/NULL, domklik 12.5/0 → 12.5/NULL, avito 0/0 не тронут, второй прогон — UPDATE 0.

Дыра 3. Жилую площадь и балконы стирал переобход выдачи

  • Было: в scraper_kit/base.py апсерт писал living_area_m2 = EXCLUDED.living_area_m2 и balconies_count = EXCLUDED.balconies_count с пометкой «Cian-specific». Выдача Домклика и Авито этих полей не отдаёт, поэтому каждый переобход ставил NULL поверх того, что добыла карточка. Та же болезнь, что #3063, соседние kitchen_area_m2/phones уже под COALESCE.
  • Улики: у 10819282 в живом стейте livingArea: 25.8, balconies: 1, а на проде NULL/NULL при scraped_at 16.09 > detail_enriched_at 14.09. Разбивка по всему проду:
source переобход после карточки строк living_area_m2 balconies_count
domklik нет 4058 2990 294
domklik да 5217 0 0
avito нет 6505 4122
avito да 8639 1
cian да 7880 5910 5223

«Жилая площадь у 16 из 3061 активных» из текста issue — это и есть переобход, а не нехватка добора.

  • Сделано: COALESCE для этих двух колонок в SET, в правой части гейта #2992 (иначе строка считалась бы изменившейся на каждом проходе) и в reconcile-UPDATE при дрейфе dedup_hash. bedrooms/loggias/cadastral_*/description_minhash не трогал: карточки Домклика и Авито их не пишут, улик нет.

Что по #3252 НЕ сделано (поэтому без Closes)

  • П.3 issue — «решить по каждому неиспользуемому полю». Это решение продукта, не парсера. В живом стейте не забираем: egrnData.floor {status,value}; в legalOptionsisOwner, isOccupied, ownerMinors, residenceMinors, encumbranceSberbank, mortgage, neighbors; в objectInfologgias, bathroom, restroom, windowView, redevelopment; в pricePredictionrentLongPricePredicted/rentShortPricePredicted и soldOffers (проданные рядом, с soldDate и ценой); в houseInfo.infolivingQuartersCount, elevatorsCount, hotWaterType, areaResidential, floors (по реестру, у 2078257603 это 27 против 25 у продавца); в productCard.house.infoceilingHeight, security, parking, yard.
  • Уже потерянное не вернётся без повторного добора. Стёртые жилые площади и owners_count у уже обогащённых карточек этим PR не восстанавливаются: detail-добор Домклика берёт только detail_enriched_at IS NULL. Перезапускать ли добор по уже обогащённым — решать владельцу.
  • Замечено, не трогал:
    • houseInfo.info бывает пустым ({} у 2078784457). Запасной путь productCard.house.wallType не существует: настоящий — house.info.wallType, но там словарь продавца («Кирпично-монолитный» против реестрового «Монолитно-кирпичный»). Если его включить, в raw_payload.wall_type окажутся два словаря.
    • balconies: 0 — неясно, «нет балкона» или «не указано».
    • Колонку building_cadastral_number пишет cadastral_geo_match, а апсерт перезаписывает её сырым EXCLUDED — форма та же, что в дыре 3. Цифрами не проверял.

#3253 п.3 — годится ли domclick_building_guid ключом дома (замер, кода нет)

Пункты 1, 2 и 4 закрыты в #3356. Замер по проду 17.09, только SELECT: 9090 объявлений с guid, из них 9052 с house_id_fk, 3784 guid.

  • На стороне Домклика guid ≈ здание. 3771 из 3784 guid дают один адрес объявления. Остальные 13 — написание одного и того же дома («Уктус м-н, 9» / «Уктус м-н, светлый микрорайон, 9»), кроме одного «Машинная 4 / 4а». Обратно: 3793 адреса из 3795 — один guid, 2 адреса (Машинная 4, Монтёрская 8/2) — по два guid на 0 м.
  • 121 guid ведёт в 2 наших дома. 86 пар ближе 30 м — дубли одного здания в houses (derived против domklik с тем же адресом, это #2690/#1772). 18 пар на 30–150 м, 15 на 150 м–1 км, 2 дальше 1 км: смесь дублей с плохой геокодировкой (Сурикова 24 — 371 м при одном адресе) и ошибок матчера. Под guid один адрес, а объявление приклеено к чужому дому: «Краснолесья 96» → дом «Краснолесья 14к2», «Серова 45» → «Московская 249», «Калинина 59» → «40-летия Октября 33», «Белинского 135» → «Цвиллинга 18», «Азина 31» → «Печерская 4».
  • 24 наших дома несут по 2–3 guid. В основном матчер склеил разные здания: Замятина 28 и 36, Крауля 168б и 170, Татищева 136 и 140, Викулова 28б и 28д, Машинная 1б к1 и к2, Пятницкая 57 ст1 и ст2, Красный пер. 8б и Никонова 25. Плюс вспомогательные объекты Домклика со своим guid («подземное сооружение», «объект», «хозяйственный корпус») и 2 настоящих двойных guid на один адрес.
  • Вывод: guid надёжнее нашего адресного матчинга, во всех разобранных расхождениях прав guid. Исключения — вспомогательные объекты и редкие двойные guid на адрес. Использовать ли guid в матчере и склеивать ли по нему дома (склейка необратима, см. #2690) — решение владельца, отдельной задачей. Поэтому #3253 не закрываю.

Тесты

  • tests/test_3252_domclick_card_fields.py: 3 теста разбора на урезанном живом стейте и 2 поведенческих на живом Postgres (переобход не стирает площадь и балконы; новое значение перезаписывает). Живые — в skip_allowlist.txt, в CI бегут на postgres-сервисе.
  • Весь МЕРА backend, DATABASE_URL=…localhost:5432/test, после rebase: 6228 passed, 44 skipped, rc=0. До записи живых тестов в allowlist прогон честно дал rc=1 «НЕУЧТЁННЫЙ ПРОПУСК (2)».
  • На локальной PostGIS с применёнными миграциями 001–320 (как в CI) все тесты с save_listings (включая #2992 и #3063) плюс domclick: 518 passed, rc=0.
  • ruff check app tests — чисто, ruff format --check по изменённым — чисто. В base.py ruff format заодно склеил одну уже существовавшую строку лога. packages/scraper-kit: своих тестов нет (pytest rc=5, no tests), ruff check src — чисто.

Фальсификация

Копии исходников до правки лежат рядом, после проверки восстановлены, diff -q пуст.

  • detail.py до правки → 3 failed:
    E       AssertionError: assert None == 6   (owners_count, карточка 2074362051)
    E       assert (0.0, 0.0) == (None, None)  (нулевые площади 2078257603)
    FAILED tests/scrapers/test_domclick_detail.py::test_parse_detail_html_full  (assert None == 1)
    
  • base.py до правки → 1 failed:
    E           AssertionError: assert (None, None) == (Decimal('25.80'), 1)
    FAILED tests/test_3252_domclick_card_fields.py::test_serp_rescrape_keeps_detail_living_area_and_balconies
    

Приёмка на проде (срок вердикта — 24.09.2026)

<deploy> — время деплоя этого PR.

  1. Сразу после деплоя. SELECT count(*) FROM _schema_migrations WHERE filename='320_listings_domclick_zero_area_to_null.sql' = 1, и SELECT count(*) FROM listings WHERE source='domklik' AND (kitchen_area_m2=0 OR living_area_m2=0) = 0 (было 303 + 84).
  2. Стирание, быстрее всего видно на Авито. SELECT source, count(*), count(living_area_m2) FROM listings WHERE source IN ('avito','domklik') AND detail_enriched_at > '<deploy>' AND scraped_at > detail_enriched_at + interval '1 minute' GROUP BY 1. У avito доля заполненной living_area_m2 должна быть порядка 60 % (как у непереобойдённых), а не ~0 (было 1 из 8639).
  3. Собственники. SELECT count(*), count(owners_count) FROM listings WHERE source='domklik' AND detail_enriched_at > '<deploy>'count(owners_count) > 0, ожидаемо порядка 80 %.
    Пункт 3 и domklik-часть пункта 2 требуют хотя бы одного успешного detail-прогона Домклика. На 17.09 он 3.6 суток не собирает, сторож в логе scraper пишет domclick_detail_backfill 3.6d/1d. Если к 24.09 успешного прогона не было, вердикт по ним откладывается с этой причиной.

Связано: #3063, #2992, #3356, #2690.

🤖 Generated with Claude Code

## #3252 — что карточка Домклика отдаёт и что мы теряем **Как проверял.** 17.09 браузером снял `window.__SSR_STATE__` целиком с трёх живых карточек ЕКБ (2078784457, 2078257603, 2074362051) и сравнил с тем, что парсер читает и что лежит на проде у этих же объявлений (listings 10546614, 10546608, 10819282, обогащены 14.09). Прод — только SELECT в read-only транзакции. ### Дыра 1. Число собственников не читалось никогда с 29.08 - **Было:** в живом стейте `egrnData.owners_count = {"status": "success", "value": 2}` — обёртка, а не число. Парсер делал `int()` от словаря и молча получал None. - **Улики:** на проде `owners_count` заполнен у 5075 из 6296 карточек ручного прогона 18.07 (там обёртку разворачивали, `scripts/domclick_local_runner.py::_extract_owners_count`) и у **0 из ~2970** карточек, обогащённых с 29.08. Той же обёрткой приходят `area` и `floor`: `raw_payload.egrn_area` у 2156 строк лежит как `{"value": 78.1, "status": "success"}`. - **Сделано:** `_egrn_value()` берёт `value` при любом статусе. Статус — это сверка с объявлением (у 2078257603 `area: {status: error, value: 65.3}` при площади объявления 67.4), а значение — сам факт из ЕГРН. Ключ `egrnData.area` подтверждён, гадания `rosreestrArea`/`object_area` удалены. В `raw_payload.egrn_area` обёртка остаётся как есть. - В `tests/scrapers/test_domclick_detail.py` фикстура «ground truth» держала egrnData скалярами — вот тест и не замечал. Поправил на живую форму. ### Дыра 2. Ноль вместо «не указано» в площадях - **Было:** у 2078257603 в стейте `kitchenArea: 0, livingArea: 0` (ремонт пустой, так Домклик пишет «не указано»). Парсер клал 0.00 в колонку, а `COALESCE(:new, old)` ещё и затирал нулём ранее известную площадь. - **Улики (прод):** `kitchen_area_m2 = 0` — 303 строки, `living_area_m2 = 0` — 84, **только domklik**, все обогащены 26.08–14.09. У avito/cian/yandex/n1 нулей нет. У прогона 18.07 нулей тоже нет: там стоял `_pos_float`. - **Сделано:** `_pos_float` для обеих площадей. **Миграция 320**: у domklik нулевые площади → NULL, ожидаемо 303 + 84 строки, при повторном запуске ничего не меняет. Проверил на локальной схеме: domklik 0/0 → NULL/NULL, domklik 12.5/0 → 12.5/NULL, avito 0/0 не тронут, второй прогон — `UPDATE 0`. ### Дыра 3. Жилую площадь и балконы стирал переобход выдачи - **Было:** в `scraper_kit/base.py` апсерт писал `living_area_m2 = EXCLUDED.living_area_m2` и `balconies_count = EXCLUDED.balconies_count` с пометкой «Cian-specific». Выдача Домклика и Авито этих полей не отдаёт, поэтому каждый переобход ставил NULL поверх того, что добыла карточка. Та же болезнь, что #3063, соседние `kitchen_area_m2`/`phones` уже под COALESCE. - **Улики:** у 10819282 в живом стейте `livingArea: 25.8, balconies: 1`, а на проде NULL/NULL при `scraped_at` 16.09 > `detail_enriched_at` 14.09. Разбивка по всему проду: | source | переобход после карточки | строк | living_area_m2 | balconies_count | |---|---|---|---|---| | domklik | нет | 4058 | 2990 | 294 | | domklik | да | 5217 | **0** | **0** | | avito | нет | 6505 | 4122 | — | | avito | да | 8639 | **1** | — | | cian | да | 7880 | 5910 | 5223 | «Жилая площадь у 16 из 3061 активных» из текста issue — это и есть переобход, а не нехватка добора. - **Сделано:** COALESCE для этих двух колонок в `SET`, в правой части гейта #2992 (иначе строка считалась бы изменившейся на каждом проходе) и в reconcile-UPDATE при дрейфе dedup_hash. `bedrooms/loggias/cadastral_*/description_minhash` не трогал: карточки Домклика и Авито их не пишут, улик нет. ### Что по #3252 НЕ сделано (поэтому без Closes) - **П.3 issue — «решить по каждому неиспользуемому полю».** Это решение продукта, не парсера. В живом стейте не забираем: `egrnData.floor {status,value}`; в `legalOptions` — `isOwner`, `isOccupied`, `ownerMinors`, `residenceMinors`, `encumbranceSberbank`, `mortgage`, `neighbors`; в `objectInfo` — `loggias`, `bathroom`, `restroom`, `windowView`, `redevelopment`; в `pricePrediction` — `rentLongPricePredicted`/`rentShortPricePredicted` и `soldOffers` (проданные рядом, с `soldDate` и ценой); в `houseInfo.info` — `livingQuartersCount`, `elevatorsCount`, `hotWaterType`, `areaResidential`, `floors` (по реестру, у 2078257603 это 27 против 25 у продавца); в `productCard.house.info` — `ceilingHeight`, `security`, `parking`, `yard`. - **Уже потерянное не вернётся без повторного добора.** Стёртые жилые площади и `owners_count` у уже обогащённых карточек этим PR не восстанавливаются: detail-добор Домклика берёт только `detail_enriched_at IS NULL`. Перезапускать ли добор по уже обогащённым — решать владельцу. - **Замечено, не трогал:** - `houseInfo.info` бывает пустым (`{}` у 2078784457). Запасной путь `productCard.house.wallType` не существует: настоящий — `house.info.wallType`, но там словарь продавца («Кирпично-монолитный» против реестрового «Монолитно-кирпичный»). Если его включить, в `raw_payload.wall_type` окажутся два словаря. - `balconies: 0` — неясно, «нет балкона» или «не указано». - Колонку `building_cadastral_number` пишет `cadastral_geo_match`, а апсерт перезаписывает её сырым `EXCLUDED` — форма та же, что в дыре 3. Цифрами не проверял. ## #3253 п.3 — годится ли `domclick_building_guid` ключом дома (замер, кода нет) Пункты 1, 2 и 4 закрыты в #3356. Замер по проду 17.09, только SELECT: 9090 объявлений с guid, из них 9052 с `house_id_fk`, 3784 guid. - **На стороне Домклика guid ≈ здание.** 3771 из 3784 guid дают один адрес объявления. Остальные 13 — написание одного и того же дома («Уктус м-н, 9» / «Уктус м-н, светлый микрорайон, 9»), кроме одного «Машинная 4 / 4а». Обратно: 3793 адреса из 3795 — один guid, 2 адреса (Машинная 4, Монтёрская 8/2) — по два guid на 0 м. - **121 guid ведёт в 2 наших дома.** 86 пар ближе 30 м — дубли одного здания в `houses` (derived против domklik с тем же адресом, это #2690/#1772). 18 пар на 30–150 м, 15 на 150 м–1 км, 2 дальше 1 км: смесь дублей с плохой геокодировкой (Сурикова 24 — 371 м при одном адресе) и **ошибок матчера**. Под guid один адрес, а объявление приклеено к чужому дому: «Краснолесья 96» → дом «Краснолесья 14к2», «Серова 45» → «Московская 249», «Калинина 59» → «40-летия Октября 33», «Белинского 135» → «Цвиллинга 18», «Азина 31» → «Печерская 4». - **24 наших дома несут по 2–3 guid.** В основном матчер склеил разные здания: Замятина 28 и 36, Крауля 168б и 170, Татищева 136 и 140, Викулова 28б и 28д, Машинная 1б к1 и к2, Пятницкая 57 ст1 и ст2, Красный пер. 8б и Никонова 25. Плюс вспомогательные объекты Домклика со своим guid («подземное сооружение», «объект», «хозяйственный корпус») и 2 настоящих двойных guid на один адрес. - **Вывод:** guid надёжнее нашего адресного матчинга, во всех разобранных расхождениях прав guid. Исключения — вспомогательные объекты и редкие двойные guid на адрес. Использовать ли guid в матчере и склеивать ли по нему дома (склейка необратима, см. #2690) — решение владельца, отдельной задачей. Поэтому #3253 не закрываю. ## Тесты - `tests/test_3252_domclick_card_fields.py`: 3 теста разбора на урезанном живом стейте и 2 поведенческих на живом Postgres (переобход не стирает площадь и балконы; новое значение перезаписывает). Живые — в `skip_allowlist.txt`, в CI бегут на postgres-сервисе. - Весь МЕРА backend, `DATABASE_URL=…localhost:5432/test`, после rebase: **6228 passed, 44 skipped, rc=0**. До записи живых тестов в allowlist прогон честно дал rc=1 «НЕУЧТЁННЫЙ ПРОПУСК (2)». - На локальной PostGIS с применёнными миграциями 001–320 (как в CI) все тесты с `save_listings` (включая #2992 и #3063) плюс domclick: **518 passed, rc=0**. - `ruff check app tests` — чисто, `ruff format --check` по изменённым — чисто. В `base.py` ruff format заодно склеил одну уже существовавшую строку лога. `packages/scraper-kit`: своих тестов нет (pytest rc=5, no tests), `ruff check src` — чисто. ## Фальсификация Копии исходников до правки лежат рядом, после проверки восстановлены, `diff -q` пуст. - `detail.py` до правки → **3 failed**: ``` E AssertionError: assert None == 6 (owners_count, карточка 2074362051) E assert (0.0, 0.0) == (None, None) (нулевые площади 2078257603) FAILED tests/scrapers/test_domclick_detail.py::test_parse_detail_html_full (assert None == 1) ``` - `base.py` до правки → **1 failed**: ``` E AssertionError: assert (None, None) == (Decimal('25.80'), 1) FAILED tests/test_3252_domclick_card_fields.py::test_serp_rescrape_keeps_detail_living_area_and_balconies ``` ## Приёмка на проде (срок вердикта — 24.09.2026) `<deploy>` — время деплоя этого PR. 1. **Сразу после деплоя.** `SELECT count(*) FROM _schema_migrations WHERE filename='320_listings_domclick_zero_area_to_null.sql'` = 1, и `SELECT count(*) FROM listings WHERE source='domklik' AND (kitchen_area_m2=0 OR living_area_m2=0)` = **0** (было 303 + 84). 2. **Стирание, быстрее всего видно на Авито.** `SELECT source, count(*), count(living_area_m2) FROM listings WHERE source IN ('avito','domklik') AND detail_enriched_at > '<deploy>' AND scraped_at > detail_enriched_at + interval '1 minute' GROUP BY 1`. У avito доля заполненной `living_area_m2` должна быть порядка 60 % (как у непереобойдённых), а не ~0 (было 1 из 8639). 3. **Собственники.** `SELECT count(*), count(owners_count) FROM listings WHERE source='domklik' AND detail_enriched_at > '<deploy>'` — `count(owners_count)` > 0, ожидаемо порядка 80 %. Пункт 3 и domklik-часть пункта 2 требуют хотя бы одного успешного detail-прогона Домклика. На 17.09 он 3.6 суток не собирает, сторож в логе scraper пишет `domclick_detail_backfill 3.6d/1d`. Если к 24.09 успешного прогона не было, вердикт по ним откладывается с этой причиной. Связано: #3063, #2992, #3356, #2690. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bot-backend added 1 commit 2026-09-17 08:31:34 +00:00
fix(tradein/domclick): собственники, нулевые площади и жилая площадь карточки перестали теряться (#3252)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 15s
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 4m55s
6e8c261ff8
Сверка парсера с живым __SSR_STATE__ трёх карточек (17.09) нашла три тихие дыры:

1. owners_count. egrnData отдаёт поля ЕГРН обёрткой {status, value}; int() от
   словаря молча давал None. Прод: 0 из ~2970 карточек, обогащённых с 29.08,
   против 5075 из 6296 у ручного прогона 18.07, который обёртку разворачивал.
   Ключ egrnData.area подтверждён — гадания rosreestrArea/object_area удалены,
   в raw_payload обёртка остаётся как есть (status = сверка с объявлением).
2. livingArea/kitchenArea = 0 у Домклика значит «не указано», а в колонку ложился
   0.00 и затирал известное значение. Прод: 303 кухни и 84 жилые площади = 0,
   только domklik. Разбор: _pos_float; строки: миграция 320 ставит NULL.
3. Жилую площадь и балконы стирал переобход выдачи: апсерт scraper_kit.base писал
   их сырым EXCLUDED, а SERP Домклика и Авито этих полей не отдаёт. Прод: domklik,
   переобойдённые после обогащения, living_area_m2 0 из 5217 (без переобхода
   2990 из 4058); avito 1 из 8639 (4122 из 6505). COALESCE в SET, в гейте #2992
   и на reconcile-пути.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Light1YT added 1 commit 2026-09-17 09:39:08 +00:00
Merge origin/main в fix/domclick-card-fields
Some checks failed
CI Trade-In / changes (pull_request) Successful in 12s
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 / 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) Failing after 5m46s
fc5735fd6d
Конфликт только в tradein-mvp/backend/tests/skip_allowlist.txt: обе стороны
дописали блок в одно место (#3252 — тесты апсерта карточки ДомКлика, #3385 —
миграция 310). Оставлены оба блока. Номер миграции ветки 320 не пересекается
с main (максимум там 310).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Light1YT added 1 commit 2026-09-17 09:56:11 +00:00
merge origin/main: починка красного main (#3572)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 21s
CI / changes (pull_request) Successful in 26s
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 7m54s
7350287be7
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bot-backend merged commit be1403289a into main 2026-09-17 10:05:10 +00:00
Sign in to join this conversation.
No reviewers
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#3569
No description provided.