Контент Завод (SaaS)
SaaS генерации контента: видео/карусели/посты, 40+ моделей, автопостинг. Прод 24contentzavod.ru, стейдж test.24contentzavod.ru.
ревьюS1 · Спринт качества контента8/9
Цель: Голоса-пул, дизайнер+фон, Wan 2.7, Студия native
В РАБОТЕS2 · Взрослый редизайн СММ-Центра19/26
Цель: Не MVP. Хаб «Создать контент» (обёртка Студии), компания над фабрикой, честные Расходы/Дашборд/Аналитика по разрезам, Ролс-канвас. Спек: myvisionagency.ru/lab/smm-redesign. Согласовать до кода.
В РАБОТЕS3 · Леджер и платежи1/2
Цель: Единая таблица transactions, симметрия списаний
планS4 · Качество видео — докрутка0/5
Цель: Динамика и подача роликов: промты, хук↔озвучка, мягкий бренд, банк структур
ревьюS5 · СММ-Центр: Каркас + Дашборд + Бриф6/6
Цель: Отдельный раздел со своим layout, дашборд-домашняя с ИИ-рекомендациями, единый бриф компании
ревьюS6 · СММ-Центр: Календарь + Публикации + Загрузка-как-есть7/7
Цель: Пульт: редакционный календарь, согласование, загрузка своего медиа, per-network времена/превью
планS7 · СММ-Центр: Российский слой публикации0/4
Цель: Заменить/дополнить Upload-Post российским API: Rutube, VK органика рилсов, OK, Дзен
ревьюS8 · СММ-Центр: Входящие + автоответы6/6
Цель: Единый инбокс комменты+директ; 2 тира автоответов (канные дёшево / ИИ платно) + база знаний
ревьюS9 · СММ-Центр: Аналитика + Тренды + Расходы4/4
Цель: Кросс-сетевая аналитика всех типов, white-label отчёты, тренды по нише, журнал расходов
ревьюS10 · СММ-Центр: ИИ-копайлот + Команда4/4
Цель: Лия-для-СММ, роли/команда, мульти-компания, авто-правила
ревьюS11 · СММ-Центр: Бренд-ассеты и шаблоны3/3
Цель: Шаблоны постов (reference-driven) + интро/аутро видео (bumpers)
ревьюS12 · Обучение, онбординг и связь с клиентом26/30
Цель: Инструкции со скриншотами по СММ-Центру, Заводу и Студии; онбординг первого входа; регистрация с почтой и телефоном, письма и второй канал связи
В РАБОТЕS13 · Пайплайны: разбор, сценарии, починка26/38
Цель: Э0-Э3 плана docs/FIX-ROADMAP.md: мерки, ремонт контракта холст-сервер, деньги под контролем, Задание (TaskSpec) вместо догадок
планS14 · Продуктовые пробелы по ролям0/10
Цель: Э4-Э5 плана docs/FIX-ROADMAP.md: превью до денег, сверка результата, память задач, продуктовые пробелы по ролям
В РАБОТЕS15 · Фундамент: стабильность под нагрузкой12/23
Цель: Убрать причины внезапных отказов и подготовить систему к росту числа клиентов. Основание: docs/STABILITY-AUDIT.md, снят с прода 05.08.2026.
Ворклог (места остановки)
Переделка двух работ для «Фабрики Брендосс» после разбора от владельца: обе прошлые версии были сделаны правдоподобно, а не правильно. КАРУСЕЛЬ «Механизмы диванов» v2: тексты переписаны на проверенные факты (клик-кляк 7-10 лет и 120-140 кг, убивает незащёлкнутый затвор; у еврокнижки ломаться нечему, срок жизни определяет обивка, ролики лечатся силиконовым спреем раз в полгода; аккордеон тяжелеет и метит пол; дельфин самый нагруженный — рычаги, крепления, люфт; книжка живучая, но усилие и стык). Прошлый текст был набором очевидностей вида «нужен метр перед диваном». Схемы перерисованы: строго боковая проекция вместо изометрии, ДВЕ фазы вместо трёх, обе на одной линии пола, фиксированный ракурс и явный запрет поворачивать диван между фазами — механика на всех шести слайдах вышла верной, перерисовывать не пришлось ни одного. РОЛИК «Он бежал к тебе» v2: снят ОДНИМ непрерывным планом, камера за спинкой дивана как в гоночной игре. Погоня, гигантские руки слева и справа, подворотня, лестница, дверь. Музыка и шумы родные от Wan, три реплики свои (ElevenLabs, голос Антон), дорожка модели приглушена до 0.62, наличие речи подтверждено обратной транскрипцией Whisper.
→ Три приёма, которые пора зашивать в завод, а не собирать руками скриптом. 1) Схемы механики: боковая проекция + две фазы + жёстко зафиксированный ракурс; изометрия с тремя фазами наложением даёт кашу и разные пропорции. 2) Один непрерывный план: оба опорных кадра обязаны быть сняты ИЗ ОДНОЙ ТОЧКИ — при разных ракурсах модель мирит их и разворачивает объект (так диван побежал назад в первом дубле). 3) Речь: Wan даёт русскую речь в кадре с человеком, но не даёт говорящей мебели — там кладём свою озвучку и проверяем обратной транскрипцией, а не на слух. Открытое: тип ткани 304 клиент так и не подтвердил; в заводе лежат две карусели про механизмы, старую кривую (4456618f) предложено снести; владельцу описана следующая карусель «Пять минут у двери» про приёмку дивана у курьера, ждёт решения.
Разбор жалобы «не работает кнопка войти» на боевом сервисе. Вход оказался исправен, лежал слой данных: PostgREST упал при перезапуске базы в 02:25 и не поднялся, два часа весь /rest/v1 отдавал 503. Кабинет не мог прочитать профиль и заводы, поэтому после верного пароля человека возвращало на форму. Заводы всё это время ничего не выпускали. Поднял supabase-rest и перезапустил kong, который держал в кэше мёртвый адрес. Проверено снаружи: rest 200, auth 200, планировщик без ошибок.
→ Владельцу на решение: падение такого слоя сейчас видно только тогда, когда клиент не может войти, то есть два часа простоя вслепую. Предложено добавить в compose Supabase зависимость rest от базы с проверкой здоровья и внешнюю проверку /rest/v1 с оповещением в Телеграм. Это правка боевого стека, жду «да». Заведена проверка по сроку на 31.08: встаёт ли REST сам после перезапуска базы, с командой и порядком починки (docker start supabase-rest, затем docker restart supabase-kong). По ядру cz-core работа не двигалась: вся сессия ушла на прод.
Продакшн для «Фабрики Брендосс», заход в новом креативном регистре: владелец забраковал бытовые идеи и попросил концепты, пробивающие баннерную слепоту. Ролик «Он бежал к тебе»: ночной мультяшно-кинематографичный город, диван удирает на своих ножках от гигантских рук, которые расхватывают чужие диваны, добегает до своей комнаты и раскладывается в кровать. Собран ДВУМЯ клипами Wan 2.7 (8 с погоня + 7 с прибытие) вместо одного пятнадцатисекундного: разные сцены, в одном i2v модель половину действия придумывает сама, а по деньгам одинаково, Wan тарифицируется посекундно. Четыре кадра gpt-image-2 цепочкой image-to-image от фото товара, каждый клип ведётся первым и последним кадром, склейка встык на действии. Карусель «Механизмы диванов»: клик-кляк, еврокнижка, аккордеон, дельфин, выкатной — у каждого не только плюс, но и честный минус (метр пола спереди, два стыка, нагруженный узел, сон почти у пола). Слайды сделаны как дорогие инженерные изометрии с фазами раскладывания, стрелками движения и выносками, палитра серии сохранена. 49 ₽.
→ Приём, который теперь работает стабильно и стоит перенести в пайплайн: сложное действие резать на два клипа по первому и последнему кадру вместо одного длинного, кадры генерить цепочкой i2i от фото товара. Тип ткани 304 всё ещё не подтверждён клиентом — на CTA новых каруселей утверждение про велюр не ставим.
Разбор «на проде затёрли выставление счетов» — и нашлось кое-что похуже. 1. ТОЧКА. Никто ничего не затирал: ключей на проде НЕ БЫЛО НИКОГДА, в бэкапе от 30.07 их тоже ноль. Они всегда стояли только на стенде. А счета от 30.07 видны в базе потому, что стенд и прод пишут в ОДНУ базу — выставлены они со стенда. Ключи перенесены на прод (.env и .next/standalone/.env, оба с бэкапом), проверены напрямую у банка: запрос состояния счёта вернул 200 и «payment_waiting». Доступы рабочие. 2. ГЛАВНОЕ: ВНУТРЕННИЕ ВЫЗОВЫ ПРОДА ШЛИ НА СТЕНД. Прод слушает 3002, стенд — 3001. У прода не была задана INTERNAL_BASE_URL, а значение по умолчанию в коде — http://127.0.0.1:3001. То есть очередь картинок СММ, публикация и сбор аналитики прода выполнялись КОДОМ СТЕНДА: другой версией, с другими ключами, с логами в чужом файле. База одна, поэтому со стороны всё выглядело работающим. Задано INTERNAL_BASE_URL и INNGEST_INTERNAL_BASE_URL на 3002. 3. СЕКРЕТ ВЕБХУКА MAX. На проде не задан, а проверка в коде пропускается, когда секрет пуст: обработчик принимал ЛЮБОЙ запрос. Открытая дверь, не поломка. Секрет перенесён. Прод перезапущен, отвечает 200, /api/inngest — 401 (не 500) и по внутреннему адресу, и по публичному. Копировать со стенда всё подряд не стал: остальные четыре настройки (KZ_OPS_TOKEN, PROMPT_ENV, DEBUG_CRITIC_KEY, BACKOFFICE_LIA_CHAT_URL) стендовые по смыслу.
→ Проверить руками то, что нельзя проверить отсюда: выставить счёт юрлицу из кабинета прода (это боевой банковский счёт, без спроса документ не создаю). Присмотреть за очередью пару дней: теперь она работает своим кодом, а не стендовым — если где-то была зависимость от стенда, она вылезет.
Ещё один продакшн-заход для завода «Фабрика Брендосс». Ролик «Диван-победитель»: турнир, соперников давят грузами и греют лампой, они оседают, наш 304 берёт медаль под 3D-надписью БРЕНДОСС. Первый и последний кадр нарисованы gpt-image-2 (последний — image-to-image от первого, иначе сцены не совпадают), Wan 2.7 i2v по обоим кадрам. Камеру удержали статичной через промт плюс negative_prompt (zoom, push in, close-up, human face) — после случая с макро-портретом в прошлом ролике это теперь обязательная часть промта. Кириллица в 3D-надписи собралась без ошибок. Реплику «Ура! Я победил!» модель не проговорила (Whisper с дорожки снял типовую галлюцинацию на музыке) — положили свою озвучку ElevenLabs на 11.2 с поверх фанфар, проверено обратной транскрипцией. Карусель «Какая ткань от какой беды»: дети и пролитый сок, кот и когти, выгорание у окна, аллергия и пыль, велюр ради удовольствия — 7 слайдов gpt-image-2, стиль серии подхвачен через styleRefUrls, 49 ₽.
→ Тип ткани 304 по-прежнему не подтверждён — на CTA новой карусели специально написано «состав обивки смотрите в карточке», чтобы не давать непроверенное утверждение. У прошлой карусели на CTA стоит «велюр на металлокаркасе»: как только клиент подтвердит состав, либо оставляем, либо перерисовываем слайд за 7 ₽. Наблюдение в копилку Г23: Wan проговаривает реплику не всегда — в кадре без людей (говорящая мебель) речи не дал, в кадре с человеком дал обе фразы.
Продакшн для клиента Оксана Яхина (завод «Фабрика Брендосс») плюс два дефекта пайплайна, найденных по ходу. Вчерашний премиум-ролик «Диван приезжает домой» приехал с пустой дорожкой (-58 dB) — озвучили: ElevenLabs, голос Виктория, текст через словарь произношения завода (Брэ́ндос, Ва́йлдберриз, велю́р), сведение -16 LUFS. Сабы продуктовый роут собрал негодные: Whisper по нашей же озвучке дал «комната ям» и «Брэндес», куски по 70 символов — пересобрал по таймингам ElevenLabs with-timestamps, 11 коротких фраз, PlayRes по реальному кадру. Собрана карусель «Ткани для дивана», 7 слайдов gpt-image-2 3:4, стиль подхвачен с прошлой серии через styleRefUrls, копирайт свой (Мартиндейл, рогожка, шенилл, флок, велюр) — 49 ₽. Снят вирусный ролик «Готовь сани летом»: первый кадр gpt-image-2 i2i от фото товара, Wan 2.7 720p 15 с. Первый дубль забраковал (камера ушла в макро-портрет, товара не видно 11 из 15 с), во втором задал negative_prompt против крупных планов и отъезд камеры — вышли обе русские реплики нативно от модели, финал с оленями над лесом, титр наложен своим ffmpeg. Обе работы и карусель лежат в заводе, две работы перенесены из служебного «Без завода» в «Фабрику Брендосс».
→ Открытый вопрос: на CTA-слайде карусели написано «велюр на металлокаркасе», а тип ткани в карточке товара не указан — подтвердить у клиента, иначе перерисовать слайд (7 ₽). Заведены Г22 (сабы должны брать наш текст, а не расшифровку) и Г23 (Wan i2v уезжает в 3:4 и не просит речь) — оба воспроизводимы, в деталях лежат рецепты.
Собран аудит стабильности с доказательствами из живого прода (docs/STABILITY-AUDIT.md) и закрыты первые зоны: индексы под проверку прав, журнал ошибок служебным ключом, таймауты и повторы для Kie. Появился смоук-прогон на Playwright, встроенный в выкладку: 14 проверок на двух ширинах, красный прогон возвращает сборку. Он сразу нашёл реальный баг с шириной холста. Починены: уезжающие за экран окна (общая причина для 23 окон раздела), гонка с незапущенной отрисовкой, зависимость работы от открытой вкладки, врущий показ хода, пресет-копировальщик, весь план карусели на одном слайде. В поддержке появились отметки доставки. Мобильный Центр пересобран: две строки вместо шести плашек, голосовой ввод, лёгкие превью в списках.
→ Открыто: работа без завода не видна в «Моих работах» (поймано на клиентском контенте); у Ролса нет служебного входа; из аудита ждут атомарное списание, генерации в фон, чистка базы от base64, воркер вместо крона, контроль публикаций. По клиенту Брендосс: карусель из семи слайдов готова и лежит в кабинете, АСМР-ролик забракован владельцем (нарезался на четыре клипа вместо одного пятнадцатисекундного и не показывал товар), переделка по правильной схеме ждёт разрешения на трату.
Аватар доведён технически. Найдена настоящая причина серии отказов: не кадр, не формат и не длина аудио, а гонка — провайдер шёл за файлом раньше, чем хранилище начинало его отдавать (доказано: те же файлы вручную минутой позже прошли дважды). Теперь ждём доступности ссылки перед отправкой. Приёмщик обрывался на длинном ответе и отдавал пустое задание — лимит поднят, добавлен повтор; в карточку уходит полный текст задачи. Ролик идёт одним куском до 30 секунд с автонарезкой только при отказе. Починена обратная связь при нажатии. Прогон владельца: ролик на 30 секунд собрался целиком.
→ Открыт вопрос ценности формата: владелец оценивает результат в 150 руб при цене 660 и себестоимости 400. Следующий шаг не в коде, а в подборе голоса и постановки на коротких дешёвых прогонах; по итогу решить, остаётся ли ИИ-аватар в витрине. Отдельно ждёт своей очереди пересборка интерфейса холста единым макетом для пяти форматов.
Разобрана настоящая причина отказов оживления: не кадр и не формат, а длина аудио — 28 секунд провайдер отбивает, 10 перекодированных принимает (падающие задачи бесплатны, поэтому границу искали прогонами). Режем теперь звук по паузам на равные части до 15 секунд, текст при этом цел. Починен звук: amix делил громкость на число дорожек, из-за чего ролик выходил на -36 dB и фон был неразличим; после normalize=0 и loudnorm стало -19.4 dB, владелец подтвердил, что улица слышна. Кадр при описанном движении рисуется планом от колен. Действия над готовой работой сведены в общий компонент и стоят одинаково во всех холстах.
→ Живой прогон 30 секунд: ждём две части по 14.4, склеенные в один ролик, весь текст, вертикаль, слышный фон. Если фон покажется петлёй — заводим базу готовых записей вместо генерации.
Аватар упрощён до прямого пути: весь текст одной озвучкой, одно оживление, никакой нарезки. Раньше моя же защита от перерасхода резала речь (из четырёх реплик озвучивались две) и плодила швы. Кадр теперь 9:16, а не 3:4. Атмосфера места слышна (0.28 вместо 0.12 плюс срез гула). Подключён словарь произношения. Текст-хук только когда сценарий пишем мы. Отдельно: действия над готовой работой сведены в общий компонент и стоят в одном месте во всех холстах — раньше в карусели были кнопки, в видео и аватаре не было ничего.
→ Прогон владельца на 30 секунд: ожидаем один ролик целиком, все реплики, вертикаль, слышный фон улицы. Дальше — пересборка интерфейса холста единым макетом для пяти форматов.
Разобрана и устранена причина отказов OmniHuman (висела с 12 спринта): не провайдер, а наш файл — тяжёлый PNG от gpt-image, кадр теперь пережимается в JPEG до 1280. Починена доставка задания в сборку: ролик выходил на 5 секунд с одной репликой из четырёх, потому что задание передавалось через состояние React и не успевало, а речь бралась из ячейки холста. Теперь задание идёт параметром, речь берётся из него целиком. Ролик стал вертикальным 9:16. Добавлены: атмосфера места по описанию кадра, пауза в конце каждого куска речи, стык через последний кадр предыдущего клипа, словарь произношения, текст-хук только когда сценарий пишем мы. Из интерфейса убрана внутренняя кухня: окно перед запуском говорит человеческим языком, в ошибках нет названий провайдеров.
→ Контролируемый прогон аватара владельцем: ждём ролик на 30 секунд двумя кусками с полным текстом. Дальше по его решению: разрешение оживления (сейчас 720p) и пересборка интерфейса холста.
Найдена и устранена причина отказов OmniHuman, висевшая с 12 спринта: не провайдер, а наш файл кадра — тяжёлый PNG от gpt-image. Диагностика прогоном на двухсекундном аудио: PNG 1.9 МБ отбивается и как .jpg, и как .png; JPEG 720x960 с нашего же домена проходит, внешняя картинка тоже. Кадр теперь пережимается в JPEG до 1280 по длинной стороне, картинки сохраняются с настоящим типом. Отдельно: клиенту больше не показывается внутренняя кухня — окно подтверждения говорит человеческим языком, из ошибок убраны названия провайдеров.
→ Контролируемый прогон аватара владельцем — должен пройти до конца. Дальше: пересборка интерфейса холста (сейчас накопились слои), превью до денег, память задач.
Задание доведено до генератора. Пост и карусель рисуют прямо по разобранному заданию, минуя агента-переписчика. Аватар и видео получают задание в карточке (task_spec) и берут из него речь дословно, действие в кадре и описание кадра; decideScene больше не вызывается, когда кадр описан человеком. Режиссёр аватара переведён с прямого ключа OpenAI на OpenRouter. Окно подтверждения блокирует запуск без лица и без фото. Проверено без генераций: задание сохраняется в карточке целиком, аватар без лица не запускается, полное задание разбирается чисто и даёт смету 330 рублей всё включено.
→ Ждём контролируемого прогона аватара владельцем: один ролик под наблюдением логов и кабинета Kie. Дальше Э4 — превью до денег, память задач, автоперерисовка при расхождении результата с заданием.
Приёмщик подключён ко всем пяти холстам: перед работой показывается «понял так» и смета, списание только после подтверждения. Роли приложенных картинок определяются зрением из ролей, названных человеком. Вычищены приписки из промтов генератора: тот же промт, что раньше давал рекламный плакат с выдуманными лозунгами, теперь даёт ровно заказанное фото. Добавлен слой качества: кадр перед дорогим шагом рисуется в двух вариантах и проверяется по чеклисту (аватар 3 руб против 200), результат сверяется с заданием по цене и телефону. Проверки прогнаны на готовых картинках без генераций; из платного — один пост 10 руб.
→ Довести Задание до генератора (сейчас спека показывается человеку, но в генерацию уходит по-старому), снести старые догадки decideRefRole и decideScene, перевести режиссёра аватара на OpenRouter. Контролируемый прогон аватара — по слову владельца. Отдельно: Kie трижды не уложился в 240 секунд на посте с длинным текстом, поднять ожидание до 300.
Собран и выложен приёмщик задач: одно ядро, пять профилей форматов, строгая схема ответа, температура 0, эндпоинт /api/smm/task/parse (ничего не генерит и не списывает). Прогон на 110 постановках задачи по всем пяти форматам без единой генерации: было 91 верно, стало 108 после того, как количество единиц, цены и телефоны, роль звукового файла и отличие темы от речи забрали у модели в код. Аватар, видео, карусель и Ролс разбираются чисто 22 из 22. Отчёт docs/PARSER-RUN.md, набор кейсов scripts/parser-cases.py.
→ Подключить приёмщика к холстам с окном «понял так» и сметой (порядок: пост, карусель, Ролс, видео, аватар), добавить зрение для ролей картинок, вычистить наши приписки из промтов генератора.
Ночная сессия: этап Э1 «перестать терять данные» сделан и выложен на стенд (коммит 08e699a8). Вложения аватара (место, товар, своя озвучка) доезжают до генератора; роли вложений записываются в attachment_roles; ручной режим кладёт речь в task_verbatim и она произносится дословно; заказ длины аватара сохраняется целиком (нашли: сохранялись только 8/15/30, остальное превращалось в null); снят потолок в три сегмента; Veo взял раскадровку холста; авто-Ролс получил бриф; карусель чейнится от свежей обложки; в генератор уходит до 16 картинок вместо 4; подхват сборки фильтруется по компании. Отдельно: цена «всё включено» — сняты доплаты по ходу у аватара. Прогон 9 генераций (5 постов, 2 карусели, 2 Ролса), 73 ₽ по кассе, результаты и картинки — docs/REGRESSION-SET.md. Эталонный пруф проблемы Э3: один и тот же промт в ручном режиме даёт ровно заказанное фото, а в режиме «С ИИ» — рекламный макет с выдуманными надписями.
→ Владельцу утром: прогнать аватар (готова карточка a5c3af8c — 25 секунд, фото места и товара, дословная речь) и видео. Дальше по плану Э2: гейт достаточности, экран «понял так» со сметой, честные отказы. Открытые вопросы прежние: вид экрана подтверждения и поднимать ли превью из Э4 в Э2.
Собран сквозной план починки: docs/FIX-ROADMAP.md (целевая архитектура со слоем Задания, контракт TaskSpec v1, схема данных task_specs/brand_kits, пять этапов с приёмкой, регресс-набор из 40 сценариев, метрики и деградация) и docs/ACCEPTANCE-PIPELINES.md (39 поведенческих критериев в формате делаю-ожидаю). Порядок: Э0 мерки, Э1 перестать терять данные, Э2 деньги под контролем, Э3 ядро (Задание вместо догадок), Э4 превью и сверка, Э5 продуктовые пробелы. Спринты 13 и 14 размечены по этапам, добавлены три задачи Э0.
→ Пять решений владельца из раздела 10 FIX-ROADMAP: порядок этапов, сетка длин аватара, вид экрана подтверждения, разрешение на живой прогон (330 ₽), поднимать ли превью из Э4 в Э2. После ответов — старт Э1.
Ролевой проход: 6 ролей (предприниматель без опыта в ИИ, предприниматель со знанием базы, маркетолог, СММщик компании, СММщик агентства, креатор) x 5 форматов x 12 сценариев = 360 (docs/SCENARIOS-ROLES.md). Перед оценкой проверил по коду, какие функции реально есть: derive, video-edit, композер, шаблоны, пресеты, труппа, бумперы, сторис, upload-media. Итог: 136 работают, 125 наполовину, 99 провальных. Вместе с матрицей по форматам — 475 способов поставить задачу, 140 из них провальные. Найдены 12 новых дефектов Д25..Д36 — это уже не баги, а продуктовые пробелы: нет превью до денег, вариантов, бренд-гайда, пакетной работы, повторяемости, разъезда по площадкам. Заведён спринт 14.
→ Спринт 13 (починка пайплайнов) ждёт четырёх решений владельца из FIX-PLAN. Спринт 14 (продуктовые пробелы) нужно приоритизировать по ролям, на которых зарабатываем: превью до денег и варианты — самые частые запросы, бренд-ассеты и пакетная работа — условие масштабирования агентств.
Второй, углублённый заход по пайплайнам — по коду, а не по памяти. PIPELINES.md переписан (контракт полей холст→сервер, 15 вызовов моделей, все списания, 12 мест где данные молча теряются, реестр Д1..Д24). SCENARIOS.md расширен с 63 до 115 сценариев: 41 работает, 33 наполовину, 41 не даст результата со списанием. Добавлены REPORT и FIX-PLAN с контрактом Задания (TaskSpec). Найдено сверх прошлого разбора: вложения аватара выбрасываются в create-content; Veo игнорирует раскадровку холста и видит idea обрезанной до 300 знаков; длины аватара 16-29 и 46-60 секунд структурно недостижимы; бриф не доходит до режиссёра авто-Ролса; карусель не чейнится от обложки при первом прогоне через очередь; в генератор уходит 4 картинки вместо 16.
→ Ждём решения владельца по четырём вопросам из FIX-PLAN: порядок волн, сетка длин аватара, где живёт подтверждение перед списанием, разрешение на живой прогон аватара (15 с = 330 ₽). Дальше волна 1 (Г7, Г8, Г10, Г11, Г12) — это починка контракта, архитектуру не трогает.
Тяжёлый день с деньгами. Заказчик поймал двойные и тройные списания за ИИ-аватар. Причина: очередь ходила к самой себе через внешний адрес, упиралась в таймаут веб-сервера, считала это сбоем и повторяла задачу — а защита от повторного запуска была написана с оговоркой «кроме внутренних вызовов», то есть не действовала ровно на очередь. Каждый повтор списывал полную цену и слал провайдеру новую задачу. Останавливал генерацию аварийно (снял ключи очереди и перезапустил). Поставлены три заслона: очередь ходит к себе напрямую; повтор в идущую сборку отклоняется даже изнутри (кроме остывшей дольше 45 минут); повтор в уже готовую работу отклоняется тоже. Плюс сверка списания с фактической длиной ролика: короче заказа — возврат, длиннее — доплата. Из 990 руб автоматически вернулось 748. Разобраны и две содержательные жалобы: ролик выходил на 6 секунд, потому что режиссёру велено писать СВОЙ текст с бюджетом 195 знаков, а сценарий клиента шёл справкой — теперь реплики достаются из кавычек кодом и произносятся дословно; кадр не перерисовывался, потому что роутер судил по короткой идее, а режиссёрский промт лежал в описании кадра — теперь роутер видит то, что человек написал. Отдельная мина: приложение читает СВОЙ .env внутри сборки, а не корневой. Правка корневого не действует, сайт при этом работает как ни в чём не бывало — так мы потеряли доступ к очереди и не заметили. Копирование добавлено в cf-deploy.sh.
→ Очередь включена, ничего само не запускается — проверено. ГЛАВНОЕ: живой прогон аватара не сделан, заведена отдельная задача. Перед ним предупредить заказчика про длину сценария и цену. Отдельно заведён отказ провайдера OmniHuman (Volcengine CV API error) — к повторам отношения не имеет. Не забыть при выкатке на прод: вебхуки обоих ботов и адрес приложения в облаке Inngest сейчас указывают на стенд.