25 августа 2026

Скил stage-snapshot-writer — выживание после закрытия терминала

Как скил stage-snapshot-writer сохраняет последний видимый оператору ответ на диск после каждого шага пайплайна, чтобы следующая команда могла продолжить работу с точного чекпойнта без повторного чтения истории сессии.

Длинный шаг пайплайна завершается, оператор выполняет /clear, чтобы освободить контекст, и следующей команде нужно знать, где остановилась работа. Без записанного состояния агент вынужден восстанавливать его с нуля. Скил stage-snapshot-writer решает эту задачу с помощью одного файла на задачу, который перезаписывается в конце каждого этапа пайплайна.

Каждая команда /dr-*, выдающая CTA-блок, записывает свой финальный видимый оператору ответ в datarim/snapshots/{TASK-ID}.snapshot.md как последний шаг. Этот файл является основным источником контекста для /dr-next после сброса сессии. Семантика перезаписи означает, что второй вызов для того же этапа всегда создаёт свежий файл — накопления устаревших состояний не происходит.

Содержимое снапшота

Файл состоит из YAML-блока frontmatter и отрендеренной секции summary с CTA. Frontmatter фиксирует идентификатор задачи, название этапа, команду, создавшую снапшот, временну́ю метку, кто его захватил (агент или оператор), рекомендуемую следующую команду и список альтернативных следующих шагов. Ещё два поля отслеживают собственный размер файла в байтах и признак усечения тела.

Жёсткий лимит в 8 192 байта — ключевое ограничение. Если отрендеренные summary и CTA вместе превышают этот предел, тело усекается по лимиту, и добавляется маркер: <!-- snapshot-truncated, full response in session jsonl -->. Полный ответ по-прежнему доступен в JSONL-журнале сессии; снапшот — не единственная запись, лишь быстрый путь.

Параллелизм и контроль безопасности

Перед записью writer получает блокировку на основе mkdir. Таймаут блокировки настраивается через DR_SNAPSHOT_LOCK_TIMEOUT (по умолчанию 60 секунд). Примитив mkdir используется вместо flock, потому что POSIX flock ненадёжен на macOS при монтировании через NFS и SMB.

Три дополнительных контроля закрывают наиболее распространённые сбои при файловых операциях. Path traversal блокируется валидацией идентификатора задачи по паттерну ^[A-Z][A-Z0-9-]+-[0-9]{4,5}$ до построения пути. Shell-инъекция предотвращается чтением тела из файлового аргумента, а не через inline-расширение. Symlink-атаки блокируются удалением любого существующего симлинка по целевому пути до атомарного переименования. Готовый файл снапшота получает chmod 600, директория блокировки — chmod 700.

Аварийное отключение и расположение реализации

Установка DATARIM_DISABLE_SNAPSHOT=1 превращает writer в no-op без изменения исходных файлов. Это удобно при работе в среде, где директория снапшотов находится на read-only монтировании, или при тестировании пайплайна без побочных эффектов.

Реализация находится в scripts/lib/snapshot-writer.sh, конкретно в функции write_stage_snapshot. Единственная точка продюсера — секция Snapshot Emission скила cta-format: writer вызывается не отдельными командами напрямую, только через эту одну точку входа. Сторона потребителя — скил dr-next-snapshot-replay, который читает файл и восстанавливает контекст для возобновляемой команды.

Коды завершения

Writer завершается с кодом 0 при успехе, 1 при ошибке ввода-вывода или ошибке валидации аргументов, 2 при отсутствии обязательного флага и 3 при таймауте блокировки. Таймаут блокировки (код 3), как правило, означает, что другой writer работает для той же задачи — правильная реакция: подождать и повторить попытку, а не перезаписывать блокировку.

Читайте что такое Datarim для понимания места снапшотов в пайплайне, или изучите скил subagent-driven-development, чтобы увидеть, как изолированные агенты используют чекпойнты во время выполнения плана.