Commit Graph

1867 Commits

Author SHA1 Message Date
Дмитрий b32626f232 docs: отчёт круга З-2.3 — приём материалов клиента
Четыре мерки с числами, семь ножей со слепками до и после, разбор задания
и шесть расхождений задания с делом.

Свои ошибки названы первыми: правка через оболочку вопреки правилу, 38 чужих
моделей, тронутых ключом -M у ide-helper и возвращённых, и два незаслуженно
зелёных сторожа.

Отдельно: прогон САМ пересобирает тестовую базу в начале, поэтому надрез
в живой базе стирается до того, как сторож его увидит. Резать надо файлы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 20:37:13 +03:00
Дмитрий b1f5bb1c6b docs(приёмка Яндекса): предсказание сбылось — хоронил я его на полчаса раньше времени
У #16 и #21 появилось по показу, списано по 0,50 руб в 16:00. Директ по всем
трём живым кампаниям пишет «Идут показы», объявления приняты: #16 — 15 из 15,
#21 — 13 из 13, #19 — 13 принято и 2 отклонено, как и задумано.

Вчерашнее предсказание «показы у #16 пойдут к 15:00» я объявил провалившимся
в 15:28. Первый показ пришёл между 15:35 и 16:00 — промах меньше часа.

Урок: у предсказания должен быть не только срок, но и допуск — к какому моменту
признаём его неверным. Без допуска опоздание на полчаса читается как провал.

Раскачка теперь известна по трём кампаниям: 4 ч 41 мин, 5 ч 17..42 мин,
3 ч 15..40 мин. Открытым осталось, почему после раскрутки #16 идёт по одному
показу в час против 25-42 у #13 — предсказание на 06.08 записано с допуском.
2026-08-05 20:07:52 +03:00
Дмитрий e572e492c4 docs: скелет отчёта круга З-2.3 — приём материалов клиента
Создан первым действием круга, до разведки, чтобы наработки не сгорели
при обрыве. Дальше файл наполняется по ходу работы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 19:09:58 +03:00
Дмитрий 1b1c1879d7 docs(приёмка Яндекса): «ноль показов» оказался не нулём — найдено единственное различие
Спросили не портал, а сам Яндекс: у #16 и #21 по одному показу, у #13 — 193
против 169 в портале (отставание часового обхода, не поломка).

Сверены две оси, которых в прежней таблице не было: стратегия целиком и
расписание по часам. У всех четырёх кампаний совпадают дословно. Отличается
ровно одно — период: у #13 срок кончается сегодня, у остальных сегодня лишь
первый день из двух.

Версия записана вместе с предсказанием, по которому её можно казнить:
06.08 у #16/#19/#21 показы обязаны пойти, у #16 примерно вдвое быстрее.
Если утром ноль при мёртвой #13 — версия неверна.
2026-08-05 19:07:24 +03:00
Дмитрий 26a897fb87 docs,обзвон: приёмочный лист круга З-2.3 заведён ДО работы
Разведка перед заданием сверила командой всё, что задача утверждает о коде.
Разошлось пять утверждений из пяти проверенных: хранилища, названного в задаче,
не существует; таблицы обзвона живут в другом файле канона; проверка про старый
отказ беспредметна; журнал ПДн есть, но зовётся иначе; хозяин срока не построен.

Своя ошибка названа первой. Я чуть не объявил, что журнала ПДн нет вовсе: два
прибора подряд сказали "нет", и вывод напрашивался крупный. Третий прибор показал
живую таблицу с готовым сервисом записи. Приборы искали своё начертание слова, а
таблица названа сокращённо. Правило метода отработало дословно.
2026-08-05 19:04:52 +03:00
Дмитрий 1fd0170ded docs,приёмка Яндекса: закрыты Я1, Я2, Я5 и карточка Я-М1 — 7 комбинаций из 9
Я1 закрыт замером #16: приняты 15 картинок из 15, показов 0, списано 0,
850 рублей в заморозке одной строкой. Доказывает, что одобрение само по себе
денег не берёт.

Я2 и вместе с ним карточка Я-М1 закрыты вердиктом по #17: отклонены оба
объявления, заморозка вернулась целиком, ни одной строки списания. Оба вердикта
существовали только в передаточной записке, в журнал приёмки записаны не были.

Я5 проведён и закрыт за смену кампанией #22: свободные ровно равны смете,
полный отказ модерации, возврат до копейки, прогон стоил ноль. Рычаг отказа
подтверждён третий раз подряд теми же двумя картинками.

Недостижимые ячейки Я2 оформлены как SKIP с проверкой живьём: обе ручки на
отклонённой кампании ответили отказом, статус и деньги не дрогнули.

Поправка к скорости показов, третья за два дня: по полной летописи #13 это
5,5 показа в час, а не 13-25 — прежнее число взято с куска разгона. Отсюда
следует, что #19 своё до срока не доберёт; владелец решил оставить как есть
и записать недостигнутым.

Молчание #16, #19 и #21 разобрано не до конца. Настройка снята с подозрения
по шести осям — у крутящейся и у молчащих совпадает всё. Но предсказание,
выведенное из объяснения, не сбылось, поэтому вопрос записан открытым, а не
закрытым красивым рассказом.

Промт смене 24.
2026-08-05 18:52:37 +03:00
Дмитрий 2da4721644 docs,обзвон: в плане отмечена одна закрытая задача из восьми — исправлено
Владелец сказал про промт «почти». Пересчёт бумаг командой вскрыл дыру,
которой промт не закрывал. Первая смена построила восемь задач, а в плане
отметила одну — З-0.2. Семь денежных задач стояли в плане как непостроенные,
то есть для следующей смены их не существовало, хотя код лежит в ветке.
Ошибка надзирателя номер 11, класс тот же: считал код и не считал бумаги.

Врезки «ПОСТРОЕНО» дописаны всем семи, с коммитом, ссылкой на приёмочный лист
и тем, чем замер разошёлся с текстом задачи. Главные расхождения теперь видны
прямо в задачах: крайняя цена разговора 1252 рубля вместо записанных 602,
цена брошенной трубки 12 рублей вместо 2, намеренно оставленный ноль за минуту
и молчаливая недостача трёх живых каналов. Датчик сходится: восемь отметок при
восьми закрытых задачах.

Вторая находка — ложный совет в самом промте. Там было написано гонять
проверку правописания руками. Запустил — она отвечает «проверено файлов: 0»,
потому что исключение лежит в самой настройке. Совет выглядел успехом и не
проверял ничего. Это ошибка номер 12, и она опаснее отсутствующего совета:
отсутствующий заставляет думать, ложный успокаивает. Записан рабочий способ и
оговорка, что улов там почти весь ложный — латинские имена файлов в ссылках.

В промт добавлен раздел 0.9 про бумаги — четвёртую обязанность надзирателя,
которой в нём не было вовсе. Куда класть свой приёмочный лист и как называть,
что обновляется в том же круге, датчик пересчёта и работа в конце смены.
Обязанностей в листе стало пятнадцать, правил девять.
2026-08-05 18:51:25 +03:00
Дмитрий 776f80de23 docs,обзвон: промт смене 2 переписан целиком — работать строго по методу
Владелец потребовал прямым словом: следующая смена обязана работать по методу, а
не по своему усмотрению. Поэтому раздел 0 переписан заново и стал жёстким входом.
В нём лист обязанностей из четырнадцати пунктов, который проходят поимённо на
каждом круге, а не держат в голове, и к каждому пункту сказано, чем он
доказывается. Отдельной строкой записано, что отступление от метода — не
ускорение, а отказ от единственного датчика, который до сих пор ловил ошибки.

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

Числа собраны командой заново: 50 задач, 96 требований, 96 решений, 23 коммита
стройки поимённо, потому что чужие смены коммитят между нашими. Прибавлен разбор
того, что вскрыл круг записей разговоров: разговор человека живёт в четырёх
местах, а не в одном, и звук оказался единственным, у которого была хоть какая-то
чистка.

Порядок работ переставлен целиком. Волна 0 встала решением владельца: пробы с
одновременными звонками отложены до ночного окна. Первой стоит волна 2, она
сервера не касается вовсе. Решений в таблице стало тринадцать, Р84 по Р96.

Ссылки и числа промта сверены с делом командой. Одно число не сошлось и
исправлено: разделов в приёмочном листе денежной волны восемнадцать, а не
пятнадцать — было перенесено из прежней редакции без перемера.
2026-08-05 18:32:11 +03:00
Дмитрий c00f61da02 docs,обзвон: приговор по добавочному кругу — срок стал месяцем по решению Р95
Сторожа резал своим ножом, третьим за смену: не менял число, а потерял перевод
часов в минуты. Это не неверное число, а неверная единица — срок молча
превращается из месяца в двенадцать часов, и на бумаге всё выглядит правильным.
Покраснела одна проверка из 27, код возврата 1.

И покраснела ровно та проба, которую исполнитель добавил вопреки моему заданию.
Прежний сторож эту поломку пропустил бы: он всюду задавал срок явно, а при явном
сроке ошибка единицы одинаково верно удаляет старое и хранит свежее. Возражение
помощника закрыло настоящий класс беды, а не формальность.

Своя неточность названа: я написал в задании привести сторожа в согласие,
подразумев, что три числа в нём разошлись. Не разошлись. Настоящая дыра была
глубже — сторож ни разу не проверял боевое умолчание вообще. Класс тот же:
предположил состояние кода, не замерив его. Третий раз за смену, и все три раза
спасал несогласный исполнитель.

Возврат доказан слепком знак в знак, дерево по своим файлам чисто, сторож снова
27 проверок при нуле красных. Голого необъяснённого старого числа не осталось
нигде.
2026-08-05 18:24:06 +03:00
Дмитрий 18dd884772 docs,обзвон: три решения владельца Р94 Р95 Р96 по записям разговоров и пробам
Владельцу показан замер: в папке робота 89 записей, из них 21 живой входящий
звонок с голосом постороннего человека, и бумага от 3 августа утверждала, что
личных данных там нет. Утверждение оказалось неправдой.

Р94 — уже накопленные записи руками не трогаем, пусть чистка съест сама по сроку.
Отрезаны обе узкие починки: стереть только чужие голоса и стереть всё разом.
Записано вслух и то, чего решение не закрывает: связка с Р95 означает, что чужие
голоса пролежат до начала сентября, и то лишь если завести расписание, а сегодня
чистку не зовёт никто.

Р95 — срок хранения месяц, столько же, сколько уже решено для записей в портале.
Отрезаны трое суток, сутки и неделя. Владельцу при выборе было сказано, что для
временной папки месяц долго, и он выбрал зная это; суммарно голос может лежать до
двух месяцев, считая второй срок уже в портале.

Р96 — пробы с тремя одновременными разговорами отложены до отдельного окна,
например ночного: сервер робота делит железо с рендером боевого сайта, а замера
опасной нагрузки у нас нет. Мина при этом остаётся заряженной, и до закрытия
З-0.1 три линии включать нельзя, хотя Т34 и Р58 их разрешают.

Протокол вырос с 93 решений до 96.
2026-08-05 18:07:49 +03:00
Дмитрий 49adecafba docs,обзвон: промт смене 2 догнал вечер — З-0.2 закрыта, уроков стало девять
Промт устарел за полдня ровно так, как сам предупреждает. Догнан командой, а не
памятью: задач 50, коммитов стройки 18, добавлена строка про построенное в круге
З-0.2 и вынесены вслух четыре вещи, которые ждут слова владельца.

Уроков надзирателя стало девять вместо семи. Восьмой: в этом же промте стояло,
что З-0.1 и З-0.2 друг другу не мешают, потому что файлы разные — а в списках
обеих задач стоит README робота. Девятый: предложил редактору сверять файл
целиком, не измерив, что шапка копии в 57 строк на сервере не появится никогда.
Оба того же класса, что первые семь.

Прибавлено правило: предлагая помощнику способ, меряй предмет так же строго, как
чужой отчёт. И оговорка к самому урожайному приёму: девять из девяти помощников
нашли ошибку в задании, но верны были не все — из пяти возражений последнего
круга одно оказалось ложным, и отличить его можно было только замером.
2026-08-05 17:58:45 +03:00
Дмитрий 3ed88eeef3 docs,обзвон: приговор по кругу З-0.2 и восьмая ошибка надзирателя
Круг записи разговоров принят своей рукой. Сторожа резал сам и шестым способом,
которого исполнитель не пробовал: перевернул знак срока. Покраснело 6 проверок
из 23 и покраснело в обе стороны — старое осталось, свежее исчезло. Возврат
доказан слепком. Прогон сервера своей рукой: 4930 проверок, красных 0, код
возврата 0 — сходится с точкой отсчёта. Интерфейсного прогона круг не требует, и
это замер: за четыре коммита не тронуто ни одного файла под app и resources.

Восьмая ошибка надзирателя того же класса, что первые семь. Найдя слепое место в
сверке, я предложил редактору лечение — сравнивать файл целиком — не измерив
предмет. Редактор измерил и отверг: выше начала диалплана лежат 57 строк шапки
про сам репозиторий, которой на сервере не будет никогда, и сплошная сверка дала
бы вечный шум в полсотни строк. Его числа проверены моей рукой и сошлись. Правило:
предлагая помощнику способ, меряй предмет так же строго, как чужой отчёт.

Из пяти возражений помощников верны четыре, одно ложно, и отличить их можно было
только замером. Своей рукой найдены две беды в бумаге исполнителя: неправда про
начало серверного файла и обещание числа 3 там, где честное число 5. Отданы
другому помощнику по правилу правщик не автор.

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

Счётчики плана были устаревшими по моей же вине со вчерашнего дня — стояло 47 при
49 задачах. Исправлено, стало 50, и рядом записано, что число уже протухало.
2026-08-05 17:55:29 +03:00
Дмитрий a3b691d437 docs: сверка настройки Лены больше не врёт про сервер и не обещает несосчитанных чисел
Раздел «Как сверить копию настройки с сервером» в bots/lena-golos/README.md.

Что было не так:
- фраза «выше [from-mango] на сервере служебные разделы Asterisk» выдумана.
  Замер 05.08.2026: там одна пустая строка и больше ничего, а сверка верхушку
  файла не видела вовсе — любой чужой раздел выше прошёл бы молча;
- проверка выключателя обещала ответ 3, но grep -c считает и пояснения тоже:
  по копии выходит 5. Правильно перенесённую работу прочли бы как беду;
- врезка обещала расхождение «ровно две строки», хотя копия от [from-mango] —
  126 строк против 107 серверных.

Что стало:
- проверок три, вместе они накрывают весь серверный файл, слепого места нет;
- новая проверка верхушки: непустых строк выше [from-mango] сегодня 0;
- счёт выключателя срезает комментарии, ответы 0 и 3 сосчитаны командой;
- врезка сохранена, объёмы в ней замерены, точный список расхождений не обещан.

Все обещанные ответы прогнаны по макетам серверного файла, сторож проверен и
красным тоже. На сервер не ходили ни одной командой.

Отчёт — docs/superpowers/priyomka/stroyka-1/z-0-2-pochinka-sverki-2026-08-05.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:45:54 +03:00
Дмитрий f7cc8c8bce fix: чистка записей молча ругалась при недоступном журнале
Глушилка ошибки стояла хвостом после ">>" и не работала: оболочка разбирает
перенаправления слева направо, и ругань про недоступный журнал успевала
вылезти раньше. Чистка не падала, но в почту расписания сыпался мусор.
Лечение - глушилка на группе.

Сторож дорос до 23 проверок: добавлены папка из переменной окружения и
недоступный журнал. Изъян показан красным на старом варианте.

Отчёт З-0-2 дописан целиком: полный прогон 4930 проверок, красных 0,
код 0; зовущие поимённо; открытые вопросы владельцу.
2026-08-05 17:25:04 +03:00
Дмитрий 09c42a956c feat: выключатель записи разговоров Лены и чистка записей по сроку
Записи разговоров копились в /tmp/lena-inworld бессрочно, включая голоса
посторонних людей с живых входящих звонков. Три вещи:

1. bots/lena-golos/extensions-lena.conf - копия настройки телефонии с
   сервера, номер замаскирован намеренно. Настройка жила только на сервере
   и дважды молча откатывалась - нужен эталон для сверки.
2. Выключатель записи: раздел globals со строкой ZAPIS_RAZGOVOROV и обе
   строки записи через ExecIf. Гасит обе Лены сразу. Запись не является
   условием разговора: при ложном условии управление идёт дальше на
   AudioSocket. Незнание = не пишем.
3. bots/lena-golos/chistka-zapisey.sh - чистка по сроку. Папка и срок
   задаются доводом или переменной. Заготовки chelovek*, imya.txt и
   подпапки не трогает никогда - два независимых замка. Пустой прогон
   тоже оставляет след. Срок 72 часа временный, назначает владелец.

Сторож bots/lena-golos/proverka-chistki.sh: 19 проверок на своей временной
папке, показан красным четырьмя разными поломками лечения.

На сервере выключатель ПОКА НЕ ПРИМЕНЁН - это записано в README.
2026-08-05 17:14:22 +03:00
Дмитрий 0a154b251b docs: скелет отчёта З-0-2 по записи разговоров Лены
Заведён отчёт круга стройка-1, задание З-0-2. Пишется по ходу работы.
2026-08-05 16:50:21 +03:00
Дмитрий 350bf8a61a docs,обзвон: промт смене 2 переписан целиком под сегодняшнее состояние
Прежняя редакция устарела за один день, и это записано в самом промте первой же
строкой: числа в промтах живут сутки. Новый файл заводить не стали намеренно —
два промта на одну стройку дали бы два источника правды.

Что переписано: семь уроков надзирателя вместо пяти, с двумя новыми, которые
вскрылись сегодня; числа собраны командой заново — 49 задач, 93 решения, прогон
сервера 4930 и прогон интерфейса 2095 при нуле красных; тринадцать коммитов
стройки перечислены поимённо, потому что по вершине ветки их не опознать —
чужие смены коммитят между нашими; порядок работ переставлен, первой стоит
задача про срок хранения записей разговоров, единственная обязанная закрыться
до первого живого звонка; решений в таблице теперь десять, Р84 по Р93.

Прибавлен раздел граблей про проверку бумаг: крючок перед коммитом не смотрит
разметку и правописание в docs/superpowers, это проверено строками 41 и 63
файла хуков, и гонять сторожа по своим файлам надо руками. Прибавлены грабли
про интерфейс: где на самом деле живут проверки экранов, почему их отсутствие
рядом с экранами обманчиво, и что прямой вызов сервера из админского экрана —
принятый порядок, а не отступление.

Разметка и правописание нового промта проверены вручную местными сторожами,
ноль ошибок в обоих.
2026-08-05 16:27:31 +03:00
Дмитрий 7f0ff8f5ab docs,обзвон: решение Р93 — один ноль в цене остаётся разрешённым, уже зная замер
Владельцу показан замер: при нуле за минуту и двух рублях за соединение час
разговора стоит клиенту два рубля, а оператору за шестьдесят минут платим мы.
Это ровно та беда, которую он сам назвал словами при Р90, только достигнутая
другим путём. Увидев замер, владелец оставил правило прежним — запрещены только
два нуля разом.

Записано отдельным решением, а не правкой Р90: основание другое. Р90 стояло на
«оба нуля одинаковы», что замер опроверг; Р93 стоит на «цену ставит админ, то
есть я сам». Отрезаны обе узкие починки. Записано вслух и то, чего решение не
закрывает: дыра остаётся открытой намеренно, ошибочный ноль за минуту в отчёте
будет выглядеть нормальной работой, предупреждения на экране нет.

Протокол вырос с 92 решений до 93.
2026-08-05 16:14:57 +03:00
Дмитрий 03e07cafd1 docs: промт смене 23 — забрать четыре прогона и поймать возврат по сроку
Работа смены: снять урожай с четырёх запущенных прогонов приёмки, поймать
последнюю бесплатную карточку Я-Д5 по летописи проводок и провести Я5.

Что несёт промт помимо состояния:

  — пороги, на которых закрываются Я3 и Я4: 1667 и 834 показа, и правило
    мерить скорость последним часом, а не средним за сутки;
  — рычаг управляемого отказа модерации — два конкретных креатива, которые
    Яндекс забраковал дважды подряд; прежнее решение про текст не работает;
  — два способа добиться «впритык» без правки денежной летописи: долив до
    круглой суммы или временная кампания-подпорка;
  — предупреждение, что сторож зависимостей красный из-за недоделанных
    файлов соседней смены и чужое чинить не нужно;
  — четыре ложные тревоги смены 22 одного корня: вывод по косвенному
    признаку вместо вопроса той стороне, которая знает ответ. Главная —
    «робота картинок не устанавливали», а он работал на третьей машине,
    и журнал веб-сервера отвечал на это одной командой;
  — ловушка записи на бою: tinker молча глотает длинные и многострочные
    куски, нужен самостоятельный php-скрипт с загрузкой приложения.

Разметка чисто, 239 строк.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 16:11:11 +03:00
Дмитрий 81f2a77c04 docs,обзвон: приговор по двум кругам владельца и седьмая ошибка надзирателя
Круги З-1.8 и З-1.9 приняты своей рукой, а не по отчётам помощников. Сторожа
резал сам и оба раза другим ножом, чем исполнитель: у запрета двух нулей
покраснели две проверки из шести, у экрана тарифа — ровно одна, та самая, что
стережёт оговорку про цену вслепую. Возврат обоих файлов доказан слепком, а не
памятью. Прогоны своей рукой: сервер 4930 проверок при нуле красных, интерфейс
2095 проверок в 257 файлах при нуле красных.

Вырезание второго рода нашло дыру, которой не видел никто: запрет ловит два нуля
разом, но ноль за минуту при ненулевом соединении пропускает, и тогда час
разговора стоит клиенту два рубля, а оператору за шестьдесят минут платим мы.
Замерено прибором, решение Р90 не переоткрывается — это вопрос владельцу.

Седьмая ошибка надзирателя: в проверки задачи З-1.9 записано «видно, кто и когда
менял цену и с чего на что», а выполнить это нельзя — ручка отдаёт только дату,
ручки чтения журнала админов не существует. Проверка списана с задачи З-1.3, где
речь про запись следа, а не про его показ. Класс тот же, что у первых шести:
утверждение о коде без замера кода. Нашёл снова исполнитель. Починено в бумагах:
проверка переписана на выполнимое, показ истории правок прибавлен в состав З-4.7.

Попутно в приёмочном листе разведены три одинаковых заголовка «Приговор» — они
мешали разметке и были там до этой правки, крючок этот путь не проверяет.
2026-08-05 16:03:37 +03:00
Дмитрий a0bb03efdd З-1.9: экран тарифа обзвона — цену меняет мышка, а не программист
Решение владельца Р91: ручка AdminObzvonTariffController готова с задачи
З-1.3, но экрана к ней не было. Добавлен экран AdminObzvonTariffView.vue
с двумя полями цены, оговоркой про вслепую назначенные цифры и человеческими
текстами отказов, один пункт меню /admin/obzvon-tariff в роутере, 9 проверок
интерфейса в admin-obzvon-tariff-view.spec.ts.

Честно: пункт 5 задания (кто и когда менял цену, с чего на что) закрыт
частично — ручка отдаёт только дату правки, кто менял и старое/новое значение
пишутся в saas_admin_audit_log, но ручки чтения этого журнала для экрана нет
и заводить её было нельзя (правка бэкенда запрещена заданием). Подробности —
в отчёте docs/superpowers/priyomka/stroyka-1/z-1-9-ekran-tarifa-2026-08-05.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 15:52:34 +03:00
Дмитрий 1c2195ebee fix(обзвон): два нуля в тарифе разом запрещены, один ноль можно
Решение владельца Р90 (docs/grilling/2026-08-03-metodika-lena-pod-klienta.md):
цена звонка — два поля, за соединение и за минуту. Оба нуля разом означали
молча бесплатный обзвон: клиент не платит, а оператору за звонки платим мы.
Одна цифра в нуле — осмысленный случай, например не брать отдельно за
соединение.

AdminObzvonTariffController::update() теперь сравнивает обе цены ПОСЛЕ
перевода в копейки и отказывает с объяснением, если обе — ноль. Ловит «0»,
«0.00» и «0.0» одинаково, а не по виду строки. Прежние отказы (пустая,
отрицательная, нечисловая цена) не тронуты.

ObzvonTariffTest.php: +6 проверок «З-1.8». Сторож доказан красным дважды —
до фикса (естественный RED) и после снятия запрета (искусственный RED),
восстановление сверено побайтово через git hash-object.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 15:29:09 +03:00
Дмитрий a9de42ccbc docs(приёмка Яндекса): Я3 и Я4 запущены; поправлена неверная оценка скорости
Владелец: «я3-я4 делай». Обе кампании собраны на минимуме площадки — 1667
показов за двое суток, смета 833,50 руб. Меньше площадка не берёт, а больше
и не нужно: чем меньше смета, тем быстрее она откручивается целиком.

  #19 «Я3 — приняли часть, вся смета» — 13 принятых картинок плюс те две,
      что Яндекс бракует у #6; в Директе 713318844, заперто 833,50 руб;
  #21 «Я4 — впритык, одобрено, половина сметы» — только принятые картинки,
      заперто 833,50 руб.

ПОПРАВКА к записи того же утра, и она важная. Я записал «Яндекс показывает
около одного раза в час, вся смета — полтора месяца, ускорить нечем». Это
ошибка измерения одной точкой. Летопись списаний по #13 показывает не ровную
струйку, а разгон: 09:00 — 6 показов за час, 10:00 — 5, 11:00 — 13, 12:00 —
25. Минимум площадки 834 показа в сутки, значит «вся смета» требует в среднем
35 показов в час, «половина» — 17. На 25 и с ростом это сутки-двое, а не
месяцы. Прежний абзац оставлен зачёркнутым, чтобы урок не потерялся: скорость
рекламной выдачи меряется последним часом, а не средним за сутки.

Как добились «впритык» второй раз: свободных было 6 666,50, а смета нужна
833,50. Доливом остаток только растёт, поэтому лишнее временно заняли
кампанией-подпоркой на 5 833,00 — она ушла на модерацию, то есть показов не
делает и денег не тратит. Свободные стали ровно 833,50, Я4 запустилась при
точном равенстве, подпорку сняли. Условие проверяется в момент запуска,
приём честный. Подпорка останется в кабинете на паузе: удаляются только
черновики.

Д=«Исправить» в обоих прогонах — SKIP, и это не лень: кнопка по построению
работает только у отклонённой кампании. Проверено живьём на #6 (принята
часть) и #13 (принята целиком) — обе ответили отказом 409 с понятным текстом,
статус и баннеры не тронуты, кошелёк не шелохнулся.

Счёт по комбинациям: закрыты 4 из 9, ещё четыре запущены и ждут вердикта.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 15:24:37 +03:00
Дмитрий 1eb56f5b18 docs,обзвон: две работы владельца заведены в план, и шестая ошибка надзирателя названа
Решения Р90 и Р91 стали задачами З-1.8 «два нуля в цене нельзя» и З-1.9 «экран
тарифа». План вырос с 47 задач до 49.

Шестая ошибка надзирателя: промт смене 2 утверждал, что экрана тарифа в плане
нет ни одной задачи. Неверно — он был внутри З-4.7 первой строкой состава.
Утверждение о плане делалось без сверки с планом, тот же класс, что первые пять.
Нашлось при заведении задачи: пошёл смотреть, куда её класть, и увидел, что она
уже там. Тариф вынесен из З-4.7 в раннюю З-1.9, потому что причина владельца
обратная по сроку — цену придётся менять сразу после первых живых звонков, а
З-4.7 стоит в волне 4 за цепочкой из трёх экранов. В З-4.7 оставлена ссылка,
чтобы не построили дважды.

В таблицу узких горл добавлено то, чего в ней не было вовсе: сквозные проверки
перед коммитом — deptrac, статанализ и сторож канона схемы — тоже горло. Они
смотрят на всё хозяйство разом, и незаконченный кусок одного круга рубит коммит
всем. Проверено дорого на стройке первой смены: два круга с разведёнными файлами
заблокировали друг другу коммит. Отсюда правило расстановки: спрашивать не только
про разные файлы, но и про новые классы и таблицы.
2026-08-05 15:16:42 +03:00
Дмитрий 0784384a9e docs,обзвон: в промте смене 2 вершина ветки устарела за сутки
В эту ветку коммитят и чужие смены — вершина ушла на чужой коммит ad4a41fb9,
и по ней больше нельзя судить, что сделано нами. Числа в разделе 2 пересчитаны
командой: список коммитов смены поимённо, третий полный прогон 4924 проверки
при нуле красных, и отдельная оговорка, что вершина признаком нашей работы
не является.

Бумаги плана, спеки и протокола перемеряны — 47 задач, 96 требований,
92 решения, без изменений.
2026-08-05 15:07:13 +03:00
Дмитрий ad4a41fb9d docs(реклама): порог предупреждения о деньгах разобран до конца
Владелец решил поднять порог с 20 до 2000 руб. Разобрано, вывод неудобный.

Настройка не там, где казалось. У кампании свой порог WarningBalance есть, но
Директ отказывает прямым текстом: значение должно быть в диапазоне от 1 до 50.
Больше 50 руб там не поставить в принципе.

Настоящая настройка у общего счёта: MoneyWarningValue = 20, счёт 712890032,
письмо на Sasha261185@yandex.ru. Видно через старую ручку AccountManagement.

Менять её программой нельзя: та же ручка на запись отвечает «Сервис временно
недоступен» во всех трёх формах запроса. Чтение работает, запись закрыта.
В новом API такого поля нет вовсе.

Браузером тоже не зайти: вход робота креативов слетел, профиль перебрасывает
на паспорт. Восстанавливается только руками владельца — пароль и код из СМС.

Значит порог меняется только в кабинете руками. Место записано.

Что программой сделать УДАЛОСЬ: у всех шести наших кампаний было выключено
SendWarnings — письма о событиях кампании, включая отказ модерации, не
приходили вовсе. Включено по решению владельца, проверено чтением обратно.

Записана и ловушка на будущее: портал этот порог при создании кампании не
задаёт вообще, Яндекс ставит свой умолчательный 20 руб.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 15:04:26 +03:00
Дмитрий 957f3d68d1 docs,обзвон: девять решений владельца, приёмочный лист смены и промт смене 2
Первая смена стройки закрыла пять задач денежной волны из семи плюс круг
починки. Бумаги приведены в соответствие с тем, что вышло.

Протокол допроса: 83 решения стало 92. Владелец решил по ходу стройки:
- Р84 на машине робота работать можно, осторожно;
- Р85 тихую недостачу трёх живых каналов чинит отдельная смена;
- Р86 письмо про возврат рекламы не трогаем до починки дороги назад;
- Р87 потолок цены решаем после первых живых звонков;
- Р88 пятый исход звонка не заводим;
- Р89 правку общего файла хуков оставляем;
- Р90 два нуля в цене запрещаем;
- Р91 экран тарифа заводим задачей в план;
- Р92 метки маскирования ПДн отложены.

Владелец поправил бумагу, и поправка настоящая: план говорит, что за звонок
снял трубку и сразу бросил берутся 2 рубля. Проверено прибором - двенадцать.
Два рубля за соединение плюс десять за начатую минуту, минута уже началась.
Ошибка плана, найденная заказчиком.

Приёмочный лист смены написан ДО работы, как требует метод, и дополнялся по
ходу. В нём точка отсчёта, приговор по каждому кругу своей рукой, улов судьи
и пять ошибок надзирателя, названные вслух. Все пять одного класса: пересказ
вместо цитаты и доверие бумаге вместо замера. Каждый раз спасал несогласный
исполнитель.

Промт смене 2 несёт вперёд пять оплаченных уроков, полный список запрещённых
файлов включая общие, и новое знание про узкие горла: сквозных проверок нет
в таблице плана, а они горло не хуже файлов. Два круга с разведёнными файлами
всё равно заблокировали друг другу коммит.

Проверено командой: протокол 92 решения и 7 разделов, план 3341 строка и
47 задач, спека 96 требований. Полный прогон своей рукой три раза за смену:
4802, 4860 и 4924 проверки, красных ноль каждый раз.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 14:56:52 +03:00
Дмитрий 49ef80cd55 fix(реклама): возобновление выдавало непроверенную кампанию за крутящуюся
Прогон Я6 приёмочного листа на боевом, с разрешения владельца трогать кошелёк
тенанта 2. Кошелёк только пополняли — из летописи ничего не вынимали.

Подгонка под «впритык»: свободных было 7 422,76 руб, долили 77,24 руб до
круглых 7 500,00 и завели кампанию на 15 000 показов по 500 руб за 1000 =
смета ровно 7 500,00 руб. Деньги отработали безупречно: запуск при точном
равенстве прошёл, заперли ровно смету, свободных осталось ровно ноль и в
минус не ушли; пауза вернула всё целиком, возобновление заперло столько же;
в летописи три честные строки, строка заморозки одна и та же.

А вот статус врал. На паузу можно поставить и кампанию, которую Яндекс ещё
проверяет — это задумано. Но «Возобновить» ставило running БЕЗУСЛОВНО, и
портал показывал зелёное «Крутится» рекламе, которой Яндекс показываться не
разрешал: показов нет и быть не может. Та же болезнь, что уже ловили на
кампании 6. Потери вердикта нет — часовой обход берёт и крутящиеся тоже.

Починка: «Крутится» ставим только когда вердикт вынесен, иначе возвращаем
«на модерации». Мерка «решено или нет» взята ТА ЖЕ, что у часового обхода:
баннер не решён, пока он не ACCEPTED и не REJECTED. Две разные мерки одного
и того же однажды разойдутся.

Сторож VozobnovlenieNeVryotProStatusTest — три проверки: не врёт на
непроверенной, не ломает одобренную, деньги ведут себя одинаково при любом
вердикте. Принят красным: до починки отдавал running.

Ловушка сторожа записана в журнал: без заглушки на отчёт о показах пауза
отвечает 200, но деньги намеренно не отпускает.

Счёт по комбинациям: закрыты 4 из 9 — Я6, Я7, Я8, Я9.

Прогоны: 430 тестов рекламы зелёные, pint чисто, статанализ 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 14:04:07 +03:00
Дмитрий 1ceba0c567 docs(приёмка Яндекса): Я1 и Я2 запущены живьём, ждут вердикт модерации
Владелец разрешил живые запуски. Заведены две кампании тенанта 2:

  #16 «Я1 приёмка — одобрение и ноль показов» — 15 баннеров с принятыми
      креативами #13, в Директе 713315004, заперто 850,00 руб;
  #17 «Я2 приёмка — отказ модерации» — только два баннера, которые Яндекс
      уже отклонял у #6, в Директе 713315067, заперто 850,00 руб.

Обе в pending_moderation, все баннеры в MODERATION. Заморозка сошлась со
сметой копейка в копейку — ещё одно живое подтверждение Я-Д1.

Записан честный вывод: управляемого способа получить отказ модерации у
портала НЕТ. Решение владельца от 03.08 «отказ — текст про займы под залог»
на деле не работает: название кампании до модерации не доезжает. Живое
доказательство — #6 с этим самым названием и обычной страницей liderra.ru:
Яндекс принял 13 баннеров из 15. Отклонённые два — 320x50 и 320x100, причину
Яндекс не назвал, а те же размеры у #13 приняты, значит дело не в размере.
Поэтому #17 собрана из тех самых отклонённых креативов — это ставка на
повтор вердикта, а не управляемый отказ.

Что проверить следующей смене: вердикты по обеим, полный возврат заморозки
при отказе, и остановить обе после замера, чтобы не капало по 0,50 руб в час.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 13:42:18 +03:00
Дмитрий a0761a5c38 fix(реклама): отказ по деньгам говорил клиенту по-английски
Прогон Я7 приёмочного листа на боевом: черновик со сметой 15 000 руб при
свободных 9 122,76 руб. Запуск не состоялся правильно — в Директе не создано
ничего, деньги не тронуты, кампания осталась черновиком. А вот текст отказа
доезжал до клиента как есть:

    Insufficient balance: price_kopecks=1500000, balance_rub=9122.76

Причина: InsufficientBalanceException наследует RuntimeException, и ручка
запуска ловила его общим уловителем, отдавая наружу getMessage. Кнопка
«Возобновить» этой болезнью не болела — там свой уловитель с человеческим
текстом, и он же показал, что сломан именно запуск.

Починка: отдельный уловитель ВЫШЕ общего. Наружу — только клиентские рубли:
сколько нужно и сколько свободно. Ни копеек, ни английского, ни нашей доли.

Сторож PonyatnyyOtkazPoDengamTest — три проверки: нет английского и копеек,
названы оба клиентских числа, нет цены рекламной площадки. Принят красным:
до починки отдавал ровно техническую строку.

Заодно: срок мобильного прокси продлён до 03.09.2026 — поправлена устаревшая
подсказка в config/services.php. На боевом дата уже заменена, плитка стала
зелёной: «жив, IP 92.36.112.83, до 03.09.2026».

В журнал приёмки записаны прогоны Я7, Я8, Я9 — все три закрыты живьём и
бесплатно — и пересчёт цены комбинаций: деньги уходят только за настоящие
показы, поэтому семь прогонов из девяти стоят ноль. Настоящая стена не
денежная, а временная: сегмент 1653 человека даёт около показа в час, и
«вся смета» это полтора месяца.

Прогоны: 427 тестов рекламы зелёные, pint чисто, статанализ 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 13:09:35 +03:00
Дмитрий 814c45e8b3 docs(приёмка Яндекса): промт смене 22 — возврат по сроку и что делать дальше
Смена 21 закрыла приёмку Яндекса почти целиком: из 29 карточек пройдены 27.
Остались две, и обе ждут не работы, а события — живого отказа всех объявлений
разом и платных комбинаций Я1-Я9.

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

Пять уроков, из которых главный второй: сторож, который НЕ покраснел при
вырезании, — это сигнал искать вторую дорогу, а не повод успокоиться. Именно так
нашлась двойная подписка на остановку рекламы.
2026-08-05 11:03:38 +03:00
Дмитрий 652b708203 fix(реклама): остановка рекламы делалась дважды; добраны все бесплатные карточки приёмки
Из 29 карточек приёмки Яндекса закрыты 27. Остались две, и обе ждут не работы,
а события: живого отказа всех объявлений разом и платных комбинаций Я1-Я9.

Нашлась вторая за день тихая беда. Слушатель остановки рекламы был подписан на
событие ДВАЖДЫ: Laravel 11 сам находит слушателей в app/Listeners по типу
параметра handle(), а в провайдере он вдобавок прописан руками. Остановка не
бесплатная: по каждой кампании клиента она идёт в Яндекс за числом показов,
платит за показанное и глушит кампанию, - и всё это делалось по два раза.
Деньги уцелели по случайности: списание идемпотентно по ключу показов, снятие
заморозки тоже, а второй заход не находил кампаний, первый уже увёл их из
работы. Ручная подписка убрана.

Найдено не глазами, а вырезанием: новый сквозной сторож Я-Б3 не покраснел,
когда подписку отключили. Если бы регистрация была одна, он обязан был.

Замерено на живой кампании #13, без единого рубля сверху:
- Я-Д3: показано 21, списано 10,50 руб = 21 x 500/1000; по смете было бы 850;
- Я-М2: кампания running, заморозка 839,50 = 850 - 10,50, показы идут;
- Я-Х4: задача из очереди под боевой ролью без контекста клиента видит
  1 кампанию служебным путём и 0 обычным - тот самый молчаливый ноль,
  ради которого служебный путь и заведён.

Новые сторожа, каждый принят красным:
- Я-Б2: денег ровно на смету - запуск проходит, вторая кампания уже нет;
- Я-Б3: деньги кончились - кампания РЕАЛЬНО встала и владельцу ушло письмо;
- Я-М4: пока вердикта нет, не двигаются ни заморозка, ни списание;
- Я-М5: после «Исправить» и повторного запуска заморозка ОДНА;
- Я-Х2: десять подделок отбиты, чужой номер клиента ничего не меняет;
- Я-Д1: заморозка равна смете копейка в копейку, включая некруглую;
- Я-Д2: сплошной обход всех семи читающих путей - наценка не видна нигде
  (прежний сторож проверял один путь из семи);
- остановка рекламы подписана ровно один раз.

Прогоны: 424 теста рекламы зелёные, статанализ 0, формат чистый.

Журнал результатов приёмки дописан разделом на 05.08 - что закрыто, чем
закрыто и чего ждём.
2026-08-05 09:52:10 +03:00
Дмитрий d8cfac6c32 docs(обзвон): промт стройки готов к запуску — чем занять смену, пока ждём разрешения
Промт дописан под сегодняшнее состояние. Числа пересобраны: вершина 90cf01b37,
протокол 83 решения, план 3341 строка.

Главная правка — §4.1. Первые два круга идут на сервере робота, а он делит машину
с рендером боевого портала и с платным Поиском клиентов, поэтому нужен явный
допуск владельца. Раньше промт говорил только это — и смена могла сесть ждать.
Теперь сказано прямо: спросить первым сообщением одной фразой и НЕ ждать сложа
руки. Названа работа, которая сервера не касается вовсе: волна 1 деньги, семь
задач, самый крупный кусок стройки; волна 2 материалы клиента, пять задач;
тумблер видимости, обязанный быть сделанным до того, как экран получит адрес.

Тут же названо, чего в это время делать нельзя: объявлять волны 1 и 2 закрытыми.
Их проверки упираются в перевод звонка, а он на сервере. Написать можно, закрыть
нельзя.

Дописано в раздел про сделанное: сторожа текста починены сегодня, но проверять
их живость на входе смена обязана всё равно — чинил их я, а оборваться установка
может снова.

Проверено: 379 строк, 8 разделов, разметка чистая живым сторожем.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 09:31:11 +03:00
Дмитрий 90cf01b374 docs(обзвон): владелец закрыл ВСЕ хвосты — 11 решений, план перестал врать
Разбор хвостов перед стройкой. Ждущих ответа вопросов у стройки больше нет:
шесть «Новое-1…6» из плана закрыты, плюс пять решений сверх них. Протокол
83 решения вместо 72.

Что решил владелец:
- Р73 этикетка чужого юрлица остаётся как есть;
- Р74 дорогу назад для рекламы чинит отдельная смена — до первых живых денег
  обзвона;
- Р75 юриста про голос за границу не спрашиваем, идём как есть. Риск законный
  и он остаётся — записан прямо, а не спрятан;
- Р76 правило часов одно на СМС и обзвон, живой СМС-модуль правим;
- Р77 пять номеров арендуем к первому живому обзвону — ОТМЕНЕНО решением Р83;
- Р78 тариф 2 плюс 10 остаётся, уточним по замеру;
- Р79 длину и содержание речи решает клиент, хвост про опенер снят;
- Р80 робота без слов-запиналок слушаем на приёмке;
- Р81 телефония уезжает на новую АТС, Манго — только испытание;
- Р82 расшифровка чужих записей живёт ШЕСТЬ месяцев, звук 30 дней;
- Р83 у Манго ничего не арендуем, переезд робота в план обзвона не заводим.

Три решения меняют сам план, и правки внесены:
- Р76 разблокировала З-3.1 целиком — развилка «одно правило или второй дом»
  стояла открытой и ждала ровно этого. Отмечено, что круг на боевой файл
  отдельный: своя приёмка, свои две строки про соседей, свой выкат;
- Р82 отменила мою страховку «расшифровка уходит вместе со звуком». Сроков
  теперь два, и чистка обязана стереть звук не тронув текст, а требование
  «сотрите меня» — достать до текста, когда звука уже нет;
- Р81 и Р83 превратили «до аренды» в «до новой АТС» в З-3.3.

Своя неточность названа вслух: в вопросе про часы я сказал «одна настройка»,
хотя решается общий код правила. Часы рассылки и часы обзвона остаются разными
числами — этого требует Т36 и проверка 8 в З-3.1. Записано и в протоколе,
и в плане, чтобы никто не прочитал Р76 как «одни часы на двоих».

Найдено при разборе: два вопроса владельцу, добавленные редактором, не попали
в промт смене 8 — «с какого кода звоним» и «расшифровки чужих записей». Оба
заданы и закрыты. Промт исправлен.

Работа, которая теперь не живёт нигде: перевод машины робота на новую АТС.
В план обзвона не заводим по решению владельца, но машина прописана на Манго
намертво. Названо вслух в протоколе и в промте.

ОБА СТОРОЖА ТЕКСТА БЫЛИ МЕРТВЫ — вскрылось при этом же коммите. Пакеты стояли
на месте, но внутри пустые: у одного остались только лицензия и схема, у другого
файл обрывался посреди строки. Причина — установка, оборванная на пакете,
которому нужен компилятор C++, а его на машине нет.

Два вывода записаны в промт смене 8:
- прежний датчик «посчитай папки в node_modules, должно быть под 750» ЛОЖНЫЙ:
  он показывал 745 при полностью мёртвых сторожах. Заменён на запуск самих
  программ;
- npx МАСКИРУЕТ поломку: не найдя программу на месте, молча качает чужую версию
  из сети, и проверка «проходит». Три отчёта «разметка чистая» в этой сессии
  опирались на неё и доказательством не были.

Починено: сломанные пакеты снесены и поставлены заново без сборки. Сторож
орфографии показан КРАСНЫМ на подсунутой ошибке — только после этого ему верю.
Он же нашёл настоящее: слово «запиналки» отсутствовало в словаре, добавлено.

Проверено командой: план 3341 строка, 21 раздел, 47 задач, по волнам
7·7·5·8·9·3·8. Протокол 83 решения, 7 разделов. Разметка и орфография чистые
живыми сторожами, а не скачанными.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 09:19:27 +03:00
Дмитрий 7c8618becc fix(портал): 404 называл посторонним внутренние имена, красную подпись не охранял никто
Живой замер 05.08.2026: любой вошедший клиент, запросив несуществующий или чужой
номер, получал в ответ «No query results for model [App\Models\AdCampaign].»
Три беды в одной строке. Английский язык — клиенту он ничего не говорит. Названы
внутренние имена: и класс, и раскладка папок портала. И сообщение подтверждало,
что за номером стоит именно кампания, — а на чужой номер портал обязан отвечать
ровно так же, как на несуществующий, ничего не подтверждая.

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

Место общее на весь портал: так отвечал КАЖДЫЙ firstOrFail() во всех разделах.

Ловушка: обработчик на ModelNotFoundException не срабатывает никогда — Laravel
успевает завернуть её в NotFoundHttpException раньше. Поймано тем, что сторож
остался красным с тем же самым английским текстом.

Второе: под слотом баннера есть красная подпись — единственное место, где клиент
узнаёт, почему картинка не загрузилась. Сторожа на неё не было ни одного. Пропади
она — заметить было бы некому: клиент жмёт «загрузить», ничего не появляется, и
никакого объяснения. Написаны три: подпись показывает слова сервера, а не общую
отговорку; пока отказа нет, подписи нет вовсе; сервер промолчал — портал всё равно
объясняет.

Ловушка: extractErrorMessage достаёт слова сервера только у настоящей ошибки axios.
Подделка без isAxiosError проваливается в общую отговорку, и сторож зеленеет, не
проверив того, ради чего написан.

Прогоны: 3909 тестов Feature зелёные, vue-tsc чисто.

Заодно промт смене 21 дописан утренними итогами: выкат сделан, восемь карточек
пройдены, снята ложная тревога про главную ветку, добавлен разбор чужого слияния.
2026-08-05 08:32:03 +03:00
Дмитрий 2c72a0cb6b feat(смс): своё имя есть, но у этой сети не согласовано — номер не уходит вовсе
Решение владельца 05.08.2026. Прежний вариант (подписать нашим «Liderra.ru»)
подменял бренд, за который клиент заплатил, причём незаметно: журнал сообщений
имя отправителя не хранит вовсе. Так уже работает отдел продаж
(SmsRecipientSelector → SKIP_NO_SENDER), и надпись на клиентском экране
(«нет имени отправителя для оператора») давно лежала готовая — её просто никогда
не показывали.

Два случая разведены НАМЕРЕННО и закреплены отдельными тестами:
  • своего имени нет вовсе (или приостановлено) — шлём от имени Лидерры, как
    и раньше. Смешай их — и рассылка встала бы у ВСЕХ разом: на бою своих имён
    заведено НОЛЬ;
  • своё имя есть, но у этой сети не согласовано — номер не уходит.

Отсев в ОТБОРЩИКЕ, а не при отправке: деньги не замораживаются, и причина видна
клиенту в предпросмотре — до оплаты.

🪤 Полный прогон поймал мою ошибку, которую выборочные тесты не видели: имя
спрашивалось ПО КАЖДОМУ номеру — 20 000 запросов в базу, отбор 20 000 получателей
вырос с 20 до 29 секунд и упёрся в сторожа скорости. Добавлена памятка на тенанта
(та же защита, что у AllowedSmsOperators, который прямо об этом предупреждает).
После лечения — 1,47 с.

Два теста часовой давности переписаны: они закрепляли ПРЕЖНЕЕ решение и после
смены решения стали неправдой. Теперь проверяют и «в канал не ушло ничего», и
«деньги целы».

Узкая щель записана в коде: если админ сузит список операторов у имени ПОСЛЕ
создания рассылки, такой номер уже лежит в снимке и уйдёт подписанным нашим именем.
Случай редкий — пересогласование переводит имя в «на рассмотрении», а это снимает
блокировку.

Проверено: 4621 тест, упал один чужой (ExampleTest — в рабочей папке не собран
фронтенд). Статанализ 0. Стиль чист.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 08:21:28 +03:00
Дмитрий 4ff02f6935 docs(обзвон): промт смене 8 — стройка кругами по методу, все бумаги готовы
Все ступени метода до стройки пройдены: спека, ворота вслепую, план, ворота
вслепую и суд, редактор. Следующая смена строит.

Промт устроен так, чтобы смена двигалась по методу строго, а не по своему
разумению:
- §0.1 велит прочесть метод ЦЕЛИКОМ и даёт команду достать его из чужой ветки —
  в нашей его нет;
- §0.2 отдельно выносит правило «правщик — не автор», которое прошлая смена
  нарушила, вместе с ценой нарушения: судья нашёл шесть ошибок, чинил их автор,
  редактор снял пять из шести. Замер: самопроверка автора стоит примерно одну
  шестую от проверки чужими глазами;
- §0.3 повторяет устройство круга дословно из метода: задание целиком, помощник
  в углу, коммит, приговор выносит надзиратель сам;
- §4.3 напоминает четыре мерки метода, включая сторожа, показанного красным.

Числа собраны командой и помечены как подлежащие пересбору на входе. Упавший
тест назван чужим с доказательством: в одиночку файл проходит 10 из 10.

Названы первые круги — З-0.2 записи разговоров и З-0.1 чужое имя, обе до первого
живого звонка и обе на сервере робота, то есть только с разрешения владельца.
Названы предусловия волн: волна 5 не начинается без денег и стоп-листа, З-4.9
тумблер видимости делается первой в волне 4, иначе все клиенты увидят
недостроенный обзвон.

Восемь хвостов владельца, из них тикающие: этикетка чужого юрлица на экране у
человека (заявка десять дней), аренда пяти номеров, юрист про трансграничную
передачу голоса, правка живого СМС-модуля ради клиентских часов, дорога назад
для рекламы.

Грабли смены дописаны: сторож орфографии смотрит docs/grilling и не смотрит
docs/superpowers; чужой замок git не снимать самому; php artisan test, не
composer test; кириллица в словарь только через AppendAllText.

Прежний промт помечен отработанным, чтобы его не взяли в работу заново.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 07:48:50 +03:00
Дмитрий c11ee3ad87 docs(обзвон): редактор снял пять заплаток из шести — 47 задач, этап 5 закрыт
Метод велит: правщик — не автор. Правило нарушили — шесть находок судьи чинил
тот, кто их допустил. Свежий редактор проверил эти заплатки и снял ПЯТЬ ИЗ ШЕСТИ.
Замер записан в план: самопроверка автора стоит примерно одну шестую от проверки
чужими глазами.

Что не выдержало:
- «семь заходов в мост»: таблица исправлена, а в самих задачах порядок остался
  старый — З-4.5 звала себя последней, З-6.7 ждала её. Исполнитель читает задачу,
  а не таблицу;
- имена наставлений робота ВЫДУМАНЫ: по мосту строка 41 — lena-vhodyashchie-promt,
  а план написал lena-priyomshchik-promt. Плюс в наставления подмешиваются три
  файла базы знаний, которых план не назвал вовсе;
- З-4.8 закрыла Т23 наполовину: требуется четыре заготовки, названа одна;
  у Т13 молчаливый робот проходил все пять проверок;
- З-6.8: имя очереди задаётся внутри задания, а не в routes/console.php — тот же
  класс ошибки, за который судья ругал соседнюю задачу; и задача стояла последней,
  хотя задания пишутся в волнах 1, 3, 5;
- проверки манеры: «в тексте нет слов про манеру» покраснеть не могла — что
  считать словом про манеру, не сказано нигде; вторая половина находки судьи не
  починена вовсе;
- порядок по узким горлам: из пяти расхождений судьи три остались, и добавилось
  новое.

Выдержала одна: переписанная проверка дословности каркаса в З-4.3.

Редактор нашёл сверх этого: Т17 — четвёртое требование без задачи, пропустили и
автор, и судья; «с какого кода звоним» из §18 спеки в плане не было ни слова;
Р72 исполнено наполовину. Внёс 33 правки, добавил раздел приёмки шестью сквозными
кругами и два вопроса владельцу. Проверил числа командой и нашёл семь неверных:
web.php 799 а не 783, чертёж записей на 3780 а не 3776, DealController а не
DealsController, «11 задач на схему» на деле 10, «5 в расписании» 4, «восемнадцать
хвостов» 24, «Р1-Р70» при 72 решениях.

Поверх редактора надзиратель добавил своё:
- З-4.9 тумблер видимости модуля — редактор назвал беду, но сказал прямо, что
  нужна новая задача, а не заплатка. Пункт «ИИ колцентр» уже стоит в меню без
  адреса; З-4.1 дописывает адрес — и все клиенты видят недостроенный обзвон.
  Своего включателя у модуля нет, это уже ловили при выкате рекламного модуля.
  Задача делается ПЕРВОЙ в волне 4, до З-4.1;
- две устаревшие ссылки на раздел «Два места, где нужно слово владельца» — раздел
  переименован, а спор двенадцати и десяти закрыт решением Р71.

Проверено командой: 3258 строк, 20 разделов, 47 задач, по волнам 7·7·5·8·9·3·8,
висячих ссылок нет, разметка чистая.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 05:53:33 +03:00
Дмитрий 1daee489a7 feat(смс): имя отправителя выбирается по оператору получателя, а не одно на всех
Имя согласовывает ОПЕРАТОР, и у каждого оно своё. Клиентская рассылка несла одно
имя всем каналам, а умолчанием ему служило `services.sms.mts.naming` — то есть имя,
согласованное с МТС, подставлялось Теле2 и подставилось бы Мегафону и Билайну.
Живой отказ Теле2 `invalid_source_address` 04.08.2026 — ровно этот механизм. На бою
у клиентов заведено НОЛЬ своих имён, значит это касалось каждой отправки.

Появился ClientSmsSenderResolver: спрашивает имя у той сети, чей номер. Пустая
строка на выходе — не «имени нет», а «своего имени для этой сети нет, канал
подпишется собственным согласованным именем из настроек».

Переведены на него оба места отправки: рассылка (SendClientSmsCampaignJob) и
авто-СМС по сделке (SendAutoSmsForDealJob).

Универсальный СМС-центр передавал имя КАК ЕСТЬ — теперь тоже падает на своё
(SMSC_NAMING). Раньше пустое имя туда не приходило никогда, с этой правкой стало
бы приходить: ушли бы СМС без отправителя.

Заплатка внутри канала Теле2 (приведение написания к своему регистру) остаётся, но
больше не несущая: она чинила следствие в одном канале, а причина была общая.

Экранное имя (ResolvesClientSmsSenderName) НЕ трогали — это запись намерения, а не
то, чем подпишется сеть; в его шапке теперь написано почему, чтобы не «починили»
обратно.

🪤 Урок по дороге: авто-СМС ловит любую ошибку и молча выходит. Справочник имён был
передан не в ту функцию — вместо падения получилась ТИШИНА, не уходило ничего.
Поймали три чужих теста, до того зелёных.

Проверено: 4614 тестов, упал один чужой (ExampleTest — в этой папке не собран
фронтенд). Статанализ 0. Стиль правленых файлов чист.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 05:28:59 +03:00
Дмитрий c50b3dbe1e docs(обзвон): ворота вслепую и суд пройдены — третья редакция плана, 46 задач
Вторую редакцию проверили трое: двое ворот вслепую и судья. Оба проверяющих
работали по спеке, план им был запрещён словами, оба отчитались «план не
открывал» и оба назвали вещи, которых в плане нет. Судья план читал и искал
ошибки надзирателя.

Проверено командой: план 2801 строка / 19 разделов / 46 задач, спека 2126 / 18 /
96 требований, протокол 2150 / 7 / 72 решения. Разметка чистая во всех трёх.
Полный прогон: 4755 из 4760, упавший тест чужой (коммит 1ed82b6b3), в одиночку
файл проходит 10 из 10 — грязь от соседнего теста, не поломка продукта.

Шесть ошибок надзирателя, найденных судьёй, все настоящие:
- план утверждал, что приёмщица живёт в отдельной папке bots/lena-vhodyashchie —
  такой папки нет, это тот же most.py вторым процессом. Заходов в мост стало
  семь, порядок в таблице горл исправлен;
- наставления робота лежат вне репозитория, задачи на это не было — З-0.7;
- Т13, Т23, Т24 не были поручены никому, все три про то, что робот говорит
  вслух — З-4.8;
- своя очередь и живое обновление экрана выброшены целиком — З-6.8;
- проверка дословности каркаса и три проверки манеры проходили при сломанной
  работе — переписаны;
- порядок по узким горлам врал в пяти местах; З-2.4 обещала поле в карточке
  сделки, не назвав ни одного файла экрана.

Улов ворот, внесённый в план и в новый §18 спеки:
- стирание по требованию человека не достаёт до звука и расшифровки: сделка
  стёрта, голос остался — З-2.5;
- безопасный ритм 40-100 наборов в день на номер измерен нами же, Т38 перебивает
  его в разы; счёт попыток не привязан к человеку — до 24 наборов за двое
  суток — З-3.8;
- дорезерв на ходу Т60 не сработает ни разу: заморозка не складывается;
- реклама физически не возвращается — состояние тупиковое, ручка ждёт другого
  состояния; письмо обещает невозможное;
- замкнутый круг: обзвон морозит деньги, списание тушит Директ, тушение отпускает
  бронь рекламы, её доедает обзвон;
- проверка «наружу не ушло ничего» неисполнима — единого журнала исходящих нет;
- своё окно клиента ломает несущее правило часов «живёт здесь и больше нигде»;
- робот не слушается скрипта — измерено, а вся защита проверяется по тексту
  скрипта; проверки переведены на запись разговора;
- этикетка на экране у человека — чужого юрлица ООО Лизинговая Омега;
- трансграничная передача голоса: в 96 требованиях ни слова.

Два решения владельца, принятых по ходу проверки:
- Р71 арендуем двенадцать номеров, не десять — спор Р41 и Р53 закрыт. Замерено:
  у оператора восемь номеров, докупить надо пять, а не двенадцать;
- Р72 у лидов, пришедших через нашу платформу, согласие уже есть — подтверждение
  спрашиваем у двух источников из четырёх.

Замеры смены: номеров у оператора восемь, в телефонию заведено два, наружу
звоним одним; письмо о нехватке денег одно и боевое; на машине робота 13 ГБ
свободно, записей 68 МБ в 89 файлах, чистки нет.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 05:21:43 +03:00
Дмитрий d1e6fcab7f fix(смс): новая запись про адрес звонившего писалась уровнем, который бой выбрасывает
Приёмка на бою вскрыла, что хвост был закрыт только на вид: строку писали
уровнем «к сведению», а на боевом LOG_LEVEL=warning — всё, что ниже, молча
отбрасывается. Запись не появилась бы в журнале НИКОГДА, и круг «список нельзя
заполнить, потому что адреса неоткуда взять» остался бы замкнут — только теперь
незаметно, с виду починенный.

Замерено живым вызовом приёмника на бою 04.08: соседнее предупреждение про
незнакомое сообщение в журнал легло, а строка «к сведению» — нет.

Уровень поднят до «предупреждение». Тест теперь стережёт именно уровень, и в нём
записано, почему: не «так решили», а «иначе бой выбросит».

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:14:30 +03:00
Дмитрий 57c36985a5 fix(сторож ссылок): ссылка на ТЗ лендинга не пускала push из любой отдельной папки
CLAUDE.md §0 ссылается на «лендинг/TZ_landing_v1_0.md», но каталог `лендинг/`
лежит в .gitignore (строка 137) — в git этого файла нет и не будет.

В общем дереве ссылка «работает» только потому, что файл есть там на диске.
В любой отдельной рабочей папке его нет, проверка ссылок краснела и не пускала
push — а сам CLAUDE.md править мимо плагина нельзя (правило §5 п.10).

Исключение узкое: ровно этот файл. Проверено — 38 из 38 ссылок CLAUDE.md
целы, ошибок ноль.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:07:56 +03:00
Дмитрий 9b634d20dc fix(сторож секретов): приёмочные документы в корне docs/superpowers/ вставали насмерть у всех
Полная проверка истории находила 5 «незамаскированных телефонов» в
docs/superpowers/2026-07-27-PRIEMKA-client-sms-fixes.md и не пускала push НИКОГО.

Замерено: все пять с префиксом 7999 — синтетические по правилу проекта
(«реальные НИКОГДА»). Настоящих персональных данных нет.

Причина: список исключений покрывает подпапки docs/superpowers/{plans,runbooks,
specs,audits,findings,prototypes}, а этот документ лежит ПРЯМО в docs/superpowers/
и под них не подпадал. Файл из истории не убрать, не переписав общую ветку, —
значит, чинить надо список.

Разрешение узкое: только docs/superpowers/ГГГГ-ММ-ДД-PRIEMKA-*.md. Прочие файлы
корня docs/superpowers/ проверяются по-прежнему.

Проверено: до правки — 5 находок, после — «no leaks found» на 7589 записях.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:00:14 +03:00
Дмитрий 78e8a57b8e docs(обзвон): план переписан под 21 новое решение владельца — 41 задача в семи волнах
План 2026-08-04 писался, когда закрытых развилок было ноль. Сейчас закрыты 28 из 29,
и пометки «заблокировано развилкой» врали в обе стороны. Вторая редакция.

Было 32 задачи в шести волнах — стало 41 в семи. Проверено командой:
2292 строки, 18 разделов, 41 задача, разметка чистая, ссылок на файлы ноль.

Разблокировано решениями владельца: вход клиента Р66/Р67/Р60, окно часов Р64,
письма Р52, каркас и личная правка Р46, обратные звонки Р62/Р63/Р48/Р54,
запись менеджера Р61, замок Т31 Р57, источники получателей Р65.
Из семнадцати заблокированных задач не осталось ни одной запертой полностью.

Прибавилось:
- волна 5 «авто-обзвон» целиком — решение Р39, перенос измеренного устройства авто-СМС;
- З-0.5 обрыв на 60-й минуте и подсказка менеджеру на 55-й — Р43;
- З-1.7 письмо про обе остановки — Р56;
- З-3.6 подтверждение согласия при каждой загрузке — Р42;
- З-3.7 закрытые номера: тишина, счётчик, бесплатность — Р48, Р49;
- З-4.4 личная правка сильнее каркаса — Р46;
- З-4.5 манера живёт у робота — Р68;
- З-4.2 сборка скрипта машиной — найденная дыра: требование Т7 стоит в спеке
  с первого дня, а задачи под него не было ни одной.

Переписано против первой редакции:
- стоп-лист — решение Р45 обратно прежней рекомендации: свой, пятый список;
- чистка — три ступени по одной строке вместо одной операции, Р50 и Р51;
- заморозка — два режима: авто по поступлению, база пачкой, Р39;
- отчёты — по людям, а не по наборам номера, Р47;
- З-2.4 первой редакции упразднена: Р50 сняло бессрочную обезличенную расшифровку.

Два места, где нужно слово владельца, оба всплыли после закрытия развилок:
1. Двенадцать попыток дозвона требуют двенадцати разных номеров Р53,
   а арендовать решено десять Р41. Арифметически невыполнимо.
2. У авто-обзвона нет загрузки списка — к чему привязать подтверждение согласия,
   не решено.

Спека выправлена шестью правками: освобождён задвоенный номер Т73 → Т98,
снята устаревшая бессрочная расшифровка, названо противоречие десяти и двенадцати
номеров в трёх местах. Требований 96, разделов 17, закрытых развилок 28.

Промт следующей смене заменяет прежний — очереди развилок больше нет.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 20:15:57 +03:00
Дмитрий 784ed07392 docs(обзвон): все 29 развилок пройдены, решения владельца Р50-Р70
Допрос по спеке «Обзвон» доведён до конца: 28 развилок закрыты решениями
владельца, одна (плата за второе плечо перевода) намеренно отложена до замера
цены звонка. Незаданных развилок не осталось — объявлено вслух.

Хранение и закон:
- Р50/Р51 — сроков два: звук месяц, текст три месяца, потом остаются сухие
  итоги. Строку не удаляем: иначе нечем подтвердить счета за прошлые кварталы;
- Р52 — в письме менеджеру и номер, и ссылка на сделку (цена: наша чистка до
  почтового ящика не дотягивается);
- Р59 — об удалении своих записей клиент узнаёт надписью на их месте;
- Р61 — менеджера клиента о записи не уведомляем.

Темп и защита:
- Р53 — шесть попыток в сутки, ровно два дня, всего до двенадцати;
- Р58 — три одновременные линии, больше только через нас (работает без замера);
- Р64 — часы менеджера задаёт клиент, и они только сужают общее окно.

Деньги:
- Р54 — обратный звонок после кампании идёт в долг, ничего не резервируем;
- Р55 — большой список запускать не мешаем, но последствие названо словами и
  нужно подтверждение;
- Р56 — письмо о минусе называет обе остановки: обзвон и рекламу.

Вход и скрипт:
- Р66 — клиента без записей берём: стандартный каркас, наши вопросы, его сайт;
- Р60/Р67 — пятнадцать записей ориентир, список на входе один;
- Р65 — источников получателей три, как в рассылках; моё Т43 снято;
- Р62 — приёмщица одна, но представляется по сделке звонящего;
- Р68 — манера живёт у робота, а не в скрипте;
- Р69 — машина отдаёт скрипт сразу размеченным;
- Р70 — правку раскладывает руками тот, кто её принимает;
- Р63 — на своём номере отвечаем всегда, запрет второго перезвона снят.

Правило, выведенное по ходу и решившее часть вопросов само: надпись — там, где
клиент за свои деньги получает работу; замок — там, где работа гарантированно
бесполезна. Р18 про выбор, а выбора нет, когда результат предрешён.

Три слепых сторожа найдены и переписаны:
- проверка «манера во всех скриптах одинакова» проходила бы ровно при
  расползании правки, то есть зеленела в момент беды;
- проверка «три клиента попросили одно и то же» считала буквальные совпадения
  в свободном тексте, которых не бывает;
- Т70 всё ещё обещало шесть месяцев звука вместо принятого месяца.

Дыра, вскрытая ответом: минус на счету гасит клиенту весь Директ, а кто
включает рекламу обратно после пополнения — не задано ни одним решением.

Настоящий мобильный номер, попавший в протокол как название проекта, замаскирован.
В истории он остаётся (коммит 06f49ce0d) — вычищать историю ветки без владельца
не стал.

План под новые решения НЕ переписан: в нём 32 задачи с пометками
«заблокировано развилкой», расставленными до ответов. Стройку не начинать.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 22:41:27 +03:00
Дмитрий e5efa5e7b4 docs(приёмка Яндекса): промт смене 20 — проверка починки типа группы
Главное для следующей смены: починка типа группы объявлений выкачена, но живьём
не проверена — Директ не меняет тип после создания, поэтому #6 и #11 доживают
срок с неправильной группой. Проверить можно только новой кампанией, и это
решение владельца, оно стоит денег.

Расписано: как проверять дёшево — сразу после запуска глянуть Subtype группы,
не дожидаясь показов; эталон для сравнения — чужая кампания 713051718 с группой
по профилю, 457 показов за четверо суток при сегменте из 134 человек.

Отдельно записаны три урока смены: тихий ноль опаснее громкой ошибки, Яндекс
молча принимает неверную настройку, и версии надо отвергать по одной за раз.

Хвостов пять, живое состояние сведено таблицей, предупреждения про соседние
смены в той же ветке и на том же боевом, про замороженный GitHub и про пароль
открытым текстом в адресе gitea.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:55:04 +03:00
Дмитрий 65f6d06ef2 fix(реклама): создаём группу по профилю пользователей, а не по ключевым фразам
Вопрос владельца «может мы что-то напортачили в настройках?» оказался в точку.

Нацеливание у нас одно — список телефонов, прицепленный отдельным условием
через AudienceTargets на сегмент Яндекс.Аудиторий. Ключевых слов мы не задаём
вовсе. Но группу создавали «по ключевым фразам» и оставляли список слов пустым.

Дока Директа разводит два типа прямо: CpmBannerKeywordsAdGroup — с ключевыми
фразами, CpmBannerUserProfileAdGroup — с условием нацеливания по профилю
пользователей. Сегменты Аудиторий это второй.

Почему поломка себя не выдавала: Яндекс такую группу ПРИНИМАЕТ. Она создаётся,
объявления проходят модерацию, включаются в показ, кампания рапортует «Идут
показы». Ни ошибки, ни отказа — просто показов нет.

Замеры, которыми отвергнуты две другие версии:
- ставка: подняли с 72 до 300 рублей за тысячу, выше рыночных 250, ждали четыре
  часа — как был один показ, так и остался;
- размер списка: у чужой рабочей кампании того же кабинета в основе сегмент на
  134 человека, и она дала 457 показов за четверо суток. У нас 1653 человека и
  один показ.

Сторож переписан и принят красным.

Тип группы после создания не меняется, поэтому живые #6 и #11 так и доживут с
неправильной группой. Проверить починку можно только новой кампанией — это
решение владельца, оно стоит денег.

Прогон: 452 сторожа блока рекламы, статанализ 0, стиль чист. Схема не менялась.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 21:45:55 +03:00
Дмитрий 1987737681 fix(смс): приёмник Теле2 сам называет адрес звонившего — белый список было нечем заполнить
Пока SMS_T2_WEBHOOK_IPS пуст, приёмник никому не отказывает — а значит, и записи
«звонили с такого-то адреса» в журнале не появляется. Круг замкнут: список нельзя
заполнить, потому что адреса неоткуда взять, а взять неоткуда, потому что список пуст.

Теперь при пустом списке каждый принятый звонок пишет строку
client_sms.delivery_hook_open_gate с адресом. Как только список задан — смолкает,
шуметь в журнале постоянно не будет.

Памятка: откуда забрать адреса одной командой; в «Открытом» отмечено, что круг
разорван, и отдельным пунктом записан незакрытый долг про имена отправителей по
каналам.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 20:14:34 +03:00
Дмитрий 61be447b41 fix(реклама): Директ отвергал запрос числа показов, а портал читал отказ как ноль
Самая тяжёлая находка смены, вылезла из вопроса владельца «показано 0, почему?
там один же есть» — из сверки карточки с кабинетом глазами.

Замер на боевом: запрос портала к Директу отвергается с кодом 400 — «В params
отсутствует обязательное поле IncludeVAT». А код ответ не проверял: брал тело,
переводил в число и получал ноль. То есть «показов не было» — не факт, а
проглоченная ошибка.

Чем накрывается. Это единственный источник числа показов, и у него две работы:
число «Показано» на карточке и основание списать деньги за открученную рекламу.
Значит ни за один показ клиенту не выставлялся счёт — реклама шла за наш счёт.
И тихий ноль опасен сам по себе: затирает настоящее число на карточке, а при
истёкшем сроке закрывает кампанию с возвратом всей заморозки.

Почему не поймали раньше: ноль выглядит как «показов ещё не было» — законное
состояние новой кампании. Отличить «не было» от «не смогли спросить» портал не
умел. На этом месте с самого начала висел TODO про сверку формата перед боем.

Три правила и три сторожа:
- IncludeVAT в запросе — без него Директ отвергает запрос целиком;
- processingMode auto — иначе отчёт строится в фоне и приходит пустое тело;
- громкая ошибка вместо тихого нуля при не-2xx и нечисловом ответе.

Наверху ошибка уже обработана правильно: обход пишет предупреждение и идёт
дальше, а «Пауза» при такой ошибке не отпускает деньги.

Четвёртая мина, вскрытая сторожем уникальности: имя отчёта строилось из секунд,
два вызова в одну секунду получали одно имя и второй читал кэш первого. Добавлен
случайный хвост.

Настоящий ноль из Яндекса остаётся нулём — отдельный сторож держит и это.

Прогон: 393 сторожа блока рекламы, статанализ 0, стиль чист. Схема не менялась.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 18:13:25 +03:00
Дмитрий 04657bd6cd feat(воронка): фильтр по нише и на личном экране менеджера
Раньше «Ниша» стояла только на «Воронке отдела». Теперь тот же фильтр есть
и на личном экране менеджера — он обзванивает подряд одну нишу, ему нужнее всех.

Список ниш у менеджера считается по ЕГО карточкам: сужение «только свои»
наложено раньше, поэтому чужая ниша в список не попадает, а ?rubric= не может
стать лазейкой к чужой воронке — на это есть отдельная проверка.

Поведение обоих экранов задаёт один кусок кода, composables/prospectRubricFilter.ts.
Двумя копиями «Без ниши последним» и самосброс исчезнувшей ниши разъехались бы
на первой же правке.

Проверено: Pest по продажам 525 зелёных, Vitest по фронту 2077 зелёных,
vue-tsc и Larastan чисто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 18:04:07 +03:00