From 11959e4c851fb4b22370cce39ef1557b0f1bfc05 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 31 Aug 2026 16:22:50 +0300 Subject: [PATCH] docs: #402 spec revision 2 per SPEC-REVIEW-402-r1 User-Visible: no Issue: #402 --- docs/specs/402-confirm-outside-main-branch.md | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/docs/specs/402-confirm-outside-main-branch.md b/docs/specs/402-confirm-outside-main-branch.md index 71f6e6a7..4b8f4e26 100755 --- a/docs/specs/402-confirm-outside-main-branch.md +++ b/docs/specs/402-confirm-outside-main-branch.md @@ -2,7 +2,8 @@ - Issue: https://github.com/Matysh/houseplan-card/issues/402 - Приоритет: P1, bug (регресс против поведения до #32); полный трек — класс A -- Ревизия: 1 (2026-08-31) +- Ревизия: 2 (2026-08-31) — по SPEC-REVIEW-402-r1 (H1: touch/kiosk; M1: причина + исключения соседних подтверждений) ## Сценарий @@ -83,14 +84,48 @@ promiseSettledOrDialogShown: false (ожидание 200 мс) смоки и мутанты. **Не в скоупе**: содержимое и оформление диалога (#32), ревалидация после -`await` у вызывающих (#32), роль `alertdialog` и `aria-describedby` (#406), -`_tapConfirm` и `_vacCalConfirm` — у них своя механика и свои ветки. +`await` у вызывающих (#32), роль `alertdialog` и `aria-describedby` (#406). + +**`_tapConfirm` и `_vacCalConfirm` — не в скоупе, и причина не та, что я +написал в ревизии 1.** Они рендерятся в той же финальной ветке `render()` +(`:11802-11878`), что и `_dangerConfirm`, — «свои ветки» было неверным +утверждением. Настоящих причин две, и обе по существу: + +1. У них **нет промиса**: `_tapConfirm` хранит синхронный `exec()`, который + вызывается прямо из обработчика кнопки, а `_vacCalConfirm` — это + информационный диалог с закрытием по `hp-close`. Ни один вызывающий не + ждёт разрешения, поэтому «висящего промиса» — самого дефекта этой задачи — + у них не бывает. +2. Их точки входа недостижимы из ранних веток: тап по маркеру и калибровка + пылесоса требуют отрисованного плана, то есть той самой основной ветки. + +Из этого следует практическое требование к реализации: при выносе +`hp-confirm` из цепочки **соседние два блока остаются на месте**. Утащить их +за компанию — значит без нужды поменять поведение диалогов, для которых эта +задача ничего не обещает. ## UX Видимых изменений в оформлении нет. Меняется только то, что подтверждение появляется там, где раньше действие молча не работало. +## Touch и kiosk + +`docs/TOUCH-SUPPORT.md` § Safety floor запрещает «best effort» в трёх вещах, +и одна из них — обход подтверждения разрушающего действия. Сейчас на touch +этот пол пробит ровно так же, как на мыши: в ветке онбординга подтверждения +нет вовсе, то есть действие либо не работает, либо (если бы работало) шло бы +без спроса. Задача поднимает пол обратно на всех вводах сразу. + +Поведение по вводам после правки одинаково и специальной работы не требует: +переносится **место рендера** одного и того же компонента `hp-confirm`, +разметка, размеры целей нажатия, поведение scrim и футера (#32 §6.2) не +меняются ни на строку. Kiosk отдельного пути не имеет — он рисуется той же +основной веткой, где подтверждение и так работало. + +Доказательство — AC8: смок из плана прогоняется в touch-эмуляции, то есть +проверяет ветку онбординга не только мышью. + ## Модель данных и миграция Не применимо. @@ -122,6 +157,13 @@ promiseSettledOrDialogShown: false (ожидание 200 мс) остаётся зелёным без правок его утверждений. - **AC7**. Бюджет initial не растёт (правка структурная). Доказательство: `npm run bundle:budget` до и после. +- **AC8**. На touch подтверждение в ветке онбординга работает так же, как + мышью: диалог появляется, тап по «Отмена» резолвит промис `false`, тап по + scrim не проваливается в план. Доказательство: тот же смок в + touch-эмуляции (`hasTouch`), как это делают существующие touch-смоки. +- **AC9**. `_tapConfirm` и `_vacCalConfirm` остались в основной ветке и их + поведение не изменилось. Доказательство: существующие смоки тапа и + калибровки зелёные без правок их утверждений. ## План автотестов @@ -135,6 +177,9 @@ promiseSettledOrDialogShown: false (ожидание 200 мс) решение резолвит промис (AC4). 5. Языковой гейт `warm` → запрос резолвится `false` сразу, `render()` по-прежнему возвращает `noChange` (AC5). +6. Тот же сценарий (1) в touch-эмуляции: диалог появляется, тап по «Отмена» + резолвит `false`, тап по scrim не доходит до плана (AC8). +7. Один `hp-confirm` в DOM — не два (риск двойного рендера ниже). **Мутант** (`scripts/mutation-gate.mjs`):