За четыре дня я перестроил AI-толкование таро и снов в Cartara, добавил с нуля нумерологию как первый новый домен и выкатил всё на свой сервер, где обкатываю проекты. А на проде, уже при живых 177 юзерах, выяснилось, что в новой фиче нет одной базовой вещи — User Memory, того самого знания о пользователе, на котором держится вся персонализация. И нет её не потому что я забыл, а потому что нейросеть незаметно снесла её при прошлом рефакторинге, и этого никто не заметил до самого прода. Вот про это и вся история, про то, как в одном релизе уживаются глубокая работа с промптами эзотерики и тупой стыд за строчку «Ты даён миру».
Cartara, если вы не в курсе, это Telegram Mini App с AI-наставницей: таро, сны, чат. Я её не пишу руками, я оркестрирую: код пишет Claude Code под моим управлением, контент в рантайме генерит модель Haiku 4.5, а я принимаю решения по каждой развилке, ловлю баги и матерюсь, когда ломается. И за эти четыре дня сломалось много чего, так что материала хватает.
С чего начали и зачем вообще ресёрч
Стартовали с аудита системы после большого рефакторинга, и я сразу упёрся в вопрос, который вроде бы и не про код: а правильно ли мы вообще толкуем? Интерпретации таро были поверхностные, карты разбирались изолированно, не было мета-анализа всего расклада, не было нарратива, который связал бы их в одну историю. И я подумал, что перед тем как пилить новые модули, неплохо бы сделать ресёрч, посмотреть лучшие практики в эзотерике и в науке о снах, чтобы не выдумывать всё из головы.
Так и сделали. Три параллельных ресёрча — таро со снами, нумерология и астрология — через веб-поиск, и всё с записью в файлы, чтобы потом переиспользовать. И тут всплыл момент, который меня всегда цепляет в работе с AI: я спросил «а ресёрчи не записываешь?», потому что без файла вся эта работа испаряется в контекст и через два дня её как не было. Записанный ресёрч — это актив, а болтовня в чате — нет.
Дальше пошла прокачка промпта таро через консилиум и дебаты. Это мой обычный процесс: несколько AI-экспертов параллельно разбирают задачу, скептик их атакует, а я выбираю. Подробнее про сам метод я писал в SCD: собрал новый метод принятия решений из двух существующих. И консилиум тут сказал умную вещь, которую я записал дословно: сначала надо доказать, что наша система толкования для таро вообще даёт ценность, а как её докажешь, если ею не пользоваться? Замкнутый круг, который ломается одним способом — взять и сделать.
Сделали новую структуру промпта таро с мета-анализом, тут же прокачали сны, добавили туда список запрещённых формулировок и гештальт-перспективу, прогнали тесты старое против нового. И уже к ночи была готова спека нумерологии как первого нового домена. А ещё я взорвался по поводу одной MVP-дискуссии, где эксперты предложили урезать чат внутри нового модуля, мол, для MVP сойдёт. Но нельзя у таро и снов иметь чат, привязанный к раскладам с контекстом, а в новом модуле взять и его отобрать. Это не экономия, это дыра в продукте, и я это отстоял.
Третий copy-paste вместо красивой абстракции
На MVP нумерологии встал главный архитектурный вопрос. У меня уже было два почти одинаковых экрана, таро и сны. Напрашивалось сделать общую оболочку, чтобы и нумерология, и будущая астрология просто на неё ложились. Красиво, по учебнику, DRY и всё такое.
Но консилиум из пяти экспертов с отдельным скептиком на стресс-тесте выдал компромисс, который я и взял: не делать общую оболочку прямо сейчас, а сделать третий copy-paste экран, и вот когда будет три похожих экрана, паттерн кристаллизуется сам, и уже тогда выносить оболочку. Логика простая: пока у тебя два примера, ты не знаешь, что в них реально общее, а что совпало случайно. Сделаешь абстракцию рано, потом будешь воевать с собственной абстракцией, когда третий случай в неё не влезет. Лучше потерпеть копипасту ещё разок и вынести её на готовых трёх примерах, чем выдумывать обобщение на двух.
Сам MVP нумерологии собрали быстро: пять расчётов и интерпретация через Haiku 4.5. Это та самая разработка с ИИ, когда от спеки до рабочего модуля проходит не неделя, а пара часов: AI-агент пишет калькулятор, роут, фронт, я смотрю и правлю развилки. И вечером я сказал: давай выкатим на сервер, где я все проекты обкатываю.
Деплой, DNS-пляски и «нахуй я вообще облако использую»
А вот тут началось то, ради чего, наверное, и стоит читать build-логи, а не релиз-ноты. Задеплоили, навесили перенаправление с тестового домена, и оно не открывается. Утром я пишу: «что-то уже дохуя часов прошло и всё ещё не открывается». Сидим в DNS-плясках между dev-доменом и основным, через облачную прослойку, которая по идее должна всё ускорять, а на деле добавляет ещё один слой, где можно споткнуться.
И в какой-то момент я задал себе честный вопрос: а нахуй я вообще эту облачную прослойку использую? На других проектах не заморачивался, всё работало напрямую. Иногда лучшее решение проблемы не в том, чтобы дебажить её десять часов, а в том, чтобы убрать сам узел, который её создаёт. Отключили прослойку, пошли напрямую, и дев-бот ожил. Один работающий бот лучше, чем три красивых домена, ни один из которых не грузится.
Дальше я открываю нумерологию и вижу: по фронту она вообще ни на что не похожа, ни на таро, ни на сны, совсем другой вид. Это и есть оборотная сторона того самого «третьего copy-paste» — AI-агент налепил новый экран по-своему, не подсмотрев в существующие. Пришлось отдельным заходом рефакторить фронтенд нумерологии под паттерны таро и снов, чтобы юзер не чувствовал, будто попал в другое приложение.
Цикл багов и строчка «Ты даён миру»
Потом пошёл цикл, который любой, кто катит свежую фичу на прод, узнает с первой секунды. Жмёшь «получить полный портрет» — «внутренняя ошибка сервера». Чинишь — чёрный экран. Чинишь — работает. Перезаходишь — опять ошибка. Пять итераций, и на каждой я матерился, потому что баг плавающий, а плавающий баг — это худший вид, его не воспроизвести по команде.
А когда экран наконец стабильно отрисовался, я прочитал текст интерпретации и увидел: «Ты даён миру». Опечатка прямо в выводе модели, которую видит живой пользователь. И вот это сочетание меня и добивает в работе с AI: ты только что через два консилиума выстроил глубокую систему толкования с мета-анализом и гештальтом, а на выходе у тебя кривая строчка, за которую стыдно перед любым, кто это откроет. Глубина внутри и косяк на поверхности живут в одном релизе.
Главный момент: «ты чё нахуй вырезал при рефакторинге?»
И вот гвоздь всей недели. Разбираясь с интерпретацией, я заметил, что нумерология не подтягивает User Memory, то, что система уже знает о пользователе. А это второй знак, который, я был на сто процентов уверен, работает везде и всегда. Спрашиваю: как это не реализовано, если он всегда там был? И получаю ответ, что при прошлом рефакторинге его, видимо, не перенесли.
То есть нейросеть при предыдущей переделке тихо снесла рабочую фичу, тесты этого не поймали, я этого не заметил, и оно доехало до прода, где сидят 177 человек. Дальше выяснилось, что и раньше там всё было сделано криво, поэтому, по сути, толком и не работало, просто никто не доковырялся. Это, наверное, самый честный урок всей истории: AI-агент не злодей, он не саботирует, он просто делает ровно то, что попало в его поле зрения в момент рефакторинга. А то, что выпало из контекста, он спокойно выкинет, и узнаешь ты об этом не из ревью, а от юзера или от собственного глаза на проде. Похожую штуку я уже ловил в Тесты зелёные, экран пустой, там AI забыл подключить отправку, и тесты молчали.
Хардкод-цены и один Codex для второго мнения
Под вечер я попросил искать везде, где есть захардкоженные цифры, особенно цены токенов, потому что для меня это критично, на этом стоит монетизация. И нашлось весёлое: на фронте welcome offer обещает 60 токенов за 99 рублей, а в другом месте логики тот же ценник даёт 40 токенов за те же 99 рублей. Подписка на канал — где-то 100 написано. Цифры живут в разных местах фронта и бэка и расходятся между собой, а это прямой путь к тому, что пользователь увидит одно, заплатит, получит другое и пойдёт писать в поддержку — про похожий косяк с оплатой я уже рассказывал в посте про то, как купил у себя же токены на проде, а транзакции нет.
Параллельно я гонял UX-ревью чата сразу через два AI — Claude и Codex от OpenAI, чтобы получить два независимых взгляда. Про то, как я использую обоих одновременно, я писал в OpenAI сделала плагин для Claude Code. Заодно починили баг, из-за которого свободный чат думал вечно, там подвис сервис, который проверяет запросы перед отправкой.
И финальным аккордом — рефакторинг, который мне реально приятно было увидеть. У меня было четыре почти идентичных хука переписки: для основного чата, для свободного, для снов и для нумерологии. Примерно 570 строк копипасты, которая расползлась ровно потому, что каждый новый модуль делался отдельным copy-paste. Слили их в один. Вот он, обещанный момент кристаллизации паттерна: когда экранов и хуков стало достаточно, общее стало видно невооружённым глазом, и обобщение легло само, без насилия над архитектурой. Про то, как я доводил эту идею до того, чтобы новый домен сам встраивался в портрет через registry, есть отдельная история — с откатом половины архитектуры как тех-долга.
Цифры этой недели
- 4 дня от аудита до нумерологии на проде
- 5 расчётов нумерологии в одном портрете
- Haiku 4.5 — модель для интерпретаций в рантайме
- 177 живых юзеров на проде в момент деплоя
- 5 итераций плавающего бага: ошибка сервера, чёрный экран, работает
- 4 хука переписки (~570 строк) слиты в один
- 2 расходящихся ценника: 60 токенов за 99₽ против 40 токенов за 99₽
Что я из этого вынес
Первое и главное. AI-агент рефачит ровно то, что видит, и тихо выкидывает то, что выпало из контекста. Если у вас нет теста на конкретное поведение фичи, а не на «entity создана», то рефакторинг через нейросеть рано или поздно снесёт что-то рабочее, и узнаете вы об этом на проде. User Memory в нумерологии — мой личный памятник этой мысли.
Второе. Ранняя абстракция дороже копипасты. Решение делать третий copy-paste, а оболочку выносить на трёх готовых примерах, оказалось верным, паттерн кристаллизовался сам, и четыре хука схлопнулись в один без боли. А на двух примерах я бы это обобщение выдумал, и оно бы мне потом мешало.
Третье, про деньги. Хардкод цен в разных местах — это не косметика, это мина. Любая цифра, которую видит пользователь и за которую он платит, должна жить в одном месте, единым источником правды. Иначе фронт обещает 60, бэк даёт 40, и доверие к продукту утекает по копейке.
И четвёртое, человеческое. Можно за неделю через консилиумы и AI-агентов построить глубокую систему толкования таро, снов и нумерологии, и тут же выдать юзеру строчку «Ты даён миру». Глубина и стыд ходят парой, особенно когда ты соло и катишь сам. Так что я не из тех, кто продаёт вам готовый блестящий фасад. Я из тех, кто показывает, как оно сделано внутри, со всеми чёрными экранами и снесёнными фичами. Вот и делайте выводы.