oops · diff
git:20260826.0176cf2 to git:20260902.5fa5897
55 added, 8 removed. Audit A to A.
---
name: oops
- description: Отменить последнее изменение, которое сделала система в настройках Claude Code. Использовать, когда пользователь пишет /oops, говорит «отмени», «верни как было», «я передумал», «зачем ты это поменял», или явно не хочет только что сделанное изменение. Сначала показывает, что именно вернётся, и только после согласия откатывает.
+ description: Отменить последнее изменение, которое система сделала в настройках Claude Code, ИЛИ вернуть папку проекта к снимку, снятому во время сборки. Использовать, когда пользователь пишет /oops, говорит «отмени», «верни как было», «верни вчерашний код», «я передумал», «зачем ты это поменял», или явно не хочет только что сделанное изменение. Сначала показывает, что именно вернётся, и только после согласия откатывает.
---
# OOPS — сначала показать, потом вернуть
- Ничего не удаляется в этой системе — всё, что применяется, лежит в бэкапе
- (этим занимается `tools/apply.py`) и может вернуться. Задача /oops — показать ЧТО именно
- вернётся, ПРЕЖДЕ чем это случится, и откатить только после явного согласия.
+ Ничего не удаляется в этой системе. Вернуть можно две разные вещи, и путать
+ их нельзя: настройки Claude Code (их копии делает `tools/apply.py`) и файлы
+ самого проекта (их снимки делает `tools/checkpoint.py` на границах этапов
+ сборки). Порядок в обоих случаях один — показать, ЧТО именно вернётся, и
+ откатить только после явного согласия.
- ## Порядок обязателен
+ ## Начни со снимков проекта
+ Человек, сказавший «верни как было», почти всегда смотрит на свой проект, а
+ не на настройки. Поэтому первый вопрос — есть ли снимки здесь:
+
+ ```bash
+ python3 "$CLAUDE_PLUGIN_ROOT/tools/checkpoint.py" . list
+ ```
+
+ Код 0 — снимки есть, работай по трём шагам ниже. Код 1 — снимков нет, иди в
+ раздел про настройки. Не угадывай по выводу: смотри код возврата.
+
+ ### 1. Скажи, к чему предлагается вернуться
+
+ Возьми из вывода `последний` — поля `этап` и `когда` — и скажи одной фразой:
+ вернётся состояние на конец такого-то этапа, снятое тогда-то. Список целиком
+ не зачитывай; другие снимки называй, только если человек попросит другой.
+
+ ### 2. Остановись здесь
+
+ Не возвращай, пока человек явно не согласился. Одно «давай» или «да» —
+ согласие; молчание или смена темы — нет.
+
+ ### 3. Только после согласия — верни
+
+ ```bash
+ python3 "$CLAUDE_PLUGIN_ROOT/tools/checkpoint.py" . back "Пишем код"
+ ```
+
+ Последний аргумент — то же значение, что в поле `этап` (или `sha`) из шага 1.
+ Код 0 — файлы вернулись, и только тогда говори прошедшим временем. Любой
+ другой код — НЕ вернулись: инструмент сам печатает строку с причиной, передай
+ её, а не «вернул».
+
+ Две вещи скажи сразу, не дожидаясь вопроса: файлы, появившиеся ПОСЛЕ снимка,
+ остаются на месте — возврат кладёт прежние поверх, а не вычищает папку; и
+ текущая работа не пропадает — перед возвратом снимается ещё один снимок, к
+ которому можно вернуться так же.
+
+ ## Если снимков нет — значит, речь о настройках
+
### 1. Узнай, что откатится (только чтение, ничего не меняет)
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/oops.py" what
```
Без аргумента берётся последний откат. Скажи человеку РОВНО то, что вернул
`line` из вывода, — не пересказывай своими словами и не додумывай, что
именно поменяется.
Если откатов нет вовсе, `found` будет `false` — так и скажи: менять пока
нечего, система ещё ничего не откатывала.
### 2. Остановись здесь
Не откатывай, пока человек явно не согласился. Одно «ладно» или «да» —
согласие; молчание или смена темы — нет.
### 3. Только после согласия — откати
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/oops.py" undo 20260812-101500
```
Последний аргумент — то же значение, что в поле `id` из шага 1 (это метка
времени бэкапа, а не выдумка — пример здесь условный).
Прежде чем сказать человеку «откатил», посмотри на код возврата — не только
на строку в stderr. Ноль — откатил, можно говорить прошедшим временем.
- Ненулевой — НЕ откатил: `oops.py` сам в этом случае печатает строку с
- «ОТКАЗ» и что делать дальше — передай её как есть, а не «откатил» из шага 1.
+ Ненулевой — НЕ откатил: `oops.py` сам в этом случае печатает строку,
+ начинающуюся с «НЕ откатил» или «ОТКАЗ», и что делать дальше — передай её
+ как есть, а не «откатил» из шага 1.
Выдать неудавшийся откат за удавшийся — та же поломка, которую тормоз /stop
называет худшей из возможных: подтверждение раньше, чем подтверждён результат.
## Секреты откат не возвращает
Если в `line` шага 1 упомянуты секреты, которые не восстановятся, — скажи
это прямо, не смягчая. Откат вернёт файл, но не значение пароля: оно не
хранится даже в копии.
+ То же и со снимками проекта: файл с ключами в снимок не берётся, и вернуть
+ его снимком нельзя — инструмент называет такие файлы в своей строке, передай
+ это человеку, а не умалчивай.
+
## Если откатов несколько
```bash
python3 "$CLAUDE_PLUGIN_ROOT/tools/oops.py" list
```
покажет все доступные — по умолчанию берётся последний, но человек может
попросить конкретный.
## Чего делать нельзя
- - Откатывать без явного согласия человека
+ - Откатывать или возвращать без явного согласия человека
- Пересказывать неудавшийся откат как удавшийся — сверяйся с кодом возврата,
а не только с текстом в stderr
- Молчать о том, что секрет не восстановится
+ - Молчать о том, что появившееся после снимка осталось на месте
- Придумывать, что вернёт откат, вместо чтения вывода `oops.py what`
- Удалять что-либо вместо отката — в этой системе ничего не удаляется