OpenSpec: влить дельты htmx-action-swap в спеки, архив change

Sync новых требований в openspec/specs/: web-ui («Действия обновляют
интерфейс на месте») и review («Петлевые действия ревью обновляют экран на
месте»). Change перемещён в changes/archive/2026-07-04-htmx-action-swap.
Конвенция web-ui.md актуализирована: сняты маркеры «будем» по реализованному.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-07-04 14:42:06 +03:00
co-authored by Claude Opus 4.8
parent 2f8e6e3576
commit 576fc4e6c0
9 changed files with 147 additions and 30 deletions
@@ -0,0 +1,57 @@
## ADDED Requirements
### Requirement: Петлевые действия ревью обновляют экран на месте
Петлевые действия распознавания на экране ревью — **Распознать заново** (`rerecognize`) и **Уточнить** (`refine`) — SHALL выполняться htmx-запросом и обновлять тело экрана ревью на месте (partial swap), без полной перезагрузки страницы и без сброса позиции прокрутки. Поскольку эти действия асинхронны (переводят загрузку в `recognizing`, распознавание доделывает воркер), своп SHALL отражать актуальное состояние — состояние `recognizing` с индикацией «идёт распознавание», а не мгновенно готовый план. Накопленные подсказки и ручные override MUST переживать перераспознавание. Это согласуется с уже действующим частичным свопом при смене выбранного источника (см. «Единый список источников совпадения на ревью»).
Пока загрузка в `recognizing`, экран ревью SHALL сам обновляться поллингом
htmx-фрагмента (`GET /fragments/downloads/{id}/review`) и по завершении
распознавания SHALL автоматически смениться на готовый план (список источников,
инфо и предпросмотр активного источника), без ручного обновления страницы. Как
только состояние вышло из `recognizing`, фрагмент SHALL возвращаться без
поллера, и опрос прекращается. Без htmx экран SHALL деградировать до ручной
ссылки «Обновить».
Выходы из ревью, после которых загрузка покидает `review`**Применить**
(`apply` → раскладка/`done`), **Позже** (`defer``deferred`) и **Отклонить**
(`cancel``cancelled`), — НЕ обязаны свопить экран на месте и MAY уводить с
экрана ревью навигацией (редирект/`HX-Redirect`), поскольку загрузка перестаёт
быть предметом этого экрана.
Поведение петлевых действий MUST деградировать без htmx: без заголовка
`HX-Request` обработчик SHALL исполнять то же доменное действие и отвечать
редиректом на `/review/{id}`, как раньше.
#### Scenario: Перераспознавание свопит экран в состояние recognizing
- **GIVEN** загрузка в `review`, экран ревью открыт
- **WHEN** пользователь нажимает «Распознать заново» или «Уточнить» с подсказкой
(htmx активен)
- **THEN** тело экрана ревью обновляется на месте в состояние `recognizing` с
индикацией «идёт распознавание», без полной перезагрузки и без прыжка
прокрутки наверх
- **AND** накопленные подсказки и ручные override сохраняются
#### Scenario: Экран сам обновляется до готового плана
- **GIVEN** экран ревью показывает состояние `recognizing` после петлевого
действия
- **WHEN** воркер завершает распознавание и загрузка снова в `review`
- **THEN** экран автоматически (поллингом фрагмента) сменяется на готовый план
(источники, инфо, предпросмотр), без ручного обновления
- **AND** после выхода из `recognizing` фрагмент возвращается без поллера и опрос
прекращается
#### Scenario: Выход из ревью уводит с экрана
- **GIVEN** загрузка в `review` с готовым превью
- **WHEN** пользователь нажимает «Применить», «Позже» или «Отклонить»
- **THEN** загрузка покидает `review` (соответственно `done`/`deferred`/
`cancelled`), а интерфейс уводит пользователя с экрана ревью навигацией
#### Scenario: Деградация петлевого действия без htmx
- **WHEN** «Распознать заново» или «Уточнить» приходит POST-запросом без
заголовка `HX-Request`
- **THEN** обработчик исполняет то же доменное действие и отвечает редиректом на
`/review/{id}`, поведение без JavaScript не ломается