Для кого: creative ops, Android UI и сборщики ресурсов, которые получают .9.png из Figma, текстурных пайплайнов или плагинов экспорта и хотят одну и ту же бинарную приёмку каждую ночь на удалённом Mac. Цель: мини-CI вокруг ФС — мониторинг каталога с дебаунсом, single-flight на партию, пакетная проверка пикселей «юбки» (строго чёрные маркеры на прозрачном кольце), шаблоны имён по плотности, лимиты байт и диска, классифицированные повторы и JSONL с последующим gzip в холодное хранилище. Геометрию и сетки срезов сверяйте с материалом «матрица: PNG-сетка и соц-срезы на удалённом M4»; оркестрацию повторов и логов — с «мониторинг PNG, повторы и архив логов», пакетные PNG-проверки — с «пакетный PNG QA».
Содержание
Модель watchdog и роль OpenClaw
Watchdog — это не «нейросеть, которая рисует nine-patch», а конечный автомат, привязанный к файловой системе: события шумные (частичные сохранения, двойные записи, синхронизаторы), вы схлопываете их в одну задачу на партию, запускаете детерминированные валидаторы, затем промоутите артефакты или отправляете в карантин. OpenClaw здесь — оркестрационная поверхность: вызывать только инструменты из allowlist с зафиксированными аргументами, пока macOS даёт стабильные пути для launchd, SSH и предсказуемого растра на Apple Silicon. Cron сам по себе промахивается по субминутным всплескам экспорта; связка «watch → дебаунс → очередь» соответствует тому, как дизайнеры реально сохраняют файлы.
Каталоги и правила дебаунса
Корень задачи на NVMe, например ~/nine_jobs/<CAMPAIGN_ID>/, с подпапками inbox, work, out, failed, quarantine, logs, archive. Не вешайте наблюдатель на тома с облачными плейсхолдерами. Рабочие умолчанчики, которые переживают передачу смены:
- Тихое окно: после последней квалифицирующей записи подождите порядка 30–45 секунд, прежде чем переносить партию из
inboxвwork(подстройте под конкретный экспортёр). - Проверка стабильного размера: два одинаковых результата
statс интервалом не меньше ~400 мс до парсинга пикселей. - Single-flight lock: один mutex на
CAMPAIGN_ID; при схлопывании быстрых сохранений пишите в логcoalesced_events. - Игнор-лист:
.DS_Store,*.tmp,*~, нулевые заглушки.
Установку хоста и health Gateway согласуйте с руководством по установке OpenClaw на все платформы, прежде чем полагаться на неинтерактивные вызовы из launchd.
Воспроизводимые шаги (скелет команд)
Замените угловые плейсхолдеры значениями кампании; держите скрипты в git рядом с манифестом навыка OpenClaw, чтобы diff показывал, что реально исполнялось в проде.
- Инициализировать дерево
export NINE_ROOT="${HOME}/nine_jobs/<CAMPAIGN_ID>" mkdir -p "${NINE_ROOT}"/{inbox,work,out,failed,quarantine,logs,archive} - Запустить дебаунс-наблюдатель (паттерн — закрепите реализацию в репозитории):
fswatch -l 2.0 -o "${NINE_ROOT}/inbox" | while read -r _; do "${NINE_ROOT}/bin/debounced_enqueue.sh" done - Слить очередь воркером (отдельный процесс, чтобы лимиты Gateway оставались предсказуемыми):
"${NINE_ROOT}/bin/worker_once.sh" --max-files 32 --trace-id "$(uuidgen)" - Проверить «юбку» для каждого кандидата (ваш скрипт декодирует RGBA и сканирует внешнее кольцо):
python3 "${NINE_ROOT}/bin/validate_patch_skirt.py" \ --path "${NINE_ROOT}/work/<ASSET>.9.png" \ --require-srgb-icc true \ --jsonl-out "${NINE_ROOT}/logs/validate.jsonl" - Переименовать при успехе по студийному шаблону (см. таблицу имён):
mv "${NINE_ROOT}/work/<ASSET>.9.png" \ "${NINE_ROOT}/out/ui__<SLUG>__<DENSITY>.9.png" - Дописать строку аудита (один JSON на строку; ротация по дням):
printf '%s\n' "{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"event\":\"promote\",\"asset\":\"<SLUG>\",\"bytes\":<N>,\"trace_id\":\"<UUID>\"}" \ >> "${NINE_ROOT}/logs/audit-$(date -u +%Y-%m-%d).jsonl" - Заархивировать промоутнутую партию:
tar -czf "${NINE_ROOT}/archive/$(date -u +%Y-%m-%d)_<BATCH_ID>.tar.gz" -C "${NINE_ROOT}/out" .
Политику полей имён для других классов PNG можно выровнять с материалом «автоименование PNG и пакетная валидация».
Таблица порогов приёмки
Используйте как контракт pass/fail между дизайном и сборкой; числа подстраивайте под игру или приложение, но сохраняйте столбцы, чтобы CI мог диффить YAML политики во времени.
| Гейт | Измерение | Пример порога «принято» | При провале |
|---|---|---|---|
| Чистота «юбки» (контурное кольцо) | Внешние 1 px строки/столбцы, сэмплы RGBA | Маркеры строго #000000 непрозрачные; прочие ячейки кольца — alpha=0 |
quarantine/ + класс данных (без слепого повтора) |
| Антиалиасная «пыль» | Любой серый с 0<alpha<255 на кольце |
0 нарушающих пикселей | Класс данных; путь PNG в JSONL |
| Прозрачность углов | Четыре угла кольца | Полностью прозрачны | Класс данных |
| Потолок байт на файл | Размер в ФС | Например mdpi ≤256 KiB; xxhdpi ≤1,5 MiB | Карантин + уведомление |
| Объём партии | Сумма байт текущего dequeue | Например ≤120 MiB на партию | Пауза очереди; ручной resume |
| Водяной знак свободного места | df на томе задачи |
≥15% свободно и ≥25 GiB абсолютный минимум | Глобальная пауза dequeue |
| ICC / цвет | Встроенный профиль | sRGB IEC61966-2.1, кроме подписанного исключения P3 | В playbook ICC или карантин |
Контракт шаблона имён
Предсказуемые имена делают слияния Gradle и ключи CDN скучными — в хорошем смысле. Стандартизируйте машиночитаемые токены и отвергайте «человеческий дрейф» на этапе промоута.
| Токен / шаблон | Смысл | Пример |
|---|---|---|
ui__<slug>__<density>.9.png |
Модуль + slug ресурса + mdpi/hdpi/xhdpi/xxhdpi | ui__hud_frame__xxhdpi.9.png |
<slug>_@<scale>x.9.png |
Альтернативный студийный стиль | hud_frame_@3x.9.png |
sha256 (sidecar) |
Строка манифеста на каждый промоут | manifest.jsonl рядом с out/ |
Классы сбоев, повторы и архив логов
Зеркальте надёжность API внутри воркера:
- Транзиент: файл занят, короткое чтение, нестабильный SMB → экспоненциальный backoff с джиттером, максимум попыток (например пять), каждая попытка дописывает JSONL с
next_eligible_at. - Данные: чистота «юбки», нарушение ICC, несоответствие шаблону имени → без автоматического повтора; перенос в
quarantineсreason_codeи ручной флаг в манифесте для повторной постановки. - Операционные: водяной знак диска, отсутствие окружения Python, 401 Gateway → глобальная пауза dequeue до
resumeпосле исправления; логируйтеpause_reason.
Форма строки (один JSON на попытку): trace_id, batch_id, asset, class, exit_code, duration_ms, stderr_tail, bytes_in, bytes_out. Ротируйте logs/*.jsonl ежедневно; gzip файлы старше ~7 суток в archive/logs/, чтобы не раздувать SSD. Тот же словарь полей удобно держать согласованным с «watchdog экспорта Lottie → PNG», чтобы ops не переучивался между motion и статикой.
Область Gateway (минимальные привилегии)
OpenClaw должен оркестрировать, а не заменять root-shell. Привяжите Gateway к 127.0.0.1, читайте токены из файла с правами только у пользователя воркера, allowlist ~/nine_jobs/<CAMPAIGN_ID>/** и закреплённые в git скрипты валидаторов. Предпочитайте явные записи инструментов вроде «запустить validate_patch_skirt.py с argv из job YAML» вместо произвольных строк shell. Каждый вызов инструмента логируйте с тем же trace_id, что и очередь, для последующего security review.
Контрольный список оператора
- Корень задачи на быстром локальном диске; без синхронизации Desktop/Documents на пути наблюдения.
- Один PID наблюдателя зафиксирован при загрузке; нет дублирующего
fswatchи GUI-синхронизатора на том же дереве. - Включены тихое окно и проверка стабильного размера; правило
.doneили манифеста описано в README. - Версия валидатора «юбки» закреплена в
requirements.txtили lockfile; та же версия в CI и на удалённом Mac. - YAML порогов в git; на
pause_reasonзаведены Grafana или почтовый webhook. - Ротация JSONL + gzip по расписанию
launchd; раз в квартал пробовали восстановление из архива. - Allowlist Gateway пересмотрен при смене путей кампаний.
FAQ
Мы и так смотрим nine-patch в превью — зачем автоматизировать кольцо?
Человек пропускает одиночную серую «пыль», из-за которой padding съезжает на одном экране. Скан после декода повторяем в 02:00 и оставляет квитанцию в JSONL.
OpenClaw даёт 401 из launchd, но не из интерактивной оболочки — почему?
Неинтерактивные сессии часто не видят те же env-файлы или элементы связки ключей. Воспроизведите тем же блоком ssh, что использует CI, проверьте права на путь токена и совпадение HOME с пользователем воркера.
Нужен ли ImageMagick на каждый пиксельный тест?
Используйте тот декодер, которому доверяет ваша сборка Android (часто Pillow или эквивалент с фиксированной версией). ImageMagick допустим, если версии совпадают с CI; важно согласование RGBA после декода, а не самый короткий набор команд в чате.
Можно ли смешать эту очередь с HEIC или Lottie?
Делитесь паттернами логирования и архива, но держите отдельные корни inbox, чтобы геометрические правила nine-patch не наследовали чужие повторы и бюджеты байт.
Итог: задокументируйте дерево, схлопывайте шумный экспорт в single-flight задачи, проверяйте чёрную «юбку» машинными порогами, применяйте шаблоны имён и гейты байт/диск, классифицируйте сбои для осмысленных повторов, а JSONL + gzip трактуйте как бортовой самописец. Когда нужен постоянный воркер на Apple Silicon вместо ночных ноутбуков, откройте аренду и покупку узлов и тарифы на MacPng — вход не требуется для сравнения планов — и инструкцию по SSH / VNC для подключения хоста. Другие материалы по автоматизации PNG — в разделе Технические идеи.
Nine-patch QA и наблюдатели на выделенном удалённом Mac
Уберите приёмку .9.png с ноутбуков дизайнеров, закрепите версии валидаторов на Apple Silicon и делитесь очередью и JSONL в едином runbook между часовыми поясами.