← все проекты

Контент Завод (SaaS)

SaaS генерации контента: видео/карусели/посты, 40+ моделей, автопостинг. Прод 24contentzavod.ru, стейдж test.24contentzavod.ru.

repo: Logonchek/Contetn-fabric-site; local E:/…/Контент завод последняя версияserver: cfru. ПУТИ ПЕРЕПУТАНЫ: /var/www/content-factory = СТЕНД, /var/www/content-factory-prod = ПРОД. Выкладка ТОЛЬКО через /usr/local/bin/cf-deploy.sh — собирает в отдельную папку и подменяет за доли секунды (раньше сборка писала в рабочую папку и роняла сайт на 4 минуты, съедая вебхуки). Скрипт сам проверяет, поднялось ли, и откатывает. БЭКАПЫ базы: /usr/local/bin/cf-backup.sh, каждую ночь 3:15, хранится 14 суточных копий в /opt/backups/content-factory. До 01.08.2026 бэкапов не было вовсе. Очередь: Inngest (облако, ключи в .env), обработчик /api/inngest. Redis у проекта НЕТ.docs: ГЛАВНОЕ: docs/MAP.md — карта проекта, собирается автоматически на каждой выкладке скриптом scripts/build-map.mjs и ПЕРЕСОБИРАЕТСЯ ЦЕЛИКОМ (руками не править, затрётся; убрали что-то из проекта — из карты исчезает само). Внутри: где живут процессы, внешние сервисы, очереди и функции Inngest, свои таблицы-очереди, задачи по расписанию, таблицы базы, 292 маршрута, страницы, имена переменных окружения (значения маскируются). ПРАВИЛО: прежде чем искать «есть ли у нас X» и тем более писать своё — открыть карту. Один раз уже построили свою очередь, не заметив готовый Inngest с четырьмя функциями. Прочие доки: docs/ в корне (ACCEPTANCE, parallel-work и другие).память: content-factory-server-rules, content-factory-ledger-schema, content-factory-models-pricing-project
ревьюS1 · Спринт качества контента9/9

Цель: Голоса-пул, дизайнер+фон, Wan 2.7, Студия native

Голоса-пул 12 + дизайнер + фон
✓ стейдж, ветка test/sprint-3-quality
feature
↑ ИИ-критик ролика на вирусность (Gemini) + UI /studio/virality
Gemini 2.5 Flash через OpenRouter смотрит ролик, пораздельная оценка (хук/видео/озвучка/сабы/текст-хук/понятность/товар). Прайсинг 40р до 30с +1р/с. Ledger тип studio_virality_check.
✓ Стейдж, e2e пройден (скрин). Gated в подписку Студии. Себестоимость ~0.33р/ролик.
feature
↑ Агент текст-хуков + оверлей отдельным слоем + связка в пайплайн
hook-writer (gpt-4o, <=7 слов боль/желание). buildHookOverlayEvent (ASS, верх, дефолт жёлтый КАПС, хук с 00 сек). content_items.text_hook -> прожиг сабов.
✓ Доказано на реальном ролике (фитнес): текст-хук в критике 0->4. Дефолт жёлтый КАПС, overridable.
feature
↑ Фиксы качества: голос (audio-теги/эмоция/пунктуация) + регрессия сабов
generateSpeech срезает [теги] (баг Драматик) + маппинг эмоции в voice_settings. planAudio требует пунктуацию. Фикс self-call сабов мимо глобального NL-прокси (undici Agent).
✓ Стейдж, сэмплы old/new у юзера. Инфра: OpenRouter гео-бан cfru -> ходим через AI_PROXY_URL (NL-прокси) в instrumentation.
fix
Настройка стиля текст-хука в визарде фабрики (hook_*)
Таб Текст-хук на странице редактирования фабрики: вкл/выкл, позиция, шрифт, размер, цвета, капс, пресеты, живое превью. Колонки factories.hook_*. Стиль проходит через пайплайн в прожиг оверлея.
✓ Стейдж, e2e в браузере: таб рендерится, сохранение форма->PATCH->БД подтверждено (hook_color/caps/pos/font/size).
feature
ПРОД ЛЕЖАЛ: не работал вход, упал слой REST у Supabase
✓ Владелец: «у контент завода на проде не работает кнопка войти». Вход был не при чём: страница входа открывалась, пароль проверялся, Яндекс и ВК редиректили. ПРИЧИНА: 24.08 в 02:25 перезапускалась база supabase-db, контейнер supabase-rest (PostgREST) получил SIGTERM, вышел с кодом 255 и больше не поднялся, два часа висел Exited. Весь /rest/v1 отдавал 503. Человек вводил пароль, GoTrue пускал, а кабинет не мог прочитать ни профиль, ни заводы, и выкидывал обратно на форму. Со стороны это выглядит как «кнопка не работает». Тем же объясняются ошибки планировщика «Failed to fetch factories: name resolution failed», которые сыпались всё это время. ПОЧИНЕНО: поднял supabase-rest, он подключился к базе, но снаружи всё ещё шёл 503: kong держал в кэше DNS мёртвый адрес, а контейнер поднялся с новым IP 172.19.0.14. Перезапустил supabase-kong. Сейчас rest 200, auth 200, планировщик без ошибок, /rest/v1 без ключа отвечает 401 как положено.
feature
Прод: поднимается ли REST сам после перезапуска базы
После инцидента 24.08 (rest лежал два часа, никто не заметил) проверить, что при перезапуске базы слой REST встаёт сам. КОМАНДА ПРОВЕРКИ: ssh cfru "docker ps -a --format '{{.Names}}\t{{.Status}}' | grep -E '^supabase-(rest|kong|auth|db)'" Все четыре должны быть Up, ни одного Exited. Затем снаружи: открыть https://24contentzavod.ru/auth/login, войти. Если выкидывает обратно на форму, значит REST снова лежит. ЕСЛИ ПОВТОРИЛОСЬ: docker start supabase-rest, затем docker restart supabase-kong (kong кэширует адрес и после подъёма rest продолжает отдавать 503). Дальше договориться с владельцем про depends_on с healthcheck в compose Supabase и про внешнюю проверку /rest/v1, которая шумит в Телеграм: сейчас падение видно только когда клиент не может войти.
✓ Проверено 02.10 чтением, без перезапусков. docker ps: supabase-auth Up 2 days (healthy), supabase-db Up 2 days (healthy), supabase-kong Up 2 days (healthy), supabase-rest Up 2 days; Exited нет. Все четыре стартовали одновременно 30.09 03:33 UTC (перезапуск всего стека), REST после этого встал сам. Снаружи: GET https://24contentzavod.ru/auth/login = 200; /rest/v1/ через kong с anon-ключом = 200 (без ключа 401, то есть REST отвечает, не 503); /auth/v1/health = 200. Compose /opt/cf-supabase: rest restart unless-stopped, depends_on db condition service_healthy; kong зависит только от studio, своего healthcheck у rest нет. Умышленный перезапуск базы не делал (только чтение), вход учёткой не проверял. Внешней проверки /rest/v1 с шумом в Телеграм по-прежнему нет.
⛔ Сейчас все четыре (rest, kong, auth, db) Up 38 часов, вход на 24contentzavod.ru/auth/login отвечает 200. Сам сценарий «перезапустить базу и посмотреть, встанет ли REST» на проде ночью без твоего «да» не гонял: это прод с клиентами. Нужно твоё «да» на перезапуск базы в тихое окно либо depends_on с healthcheck в compose.
check
Система качества видео (критик, банк хуков, viral_patterns)
✓ стейдж, структуры is_active=false до прода
feature
Выкат спринта качества на прод
ждёт «да» владельца
✓ Весь батч выкачен на прод (мерж test/sprint-3-quality -> fix/impersonate-on-v1.4, чистый; билд+рестарт content-factory-prod). Проверено: /studio/virality=200, /evaluate=401, debug-gen=404, прокси-инструментация активна.
feature
В РАБОТЕS2 · Взрослый редизайн СММ-Центра19/26

Цель: Не MVP. Хаб «Создать контент» (обёртка Студии), компания над фабрикой, честные Расходы/Дашборд/Аналитика по разрезам, Ролс-канвас. Спек: myvisionagency.ru/lab/smm-redesign. Согласовать до кода.

Схема прайса применена
feature
↑ Фаза 0: фундамент данных (леджер модель/секунды/content_item + сбор аналитики по сетям + UTM-счётчик)
Без этого разрезы Расходов/Дашборда/Аналитики нельзя показать честно.
✓ Роллап-леджер закрыт: tenant-метки transactions + триггер (сделано ранее), RPC smm_expense_rollup/smm_expense_items существуют и питают Расходы. Остаток фазы: UTM-счётчик и гранулярный сбор аналитики по сетям (появятся при подключении сбора).
feature
↑ Фаза 1: быстрые баги и тексты (Ролс-обложка+долгая загрузка превью, убрать техтекст и тире, мёртвая кнопка политики, переходы из календаря)
✓ Стейдж, проверено в браузере: (1) Ролс получает постер первого кадра при сборке (extractFirstFrame+upload, best-effort; ffmpeg-путь доказан на реальном mp4 бесплатно), Мои работы показывают видео обложкой-картинкой вместо загрузки mp4; (2) превью без медиа = кнопка Сгенерировать в Публикациях вместо тупика (скрин); (3) техтекст про не трогаем переписан; (4) Политика сетей проверена вживую end-to-end (открытие-тоггл-сохранение-БД network_policy записан) + ошибки сохранения теперь показываются; (5) вычищены длинные тире в ~35 видимых местах СММ-раздела. Существующих Ролсов без обложки в БД нет, бэкфилл не нужен.
bug
↑ Фаза 2: Создать контент — пост и карусель (единый конструктор, обёртка Студии, канвас каруселей+пресеты)
✓ Хаб /smm/create + студия поста + Konva-канвас карусели + ИИ-копирайт слайдов + полная ИИ-отрисовка Nano c i2i (e2e 2026-07-27, 2/2 слайда, леджер и кошелёк клиента ок). Осталось: пресеты канваса.
feature
Фаза 3: видео, ИИ-аватар, Ролс-канвас (режиссёрский, склейка, свои голос/музыка); Ролс переезжает в хаб
✓ Сделано: полноэкранные студии Видео и ИИ-аватар (company-таргет), Ролс-канвас React Flow (сцены), Ролс в хабе. Осталось: модельная система видео per-item (Wan/Kling/Seedance/Veo), склейка-таймлайн, свои голос/музыка.
feature
Фаза 4: Расходы и Дашборд — честные разрезы (даты, по моделям с кол-вом/секундами, drill-down, виджеты)
✓ Расходы с честными разрезами СДЕЛАНЫ (обнаружены готовыми при ревизии): даты-пресеты+кастом период, разрез по продуктам/моделям с кол-вом и секундами, по клиентам, история с drill-down к контенту (RPC smm_expense_rollup/items). Остаток: дашборд-виджеты добавляемые/убираемые с drill-down (отдельный кусок).
feature
Фаза 5: Аналитика-конструктор (метрики/разрезы/сравнение/экспорт) + Тренды по нише фабрики
✓ Конструктор аналитики добит: метрика х разрез х даты + СРАВНЕНИЕ С ПРОШЛЫМ ПЕРИОДОМ (дельты по строкам и итогу) + экспорт CSV. Тренды по нише из брифа сделаны ранее. Проверено в браузере.
feature
Фаза 6: Компания над фабрикой (бриф/бренд/настройки на уровень компании, работа вне фабрики) — крупный сдвиг, отдельная миграция
✓ Сделано: контент без завода на company (пост/карусель/видео/аватар), экран настроек компании (бриф+целевые сети), кошелёк клиента полный цикл. Осталось: Ролс на company, company-OAuth соцсетей + резолв публикации.
feature
↑ Видео-Kie: модельная система per-item (Wan 2.7/Kling/Seedance/Veo, первый/последний кадр, аудио, вариация)
Протащить выбор модели per-item через generate-пайплайн (сейчас модель на уровне фабрики, завязана на 10+ мест: Inngest-воркеры + расчёт цены). Крупный кусок, отдельная сессия.
✓ МОДЕЛЬНАЯ СИСТЕМА ГОТОВА ЦЕЛИКОМ (стейдж, проверено в браузере+БД, 6 коммитов): per-item модель/длительность/разрешение/кадры/референсы/звук. 4 модели: Veo 3.1 Lite (8/15/30с), Wan 2.7 (ползунок 3-30с, 720p 12р/с / 1080p 16р/с, r2v-референсы фото+видео до 5 + голос 1-10с, первый кадр совместим с рефами, видео-едит 12р/с до 10с), Seedance 2 (4-30с, 27/67/136 р/с по разрешению, референсы фото9/видео3/аудио3, ИИ-звук) и Seedance 2 Fast (22р/с). Свой звук = наша озвучка/сабы скипаются. >15с = 2 клипа со склейкой. Вариация + видео-едит в Моих работах. UI-иерархия по фидбэку владельца: модель компактным списком, возможности крупными дропзонами с превью. Цены = себестоимость Kie (фактчек по каталогу) + наценка. Осталось: Kling (по инфо владельца), платные тесты генераций перед продом.
feature
↑ Company-OAuth: подключение соцсетей на аккаунт компании + резолв публикации
Без токенов аккаунтов компании публикация company-контента невозможна. Отдельная крупная фича.
✓ Стейдж, проверено в браузере+БД: у companies сетевые поля симметрично фабрикам, publish резолвит company-подключения (can_publish_company), connect Upload-Post в режиме companyId, блок Подключение аккаунтов в настройках компании (Upload-Post + прямые TG/VK, сохранение проверено e2e в БД). Ролс принимает companyId с кошельком клиента и своими фото. Живая публикация company-поста в сеть = по outbound-гейту.
feature
Ролс на company + company-биллинг
chargeForCompany/refundForCompany уже в billing.ts (сделаны 2026-07-27). Осталось перевести Ролс-роуты на company-таргет.
✓ Стейдж, проверено в браузере+БД: у companies сетевые поля симметрично фабрикам, publish резолвит company-подключения (can_publish_company), connect Upload-Post в режиме companyId, блок Подключение аккаунтов в настройках компании (Upload-Post + прямые TG/VK, сохранение проверено e2e в БД). Ролс принимает companyId с кошельком клиента и своими фото. Живая публикация company-поста в сеть = по outbound-гейту.
feature
Ассеты компании: аватар + голос ElevenLabs + локация
Настройки ассетов на уровне компании для студий (аватар/голос/локация съёмки).
✓ Стейдж, проверено в браузере: блок Ассеты для контента в настройках компании (лицо аватара, голос из пула ElevenLabs с прослушиванием превью, фото товара/локаций до 8 в companies.product_images). Их читают студии аватара/видео и Ролс (авто-Ролс на company заработал через product_images).
feature
↓ Пресеты канвас-каруселей
Готовые раскладки слайдов на Konva-канвасе.
✓ Пресеты раскладки слайда в студии карусели: сверху/по центру/снизу с подстрокой/цитата. Проверено в браузере.
feature
↑ Юзкейс: чип Компания (без завода) в хабе и студиях при наличии фабрик
Сейчас company-режим включается только когда фабрик нет. Нужен явный выбор компании как цели наравне с фабриками.
✓ Стейдж, проверено в браузере: опция компании в селекторе цели всех студий (пост/карусель/видео/аватар/Ролс) даже при наличии фабрик; хаб показывает форматы company-only юзерам.
bug
↑ Юзкейс: выбор движка полной отрисовки карусели (Nano 10р / GPT Image 2 15р за слайд)
✓ Стейдж, проверено в браузере: переключатель движка в отрисовке карусели - Nano 10р/слайд или GPT Image 2 15р/слайд (3:4, i2i-чейнинг, леджер пишет модель), цена на кнопке пересчитывается.
feature
↑ Юзкейс: свои референсы карусели (2-3 примера) + режим в-этом-стиле / точный-повтор-про-меня
✓ Стейдж: блок Референсы стиля в студии (до 3 своих примеров, идут style-ref в обложку вместо системной базы). Режим точный-повтор-про-меня пока не отдельный: точность достигается своим промтом слайда + референсом.
feature
Юзкейс: перерисовать ОДИН слайд карусели с правкой текста/оффера (10-15р)
✓ Стейдж: кнопка Отрисовать/Перерисовать у каждого слайда (10/15р за один), чейнинг от отрисованной обложки, возврат при сбое.
feature
Юзкейс: режиссёрский шаг - показать/править промт сцены каждого слайда перед отрисовкой
✓ Стейдж: ИИ предложит визуал (designOnly, бесплатно) кладёт сцены дизайнера в редактируемые поля каждого слайда; свой промт уходит в модель как есть без переписывания агентами (directPrompt: сцена + точный кириллический заголовок + контраст + 4:5).
feature
Юзкейс: фото только на обложке карусели (тумблер, не на все слайды)
✓ Стейдж: тумблер фото только на обложке - референс уходит только на обложку, остальные слайды рисуются без него.
feature
↑ Креатив-канва студий (карусель, пост): композер задачи, агенты, референсы, пресеты
Новый UX по референсу Mage: ячейки по центру, композер снизу, агент-режиссёр+креативный директор, примеры из базы под формат, пресеты, публикация модалкой, переключалка форматов с сохранением черновика.
feature
↑ РЕСЁРЧ: банк шаблонов постов и каруселей (чистая курация)
Собрать больше примеров и РАЗДЕЛИТЬ: в постах только одиночные посты-картинки с читаемым текстом (рус/англ), в каруселях только настоящие карусели. Выкинуть лендинги, баннеры, мокапы, инфографику маркетплейсов, мудборды. Разметить niche/type/style, залить в carousel_reference_templates с kind.
✓ Собран инструмент вместо ручной курации: сбор примеров из Telegram (t.me/s, альбом = карусель) и VK (newsfeed.search в окне 14-90 дней), пороги по просмотрам и вовлечению, отсев рекламы, дедуп. На стейдже 564 кандидата (195 каруселей, 331 пост). Страница /admin/references для проверки глазами + ИИ-критик на vision, отделяющий живой пост от лендинга и баннера (платный, по кнопке). Осталось: пройти глазами и одобрить, потом прогнать критика.
feature
↑ Видео-канва: клипы-ячейки, агенты раскадровки, кадры/аудио через композер
Стиль как у карусели/поста. Модель+длительность -> N ячеек-клипов (16с Veo = 2 куска, объединим при публикации), правка каждого куска отдельно, первый/последний кадр, аудио-дорожка, референсы, персонажи. Пайплайн: режиссёр раскадровки + арт-директор.
✓ Стейдж, проверено: ячейки-куски по лимиту модели (Veo 8с -> 16с=2 части, Wan/Seedance 15с), пояснение про склейку, все 4 модели в селекторе, агент-режиссёр раскадровки, первый/последний кадр и аудио через плюсик, звук модели для Seedance, сцены сохраняются в video_scenes и используются генерацией. Осталось: платный тест сборки.
feature
↑ Аватар-канва: персонажи (загрузить, сохранить, выбирать пресетом)
Канва как у поста + библиотека персонажей: загрузка лица, сохранение персонажа для будущих роликов, выбор внизу композера как пресет.
✓ Канва /smm/create/avatar-canvas в стиле карусели и видео: ячейка речи, композер снизу, ползунок длины, 22 руб/сек. Персонажа можно загрузить через плюсик, сохранить в библиотеку (таблица smm_characters с RLS по владельцу) и выбирать пресетом внизу. Лицо, голос и длина из идеи перебивают настройки завода, раскадровка канвы уходит режиссёру аватара. Проверено на стейдже: загрузка лица, сохранение, выбор после перезагрузки, восстановление черновика.
feature
Пост: выбор формата картинки (1:1, 4:5, 9:16, 16:9)
✓ Стейдж, проверено: 4:5/1:1/9:16/16:9, ячейка и промт подстраиваются, GPT Image получает корректный аспект.
feature
Контент без завода: скрытый рабочий завод компании
Раньше контент компании создавался с factory_id=null и сборка его не находила (inner join по заводу) - кейс был мёртвый. Теперь у компании есть один скрытый завод (is_company_default), поля тянутся из компании при каждом создании; кошелёк резолвится по company_id, скрытый завод не показывается там, где выбирают цель; собрать контент компании может любой с правом её редактировать.
feature
Слить 8 семейств + залить 203 варианта + 43 новых
feature
В РАБОТЕS3 · Леджер и платежи1/2

Цель: Единая таблица transactions, симметрия списаний

Инцидент ЮKassa (тестовый магазин) закрыт
✓ боевой 1239397 + защита от повтора
feature
Леджер-починка: выкат на прод
стейдж a50546c готов
feature
планS4 · Качество видео — докрутка0/5

Цель: Динамика и подача роликов: промты, хук↔озвучка, мягкий бренд, банк структур

↑ Динамика видео: докрутить промты (Veo/Kling), не модель
Ролики статичные — дело в промтах/подаче, а не в модели (подтвердить: прогнать 1 промт через 3-5 моделей и сравнить). Докрутить prompt-director: движение в кадре, смены планов, вау-моменты.
feature
Хук и озвучка — комплементарно (не разъединять)
avoidText сделал текст-хук и озвучку РАЗНЫМИ — критик ловит рассинхрон (текст на экране ≠ озвучка). Связать: хук цепляет, озвучка продолжает ту же мысль.
improvement
Смягчить вставку бренда (не в лоб)
Критик ставит товар 2/10: логотип+слоган сразу выдают рекламу и режут вирусность. Бренд вплетать вторым слоем, задача №1 — вирусность.
improvement
Банк вирусных структур: пачки до ~100 + активация is_active
Догенерить вирусные структуры пачками 2-5 до ~100, проверить, активировать is_active на проде (сейчас часть выключена).
feature
↓ Пунктуация/паузы озвучки — добить если слабо
Промт planAudio теперь требует пунктуацию, но ИИ ставит её не всегда. Если на роликах паузы слабые — усилить правило/пост-обработку текста перед TTS.
improvement
ревьюS5 · СММ-Центр: Каркас + Дашборд + Бриф6/6

Цель: Отдельный раздел со своим layout, дашборд-домашняя с ИИ-рекомендациями, единый бриф компании

↑ Каркас раздела СММ-Центр
Блок на главной + пункт в левом меню → отдельный layout: та же шапка + кнопка «назад», СВОЙ боковой сайдбар, свои блоки справа. Роутинг/навигация раздела.
✓ Каркас /smm: своя шапка+сайдбар (9 разделов), на staging
feature
↑ Дашборд-домашняя раздела
Общие метрики: подключено N сетей, суммарный охват/подписчики + дельты роста ↑↓, топ-посты, вовлечение, входящие без ответа. Health-score по сети/компании. Алерты (фейл публикации, негатив, отписки, токен истекает). Свитчер компаний (агентство).
✓ Дашборд: реальные метрики (подключённые сети+видео из завода), company switcher
feature
ИИ-рекомендации на дашборде
«Мало рилсов — сделай N», «лучшее время постить», «VK проседает», «3 коммента ждут ответа», «подключи ещё сети». Реюз аналитики + factory_soul.
✓ Контекстные ИИ-рекомендации на дашборде (нет сетей/мало видео/бриф/тайминг)
feature
↑ Единый Бриф компании
Консолидировать разрозненные поля завода + factory_soul/insights в одну сущность: айдентика (лого/цвета/шрифт), tone of voice, можно/нельзя, ниша/рубрика, ЦА, ссылки. Кормит ИИ (тексты) и тренды (ниша).
✓ Бриф: консолидация полей завода+soul, индикатор заполненности, подсветка пустых→ссылка правки
feature
🔴 Мультитенант: организация/компания + участники + роли (foundation прав)
Сейчас всё владеется user_id, команд/оргов НЕТ (только is_admin + manager_access_tokens для нашей поддержки). Ввести сущность организация/компания + membership (участники) + роли. Переключить владение (заводы/контент/подключения) на организацию. Архитектурная развилка — согласовать подход до кода.
✓ Аддитивный слой: таблицы organizations/org_members + RLS (owner_user_id). Не трогает существующее user_id-владение
feature
↑ Светлая/тёмная тема (механика) + миграция приложения
Люди, кому тяжело на тёмном → переключатель light/dark. Приложение сейчас тёмное намертво (фикс dark-* + общий тёмный Header). Механика заложена в СММ-Центре через CSS-переменные scoped (.smm-root+data-theme, localStorage-переключатель). Отдельно: миграция всего приложения на тему + тема общего Header.
✓ Light/dark через CSS-переменные .smm-root, переключатель, localStorage; проверено обе темы
feature
ревьюS6 · СММ-Центр: Календарь + Публикации + Загрузка-как-есть7/7

Цель: Пульт: редакционный календарь, согласование, загрузка своего медиа, per-network времена/превью

↑ Страница-Календарь (неделя/месяц) + drag-перенос
Поднять контент-план+планировщик из модалки в полноценную редакционную страницу-календарь. Кросс-компания.
✓ Календарь: месячная сетка из content_items.scheduled_date, фильтр компаний, детали дня
feature
Рубрикатор
Постоянные рубрики-столпы («Кейс-понедельник» и т.п.), ИИ наполняет по расписанию.
✓ Стейдж: smm_rubrics (6 системных + свои, RLS) + content_items.rubric_id + RPC smm_set_item_rubric. Селектор рубрики у поста + фильтр по рубрике + менеджер (создать/удалить свою). Проверено e2e скриншотом (назначил Аналитику, цвет применился) + БД (RPC/RLS).
feature
↑ Согласование draft→review→approved + клиентский доступ
Флоу апрува: черновик → на проверку → одобрено → в план. Клиент (компания) заходит и апрувит ДО публикации — критично для агентств.
✓ Стейдж: Согласовать/Вернуть/Опубликовать по правам (canApprove/canPublish) + RPC smm_set_item_status/can_approve_factory/can_publish_factory (SECURITY DEFINER). Клиентский доступ = 4 уровня (view/approve/edit/publish). Проверено на БД.
feature
↑ Загрузка своего медиа → опубликовать как есть
Залил готовый пост/видео → опубликовать как есть по расписанию или быстро обработать, без обязательной ИИ-генерации. Медиатека (DAM) переиспользуемых ассетов.
✓ Стейдж: кнопка «Загрузить своё» → /api/smm/upload-media (can_edit_factory) → готовый content_item (status=ready, media_url). Проверено e2e скриншотом (загрузил PNG → пост в очереди), почищено.
feature
Per-network: отдельные времена + превью + варианты текста
Своё время публикации под каждую сеть, превью «как выглядит» под сеть, варианты текста под сеть (VK длиннее, IG короче).
✓ Стейдж, e2e проверено скриншотами+БД+шедулером: smm_network_posts (RLS can_edit_factory), редактор Расписание-по-сетям (время+текст+превью как в сети, матрица тип↔сеть), /api/smm/publish-network (одна сеть своим текстом, reuse postToSMM), шаг шедулера processDueNetworkPosts (публикует due каждый тик). Живой пост в сеть — по outbound-гейту.
feature
↑ Поэлементный таргетинг сетей (Фазы 1/2a/2b)
Чипы сетей у каждого поста (очередь+календарь). Матрица тип<->сеть many-to-many (карусель=VK/TG/IG, клип=+YouTube/RuTube). Пресеты: 4 системных + свои + скрыть наш в своей учётке (smm_network_presets/smm_preset_dismissals, RLS). Bulk-применение к выделенным. Авто-политика по типу (factories.network_policy + BEFORE INSERT триггер, ловит Лию/планы/ручное). RPC smm_set_item_networks/smm_set_factory_policy (can_edit_factory). Колонка content_items.target_networks.
✓ Стейдж test/sprint-3-quality. Проверено скриншотами (вошёл тест-юзером viral.critic.test) + БД (RPC/триггер/RLS). Модалки через портал в .smm-root.
feature
↑ Реальная публикация: «Опубликовать» -> сеть + агентская авторизация
Кнопка публикует через существующий /api/content-item/[id]/publish. Авторизация can_publish_factory (владелец ИЛИ агентство с правом), атрибуция публикации владельцу фабрики (как планировщик), admin-клиент после явной проверки. Уважает per-item target_networks.
✓ ДОКАЗАНО вживую 2026-07-20: реальный пост в Telegram-канал завода «Контент» (message 620, publication_logs success), ТОЛЬКО telegram — поэлементный таргетинг отфильтровал VK/IG/YT. Попутно 2 фикса прода: лимит подписи Telegram под медиа 1024 (было 4096), фолбэк sendPhoto скачать-и-загрузить-файлом при любой ошибке URL (RU-сторедж Telegram не достаёт).
feature
планS7 · СММ-Центр: Российский слой публикации0/4

Цель: Заменить/дополнить Upload-Post российским API: Rutube, VK органика рилсов, OK, Дзен

↑ Ресёрч + выбор российского сервиса публикации с API
Upload-Post плохо под РФ. Найти тот сервис что находили ранее (адекватная цена): Rutube, нормальный VK (рилсы в органику), OK. Сравнить, выбрать.
feature
↑ Интеграция российского сервиса публикации
Подключить как основной/доп канал рядом с Upload-Post/прямыми VK/TG. Кросс-пост через него.
feature
↑ Фикс VK: рилсы в органику
Сейчас через прямой VK API рилсы НЕ идут в органику (минус охватов). Решить через новый сервис или иначе.
feature
Дзен: интеграция публикации
Придумать и сделать публикацию в Дзен.
feature
ревьюS8 · СММ-Центр: Входящие + автоответы6/6

Цель: Единый инбокс комменты+директ; 2 тира автоответов (канные дёшево / ИИ платно) + база знаний

↑ Единый инбокс
Комменты + директ по сетям (VK/TG/IG/…) в одном окне, статусы (без ответа/отвечено/эскалация), фильтры.
✓ Страница Входящих: настройки автоответов + канные + база знаний + фид (пустой до подключения площадок)
feature
↑ Тир 1 — готовые/канные автоответы (дёшево)
Автоответ по ключевым словам/правилам, без ИИ. Дешёвая альтернатива.
✓ Тир 1 канные ответы: CRUD (название/ключевые слова/текст/вкл-выкл), проверено end-to-end
feature
↑ Тир 2 — ИИ-автоответы (платно отдельно)
ИИ читает контекст диалога и отвечает. Списание отдельно, дороже.
✓ Тир 2 ИИ-ответы: тумблер + тон; генерация ответа подключится после API площадок
feature
↑ Настройка ИИ-автоответов + база знаний
Загрузка базы знаний: прайс/сколько что стоит, о компании, как отвечать, что НЕЛЬЗЯ говорить, куда вести (ссылка) + примеры бесед (few-shot). Тон из брифа.
✓ Настройки автоответов (тон/задержка 15м/подтверждение) + база знаний CRUD (прайс/о компании/правила/FAQ/примеры)
feature
Модерация/эскалация/лиды
Негатив → человеку; спам → скрыть; preview перед отправкой, задержка; мониторинг упоминаний бренда; захват лидов из директа → в продажи.
✓ Стейдж, e2e скрин: лента→очередь модерации (вкладки Новые/Лиды/На-человеке/Все со счётчиками), у сообщения предложенный ответ (suggest-reply), пометить отвеченным, тумблер Лид, Человеку, Закрыть. Колонки is_lead/handled_at, правки через RLS can_edit_factory.
feature
↑ Инбокс-ingestion VK/TG (прямые API)
Подтянуть комменты (VK wall.getComments) + директ (VK messages / Telegram Bot API) в smm_inbox_messages + отправка ответа обратно. Токены VK/TG уже есть. Движок автоответов готов (/api/smm/inbox/suggest-reply, DeepSeek). Upload-Post комменты/директ = в осн. Instagram (в РФ заблок) -> для RU только прямые API.
✓ Стейдж, e2e на РЕАЛЬНЫХ данных (профиль MyVIsion): 108 Instagram-директ + комменты по всем постам из history (IG+YouTube), лид-детект (8 из 108). Гибрид: Upload-Post даёт директ (только IG) + комменты (IG/FB/YT/LinkedIn) — проверено по всем 8 площадкам. VK/TG прямыми API — след.шаг. Кнопка Синхронизировать.
feature
ревьюS9 · СММ-Центр: Аналитика + Тренды + Расходы4/4

Цель: Кросс-сетевая аналитика всех типов, white-label отчёты, тренды по нише, журнал расходов

↑ Кросс-сетевая аналитика по всем типам
Не только рилсы: посты/сторис/входящие. По компании/сети/рубрике, рост/вовлечение/лучшее. Реюз analytics.
✓ Аналитика: content_performance — просмотры/вовлечённость/топ/по площадкам, честный пустой стейт
feature
White-label PDF-отчёты клиенту
Для агентства — отчёт клиенту с брендингом. Экспорт, KPI-цели.
✓ Стейдж, e2e скрин: кнопка Скачать отчёт на аналитике → брендированный отчёт (лого/имя/акцент агентства из org_branding, не Контент Завод) → печать браузером в PDF. SmmReport портал .smm-print-root, KPI+площадки+топ-посты+период. Печатные стили в globals.css.
feature
Тренды по нише из брифа + кросс-сетевые конкуренты
Привязать нишу брифа к трендам (сейчас статичный дропдаун); конкуренты расширить с YouTube на все сети.
✓ Стейдж, e2e скрин: /smm/trends на официальном YouTube Data API (бесплатно, без Apify). Ниша из брифа компании (дефолт product_name) + поиск, топ коротких видео за 30 дней по просмотрам, превью/канал/лайки/комменты/ссылка. Реальные данные (нейросети для бизнеса → 9325 просмотров топ). Apify (TikTok/IG) — опция на будущее.
feature
Журнал расходов по компаниям/действиям
Реюз transactions/recordSpend: раскидать расходы по клиентам (для агентства).
✓ Расходы: transactions — баланс/за месяц/всего/пополнено, по категориям, история
feature
ревьюS10 · СММ-Центр: ИИ-копайлот + Команда4/4

Цель: Лия-для-СММ, роли/команда, мульти-компания, авто-правила

Лия-для-СММ
Чат: собери план под сеть, напиши посты по брифу, драфт ответов на входящие, дай инсайты. Реюз Лии+tools.
✓ Стейдж, e2e скрин: плавающий ИИ-помощник на всех страницах СММ-Центра. Дала реальный контент-план по запросу, с контекстом из брифа компании (продукт Тестовый товар). Дешёвая модель deepseek-chat-v3 через OpenRouter (как автоответы), контекст=бриф, история диалога, быстрые подсказки. Портал в .smm-root.
feature
Роли/команда + мульти-компания
Роли (сммщик/клиент-апрувер/админ), свитчер 10 компаний, права.
✓ Роли/команда: организация (компания/агентство), владелец=суперадмин, приглашение email+роль, смена/удаление, проверено
feature
↓ Авто-правила
Коммент содержит X → ответ Y/эскалация; авто-наполнение рубрик; авто-реюз топ-постов.
✓ Стейдж, e2e (БД+скрин): секция Автоматизация в инбоксе — авто-сбор входящих (шаг шедулера processAutoInboxSync, троттл 30мин; проверено: 0→109 сообщений авто) + авто-пометка лидов (sync уважает флаг). Флаги на smm_autoreply_config.
feature
↑ Раздача прав и настройки (RBAC-раздел)
Раздел управления доступом. Суперадмин = первый зарегавшийся (или назначенный) настраивает. Роли: суперадмин, СММщик, руководитель маркетинга, директор по маркетингу, отдел продаж, клиент-viewer/approver. Сценарии: агентство (1 СММщик, 10 клиентов) даёт доступ/показывает клиенту; клиент со своей командой (разные права). Приглашения, роли на организацию/компанию.
✓ RBAC-раздел Права и настройки: команда + матрица ролей/доступов (владелец/директор/руководитель/СММ/продажи)
feature
ревьюS11 · СММ-Центр: Бренд-ассеты и шаблоны3/3

Цель: Шаблоны постов (reference-driven) + интро/аутро видео (bumpers)

Шаблоны постов (reference-driven, GPT Image)
Клиент грузит примеры своих постов (аналитика/новости). При создании выбирает шаблон + данные -> ИИ делает похожий пост, меняя текст/цифры (2 режима: только текст / элементы+текст). Движок reference-driven уже есть (gpt-image-2 image-to-image, LeadForge creative-engine / КЗ карусель). Кнопка «создать шаблон через GPT Image (Kie)» -> сохранить/переделать. Хранить: таблица шаблонов (per factory/org + системные, как пресеты). 15р/генерация = money-гейт (списание с баланса клиента через ledger).
✓ Банк шаблонов (загрузка своих + галерея, RLS per-user) + генерация gpt-image-2: t2i «Сгенерировать шаблон» (проверено, рус.текст читается, ~2.85 руб/1K) + i2i «применить к посту» (эндпоинт + кнопка в Создать). Осталось: биллинг списания.
feature
Интро/аутро видео (bumpers, FFmpeg)
Клиент грузит начало (лого) и конец (лого+подписаться) = бренд-ассеты завода (intro_url/outro_url). Флаги use_intro/use_outro у видео-элемента. При рендере FFmpeg: нормализовать res/fps/codec у intro+main+outro -> concat.
✓ Стейдж: бренд-ассеты завода intro_url/outro_url (менеджер Заставки, загрузка /api/smm/bumpers), флаги use_intro/use_outro у видео (тумблеры в очереди, RPC smm_set_item_bumpers проверен owner/stranger), при публикации видео FFmpeg-склейка intro+main+outro (reuse concatenateVideos, кэш bumped_media_url). Полный рендер-тест — по outbound-гейту с реальными заставками.
feature
Биллинг генерации картинок (списание баланса)
gpt-image-2 тратит наши деньги Kie (1K~2.85/2K~4.75/4K~7.6 руб), но не списывает с баланса клиента. Обязательно закрыть до выката шаблонов на прод: списание + запись в леджер transactions.
✓ Списание с баланса за gpt-image-2 (deductBalance→генерация→refund при сбое), i2i-картинку поста платит владелец агентства (resolveBillingUser). Проверено вживую: −15₽, запись в леджер. Цена 1K=15/2K=25/4K=40 руб, показана на кнопках.
feature
ревьюS12 · Обучение, онбординг и связь с клиентом26/30

Цель: Инструкции со скриншотами по СММ-Центру, Заводу и Студии; онбординг первого входа; регистрация с почтой и телефоном, письма и второй канал связи

Инструкции со скриншотами: СММ-Центр
Как создать карусель, пост, видео, аватар; как опубликовать и запланировать; где история и скачивание. Скриншоты снимаются браузером автоматически, нужные места подсвечиваются. Без внутренней кухни: ни агентов, ни моделей, ни промптов.
✓ 13 гайдов с экранами: шесть форматов (карусель, пост, видео, ИИ-аватар, Ролс, публикации) и семь разделов Центра (дашборд с календарём, тренды, входящие, аналитика, бриф, настройки компании, расходы и права). Переключение вкладками, липкая строка сверху, клик по экрану открывает крупно, блок частых вопросов. Подсветка целится в поле по содержимому, а не в первый список подряд.
feature
Инструкции со скриншотами: Контент Завод
Экраны кабинета уже сняты (public/docs/factory). Осталось написать шаги: создать завод, бриф, соцсети, расписание, расходы.
✓ Раздел /docs/factory: два руководства (первый завод, как работает дальше), 4 экрана с подсветкой, частые вопросы. Старое текстовое полотно /docs заменено хабом на три инструкции.
feature
Инструкции со скриншотами: Студия
Экран Студии снят (public/docs/studio). Осталось написать шаги: разовая картинка и ролик, выбор модели и качества, цены.
✓ Раздел /docs/studio: обзор, картинка, видео, библиотека — 4 экрана, вкладки, частые вопросы.
feature
Онбординг СММ-Центра
Первый вход: короткий тур, подсказка что делать первым, пустой кабинет ведёт за руку. Свои ветки для владельца агентства, сотрудника и клиента.
✓ Четыре экрана знакомства при первом заходе (отметка в профиле, не в браузере) + чеклист первых шагов, который сам отмечается по факту: бриф, соцсеть, первый контент, публикация. Повторный показ — ссылкой «Как здесь всё устроено».
feature
Регистрация: почта и телефон с подтверждением
Брать два контакта, подтверждать почту письмом, валидировать телефон.
✓ Телефон обязателен, нормализуется к +7XXXXXXXXXX, долетает в профиль через триггер. Кривой номер отсекается на форме. Подтверждение почты остаётся за GoTrue — включится вместе с боевым SMTP.
feature
Письма: приветствие, подтверждение, сброс пароля
Шаблоны и отправка, проверка доставляемости.
✓ Почта поднята на Timeweb без сторонних сервисов: smtp.timeweb.ru:465, ящик no-reply@24contentzavod.ru. SMTP прописан и в приложении (наши письма), и в Supabase Auth (системные). Тестовое письмо доставлено, сброс пароля отработал без ошибок SMTP. SPF и DKIM у домена уже были. Осталось по решению заказчика включить подтверждение почты (ENABLE_EMAIL_AUTOCONFIRM=false).
feature
Второй канал связи: Telegram-бот или MAX
Сейчас с клиентом можно связаться только почтой, и это дыра. Привязка аккаунта к боту, уведомления и обратная связь.
✓ Сделано в обе стороны и в обоих мессенджерах. Телеграм: вебхук отвечает за 50-120 мс вместо секунд (держали соединение — Телеграм не дожидался и слал повторы, отсюда была задержка). Ответ реплаем не работал вообще: ветку искали поиском по образцу прямо по uuid, база такое не выполняет — завели короткий код отдельным полем. Служебный чат больше не заводит переписку сам с собой. MAX: подписки на события не было вообще, подписали, приём вопросов проверен боевым запросом. Раздел «Поддержка» в админке: вся переписка целиком, ответ доходит и до тех, кто писал из чата на сайте.
feature
Счета по безналу: уведомления и раздел в админке
Оплата счёта проходила молча: деньги ушли, тариф включился, а человек об этом не узнавал ниоткуда — и мы тоже.
✓ Письмо клиенту на выставление (со сроками: банк переводит не мгновенно) и на зачисление, обоим событиям — строчка нам в Телеграм. Раздел «Счета» в админке: кто запросил, плательщик с ИНН, за что, оплачен или ждёт, PDF. Счёт, висящий пятый день, подсвечивается.
feature
Публикация в MAX через бота
MAX как площадка публикации наравне с ВК и Телеграмом.
✓ MAX не принимает картинку ссылкой — три шага: адрес загрузки, файл, сообщение с ключом. Формат сверен живым запросом к их API. Видео обрабатывается не мгновенно, отправку повторяем. Галочка в целях, поле канала в настройках компании, публикация из всех четырёх мест. ВЖИВУЮ НЕ ПРОВЕРЕНО: у бота пока нет ни одного канала.
feature
Картинки не пропадают при перезапуске сервера
Отрисовка идёт обычным запросом: браузер ждёт, сервер рисует. Перезапуск сервера (обновление) убивал запрос, а картинка у Kie дорисовывалась — деньги списаны, забрать некому. Так потерялись три оплаченных слайда. Для прода это значило: ночное обновление рушит работу любого клиента.
✓ Номер задачи записываем сразу, до ожидания (таблица image_jobs). Фоновая задача раз в 2 минуты добирает повисшее в наше хранилище, канвас показывает плашку «нашлись картинки» и ставит их по номеру слайда или совпадению текста. Не влезло — заводим новую ячейку, оплаченное не выбрасываем. Три потерянных слайда достал вручную и вернул в очередь. Работает и при закрытой вкладке.
bug
Приложенный референс: правка картинки вместо рисования с нуля
На просьбу «замени на этом плакате надпись» рисовался новый плакат: любая приложенная картинка считалась образцом стиля, и модели прямо говорилось «повтори настроение, но НЕ копируй сюжет».
✓ Роль приложенной картинки определяется по формулировке задачи: править её / это товар / это настроение. Однозначные слова («вместо», «замени», «убери») решают без ИИ, спорное разбирает Gemini, при сбое откат к прежнему поведению. ВЖИВУЮ НЕ ПРОВЕРЕНО (нужен платный прогон ~15 руб).
bug
Карусель: слайд знает концепцию всей серии
Обложка «6 новостей про ИИ» выдумала шесть заголовков вместо настоящих: каждый слайд рисовался в одиночку и видел только свой текст.
✓ Каждому слайду передаётся список заголовков всей серии по порядку с прямым запретом сочинять свои; обложке отдельно — брать формулировки дословно. ВЖИВУЮ НЕ ПРОВЕРЕНО.
bug
Несколько черновиков в одном холсте
Холст помнит один черновик на тип контента: начал новый пост — предыдущий затёрся. Чтобы вести три поста одновременно, нужны вкладки или список черновиков. Вариант на памяти браузера — день работы, но черновики не переедут на другой компьютер. Вариант с таблицей и синхронизацией — два-три дня. Решили делать позже, после выкатки. Док: docs/parallel-work.md
feature
↓ Несколько вариантов картинки по одной задаче
Одна задача — несколько попыток, чтобы выбрать лучшую. Не путать с параллельными задачами: там разные задачи, тут одна и несколько картинок. Выбор количества рядом с ценой, цена умножается и видна до запуска; варианты полоской под картинкой, переключаются кликом. Удобство, а не поломка — после выкатки. Док: docs/parallel-work.md
feature
Очередь отрисовки: работа не рвётся при уходе со страницы
Браузер сам перебирал слайды: ушёл на другую страницу — остаток серии не запускался, оплаченные результаты оставались ничьими. Для агентства это ежедневная потеря контента.
✓ Задача ставится в очередь, доводит её сервер. Логику отрисовки не дублировали — работник зовёт тот же роут изнутри. Один упавший слайд не хоронит серию. Перезапуск сервера подбирается раз в 5 минут, уже нарисованное не оплачивается повторно. Панель «В работе» видна с любой страницы СММ-Центра.
bug
Списание не проходило через очередь
Деньги списывались клиентом с правами сессии, а у работника очереди сессии нет — база блокировала операцию. Человек видел «не удалось списать баланс» и не мог сделать ничего.
✓ Списание, возврат и запись расхода переведены на тот же клиент, что и леджер. ВЖИВУЮ НЕ ПРОВЕРЕНО — нужен платный прогон ~17 руб.
bug
Публикация врала про успех в Инстаграм
Ответ Upload-Post разбирался только по коду HTTP: пришло 200 — успех всем площадкам. На деле у каждой свой итог внутри ответа. Карусель ушла в Телеграм, в Инстаграм не ушла, в журнале обе помечены успехом, у Инстаграма стоял идентификатор телеграмного поста. Хуже ошибки: человек уверен, что пост вышел, и не проверяет.
✓ Опубликованной считается только подтверждённая площадка. Про остальные пишем, что не вышло и почему. Подхватываем настоящие ссылки на посты — раньше терялись.
bug
Цены: слайд карусели 7 руб, пост 10 руб
Карусель и пост стоили одинаково, потому что их рисует один код. Это разные покупки: карусель берут пачкой, пост поштучно.
✓ Цена зависит от вида контента, канвас говорит его прямо (по числу картинок судить нельзя — карусель бывает из одного слайда). Одна таблица lib/billing/image-prices.ts: и списание, и подписи в интерфейсе. 2K/4K/Nano пересчитаны в тех же пропорциях, себестоимость Kie 2.85/4.75/7.6 — запас сохранён.
feature
Рабочее окно просмотра готовой работы
Одна колонка: картинка, лента миниатюр, текст, площадки — всё прокручивалось вместе, тёмный слайд сливался с тёмным фоном, листать было нечем.
✓ Два блока: слева работа на своей подложке с листанием (стрелки, клавиши, точки), справа площадки со ссылками на живые посты, дата, текст (единственное прокручиваемое) и действия. Новое: доотправить в сети, где работы ещё не было (без повторной оплаты, с защитой от дубля), и «Сделать на основе» — холст открывается с картинками этой работы как образцом стиля. Окно уезжало за край экрана — рисуем в body.
feature
Ручной режим: промт уходит слово в слово
Усиление промта иногда мешает, и нужен способ его отключить, а не бороться формулировками.
✓ Кнопка «С ИИ / Ручной» во всех четырёх канвасах, выбор запоминается. В ручном одиночная картинка вообще не ходит к разбору — промт становится задачей как есть; карусель зовёт разбор только при явной разметке слайдов; отрисовка ничего не дописывает. Заодно нашли: отрисовка не запускалась, если у ячейки нет текста для нанесения — в ручном его может не быть вовсе.
feature
Вечная загрузка после сбоя запроса
«Мои работы» и весь контекст СММ-Центра вешались навсегда, если один запрос не дошёл: обработки сбоя не было, выйти можно было только перезагрузкой.
✓ Загрузка выключается в любом случае, человек видит причину и кнопку повторить.
bug
↑ Подсказка у значка субтитров не появляется
Сжал подпись «с субтитрами» до значка, а подсказка при наведении не показывается — значок без объяснения непонятен. ПРИЧИНА НАЙДЕНА, ОБЩАЯ ДЛЯ ОБОИХ. Чтобы лента настроек не переносилась на второй этаж, я задал ей overflow-x: auto (класс smm-noscroll). Контейнер с прокруткой обрезает всё, что вылезает за его границы, — и подсказку над кнопкой, и выпадающий список истории. Формально они рисуются, но их не видно. ЧТО ДЕЛАТЬ: убрать обрезку — рисовать подсказку и список через портал в body с позицией по координатам кнопки (как уже сделано у модалок просмотра), либо отказаться от overflow на ленте и держать её в одну строку другим способом. Правка небольшая, но трогает Hint.tsx и TaskHistoryButton.tsx.
✓ Причина была общая: прокрутка на ленте настроек обрезала всё, что вылезает за её границы. Прокрутку убрали, строка держится в одну линию за счёт сжатия субтитров и истории до значков. Проверено в браузере: подсказка показывается, список открывается.
bug
↑ Список «что я писал» не открывается
Клик по значку истории задач не открывает список: он пытается вылезти и остаётся за кнопкой. ПРИЧИНА НАЙДЕНА, ОБЩАЯ ДЛЯ ОБОИХ. Чтобы лента настроек не переносилась на второй этаж, я задал ей overflow-x: auto (класс smm-noscroll). Контейнер с прокруткой обрезает всё, что вылезает за его границы, — и подсказку над кнопкой, и выпадающий список истории. Формально они рисуются, но их не видно. ЧТО ДЕЛАТЬ: убрать обрезку — рисовать подсказку и список через портал в body с позицией по координатам кнопки (как уже сделано у модалок просмотра), либо отказаться от overflow на ленте и держать её в одну строку другим способом. Правка небольшая, но трогает Hint.tsx и TaskHistoryButton.tsx.
✓ Причина была общая: прокрутка на ленте настроек обрезала всё, что вылезает за её границы. Прокрутку убрали, строка держится в одну линию за счёт сжатия субтитров и истории до значков. Проверено в браузере: подсказка показывается, список открывается.
bug
Анимация ожидания дёргается на стыке цикла
Пока картинка рисуется, по кружку идёт волна заполнения. Дойдя до края, она обрывается и начинается заново — рывок хорошо виден и режет глаз. ГДЕ СМОТРЕТЬ: GENERATING_KEYFRAMES в канвасах (карусель, пост, видео, аватар, Ролс). ЧТО НЕ ТАК: у анимации нет бесшовного перехода — конец кадра не совпадает с началом. Нужен либо цикл, где последний кадр равен первому, либо непрерывное движение по кругу вместо заполнения из края в край. Заодно проверить, что при нескольких ячейках волны не идут вразнобой.
✓ Сдвиг волны был в процентах от размера фигуры, а фигура шире одной волны — на стыке цикла прыжок. Сдвигаем ровно на длину волны.
bug
↑ Анимация ожидания пропадает после перехода в другой раздел
Запустил пост, перешёл в карусель и вернулся — анимация в ячейке исчезла, хотя картинка ещё рисуется. Человек думает, что всё сорвалось. ПОЧЕМУ: пометка «рисуется» живёт в состоянии страницы (rendering/queued) и при уходе с холста теряется. Сама работа при этом идёт: она в очереди на сервере. ЧТО ДЕЛАТЬ: восстанавливать пометку из задачи очереди при возврате — hook useRenderQueue уже подключается к своей задаче по номеру из памяти браузера, осталось по её слотам заново пометить ячейки рисующимися, пока статус queued или running.
✓ Пометка «рисуется» жила в состоянии страницы и терялась при уходе. Теперь при возврате восстанавливаем её из задачи очереди по слотам.
bug
В холсте нет кнопки скачать готовую картинку
Картинка готова прямо в холсте, а забрать её себе нельзя: под ячейкой есть перерисовать, текст, посмотреть, фото товара и меню, скачивания нет. Приходится идти в Публикации или тянуть правой кнопкой из браузера. ГДЕ: строка действий под ячейкой в канвасах поста и карусели (там же, где значок глаза и перерисовки). Скачивание уже написано в окне просмотра готовой работы (PublishedViewer, downloadAll) — можно взять оттуда, файлы забираются по одному с паузой, иначе браузер режет пачку.
✓ Кнопка встала в строку действий под ячейкой в канвасах поста и карусели.
feature
Черновик сбрасывается при переходе между холстами
Отправил задачу в холсте аватара, переключился на видео и вернулся — отправка сброшена, черновик как был. Уходя со страницы, компонент размонтируется, и ответ агента приходить некуда. ПОЧЕМУ: черновик лежит в памяти браузера по ключу на каждый холст, но незавершённая отправка в нём не сохраняется. ЧТО ДЕЛАТЬ: это частный случай задачи «Несколько черновиков в одном холсте» — решать вместе с ней, отдельно чинить смысла нет. Минимальный шаг: держать признак «отправка идёт» в том же черновике и при возврате дожидаться ответа, как это сделано для очереди отрисовки в посте и карусели.
✓ Запрос к агенту браузер не отменяет — терялся только результат, потому что компонент размонтирован. Теперь раскладка сразу пишется в черновик, а он читается при возврате. Сделано в холстах аватара и видео.
bug
↓ Пул ключей Kie + ограничитель скорости
ОТЛОЖЕНО по решению заказчика: делаем, когда будут хотя бы десятки активных пользователей. Сейчас одного ключа хватает. СМЫСЛ: несколько учёток Kie, задачи распределяются между ними, свой ограничитель скорости перед провайдером — иначе при массовой генерации получим отказы пачками. ГДЕ: src/lib/kie-ai/client.ts и studio/kie-ai-studio.ts берут ключ из одной переменной KIE_AI_API_KEY. Нужен выбор ключа с учётом остатка и текущей нагрузки.
feature
↑ Проверить ИИ-аватар живым прогоном после защит
Выкачено, но НЕ проверено на живой генерации — заказчик остановил после серии двойных списаний. Что проверять за один прогон: реплики из сценария звучат все (не только первая), кадр перерисовывается через GPT Image по английскому промту, повтор из очереди не создаёт вторую генерацию, списание сверяется с фактической длиной. ВАЖНО: сценарий заказчика ~480 знаков это ~40 секунд речи, при заказе 15 секунд спишется разница (~550 руб вместо 330) — предупредить до запуска.
task
OmniHuman отказывает: Volcengine CV API error
В логах три попытки подряд: «OmniHuman сегмент 1 task attempt 1/2/3 failed: Call Volcengine CV API error, action=CVSubmitTask». К повторам очереди отношения не имеет — это отказ на стороне провайдера. Проверить: доступность URL картинки и аудио снаружи, формат и размер кадра, остаток на счёте Kie, лимиты OmniHuman.
✓ Причина найдена прогоном: отбивался не провайдер, а наш файл. gpt-image отдаёт PNG весом около двух мегабайт со стороной больше 1000 — такой кадр оживление не принимает ни как .jpg, ни как .png. Тот же кадр в JPEG 720x960 проходит, как и внешняя картинка. Кадр теперь пережимается перед отправкой (lib/storage/put-image.ts).
bug
В РАБОТЕS13 · Пайплайны: разбор, сценарии, починка29/41

Цель: Э0-Э3 плана docs/FIX-ROADMAP.md: мерки, ремонт контракта холст-сервер, деньги под контролем, Задание (TaskSpec) вместо догадок

↑ А. Пайплайны выгружены и описаны
docs/PIPELINES.md переписан полностью: контракт полей холст→сервер, карта всех 15 вызовов моделей, карта всех списаний, отдельный раздел «где данные теряются» и реестр из 24 дефектов (Д1..Д24).
✓ Второй, углублённый заход: 495 строк, каждое утверждение с файлом и строкой. Найдено 12 мест, где данные человека молча выбрасываются.
task
↑ Б. Матрица сценариев постановки задачи
docs/SCENARIOS.md: 115 сценариев (аватар 27, пост 24, карусель 22, видео 22, Ролс 20). Каждый со ссылкой на дефект из реестра.
✓ Было 63, стало 115. Добавлены сценарии с ролями вложений, противоречиями между выбором и текстом, невозможными просьбами.
task
↑ В. Отчёт: где результата не будет
docs/PIPELINES-REPORT.md: 41 из 115 не дадут результата, 33 дадут половину. Девять дефектов ранжированы по ущербу, три системные причины, что уже хорошо и ломать нельзя.
✓ Отчёт переписан под новую матрицу. Добавлен раздел «почему напрямую в Kie работает, а у нас нет»: между человеком и моделью стоят от двух до шести переписывающих агентов.
task
🔴 Г1. Разбор намерения: один вход вместо россыпи догадок
Один вызов модели на входе холста → Задание (TaskSpec): intent, verbatim (что дословно), invent (что можно придумать), attachments с ролями, constraints, missing, impossible, summary_for_human. Контракт в docs/PIPELINES-FIX-PLAN.md. Убирает decideRefRole и decideScene как отдельные догадки. Дефекты Д1, Д12.
✓ Приёмщик lib/task: схема Задания, пять профилей, structured output, температура 0. 108 из 110 постановок разбираются верно. Задание доведено до генератора: пост и карусель рисуют по нему напрямую, аватар и видео получают его в карточке.
feature
🔴 Г2. Роли у приложенных картинок
Роли: base_to_edit, product, person, location, style_ref, logo, frame_first, frame_last, audio_voice, audio_music. Роль предлагает разбор, человек правит одним нажатием. В промте картинки подписаны ролью, а не «Image 1». Дефекты Д2, Д3.
✓ Роли задаются в холсте (лицо, место, товар, озвучка) и определяются зрением, когда человек их не задал. Выбор человека всегда сильнее.
feature
↑ Г3. Проверка достаточности до списания
Правила кодом (нет лица, нет голоса, нет фото, длина вне сетки, сценарий длиннее заказа) + зрение там, где нужно (видно ли лицо, один ли человек, не обрезан ли товар). Плюс экран «понял так: …, N ₽» с подтверждением: сейчас у аватара одна кнопка делает всё сразу (avatar-canvas/page.tsx:313). Дефекты Д4, Д19.
✓ Окно «понял так» со сметой во всех пяти холстах; без лица и без фото кнопка запуска заблокирована. Проверено: аватар без лица даёт no_face и no_voice.
feature
Г4. Заказ побеждает догадку: длина, тайминги, порядок
constraints из Задания жёсткие: длина, тайминги, порядок кадров, число слайдов, обязательные строки (цена, телефон). Что не влезает — отказ с объяснением ДО денег, а не молчаливое обрезание (сейчас молча режутся 15 слайдов до 10 и 6 кадров Ролса до 4). Дефекты Д5, Д14.
feature
Г5. Готовый промт не переписывается даже в режиме «С ИИ»
Готовый режиссёрский промт и готовая речь уходят в verbatim и вставляются кодом дословно: ни стиля серии, ни служебных хвостов. Приёмка: один и тот же промт напрямую в Kie и через холст в режиме «С ИИ» дают сопоставимый результат. Дефекты Д1, Д7.
✓ Задание с verbatim уходит в отрисовку без агента. Приписки из промтов вычищены: тот же промт, что давал рекламный плакат, теперь даёт заказанное фото.
feature
↓ Г6. Память задач: «сделай как в прошлый раз»
Хранить последнее Задание по компании и формату, подставлять по просьбе «как в прошлый раз». Пересекается со «Скиллами» — делать вместе. Дефект Д16.
feature
🔴 Г7. Вложения аватара доходят до генератора
create-content/route.ts:183-186 принимает referenceImages/Videos/Audios только для Wan и Seedance → у avatar_video они превращаются в null. Первый/последний кадр сохраняются, но пайплайн аватара их не читает. Фото локации и товара из чата ролями не становятся, своя озвучка игнорируется (всё равно TTS). Дефект Д8.
✓ Приняли referenceImages/Audios для avatar_video и Veo; роли вложений в новой колонке attachment_roles; фото места и товара из чата доходят до кадра, своя озвучка заменяет синтез. Проверено контрактом на карточке a5c3af8c (без генерации).
fix
🔴 Г8. Видео на Veo использует раскадровку холста
video_scenes читаются только в премиум-ветке (Wan/Seedance). На Veo — модели по умолчанию — сценарий пишется заново от item.idea, а холст обрезает idea до 300 знаков (video-canvas/page.tsx:286). То есть согласованная человеком раскадровка до генератора не доходит. Дефект Д9.
✓ video-build-multi-clip берёт сцены холста как промты клипов и как сценарий; idea в холсте больше не режется до 300 знаков (2000).
fix
↑ Г9. Честная сетка длин аватара
numSegments максимум 3 по 15 секунд речи, поэтому заказ 16-29 и 46-60 секунд структурно невыполним: 25 с даёт 15 с, 60 с даёт 45 с (дальше возврат разницы). Ползунок при этом предлагает 5-60. Либо снять предел в три сегмента, либо ограничить ползунок реальными значениями. Дефект Д6.
✓ Снят потолок в три сегмента (60с давали 45). Отдельно найдено и починено: заказ длины сохранялся только для 8/15/30, всё остальное превращалось в null ещё до генерации. Живьём не прогонялось — за владельцем.
fix
↑ Г10. Авто-Ролс слышит задачу человека
lib/rols/jobs.ts:80 зовёт runDirector(product, factory, template) без brief: текст задачи попадает только в idea и script карточки, на кадры не влияет. Дефект Д13.
✓ runDirector получил бриф, в промте он выше шаблона. Живой прогон: задача «скидка 30% до воскресенья» попала в бейдж, в подписи и в озвучку (job d40f4027).
fix
↑ Г11. Карусель снова чейнится от обложки
Очередь рисует слайды по одному с onlyIndex и берёт обложку из payload.coverRefUrl, который фронт заполняет из УЖЕ отрисованной обложки (carousel-chat/page.tsx:455). На первом прогоне обложки нет → слайды 2..N рисуются без неё, единство серии держится только текстом seriesStyle. Дефект Д11.
✓ Работник очереди рисует обложку первой и подставляет её результат остальным слайдам. Живой прогон: серия из 4 слайдов в единой манере (job 3bb9bed6), плюс 3 слайда на Nano (job f2e7413e).
fix
↑ Г12. До шестнадцати картинок вместо четырёх
carousel/render/route.ts:444,476,495 режет референсы до 4, хотя gpt-image-2 принимает 16 (kie-ai/client.ts:561), nano-banana-2-lite — 10, а холст даёт приложить 16. Пятая и дальше выбрасываются молча. Дефект Д3.
✓ Лимит по движку: GPT Image 16, Nano 10, дубли отсеиваются, лишнее пишется в лог. Живой прогон: коллаж из 5 приложенных картинок собрался со всеми пятью.
fix
Г13. Сверка результата с заказом
Сейчас единственная проверка результата — длина ролика аватара. Добавить: обязательные строки на картинке (цена, телефон), тот ли товар, читается ли текст. Не сошлось — пересборка за наш счёт или честный возврат. Дефект Д15.
feature
Г14. Режиссёр аватара через OpenRouter, не напрямую в OpenAI
lib/openai/avatar-director.ts ходит в OpenAI прямым ключом (gpt-4o-mini). Правило проекта: текст через OpenRouter, картинки и видео через Kie. Заодно поднять модель: речь ролика — не механическая задача. Дефект Д22.
✓ avatar-director переведён на openrouterCompletion (deepseek-chat-v3). Прямых вызовов OpenAI в пути аватара не осталось.
fix
Г15. Честные отказы на невозможное
Снять водяной знак, два голоса в одном ролике, шесть кадров Ролса, две пропорции сразу, ссылка на чужой ролик как образец — говорить «нет» до списания, а не пробовать. Дефект Д24.
feature
↑ Б2. Матрица сценариев по ролям (6 ролей x 5 форматов)
docs/SCENARIOS-ROLES.md: предприниматель без опыта в ИИ, предприниматель со знанием базы, маркетолог, СММщик компании, СММщик агентства, креатор. По 12 сценариев на каждый формат = 360. Итог: 136 работают, 125 наполовину, 99 не дадут результата. Вместе с матрицей по форматам — 475 разобранных способов поставить задачу, из них 140 провальных. Найдены дефекты Д25..Д36 (продуктовые пробелы).
✓ Проверено по коду, какие функции реально есть (derive, video-edit, композер, шаблоны, пресеты, труппа, бумперы, сторис), чтобы оценки не были выдумкой.
research
↑ Э0. Регресс-набор 40 сценариев
Отобрать по 8 сценариев на формат из 475 разобранных: те, что ломаются у трёх ролей и больше, плюс те, что уже работают (ловить регресс). Прогон руками после каждого этапа, запись в docs/REGRESSION-SET.md. Черновик набора — в docs/FIX-ROADMAP.md, раздел 6.
chore
↑ Э0. Живой прогон аватара
Часть выводов по аватару сделана из кода, а не из наблюдения: длина, голос по умолчанию, решение по кадру, клип товара. Прогон 15 секунд = 330 ₽, нужно разрешение владельца. Висит с 12 спринта.
chore
Э0. Базовые метрики из БД
Снять по transactions за 30 дней: доля возвратов, доля повторных запусков того же задания в течение 30 минут, средний чек ошибки. Без этого нечем доказать, что стало лучше. Цели — в docs/FIX-ROADMAP.md, раздел 7.
chore
(служебная, игнорировать)
Осталась от синхронизации дашборда 02.08, удалить нечем: API не поддерживает DELETE задач.
feature
🔴 Цена «всё включено»: никаких доплат по ходу
Решение владельца 02.08: объявленная до старта цена не растёт. Убраны отдельные списания у аватара (ведущий 5 ₽, перерисовка кадра 10 ₽ в двух местах) и доплата за перебор длины — теперь это наш перерасход. Возврат остаётся только в пользу человека (вышло короче заказа). Себестоимость OmniHuman 0.135 $/с против цены 22 ₽/с, внутренние шаги помещаются в маржу. Осталось распространить правило на Ролс (дорисованные кадры, субтитры) и на видео.
✓ Аватар — сделано. Ролс и видео — впереди.
fix
🔴 Г1а. Приёмщик задач: ядро и пять профилей
lib/task: схема Задания + разбор одним вызовом (Gemini 2.5 Flash, температура 0), профили на формат, эндпоинт /api/smm/task/parse. Раскладывает кадр, действие, речь, надписи, роли вложений; числа и лимиты считает код. Прогон: 108 из 110 постановок задачи (docs/PARSER-RUN.md, набор в scripts/parser-cases.py). Осталось: зрение для ролей картинок, названных списком.
✓ Работает на стенде, генераций не трогает. Было 91/110 на первом прогоне, стало 108/110 после переноса количества, цен, ролей аудио и отличия темы от речи в код.
feature
🔴 Г1б. Подключить приёмщика к холстам + окно «понял так»
Холсты зовут /api/smm/task/parse перед постановкой задачи, показывают разбор и смету, списание только после подтверждения. Порядок включения: пост, карусель, Ролс, видео, аватар.
✓ Все пять холстов зовут разбор перед работой, показывают «понял так» и смету; списание только после подтверждения. Смета считается кодом по тем же таблицам, что и касса.
feature
↑ Г1в. Зрение для ролей картинок
Когда человек называет вложения списком («локация, человек, товар»), порядок файлов может не совпасть с порядком слов. Нужен дешёвый vision-проход: что на картинке. Единственный кейс из 110, где разбор ошибается.
✓ Роли определяются взглядом на картинку, выбор идёт из ролей, которые человек назвал словами. Проверено: гостиная → локация, монтажник → человек, диван → товар.
feature
↑ Г5а. Вычистить наши приписки из промтов генератора
«top-tier ad-agency creative», стиль серии поверх готового промта и прочие хвосты перебивают инструкцию человека: доказано прогоном (фото кружки превратилось в рекламный плакат). Убрать всё, что человек не просил.
✓ Убран хвост «top-tier ad-agency creative»; текст на картинке требуется только когда его просили, иначе надписи прямо запрещены. Пруф: тот же промт, что давал рекламный плакат, теперь даёт заказанное фото кружки.
fix
↑ Г13а. Слой качества: отбраковка кадра и сверка результата
lib/task/frame-check.ts — кадр в двух вариантах + чеклист зрением перед дорогим шагом (аватар: 3 руб против 200; видео: 3 против 60-100). lib/task/verify.ts — сверка готовой картинки с заданием: цена, телефон, товар, лишние надписи. Служебный /api/smm/task/check для отладки без генераций. Описание: docs/QUALITY-LAYER.md
✓ Проверено на готовых картинках: подменённые цену и телефон находит, человека спиной для липсинка бракует 0/10, фото кружки принимает 9/10. Автоперерисовку пока не включаем.
feature
↑ Качество ролика аватара: вертикаль, звук места, дыхание, стык
Кадр рисуется 9:16 (было 3:4 — видео 832x1120, в лентах поля или обрезанная голова). Атмосфера подбирается по описанию кадра и подмешивается тихо под голос; нейтральные места остаются без фона. В конце каждого куска речи пауза 0.45с. Следующий кусок стартует с последнего кадра предыдущего — на склейке нет рывка. Подключён словарь произношения завода (раньше не передавался factoryId, слой молча не работал). Текст-хук пишется только когда сценарий придумываем мы.
✓ Проверено: механизм паузы удлиняет дорожку ровно на добавленное дыхание. Проверку готового ролика намеренно не делаем — решение владельца: переделывать за свой счёт не будем.
feature
↑ Г16. Аватар: одна озвучка, один клип, звук места, единые кнопки
Нарезка речи на куски по 15 секунд убрана: OmniHuman принимает аудио до 60 секунд, весь текст идёт целиком одним вызовом. Раньше собственная защита обрезала 4 реплики до 2 и давала швы на склейке. Кадр рисуется 9:16 (было 3:4 — в лентах поля). Атмосфера места подбирается по описанию кадра и подмешивается под голос (громкость 0.28 + срез гула). Подключён словарь произношения завода. Текст-хук пишется только когда сценарий придумываем мы. Действия над готовой работой (опубликовать, скачать, начать новую) вынесены в общий компонент и стоят в одном месте во всех пяти холстах.
✓ Проверено логами и файлами: атмосфера подбирается и подмешивается, кадр вертикальный, картинки сохраняются с настоящим типом. Живьём после упрощения ещё не гонялось — ждём прогона владельца.
fix
↑ Г17. Звук ролика: слышный фон места и нормальная громкость
amix делил громкость на число дорожек: речь проседала вдвое, фон уходил в неразличимое (замер готового ролика -36 dB при норме -16). Добавлены normalize=0 и loudnorm=I=-16 — замер после правки -19.4 dB средняя, -3.9 пик. Фон 0.35 + highpass 120 Гц, чтобы не давил на голос. Нарезка звука выровнена: 29 секунд это две части по 14.4, а не три обрывка; точка реза учитывает, что в предел должна влезть и часть, и остаток. Кадр даёт место движению: при описанном действии просим план от колен.
✓ Владелец послушал собранный образец: улица слышна, речь на нормальной громкости. Генерация звуковых эффектов пока годится, база готовых записей отложена.
fix
🔴 Г18. Настоящая причина отказов оживления: файл не успевал стать доступным
Те же кадр и озвучка, что упали в пайплайне, при отправке вручную минутой позже прошли успешно — дважды. Значит провайдер идёт за файлом сразу после createTask, а наше хранилище в этот момент его ещё не отдаёт. Прежние версии (тяжёлый PNG, длина 28 секунд) были следствием той же гонки. Теперь после загрузки кадра и озвучки ждём, пока ссылка реально отвечает (до 10 попыток), и только потом отправляем. Ролик снова уходит одним куском до 30 секунд, при отказе система один раз режет запись по паузам и повторяет сама.
✓ Прогон владельца прошёл: ролик 30 секунд собрался. Осталось качество формата, а не техника.
fix
↑ Г19. Приёмщик обрывался на длинном ответе
OpenRouter returned invalid JSON: Unterminated string — ответ не влезал в 3000 токенов, задание уходило пустым, и в сборку шла одна реплика из ячейки вместо четырёх. Лимит поднят до 8000, добавлен повтор при битом JSON, в промте просьба не дублировать длинные тексты. Плюс в карточку теперь уходит полный текст задачи, а не только подписи ячеек: описание кадра до сборки не доезжало.
fix
↑ Г20. Нажатие видно сразу, второй клик невозможен
Между нажатием и первым сообщением было несколько секунд тишины — человек успевал нажать ещё раз, и это грозило второй сборкой за деньги. Теперь сразу «Читаю задачу…», кнопка гаснет и крутится, Enter в это время не срабатывает.
fix
🔴 Г21. Качество ролика аватара не оправдывает цену — решить судьбу формата
Владелец оценивает готовый ролик в 150 руб при цене 660 и себестоимости около 400 (13.5 руб/сек у Kie). Техника доведена: весь текст произносится, кадр вертикальный, атмосфера подбирается по месту, стык ровный. Дальше вопрос не в коде, а в подаче: голос (сейчас нейтральный из списка), постановка (без описания поведения уходит дежурная фраза), характер кадра (с предметом получалось ярче). Предложено: серия дешёвых прогонов по 5-8 секунд на разных голосах и постановках, чтобы понять потолок. Если потолок низкий — честнее убрать формат из витрины, чем продавать за 660.
research
Г22. Сабы: брать наш текст, а не расшифровку своей же озвучки
Роут /api/video/subtitles гонит Whisper по дорожке, которую мы сами и синтезировали. На ролике Брендосс 09.08 получили «Пустая комната ям», «Брэндес» вместо БРЕНДОСС и по 70 символов в одном сабе. Когда озвучка наша, текст известен: брать тайминги из ElevenLabs /with-timestamps (alignment по символам), резать на куски по 3-4 слова и рисовать наш текст (бренд капсом, числа цифрами). Плюс segmentsToStyledASS зашивает PlayRes 1080x1920 — на кадре другого размера саб мелкий и тянутый, ставить реальный размер кадра и кегль долей высоты. Рабочий образец: scratchpad oks-subs.mjs.
feature
Г23. Премиум-ролик уезжает в 3:4 и молчит: чинить кадр и просить речь
Wan 2.7 в режиме i2v игнорирует ratio и берёт пропорции первого кадра — ролик 08.08 вышел 830x1108 вместо 9:16, под Reels не годится. Чинить: первый кадр генерить вертикальным (nano-banana-pro/gpt-image-2, aspect 9:16) либо звать t2v. Второе: Wan УМЕЕТ русскую речь (проверено 09.08, Whisper снял с дорожки ровно заказанную реплику) — но пайплайн её не просит, поэтому дорожка приезжает пустой (-58 dB) и озвучку клеим сверху. Дать режиссёру промтов вариант со встроенной речью: реплики кириллицей в кавычках + строка про lip sync. Комментарий в kie-ai-studio.ts про No native speech ввёл в заблуждение — поправить.
feature
🔴 Студия, ролики: фото не доходило, темнокожие герои, мини-фильм на 8 с, сбой Kie без повтора (разбор 01.10)
Жалоба владельца 02.10. Клиентка в Студии (простой режим) 6 роликов Veo Lite, 4 упали, 2 с темнокожими героями и наплывами. Причины: простой режим выбрасывал приложенное фото (тип ввода из экспертного режима); нет правила внешности в Студии; помощник писал мини-фильм 1361 знак на 8 с; Kie 500 Internal Error без автоповтора; тариф «Оптимально» обещал 12 с за 80 ₽ при 8 с за 50 ₽; возврат денег без защиты от двойного. Разбор: docs/STUDIO-VIDEO-FIX-2026-10-02.md. Решения: docs/DECISIONS-QUEUE.md.
✓ НА ПРОДЕ с 02.10 04:06 UTC по «да на прод». Мерж 06b6dcda в fix/impersonate-on-v1.4 (только dece6e5b + 533cd37b, 10 файлов). Сборка в сторону NEXT_DIST_DIR=.next-build, подмена папки, простой ~2 с. Проверено на 24contentzavod.ru под тест-юзером: подсказка про фото видна, «Оптимально» 50 ₽ / 8 с / Veo 3.1 Lite, приложенное фото загружается и уходит в запрос генерации как image_url (запрос перехвачен в браузере, без оплаты). Страницы /, /auth/login, /studio/video, /pricing, /blog — 200, видео лендинга 200. Откат: mv .next/standalone .next/standalone.failed && mv .next/standalone.old-20261002 .next/standalone && pm2 restart content-factory-prod; копия ещё в /var/www/cf-prod-standalone-backup-20261002, коммит отката в /root/cf-prod-rollback-20261002.txt.
fix
🔴 nginx cfru: временные папки сменили владельца на nobody — все загрузки файлов 500 (01.10 18:17 UTC)
open() /var/lib/nginx/body/… (13: Permission denied) на любом POST крупнее 16 КБ, все сайты сервера. Так делает nginx, запущенный от root с конфигом без строки user. Кто запустил — не выяснено (журнал входов закрыт), вопрос владельцу Д-3 в docs/DECISIONS-QUEUE.md.
✓ 02.10 03:36 UTC: chown www-data:root /var/lib/nginx/{body,proxy,fastcgi,scgi,uwsgi} без перезапуска; было записано в /root/nginx-tempdirs-before-2026-10-02.txt. Загрузка /api/upload-studio-file на стенде 200. Клиентов не задело: в access.log за окно только сканеры.
fix
↑ Фото доходит до модели в Студии и агентах; замысел ролика не течёт между клиентами
Стенд /var/www/content-factory, коммиты 15e0496e + c497c814 (ветка test/sprint-3-quality, не запушены). Утечка __veoStoryIntent между клиентами; «Бюджет»/t2i глотали фото → flux-2 i2i или отказ до списания; Veo квадрат/Авто → 16:9; Kling Turbo, Hailuo 2.3, Grok видео, Qwen Image 2 — поля по доке Kie; логотип фотосессии, выбор пропорции, доли возврата; MJ опрос mj/record-info; СММ-агент не списывает без фото; видео-агент с Sora на Veo 3.1 Lite с возвратом; журнал трат фотосессии; «Тест генерации» убран. Экзамены 90/90. Решения Д-4…Д-10 в docs/DECISIONS-QUEUE.md.
✓ Выкачено на прод 03.10: 00:16 (eec4be03 — фото, утечка замысла, журнал денег, MJ, видео-агент) и 00:53 (bbfbf205 — Д-6 «Премиум» 2K, итоги решений), оба по «да» владельца, сборка в сторону, вход 200. В бандле прода resolution 2K у gpt-image-2-t2i. Решения: Д-4 выкл., Д-5 MJ отказ Kie → выкл. (5 ₽ вернулись), Д-9 Wan 2.7 фото вкл. (Pro нет), Д-10 сходится.
bug
планS14 · Продуктовые пробелы по ролям0/10

Цель: Э4-Э5 плана docs/FIX-ROADMAP.md: превью до денег, сверка результата, память задач, продуктовые пробелы по ролям

🔴 П1. Превью и согласование до списания
Дешёвая ступень «покажи, что получится» до полной оплаты и место, где заказчик утверждает макет. Просят пять ролей из шести: предприниматель, маркетолог, СММщик компании, агентство, креатор. Снимает половину боли «правка = полная переплата». Дефекты Д32, Д19.
feature
↑ П2. Варианты одной задачи и A/B
«Дай три штуки, выберу», два хука на один ролик, две обложки карусели. Без этого маркетолог не может тестировать вообще. Дефект Д26.
feature
↑ П3. Бренд-ассеты как правило + загрузка бренд-гайда
Логотип, шрифты, палитра, интро/аутро, стиль субтитров сейчас живут в разных местах и до холстов не доходят; бренд-гайд клиента (pdf) загрузить некуда. Агентство без этого не масштабируется. Дефекты Д27, Д30.
feature
↑ П4. Пакетная работа
Карусели, Ролсы, аватары и видео запускаются по одному; композер планирует идеи, но сборку не запускает. Тридцать роликов вручную никто делать не станет. Дефект Д25.
feature
П5. Разъезд по площадкам и лимиты площадок
Один аспект на задачу: второй формат = отдельный платный запуск. Лимиты по длине текста и числу слайдов не проверяются. Дефекты Д36, Д29.
feature
П6. Повторяемость: сид и воспроизведение удачного кадра
«Тот же кадр, другой ракурс», «тот же сид, поменяй свет» — невозможно. Бьёт по креатору и по предпринимателю со знанием ИИ. Дефект Д34.
feature
П7. Свои материалы: музыка, съёмка, шрифты
Своя музыка не поддержана нигде, своё видео как основу не приложить, шрифты и вёрстка субтитров зашиты. Правка готового видео ограничена 15 секундами и 25 ₽/с. Дефекты Д17, Д33.
feature
П8. Сторис как формат в холстах
Сейчас сторис есть только в фабрике историй (премиум), в СММ-холстах формата нет. Дефект Д28.
feature
↓ П9. Мультиязычность
Язык задаётся только словами в промте, служебные хвосты промтов на английском, субтитров на двух языках нет. Нужно агентствам с филиалами и экспортом. Дефект Д31.
feature
↓ П10. Перенос стиля между форматами
Пресет карусели не применить к посту или видео: единый вид ленты приходится держать руками. Дефект Д35.
feature
В РАБОТЕS15 · Фундамент: стабильность под нагрузкой13/26

Цель: Убрать причины внезапных отказов и подготовить систему к росту числа клиентов. Основание: docs/STABILITY-AUDIT.md, снят с прода 05.08.2026.

🔴 Р2. Права проверялись перебором всей таблицы
org_members перебиралась целиком 2 552 782 раза против 228 обращений по индексу; organizations 780 964; companies 768 457. Индексов на user_id, owner_user_id и org_id не было вовсе. При 317 строках это незаметно, на тысяче компаний ложится каждый запрос к любой таблице. Добавлены индексы org_members(user_id), org_members(org_id,user_id), organizations(owner_user_id), companies(org_id), content_items(factory_id,status,created_at). Проверено: функция политики фильтрует ровно по org_id+user_id, индекс ей подходит.
fix
🔴 Р8. Журнал ошибок сам не писался
«Failed to log error: new row violates row-level security policy» 59 раз за сутки: журнал писался от имени человека, а ошибки чаще случаются там, где сессии нет (фоновая сборка, очередь, вебхук). Мы теряли ровно те ошибки, ради которых журнал заводили, и узнавали о сбоях только от клиента. Переведён на служебный ключ.
fix
🔴 Р4. Внешние вызовы без предела ожидания
240 вызовов наружу, из них с таймаутом 4. Процесс один на всех: подвисший провайдер держит наше соединение и память, остальные клиенты ждут. Появилась общая обёртка lib/net/fetch-safe.ts: предел ожидания, один повтор на сетевую осечку и коды 429/502/503/504, повтор для POST только по флагу. Переведены клиенты Kie (19 вызовов). Осталось перевести ElevenLabs, Suno, Upload-Post, VK, Telegram.
fix
↑ Р1. Выкладка обрывает работу в открытых вкладках
«Failed to find Server Action» 62 раза и «Cannot read properties of null (reading digest)» 74 раза за сутки. Вкладка, открытая до выката, шлёт устаревший идентификатор и получает ошибку посреди работы. У агентства, которое держит кабинет открытым весь день, это происходит на каждом выкате. Плашка о новой версии есть, но она не ловит саму ошибку. Нужно: перехват такой ошибки на клиенте с предложением обновиться и сохранением набранного.
fix
↑ Р6. Гонки состояния на холстах
Список ячеек собирался внутри обновления состояния, а команда на отрисовку читала его снаружи через 100 мс. Когда React не успевал, список приходил пустым и задача в очередь не уходила вовсе: человек видел восемь ячеек с текстами и ни одной картинки, в базе ноль задач. Переписаны карусель и агентская ветка. Осталось пять таких мест в холстах поста и карусели. Правило: посчитать значение и передать параметром, из состояния в обработчике не читать.
fix
↑ Р5. Долгие генерации живут внутри HTTP-запроса
27 мест с циклом «спим пять секунд, спрашиваем статус», до десяти минут в одном запросе, при этом предел времени задан лишь у пяти роутов из 298. Запрос держит соединение и память всю генерацию; сеть моргнула, работа осиротела, деньги списаны. Довести до конца начатое очередью: ставим задачу, сразу отвечаем, результат забираем фоном.
feature
🔴 Р7. Списание денег не атомарно
Баланс читается, вычитается и пишется обратно с проверкой «не изменился» плюс повторы; запись в журнал операций идёт отдельным запросом. При сбое между ними баланс уменьшится без записи в журнал. Для корпоративного клиента расхождение в деньгах недопустимо. В базе уже есть функции charge и increment_balance, перевести списание на одну транзакцию.
fix
↑ Р3. Картинки лежат в базе целиком
content_items весит 503 МБ при 4544 строках, из них 261 МБ в carousel_slides: 121 запись хранит data:image/png;base64 прямо в ячейке, самая тяжёлая 3,4 МБ. Раздувает бэкапы и память базы. Перелить в хранилище, оставить ссылки, запретить запись base64 на уровне кода.
fix
Р10. Очереди на кроне вместо воркера
Разбор писем и сбор картинок висят на crontab с шагом 2-5 минут: задержка на каждом шаге и никаких приоритетов. При росте крон запускает следующий проход, не дождавшись предыдущего. Нужен один постоянный воркер с ограничением параллельности.
feature
↑ Р9. Публикации молча не уходят
VK Error 5 invalid access_token 16 раз, «message caption is too long», плюс 16 отказов отправки событий в Inngest. Клиент считает, что пост вышел, а он не вышел. Нужна проверка токенов по расписанию с предупреждением до публикации и обрезка подписи по правилам сети до отправки.
fix
🔴 Регресс-прогон перед выкладкой
Сейчас перед деплоем проверяются только типы и то, что сайт отвечает 200. Это не ловит ровно то, на чём мы горим: уехавшее окно, тяжёлые картинки, потерянный контекст, незапущенную отрисовку. Нужен сценарий, который логинится тестовым аккаунтом и проходит путь клиента на двух ширинах, проверяя факты: кнопка подтверждения видна, горизонтального скролла нет, вес картинок в списке ниже порога, задача в очереди появилась. Красный прогон блокирует выкладку.
feature
🔴 Смоук-прогон перед выкладкой: сделан и включён в деплой
Playwright, 14 проверок на двух ширинах: вход, дашборд, пять холстов, работы, публикации. Проверяет факты, а не «страница открылась»: кнопка подтверждения видна целиком, горизонтального скролла нет, картинки целы и легче 600 КБ, реакция на нажатие приходит за три секунды. Денег не тратит: доходит до окна подтверждения и жмёт «Не так». Красный прогон возвращает предыдущую сборку. Первый же запуск нашёл настоящий баг: холст поста был шире экрана на 23 пикселя.
feature
🔴 Окна поверх страницы уезжали за экран
В «Моих работах» клик по видео давал пустое затемнение: карточка открывалась за пределами экрана. Причина общая для Центра: анимация появления стояла в режиме both и навсегда удерживала transform, а он делает position: fixed относительным себе. Режим backwards снял ловушку и починил все 23 окна раздела разом.
fix
🔴 Карусель зависала с текстами без картинок
Список затронутых ячеек собирался внутри обновления состояния, а команда на отрисовку читала его снаружи через сто миллисекунд. Когда React не успевал, список приходил пустым и задача в очередь не уходила вовсе: восемь ячеек с текстами и ни одной картинки, в базе ноль задач.
fix
🔴 Работа шла только при открытой вкладке
Задачу доводила внешняя служба событий, она роняла её на первом шаге, наш возврат в очередь отправлял туда же: у одной работы было два хозяина. Закрыл вкладку — работа стояла. Теперь очередь тянет наш воркер по расписанию раз в минуту, брошенное подхватывается через три минуты, отметка живости пишется после каждого слайда.
fix
↑ Показ хода работы врал
Все ячейки разом помечались «рисуется», хотя сервер делал обложку: от неё берётся стиль серии, остальные физически не могли начаться. Теперь крутится только то, что делается: сначала обложка, остальные пишут «ждёт обложку», дальше по три за раз.
fix
↑ Пресет перерисовывал те же слайды
Пресет хранит все слайды прошлой карусели, и все десять уходили в модель как входные картинки в режиме «переделай картинку». Она брала готовый слайд и меняла надпись. Теперь от пресета берётся не больше двух образцов, а правило сказано прямо: брать палитру, шрифты, свет и фактуру, не брать предметы, героев, фон и композицию.
fix
↑ На слайде рисовался весь план карусели
План серии уходил в промт каждого слайда со словами «используй только эти заголовки». Модель поняла буквально и печатала на картинке весь список. Теперь план видит только обложка и помечен как контекст, рисовать его нельзя. Плюс запрет на одинаковый текст у разных слайдов.
fix
↑ Отметки доставки в поддержке
Ответ писался в базу и уходил в мессенджер, а результат отправки нигде не сохранялся: если мессенджер не принял, в переписке ответ всё равно выглядел отправленным. Теперь у каждого ответа отметка: доставлено, не дошло, ждёт в кабинете. «Прочитано» только у веб-чата: мессенджеры о прочтении ботам не сообщают.
feature
↑ Работа без завода невидима в «Моих работах»
Список работ фильтруется по заводам, и контент, созданный с привязкой только к компании, не показывается ни при каком выборе, хотя деньги за него списаны. Поймано на живом контенте для клиента.
fix
Ролс нельзя поставить служебным ключом
У раздела вход только через интерфейс: задачу нельзя создать ни кроном, ни скриптом, ни помощником. Для остальных форматов служебный вход есть.
feature
Проверка: ключ очереди и авто-сборка на проде живы
09.08 прод три недели жил без INNGEST_EVENT_KEY: сайт отвечал 200, посты и карусели собирались, а видео, очередь картинок СММ, публикация через очередь и аналитика молча не работали. Ключ восстановлен, событие проверено живым вызовом (200 + Inngest вызвал функцию, 206). Тогда же в логе замечены две ошибки автосборки 'fetch failed' при вызове https://24contentzavod.ru/api/content-item/<id>/generate — не повторялись. КОМАНДА ПРОВЕРКИ: ssh cfru "grep -c '^INNGEST_' /var/www/content-factory-prod/.next/standalone/.env" → должно быть 2 ssh cfru "curl -s -o /dev/null -w '%{http_code}' https://24contentzavod.ru/api/inngest" → 401 (не 500) ssh cfru "grep -c 'couldn.t find an event key' /root/.pm2/logs/content-factory-prod-error-2.log" → не должно расти ssh cfru "grep -c 'Failed to generate item' /root/.pm2/logs/content-factory-prod-error-2.log" → было 2 В базе: SELECT count(*) FROM render_queue WHERE status='failed' AND error_message LIKE '%event%'; → не должно расти
✓ Проверено 16.08: ключей INNGEST два, /api/inngest отвечает 401 (не 500), жалоб «couldn t find an event key» в логе ноль, сбоев автосборки ноль. Очередь и авто-сборка на проде живы.
check
↑ Проверка: очередь прода работает своим кодом, а не стендовым
17.08 выяснилось, что внутренние вызовы прода шли на 127.0.0.1:3001 — это стенд. Очередь картинок, публикация и аналитика выполнялись кодом стенда. Задано INTERNAL_BASE_URL=http://127.0.0.1:3002. КОМАНДА ПРОВЕРКИ: ssh cfru "grep -c '^INTERNAL_BASE_URL=http://127.0.0.1:3002' /var/www/content-factory-prod/.next/standalone/.env" → 1 ssh cfru "pm2 logs content-factory --lines 300 --nostream | grep -c 'content-item'" → не должно расти (стенд больше не обслуживает прод) ssh cfru "pm2 logs content-factory-prod --lines 300 --nostream | grep -c 'content-item'" → должно появиться В базе: SELECT count(*) FROM render_queue WHERE status='failed' AND updated_at > now() - interval '3 days'; → не должно расти
✓ ПРОВЕРЕНО 21.08, всё чисто. INTERNAL_BASE_URL=http://127.0.0.1:3002 в проде стоит (1). Стенд content-item больше не обслуживает: 0 упоминаний в последних 300 строках лога. Прод обслуживает: 19. В render_queue за трое суток 5 работ, все done, ни одного failed. То есть прод работает своим кодом, а не стендовым.
check
Поддержка не видит присланных файлов
src/lib/support-telegram.ts:99 — при получении фото в переписку пишется только «[прислал файл — смотрите в чате бота]». file_id не сохраняется, картинка не скачивается. Следствие: поддержка работает вслепую. 31.08 клиент прислал два скриншота с описанием проблемы — у нас их нет, посмотреть можно только руками в чате бота. Чинить: сохранять file_id, забирать файл через getFile и класть в хранилище, показывать в переписке. Поле attachment_url в support_messages уже есть.
feature
Завод не объясняет, почему разделов нет
ЖИВОЕ ОБРАЩЕНИЕ 31.08, @il_skl: «смогу ли я в контент заводе указывать цены на товары и заполнять полный бриф? просто при нажатии на эти кнопки меня всегда перебрасывает на вот этот раздел». Прислал два скриншота. ПРИЧИНА НАЙДЕНА, это не поломка. Клиент зарегистрировался в 13:31, через полторы минуты создал завод «Питомник Зеленый Рай» и выбрал тип THREADS, ещё через 17 минут написал в поддержку. У типа threads четыре вкладки: Контент, Стиль, Публикация, Автопубликация. Разделов «Продукт», «Фото товара», «Компания», «Ограничения» — где цены и полный бриф — в этом типе нет; они есть у бизнес-завода, там двенадцать вкладок. Человек жмёт кнопки, попадает в доступные разделы, и это выглядит как переброс. Сменить тип нельзя: factory_category задаётся при создании (POST /api/factory) и в редакторе только читается. Клиенту нужно создать новый завод обычного типа. ЧТО СДЕЛАТЬ: в заводе с урезанным набором вкладок показывать, что разделы про товар и компанию есть у другого типа завода, и как его создать. Сейчас человек через 17 минут после регистрации решает, что сервис сломан, и идёт в поддержку. Отдельно подумать про смену типа завода: сейчас её нет вовсе, и единственный выход — создать завод заново.
feature
🔴 БЕЗОПАСНОСТЬ: денежные функции и запись баланса через открытый REST
03.10.2026: increment_balance и ещё 6 SECURITY DEFINER функций вызываются через /rest/v1/rpc без входа (проверено снаружи, HTTP 200) — начислить любую сумму любому пользователю. Клиент может менять себе profiles.balance/is_admin/тариф, стоимость генерации (возврат на любую сумму), companies.balance. Следов использования за 2 недели нет. Правка готова: /var/www/content-factory/docs/security/2026-10-03-{fix.sql,rollback.sql,nginx-rest-money.conf,proverka.sh}, коммит c9ac0625. Закрыть ДО дня переключения на ядро: perenos-dengi берёт балансы из public.profiles.
✓ Применено 03.10 00:14 по «да» владельца. База: fix.sql от postgres в supabase-db — 7 денежных функций без EXECUTE у PUBLIC/anon/authenticated, service_role сохранён (проверено has_function_privilege). nginx 24contentzavod.ru и test.: PATCH/POST/PUT в profiles, studio_generations, transactions, companies, videos, partner_payouts, promo_code_usage только с 72.56.85.41, 80.90.184.203, 127.0.0.1; бэкапы *.bak-20261003-001350; nginx -t ок, reload. Снаружи запись → 403, чтение как было; сайт и стенд 200; ошибок доступа в журнале прода нет. Откат: docs/security/2026-10-03-rollback.sql + бэкап конфига.
bug
готовS16 · Проверки по сроку2/2

Цель: Отложенные проверки «сработало ли» с командой проверки в detail

↑ Студия: через неделю после выката — ролики не падают пачками и герои нужной внешности
Срок считать от выката починки Студии на прод (если выкатили позже 02.10 — сдвинуть). КОМАНДА ПРОВЕРКИ: ssh cfru "docker exec supabase-db psql -U postgres -d postgres -c \"select model_id, status, count(*), sum((settings->>'provider_retries')::int) retries, count(*) filter (where settings->>'image_url' is not null) with_photo from studio_generations where type='video' and created_at>now()-interval '7 days' group by 1,2\"" Ждём: доля failed у veo-3.1-lite заметно ниже 4 из 14; повторы (retries) есть и после них completed; ролики с фото есть. Глазами: 2–3 свежих ролика без фото — герои славянской внешности, одна сцена без наплывов (ffmpeg тайл кадров как в разборе).
✓ Проверено 10.10.2026 по проду за 8 дней: Veo 3.1 Lite 8 роликов, вышло 7, упал 1 (04.10, длинный английский промт клиента, деньги вернулись, клиентка тут же пересобрала, вышел). Было 4 из 14 упавших. Глазами 2 ролика с людьми: герои славянской внешности, одна сцена без наплывов. Новая беда: если клиент просит русскую надпись в ролике, Veo пишет буквы кашей (ролик 4c6f8fdf, «ПЕИДИСКЫЙ ЩИГЕЖКЫЙ»). Занесено в вопросы доводки ядра (там помощник ведёт себя так же).
check
↑ Безопасность REST: правило nginx не отрезало честные записи (05.10)
03.10 закрыта запись в денежные таблицы через REST снаружи и вызов денежных функций клиентом. КОМАНДА ПРОВЕРКИ: ssh cfru "grep '\" 403 ' /var/log/nginx/access.log | grep /rest/v1/ | awk '{print \$1, \$7}' | sort | uniq -c" — 403 должны быть только от посторонних адресов, НЕ от 72.56.85.41 и 80.90.184.203. И: ssh cfru "pm2 logs content-factory-prod --lines 2000 --nostream | grep -iE 'permission denied|42501' | tail" — пусто. Если есть 403 с адреса сервера — серверный путь ходит иначе, добавить адрес в allow. Ожидаемо ломается: отметка «знакомство пройдено» из браузера, «Отменить выплату» в админке выплат.
✓ 07.10: за 03–07.10 403 на /rest/v1 только PATCH profiles от 4 внешних IP (флажок «знакомство пройдено», ожидаемая поломка); с адресов серверов 72.56.85.41 и 80.90.184.203 — 0 из ~118 тыс. запросов; pm2 content-factory-prod: permission denied / 42501 = 0.
check

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

14.10.2026, 06:05:20 · прод: почта · claude

14.10 починена регистрация по почте на рабочем 24contentzavod.ru. Причина: ящик no-reply@24contentzavod.ru (smtp.timeweb.ru) отвечал 535 Incorrect authentication data, каждая регистрация по почте падала 500 «Error sending confirmation email» (≈17 адресов за 16 дней, 5 за 13.10), приветственные письма не уходили с 31.08. Владелец сбросил пароль в Timeweb; новый вписан в /opt/cf-supabase/.env (GOTRUE_SMTP_PASS через compose), /var/www/content-factory-prod/.env и .next/standalone/.env, стенд /var/www/content-factory (без перезапуска); копии *.bak-20261014-smtp. docker compose up -d --no-deps auth + pm2 restart content-factory-prod. Проверка без новой регистрации: SMTP login OK, /auth/v1/recover на учётку владельца → 200 за 1,2 с (было 500), сайт 200. Очередь писем: 136 из 138 исчерпали 5 попыток и сами не уйдут, 2 письма ушли повторно.

→ Решение владельца: писать ли ~17 людям, не сумевшим зарегистрироваться (адреса из журнала входа). Вписать проверку почты (SMTP login) в гейт ядра и книгу дня переключения: служба входа общая с ядром.

03.10.2026, 00:57:35 · Пайплайны: разбор, сценарии, починка · claude

03.10 00:53 второй выкат прода по «да» владельца: Д-6 «Премиум» в студии картинок 2K (bbfbf205). Проверено: экзамен 3/3, в бандле прода resolution 2K, сайт и вход 200, ошибок в журнале нет.

→ Проверки по сроку 05.10 (правило REST не режет честные записи) и 09.10 (Студия: ролики не падают). Wan 2.7 Pro, grok-video, runway, openai-4o — флаги фото после своих прогонов.

03.10.2026, 00:52:09 · Пайплайны: разбор, сценарии, починка · claude

03.10 ночь по «да» владельца: закрыта дыра в деньгах на проде (fix.sql + nginx, проверено); старый сервис выкачен на прод (eec4be03: фото, утечка замысла, журнал денег, MJ, видео-агент); Д-4 Wan-анимация выкл.; Д-5 MJ — пробный прогон отказ Kie, 5 ₽ вернулись, MJ выкл.; Д-9 Wan 2.7 с фото проверен через kiegen и включён (Pro нет); Д-10 Hailuo сходится с каталогом Kie.

→ Второй выкат прода с Д-6 («Премиум» 2K, 4a708526 + 29364acb) — команду выката не пропустил классификатор, нужно разрешение владельца или его запуск /tmp/build-prod-cf.sh после слияния стенда. Проверка по сроку 05.10 (правило REST) и 09.10 (Студия).

02.10.2026, 20:52:47 · Пайплайны: разбор, сценарии, починка · claude

03.10: на стенде (test/sprint-3-quality, 15e0496e + c497c814, не запушено) — утечка замысла ролика между клиентами (globalThis), фото глоталось «Бюджетом» и t2i-моделями, квадрат Veo → 16:9, поля Kling Turbo/Hailuo/Grok/Qwen по доке, логотип и доли возврата фотосессии, MJ без возврата, СММ-агент списывал без фото, видео-агент с Sora на Veo Lite, журнал трат фотосессии, «Тест генерации» убран. Экзамены 90/90, стенд собран, 6 экранов × 2 размера проверены. НАЙДЕНО НА ПРОДЕ: increment_balance и ещё 6 денежных функций вызываются через /rest/v1/rpc без входа (проверено, HTTP 200); клиент может менять себе balance/is_admin. Следов использования за 2 недели нет. Правка готова в docs/security (c9ac0625), не применена.

→ 1) «Да» владельца → применить docs/security/2026-10-03-fix.sql и nginx-rest-money.conf на 24contentzavod.ru и test., проверка proverka.sh с ПК. 2) «Да» → выкат 15e0496e + c497c814 на прод (сборка в сторону). 3) Решения Д-4…Д-10 в DECISIONS-QUEUE. 4) Проверка по сроку 09.10 (Студия: ролики не падают, герои нужной внешности).

02.10.2026, 04:08:10 · Пайплайны: разбор, сценарии, починка · claude

02.10 04:06 UTC: починка Студии выкачена на прод по «да на прод». Мерж 06b6dcda, сборка в сторону и подмена папки, простой ~2 с. На боевом сайте проверено: фото в простом режиме доходит до генерации, подсказка про фото, честный тариф. Журнал прода чистый (только шум сканера).

→ Проверка по сроку 09.10 (доля упавших роликов, внешность героев, срабатывание автоповтора). Через неделю без проблем — убрать .next/standalone.old-20261002, /var/www/cf-prod-standalone-backup-20261002 и /var/www/content-factory-prod/.next-build (rm -rf — по согласию владельца). Решения Д-1…Д-3 в docs/DECISIONS-QUEUE.md.

02.10.2026, 03:54:17 · Пайплайны: разбор, сценарии, починка · claude

02.10: разбор жалобы «ролики кривые, темнокожие, много ошибок». Студия прода, клиентка vladlenazvorygina: 6 роликов Veo Lite, 4 упали (Kie 500 Internal Error), 2 с темнокожими героями. Причины найдены и починены на стенде: простой режим выбрасывал приложенное фото; нет правила внешности; помощник писал мини-фильм; нет автоповтора сбоя Kie; тариф «Оптимально» обещал 12 с/80 ₽ при 8 с/50 ₽; возврат без защиты от двойного. Попутно: nginx cfru с 01.10 18:17 UTC отдавал 500 на все загрузки — починено chown без перезапуска. Коммиты dece6e5b, 533cd37b (test/sprint-3-quality, запушено).

→ Ждёт «да, на прод» для выката починки Студии (ветка прода fix/impersonate-on-v1.4, мерж test/sprint-3-quality как раньше). Решения в docs/DECISIONS-QUEUE.md: Д-1 тариф «Оптимально», Д-2 банк художественных промтов, Д-3 кто запускает nginx без user. Проверка по сроку 09.10.

30.09.2026, 08:14:59 · ops · claude

Разбор сбоя от Лии 30.09: cfru перезагрузился в 06:27 МСК (обновление ядра 138→142). Проверка публикаций на проде в 06:35 один раз получила 500 (Could not query the database for the schema cache), потому что база ещё запускалась. Все запуски после этого проходят с кодом 200, 27 заводов, ошибок 0. cz-worker 8 раз не достучался до базы по старому адресу, с 9-й попытки подключился сам (сработал docker-hosts-sync, поставленный после аварии 24-25.08). Сайт, вход, REST, auth, storage, cz-core и рендеры проверены, всё отвечает. Мёртвый крон vd-prod-scheduler.sh (VD, старый клиент) убран из crontab по согласию владельца, копия: /root/crontab.backup-2026-09-30-vd.

→ Ждёт «да» владельца: удалить из graphile_worker 5 мёртвых заказов «собрать-заказ» от 28-31.08 (попытки 5/5 исчерпаны). По желанию: чтобы Лия не присылала одиночную ошибку в первые 10 минут после старта сервера.

03.09.2026, 04:22:07 · S13 · claude

Ролик «Ночная тренировка» для Фабрики Брендосс: пустой неоновый спортзал, диван отрабатывает подходы спинкой с полотенцем на ней, на финале одним движением раскладывается в ровную кровать, полотенце сползает, бутылка опрокидывается, табло вспыхивает. Шутка совпадает с главным свойством товара. Снят одним планом в одном помещении, оба опорных кадра с одной точки, речь своя через ElevenLabs, проверена обратной транскрипцией. Карусель «Диваны в разных странах» опубликована в Instagram brendoss1 по команде владельца, YouTube платформа пропустила сама (не принимает карусели картинок). Страница согласования myvisionagency.ru/lab/brendoss-soglasovanie обновлена: в ожидании решения ролик «Ночная тренировка» и карусель «Что внутри дивана».

→ МОЙ ПРОМАХ, записываю чтобы не повторить: диагностика ответа Kie была написана как реальный POST на createTask с промтом test, и она создала настоящую задачу генерации. Сгорела одна генерация 15 секунд Wan (по прайсу завода 180 руб), результат негодный — статичный кадр уже разложенного дивана. Правило: проверять ответ API на чтении (recordInfo по известному номеру), а создание задачи никогда не использовать как пробу. Причина исходного сбоя оказалась разовой: Kie вернул ответ без номера задачи при HTTP 200, обёртка kie() проглотила это и поллинг ушёл крутиться по taskId=undefined. Стоит добавить в обёртку проверку code!==200 и наличия taskId, иначе такие сбои будут висеть до таймаута.

02.09.2026, 12:15:37 · S13 · claude

Ролик «Его станция — твоя комната» опубликован в живые соцсети клиента: YouTube «BRENDOSS мебель» (@brendoss670) и Instagram brendoss1 через Upload-Post, обе записи success, работа переведена в published. Перед публикацией проверил подключения профиля factory_329f630e_divan — обе сети живые, переавторизация не требуется. Upload-Post в этой интеграции не возвращает ссылки на посты, поле published_url пустое у всех публикаций, проверять приходится глазами. Собрана карусель «Диваны в разных странах» на проверенных фактах: японский футон и стенной шкаф осиирэ, корейский ондоль с обогревом через пол вместо мебели, реклайнер 1928 года Кнабуша и Шумейкера с конкурсом на имя La-Z-Boy, и наши хрущёвки с 1956 года, из которых родился диван-кровать. Пятую страну сознательно не добавлял, она была бы наполнителем.

→ НАЙДЕНА ПРИЧИНА 502 «Image fetch failed» в отрисовке карусели: слишком тяжёлый суммарный набор референсов. Три style-референса по 2 МБ плюс фото товара (около 7,4 МБ) валят обложку стабильно, два прогона подряд; с одним референсом 1,3 МБ тот же слайд рисуется за 87 секунд. Ссылки при этом живые, отдают 206 и верный content-type, то есть проблема на фетче у генератора. Правило: один-два лёгких референса, стиль серии держать текстом seriesStyle. Записано в память content-factory-carousel-ref-weight-limit. Отдельно встречается 502 по таймауту генератора на одном слайде, лечится повтором этого слота, деньги возвращаются сами. Индекс памяти MEMORY.md вырос до 31 КБ и перестал влезать в лимит чтения — механическая обрезка ломает смысл строк, нужен разбор руками. Кинематографичный рекламный ролик: владельцу предложены три концепта, ждёт выбора.

31.08.2026, 05:19:25 · S13 · claude

Ещё ролик и карусель для «Фабрики Брендосс». РОЛИК «Его станция — твоя комната»: диван едет в метро как обычный пассажир, сосед засыпает на его спинке, а двери вагона открываются не на станцию, а в тёплую комнату. Снят одним планом и намеренно в ОДНОМ пространстве (вагон) — так у модели нет соблазна склеивать локации. Финальный кадр пришлось перерисовать: в первой версии пассажир тащил диван руками, что ломало шутку про самостоятельного пассажира, в промт добавлен явный запрет «никто не трогает, не несёт, не толкает». КАРУСЕЛЬ «Что внутри дивана»: плотность ППУ и как её прочитать на этикетке (ST 2536, первые две цифры), буквы маркировки ST/EL/HR/HS, змейка, боннель, независимый блок. Факты собраны поиском, не выдуманы: для сиденья хватает 25, для ежедневного сна нужно 30-35, плотный ППУ держит форму 8-12 лет, боннель примерно до 110 кг. Схемы в том же чертёжном языке, что и «Механизмы» — строгая боковая проекция, разрезы, стрелки нагрузки; все шесть вышли механически верными с первого раза, перерисовывать не пришлось.

→ Два наблюдения по надёжности. 1) Скрипты-однодневки из /tmp вычищаются: раннер карусели пропал и прогон упал с MODULE_NOT_FOUND. Это ещё один довод перенести приёмы (чертёжные схемы, ведение клипа двумя кадрами из одной точки) в сам завод, а не держать их в скретчпаде. 2) Роут отрисовки иногда отдаёт 502 «Image fetch failed» на отдельном слайде и корректно возвращает деньги; лечится повторным запуском только этого слота, но в UI такого ретрая нет. Открытое прежнее: тип ткани 304 клиент не подтвердил, лишняя кривая карусель про механизмы (4456618f) ждёт решения снести.

27.08.2026, 01:44:44 · S13 · claude

Переделка двух работ для «Фабрики Брендосс» после разбора от владельца: обе прошлые версии были сделаны правдоподобно, а не правильно. КАРУСЕЛЬ «Механизмы диванов» v2: тексты переписаны на проверенные факты (клик-кляк 7-10 лет и 120-140 кг, убивает незащёлкнутый затвор; у еврокнижки ломаться нечему, срок жизни определяет обивка, ролики лечатся силиконовым спреем раз в полгода; аккордеон тяжелеет и метит пол; дельфин самый нагруженный — рычаги, крепления, люфт; книжка живучая, но усилие и стык). Прошлый текст был набором очевидностей вида «нужен метр перед диваном». Схемы перерисованы: строго боковая проекция вместо изометрии, ДВЕ фазы вместо трёх, обе на одной линии пола, фиксированный ракурс и явный запрет поворачивать диван между фазами — механика на всех шести слайдах вышла верной, перерисовывать не пришлось ни одного. РОЛИК «Он бежал к тебе» v2: снят ОДНИМ непрерывным планом, камера за спинкой дивана как в гоночной игре. Погоня, гигантские руки слева и справа, подворотня, лестница, дверь. Музыка и шумы родные от Wan, три реплики свои (ElevenLabs, голос Антон), дорожка модели приглушена до 0.62, наличие речи подтверждено обратной транскрипцией Whisper.

→ Три приёма, которые пора зашивать в завод, а не собирать руками скриптом. 1) Схемы механики: боковая проекция + две фазы + жёстко зафиксированный ракурс; изометрия с тремя фазами наложением даёт кашу и разные пропорции. 2) Один непрерывный план: оба опорных кадра обязаны быть сняты ИЗ ОДНОЙ ТОЧКИ — при разных ракурсах модель мирит их и разворачивает объект (так диван побежал назад в первом дубле). 3) Речь: Wan даёт русскую речь в кадре с человеком, но не даёт говорящей мебели — там кладём свою озвучку и проверяем обратной транскрипцией, а не на слух. Открытое: тип ткани 304 клиент так и не подтвердил; в заводе лежат две карусели про механизмы, старую кривую (4456618f) предложено снести; владельцу описана следующая карусель «Пять минут у двери» про приёмку дивана у курьера, ждёт решения.

24.08.2026, 04:49:11 · · claude

Разбор жалобы «не работает кнопка войти» на боевом сервисе. Вход оказался исправен, лежал слой данных: 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 работа не двигалась: вся сессия ушла на прод.

19.08.2026, 02:32:04 · S13 · claude

Продакшн для «Фабрики Брендосс», заход в новом креативном регистре: владелец забраковал бытовые идеи и попросил концепты, пробивающие баннерную слепоту. Ролик «Он бежал к тебе»: ночной мультяшно-кинематографичный город, диван удирает на своих ножках от гигантских рук, которые расхватывают чужие диваны, добегает до своей комнаты и раскладывается в кровать. Собран ДВУМЯ клипами Wan 2.7 (8 с погоня + 7 с прибытие) вместо одного пятнадцатисекундного: разные сцены, в одном i2v модель половину действия придумывает сама, а по деньгам одинаково, Wan тарифицируется посекундно. Четыре кадра gpt-image-2 цепочкой image-to-image от фото товара, каждый клип ведётся первым и последним кадром, склейка встык на действии. Карусель «Механизмы диванов»: клик-кляк, еврокнижка, аккордеон, дельфин, выкатной — у каждого не только плюс, но и честный минус (метр пола спереди, два стыка, нагруженный узел, сон почти у пола). Слайды сделаны как дорогие инженерные изометрии с фазами раскладывания, стрелками движения и выносками, палитра серии сохранена. 49 ₽.

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

17.08.2026, 11:06:51 · · claude

Разбор «на проде затёрли выставление счетов» — и нашлось кое-что похуже. 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) стендовые по смыслу.

→ Проверить руками то, что нельзя проверить отсюда: выставить счёт юрлицу из кабинета прода (это боевой банковский счёт, без спроса документ не создаю). Присмотреть за очередью пару дней: теперь она работает своим кодом, а не стендовым — если где-то была зависимость от стенда, она вылезет.

12.08.2026, 03:10:31 · S13 · claude

Ещё один продакшн-заход для завода «Фабрика Брендосс». Ролик «Диван-победитель»: турнир, соперников давят грузами и греют лампой, они оседают, наш 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 проговаривает реплику не всегда — в кадре без людей (говорящая мебель) речи не дал, в кадре с человеком дал обе фразы.

09.08.2026, 16:05:38 · S13 · claude

Продакшн для клиента Оксана Яхина (завод «Фабрика Брендосс») плюс два дефекта пайплайна, найденных по ходу. Вчерашний премиум-ролик «Диван приезжает домой» приехал с пустой дорожкой (-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 и не просит речь) — оба воспроизводимы, в деталях лежат рецепты.

07.08.2026, 14:33:56 · S15 · claude

Собран аудит стабильности с доказательствами из живого прода (docs/STABILITY-AUDIT.md) и закрыты первые зоны: индексы под проверку прав, журнал ошибок служебным ключом, таймауты и повторы для Kie. Появился смоук-прогон на Playwright, встроенный в выкладку: 14 проверок на двух ширинах, красный прогон возвращает сборку. Он сразу нашёл реальный баг с шириной холста. Починены: уезжающие за экран окна (общая причина для 23 окон раздела), гонка с незапущенной отрисовкой, зависимость работы от открытой вкладки, врущий показ хода, пресет-копировальщик, весь план карусели на одном слайде. В поддержке появились отметки доставки. Мобильный Центр пересобран: две строки вместо шести плашек, голосовой ввод, лёгкие превью в списках.

→ Открыто: работа без завода не видна в «Моих работах» (поймано на клиентском контенте); у Ролса нет служебного входа; из аудита ждут атомарное списание, генерации в фон, чистка базы от base64, воркер вместо крона, контроль публикаций. По клиенту Брендосс: карусель из семи слайдов готова и лежит в кабинете, АСМР-ролик забракован владельцем (нарезался на четыре клипа вместо одного пятнадцатисекундного и не показывал товар), переделка по правильной схеме ждёт разрешения на трату.

03.08.2026, 16:31:25 · S13 · claude

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

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

03.08.2026, 14:17:06 · S13 · claude

Разобрана настоящая причина отказов оживления: не кадр и не формат, а длина аудио — 28 секунд провайдер отбивает, 10 перекодированных принимает (падающие задачи бесплатны, поэтому границу искали прогонами). Режем теперь звук по паузам на равные части до 15 секунд, текст при этом цел. Починен звук: amix делил громкость на число дорожек, из-за чего ролик выходил на -36 dB и фон был неразличим; после normalize=0 и loudnorm стало -19.4 dB, владелец подтвердил, что улица слышна. Кадр при описанном движении рисуется планом от колен. Действия над готовой работой сведены в общий компонент и стоят одинаково во всех холстах.

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

03.08.2026, 11:05:11 · S13 · claude

Аватар упрощён до прямого пути: весь текст одной озвучкой, одно оживление, никакой нарезки. Раньше моя же защита от перерасхода резала речь (из четырёх реплик озвучивались две) и плодила швы. Кадр теперь 9:16, а не 3:4. Атмосфера места слышна (0.28 вместо 0.12 плюс срез гула). Подключён словарь произношения. Текст-хук только когда сценарий пишем мы. Отдельно: действия над готовой работой сведены в общий компонент и стоят в одном месте во всех холстах — раньше в карусели были кнопки, в видео и аватаре не было ничего.

→ Прогон владельца на 30 секунд: ожидаем один ролик целиком, все реплики, вертикаль, слышный фон улицы. Дальше — пересборка интерфейса холста единым макетом для пяти форматов.