2026 OPENCLAW
SKILLS_
SNAPSHOT_
STALE_
RESET.

Абстрактная визуализация оркестрации навыков и автоматизации

Сценарий 2026: пакеты из ClawHub легли в ~/.openclaw/skills/, SKILL.md на диске свежие, а runtime Agent в Telegram/Slack отдаёт старый tool graph. Вы гоняете /new и sessions.reset — в логах Gateway нет строки пересканирования skillsSnapshot, модель ведёт себя как после 429-fallback. Это не «битый npm», а рассинхрон трёх слоёв: (A) in-memory snapshot процесса Gateway, (B) sessions.json с runtimeOverrides, (C) физический каталог skills на том UID, под которым крутится launchd. Ниже — инженерный runbook с метриками, jq-паттернами, матрицей решений и перекрёстными ссылками на invalid config / doctor, fallback → openclaw.json и JSONL bootstrap hang.

1. Механика: почему reset не инвалидирует skillsSnapshot

Слой A — процесс Gateway. При старте строится immutable (до рестарта) снимок: резолвинг SKILL.md, manifest hooks, tool IDs. Ключ кэша часто завязан на стартовый mtime корня skills, а не на каждое сообщение. /new обнуляет conversation buffer и routing key в агенте, но не обязан вызывать skills.scan в том же PID. Симптом: в логе после reset есть session.cleared, но нет пары skills.scan + duration_ms.

Слой B — sessions.json. Поля runtimeOverrides.model, runtimeOverrides.auth (имена условные — смотрите фактический schema вашей сборки) переживают reset, если reset трогает только transcript, а не entry канала. Итог: router видит capability tags нового browser-skill, но endpoint — text-only LLM → skill молча отфильтрован на routing layer без exception в UI.

Слой C — диск и UID. Типичный антипаттерн: skills поставили из интерактивного zsh под $USER, Gateway под launchd с урезанным HOME или другим OPENCLAW_STATE_DIR — на диске «есть», для процесса «нет». Проверка: sudo -u <gateway-user> test -r ~/.openclaw/skills/foo/SKILL.md.

По внутренней выборке MACGPU (≈140 инцидентов Gateway, Q1–Q2 2026) класс «install OK / snapshot stale» — 34 %, реальные ошибки установки — ~11 %. Остальное — config/fail-closed и JSONL.

2. Матрица триажа

СигналПервое действиеЗапрет
find SKILL.md ↑, tool list =PID age + restart --force --wait + probeТолько /new в канале
После reset модель = fallbackjq по runtimeOverrides для channelIdrm sessions.json без .bak
Один channelIdТочечное удаление entryГлобальный truncate
После v2026.5.x всё деградировалоagents в openclaw.json + doctorПараллельно skills + plist
Нужен audit trailЭталонный удалённый Mac, те же 6 шаговПравка prod sessions в пик

3. Три слоя в одном процессе (шпаргалка SRE)

Диск → PID Gateway (skillsSnapshot в RAM) → sessions.json/jsonl. /new бьёт по слою session, не гарантируя инвалидацию слоя A. Правильный порядок: verify disk → jq sessions → restart --force --wait → probe. Обратный порядок = бесконечные reset в Telegram без единой строки skills.scan.

launchd не наследует .zshrc. Установка skills в интерактивном shell при Gateway с урезанным env — классический «файлы есть, процесс слепой». Сравните OPENCLAW_STATE_DIR, HOME, PATH из launchctl print и из login-shell до любого ClawHub install на prod.

Мульти-агент: каталоги ~/.openclaw/agents/<id>/sessions.json независимы; snapshot привязан к конкретному gateway worker, обслуживающем agent id. Ошибка «почистили не тот sessions.json» даёт ложное ощущение, что skillsSnapshot «не лечится».

4. Шестишаговый runbook (операторский)

Шаг 1 — заморозить квадруплет доказательств

openclaw --version, ps -o lstart= -p $(pgrep -f openclaw-gateway), find ~/.openclaw/skills -name SKILL.md | wc -l + shasum -a 256, ключ сессии (channelId/account). В тикет: openclaw status, openclaw gateway status, tail -n 200 gateway.log. Без квадруплета — запрет на параллель «rm sessions + reinstall + plist».

Шаг 2 — верификация source of truth на диске

Сверить OPENCLAW_STATE_DIR в shell vs launchd (launchctl print gui/$UID/…). Remote: rsync -avc skills tree. ClawHub: зафиксировать name@version для diff со строкой scan в логе.

Шаг 3 — хирургия sessions.json

cp sessions.json sessions.json.bak.$(date +%Y%m%d%H%M). Пример удаления override одного канала (подставьте путь):

jq 'del(.channels["telegram:YOUR_CHAT_ID"].runtimeOverrides)' \ ~/.openclaw/agents/main/sessions.json > /tmp/sessions.json && \ mv /tmp/sessions.json ~/.openclaw/agents/main/sessions.json # Поиск всех runtimeOverrides: jq '[paths | select(.[-1]=="runtimeOverrides")] | .[0:20]' \ ~/.openclaw/agents/main/sessions.json

Если sessions.json >2 MiB или channel jsonl >20 MiB — сначала архивация по JSONL-runbook, иначе bootstrap съест окно приёмки.

Шаг 4 — reset + немедленный probe

/new или RPC sessions.reset → сообщение-зонд: «перечисли все tool/skill id». Два провала подряд → шаг 5; третий слепой reset запрещён (порог §7).

Шаг 5 — принудительный рестарт Gateway

openclaw gateway restart --force --wait for i in 1 2 3; do openclaw gateway status || exit 1; sleep 5; done # launchd cold kick (label подставить): # launchctl kickstart -k gui/$(id -u)/ai.openclaw.gateway

Ожидаемая строка лога: scan completed, tool_count=N. Сверить N с find … | wc -l. Во время restart-storm — не трогать openclaw.json (fail-closed).

Шаг 6 — матрица приёмки на удалённом эталоне

Повторить 1–5 на reference Mac; diff tool_count, hash SKILL.md, scan duration_ms. В прод — только после 30 мин стабильного probe и зелёного channels.probe. Closure: PID lstart до/после, фрагмент лога, jq-diff sessions (без PII в открытом тикете).

5. Три технических ворот

Ворота snapshot: |tool_countlog − countfind| = 0, иначе статус «не принято».

Ворота session: первый ответ после reset содержит id нового skill; откат <10 мин → restore .bak, freeze writes.

Ворота environment: diff env (OPENCLAW_*, PATH, NODE) shell vs launchd пустой; hash skills dev ≠ prod → merge запрещён.

6. Кейс: PID 11 суток + runtimeOverrides.model

ClawHub: summarize, browser, calendar — success. Telegram probe: 7 tools. MacBook с той же openclaw.json: 10 tools. Gateway lstart 11 days ago; runtimeOverrides.model = fallback после 429.

До restart --force --wait в логе нет skills.scan. После — scan 312 ms, tool_count 7→10. jq удалил только override группы; окно 30 мин без регрессии. MTTR до runbook: медиана 4,2 ч (n=6); после — 28 мин (n=4). Связка: fallback-статья = config truth; эта = session cache + process snapshot. CPU 100 % без свежих строк — сначала JSONL bootstrap.

7. Observability: что парсить в SIEM

Минимальный набор событий: skills.scan (duration_ms, tool_count, content_hash), session.reset (channelId), gateway.start (pid, lstart). Алерт: uptime_gateway_days >7 AND skills_dir_mtime > gateway_start_mtime → auto-ticket «force restart required». Dashboard: размер sessions.json, count(path ends with runtimeOverrides), размер largest channel jsonl. Снижение ночных эскалаций у заказчиков с дашбордом: оценка 40–55 % (скользящие 90 дней, Q2 2026).

8. Числовые пороги (в change request)

① uptime >7 дней + изменён skills dir → обязателен restart --force --wait. ② >2 неудачных /new на channel → разбор sessions.json. ③ sessions.json >2 MiB или jsonl >20 MiB → архив. ④ приёмка ≥30 мин. ⑤ hash skills эталон ≠ prod → нельзя закрывать «prod updated».

9. Удалённый Mac и MACGPU

Ноутбук скрывает рассинхрон launchd/GUI. Для 7×24 нужен выделенный Apple Silicon с фиксированным plist, тем же runbook и сравнимыми логами до prod. MACGPU — эталонный узел: воспроизвести шесть шагов, приложить diff к заявке на ночной рестарт Gateway.

10. Rollback и мульти-агент

Провал ворот B: остановить supervised Gateway, откатить sessions.json.bak, старт с задокументированной причиной. Повторный clawhub install без restart только засоряет диск и скрывает root cause. В change log пишите: tool_count до/после, lstart PID, hash skills — это проходит ITSM и упрощает разбор инцидентов.

Несколько агентов под ~/.openclaw/agents/*: snapshot обновляется на процесс Gateway, не «на всю машину». Reset в agent A не обновляет tool graph agent B — сверьте openclaw.json → agents перед jq.

Инвалидация кэша (теория): пока не появится официальный RPC «reload skills», единственный детерминированный способ сбросить слой A — новый PID. Watch на skills_dir_mtime > gateway_start_time можно повесить в cron на эталонном Mac; при срабатывании — не reset в Telegram, а gateway restart --force --wait в maintenance window.

11. Ночной чеклист (копировать в тикет)

(1) Квадруплет в первый комментарий. (2) find SKILL.md + shasum prod vs эталон — при diff сначала sync, не /new. (3) jq-путь к runtimeOverrides канала; delete только если поле есть. (4) Ровно один gateway restart --force --wait, 3× status. (5) Probe с именем нового skill из SKILL.md. (6) Таймер 30 мин; регресс → .bak. (7) Closure: tool_count, PID lstart, строки diff sessions. Запрет: третий reset до restart процесса. (8) Если в логе session.cleared без skills.scan — классифицировать как «слой A», не переустанавливать пакеты.

Дополнительно для hardening: вынесите skills deploy в CI job с post-step openclaw gateway restart --wait на staging, затем promote hash на prod — так вы отделяете «доставку файлов» от «инвалидации snapshot». На staging держите тот же launchd label, что на prod; иначе ловите ложноположительные green builds.

12. Диагностика по логам (паттерны grep)

grep -E 'skills\.scan|session\.(reset|cleared)|runtimeOverrides' ~/.openclaw/logs/gateway.log | tail -50 — если после install есть только session.cleared, а skills.scan старше install timestamp, диагноз «слой A». Если skills.scan свежий, но probe не видит tool — копать runtimeOverrides и capability routing (слой B). Если scan свежий и override пуст, но канал один — смотреть jsonl размер и bootstrap (статья 0429). Не смешивать три класса в одном тикете.

Для нагрузочных стендов: после массового deploy skills не полагайтесь на «пользователь сделает /new» — автоматизируйте post-deploy hook с restart --force --wait и assert tool_count в CI. Пороги §8 заведите как unit-тесты на staging (uptime, размер sessions, hash skills). Это снимает 80 % повторных ночных звонков в типичных SaaS-командах, где Bot обновляется еженедельно.

13. Сопоставление с invalid config и fallback

invalid config / fail-closed: процесс не поднимается, doctor ругается на schema — не этот runbook. fallback drift: истина в openclaw.json, sessions вторичны. skillsSnapshot stale (здесь): процесс UP, install OK, tool list/old model после reset — слои A/B. JSONL bootstrap hang: CPU 100 %, логи замирают, размер jsonl огромный — сначала 0429. Таблица эскалации экономит часы: не чинить snapshot, пока Gateway не отвечает на health check.

14. Типовые ложные гипотезы (отбрасывать сразу)

«Переустановить openclaw глобально» — не лечит snapshot, если sessions и PID не тронуты. «Удалить весь ~/.openclaw» — data loss, нарушение retention. «Добавить skill только в workspace репозитория без sync на Gateway-host» — слой C. «Поменять модель в openclaw.json без restart» — может усугубить drift с override в sessions. Правильная гипотеза почти всегда проверяется за 15 минут квадруплетом + одним force restart. Итог для тимлида: rollout skill закрыт только при совпадении tool_count в логе и на диске, новом lstart PID и чистом diff sessions по целевому channelId — иначе инцидент остаётся открытым, даже если ClawHub написал success.

15. FAQ (коротко, по делу)

Только install без restart? На dev иногда; на prod 7×24 — нет.
/new vs sessions.reset? UX vs batch; оба не заменяют force restart процесса.
rm sessions.json? Только с .bak; предпочтительно jq по channelId.
invalid config? Сначала doctor-статья; эта — когда Gateway UP, tools stale.
Linux? systemd вместо launchd; слои A/B/C те же.
ClawHub success, нет SKILL.md? Пакет не попал в scan — проверьте layout каталога.

Если после всех шагов tool_count совпал, но бизнес-логика skill «не срабатывает», переходите к отладке manifest/capability tags (vision, browser, exec) — это уже не skillsSnapshot, а routing policy. Не смешивайте тикеты: один инцидент — один root cause class. На удалённом Mac через MACGPU воспроизведите те же шесть шагов до prod cutover: эталонный лог с skills.scan убеждает команду быстрее, чем спор в чате о «битом OpenClaw».

Пороги из §8 занесите в runbook команды как обязательные поля closure — без них postmortem повторяет те же ошибки через неделю. POST-105: тот же сюжет, три слоя, один force restart.