From d65b9e39d5e6dde0158d733f45cc9b2e299d310e Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sat, 26 Sep 2026 07:35:07 +0000 Subject: [PATCH] docs: review document for #660 Issue: #660 User-Visible: no --- docs/reviews/INDEX.md | 3 +- docs/reviews/SPEC-REVIEW-660-r2.md | 318 +++++++++++++++++++++++++++++ 2 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 docs/reviews/SPEC-REVIEW-660-r2.md diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index b6a3d775..200a9ab5 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,10 +1,11 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1075, issue: 380. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1076, issue: 380. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| | #660 | [SPEC-REVIEW-660-r1.md](SPEC-REVIEW-660-r1.md) | spec · r1 | 🔴 красный | 2 | 1 | Раздел ## ТЗ в теле issue отсутствует целиком; Изменение прямо противоречит двум местам; AC «расстояние уменьшено ровно вдвое» не | `docs/process/AUTHOR.md` `REVIEWER.md` `test/core-file-budget.test.mjs` `scripts/smoke-select.mjs` `demo/helpers/hp-test.mjs` `docs/UX-MODES.md` `docs/reviews/SPEC-REVIEW-647-r1.md` | +| #660 | [SPEC-REVIEW-660-r2.md](SPEC-REVIEW-660-r2.md) | spec · r2 | 🔴 красный | 1 | 0 | Скоуп п.3 переносит крестик внутрь .modes, но .modes | `src/styles/chrome.styles.ts` `src/houseplan-card.ts` `docs/USER-GUIDE.ru.md` `docs/UX-MODES.md` `src/houseplan-editor-runtime.ts` `src/header-menu.ts` `smoke_mobile_view_header.mjs` | | #657 | [CODE-REVIEW-657-r1.md](CODE-REVIEW-657-r1.md) | code · r1 | 🔴 красный | 1 | 0 | после fast-forward слияния (dev не двигался за время ревью) docs/reviews/INDEX.md остаё… | `docs/reviews/INDEX.md` `test/reviews-index.test.mjs` `_process.yml` `merge-candidate.mjs` `test/merge-candidate.test.mjs` `scripts/reviews-index.mjs` | | #657 | [CODE-REVIEW-657-r2.md](CODE-REVIEW-657-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | из r1 — проверка закрытия | `scripts/merge-candidate.mjs` `PROCESS.md` `mutation-registry.mjs` `INDEX.md` | | #656 | [CODE-REVIEW-656-r1.md](CODE-REVIEW-656-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | diff --git a/docs/reviews/SPEC-REVIEW-660-r2.md b/docs/reviews/SPEC-REVIEW-660-r2.md new file mode 100644 index 00000000..fa7e74c0 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-660-r2.md @@ -0,0 +1,318 @@ +# SPEC-REVIEW-660-r2 + +- **Issue:** https://github.com/Matysh/houseplan-card/issues/660 +- **Этап:** `S4-spec-review` (ревью ТЗ, PROCESS.md §2.4) +- **Трек:** полный (не пересматривался в r2, обоснование не менялось — см. «Унаследовано + из r1») +- **Материал:** тело issue #660 в редакции r2 (`updated_at: 2026-09-26T07:25:23Z`, + `body` длиной 16919 символов) — исходная постановка владельца + раздел `## ТЗ`, + добавленный автором после SPEC-REVIEW-660-r1 (комментарий «ТЗ переработано после + SPEC-REVIEW-660-r1», `2026-09-26T07:25:21Z`); таймлайн меток: вердикт r1 + (07:22:39) → `S4-spec-review` снята, `S3-spec` выставлена (07:23:18) → комментарий + автора о переработке (07:25:21) → `S3-spec` снята, `S4-spec-review` выставлена + (07:25:23). Отдельного события `edited` API timeline не отдаёт (не отдавал и для + r1) — тело сверено напрямую: в r1 раздела `## ТЗ` не было ни строки (см. + SPEC-REVIEW-660-r1), сейчас он присутствует целиком. +- **Заход:** r2 · блокирующих циклов израсходовано 1 из 4 (полный трек, лимит 4) +- **Роль:** ревьюер ТЗ (не автор) + +## Скоуп ревью + +Задача не изменилась с r1: полировка шапки главной панели после #647 — (1) +inline-кнопки сводной панели остаются активными во всех трёх редакторах на +ширинах >480 px; (2) расстояние между блоком редакторов и блоком зума уменьшается +вдвое; (3) резерв под крестик закрытия переезжает внутрь общей подложки блока +редакторов; (4) `Esc` получает единый терминальный выход в View из Plan и Devices. + +Проверялось: закрыты ли три находки SPEC-REVIEW-660-r1 (High-1 — отсутствие +раздела `## ТЗ`; High-2 — противоречие с `docs/UX-MODES.md`; Medium-1 — отсутствие +допуска/целевых значений расстояния); полнота обязательных разделов §7.1 нового +текста; однозначность и проверяемость каждого AC вместе со способом доказательства +(§2.5 DoR); техническая реализуемость новых пунктов Скоупа по коду «как есть», +а не только по формулировке; согласие с `docs/SCOPE.md` и каноном подсистемы. + +**Дельта не локальна.** r1 установил, что раздел `## ТЗ` отсутствовал целиком; r2 +дописывает его впервые полностью — объём новой дельты сопоставим с самой задачей +(PROCESS.md §2.10: «разбор остаётся полным, если... объём сопоставим с задачей»). +Поэтому ниже — полный разбор нового раздела `## ТЗ`, а не только сверка трёх +находок r1 построчно (хотя она тоже сделана — см. «Закрытие раунда r1»). + +## Как проверялось + +1. Прочитаны PROCESS.md §2.4, §2.5, §2.10, §4, §7.1, §7.2, `docs/process/REVIEWER.md` + целиком. +2. Прочитано текущее тело issue #660 целиком (`gh issue view 660 --json body`, + доступ к MCP `get_issue`/`get_issue_comments` был запрещён средой — использован + `gh` CLI напрямую) и все 4 комментария (`gh issue view 660 --comments`): + «Аналитика», ответ владельца Q1/Q2, вердикт r1, финальный комментарий автора + «ТЗ переработано после SPEC-REVIEW-660-r1». +3. Сверена история меток issue (`gh api .../timeline`) — порядок событий + red-вердикт → `S3-spec` → комментарий автора → `S4-spec-review` подтверждён (см. + «Материал» выше). +4. Прочитан `docs/reviews/SPEC-REVIEW-660-r1.md` целиком — три находки (High-1, + High-2, Medium-1) сверены построчно с новым текстом (раздел «Закрытие раунда + r1» ниже). +5. Прочитан `docs/UX-MODES.md` целиком (строки 1-140) — сверены обе цитаты, + которые High-2 называл противоречащими (57-61, 116-125), и новый текст AC10 / + Скоуп п.7, который их должен заменить. +6. Прочитан код, который новый раздел `## ТЗ` описывает как основу реализации: + - `src/houseplan-card.ts:10805-10824` — текущая разметка `.modes` / + `.editor-close-slot` (сосед `.modes`, не потомок) / `.spacer` / `.zoomctl`; + - `src/houseplan-card.ts:2825-2995` (`_onKey`) — три ветки `Esc` (Decor уже + терминальна, Devices и Plan — нет), подтверждает feasibility Скоуп п.6 и + AC7/AC8; + - `src/summary-panel-runtime-loaded.ts:190-286` (`renderControls`, + `menuItems`) — подтверждает, что раздел `.summary-control` уже скрывается + **CSS-ом**, а не JS-гвардом по ширине (см. находку ниже — это единственное + техническое место, где новый текст ТЗ разошёлся с реальной архитектурой); + - `src/header-menu.ts` целиком — состав `headerMenuItems()`, подтверждает Q2; + - `src/houseplan-editor-runtime.ts:916-946` (`_setMode`) — повторный клик по + активному пункту меню редактора не переключает в View (`if (this.host._mode + === mode) { ...; return; }`) — проверка того, что на телефоне единственный + путь выйти из Plan/Devices без физической клавиши `Esc` — крестик в шапке; + - `src/styles/chrome.styles.ts:150-262, 280-282` — все media-запросы, + участвующие в шапке (`max-width: 480px`, `max-width: 720px`), включая + правило `.head > .zoomctl, .head > .editor-close-slot { flex: none }`. +7. Прочитан `docs/USER-GUIDE.ru.md:247-290` («Шапка на телефоне», «Сводная + панель») и `docs/USER-GUIDE.md:225-260` (тот же раздел на английском) — + Release-артефакты ТЗ требуют явно проверить эти файлы на предмет описаний + старой позиции крестика. +8. Проверено i18n: `title.close_editor` существует в `src/i18n/{en,ru}.json:585` + без изменений — заявление «новых строк нет» подтверждено. +9. Проверено, что продуктового кода для #660 в диапазоне `origin/dev...HEAD` нет + (`git diff origin/dev...HEAD --stat` пуст) — гейты сознательно не гонялись, + этап `spec`. + +## Находки + +### High-1 (в скоупе). Скоуп п.3 переносит крестик внутрь `.modes`, но `.modes` +скрыт (`display:none`) на ширинах ≤480 px — перенос убирает крестик из шапки +телефона, где он сейчас виден независимо от `.modes`, и делает недоказуемым +собственный AC9, а на телефоне без физической клавиатуры — блокирует выход из +Plan/Devices вообще + +**Файл:** тело issue #660, раздел `## ТЗ` → Скоуп п.3 и AC4/AC9; +`src/styles/chrome.styles.ts:150-153` (`@media (max-width: 480px) { ... .head > +.title, .head > .modes, .head > .spacer, .head > .header-action, .head > +.summary-control { display: none; } ... }`) и `:166` (`.head > .zoomctl, .head > +.editor-close-slot { flex: none; }` — обратите внимание, это отдельное от +`.modes` правило, `.editor-close-slot` в него не входит и остаётся видимым); +`src/houseplan-card.ts:10812-10824` (текущая разметка: `.editor-close-slot` — +``-сосед `.modes`, а не её потомок); `docs/USER-GUIDE.ru.md:277` («В +редакторе крестик закрытия остаётся в строке» — именно про телефонную шапку, +раздел «Шапка на телефоне»); `docs/UX-MODES.md:17-20` («space tabs..., the zoom +cluster, one gear and — for an admin — the editor X slot of #647» — крестик +перечислен как отдельный от сегментированного контрола элемент шапки телефона, +которого на телефоне вообще нет, см. строки 31-38: сегментированный контрол — +desktop-виджет). + +**Что не так.** На ширине ≤480 px CSS-медиазапрос прячет `.modes` целиком +(`display: none`), но НЕ прячет `.editor-close-slot` — это два разных селектора, +`.editor-close-slot` сегодня физический сосед `.modes` в разметке, поэтому его +видимость не зависит от видимости `.modes`. Это и есть тот механизм, которым +сегодня работает описанное в `docs/USER-GUIDE.ru.md:277` поведение: «в редакторе +крестик закрытия остаётся в строке» на телефоне, хотя сама сегментированная +группа режимов на телефоне вообще не рендерится в этом смысле (телефонная шапка +— вкладки пространств, зум, шестерёнка и отдельно крестик, по +`docs/UX-MODES.md:17-20`; сами редакторы там открываются из меню шестерёнки, а не +через `.modetab`). + +Скоуп п.3 без каких-либо оговорок по ширине требует: «Переместить единственный +фиксированный 24 px слот крестика внутрь `.modes`». Если слот становится +потомком `.modes`, он подчиняется тому же `display: none` на ≤480 px и **исчезает +из телефонной шапки целиком** — CSS не даёt способа выборочно показать потомка +элемента с `display: none` на родителе. Это не гипотеза: правило `.modes` не +запрещает read её как «ничего в её пределах не занимает места и не видно», +таково поведение `display: none` в CSS без исключений для потомков. + +Последствия по коду, не по домыслу: + +1. **AC9 недоказуем как написан.** AC9 буквально требует: «на 390/481/620 px нет + ... потери доступа к закрытию редактора». 390 px — это ширина внутри + телефонного брейкпоинта (≤480). План автотестов обещает именно такую проверку + («mobile/layout smoke проверяет ... доступность zoom/menu/close на + 390/481/620»). При буквальной реализации Скоуп п.3 эта проверка на 390 px + обязана упасть — не потому, что смок неверный, а потому что доступ к закрытию + в этой точке ширины реально теряется. +2. **Это не «менее удобно», а тупик для touch-only админа.** Проверено + `src/houseplan-editor-runtime.ts:916-935`: повторный клик по тому же пункту + меню («Редактор плана» и т.п.), когда он уже активен, — no-op + (`if (this.host._mode === mode) { ...; return; }`, соответствует «re-clicking + the active tab does nothing» из `docs/UX-MODES.md:49`). В `headerMenuItems()` + (`src/header-menu.ts:62-77`) нет отдельного пункта «Вернуться в просмотр». `Esc` + — клавиатурное событие, недоступное чисто touch-пользователю телефона. Значит + сегодня единственный способ выйти из Plan/Devices на телефоне — тап по + `.editor-close-slot` в шапке. Если он пропадает вместе с `.modes`, + администратор с телефоном без клавиатуры физически не может закрыть Plan или + Devices после входа в них — полная потеря функциональности, не деградация. +3. **Ничего в ТЗ этого не решает.** «Не-скоуп» явно исключает «Изменение + мобильного меню» — но восстановление видимости крестика на ≤480 px требует + трогать CSS-структуру телефонной шапки (сам медиазапрос `.modes`/родственные + правила), а это прямо соседствует с исключённой поверхностью и нигде не + выделено как разрешённое исключение. «Принято предположительно» перечисляет + технические детали для desktop-раскладки (один DOM-слот, CSS-переменная + размера, spacer), но не содержит ни слова про сохранение видимости слота на + ≤480 px. «Риски» называют overflow на узких ширинах как риск, но не называют + риск потери доступа к закрытию — хотя для него уже есть готовая AC (AC9), + которая от этого и должна защищать. + +Это не редакционная придирка: пункт Скоупа буквально противоречит собственному AC +того же документа и документированному поведению `docs/USER-GUIDE.ru.md`, и +разрешение противоречия («крестик остаётся отдельным элементом на ≤480 px» либо +«медиазапрос `.modes` переписывается, чтобы прятать только `.modetab`, но не +вложенный крестик») — продуктово наблюдаемая деталь (это ровно то, что видит +пользователь телефона), а не техническая, которую агенты «решают сами» по §7.1. + +**Как закрыть.** В Скоуп п.3 явно оговорить поведение на ≤480 px: либо крестик +остаётся физическим соседом `.modes` в разметке на этой ширине (тогда +формулировка «переместить... внутрь `.modes`» ограничивается шириной >480 px и +это должно быть написано прямо), либо медиазапрос телефонной шапки переписывается +так, чтобы прятать только `.modetab`-кнопки, сохраняя видимость и позицию +крестика, — в этом случае это нужно явно внести в Скоуп и снять как исключение +из «Не-скоуп: изменение мобильного меню» (шапка ≠ меню шестерёнки, но +формулировка сейчас этого не разделяет). Добавить в AC9 или отдельным AC явное +требование: на ≤480 px в открытом редакторе крестик остаётся видимым, кликабельным +и в неизменной позиции шапки, как до #660. Указать способ доказательства (тот же +`smoke_mobile_view_header.mjs`, расширенный сценарием «admin входит в Plan/Devices +на 390 px, крестик виден и кликабелен»). + +## Что проверено и корректно + +- **High-1 из r1 закрыт содержательно.** Раздел `## ТЗ` теперь содержит все + обязательные части §7.1: Сценарий, Что человек увидит до/после (явная пара), + Проблема по коду (с конкретными строками/методами), Скоуп, Не-скоуп, Контракт + поведения (AC1…AC10), UX/i18n/модель данных, таблица «AC · чем доказан · чем + краснеет» — все 10 строк заполнены с конкретным механизмом и мутантом, План + автотестов со ссылками на существующие файлы (`demo/smoke_editor_tabs.mjs`, + `demo/smoke_mobile_view_header.mjs`, `scripts/mutation-registry.mjs`), Риски, + Откат, Release-артефакты, «Принято предположительно». Структурно соответствует + образцу #647. +- **High-2 из r1 закрыт содержательно.** Скоуп п.7, AC10 и Release-артефакты + прямо называют обе фразы `docs/UX-MODES.md`, которые нужно заменить («outside + the editors», «all summary surfaces disappear»), без домысливания + формулировки замены — только контракт, который она обязана передать. +- **Medium-1 из r1 закрыт содержательно.** AC3 задаёт измеримые целевые значения + (50 ±1 px на 768/1000/1200/1400, 40.5 ±1 px на 481/620) вместо «вдвое без + чисел»; допуск назван явно, в духе AC соседних задач. +- **Архитектурная состоятельность AC1/AC2 (desktop/mobile split summary + controls) подтверждена по коду.** Вопреки формулировке «Проблема по коду» + («...хотя desktop-вызов уже остаётся в шапке»), проверка `renderControls()` + (`src/summary-panel-runtime-loaded.ts:262-263`) показала: вызов кнопок в шапке + безусловен по ширине уже сегодня, а деление desktop/mobile целиком на стороне + CSS-класса `.summary-control` (`chrome.styles.ts:152-153`), не JS. Значит для + AC1 достаточно снять guard `host._mode !== 'view'` в `renderControls()` — + никакой новой width-detection логики не требуется, техническая реализуемость + этой части ТЗ выше, чем предполагает её собственный текст. +- **AC7/AC8 (терминальный `Esc`) реализуемы буквально как описано.** Три ветки + `_onKey` (`src/houseplan-card.ts:2825-2995`) действительно последовательно + `return`-ят после каждой внутренней отмены; Decor уже заканчивается + `_setMode('view')`; добавление того же терминального шага в конце веток Devices + и Plan механически укладывается в существующую структуру, двойного действия по + архитектуре не возникает. +- **i18n-заявление подтверждено.** `title.close_editor` существует в + `src/i18n/en.json:585` и `src/i18n/ru.json:585` без изменений, новых ключей ТЗ + не заявляет и не требует. +- **Q1/Q2 не переинтерпретированы.** Текст «Принятые решения владельца» дословно + совпадает с ответами владельца из комментария (сверено посимвольно), Скоуп п.1 + и п.2 отражают именно Default/Альтернативу, без расширения. +- **Track/трек не пересматривался и не должен был** — обоснование r1 (два + нарушенных критерия §5: несколько поверхностей + новый UX-контракт) относится + к неизменной части текста. + +## Чего не проверял + +- Гейты (`tsc`, `npm test`, `npm run build`, `check-docs.mjs`, смоки, golden, + инварианты) — не прогонял: этап `spec`, продуктового кода для #660 в + `origin/dev...HEAD` нет (`git diff` пуст). Предмет код-ревью после реализации. +- Не измерял независимо 100/81 px baseline или новые 50/40.5 px в браузере — + как и в r1, принял измерения «Аналитики» на веру; это станет предметом + код-ревью, когда появится браузерный смок. +- Не проверял, существует ли уже `scripts/mutation-registry.mjs` с местом под + новые мутанты #660 — план автотестов только обещает их добавить, это + нормально для стадии `spec` (мутанты появляются в реализации). +- Не проверял английский `docs/USER-GUIDE.md` на предмет отсутствующего раздела + «Phone header» (в отличие от `docs/USER-GUIDE.ru.md:265-278`, английская версия + такого подраздела не содержит вовсе) — это существующее расхождение + RU/EN-гайдов, не создано и не усугублено #660; не поднимаю отдельной находкой, + но автору стоит иметь это в виду при правке Release-артефактов: обновлять + нечего в EN-версии по этому месту не потому что она «уже верна», а потому что + там нет соответствующего текста. +- Не проверял production-числа анимации/transition сдвига кнопок при появлении + крестика (мгновенно или с анимацией) — текст ТЗ явно это не фиксирует, но AC5 + («соседние контролы не дёргаются») и общий контракт переходов в + `docs/UX-MODES.md:47-55` (короткий fade + интерполяция высоты) дают достаточный + ориентир для «Принято предположительно»; не считаю это открытым вопросом, + требующим отдельной находки. +- Не проверял ширины `docs/TOUCH-SUPPORT.md` подробнее констатации, что + редакторы остаются desktop-first/best-effort — вне скоупа этой задачи, как и в + r1. + +## Закрытие раунда r1 + +| Находка (r1) | Чем закрыта | Где это видно | +|---|---|---| +| High-1: раздел `## ТЗ` отсутствовал целиком | Добавлен полный раздел `## ТЗ` со всеми обязательными подразделами §7.1 (Сценарий, До/После, Проблема, Скоуп/Не-скоуп, AC1…AC10 с доказательством, UX/i18n/данные, План автотестов, Риски, Откат, Release-артефакты, «Принято предположительно») | тело issue #660, после `---`, начиная с `## ТЗ` | +| High-2: противоречие с `docs/UX-MODES.md`, апдейт не запланирован | Скоуп п.7, AC10 и Release-артефакты прямо называют обе цитаты канона на замену | тело issue #660, разделы «Скоуп» п.7, «AC10», «Release-артефакты» | +| Medium-1: нет допуска/целевых значений расстояния | AC3 задаёт 50 ±1 px (768–1400) и 40.5 ±1 px (481–620) | тело issue #660, «AC3. Gap» | + +Все три находки r1 закрыты содержательно, без формальных отписок. Новый High-1 +этого раунда — независимая находка на техническом стыке, который стал виден +только после того, как появился текст для проверки (в r1 разбирать было нечего — +раздела не было). + +## Унаследовано из r1 (без повторной проверки в этом раунде) + +- **Отказ от лёгкого трека (`small`) и выбор полного трека.** Обоснование — + задействовано более одной поверхности и вводится новый UX-контракт — текст не + менялся между r1 и r2; принято по SPEC-REVIEW-660-r1, раздел «Что проверено и + корректно», без повторного анализа критериев §5 в этом раунде. +- **Продуктовая правомерность вопросов Q1/Q2** (оба — что видит/делает + пользователь, оба с default-вариантом) — установлено в SPEC-REVIEW-660-r1, + текст вопросов и ответов не редактировался, сверен только на дословное + совпадение с новым «Принятые решения владельца» (см. «Что проверено и + корректно» выше) — само правомерность формулировки вопросов заново не + пересматривалась. +- Утверждения кода из комментария «Аналитика» (`renderControls`, `header-menu.ts` + guard, `.editor-close-slot` sibling, три ветки `_onKey`) были построчно + проверены в r1 (`docs/reviews/SPEC-REVIEW-660-r1.md`, материал + `268f8f32087b`) — в этом раунде они перепроверены заново (см. «Как + проверялось» пп. 6-7), поскольку дельта признана нелокальной; формально это + не «наследование», а независимое повторное подтверждение с тем же выводом. + +## Вердикт + +Найден 1 High, в скоупе задачи. Все три находки SPEC-REVIEW-660-r1 закрыты +содержательно — структура и полнота раздела `## ТЗ` больше не блокируют. Но +полный разбор впервые появившегося текста вскрыл новое, самостоятельное +противоречие: Скоуп п.3 (переместить крестик внутрь `.modes`) без оговорки по +ширине ломает видимость крестика на ≤480 px, потому что `.modes` скрыт +`display: none` в этом диапазоне, а `.editor-close-slot` сегодня — её сосед, а не +потомок. Это напрямую противоречит документированному поведению телефонной шапки +(`docs/UX-MODES.md:17-20`, `docs/USER-GUIDE.ru.md:277`) и делает недоказуемым +собственный AC9 задачи; для touch-only администратора на телефоне это не +деградация, а полная потеря способа выйти из Plan/Devices (проверено по коду: +`_setMode` не переключает обратно в View повторным кликом по активному пункту +меню, отдельного пункта «Просмотр» в меню нет, `Esc` недоступен без клавиатуры). +Разрешение — продуктово наблюдаемая деталь (что видит и может сделать +пользователь телефона), не техническая, которую можно решить между агентами по +умолчанию. + +Красный вердикт: ТЗ возвращается автору на доработку Скоуп п.3 (и, при +необходимости, AC9/Не-скоупа) с явной оговоркой поведения крестика на ≤480 px. +Отдельные issue не заводятся — находка в скоупе. + +Вердикт: красный · заход r2 · блокирующих циклов 2/4 · High: 1 · Medium: 0 → в задаче + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `4b8a82c08a7e` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `7cc2ff9fb72ff2627617fd7c86d240207b8f042f` + ``` + git log --all --format='%H %T' | grep 7cc2ff9fb72f + ``` +- Тело issue: `d20b5c1fa1ed9fe13ee58b29a71d6de650976a7ac810c2567b11fef1e83c42f0` +- Вердикт конвейера: `red` · High 1