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 модель = fallback | jq по runtimeOverrides для channelId | rm 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 одного канала (подставьте путь):
Если 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
Ожидаемая строка лога: 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.