review.py, Memex делает всё локальное автономно, облако — один компактный проход (≤10 агентов, без картинок), все поверхности — из одного pravki. Сессия Claude систему вызывает, а не переписывает.Ревью ката (cut_review): монтажёр прислал сборку → локальный разбор экранов и речи → один облачный проход → ТЗ и все поверхности. ТЗ из исходников (montage_tz): ката нет — монтажный лист собирается из съёмки по пословным якорям (6.6).
Общее: карточка фильма + профиль канала, одна стейт-машина review.py, транскрипт, рендер графики, телефонный бриф, Memex-раннер. Форматы поверхностей — канон 6.4 (6 слоёв, ОДНА таблица во вкладке, блоки ❌/▶/📋/📍/📚/🎬/💬) — не переизобретаются.
Зачем система: четыре цикла ревью сожгли ≈99 M токенов; 59 % — фан-аут воркфлоу (1 080 агентов, ≈54 k накладных на каждого), аудит экранов гонялся 5 раз (741 агент, 33,5 M), 271 разовый скрипт писался в сессиях. На данных YTUVI02 24 из 26 находок класса «вёрстка» прошли трёх скептиков, хотя по правилу Романа это не ошибки — качество даёт фильтр по классу в коде, а не скептики.
scripts/05_editing/0509_review_cycle/ # код (git); на Memex — rsync-копия с VERSION
├── review.py · proj_config.py · stages/ · cloud/ · montage/ · shared/ · memex/ · geo/ · templates/ · docs/contracts.md
{project}/00_Setup/05_Review/ # всё состояние фильма
├── review_card.json · review_state.json · REVIEW_STATE.md · review_terms.json
├── {CODE}_v1.words.json · {CODE}_review_v6.json (UXP Review-пикер сканирует эту папку)
├── pravki/ (pravki_v2.json — источник истины) · work/v1/ (кадры, OCR, VLM, LLM, пробы, кандидаты, находки)
├── cloud/ (in/ out/ raw/ state.json CALL.txt) · mockups/ · notes/ · logs/
YTs/{CH}/review_profile.json # профиль канала: стиль, каноны, классы ТЗ, чувствительностьРабочих копий инструмента рядом с данными больше нет — так расходились три версии (репо · work/v6 · Memex). Карточка ищется по YTAI_CARD, YTAI_PROJECT_DIR или вверх от текущей папки; внешние id (док, Drive, лист) — только из неё. ⚠️ Фолбэка на прошлый фильм нет, но и отказа нет: при пустом ключе стадия отмечается пройденной с пометкой «пропущена», и круг доходит до конца без вкладки — см. 6.1.
Цепочка не ставит себе зависимости сама. Если чего-то нет, прогон падает на середине, и по сообщению не всегда понятно, чего не хватило. Минимум — такой.
| Что | Зачем и где нужно |
|---|---|
Три окружения Python.venv_transcribe · .venv_vlm · .venv_llm |
расшифровка речи · чтение экранов зрячей моделью · текстовая модель и маршрутизация. Ставятся отдельно друг от друга: модели тянут разные версии библиотек |
| Локальные модели whisper large-v3 · Qwen2.5-VL-7B · Qwen3-8B |
речь · дословное чтение каждого экрана · признаки и доводка строк. Качаются один раз, живут в кеше моделей |
Распознавание текстаvision_ocr_ru |
системный OCR Apple: именно он находит все экранные опечатки. Без него стадия чтения экранов не пройдёт |
ffmpeg | нарезка кадров и работа со звуком |
rclone | скачать кат с Drive и положить туда материалы круга |
node + UXP-панель |
проверочная сборка секвенции. ⚠️ Это останавливающая стадия: без node круг не дойдёт до поверхностей |
chrome-headless-shell |
рендер графики в 4K. Обычный Chrome в headless подвисает — нужен именно shell-сборка |
poppler (pdftoppm, pdftotext) |
постраничная приёмка вкладки по PDF |
| Доступы | Google (док, лист, Drive) и Telegram — для брифа |
--no-doc и --no-drive, либо в
карточку кладутся тестовые id. Иначе первый же добросовестный прогон перезапишет вкладку в живом
документе заказчика — и правки, которых там ещё никто не видел, исчезнут.Кто что делает и почему суждение отдано одному судье — 6.5 Review Stage. Здесь — порядок стадий, их гейты и команды. Автономный прогон на Memex: review.py memex start → nohup + caffeinate + сторож, вехи в Telegram, ноутбук можно выключить. Таблица ниже генерится из кода (review.py docs), поэтому не расходится с тем, что реально выполняется.
| # | стадия | хост | инструмент | гейт |
|---|---|---|---|---|
| 1 | download | memex | rclone из cut_drive напрямую | кат на диске |
| 2 | frames | memex | ffmpeg 1 fps 1080p | кадров ≥ длительность − допуск |
| 3 | static | mac | static_stretches: где кадр не меняется (PIL, 0 токенов) | static_stretches.json |
| 4 | ocr | memex | s2_ocr_hires (Apple Vision, bbox) | селфчек ocr + якоря |
| 5 | transcript | memex | wordrole_transcribe --plain (.venv_transcribe) | words.json |
| 6 | vlm | memex | s3_vlm Qwen2.5-VL-7B | селфчек vlm |
| 7 | llm | memex | s4_llm Qwen3-8B (признаки, не вердикты) | селфчек llm |
| 8 | probe | memex | s3b_probe_vlm: чужие следы, обрезка, zoom-перечит | probes на всех экранах |
| 9 | selfcheck | memex | s5_selfcheck all | ALL OK |
| 10 | route | mac | route_candidates: auto / cloud / drop | candidates.json |
| 11 | cloud | mac | pack → Workflow wf_judge (J≤4, F, V, S) → collect | все пакеты done, покрытие 100 % |
| 12 | apply | mac | s8_apply_audit: классовый фильтр, одна ТЗ на экран | audit_v6.json + pravki |
| 13 | align | mac | align: n-gram кат ↔ план/прошлые версии (card.align_against) | align.json |
| 14 | chapters | mac | chapters_from_plan --apply: главы ката по плану частей (card.chapters_plan) через align; chapter экранов перепомечается | chapters_proposal.json (инверсия → карточка не тронута) |
| 15 | risk | mac | risk_registry (YTCH): ⚠️ на подтверждение фонда, не ⛔ | risk.json |
| 16 | acts | mac | acts_compact Qwen3-8B по актам + проверки структуры (YTCH) | acts_compact.json |
| 17 | sub | mac | sub_from_prev: подглавы прошлого круга → card.sub на ось этого ката (проекция + речь + пауза) | card.sub заполнен (или в карточке нет prev_pravki) |
| 18 | claims | mac | claims_pick: крупные фразы фильма → card.claims (дословно из ката, без чувствительных тем) | claims_pick.json |
| 19 | verdict | mac | 1 облачный агент: вердикт, обязательные правки, структура (YTCH) | verdict.json применён |
| 20 | terms | mac | terms_index | terms_v6.json |
| 21 | format_tz | mac | s10_format_tz + lint | lint_v7.json |
| 22 | polish | mac | s14_polish_local Qwen3-8B по одной строке + guard | длинных строк 0 |
| 23 | sources | mac | s11_apply_sources | — |
| 24 | render | mac | make_infographics_v6 (chrome-headless 4K PNG) | PNG в mockups |
| 25 | review_json | mac | make_review_v6 (ytai-part-v1, 6 слоёв) | {CODE}_review_v6.json |
| 26 | mock | mac | mockbuild_v6.js через partsBuilder | 0 ошибок |
| 27 | previews | mac | s7 + s12 --render + preview_qc_local | qc 0 high |
| 28 | drive | mac | s9_materials_drive + s12 --upload/--apply + ensure_shots | файлы с комментами, все картинки pravki в shots_ids |
| 29 | sheet | mac | tz_sheet | лист обновлён |
| 30 | carry | mac | shared/tz_carry.py: несделанное из прошлого ТЗ → строки вкладки (номера своего круга) | tz_carry.json собран из текущей модели сверки |
| 31 | doc_tz | mac | ensure_shots → doc_tab_tz_v4, 9 колонок с «Говорит»; кадры закрытого фильма — только run --images temp, с Мака (гейт: review.py edits) | вкладка записана |
| 32 | doc_nav | mac | doc_tab_review_v1 (навигатор) | вкладка записана |
| 33 | verify | mac | doc_tab_tz_v4_verify | ALL PASS |
| 34 | doc_qc | mac | doc_pdf_qc (pdftotext/pdfimages/PIL) | 0 high |
| 35 | phone_brief | mac | phone_brief → Telegram | файл ≤1 МБ отправлен |
| 36 | producer_page | mac | producer_page / review_page | HTML |
| 37 | screens_plan | mac | screens_plan: каждому экрану — таймкод, длительность и макет | screens_plan.json, все экраны внутри длины ката |
| 38 | structure | mac | 1 облачный агент: структура/тезисы/графика | montage_plan обновлён |
| 39 | screens_page | mac | screens_page: витрина экранов одним самодостаточным HTML | {CODE}_{cut}_screens.html, ноль внешних адресов |
| 40 | doc_chapters | mac | doc_tab_chapters_v1: вкладка «Главы» — структура текстом, все главы и подглавы, варианты заставки | вкладка записана (кадры — временным доступом) |
| 41 | feedback | mac | feedback_model → 1 облачный агент-сверщик (feedback_call) → вливание; только при card.prev_pravki | feedback.json, ответ сверщика влит |
| 42 | feedback_page | mac | feedback_page: HTML «Обратная связь по кату» продюсеру (в Telegram — отдельной командой) | {CODE}_{cut}_feedback.html |
| 43 | doc_feedback | mac | doc_tab_feedback_v1 (кадры — только run --images temp, с Мака) → doc_tab_feedback_v1_verify | ALL PASS |
| # | стадия | хост | инструмент | гейт |
|---|---|---|---|---|
| 1 | transcript | memex | wordrole_transcribe --plain (.venv_transcribe) | words.json |
| 2 | segment | memex | segment_local Qwen3-8B: тезисы + якоря | segments.json |
| 3 | montage | mac | build_montage по пословным якорям | montage.json |
| 4 | structure | mac | 1 облачный агент: структура/тезисы/графика | montage_plan обновлён |
| 5 | mockups | mac | build_mockups + DOM-QC | PNG 4K |
| 6 | design_review | mac | 1 облачный агент по контактному листу мокапов | design_review.json применён |
| 7 | structure_html | mac | build_structure_html | HTML |
| 8 | standalone | mac | make_standalone (для телефона) | один HTML |
| 9 | phone_brief | mac | phone_brief → Telegram | файл ≤1 МБ отправлен |
chapters) — порядок глав в кате разошёлся с планом частей. Такой прогон карточку не трогает: предложение остаётся в chapters_proposal.json, решает Роман.16 стадий из 43 — останавливающие (download · frames · ocr · transcript · vlm · llm · route · cloud · apply · terms · format_tz · render · review_json · mock · doc_tz · verify): их падение прекращает цепочку. Останавливающих ровно шестнадцать с самого начала, а мягких прибавляется — поэтому сверяйтесь с таблицей выше, а не с этим числом. Остальные мягкие — прогон идёт дальше, а замечание остаётся в логе. Каждая стадия идемпотентна, гейт — по артефактам на диске; review_state.json можно потерять — ничего не переделается. Пауза/стоп — флаги ~/.cache/<project>/PAUSE|STOP, стадии читают их на границе экрана.
Смотреть хвост лога именно этой стадии в 05_Review/logs/ — там причина, а не в
общем выводе. Починив, продолжать не с начала: review.py resume идёт с первой
незакрытой стадии, --from <стадия> — с нужной, --only <стадия> —
ровно одну. Уже сделанное не переделывается: гейты смотрят на артефакты на диске, поэтому даже
потерянный файл состояния не заставляет проходить круг заново.
Сначала снять их: review.py edits читает вкладку и переносит в список
правок — удалённые строки становятся снятыми, дописки сохраняются как его комментарии. Только
после этого пересобирать поверхности: review.py run --from format_tz. Пропустить
этот шаг нельзя — гейт откажется переписывать вкладку, и это защита от молчаливого затирания.
Новый круг живёт в своей подпапке: в карточке меняется cut_version (v2,
v3…), и рабочие файлы прошлого круга остаются нетронутыми. Чтобы сверка с прошлым
кругом заработала, в карточку добавляются прошлый список правок и версия прошлого ката — тогда
на выходе появится «Обратная связь по кату»: что нового и что стало с каждым пунктом прошлого ТЗ.
Номера ТЗ сквозные и не переиспользуются, поэтому «ТЗ-14» в переписке значит одно и то же
в любом круге.
Скилл /review читает ровно шесть файлов и в этом порядке: тикет сессии docs/TICKET_next_session.md (сценарии практики, карта «что менять где», открытые хвосты), README стадии, contracts.md, REVIEW_STATE.md проекта, карточку, профиль канала. Дальше он только вызывает review.py. Первым идёт именно тикет — в нём то, что успело измениться после прошлого круга. Тикет для новой сессии не пишется руками — review.py ticket генерит его из карточки и стейта: запуск в новом чате, факты, состояние стадий, следующий шаг, грабли проекта, «готово, когда».
R=~/YTAI/scripts/05_editing/0509_review_cycle/review.py
python3 $R init --project <path|CODE> --channel YTUVI --mode cut_review --cut gdrive:…/cut.mp4
python3 $R memex --project P push [--with-cut] · start · status · pause · resume · pull
python3 $R run --project P --until route # после pull: маршрутизация
python3 $R cloud --project P judge --print-call # → Workflow({...}) один раз → cloud collect --run <id>
python3 $R resume --project P # apply → … → doc → verify → бриф в TG
python3 $R edits --project P # правки Романа из дока — ДО регенерации вкладок
Workflow({...}) — не команда терминала. Флаг --print-call только печатает готовый вызов; исполняет его сессия Claude Code своим инструментом. Если вы в терминале и сессии нет — этот шаг так не пройти, а стадия cloud останавливающая: круг встанет на ней.Второй путь, без сессии. review.py memex start --autonomous — вся цепочка целиком на Memex, и облачные проходы там выполняет безголовый агент (shared/headless_claude.py). Ноутбук можно закрыть, вехи приходят в Telegram, результат забирается memex pull --all. Без флага --autonomous Memex делает только «глаза» — от скачивания ката до самопроверки — и останавливается перед маршрутизацией.
Гигиена главного потока (нарушение = утечка токенов): кадры и скриншоты только через shared/shot.py (≤1280 px или кроп по bbox), JSON > 50 КБ только через shared/peek.py, никаких разовых скриптов в проекте (баг → правка в репо + memex push), Grep/Glob вместо cat, сессию закрывать status + ticket.
YTs/YTUVI/review_terms_base.json): плашки V3, мини-карты, канон «МЬЯНМА (БИРМА)», confusables, canon_words.Полные схемы — docs/contracts.md в папке стадии.
Опечатки: токен вне словаря (pymorphy3 + каталог + canon_words), три независимых чтения (OCR = VLM = zoom) и найденное исправление из озвучки/каталога → auto; пары Й/И, Ё/Е, Щ/Ш и омоглифы — всегда в облако. Валюта, английский без перевода, дефисы — регексы по канону профиля. Дубли по OCR-сигнатуре, existing_tz по таймкоду. Класс «вёрстка/вкус» не кандидат. На YTUVI02: 61 из 84 старых находок решаются локально, 0 ложных auto, в облако — 24 кандидата.
≤50 экранов и ≤60 кандидатов на пакет: строки OCR с индексами, текст и описание VLM, озвучка ±8 с, локальные сигналы, кандидаты, список существующих ТЗ, канон канала. Кадры не прикладываются намеренно: сомнение в буквах → need_frames, код нарежет кропы. 40-минутный фильм — 4 пакета по ~100 КБ.
Судья J по пакетам (confirm/refute/need_frame/fact_check по кандидатам + новые находки по тексту всех экранов + clean_screens), факт-чек F одним агентом по списку утверждений (WebSearch по авторитетам канала), кропы V одним агентом (≤16 кропов ≤800 px или контактный лист 4×4), скептик S одним агентом на весь список — default real = true, опровержение только с кодом: T вкус · V допустимый вариант · H буквы за головой → «проверить исходник» · C покрыто ТЗ · F факт защитим · D дубль. Агент сначала пишет результат на диск (cloud/out/), потом возвращает — обрыв по лимиту ничего не теряет.
cloud collect собирает out/, журнал воркфлоу, task-output; проверяет покрытие (непокрытые экраны досылаются пакетом J_NNb); сливает в audit_findings.json. Повтор — только pending-пакеты; перед повтором cloud salvage (достаёт результаты упавшего прогона из логов сессии) и cloud cost (таблица прогонов — метрика экономии).
YTCH: локально n-gram выравнивание, стоп-реестр (25 паттернов, ⚠️ на подтверждение фонда), Qwen3-8B по актам + кодовые проверки структуры (фонд не раньше 34-й минуты, тизер не только из бед, последний звук) → 1 агент вердикта. YTEVO: 1 агент структуры + 1 дизайн-ревью по контактному листу (6.6).
Все поверхности собираются из одного pravki, поэтому не расходятся между собой: номер ТЗ — позиция записи в списке, снятая Романом строка исчезает разом везде. Что именно видят Роман и монтажёр, как устроена каждая вкладка и какие у них гейты — 6.3 Review Surfaces; канон кадра и шести слоёв секвенции — 6.4 Review Timeline.
Гейт стоит на двух вкладках из трёх — на ТЗ и на навигаторе: review.py edits перед их регенерацией. Удалённые Романом строки становятся снятыми, его дописки сохраняются; без этого шага пересборка этих двух вкладок отказывается стартовать. Вкладка «Обратная связь по кату» гейта не имеет намеренно — она целиком пересобирается кодом. Лист, папка на Drive, страница продюсера и бриф пересобираются свободно: правки Романа живут во вкладке ТЗ, а не в них.
Приёмка — кодом, а не агентами: doc_pdf_qc проверяет вкладку постранично по PDF (сироты заголовков, подписи под картинками, перечисления, длинные абзацы), preview_qc_local — геометрию и читаемость превью, s14_polish_local доводит строки ТЗ локальной моделью под кодовым стражем. Это заменило 37 облачных агентов.
| стадия | было (агентов / токенов) | стало |
|---|---|---|
| аудит экранов | 233–244 / 6,1–14,8 M | 0 — локально (OCR, VLM, LLM, пробы, маршрутизация) |
| догоняющая верификация | до 264 за 3 прогона / 12,6 M | 0 — pending-пакеты, salvage |
| судья J + факты F + кропы V + скептик S | — | 7 (≤10) / ≈0,7–1,5 M |
| listify · QA дока · QA превью | 65 / ≈6,2 M | 0 — код + локальные модели |
| YTCH: документальный вердикт | 36 / 8,7 M | 1–2 / 0,12–0,25 M |
| YTEVO: ТЗ из исходников | 11 / ≈1 M | 2 / 0,15–0,2 M |
Главный тред: ≤300 k на цикл (пять файлов на старте, кадров 0, скриптов 0). Замер: review.py cloud cost --session <id>.
typo · grammar · fact · currency · language · mismatch · foreign_trace (+ structure у YTCH); вёрстка/вкус/темп не попадают по коду. Целевой размер списка никогда не задаётся.status: rejected = Роман снял строку; повторный s8_apply_audit не перенумеровывает.hard: true).export PATH=/opt/homebrew/bin:$PATH; версия кода на Memex = VERSION, дрейф виден в memex status.html,body{background:transparent}, chrome-headless-shell; стиллы ≤4,8 с; tc на сетке fps из карточки — частоты NTSC считаются точной дробью (29,97 = 30000/1001), иначе к концу фильма набегает сдвиг в кадры; клипы 23.976 интерпретировать в частоту секвенции.route_candidates --eval: 61/84 локально, 0 ложных auto, облачный список 24 на 95 экранов; пробы: вотермарк «唐» (s058) пойман, «ВЫСОКВАЯ» (s031) — три чтения → auto.cloud cost.montage.json = 0 расхождений, 28/28 мокапов побайтно.pull сверяет md5. Внешние поверхности (док, лист, Drive, бриф) прогнаны на тестовых ресурсах: verify ALL PASS, гейт edits сработал; полировка 41 строки ТЗ локальной Qwen3-8B за 78 с.Регрессия перед каждым коммитом: review.py selftest — около минуты, ноль токенов. Проверяет, что весь python и javascript стадии компилируются, скрипты Memex синтаксически целы, карточка проходит проверку, каталог терминов грузится, маршрутизация не даёт ни одного ложного автоподтверждения, проверочная сборка секвенции проходит с нулём ошибок, русский и английский эталоны совпадают байт-в-байт, а в таблицах перевода нет дыр. В конце печатает «ИТОГ OK» либо «ИТОГ: FAIL N». Правило простое: правка кода без прошедшего selftest не уезжает ни в коммит, ни на Memex. ⚠️ Если выход изменился намеренно — скажем, вы поменяли дизайн заставки, и эталон честно разошёлся, — эталон надо переснять, а не игнорировать красный: иначе следующая сессия увидит чужую красноту и не поймёт, своя она или нет.
Тулинг-эталон и история решений — 6.4; исходники метода — docs/contracts.md, README.md стадии.