Commit Graph

1524 Commits

Author SHA1 Message Date
Дмитрий 235c55fd6f fix(finder): реальный телефон директора убран из тестов службы поиска
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
Утренняя чистка ПДн искала только в app/ и docs/ и пропустила моя/sales-finder —
папка скрыта от обычного поиска, номер оставался живым в трёх тестах (26 раз).
Заменён на фиктивный 79990000001, все 321 тест зелёные.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 15:01:25 +03:00
Дмитрий 31d6df0fcc feat(реклама): промпт и скрипт генерации картинок под Яндекс.Директ
Буклет 2:3 Директ не принимает. Два формата под требования Яндекса
(квадрат 1:1 и широкий 16:9), текста на картинке нет кроме логотипа,
макет телефона и карточка с номером убраны — риск модерации по 152-ФЗ.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 12:10:57 +03:00
Дмитрий 9a410a3358 docs(sales): поправки плана рекламы по ходу выполнения (stage_changed_at, оба трейта в тестах)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 11:53:54 +03:00
Дмитрий 49ee084b7e fix(sales): номер без хозяина не попадает в рекламу
Номера, заведённые до v8.77, остались без firm_id. Ночной пересчёт обходит
фирмы и такой номер не видит, а заливка видела — он крутился бы вечно.
Нашёл rls-reviewer при сквозной проверке.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 11:51:50 +03:00
Дмитрий c43ed7b283 feat(sales): экран прогрева — список фирм, назначение менеджера, 11 сроков
Task 8 плана v2 (реклама на кандидатов): начальник видит таблицу фирм на
прогреве (человеческие подписи состояний: «Реклама идёт», «Прогрет — ждёт
менеджера» и т.п.), кнопкой «Назначить менеджера» заводит карточку в воронку
через POST /api/sales/ad-audience/firms/{id}/assign, и правит 11 сроков
планировщика понятными фразами («Сколько дней греем до звонка менеджера» и
т.д.) вместо технических ключей.

Список менеджеров переиспользует существующий listSalesManagers() —
отдельного маршрута не заводили. api/sales.ts дополнен типами и функциями
для двух новых бэкенд-ручек Task 7 (firms/assign), которых там ещё не было.

Тест положен в tests/Frontend/ (а не в views/sales/__tests__/, как в плане) —
это единственный путь, который реально подключён в vitest.config.ts; мокает
модуль api/sales.ts, а не global.fetch — экран ходит через axios-обёртку.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 11:32:00 +03:00
Дмитрий 79d1567e7d feat(sales): список прогрева и назначение менеджера из рекламы
Task 7 плана v2 (реклама на кандидатов): начальник видит список фирм
на прогреве (GET /api/sales/ad-audience/firms) и назначает менеджера
(POST .../assign) — из снимка фирмы рождается карточка «Потенциальные
клиенты» стадии new, реклама дальше следует за стадией карточки.
PATCH /api/sales/ad-audience теперь принимает все 11 сроков планировщика,
GET отдаёт их в durations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 11:19:46 +03:00
Дмитрий 1e33da15c2 @
fix(судья): судит только ЕЁ голос + второе ухо отделяет крепкие находки от слабых

Полное заключение 19.07 вскрыло две беды судьи. Владелец: сначала судья, потом голос.

1. СУДИЛ ЧУЖОЙ ГОЛОС. Доложил «велено „шарвутся", услышано „шорвутся"» — а
   «шарвутся» сказал КЛИЕНТ. Судья сверял весь журнал целиком, обе стороны, и
   писал в брак Александры чужое произношение. Лечение не выкидыванием слова:
   каждое ожидаемое слово теперь помнит, КТО его должен был сказать, и находка
   докладывается только по её речи. Выравнивание по-прежнему по ВСЕЙ записи —
   иначе её слова начнут цепляться к клиентским; отсекаем на докладе, не на сверке.
   Прибор частиц слушает звук и тем более не знает, чей голос — судит только те
   слова, которые велели сказать ей.
   Было 8 звуковых находок → стало 6, ушли обе клиентские.

2. НЕ ОТЛИЧАЛ «голос сказал плохо» от «ухо не расслышало» — выглядит одинаково.
   Второе ухо другого устройства (модель разметки букв, уже стоит, качать нечего)
   слушает ту же запись. Оба уха не расслышали — находка крепкая; второе
   расслышало верно — слабая.

   🔴 Первая версия СНИМАЛА слабые — и убила «затишье», которое владелец
   подтвердил СВОИМ УХОМ: второе ухо расслышало это слово верно. Правило «оба
   уха обязаны ошибиться» режет правду. Второе ухо — СВИДЕТЕЛЬ, а не судья:
   говорит, насколько находка крепкая, а не есть ли она. Теперь понижение до
   СИГНАЛА: видно в статистике, приговор не двигает, накопитель на пачке
   разговоров сам отделит системное от случайного.

Итог по записи: 6 находок, 3 крепкие («первые»→«первое», «как-то» 81% и 114%),
3 слабые (в том числе подтверждённое владельцем «затишье»).

🪤 Испытания начали тянуть тяжёлые модели и вставать намертво. В conftest
общая заглушка: гигабайтным моделям в испытаниях не место, кому нужна
настоящая — подменяет явно у себя.

Тестов 173 → 183.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 10:57:27 +03:00
Дмитрий f6abd1764d feat(sales): фирма на прогреве помнит увиденную стадию — честный ночной пересчёт рекламы
Task 5 плана v2: RecalcAdAudienceJob (routes/console.php, дневное 03:10 МСК) ночью
сверяет стадию связанной карточки sales_prospects с последней запомненной у фирмы
(sales_ad_audience_firms.stage_seen/stage_changed_at) и зовёт AdAudienceScheduler,
чтобы проставить каждому номеру состояние active/paused/stopped.

Найдена и закрыта дыра в исходном плане: ни prospect->updated_at (двигается ЛЮБОЙ
правкой карточки — заметка менеджера ложно продлевала бы рекламу), ни firm->assigned_at
(момент назначения менеджера, не смены стадии) не годились источником даты «сколько
фирма сидит в текущей стадии». Решение: фирма сама хранит эту дату — миграция
2026_07_20_110000 (+2 nullable-колонки, db/CHANGELOG_schema.md v8.78). Новый тест
«правка карточки не перезапускает отсчёт рекламы» закрывает ровно эту дыру.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:54:21 +03:00
Дмитрий 566f016c9c feat(sales): в прогрев уходит фирма целиком, а не отдельный номер
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:35:41 +03:00
Дмитрий 98015db231 @
feat(судья): ловит «как-то» — частица после дефиса не бывает ударной

Владелец: на 0:35 «как-то» и «когда-то» звучат криво, лови. Следа в тексте нет
— ухо записало их верно, с дефисом. Значит дефект чисто звуковой.

🔑 ПОЧЕМУ ЭТО ИЗМЕРИМО, когда абсолютное ударение — нет. Сравниваем два слога
ОДНОГО слова, сказанных одним голосом в один момент. Не надо угадывать, какой
слог в слове ударный (две попытки провалились, потолок 53% против 51% у
болвана) — достаточно, что частица не должна быть приметнее корня. Правило
языка, не список слов: -то, -нибудь, -либо, -ка безударны в ЛЮБОМ слове.

🔴 ПОРОГ ВЗЯТ ИЗ САМОЙ РЕЧИ, а не подогнан под названные случаи. Замер по 133
словам записи: обычная безударная последняя гласная звучит примерно в 30% силы
сильнейшей гласной корня, у трёх четвертей слов — ниже 50%. Отсюда порог 50%.
Испытание запрещает менять его вне этих границ.

Живой прогон, 4 слова с частицей:
  0:36 «как-то»      → 81% силы корня   🔴 НАЗВАН ВЛАДЕЛЬЦЕМ
  0:55 «как-то»      → 114%             🔴 владелец не называл, судья нашёл сам
  2:37 «смотрите-ка» → 113%             🔴 то же
  0:34 «когда-то»    → 35%, чисто — по замеру это норма, подгонять не стал

🪤 РАЗГАДКА ПРОВАЛА АКУСТИКИ. Замер показал: все гласные выходили ровно по
0.021 с. Модель ставит по одной вспышке на букву, а между ними молчит — если
считать буквой только вспышку, длительность перестаёт что-либо значить. Мой
вчерашний «фикс» ровно это и сделал (60% → 52%). Пустые кусочки возвращены
предыдущей букве: так из привязки и получаются протяжённости звуков.

🪤 ЛОЖНАЯ ТИШИНА, пойманная на живом прогоне: ухо режет «как-то» на «как» и
«-то», прибору доставался огрызок без корня — и он докладывал «чисто» на всех
четырёх словах. Молчание, похожее на «проверено», хуже выдумки: выдумку видно,
а это нет. Куски склеиваются обратно, огрызок без корня к суду не принимается.

Тестов 162 → 173.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 10:25:10 +03:00
Дмитрий 9bc587c2de fix(sales): реальный телефон директора убран из тестов и планов; клиент Яндекс.Аудиторий возвращён в main
Коммит d2c2ec43 от 19.07 оторвался от main (dangling, ни в одной ветке):
чистка ПДн и YandexAudienceClient в основную ветку так и не попали.
Номера заменены на фиктивные 7999000000X, клиент и его тесты внесены заново.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:24:21 +03:00
Дмитрий 66f678697d feat(sales): правила рекламы по стадиям воронки 2026-07-19 10:16:39 +03:00
Дмитрий e25f940f39 feat(sales): модель фирмы на прогреве и настраиваемые сроки 2026-07-19 10:11:09 +03:00
Дмитрий 0be050395f @
feat(судья): ударение ловится ПО СЛЕДУ В ТЕКСТЕ — подтверждённый случай пойман

Владелец переслушал запись и назвал живой дефект: на 1:40 она говорит
«зАтишье» вместо «затИшье». Плюс сказал: не правь Александру, правь судью,
чтобы ловил.

🔑 КЛЮЧ, который дала эта правда. Ухо записало слово как «затЕшье» — не так,
как велено. Это и есть след: в русском безударная гласная РЕДУЦИРУЕТСЯ.
Ударение съехало → бывшая ударная «и» стала безударной → съехала в «е» →
распознавалка честно написала другую букву. Значит уехавшее ударение видно
В БУКВАХ, и городить акустику для него не нужно.

Прибор: согласные слова совпали, а гласная — нет. Это устройство языка,
а не список слов: проверено на «молоко/малоко», «сторона/старана»,
«телефон/тилефон» — работает на слове, которого мы в глаза не видели.

Разделение по смыслу, тоже из устройства языка: ПОСЛЕДНЯЯ гласная в русском —
это окончание (падеж, число, лицо), а ударение живёт в теле слова. Разошлась
последняя — доклад про окончание (признак 3); разошлась не последняя — про
ударение (признак 46). Иначе владелец не поймёт, что чинить.

Проверка на всей живой записи, 296 слов — 4 находки, ни одной лишней:
  признак 46: «затишье» → «затешье», гласная 2-го слога  ← ПОДТВЕРЖДЁН ВЛАДЕЛЬЦЕМ
  признак  3: «пациенты» → «пациента», «ступеней» → «ступень»,
              «проверяете» → «проверяйте»

🔴 Акустический разбор остаётся отвергнутым (две попытки, потолок 53% против
51% у тупого угадывания) — запись о нём в NENADYOZHNO уточнена: речь про метод,
а не про признак. На подтверждённом случае акустика ПРОМОЛЧАЛА, текст поймал.

Тестов 153 → 162.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 10:06:24 +03:00
Дмитрий ba98334e8c docs(sales): план рекламы на кандидатов v2 — прогрев до менеджера, сроки по стадиям
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 09:53:57 +03:00
Дмитрий 2e631cf16f @
feat(судья): ударения нормальным методом — сделано, измерено, ПРОВАЛЕНО честно

Владелец: доводить ударения нормальным методом. Доведено. Не работает,
и я это показываю числами, а не прячу.

ЧТО СДЕЛАНО НОРМАЛЬНО (в отличие от первой попытки):
  · привязка звука к БУКВАМ (wav2vec2 + просмотр путей CTC на numpy) —
    границы гласных больше не угадываются по провалам громкости,
    а вычисляются: мы знаем буквы, которые она произносила;
  · высота тона автокорреляцией — третья примета, которой не было вовсе,
    а в русском она выдаёт ударение сильнее прочих;
  · приметность слога по трём приметам, тон считается по УХОДУ от среднего
    тона этого же говорящего (у мужчин и женщин высота разная).

ЗАМЕР НА ТЕХ ЖЕ СЛОВАХ, что и первая попытка (иначе сравнивать нельзя):
  первая попытка ............ 40%
  вторая, как есть .......... 52%
  ПОТОЛОК по всем весам ..... 53%
  тупое «всегда 2-й слог» ... 51%   ← вот с чем надо сравнивать
  только громкость .......... 52%
  только тон ................ 37%

Прибор не несёт НИЧЕГО сверх угадывания. Дело не в весах и не в ошибке кода:
сами приметы на этой записи не разделяют ударный слог и безударный.
Признак 46 остаётся выключенным, замер записан в NENADYOZHNO прямо в коде.

🪤 По дороге поймано и закреплено испытаниями:
  · октавная ошибка — на двойном периоде отклик почти такой же, прибор
    докладывал голос вдвое ниже настоящего;
  · край окна — у звука ниже человеческого голоса отклик плавно спадает,
    горба нет, а прибор докладывал частоту с границы окна;
  · пустые кусочки помечались буквой — гласная получала чужую длину.
    🔴 Починка этого сделала результат ХУЖЕ (60% → 52%): прежний перекос
    случайно помогал. Записано, чтобы никто не «вернул как было».

Прежде чем вкладываться в обученный определитель ударения — стоит убедиться,
что дефект вообще существует: слышал ли кто-нибудь, чтобы она ставила
ударение неверно. Инструмент строился под неподтверждённую беду.

Тестов 135 → 153.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 09:51:24 +03:00
Дмитрий e09657bbb9 docs(sales): HANDOFF рекламной аудитории + спека v2 (порядок перевёрнут)
Владелец переформулировал: сначала ГРЕЕМ рекламой, потом отдаём менеджеру.
Прогрев — отдельный этап ДО воронки, карточка рождается при назначении менеджера.

Правила рекламы теперь следуют за стадией карточки, все сроки настраиваются:
прогрев 3 дня, новые 3, взят в работу 14, переговоры до даты созвона
(просрочена → +3 → стоп), недозвон 7, отказ 3, регистрация/тестирование 30,
пополнил баланс и пользователь — стоп.

Проверено на боевых данных: у «Взят в работу» и «Регистрация/Тестирование»
даты созвона нет и не будет — им обязателен свой срок, иначе реклама вечная.
У «Переговоров» дата обязательна в коде, логика владельца закрывает полностью.

HANDOFF содержит промпт для следующей сессии, все технические грабли,
состояние Яндекса (сегмент 58029600, письмо в поддержку отправлено)
и запись об инциденте с ПДн в истории коммитов.

Все телефоны в документах замаскированы.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 09:34:59 +03:00
Дмитрий c97e562d8c @
feat(судья): спектр звука — окончания, обрывы, бренд; ударения измерены и отклонены

Владелец: судья ДОЛЖЕН ловить окончания и ударения, системно, не заплаткой.
Спектр I не работал ни одним признаком из пяти — судья слышал только текст.

ПРИЁМ, общий для всего спектра: мы точно знаем текст, отправленный в голос,
значит эталон есть на КАЖДОМ слове, включая невиданное. Слушаем запись
ОТДЕЛЬНЫМ ухом судьи и сверяем «велено» с «услышано». Никаких списков слов.
Ухо судьи нарочно не то, что в мосту: тем же ухом ошибку не поймать —
прибор согласится сам с собой.

Заработали три признака: 3 окончания, 4 обрыв реплики, 5 бренд «Лидэрра».
На живой записи 19.07 нашли настоящее: «меня зовут алексан(др)»
и «компания лидера» — ровно то, ради чего затевалось.

🔴 УДАРЕНИЯ — ЧЕСТНЫЙ ОТКАЗ, а не тихий пропуск. Признак 46 заведён, прибор
написан (физика: ударный гласный длиннее и громче; эталон — словарь ударений
русского, знает любое слово; правило «ё всегда ударная» работает без словаря).
На синтетических гудках прибор безошибочен. На ЖИВОЙ речи: 187 судимых слов,
совпало с эталоном 40%. Перебор настроек — 32–47% при случайном угадывании
около 40%. Прибор не знает ничего; голос столько ошибок не делает, врёт
измеритель. Причина: громкость и длительность не разделяют слоги живой речи.
Нужен разбор по звукам (гласные + высота тона), а не огибающая громкости.
Признак внесён в новый список NENADYOZHNO, судья по нему МОЛЧИТ. Сторож
покрытия расширен: негодный прибор обязан лежать в списке с ЧИСЛОМ замера,
иначе через месяц его тихо включат обратно.

🪤 Наивное сопоставление «по порядку подряд» опознало на живой записи 27% слов
вместо 86% и выдало ложную тревогу об обрыве: журнал стенда не пишет ни
приветствия, ни филлеров, а в звуке они есть. Заменено на difflib — лишнее
терпится с ОБЕИХ сторон.

Признаков 45 → 46, тестов 125 → 135.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 09:13:10 +03:00
Дмитрий 3ab8b2cbff feat(sales): руками введённые телефоны контактов чистятся при сохранении (формат 79…, дубли долой)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 08:57:02 +03:00
Дмитрий 44b892c771 feat(sales): экран «Реклама на кандидатов» в кабинете начальника
GET/PATCH /api/sales/ad-audience — три числа (в рекламе сейчас, выходят на
этой неделе, ждут отправки), рубильник и срок хранения номера. Доступ только
роли head — гейт denyIfNotHead зеркалит SalesManagersController.

Экран объясняет обычными словами, что список пополняется только кнопкой
«Отправить в рекламу» в Поиске клиентов, и предупреждает, когда номеров
меньше 100 (Яндекс не запустит рекламу).

Тесты: 9 в tests/Feature/Sales/AdAudienceScreenTest.php (доступ, три числа,
смена настроек, валидация срока). SharesSupplierPdo — модели на pgsql_supplier.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 08:46:36 +03:00
Дмитрий 536716a65e @
feat(судья): опровергатели против ложных тревог + чтение всех трёх форм журнала

Владелец: «нам надо пару сотен разговоров прогнать, мы умрём слушать сами».
Значит на объёме ложная тревога дороже пропуска: судья с выдумками бесполезен,
ему перестают верить. Первый живой запуск коллегии 19.07 дал ЧЕТЫРЕ ложных
СТОПа на два разговора — два разных довода принял за противоречие, оговорку
«приходят люди или нет» за гарантию, настоящий подарок за возврат денег.

Два системных замка, оба универсальные:

  1. Поле «narushen» вместо разбора прозы. Судья писал в обосновании
     «признак соблюдён, нарушения нет» — и всё равно подавал это находкой.
     Думать вслух теперь некуда: есть отдельное поле. Поля нет (старая форма
     ответа) — считаем нарушением, чтобы не терять молча.

  2. Опровергатели. Каждый СТОП коллегии уходит к трём независимым судьям,
     которым велено ОПРОВЕРГНУТЬ, и при сомнении опровергать. Опровергнут
     двумя из трёх — понижается до СИГНАЛА (не выбрасывается: судью самого
     надо мерить). Приборные СТОПы через опровержение НЕ гоняем — приборы
     нельзя уговорить, а деньги владельца тратить незачем.

Проверка на живых деньгах, эталон v9 от 17.07:
  было  — СТОП по трём обвинениям, два из них выдуманы;
  стало — оба выдуманных опровергнуты и понижены, СТОП остался ОДИН
          и настоящий: прибор 15 поймал перевёрнутую цену
          «от пятидесяти пяти до двадцати пяти». 10 обращений, 4.11 ₽.

Судья теперь читает все три формы журнала (боевой мост / стенд моста /
движок v9) + автоопределение формы: владелец подсовывает файл, не думая.
Стенд и движок не пишут решение маршрута — признак 44 там честно
не измеряется, а не делает вид, что проверен.

🪤 Четвёртый вид тех же граблей: прибор 41 «цену вперёд не тащи» ловил слово
«почему» — внутри него сидит «почем». Обвинял её за вопрос «почему не начали».
Найдено судом над эталоном, починено, регрессия закреплена.

Тестов 77 → 100.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 08:39:16 +03:00
Дмитрий b4c51bf0bc feat(admin): СМС-центр (smsc.ru) на плашке внешних сервисов — баланс, пороги, кнопка пополнения
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 08:25:28 +03:00
Дмитрий bb20a8859d @
feat(sales): приём номеров в рекламную аудиторию

Сервис-канал POST /api/sales/integration/ad-audience (тот же X-Sales-Token,
что и «Отдать менеджеру»). Новый номер добавляем, известный — продлеваем срок
из настройки и просим ночной джоб дослать (synced_at=NULL, removed_at=NULL).
Формат Яндекса строгий: 11 цифр с 7, без плюса.

Task 3 плана 2026-07-19-reklamnaya-auditoriya-kabinet-nachalnika.

Моделям дописаны @property-докблоки (конвенция проекта, как у SalesProspect) —
без них Larastan не видит полей.

Тесты: 6 в tests/Feature/Sales/AdAudienceIntakeTest.php, вся Sales-пачка 264 зелёные.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-07-19 08:16:14 +03:00
Дмитрий d7e6766760 feat(sales): модели рекламной аудитории 2026-07-19 08:01:58 +03:00
Дмитрий 237be1f7fd @
feat(судья): закрыты три слепых пятна — сор из избы, маршрут обязательств, разворот сферы

Четыре дефекта живого прогона 18.07 судья не видел. Три из них закрыты
приборами и рубрикой, четвёртый (противоречие себе) уже покрыт признаком 13
и ждёт первого живого запуска коллегии.

Лечим КЛАСС, а не случай — ни одного слова из живого разговора в коде нет:

  43 «сор из избы» (правдоруб, СТОП) — признание клиенту наших сбоев и
     внутренней кухни. Смысловой, судит роль. Тест запрещает привязку к фразе.
  44 «зона обязательств ведётся умным мозгом» (прибор, ТРЕВОГА) — меряем
     РЕШЕНИЕ маршрута, а не имя модели. Зона = вопрос И тема обязательств.
     🔴 Вторая сторона правила важнее первой: когда ухо съедает ключевое слово,
     реплика клиента в журнале уже испорчена — зато её ответ цел. Заговорила
     про обязательства с быстрого мозга — тот же дефект с уцелевшей стороны.
  45 «разворот сферы доведён до конца» (прибор, ТРЕВОГА) — судья не знает
     ни одной ниши, читает след моста: заметил чужую сферу и не сменил справку.

Мост НЕ тронут: весь след уже был в журнале, надо было научиться читать.

🪤 Третий раз одни грабли: первая версия прибора резала правду
(«Договорились!» → договор, «Отвечаю:» → ответственность). Поймано только
адверсарным прогоном НА ПРАВДЕ. Формы сужены, регрессия закреплена тестом.
Итог прогона: 12/12 верных реплик чисто, 4/4 бракованных пойманы.

Тестов 61 → 77.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 07:49:02 +03:00
Дмитрий d7eaee6021 feat(finder): убраны значки 📱☎️ из подписей номеров (просьба владельца)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 07:46:00 +03:00
Дмитрий 4f172ad88b @
docs(golos): HANDOFF — судья и четыре дефекта Александры

Передача следующей сессии: где что лежит, что сделано, четыре дефекта найденных
ГЛАЗОМ (судья их пока не видит) и порядок работы — сперва научить судью их ловить,
показать владельцу, и только потом чинить.

🔴 Главное правило вынесено в шапку: ни судью, ни Александру нельзя точить под
конкретный случай. Никаких регулярок под «база перепуталась», списков с «натяжными
потолками» и синонимов «гарантии» в маршрут. Для каждого дефекта указан КЛАСС
проблемы: смысловая связность, сила свидетельства о нише, доверие к компании,
независимость маршрута от точного слова.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 07:27:22 +03:00
Дмитрий dff4b62002 feat(finder): номера без «+» (79…) — формат для Яндекс Аудиторий, ДаДата/СМС-центр совместимы
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 07:22:55 +03:00
Дмитрий dc4a17cb43 docs(finder): правка владельца — живость менеджеру не показываем, зачёркиваем только «не существует»
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 07:05:11 +03:00
Дмитрий cffbc1e7c3 feat(finder): живость не показываем менеджеру — зачёркиваем только «не существует» (решение владельца)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 06:57:22 +03:00
Дмитрий d826d96a86 fix(finder): HLR — финальный отказ приходит статусом 20 (не 1); вердикт по err, проверено живым боем
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 06:10:19 +03:00
Дмитрий 37809697b6 @
docs(golos): мини-прогон трёх сценариев на сервере + первый суд

Карта судьи по 3 разговорам: доля речи 75-82% при норме 35-45, за 4 реплики один
довод из 13, выдумки ушей в каждом разговоре.

🔴 Записаны слепые пятна судьи — то, что глаз увидел, а он нет: самопротиворечие
внутри реплики, разворот ниши не сработал (замок «подтвердить дважды» слишком строг —
клиент называет сферу ОДИН раз), признание клиенту «база у нас перепуталась».

🔴 Механическая находка: клиент спросил про гарантии, уши съели слово «гарантии» —
маршрут по словам не сработал, и дешёвая модель полезла рассуждать о законе
(«отвечать будете вы», «согласие на обработку данных»). Съеденное ухом ключевое
слово ломает маршрутизацию — это дефект схемы, а не промпта.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-19 06:02:51 +03:00
Дмитрий cb81d9faad @
feat(sudya): спектр продажи по нашей методике + накопитель слабых мест

Судья умел говорить, чего она НЕ должна говорить (красные флажки), но не умел
судить, КАК она продаёт. Добавлены признаки по методике из базы наставника:
крючок, лесенка подачи, финал по теплоте, ведёт вопросами, цену вперёд не тащит.

🔴 Живой замер на сервере опроверг мою догадку. Я ждал, что она ВЫВАЛИВАЕТ доводы
пачкой — а она за шесть реплик назвала ОДИН блок из тринадцати. Говорит 71% времени
и почти ничего не доносит: много сочувствия, мало содержания. По доле речи это
не видно, поэтому добавлен признак 42 на пустословие. Детектор блоков проверен
на эталонном тексте базы — узнаёт 12 из 13, то есть находка настоящая, не слепота.

Накопитель: один разговор ничего не говорит, смысл появляется на пачке. Раскладывает
находки на системное / частое / шум — чтобы не гоняться за случайностью и не портить
то, что работает. Признак считается один раз на разговор: десять срабатываний в одном
не делают дефект системным.

🔴 Судья ДОКЛАДЫВАЕТ, а не правит: где промахнулась, как часто, дословные примеры.
Что чинить — решает владелец. Советов «крути здесь» в накопителе нет намеренно.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 19:36:31 +03:00
Дмитрий 28db52fb6e docs(разведка): проверка первоисточниками — 4 факта Perplexity оказались неверны + письмо в поддержку Яндекса
Три агента перечитали официальную документацию Яндекса, ВК и МТС.
Итог: Perplexity дал минимум 4 неверных факта, каждый пойман только
чтением первоисточника.

Исправлено:
- площадок ТРИ, не четыре: myTarget мёртв, вся дока 301 → ads.vk.ru
- ВК: два порога — 100 руками, 2000 через API (мы автоматизируем ⇒ 2000);
  создание не более 1 списка в час
- МТС: 0,48 руб/показ по прайсу от 01.06.2026, а не 0,9 (цена 2024 года);
  показывает ТОЛЬКО не-абонентам МТС ⇒ канал B3 через Telegram недостижим
- квоты Аудиторий: 5000 запросов в СУТКИ на логин, а не 100 в секунду
- медийка: от 300 руб/день, порога 35 000 не существует
- PUT /segment/{id} меняет только название; данные — modify_data
  с режимами addition/subtraction/replace
- автотаргетинг на Поиске отключить нельзя (но и не надо — сегмент режет
  через «И», автотаргетинг задаёт лишь набор запросов)
- look-alike выключается конкретной радиокнопкой «Только выбранный сегмент»

Новое:
- фича универсальная: клиент жмёт кнопку, Лидерра — такой же клиент у себя же
- агентский логин Директа без условий, но договор — 3 клиента и 3 млн/мес
- в API Аудиторий аналога Client-Login НЕТ; мультиклиентность через делегатов,
  но в интерфейсе такого раздела нет ⇒ 5 блокирующих вопросов в поддержку
- Метрика уже стоит (счётчик 110476275) — второй бесплатный источник сегментов

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 19:33:37 +03:00
Дмитрий fbca7e13f9 @
feat(sudya): оркестратор, карточка звонка и приёмка на подсадных ошибках

Оркестратор сам ничего не проверяет — собирает слои и выносит итог: любой СТОП →
СТОП, иначе ТРЕВОГА, иначе НОРМА. Сломанный якорь перекрывает всё. В бою полная
коллегия не зовётся — только приборы, деньги владельца берегутся.

Приёмка судьи: девять диалогов с нарочно посаженным браком (выдуманное число,
перевёрнутая цена, мужской род о себе, «ты», своё имя вместо обращения, латиница,
потерянная реплика, выдумка ушей, долгая пауза) — судья обязан найти каждый.
Плюс чистый якорь, на котором он обязан промолчать: если судья бракует хорошее,
это хуже пропущенного брака. Все десять проверок прошли.

Проверено сквозняком на живом журнале, а не только на выдуманных примерах:
судья честно поймал, что она говорит 57% времени при норме 35–45%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 18:59:29 +03:00
Дмитрий e2e054365c @
feat(sudya): приборы техники и характера + сторож покрытия рубрики

Техника: задержки до звука и до ответа, потеря реплики клиента (СТОП — мост однажды
глох во время думания и сказанное исчезало), выдумки ушей на тишине, доля её речи.

Характер v9: женский род, «вы», повторное приветствие, своё имя вместо обращения,
длина реплики, латиница. Женский род правится ТОЛЬКО про себя — тест стережёт
живую ловлю 18.07, когда сторож сделал пациента-мужчину «готова».

🔴 Сверка вскрыла дыру в собственном плане: признаки 8 и 9 стояли в рубрике как
измеряемые, а кода не было — судья молча делал вид, что проверяет. Признак 8
реализован (перебивания были, а обрезки нет — тот самый утренний дефект моста).
Признак 9 честно записан как неизмеряемый: журнал пишет, что мост ЖДАЛ думающего,
но не пишет случаи, когда оборвал. Добавлен тест покрытия: каждый приборный признак
либо имеет код, либо стоит в списке с причиной. Дыра больше не спрячется.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 18:55:03 +03:00
Дмитрий bf30a83ed2 @
feat(sudya): прибор правды о числах и коллегия судей со слепым протоколом

Прибор ловит два дефекта, пойманных владельцем живьём: числа вне замка фактов
и цену наизнанку («от пятидесяти пяти до двадцати пяти» вместо «от двадцати пяти
до пятидесяти пяти»).

🔴 Адверсарный прогон поймал ПОВТОР истории: прибор резал правду «минимальный
заказ — одна заявка». Ровно на этой форме сторож чат-бота однажды уже съел верный
ответ и оставил клиенту обрубок. Добавлены формы один/одна/одну/штука, случай
закреплён отдельным тестом — тестов из плана было мало, они этого не видели.

Коллегия: четыре узкие роли вместо одной большой рубрики, вопрос НЕЙТРАЛЬНЫЙ
(наводящий однажды заставил судью объявить роботом живого диктора), находка без
цитаты понижается до сигнала, якорь-контроль, автостоп и кеш по деньгам.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 18:47:52 +03:00
Дмитрий 7ee40fcde5 docs(разведка): реклама по своим номерам (4 площадки) + аналоги поставщика в СНГ и мире
Две находки одной сессии.

1. Реклама по своим номерам — берём все 4 площадки:
   Яндекс Аудитории (порог 100, полный API, максимум площадок), VK Реклама
   (порог 100 — поправка, 2000 относится к старому myTarget), myTarget (2000,
   ради Одноклассников), МТС Маркетолог → Telegram Ads (0,9 руб/показ, без API).
   Главный сценарий — недозвоны, которые сейчас списываются в ноль.
   Look-alike выключен намеренно: согласие давали конкретные люди.
   Грабли автовыгрузки: формат 79995551111, SHA-256 без соли, статус
   «Обновляется» на несколько часов после заливки.

2. Аналогов нашего поставщика (ГЦК/BG) нет нигде — проверено 9 стран СНГ
   и 12 мировых рынков. Операторы монетизируют данные, но контакт наружу
   не выдают: закрытый двор от Казахстана до США. Законы всех девяти стран
   СНГ требуют отдельного согласия на передачу номера третьему лицу.
   Российская модель — аномалия, моат сильнее, чем считали.
   Казахстан — единственный перспективный (Kcell Target Call, DMP.one уже там).
   Беларусь закрыта законом 99-З дословно. Узбекистан — вторым, разведать глубже.

Дыры выписаны честным списком: локализация данных в КЗ/УЗ, реальные цены,
льёт ли BG по Казахстану (проверяется тестовым проектом за час).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 18:45:16 +03:00
Дмитрий ec8cd1ddb2 @
feat(sudya): разбор журнала моста и надзор за судьями

Разговор на входе судьи: реплики кто-что, пометка оборванных, доля её речи,
события моста (перебивания, ожидание думающего, выдумки ушей, потери реплик).
Всё чтение журнала живёт в одном файле — сменится формат, правим одно место.
Проверено на настоящих строчках сегодняшнего боевого журнала, не только на тесте.

Надзор: промах = судья сказал НОРМА, а владелец нашёл брак ушами. Сказал СТОП —
поймал, не промах. Доля выше 20% — судья негоден. Без этого слоя коллегия
со временем халтурит незаметно: она же сама себя и оценивает.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 18:43:12 +03:00
Дмитрий 17cf679652 @
feat(sudya): план судьи + рубрика на 36 признаков

Рубрика — единственный источник правды по критериям: спектры I звук, II техника
разговора, III правда и обязательства, IV характер, V продажа (новое — этого не
судил ни один прежний судья), VI проверка самого судьи.

Каждый признак несёт тяжесть: СТОП двигает вердикт в брак, ТРЕВОГА зовёт смотреть
глазами, СИГНАЛ идёт только в статистику. Из 36 признаков 16 — СТОП.

Тесты закрепляют целостность: ровно 36, номера без дыр, поля из допустимых множеств,
спектр V судит только продавец.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 18:39:18 +03:00
Дмитрий d2b74c8b04 docs(finder): спека и план проверки телефонов (ДаДата + HLR)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 18:22:40 +03:00
Дмитрий f386a2e27b fix(finder): мусорные номера подписаны «номер не распознан» (по спеке)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 18:21:48 +03:00
Дмитрий f8bd812807 test(finder): отрисовка размеченных номеров закреплена тестами (HTML + Excel)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 18:13:33 +03:00
Дмитрий d9e82f6e3c @
docs(sudya): проект сводного судьи диалогов Александры

Собран из трёх существующих семейств судей: голосовые (NISQA/дуэли/glitch),
чатовые (AnswerGuard + слепые судьи-агенты), нормативные (llm-judge/reviewer-agent/
judge-evaluator). Ни одно из них не судило ГЛАВНОЕ — продала ли она; для номера
менеджера по продажам на лендинге это ключевой спектр.

Устройство: приборы (приговор) → коллегия узких судей-ролей (находки) →
судья над судьями (доля промахов). 36 признаков в шести спектрах.

Протокол честности, каждое правило оплачено ошибкой: слепота, нейтральный вопрос,
живой якорь в партии (забраковал якорь → партия недействительна), роли вместо
одной большой рубрики, находка без цитаты источника не считается.

Границы названы явно: звук живых клиентов не пишем (ПДн — отдельная работа),
судья не правит Александру сам, владелец остаётся высшей инстанцией.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 18:09:39 +03:00
Дмитрий f2221101c6 feat(finder): метки номеров в списке и Excel — живые мобильные первыми, мёртвые зачёркнуты
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 18:04:24 +03:00
Дмитрий ba62359337 fix(finder): нераспознанные номера в warning (не теряем), guard эндпоинта, секреты читаем раз
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:58:37 +03:00
Дмитрий 3db5115e6e feat(finder): проверка номеров встроена в сбор контактов (+2 поля Firm)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:46:52 +03:00
Дмитрий 40fa829738 fix(finder): оркестратор — сбой на одном номере не роняет остальные; junk-путь закреплён тестами
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:41:49 +03:00
Дмитрий c3eff704a3 feat(finder): оркестратор проверки номеров + сортировка для показа
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:34:49 +03:00
Дмитрий 74f3048e91 fix(finder): HLR — id=0 не терять, строковые статусы коерсить, опрос короче (8×0.5с)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 17:30:32 +03:00