Files
jellybit/openspec/changes/archive/2026-08-06-cancel-dismiss-split-wording/tasks.md
T
av 0b02a8c224 specs: в state-reconciliation разведены Cancel и Dismiss по состояниям
- требование «Ручное закрытие загрузки» приведено к коду: два пути закрытия,
  error_code на каждом, раскладка поверхностей — описательно, а не SHALL
- уборка своего торрента после отмены названа исключением по состоянию, а не
  по команде; убрана ложная гарантия «данных пользователя не касается»
- в docs/review.md записан проскочивший дефект гарда окна после add и новый
  вопрос проходу adversary про асимметрию признака владения
2026-08-06 15:50:41 +03:00

4.9 KiB

1. Спека

  • 1.1 Влить дельту в openspec/specs/state-reconciliation/spec.md (требование «Ручное закрытие загрузки (стоп-кран)» целиком) — делает opsx:archive/opsx:sync, руками спека не правится.
  • 1.2 Прогнать openspec validate --strict cancel-dismiss-split-wording.

2. Код

  • 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. Верификация

  • 3.1 task gate зелёный.
  • 3.2 Ревью изменения (второй чекпоинт) проведено, триаж сохранён в openspec/changes/cancel-dismiss-split-wording/review/.

Рубрика ревью предложения (проход review-rubric, чекпоинт 1)

Свойства, по которым судится требование о пользовательской команде, переводящей сущность в терминальное состояние. Порождены до чтения предмета; здесь стоят приёмочными критериями наравне с A1–A3.

  • R1. Отрицания побочных эффектов сверены с carve-out'ами инвариантов: у каждого «SHALL NOT трогать X» есть либо сценарий, либо ссылка на требование, где X всё-таки трогается.
  • R2. Пол доступности задан перечислением состояний, названо, что бывает при вызове из недопустимого (конфликт или no-op).
  • R3. Идемпотентность повтора определена по каждому пути отдельно, без обобщающего «закрытие».
  • R4. Различимость инициатора зафиксирована литералом; где различение теряется — записано ограничением, а не умолчано.
  • R5. Судьба прежней диагностики названа для обоих путей.
  • R6. Обязательства поверхностей фальсифицируемы: по тексту строится таблица «состояние × поверхность»; круговых формулировок нет.
  • R7. Подтверждение опасного нормировано в теле требования, а не только в сценарии одной поверхности — по фактическому гейту: обособление плюс дополнительный шаг там, где транспорт его поддерживает (чекпоинт 2, D11).
  • R8. Названо, какие штатные команды из полученного терминального состояния отпадают.
  • R9. Конкурентность разрешена правилом «кто первый» (единый сериализующий узел).
  • R10. Допустимость команды переоценивается на момент исполнения, а не по снимку рендера. Не закрыто этим изменением — отдано урожаем: свойство общее для всех команд проекта, дом ему не в этом требовании.
  • R11. Терминальность имеет описанный выход (relink) и согласована со сверкой.
  • R12. Спека фиксирует наблюдаемое, а не внутреннее: косметическая правка UI не делает её ложной.

Критерии приёмки (из постановки docs/tasks/items/dismiss-marker-lost.md)

  • A1. Требование спеки различает Cancel и Dismiss по состояниям и называет error_code для каждого пути закрытия. Оракул: openspec validate --strict.
  • A2. В спеке есть сценарий «пользователь закрывает не-терминальную загрузку из веб-UI» с исходом cancelled и названным error_code. Оракул: тот же прогон.
  • A3. Гейт Dismissable в коде и danger-zone шаблона остаются как есть. Оракул: git diff --stat в отчёте ревью — файлов под internal/ и web/ нет.