Слияние конкурентов больше не «чёрная дыра» (баг «САПС/Метрополис»: карточка
исчезла без следа, вернуть было нечем). Теперь каждое слияние пишет событие в
autopodbor_merge_events со СНИМКОМ поглощённых карточек (имя/сайт/телефоны/
справочники), кто и когда слил.
- Таблица autopodbor_merge_events (+RLS tenant_isolation, паттерн 1:1 с sources,
rls-ревью OK; nullOnDelete на survivor_id/user_id — история не рушится).
- AutopodborCompetitorMerger::merge($tenantId,$ids,$name,$userId) пишет событие.
- GET /field/merge-events — история; POST /field/merge-events/{id}/restore —
возврат поглощённых как предложения (защита от повторного возврата).
- Фронт: панель «🕘 История слияний» + «↩ Вернуть карточку».
Бэк 428/428, фронт 12/12, Pint чистый, build ок. schema.sql канон-синк всех
таблиц автоподбора — предвыкатный TODO (вся фича migration-only в этой ветке).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Две починки в «Конкурентном поле» + превью выжившего в окне склейки:
1. Переименование конкурента (PATCH competitors/{id}) не обновляло имена
уже созданных проектов — они носят имя-снимок конкурента. Теперь при
смене имени проекты синхронизируются (syncNamesForCompetitor): меняется
только отображаемое имя, signal_identifier поставщика не трогаем.
2. Слияние дублей не пересматривало ящик выжившего. Если выжившим по
возрасту/деньгам оказывалось предложение, объединённая карточка уезжала
в «Предложения», даже когда одна из склеиваемых была в «Поле». Теперь
объединённая получает сильнейший ящик (поле > предложение > архив) —
только повышаем, никогда не понижаем.
3. Окно «Почистить поле» показывает, какая карточка останется после склейки
(survivor во duplicateGroups) — не затираем имя вслепую.
Тесты: весь блок автоподбора зелёный (426). Larastan в этой рабочей копии
падает без вывода на любом файле — среда, не код.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Кейс «Образцово»: у застройщика (СМ.Сити) один номер отдела продаж легитимно
висит на всех его ЖК (277-99-01 на 9 проектах). Прежний порог dropCrowdedKeys
(>4 карточек → «рекламный», выкинуть) прятал это, и окно «Найти дубли» не
показывало проекты застройщика — systematically (6 таких номеров в данных).
Решение владельца 05.07: порог по ТЕЛЕФОНУ (p:) убрать — клиент подтверждает
склейку вручную («Это разные»), тихой ложной склейки нет; рекламные-подменыши
и так отсекаются на сборе. Порог по АДРЕСУ (a:, бизнес-центр) оставлен.
Проверено на AutoMoney: его номер у 3 карточек — все реально Автодом24, группа
верная, монстр-группы снятие порога не даёт.
Тесты переписаны со старого поведения на новое (unit + feature), 421/421.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Кнопка «Найти и объединить дубли» на экране поля теперь ловит и предложения,
дублирующие карточки поля (scope=cross): счётчик учитывает их, окно помечает
«· предложение», объединение сливает предложение в карточку поля (выживает поле,
merger не трогали). Бэкенд оставляет только группы с ≥1 карточкой поля — пары
чисто-предложений на экране поля не мусорят.
Файл-статус сессии — docs/superpowers/findings/2026-07-05-avtopodbor-session-status.md.
Feature 154/154, фронт 32/32, Pint чистый, билд собран.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. Разворот по телефонам запускается ТОЛЬКО при наличии своего сайта (seedDomain).
Без сайта имя размыто (напр. «Южный берег» → автосервисы/гостиницы), сеедные
телефоны грязные, а разворот их лишь умножает. Доказано вживую: ДСК/СМ-сити
(сайт есть) — чисто; «Южный берег» (нет) — 70% мусора.
2. Поиск дублей научился кросс-ящик поле↔предложения (scope=cross): предложение-
дубль карточки поля теперь всплывает (merge кросс-ящик уже умеет). В выдаче
виден box каждой фирмы. Без scope — прежнее поведение (один ящик).
3. На кнопке «Найти и объединить дубли» показывается число найденных групп-дублей
(считается на загрузке, обновляется после слияния/«это разные»).
Юнит 267/267, feature 153/153, фронт 15/15.
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>