## 1. Спека - [x] 1.1 Влить дельту в `openspec/specs/state-reconciliation/spec.md` (требование «Ручное закрытие загрузки (стоп-кран)» целиком) — делает `opsx:archive`/`opsx:sync`, руками спека не правится. - [x] 1.2 Прогнать `openspec validate --strict cancel-dismiss-split-wording`. ## 2. Код - [x] 2.1 Правок нет и быть не должно: `internal/httpapi/download.go`, `web/templates/partials/download_main.html`, `internal/tgbot/render.go`, `internal/worker/worker.go` — только чтение. Проверка — пустой `git diff --stat` под `internal/` и `web/`. ## 3. Верификация - [x] 3.1 `task gate` зелёный. - [x] 3.2 Ревью изменения (второй чекпоинт) проведено, триаж сохранён в `openspec/changes/cancel-dismiss-split-wording/review/`. ## Рубрика ревью предложения (проход `review-rubric`, чекпоинт 1) Свойства, по которым судится требование о пользовательской команде, переводящей сущность в терминальное состояние. Порождены до чтения предмета; здесь стоят приёмочными критериями наравне с A1–A3. - [x] R1. Отрицания побочных эффектов сверены с carve-out'ами инвариантов: у каждого «SHALL NOT трогать X» есть либо сценарий, либо ссылка на требование, где X всё-таки трогается. - [x] R2. Пол доступности задан перечислением состояний, названо, что бывает при вызове из недопустимого (конфликт или no-op). - [x] R3. Идемпотентность повтора определена **по каждому пути отдельно**, без обобщающего «закрытие». - [x] R4. Различимость инициатора зафиксирована литералом; где различение теряется — записано ограничением, а не умолчано. - [x] R5. Судьба прежней диагностики названа для обоих путей. - [x] R6. Обязательства поверхностей фальсифицируемы: по тексту строится таблица «состояние × поверхность»; круговых формулировок нет. - [x] R7. Подтверждение опасного нормировано в теле требования, а не только в сценарии одной поверхности — **по фактическому гейту**: обособление плюс дополнительный шаг там, где транспорт его поддерживает (чекпоинт 2, D11). - [x] R8. Названо, какие штатные команды из полученного терминального состояния отпадают. - [x] R9. Конкурентность разрешена правилом «кто первый» (единый сериализующий узел). - [ ] R10. Допустимость команды переоценивается на момент исполнения, а не по снимку рендера. **Не закрыто этим изменением** — отдано урожаем: свойство общее для всех команд проекта, дом ему не в этом требовании. - [x] R11. Терминальность имеет описанный выход (relink) и согласована со сверкой. - [x] R12. Спека фиксирует наблюдаемое, а не внутреннее: косметическая правка UI не делает её ложной. ## Критерии приёмки (из постановки `docs/tasks/items/dismiss-marker-lost.md`) - [x] A1. Требование спеки различает `Cancel` и `Dismiss` по состояниям и называет `error_code` для каждого пути закрытия. **Оракул:** `openspec validate --strict`. - [x] A2. В спеке есть сценарий «пользователь закрывает не-терминальную загрузку из веб-UI» с исходом `cancelled` и названным `error_code`. **Оракул:** тот же прогон. - [x] A3. Гейт `Dismissable` в коде и danger-zone шаблона остаются как есть. **Оракул:** `git diff --stat` в отчёте ревью — файлов под `internal/` и `web/` нет.