Имя проекта следует за конкурентом: после склейки дублей все проекты объединённого
получают имя выжившего конкурента, при совпадении различаем источником, а не цифрой.
Проекты не удаляются и не рвутся — меняется только имя.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Диалог дублей: селект имени среди выбранных к слиянию, по умолчанию первое.
Merger и ручка принимают опциональное имя. Обе экрана.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Конкурент хранит список элементов {name,sites,cards} - подкомпании/ЖК холдинга.
Слияние складывает элементы всех объединяемых, ничего не роняет.
Миграция бэкфилла: один элемент из текущих site_url + directory_urls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Шаг 1 «Конкурентное поле» — чекпоинт:
- Финальный проход «Найти и объединить дубли» на поле и предложениях; клиент решает по каждой группе, ничего не склеиваем молча.
- Тихая склейка только по сайту и коду справочника; телефон и людный номер у более чем 4 фирм — на решение клиента.
- Колонка phones jsonb; телефон-дубли видны уже на «Предложениях».
- Sonar даёт только имя и тип, сайт всегда через EXA; вскрываем все карточки без гейта «есть сайт».
- Яндекс-карточки через локальный Playwright параллельно; рубрика из заголовка идёт в описание.
- Фикс рекламных номеров: 2ГИС-парсер разбирает телефоны пообъектно и выкидывает рекламные кнопки с platforms/caption чужих фирм.
Тесты: автоподбор 224/224 unit, 105/105 feature; фронт-спеки зелёные. Времянки app/scripts/diag-*/probe-* в гит не входят.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>