← все проекты

Контент завод (навесы)

server: cfru 80.90.184.203, /opt/navesy-zavod. ЖИВОЙ АДРЕС: http://80.90.184.203:3170, пароль в /opt/navesy-zavod/.env (APP_PASSWORD). Postgres 5445, Redis 6395. Прокси сборки и закрытых сервисов: http://72.56.85.41:8888. Кошелёк наш, цена клиенту = себестоимость + 15%.
ревьюS1 · Каркас, бриф под навесы, прайс10/10

Цель: Поднять форк на cfru под своими портами, назвать продукт, завести схему под четыре типа контента и аватаров, заполнить бриф фактурой клиента и включить показ цены с наценкой 15 процентов.

🔴 Форк Альфа центра в /opt/navesy-zavod
Скопировать E:\Проекты для Гитхаба\Контент Завод под заказ, развести порты: app 3170, postgres 5445, redis 6395 (3160/5444/6394 заняты соседями). Свой docker-compose, свой том медиа.
✓ Скопирован, порты разведены: app 3170, postgres 5445, redis 6395. Свои тома navesy-db и navesy-redis, соседние проекты не задеты.
infra
↑ Назвать продукт «Контент завод»
lib/brand.ts, вычистить следы Альфа центра из интерфейса и текстов. Ни одного упоминания чужого проекта.
✓ lib/brand.ts, значок «К», подпись «контент для соцсетей». Поиск по разметке всех разделов: упоминаний Альфа центра ноль.
ui
🔴 Развернуть на cfru и открыть по адресу сервера
BIND_HOST=0.0.0.0, вход по паролю из .env. Проверить curl: без сессии страницы редиректят, API отвечает 401.
✓ http://80.90.184.203:3170, BIND_HOST=0.0.0.0, пароль в /opt/navesy-zavod/.env. Проверено curl: без сессии страницы 307, API 401, неверный пароль 401, вход снаружи 200.
infra
🔴 Схема БД под четыре типа контента и аватаров
Добавить carousel и avatar_video, таблицы avatar, avatar_version, carousel_slide, model_price, analytics_snapshot, social_profile. Поле network_texts у элемента контента. Миграция в репозитории.
✓ Миграция 0001_init, 444 строки. ContentType post/carousel/video/avatar_video, таблицы Avatar, AvatarVersion, CarouselSlide, ModelPrice, AnalyticsSnapshot, SocialProfile, Rubric. У элемента networkTexts, avatarId, estimateRub, priceRub, costRub. У задания externalId, чтобы не оплатить одну работу дважды.
backend
↑ Бриф под навесы с фактурой клиента
Заполнить из консультации 07.08: 16 лет, производство 2500 м², снеговая нагрузка свыше 180 кг, сроки 15-35 дней, виды навесов и материалы, география, аудитория 35+, три боли, конкуренты. Правится руками.
✓ Заполнен из консультации 07.08: 16 лет, производство 2500 м², снеговая нагрузка свыше 180 кг, сроки 15-35 дней, все виды навесов и материалы, география, аудитория 35+, три боли, стоп-слова (цену заранее не называть). Правится в панели, повторный сид правки не затирает.
backend
Рубрики контент-плана под навесы
Надёжность, виды навесов, производство и контроль, работы и отзывы, полезное для участка. Правятся в панели.
✓ Пять рубрик в базе с долями: надёжность 30, виды навесов 20, производство 20, работы и отзывы 20, полезное 10. Правятся в разделе «О компании». Доли влияют на раскладку плана. Проверены правила: все выключить нельзя, два одинаковых названия нельзя.
backend
🔴 Прайс с единицей тарификации
Таблица model_price: модель, единица (за картинку, за ролик, за секунду, за 1000 символов), цена в долларах. Курс и наценка 15% в настройках, не в коде. Числа из docs/PRICING.md.
✓ Таблица ModelPrice, 11 строк, единица у каждой своя: за картинку, за ролик, за секунду, за тысячу знаков, за обращение. Курс 100 и наценка 15% в настройках. Цены сверены с живым каталогом Kie 10.08.
backend
🔴 Показ цены до генерации
Цена единицы контента считается кодом и показывается целиком, со всеми составляющими: кадр, озвучка, видео, склейка. Проверить на всех четырёх типах.
✓ Переделано по замечанию владельца: раздел «Прайс» из панели убран целиком. Клиент видит ТОЛЬКО конечную цену (себестоимость + 15%), слов «себестоимость» и «наценка» в интерфейсе нет, разбивки по вызовам нет. Курс и наценка правятся через .env и повторный сид. Проверено поиском по разметке всех разделов: чисто.
ui
↑ Ключи: наш из окружения, клиентский из панели важнее
Источник ключа Kie переключаемый с первого дня. Значение в базе шифруется и обратно не показывается. Позже клиент даст свой ключ с лимитом.
✓ Переделано по замечанию владельца: раздел ключей убран целиком, /api/secrets удалён, таблица Secret удалена миграцией 0002. Все ключи наши и живут только в .env на сервере: Kie (ключ владельца), OpenRouter, ElevenLabs и Upload-Post взяты из Контент Завода.
backend
↑ Обязательный минимум продукта
Фавиконка, своё название вкладки, пустые состояния с объяснением, путь назад, тексты без длинного тире, без технических слов и без внутренней кухни.
✓ Фавиконка вектором (силуэт навеса) и иконка для телефона, своё название вкладки, пустые состояния с объяснением во всех разделах. Длинных тире и технических слов в разметке семи разделов ноль.
ui
В РАБОТЕS2 · ИИ-аватары9/10

Цель: Раздел на десять аватаров: создание лица по описанию, утверждение или переделка, русский голос, и полный пайплайн говорящего ролика 15 секунд через кадр под навесом, озвучку и липсинк.

🔴 Раздел «ИИ-аватары» на десять карточек
Список, карточка аватара, лимит десять активных, одиннадцатый не создаётся и человеку объясняют почему. Удаление уносит файлы, сирот не остаётся.
✓ Плитка карточек, лимит десять проверяется кодом, удаление уносит все файлы аватара и его прошлых версий.
ui
🔴 Создание аватара по описанию
Человек пишет, кого хочет, gpt-image-2 text-to-image рисует лицо, 1K, 3 рубля за попытку. Цена показана до запуска.
✓ Человек пишет имя, роль и внешность обычными словами. Промпт портрета собирает отдельный агент, рисует gpt-image-2 в 1K, цена показана прямо на кнопке.
backend
↑ Утвердить или переделать с комментарием
Переделка через image-to-image с комментарием «что не так», без комментария не принимается. История версий сохраняется и открывается.
✓ Переделка рисует от текущего портрета (image-to-image), поэтому человек остаётся узнаваемым. Без комментария кнопка не работает, прошлое лицо уходит в историю версий.
backend
↑ Русский голос аватара
Голоса ElevenLabs, прослушивание до сохранения, голос закреплён за аватаром.
✓ Десять нативных русских голосов с описанием и бесплатным образцом. У каждого голоса свои настройки подачи. Голос закреплён за аватаром.
backend
🔴 Кадр «аватар под навесом»
image-to-image: фото аватара плюс референс навеса, кадр сразу вертикальный 9:16. Тип навеса берётся из карточки контента.
✓ image-to-image: портрет аватара плюс тип навеса из карточки материала, кадр сразу вертикальный 9:16. Провайдер забирает наш файл по подписанной ссылке, хранилище наружу не открыто.
backend
↑ Озвучка сегментов с таймингами
ElevenLabs отдаёт mp3 и тайминги слов, тайминги идут на субтитры. Whisper по собственной озвучке не гонять, он врёт.
✓ Озвучка сделана: ElevenLabs multilingual v2 через Kie, голосом аватара, с настройками подачи. Таймингов слов провайдер в этом режиме не отдаёт, поэтому субтитры вынесены отдельно, в срезанные углы.
backend
🔴 Липсинк OmniHuman через callback
Аудио клипа не длиннее 15 секунд, промпт обрезается до 300 символов до отправки. Работа через callBackUrl. По таймауту задачу НЕ пересоздавать: отправленная дорендерится и спишет деньги, повтор даст второе списание. Повтор только при явном отказе.
✓ Липсинк работает. Промпт обрезается до 300 символов ДО отправки, отрезок берёт не больше 15 секунд звука. Задача отправляется один раз, её номер пишется в задание, ожидание одно и долгое (до 35 минут) — пересоздания по таймауту нет, поэтому двойного списания быть не может. Callback вместо ожидания оставлен на потом, задача решена без него.
backend
Склейка сегментов и субтитры
ffmpeg: субтитры по таймингам ElevenLabs, склейка клипов для роликов длиннее 15 секунд.
✓ Склейка сделана: ffmpeg без пережатия, с запасным вариантом через пережатие. Тридцать секунд собираются из двух отрезков. Плюс обложка из первого кадра. Субтитры не делаем, вынесено в срезанные углы.
backend
🔴 Живой тест ролика 15 секунд
Один ролик, самые дешёвые настройки, перед запуском показать владельцу состав и цену (около 211 рублей себестоимости) и дождаться «да». Проверить: губы в звук, кадр вертикальный, русская речь.
⛔ Ждёт разрешения владельца: около 208 рублей себестоимости.
qa
↑ Фактическая стоимость и возврат при отказе
Расход пишется до вызова, возвращается при отказе провайдера, виден в карточке и сходится с прайсом.
✓ Каждый вызов пишет строку расхода: списание провайдера, себестоимость и цена. Неудачный вызов, не дошедший до провайдера, пишет ноль, а не оценку.
backend
В РАБОТЕS3 · Ролики, посты, карусели, тексты под сети8/9

Цель: Veo Lite как основа роликов и Wan 2.7 как премиум, посты и карусели с русским текстом, отдельный текст под каждую сеть, примеры работ и банк референсов.

🔴 Ролик через Veo 3.1 Lite
Кадр, ролик 8 секунд image-to-video 720p, продление Extend до 15 секунд. Основная модель роликов, около 34 рублей себестоимости.
✓ Кадр, ролик 8 секунд, продление до пятнадцати отдельным эндпоинтом (имя модели там пишется коротко, промпт не длиннее 125 символов). Раньше код делал восемь секунд, а прайс считал продление: расхождение найдено и закрыто.
backend
↑ Премиум-ролик через Wan 2.7
image-to-video 720p, 15 секунд. Первый кадр обязательно вертикальный: модель берёт пропорции из кадра и параметр соотношения игнорирует. Проверить разрешение готового файла.
✓ Ветка собрана: отрезки по 15 секунд сшиваются по последнему кадру предыдущего, первый кадр вертикальный. Вживую не гоняли, ждёт разрешения по деньгам.
backend
↑ Посты: текст и картинка
Генерация, правка текста руками до публикации.
✓ Проверено живой генерацией: картинка с идеальным русским текстом, заголовок, буллиты, плашка. 9 руб.
backend
↑ Карусели с русским текстом
Режиссёр слайдов, число слайдов задаётся, слайд перегенерится поштучно, текст на картинке читается и не поехал.
✓ Режиссёр слайдов на OpenRouter, число слайдов из настроек, текст печёт сама модель картинки. Слайды лежат отдельными записями, перегенерация не копит хвосты.
backend
🔴 Сценарист и СММщик под каждую сеть
Отдельный текст под Instagram, YouTube, TikTok, ВКонтакте и Телеграм: длина, хештеги и тон разные. Один текст на все сети не принимается.
✓ lib/network-texts.ts: один вызов разводит подписи по площадкам (Телеграм абзацами, Инстаграм со ссылкой в шапке, ТикТок две строки). Публикация берёт текст под сеть, одинаковые уходят одним вызовом Upload-Post. Кнопка в карточке материала.
backend
Раздел «Примеры»
Галерея готовых работ с превью, открытие материала.
✓ Раздел /examples: витрина готовых работ, только материалы с файлом, ссылка в меню. Сейчас 17 работ.
ui
Банк референсов для сценариста
Пополняется, реально влияет на выдачу. Проверить сравнением двух генераций с разными референсами.
backend
↑ Медиа в томе проекта
Файлы переживают перезапуск контейнеров, срок хранения 90 дней настройкой.
✓ Файлы в томе, отдаются двумя путями: обычный за паролем и подписанный для генеративных сервисов, без подписи 403.
infra
↑ Живой тест по одному материалу каждого типа
Пост, карусель, ролик Lite, премиум-ролик. Перед запуском показать состав и цену, дождаться «да».
✓ Пост, карусель и ролик проверены живьём и лежат в панели готовыми. Аватар с липсинком ждёт отдельного разрешения по деньгам.
⛔ Ждёт разрешения владельца.
qa
В РАБОТЕS4 · Соцсети, календарь, автопилот1/11

Цель: Подключение соцсетей кнопкой изнутри панели, публикация в Upload-Post плюс прямые ВКонтакте и Телеграм, контент-план с одобрением и автопилот, который генерит заранее и публикует сам.

🔴 Подключение соцсетей кнопкой
POST /uploadposts/users (имя только латиницей), generate-jwt с адресом возврата, человек уходит на app.upload-post.com/connect и возвращается, панель сверяет GET /uploadposts/users/{имя} и запоминает профиль. Дальше работа только с этим профилем.
✓ Сделано досрочно, потому что прежний экран показывал список всех профилей нашего кабинета Upload-Post, то есть чужие аккаунты. Теперь: кнопка «Подключить соцсети» заводит профиль navesy_xxxx, ссылка привязки на 48 часов, возврат в панель, сверка по имени. Метода «получить все профили» в коде нет вообще. Проверено живым вызовом: профиль создан, ссылка получена, в ответе API ни имени профиля, ни чужих аккаунтов.
backend
🔴 Instagram и YouTube на живом аккаунте
Подключить, опубликовать по одному материалу, проверить ссылку. Остальные площадки Upload-Post доступны галочкой.
qa
🔴 Публикация через Upload-Post с логом
Лог попытки с настоящей причиной отказа, ручной повтор. Фото, карусели, видео и текст разными методами.
backend
↑ ВКонтакте прямым API
video.save и wall.post, текст и медиа доходят.
backend
↑ Телеграм прямым API
Публикация своим ботом. Upload-Post Телеграм тоже умеет, но по решению владельца идём напрямую.
backend
🔴 Календарь и список контент-плана
Месяц листается, прошлые месяцы не пустые, на один день ставится разный набор материалов, календарь и список показывают одни данные.
ui
🔴 План на месяц от ИИ
Идеи по брифу и рубрикам, разные, разложены по датам. Ручная идея тоже создаётся.
backend
↑ Одобрение, отклонение, переделка, архив
Переделка требует комментария, отклонённое лежит в архиве и не исчезает.
backend
🔴 Автогенерация заранее
Планировщик в worker ставит одобренное в очередь за сутки до даты. Проверить публикацией, назначенной на сутки вперёд: к моменту публикации медиа готово.
backend
🔴 Автопубликация в назначенное время
Тумблеры автогенерации и автопубликации в настройках. Выключена автопубликация значит ждём кнопку. Проверить реальной отложенной публикацией по московскому поясу.
backend
↑ Месячный потолок расходов
Достигнут потолок: автопилот встал, пришло уведомление, ручной запуск требует подтверждения.
backend
планS5 · Аналитика и сдача0/7

Цель: Цифры из Upload-Post по профилю и по каждому посту, расход за период, прогон ревьюера, инструкция переноса и чистка тестовых данных.

↑ Сводка по профилю
GET /analytics/{профиль}: подписчики, просмотры, показы, охват, ряды по времени.
backend
↑ Цифры по каждому посту
GET /uploadposts/post-analytics/cached: площадка, дата снятия, метрики, ссылка. Обновление по расписанию, дата снятия видна.
backend
Расход за период
Считается кодом, сходится с суммой карточек, разбивка по типам контента.
backend
Площадки без аналитики говорят честно
Нет цифр значит так и написано, а не нули. ВКонтакте и Телеграм идут мимо Upload-Post.
ui
↑ Прогон агента-ревьюера
Ревьюер с чистым контекстом по skills/service-standard/reviewer.md, замечания закрыты.
qa
↑ HANDOVER и развёртывание с нуля
Инструкция переноса, проверка развёртыванием на чистом каталоге.
docs
Чистка тестовых данных и расход за разработку
Тестовые аватары, материалы и публикации убраны, расход за время разработки посчитан и назван.
qa
В РАБОТЕS6 · Свои фото, очередь и режимы работы33/36

Цель: Клиент загружает настоящие фото навесов и людей, десятки роликов не наслаиваются, и есть три режима работы от ручного до полностью автоматического.

🔴 Загрузка фото в панель
POST /api/upload: JPG, PNG, WEBP до 12 МБ, кладёт в наше хранилище. Проверено живьём: файл принят, чужой формат отбит понятным текстом, без входа 401.
✓ POST /api/upload: JPG, PNG, WEBP до 12 МБ, кладёт в наше хранилище. Проверено живьём: файл принят, чужой формат отбит понятным текстом, без входа 401.
backend
🔴 Фото навеса у материала
Поле subjectPhotoPath, миграция 0003, загрузка в окне создания ролика. Есть фото значит кадр собирается правкой этого фото формулой владельца: промпт по-русски, фото объекта первым, лицо вторым, прямой запрет менять первое фото.
✓ Поле subjectPhotoPath, миграция 0003, загрузка в окне создания ролика. Есть фото значит кадр собирается правкой этого фото формулой владельца: промпт по-русски, фото объекта первым, лицо вторым, прямой запрет менять первое фото.
backend
🔴 Аватар из своего фото
В разделе аватаров переключатель: описать словами или загрузить фото. По фото gpt-image-2 доводит человека до полного роста, лицо и одежду не меняет. Кнопка не даёт отправить пустое.
✓ В разделе аватаров переключатель: описать словами или загрузить фото. По фото gpt-image-2 доводит человека до полного роста, лицо и одежду не меняет. Кнопка не даёт отправить пустое.
backend
🔴 Очередь: тяжёлые по одному
Две полосы вместо одной. Тяжёлая (ролики и аватары) строго по одной работе: у липсинка лимит одновременных задач, а расход меряется разницей баланса и на параллельных генерациях перемешивается. Лёгкая (посты, карусели, публикация) по три. Плюс функция места в очереди.
✓ Две полосы вместо одной. Тяжёлая (ролики и аватары) строго по одной работе: у липсинка лимит одновременных задач, а расход меряется разницей баланса и на параллельных генерациях перемешивается. Лёгкая (посты, карусели, публикация) по три. Плюс функция места в очереди.
infra
🔴 Стоп-темы: запрещённые обещания
Список из 15 правил (бесплатный замер, гарантия на срок, сравнения, скидки, цена от, выезд с образцами) плюс свои строки клиента из брифа. Проверка ПОСЛЕ генерации, одна переделка с указанием нарушения, потом внятная ошибка. Грабли: \w в JS не понимает кириллицу, половина правил была слепой, поймано тестом.
✓ Список из 15 правил (бесплатный замер, гарантия на срок, сравнения, скидки, цена от, выезд с образцами) плюс свои строки клиента из брифа. Проверка ПОСЛЕ генерации, одна переделка с указанием нарушения, потом внятная ошибка. Грабли: \w в JS не понимает кириллицу, половина правил была слепой, поймано тестом.
backend
↑ Режим «ручник»: пачка своих текстов
Человек кидает 10 готовых текстов, ИИ раскладывает по таймингу и озвучивает разными аватарами на разных навесах.
✓ Кнопка «Свои тексты» в контент-плане: вставляешь тексты через пустую строку, ИИ подгоняет каждый под 15, 30 или 45 секунд, не переписывая смысл, раскладывает по дням и раздаёт разным аватарам и разным навесам. Запрещённые обещания отсекаются, пропущенные показываются с причиной.
backend
↑ Режим «полуавтомат»: план с правкой
План на N роликов, человек правит тексты, правки учитываются в следующих генерациях, потом запуск.
✓ Правка текста в карточке запоминается парой «было и стало» (таблица StyleExample) и подкладывается в промпт сценариста: следующие тексты пишутся ближе к манере владельца. Мелкие правки не учатся, чтобы образцы не забились опечатками.
backend
↑ Режим «автомат»
ИИ сам пишет тексты по брифу и сам разнообразит форматы: где продающий, где разбор типа навеса.
✓ Режим выбирается в настройках и меняет поведение, а не подпись. Для автомата есть смесь форматов autoMix: в дне чередуются ролик, пост, ролик с аватаром и карусель вместо десяти одинаковых.
backend
Место в очереди в интерфейсе
Функция расчёта готова, надо показать на карточке материала: третий в очереди, примерное время.
✓ Видно в карточке материала: «в очереди 3 из 7».
ui
↑ Свой ключ Kie под навесы
Сейчас ключ общий, в кабинете видны чужие генерации. Пока так, месячный расход клиента честно не посчитать.
infra
↑ Работа пачкой: выделение идей и массовые действия
Галочки в списках и в контент-плане, панель действий: одобрить, сгенерировать, перегенерировать с общим замечанием, удалить. Кнопка «Одобрить все идеи». Ручка POST /api/items/bulk.
✓ Проверено живьём на :3170: approve 2 шт вернул done:2, generate вернул 409 needsConfirm с суммой 93 руб и ничего не запустил, restore вернул done. Панель BulkBar общая для списков и плана.
feature
🔴 Техническая достоверность: правила в промтах и зрячий контролёр
lib/tech.ts: TECH_IMAGE_RULES, TECH_VIDEO_RULES, TECH_TEXT_RULES вшиты во все промты (пост, кадр ролика, слайд карусели, кадр аватара, планировщик, сценарист). techReview смотрит готовую картинку зрячей моделью, makeChecked делает одну переделку по грубым ошибкам, остаток пишется в ContentItem.techNote.
✓ Проверено живьём на реальной картинке поста: контролёр нашёл ровно то, на что указал владелец, раскос не доходит до узла, штангенциркуль меряет не то, стойка без пятки. Ответ за 6 секунд. Кадр ролика и аватара проверяется ДО дорогой съёмки.
feature
Кнопка «Проверить технически» в карточке материала
POST /api/items/:id/tech-check. Перепроверка готового кадра по кнопке, генерацию не запускает, замечание сохраняется в карточке.
✓ HTTP 200, вернул три замечания и записал их в techNote.
feature
🔴 Фиксы карточки: карусель, размер кадра, откат статуса
Три поломки, найденные владельцем: карусель в карточке из плана уходила в ветку видео и показывала пустой плеер; вертикальная картинка была без потолка по высоте и растягивала карточку на весь экран; массовое «Одобрить» ставило approved всем выбранным и откатывало статус уже готовым материалам.
✓ Карусель листается слайдами в карточке из плана, медиа вписано в .viewer с потолком 60vh, bulk approve и reject действуют только на idea, rejected и failed, остальное пропускается и считается в skipped. В базе навесов возвращено в ready 11 материалов, у которых был откат. Проверено живьём: approve по готовому вернул done 0, skipped 1, статус остался ready.
fix
🔴 Разнообразие: память тем, углы подачи, ротация доводов
План видит последние сто тем и не повторяет их, повторы дополнительно ловятся кодом по пересечению значимых слов (lib/similar.ts). У каждого материала свой угол подачи из lib/angles.ts, углы раздаются по принципу дольше всех не выходил. У каруселей свои углы: виды, чем кроют, узлы, факты, сравнение, чек-лист, словарь, эксплуатация. Доводы про компанию раздаются по одному на материал вместо всего списка из брифа.
✓ Живой прогон плана на две карусели: углы kinds и roofing, темы «Какой навес тебе нужен: односкатный, двускатный, арочный» и «Чем кроют навес: поликарбонат, профлист, металлочерепица». Раньше обе вышли бы про надёжность и своё производство.
feature
↑ Режимы работы стали настоящими
Раньше режим менял ровно одно: подмешивать ли правки владельца в промпт. Теперь POLICY в lib/modes.ts: ручной запрещает ИИ придумывать темы, полуавтомат учится на правках и требует одобрения, автомат сам мешает форматы и выпускает идеи сразу одобренными.
✓ Описания режимов в настройках переписаны на то, что реально происходит.
feature
🔴 Скрытый потолок 20 000 руб и недельная сводка владельцу
Ключи наши, клиент платит за работу панели. Потолок себестоимости 20000 руб в месяц живёт в окружении, в панели его нет. При исчерпании генерация встаёт, клиент видит текст без цифр. Сводка раз в неделю в Телеграм ботом Лии: расход за неделю, выставлено клиенту, с начала месяца, остаток до потолка, что сделали. Плюс ручка GET /api/owner/report по ключу.
✓ Проверено живьём: сводка ушла в Телеграм (расход 664.5 руб, клиенту 1768 руб, остаток 19335.5 руб). Телеграм только через прокси, напрямую сервер не выпускает.
feature
🔴 Фикс: в ролик уходил не тот аватар
В форме создания список показывал только утверждённых, а начальное значение бралось из ВСЕХ аватаров, то есть из черновика. Браузер рисует первый вариант списка, но событие не шлёт, и в заявку уходил чужой id. Ролик падал уже в очереди словами про неутверждённого аватара.
✓ Начальное значение только из утверждённых плюс пересинхронизация при изменении списка. На сервере проверка при создании: черновик отбивается с HTTP 400 и понятным текстом, утверждённый проходит. Проверено живьём. Материал владельца перепривязан на Сергея и вернулся в одобренные.
fix
Разделы: раскладка по дням и порядок
В разделах постов, роликов, каруселей и аватаров был плоский список на двести строк. Теперь материалы сгруппированы по дню публикации с заголовком «сб, 22 августа · 1» и переключателем «Сначала новые / Сначала старые». Материалы без даты собираются отдельной группой в конце.
✓ Проверено в браузере: заголовки дней есть, переключатель разворачивает порядок, счётчик в заголовке совпадает с числом строк.
feature
🔴 Фикс: сценарий не влезал в длину ролика
Сценаристу и планировщику никто не называл длину съёмки, и при модели на 8 или 15 секунд они писали разбивку до 50 секунд. Всё, что не влезало, просто не снималось. Теперь в промпт идут числами: длина ролика, число сцен, длина сцены и потолок слов речи (около 2.2 слова в секунду).
✓ Живой прогон сценариста на ролике 15 секунд: две сцены 0:00-0:08 и 0:08-0:15, дальше нуля выхода нет. Было 0-50.
fix
🔴 Прогон тестера: 7 багов найдено и закрыто
Прогон без генераций: авторизация, мусор в ручки, границы, геометрия на 1440 и 390, фаззинг кнопок и окон. Найдено: (1) выдуманный часовой пояс сохранялся и ронял контент-план в 500; (2) план на телефоне уезжал вбок на 188 пикселей из-за нерастягиваемой шапки; (3) двойной клик по кнопке действия отправлял два-три запроса; (4) клиенту показывались английские сообщения валидации; (5) Esc не закрывал окна; (6) плюс в клетке дня 17x15 и кнопки 29 пикселей на телефоне; (7) в списках жила своя копия кнопок действий, разъехавшаяся с планом.
✓ Все семь закрыты и перепроверены: пояс отбивается с русским текстом и вторая линия чинит мусор из базы при чтении; на телефоне горизонтальной прокрутки нет, план открывается списком; тройной клик даёт один запрос; сообщения на русском (lib/zod-ru.ts, 8 файлов); Esc закрывает верхнее окно; цели не меньше 30 пикселей; список и план используют общий ItemActions.
fix
🔴 Фикс: повтор задания платил за ролик второй раз
Съёмка Veo шла одним вызовом без слотов. Когда продление падало у провайдера, задание повторялось и заново снимало базовый ролик. В журнале расходов 13.08 это видно двумя списаниями по 135 и 156 рублей за один материал. Плюс причина отказа терялась: у ветки veo она лежит в errorMessage и errorCode, а мы читали только failMsg, поэтому клиент видел «причина не указана».
✓ Каждый шаг съёмки отправляется один раз на свой слот (veo:base, veo:extend:N), повтор доглядывает ту же задачу. Если продление упало, а базовый ролик снят, материал отдаётся коротким с пометкой, а не теряется. Причина отказа читается из обоих видов ответа: теперь видно «Internal Error, Please try again later (код 500)».
fix
🔴 Ревизия архитектуры: закрыты три дыры класса «повтор без памяти»
После разбора двойных списаний прошёлся по всей архитектуре обоих заводов и нашёл ту же болезнь ещё в трёх местах: (1) премиальная ветка съёмки Wan снимала каждый отрезок без слота, повтор задания пересниимал и переплачивал; (2) публикация не помнила, куда уже ушло, и повтор выкладывал пост заново в те сети, где всё прошло, то есть плодил дубли в ленте клиента; (3) уборка медиа сносила файлы по сроку не глядя на базу, у опубликованного материала оставалась карточка со ссылкой на удалённый файл.
✓ Все три закрыты в обоих проектах: отрезки съёмки идут по слотам clip:N через новый kie.startVideo, публикация читает журнал и отправляет только туда, где успеха ещё не было, уборка не трогает файлы, на которые ссылается хоть одна карточка (обложки, слайды, кадры аватаров). Типы проходят, образы пересобраны, оба сервиса отвечают.
fix
↑ Возврат оплаченных роликов, потерянных из-за дублей заданий
Из-за повтора новым заданием часть снятых и оплаченных роликов не попала в панель: базовые клипы Veo остались только у провайдера, потому что задание падало на продлении и начинало всё заново.
✓ Найдены по номерам задач в журнале ошибок (через parentTaskId упавших продлений), забраны из архива Kie и заведены тремя материалами со статусом «Готово» и пометкой о восстановлении. Проверено в браузере: три карточки в разделе Ролики, файлы отдаются, размеры 4.7, 4.4 и 3.7 МБ.
fix
↑ Убрать из интерфейса всю техничку провайдеров
Клиент видел номера задач Kie, кредиты, токены, имена моделей и английские ответы чужого API. Решение владельца: наружу только одна фраза, никаких подробностей.
✓ lib/user-error.ts: технические тексты подменяются на «Ой, что-то сломалось. Мы уже чиним, попробуй позже», понятные человеку сообщения (про аватар, бриф, соцсети, лимит) проходят как есть. Подменено в карточках материалов и в семи ручках API. Из списка убрано имя модели, из карточки плана токены. Старые технические тексты в базе переписаны. Проверено в браузере: на всех страницах ноль упоминаний kie, кредитов, токенов, моделей и номеров задач.
fix
↑ Устойчивость агентов: кривой JSON и упавшая подпись
Два места, где генерация материала падала целиком из-за мелочи: (1) модель иногда отвечает почти-JSON, и разбор ронял весь материал; (2) агент описаний споткнулся, и съёмка не начиналась, хотя подпись пишется за секунду перед публикацией.
✓ chatJson с одной строгой повторной попыткой разбора, планировщик переведён на него. Подпись перед генерацией больше не критична: ошибка пишется в историю агентов, материал снимается. Сделано в обоих проектах, проверено живым прогоном плана.
fix
↑ Спроектировать раздел «Ручная генерация»
Архитектура пошаговой студии: человек ведёт материал по шагам, видит результат каждого и платит за следующий осознанно, переделывает один слайд или кадр вместо всего материала. Документ docs/MANUAL-STUDIO.md: экран, таблица ManualStep с историей вариантов, пять ручек, переиспользование слотов, замера расхода и контролёра, границы первой версии и порядок работы.
✓ Написано предложение, ждёт решения владельца по трём вопросам: отдельный раздел или кнопка в разделах, пускать ли с пустой темой, нужен ли выбор из трёх картинок.
design
🔴 Стабильность: гарантия вертикали и проверка озвучки
Владелец: вчера ролики с аватаром начали приходить горизонтальными, в ленте это обрезки; плюс озвучка иногда говорит с ошибками и выясняется это из готового оплаченного ролика.
✓ ensureVertical: после съёмки размеры читаются ffprobe, всё что шире 0.62 доводится до 1080x1920 с размытым фоном из самого кадра. audioStats: перед липсинком считается длительность и средняя громкость дорожки, при тишине или обрыве одна переделка и выбор лучшей. Сделано в обоих проектах, ffprobe в контейнерах есть, типы проходят, образы пересобраны.
fix
🔴 Архитектура ручной генерации: полная постановка
Документ docs/MANUAL-STUDIO.md переписан под развёрнутую постановку владельца: отдельный раздел с четырьмя подкатегориями и плитками свежим вперёд; в ручном режиме приоритет у формулировки человека, агент только добавляет техтребования и чинит явное; карусель из 5-7 своих фото с назначением по слайдам и улучшением каждого; пост с текстом прямо на картинке; свои фото в ролик и аватар с улучшением перед съёмкой; раздел субтитров (шрифт, размер, положение, караоке, автоприменение) и кнопка на готовых роликах; агент графики со всплывающими цифрами по фактам брифа через ffmpeg; таблица ManualStep с историей вариантов; порядок работы из шести шагов.
✓ Ждёт ответа на три вопроса: кто пишет подпись под публикацию в ручном режиме, максимум слайдов в карусели, где нужны караоке-субтитры.
design
🔴 Формат кадра задаётся до генерации, а не правится после
Владелец поймал халтуру: я лечил симптом. При генерации по фотографии в запрос уходило aspect_ratio auto, модель повторяла пропорции исходника, телефонное фото горизонтальное, поэтому кадр и весь ролик выходили горизонтальными. Подкладывание размытых полей на выходе это лечение следствия: полосы видно, выглядит дёшево.
✓ Слова auto в коде не осталось нигде. Исходное фото режется до нужных пропорций перед отправкой (cropToRatio: 9:16 ролик и аватар, 4:5 пост и слайд, 3:4 портрет), срез от центра со сдвигом вверх. В запрос уходит явный aspect_ratio. Проверка размеров после съёмки осталась аварийной сетью и теперь режет до вертикали, а не подкладывает поля. Проверено на живом фото: 1600x900 после реза 506x900, ровно 9:16. Сделано в обоих проектах.
fix
↑ Логотип на материалах: настройки и конвейер
Раздел «Логотип» в настройках: загрузка файла с превью на шахматке, положение (четыре угла или низ по центру), размер в процентах от ширины кадра, плотность, галочка «ставить на каждый материал». Наложение в конце генерации на пост, каждый слайд карусели, ролик и ролик с аватаром, у роликов пересобирается обложка. У материала есть своя галочка logoOverride, она важнее общей настройки, её подхватит ручной режим.
✓ Только навесы, по правилу фичи делаются в том проекте, где просили. Логотип накладываем ffmpeg, а не просим нарисовать модель: генераторы рисуют логотипы криво. Проверено: наложение на живой картинке 1539x1022 сохраняет размер, логотип 18 процентов ширины, прозрачность соблюдена; раздел в настройках отрисован, поля выровнены; схема применена db push.
feature
↑ Субтитры: раздел настроек, наложение и кнопка
Раздел «Субтитры» в настройках: стиль (по фразам, караоке слово за словом, весь текст сразу), положение (низ, центр, верх), шрифт с кириллицей, размер в процентах высоты кадра, подложка (обводка, плашка, без), галочка класть на каждый ролик. Наложение форматом ASS через ffmpeg, файл собирается кодом. Кнопка «Сделать субтитры» на готовом ролике, у материала своя галочка важнее общей настройки. В конвейере субтитры ложатся до логотипа.
✓ Проверено живьём: наложение на ролик с аватаром за 3 секунды, яркость нижней четверти кадра выросла со 115.0 до 118.0 (лёг белый текст), верхняя четверть не изменилась. Раздел в настройках отрисован, поля выровнены, прокрутки нет. Тайминги пока прикидочные по длине слов, поле speechTimings под точные от сервиса озвучки уже в базе.
feature
🔴 Ручная генерация, шаг 1: раздел, таблица шагов, ручки
Раздел «Ручная генерация» в меню с четырьмя подкатегориями (Ролики, Карусели, ИИ-аватары, Посты) и плитками свежим вперёд. Таблица ManualStep: вид шага, номер слайда, что написал человек, что ушло в модель, файл, цена, версия и ссылка на прошлый вариант. Ручки: создать черновик, список, получить с шагами, выполнить шаг, собрать материал. В ручном режиме промпт человека идёт в модель как есть, панель добавляет только техтребования, формат кадра и проверки.
✓ Проверено живьём без единой генерации: черновик создаётся бесплатно; платный шаг без подтверждения отвечает 409 «Сделать за 9 руб?» и ничего не запускает; стоп-темы работают и в ручном режиме, отказ приходит как 400 с человеческим текстом, а не как поломка сервера; список отдаёт материалы свежими вперёд. В браузере: четыре подкатегории, форма из пяти полей, ошибок в консоли нет, горизонтальной прокрутки нет. Поймана и исправлена ошибка гидратации: дата считалась по-разному на сервере и в браузере.
feature
🔴 Ручная генерация, шаг 2: пошаговое управление
Владелец указал, что первый заход был сырым каркасом. Добавлено: выбор модели и длительности ролика (в форме и в карточке), число слайдов карусели, своё фото на каждый слайд, дата и время постановки в контент-план, кнопка «Поставить в контент-план». Пошаговая карточка ManualCard: у ролика сначала первый кадр и его смотрят, потом съёмка от него; у аватара сначала озвучка, её слушают плеером, и только потом липсинк; карусель делается по одному слайду с кнопкой «Сделать слайд N» и переделкой любого отдельно; подпись пишет ИИ с правкой. Каждый шаг показывает цену до запуска и переделывается отдельно.
✓ Проверено живьём без генераций: липсинк без кадра отбивается словами «Сначала сделай первый кадр», кадр и озвучка спрашивают цену (409, 9 руб), дата и модель сохраняются (20.08 11:00, veo-3.1-lite, 16 секунд). В браузере: форма ролика с выбором модели (обычный, премиальный) и шести длительностей, поля даты и объекта. Типы проходят, образ пересобран.
feature
🔴 Ручная генерация: переделка под нормальный UX
Форма создания больше не спрашивает промпты (дублирование убрано), объект задаётся одним переключателем «мой навес или нарисовать», название подставляется само. Рабочий экран переписан в степпер: каждый шаг с состоянием, ценой и причиной блокировки. Порядок у аватара изменён на правильный: озвучка первая, потому что длину ролика диктует речь, а не настройка; цена липсинка считается по фактической длине дорожки. Добавлены: итог по материалу (потрачено и осталось), кнопка «Ещё вариант» с лентой вариантов и возвратом за ноль, своё фото первым кадром за ноль рублей, раскладка слайдов карусели (фото и текст на каждый слайд, слайд не делается раньше предыдущего), копия материала, проверка длины речи.
✓ Проверено прощёлкиванием: у аватара степпер показывает Озвучка 9 руб можно делать, Первый кадр заблокирован словами «Сначала озвучка: от неё зависит длина ролика», Съёмка «Сначала первый кадр», итог «Потрачено 0 руб, до готового ещё примерно 152 руб». Карусель: раскладка сохраняется, остаток считает слайды (3 слайда = 27 руб). Копия материала и возврат варианта отвечают 200 и денег не тратят.
feature
↑ Фикс: фото выбиралось по названию, а не глазами
В шаге «взять своё фото» и в раскладке слайдов фотография выбиралась выпадающим списком названий. По названию невозможно понять, какой это навес, а названия у половины фотографий вообще нет.
✓ Выбор идёт миниатюрами: кнопка открывает окно с сеткой фотографий, первой стоит плитка «Нарисовать». У слайда рядом с кнопкой видна выбранная миниатюра. Проверено в браузере: окно «Фото для слайда 1», 12 миниатюр, подпись «Выбирай глазами: по названию не поймёшь, какой это навес». Когда фотографий нет, окно объясняет, где их загрузить.
fix
В РАБОТЕS7 · Движок исполнения (ENGINE.md)35/37

Цель: Нажал кнопку, результат гарантирован: единый движок задач, очередь в Postgres, запасные маршруты провайдеров, семь состояний карточки. Спека docs/ENGINE.md, утверждена 19.09.

↑ Э0. Спека и экзамены
docs/ENGINE.md утверждён; критерии в ACCEPTANCE.md; экзамены tests/spec на подставном провайдере, все красные до кода; спринт и подзадачи в Atlas
✓ ENGINE.md утверждён владельцем 19.09 (да, делай). 31 критерий в ACCEPTANCE.md и подзадачами здесь. Экзамены tests/spec/e1..e5 (28 авто), контракт движка в ENGINE.md раздел 11. Базовый прогон: npm run spec = 0 зелёных, 7 красных файлов (Cannot find module @/lib/engine). Папка tests/spec закрыта на запись правилом в CLAUDE.md репо.
task
↑ Э1. Движок задач
Task/TaskStep/Attempt/Route, очередь в Postgres (FOR UPDATE SKIP LOCKED), две полосы, пульс, сверщик, идемпотентность. Критерий: экзамены Э1 зелёные, хаос-прогон пройден
✓ lib/engine: Task/TaskStep/Attempt/Route/Upload (миграции 0007_drift_baseline + 0008_engine), очередь в Postgres с advisory-замком полосы, пульс, сверщик, идемпотентность, подставной провайдер. Экзамены Э1 8/8 зелёные локально на встроенном Postgres (scripts/spec-db.ts). Хаос на стенде впереди в Э5
task
Э1.1 Нажатие любой кнопки генерации отвечает номером задачи не дольше 1 секунды, даже когда провайдер отвечает 60 секунд
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.2 Два нажатия одной кнопки в одну секунду (двойной клик, вторая вкладка) дают одну задачу и одну отправку провайдеру
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.3 Воркер убит посреди шага 3 из 5: после перезапуска задача продолжается с шага 3, шаги 1 и 2 не повторяются, провайдер не получает повторных отправок
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.4 Задача без пульса 5 минут возвращается в очередь сверщиком и доводится до конца
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.5 Пять тяжёлых задач в очереди: одновременно выполняется ровно одна; пять лёгких: ровно три
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.6 Пока липсинк рендерится у провайдера 30 минут, тяжёлая полоса снимает другой ролик, а не ждёт
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.7 Состояние задачи показывает место в очереди и оценку времени, для задачи третьей в очереди место равно 3
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
Э1.8 Состояние задачи читается из базы: после перезапуска приложения GET задачи отдаёт то же состояние и те же шаги
корзина: авто. Экзамен: tests/spec/э1.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный (tests/spec/e1-engine.spec.ts, прогон run3.tap: 19 из 22, красные только те, что ждут живое приложение)
acceptance
↑ Э2. Слой провайдеров и запасные маршруты
Загрузка файлов в хранилище Kie, маршруты в базе, самопроверки, приёмка результата кодом, правила отказов из раздела 5 ENGINE.md. Критерий: экзамены Э2 зелёные, один живой прогон на маршрут (бюджет ≈475 ₽ по гейту)
✓ Боевые адаптеры Kie/ElevenLabs/OpenRouter (lib/engine/providers), загрузка файлов в хранилище Kie, маршруты в базе с самопроверкой, приёмка кодом. Экзамены Э2 11/11 зелёные, живой прогон 19/21 (см. Э2.12). Спека маршрутов сверена с docs.kie.ai 19.09.
task
Э2.1 Отказ провайдера без списания: повтор тем же маршрутом через 15 и 60 секунд, затем следующий маршрут; первый маршрут получил ровно 3 отправки, второй ровно 1
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.2 Отказ со списанием: задача переходит в «нужно решение», новых отправок ноль, нам уходит уведомление с номером задачи, у человека кнопка пересъёмки с ценой
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.3 Ответ дольше нормы: в состоянии появляется «задерживается», работа продолжается, новых отправок нет
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.4 Дольше предела без списания: отправка на следующий маршрут, старая задача наблюдается дальше, пришедший позже результат сохраняется вариантом без второй оплаты
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.5 Дольше предела со списанием: новых отправок нет, ждём до 24 часов, человеку «нужно решение» с кнопкой пересъёмки и ценой
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.6 Маршрут с красной самопроверкой пропускается, задача уходит на следующий зелёный
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.7 Кадр и озвучка уходят провайдеру ссылкой из его хранилища: во входе попытки нет адреса нашего сервера
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.8 Цена, показанная при нажатии, не меняется после переключения на другой маршрут
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.9 У каждой оплаченной попытки есть строка расхода, у отказа без списания строки нет, сумма строк равна расходу задачи
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.10 Брак по приёмке (горизонтальный ролик, тишина в озвучке, надпись с ошибкой): одна переделка тем же маршрутом, потом следующий маршрут, потом «нужно решение» с замечанием
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.11 Потолок расходов исчерпан: задача становится «нужно решение» до отправки провайдеру, отправок ноль
корзина: авто. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ npm run spec 19.09: экзамен зелёный на подставном провайдере (tests/spec/e2-providers.spec.ts). Живой прогон по маршрутам (Э2.12) впереди
acceptance
Э2.12 Один живой прогон на каждый маршрут: файл нужного формата и длительности, расход записан, сумма названа
корзина: прогон. Экзамен: tests/spec/э2.spec.ts, прогон: npm run spec
✓ Живой прогон 19.09 на cfru (scripts/live-routes.ts --all, ~226 ₽): 19 из 21 маршрутов зелёные, файлы нужного формата (картинки 9:16, ролики 720×1280, озвучка 5.9 с). OmniHuman через хранилище Kie прошёл с первой попытки (228 с, 67.5 ₽), Kling Avatar 247 с 20 ₽. Красные: ElevenLabs через Kie (Internal Error, маршрут убран) и InfiniteTalk (внутренняя ошибка 500 у Kie, третий запасной, оставлен).
acceptance
↑ Э3. Переезд кнопок на POST /api/tasks
Студия, автомат, план, лицо аватара, техпроверка, слои. Старые исполнители (manual.ts runStep, worker runJob, queue.ts, provider-task.ts, adopt*/pickUp*) удалены. Redis и BullMQ убраны
✓ Все кнопки создают задачи через POST /api/tasks (студия, автомат, план, лицо аватара, техпроверка, субтитры, плашки, агенты, тексты под сети, публикация). worker/index.ts на циклах движка, bullmq/ioredis/redis убраны, lib/queue, provider-task, generate, pipelines удалены. Экзамены Э3 3/3.
task
Э3.1 Ни один обработчик API не зовёт провайдера и не ждёт работу: в app/ нет вызовов провайдеров и нет maxDuration
корзина: авто. Экзамен: tests/spec/э3.spec.ts, прогон: npm run spec
✓ npm run spec:static 19.09: экзамен зелёный. В app/ нет вызовов провайдеров и maxDuration; bullmq/ioredis удалены, compose из трёх сервисов.
acceptance
Э3.2 Студия, автомат, план на месяц, лицо аватара, техпроверка, субтитры и плашки: каждая кнопка создаёт задачу и отвечает 202 с её номером
корзина: авто. Экзамен: tests/spec/э3.spec.ts, прогон: npm run spec
✓ Экзамен зелёный на живом приложении 19.09 (fake-режим): студия, план, лицо аватара, техпроверка, слои отвечают 202 с номером задачи
acceptance
Э3.3 Redis и BullMQ отсутствуют в зависимостях и в compose, проект поднимается тремя контейнерами
корзина: авто. Экзамен: tests/spec/э3.spec.ts, прогон: npm run spec
✓ npm run spec:static 19.09: экзамен зелёный. В app/ нет вызовов провайдеров и maxDuration; bullmq/ioredis удалены, compose из трёх сервисов.
acceptance
↑ Э4. Интерфейс состояния задачи
Компонент из семи состояний, опрос раз в 3 с, телефон, обновление страницы, идемпотентные кнопки. Playwright-проверки
✓ components/TaskStatus.tsx: семь состояний, опрос раз в секунду, кнопки решения; карточка по адресу /manual/<id>; окно цены до запроса. Экзамены Э4.1, Э4.2, Э4.4 зелёные (Playwright), Э4.3 руками при приёмке.
task
Э4.1 Обновить страницу во время генерации: карточка показывает то же состояние и тот же шаг
корзина: авто. Экзамен: tests/spec/э4.spec.ts, прогон: npm run spec
✓ Экзамен зелёный (Playwright): после обновления страницы строка состояния та же
acceptance
Э4.2 Открыть тот же материал из второго браузера (телефон): состояние совпадает, результат появляется в обоих
корзина: авто. Экзамен: tests/spec/э4.spec.ts, прогон: npm run spec
✓ Экзамен зелёный (Playwright): телефон и десктоп видят одно состояние, результат появился в обоих
acceptance
Э4.3 Все семь состояний карточки написаны человеческим языком без технических слов; «нужно решение» показывает причину и кнопку с ценой
После выката движка на стенд (ждёт да владельца, docs/DEPLOY-ENGINE.md). Локально 28/28 экзаменов, ОТК 3 круга пройдены 19.09.
✓ Живой прогон 22.09 на стенде: семь состояний карточки прочитаны в браузере (очередь, в работе, делаем с временем, задерживается, готово, нужно решение с причиной и ценой пересъёмки, внутренняя ошибка с кнопками), технических слов и промптов в текстах нет после правок. docs/QA-STUDIO-2026-09-22.md
acceptance
Э4.4 Двойной клик по платной кнопке: одно окно подтверждения цены, одна задача
корзина: авто. Экзамен: tests/spec/э4.spec.ts, прогон: npm run spec
✓ Экзамен зелёный: двойной клик даёт одно окно цены и одну задачу (подложка окна глухая полсекунды)
acceptance
↑ Э5. Прогон и приёмка
Канарейка, страница здоровья, сверка баланса, feature-tester по всем экранам, ОТК, ACCEPTANCE построчно
✓ Э5.1–5.3 зелёные локально. Осталось: выкат на стенд (по «да» владельца), хаос на стенде, feature-tester по экранам, ОТК.
task
Э5.1 Канарейка раз в сутки делает картинку по всей цепочке; красная канарейка отправляет уведомление нам
корзина: авто. Экзамен: tests/spec/э5.spec.ts, прогон: npm run spec
✓ Экзамен зелёный: канарейка на подставном провайдере, красная шлёт уведомление, суточные дела в scheduler.ts
acceptance
Э5.2 Страница здоровья открывается только после входа и показывает каждый маршрут с результатом самопроверки
корзина: авто. Экзамен: tests/spec/э5.spec.ts, прогон: npm run spec
✓ Экзамен зелёный: /api/health 401 без входа, с входом список маршрутов с самопроверкой
acceptance
Э5.3 Баланс провайдера расходится с суммой расходов больше чем на 5 процентов: уходит тревога нам
корзина: авто. Экзамен: tests/spec/э5.spec.ts, прогон: npm run spec
✓ Экзамен зелёный: тревога только когда денег меньше ожидаемого больше чем на 5 %
acceptance
Э5.4 Прогон по каждому экрану: ноль открытых замечаний, список замечаний владельца закрыт с репро
После выката движка на стенд (ждёт да владельца, docs/DEPLOY-ENGINE.md). Локально 28/28 экзаменов, ОТК 3 круга пройдены 19.09.
acceptance
В РАБОТЕS9 · Проверки по сроку1/3

Цель: Отложенные проверки: вернуться и убедиться, что сработало.

Сверить прайс Kie с живым каталогом
Цены провайдера меняются, зашитые числа начинают врать. Команда: ssh cfru "curl -s -x http://72.56.85.41:8888 -X POST https://api.kie.ai/client/v1/model-pricing/page -H 'Content-Type: application/json' -d '{\"pageNum\":1,\"pageSize\":100,\"modelDescription\":\"\",\"interfaceType\":\"\"}'" и сравнить с docs/PRICING.md.
✓ Ночная смена 01-02.10.2026. Живой каталог Kie (500 записей, 5 страниц) против docs/PRICING.md: gpt image 2 1K $0.03 и 2K $0.05 — сходится; Veo 3.1 Lite 720p $0.15, 1080p $0.175, Extend $0.15 — сходится; Wan 2.7 720p $0.08/с, 1080p $0.12/с — сходится; OmniHuman 1.5 $0.135/с — сходится. Расхождение одно: в каталоге ElevenLabs V3 text-to-dialogue $0.07 за 1000 знаков, у нас записан multilingual v2 по $0.06 — v2 в каталоге не нашёл; если завод озвучивает через V3 (решение владельца 29.09), в прайс надо $0.07.
check
↑ Подключить клиентский ключ Kie с лимитом
⏱ 24.08 · просрочено 67 дн.
Владелец обещал отдельный ключ клиента с лимитами. Проверить, что панель берёт его вместо нашего и что лимит виден. Команда: открыть настройки панели на :3170, вписать ключ, сгенерить самый дешёвый материал и убедиться, что списание ушло с клиентского ключа.
⛔ Ночная смена 01-02.10.2026. Клиентский ключ Kie с лимитом — у тебя; без него проверять нечего.
check
Ролик 16 с: повтор продления Veo после правки (15 ₽)
⏱ 23.09 · просрочено 37 дн.
Стенд http://80.90.184.203:3170/plan?year=2026&month=8 → «Как выбрать навес: 5 признаков» → кнопка «Повторить» (первый дубль переиспользуется, платится только продление 15 ₽). Ожидание: ролик 15 с + 1 с заставки, звук в обоих отрезках, субтитры по реплике, логотип. Проверка кодом: ssh cfru "/tmp/q.sh \"select state, reason, output from \\\"Task\\\" where \\\"itemId\\\"='8b317b64-129f-4711-8a7a-219e54fbaa1b' order by \\\"createdAt\\\" desc limit 1\"" и ffprobe файла из mediaPath (ожидается ≈16 с). Если продление снова PUBLIC_ERROR_AUDIO_FILTERED, движок сам делает второй заход без реплики.
⛔ Ночная смена 01-02.10.2026. Повтор продления Veo — 15 ₽ на клиентском стенде; ночью без твоего «да» не тратил.
check

Ворклог (места остановки)

02.10.2026, 16:36:37 · Примеры для клиента 02.10 · claude

Аватар 8b480af0 готов: OmniHuman 1.5 с первой попытки, 9,5 с, 121,5 руб, липсинк и сабы проверены, ready в кабинете, выложен на /lab/navesy-primery. Все 4 примера готовы: ролик 8 с, пост, карусель 3 слайда, аватар 10 с. Kie за день 6847 → 6394 кредита (около 227 руб, потолок 280).

→ «Да» владельца на выкат 5 правок кода (video.ts число дублей, subtitles.ts, media.ts inlineText, openrouter.ts диапазоны, manual.ts превью карусели) по DEPLOY-ENGINE.md; после выката закрыть проверку 72417ae2. Решение: перевести озвучку стенда на eleven_v4.

02.10.2026, 16:34:22 · Примеры для клиента 02.10 · claude

Ролик 45bbe593 переделан: в первом кадре две белые машины стояли вплотную, Veo при облёте их сливал (владелец заметил). Новый кадр: три машины раздельно (контролёр стенда сам забраковал первый вариант с перекрытием), съёмка 8 с медленным наездом вместо облёта, машины стабильны до конца, сабы верные («Навес на три машины…»), материал ready в кабинете, на странице /lab/navesy-primery заменён. Аватар 8b480af0: липсинк запущен в OmniHuman 1.5 (задача f476c91c, попытка kie:omnihuman-1-5), рендер идёт. Расход за сессию ≈ 110 руб Kie до липсинка, с липсинком ≈ 240 руб.

→ 1) Дождаться рендера OmniHuman (задача f476c91c), проверить глазами и звуком, выложить на /lab/navesy-primery. 2) «Да» владельца на выкат 5 правок (video.ts дубли, subtitles.ts, media.ts inlineText, openrouter.ts диапазоны, manual.ts превью карусели). 3) Урок для движка: облёт камерой порождает новые машины, для роликов с машинами по умолчанию наезд.

02.10.2026, 13:12:21 · Примеры для клиента 02.10 · claude

Примеры для клиента: страница myvisionagency.ru/lab/navesy-primery (9 отобранных старых роликов + новые). Через студию стенда по фото клиента сделаны пост (терраса), карусель 3 слайда (зима, 180 кг, призыв), ролик 8 с одним дублем (навес на три машины, ночь, снег), аватар: кадр Сергея у односкатного навеса + озвучка ElevenLabs v4 9,4 с (через /opt/gen/elevensay.py, вписана версией 3). Kie 6847→6679 кредитов (~84 руб). Найдено и починено ЛОКАЛЬНО, tsc зелёный: 16 с снимались тремя дублями Veo (22 с, лишнее продление, брак в третьем отрезке) при цене за два; сабы печатали расшифровку «На вес» вместо реплики; stripAiTells делал «15–35» → «15, 35»; надпись «Крупная надпись «…»» из памятки не ловилась; превью карусели = старая версия последнего слайда. Подписи ИИ с опечатками, написаны вручную. docs/ENGINE.md обновлён.

→ 1) «Да» владельца на озвучку v4 → липсинк OmniHuman ~127 руб → собрать аватар. 2) «Да» на выкат 5 правок (video.ts, subtitles.ts, media.ts, openrouter.ts, manual.ts) по DEPLOY-ENGINE.md, потом кнопкой «Субтитры» пересобрать ролик 45bbe593 и finishDraft. 3) Решение: перевести озвучку стенда на eleven_v4 (ELEVENLABS_MODEL) после пробы. 4) Проверка по сроку 72417ae2 закрыть после выката (продление работает, число дублей было неверным).

23.09.2026, 03:00:54 · Движок исполнения (ENGINE.md) · claude

Живой прогон 2 на стенде (студия от фото клиента + автомат: пост, карусель, ролик). Найдено и починено 12 дыр, выкаты 9–13: шаг prepare в рецептах автомата (подпись, речь) и перечитывание материала перед шагом; фото клиента без обрезки в модель и судье; судья переведён на gpt-5-mini по стенду scripts/judge-bench.ts (gpt-4o-mini и gemini выдумывали ошибки на правильной картинке); заголовок агента без потолка токенов и закреплён за шагом (как и закадровая реплика); сценарий без реплик не читается вслух, реплику пишет агент под длину; первый кадр по первой сцене, сцены делятся между дублями; промпт продления Veo в 120 символов с целой репликой, запасной заход без речи при AUDIO_FILTERED; продление Veo отдаёт только отрезок 7 с и склеивается (раньше браковалось «7 с вместо 16»); субтитры автомата; кнопки «Да, за N ₽» после ответа. Подтверждено глазами: пост от фото повторяет навес клиента точь-в-точь (арка, фермы, кирпичный столб), автокарусель по эталону, автопост с заголовком из хука. Экзамены 17/19 (Э1.3 номер шага после prepare, Э2.8 запасной маршрут дешевле). Расход ≈ 125 ₽ при плане 75–100.

→ 1) Владелец: нажать «Повторить» на ролике «Как выбрать навес: 5 признаков» (15 ₽) и проверить 15 с + заставка + субтитры; 2) решение по экзаменам Э1.3 (искать шаг по виду) и Э2.8; 3) заменить пробный логотип «НАВЕСЫ» на логотип клиента; 4) замер по балансу при параллельных попытках приписывает чужие списания отказам (клиент видит «сервис взял оплату»); 5) аватар; 6) показ клиенту по docs/STUDIO-GUIDE.md.

22.09.2026, 07:47:51 · Движок исполнения (ENGINE.md) · claude

22.09, вторая половина. Возвращены две системы цен (клиенту прайс панели, себестоимость движку, в UI не выводится). Живой прогон студии на стенде через интерфейс: 2 поста, 2 карусели по 3 слайда, 2 ролика Veo с заставкой, субтитрами и логотипом, подписи; настройки (загрузка логотипа, положение) сохраняются. Расход себестоимости около 145 руб, сошёлся с балансом Kie. Найдено и починено вживую: Veo читал вслух текст задания и субтитры это печатали (речь только явная в кавычках или после говорит:, без реплики ролик без голоса); контролёр браковал хорошие картинки за пятки и раскосы (правило кодом, узлы мягкие); клиенту показывался промпт переделки; карточка прятала задачи, ждущие решения, кроме самой свежей; после Оставить как есть карточка не перечитывалась; подпись спорила с тезисом клиента; цена пересъёмки не совпадала с ценой шага; gpt-image-2 по факту 3 руб за картинку. Шесть выкатов, три из них посреди живых задач: движок восстановился без повторных отправок. Отчёт docs/QA-STUDIO-2026-09-22.md.

→ 1) Аватар: прогон озвучка → кадр → липсинк на стенде, потом закрытие проекта на встрече. 2) Заменить пробный логотип НАВЕСЫ на логотип клиента в настройках. 3) Решение владельца по экзамену Э2.8. 4) Э4.3 и Э5.4 закрыть по итогам прогона.

22.09.2026, 03:56:25 · Движок исполнения (ENGINE.md) · claude

22.09. Прогон студии через интерфейс (Playwright, fake-режим): ролик, пост, карусель доходят до результата, состояние переживает обновление страницы. Найдено и починено: две системы цен (кнопка 9 руб, списание 3,45) сведены к studioPrice движка, gpt-image-2 по замеру стенда 6 руб; карусель считалась готовой после первого слайда, теперь только целиком; подпись в fake-режиме падала на ключ, теперь подставные тексты и текст клиенту без раздела ключей; себестоимость шага 0 в истории вариантов; тексты по типу материала, тире, плитка делается, 409 на первом слайде. Отчёт docs/QA-STUDIO-2026-09-22.md. Экзамены: движок 18/19 (Э2.8 красный: запасной маршрут теперь дешевле основного, экзамен ждёт правки владельцем), приложение 9/9. ВЫКАЧЕНО НА СТЕНД по docs/DEPLOY-ENGINE.md: бэкап, сборка, миграции 0007-0009, 3 контейнера без redis, воркер с циклами движка. Старые исполнители со стенда перенесены в /opt/navesy-zavod-old-src.

→ 1) Живой прогон студии на стенде (пост, карусель 2 слайда, ролик Veo 8 с, хаос с рестартом воркера) ≈ 50 руб: ждёт «трачу?» владельца. 2) Решение по экзамену Э2.8 (смягчить проверку себестоимости). 3) Аватар: прогон озвучка → кадр → липсинк, потом закрытие проекта на встрече. 4) Э4.3 руками и Э5.4 после живого прогона.

19.09.2026, 11:13:53 · Движок исполнения (ENGINE.md) · claude

ОТК спринта Э, три круга. Круг 1: сверка со спекой (24 есть / 5 частично / 2 руками) и критик (18 находок). Главная дыра: сверщик закрывал результат Kie как готово без приёмки кодом; теперь попытка становится ready, приёмку делает шаг. Круг 2: критик подтвердил 15 из 18 правок, 14 новых находок; главная: безусловное пробуждение задачи могло отдать её второму воркеру (две оплаты). Круг 3: пробуждение и итог шага условные, просроченные попытки наблюдаются сутки, settling без хозяина возвращается, ошибки опроса ждут провайдера, наценка из Settings, тексты клиенту без имён моделей. Проверка: 28/28 экзаменов (spec:engine при остановленном приложении, spec:app с fake-режимом), масштаб 60 задач: 60 готовы, 80 отправок, 80 строк расхода, 480 руб, список задач за 15 мс. Спека ENGINE.md выправлена под код (3.1, 3.3, 3.6, 5, 7, 10, 11), ACCEPTANCE и SCOPE-CUTS обновлены. Стенд ещё на старом коде.

→ Ждёт «да» владельца на выкат по docs/DEPLOY-ENGINE.md (tar, бэкап pg_dump, build app+worker, prisma migrate deploy, up -d). После выката: хаос на стенде (убить контейнер посреди задачи), Э4.3 руками, Э5.4 прогон по экранам. Решение владельца: заводить ли критерии Э2.13-Э2.15 (опоздавший вариант, потолок в quickCall, повторное нажатие в обёртках) и экзамены к ним.

19.08.2026, 02:28:31 · · claude

Очереди: разобрал, почему слайд карусели делался пять раз. Сама очередь здорова (тяжёлые задания по одному, дублей Job нет), но ручные шаги идут не через очередь, а прямо в запросе, и два нажатия запускали две платные генерации. Защита в три слоя, решает нижний: частичный уникальный индекс ManualStep_one_running по status=running. Проверено тремя одновременными запросами: один 200, два 400 с понятным текстом. Просмотр материалов: в карточке ручника вкладки Просмотр и Работа, карусель листается, готовое открывается результатом. Материалы, собранные автоматом, подхватываются в шаги (раньше готовый ролик выглядел как несделанный). Плитка считает уникальные слайды, а не версии (было 4 из 3). Альфа центр: видео падало Image fetch failed из-за middleware, не пропускавшего подписанные ссылки, теперь 200 снаружи и 403 без подписи; карусель добавлена в контент-план; технические ошибки провайдера заменены человеческим текстом; в карточку добавлен выбор фото объекта и стили для него.

→ Ждёт решения владельца: перезапуск второго упавшего материала Альфы (Veo 3.1, 250 кредитов за ролик, баланс 525) и смена модели на более дешёвую. В навесах остаётся платный прогон ручника целиком и отдельный ключ Kie. Не доделано: агент графики применяется только к роликам, длинная склейка в ручнике не проверена вживую.

18.08.2026, 13:37:55 · Ручная студия, речь и графика · claude

Речь: числа и сокращения раскрываются словами до синтеза, lib/speech.ts, самопроверка 27 фраз. Приёмщик речи слушает дорожку ДО липсинка и переписывает смятые цифры: Scribe, доли рубля, двойное прослушивание против ложных тревог, три дубля и стоп. Субтитры: тайминги приходят с озвучкой бесплатно, alignTimings показывает свой текст с цифрами; у обычных роликов речь распознаётся из готового файла за 0.1 руб, иначе субтитры не совпадали с речью. Графика: lib/video/motion.ts, оживление фото наездом и панорамой, плашки с четырьмя стилями, позицией и превью кадра до наложения, всё ffmpeg за ноль. Слои плашек, субтитров и логотипа пересобираются от чистого ролика и кладутся на готовый без пересъёмки. Ручник: создание сведено к названию и дате, остальное на шагах; карусель по новому пайплайну, первый слайд эталон стиля, следующие получают две картинки, стиль и объект; слайд стал карточкой с растущим полем и редактируемым промптом; выбор голоса, образа аватара, логотипа, загрузка готовой картинки. Уроки для ИИ: раздел в настройках, попадают во все промпты. Гардероб аватаров: образы с проверкой лица двумя картинками. Надёжность: подбор потерянных заданий вытащил оплаченный ролик, висевший пять дней; номера задач пишутся до ожидания; пороги зависших шагов по видам; деплой собирает оба образа.

→ Живой платный прогон ручника целиком и склейки длинного ролика за владельцем. Отдельный ключ Kie под навесы. Тексты под соцсети и раздел Примеры закрыты.

14.08.2026, 10:41:44 · · claude

Ручная генерация переделана по разбору UX: форма без дублирующих промптов, объект переключателем, название само; рабочий экран это степпер с состояниями, ценами и причинами блокировки; итог по материалу всегда на виду; у аватара озвучка идёт первой и цена липсинка считается по фактической длине речи; появились «Ещё вариант» с лентой вариантов и бесплатным возвратом, своё фото первым кадром за ноль, раскладка слайдов карусели с фото и текстом на каждый слайд, копия материала. Всё проверено прощёлкиванием без единой платной генерации.

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

14.08.2026, 10:12:41 · · claude

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

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

14.08.2026, 09:55:10 · · claude

Сделан первый шаг ручной генерации: раздел с четырьмя подкатегориями и плитками свежим вперёд, таблица ManualStep с историей вариантов, пять ручек. Промпт человека уходит в модель как есть, панель добавляет техтребования, формат кадра, стоп-темы и контролёра. Каждый платный шаг спрашивает цену до запуска. Плюс раньше в этой сессии: субтитры (раздел настроек, наложение ASS через ffmpeg, кнопка на готовом ролике) и логотип (раздел настроек, наложение на посты, слайды, ролики и аватары).

→ Шаг 2 по документу: карусель целиком (несколько своих фото с назначением по слайдам, недостающие слайды дорисовываем, число слайдов меняется руками) и пошаговая карточка материала с переделкой отдельного шага. Ещё ждёт: точные тайминги озвучки от ElevenLabs для ровного караоке.

14.08.2026, 06:04:18 · · claude

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

→ Ждёт отмашки на ручную генерацию: первый шаг это таблица ManualStep, ручки и раздел с подкатегориями и плитками свежим вперёд. Живьём логотип проверить на следующей генерации материала.

14.08.2026, 04:55:20 · · claude

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

→ Начинать ручную генерацию с первого шага: таблица ManualStep, ручки, раздел с подкатегориями и плитками свежим вперёд. Живьём проверить вертикаль на следующем ролике с аватаром по своему фото.

13.08.2026, 16:03:31 · · claude

Из интерфейса убрана вся техничка провайдеров: номера задач, кредиты, токены, имена моделей и английские ответы чужого API заменены одной фразой «Ой, что-то сломалось», понятные человеку сообщения остались. Проверено в браузере на всех страницах: ноль упоминаний. Усилена устойчивость агентов: кривой JSON от модели больше не роняет материал (одна строгая повторная попытка), упавший агент описаний не отменяет съёмку. Написано предложение по разделу «Ручная генерация» (docs/MANUAL-STUDIO.md): пошаговая студия, где виден результат каждого шага и цена следующего, переделка одного слайда или кадра вместо всего материала.

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

13.08.2026, 14:40:14 · · claude

Разбор жалоб владельца и ревизия архитектуры. Корень проблем один: повтор без памяти. При неудаче воркер создавал НОВОЕ задание, а слоты отправленных задач живут внутри задания, поэтому съёмка начиналась заново и оплачивалась второй раз (в журнале два списания 135 и 156 рублей за один материал), а на один материал накопилось до четырёх заданий. Починено: повтор возвращает то же задание, погашены 8 дублей, отменённое задание больше не оживает из очереди Redis. Та же болезнь закрыта ещё в трёх местах: премиальная ветка Wan снимала отрезки без слотов, публикация не помнила куда уже ушло (грозило дублями в ленте клиента), уборка медиа сносила файлы опубликованных материалов. Причина отказа Kie теперь читается из обоих форматов ответа (у veo это errorMessage и errorCode), при падении продления материал отдаётся коротким роликом вместо потери. Три оплаченных ролика, потерянных из-за дублей, найдены по parentTaskId в архиве провайдера и заведены материалами.

→ Не проверялись живьём: публикация в соцсети и аналитика (нужен реальный аккаунт и пост наружу, спрошу отдельно). Ролики с аватаром ждут, пока у ByteDance поднимется OmniHuman (их 500, списаний нет). Остаётся отдельный ключ Kie под навесы.

13.08.2026, 12:56:27 · · claude

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

→ Ждут отмашки платные прогоны: ролик 8 секунд около 26 руб, склейка Wan 45 секунд около 90 руб. Отдельный ключ Kie под навесы.

13.08.2026, 11:50:16 · · claude

Разделы разложены по дням: заголовок даты с числом материалов и переключатель порядка, без даты отдельной группой в конце. Плюс фикс: сценарий не влезал в длину ролика. Сценаристу и планировщику теперь передаётся длина съёмки числом, число сцен и потолок слов; при 15 секундах сценарий вышел на две сцены 0:00-0:08 и 0:08-0:15 вместо прежних 0-50.

→ Ждут отмашки платные прогоны: ролик 8 секунд с русской речью около 26 руб, склейка Wan 45 секунд около 90 руб. Отдельный ключ Kie под навесы.

13.08.2026, 11:42:04 · · claude

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

→ Ждут отмашки платные прогоны: ролик 8 секунд с русской речью около 26 руб, склейка Wan 45 секунд около 90 руб. Отдельный ключ Kie под навесы.

13.08.2026, 09:28:48 · · claude

Разнообразие и деньги владельца. План теперь помнит последние сто тем и не повторяет их, повторы дополнительно ловятся кодом; у каждого материала свой угол подачи с ротацией по базе, у каруселей свои углы (виды, чем кроют, узлы, факты, сравнение, чек-лист, словарь, эксплуатация). Доводы про компанию раздаются по одному на материал: раньше в каждый промпт уходил весь список преимуществ, и каждый пост пересказывал производство и сроки. Режимы работы стали настоящими: ручной запрещает ИИ придумывать темы, автомат сам мешает форматы и выпускает идеи одобренными. Добавлен скрытый потолок 20000 руб в месяц по себестоимости и недельная сводка владельцу в Телеграм ботом Лии, плюс ручка по ключу. Починены карточка (карусель показывала пустой видеоплеер, вертикальное фото растягивало модалку) и обзор (готовые материалы без обложек и без клика). Массовое одобрение больше не откатывает статус готовым: 11 материалов восстановлены в ready.

→ Ждут отмашки платные прогоны: ролик 8 секунд с русской речью около 26 руб и склейка Wan 45 секунд около 90 руб. Отдельный ключ Kie под навесы. Проверить на живом плане, что углы не повторяются на горизонте месяца.