diff --git a/docs/reviews/SPEC-REVIEW-449-r2.md b/docs/reviews/SPEC-REVIEW-449-r2.md new file mode 100644 index 00000000..3a5804e1 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-449-r2.md @@ -0,0 +1,269 @@ +# SPEC-REVIEW — issue #449 · заход r3 (см. «Расхождение нумерации» ниже) + +- Issue: https://github.com/Matysh/houseplan-card/issues/449 +- Этап: ревью ТЗ (PROCESS.md §2.4) +- ТЗ: `docs/specs/449-double-fit-all.md` +- Материал: ветка `issue/449-double-fit-all`, SHA `9238ce666bee7ea9b7eddcd9e5b3f083b96ad114` +- Трек: полный (issue не помечен `small`); лимит циклов ревью ТЗ — 4 (§2.4) +- Заход r3 (истинный порядковый номер — см. ниже), блокирующих циклов + израсходовано до этого вердикта: **2**/4 (r1 — жёлтый, r2 — жёлтый) + +## Расхождение нумерации: env дал «заход r2 · циклов 1/4», это неверно + +Заголовок задачи для этого прогона (`needs.guard.outputs.cycle`/`spent`, +рендерится в `.github/workflows/process.yml:437-440,625`) сообщил «Заход: r2 · +блокирующих циклов израсходовано 1 из 4». Это не совпадает с историей issue: + +- r1 — жёлтый вердикт, коммент + [#issuecomment-5542152824](https://github.com/Matysh/houseplan-card/issues/449#issuecomment-5542152824), + документ опубликован коммитом `9206ef64` под именем + `docs/reviews/SPEC-REVIEW-449-r1.md`; +- правка `e027b2a0` закрыла M1; +- r2 — жёлтый вердикт, коммент + [#issuecomment-5542290451](https://github.com/Matysh/houseplan-card/issues/449#issuecomment-5542290451), + сам документ внутри себя корректно называет себя «заход r2» и явно ссылается + на материал r1 (`9206ef64`, SHA `5847bf2b1bb6`); +- правка `9238ce66` (материал этого раунда) закрывает M2. + +То есть до этого прогона фактически было **два** жёлтых вердикта, а не один, и +этот прогон — **третий**, а не второй. + +**Корневая причина найдена.** `guard`-джоб считает `attempt`/`spent` не по +номеру, а по числу комментариев issue, которые одновременно проходят два +regex-теста: `Вердикт:` и буквальную подстроку маркера (`SPEC-REVIEW` для +этапа spec) — `.github/workflows/process.yml:87-93`. Комментарий r1 закончился +фразой «Документ: см. артефакт ревью (публикуется шагом конвейера)» — +**без имени файла**, поэтому подстроки `SPEC-REVIEW` в его теле нет, и jq-фильтр +`of_stage` его не засчитывает. Комментарий r2, наоборот, заканчивается +«Документ: `docs/reviews/SPEC-REVIEW-449-r2.md`» — с маркером — и он единственный +учтён. Итог на момент этого прогона: `of_stage` = 1 (только r2), `attempt` = 1+1 += 2, `spent` = 1. Оба числа занижены ровно на единицу — комментарий r1 +исключён из подсчёта навсегда, если его текст не поправить. + +**Уже нанесённый ущерб.** Тем же образом на предыдущем прогоне `guard` посчитал +`cycle=1` для того, что публикующийся ревьюер верно назвал «заход r2» в тексте. +Шаг публикации (`.github/workflows/process.yml:661`, +`doc="docs/reviews/${marker}-${NUM}-r${CYCLE}.md"`) берёт номер не из текста +ревью, а из `$CYCLE` — и положил документ r2 в файл `…-r1.md`, **затерев** +оригинальный документ r1. Оригинал не потерян безвозвратно — он читается из +истории git: + +``` +git show 9206ef64:docs/reviews/SPEC-REVIEW-449-r1.md +``` + +— но рабочее дерево на `origin/dev` сейчас содержит под именем `…-r1.md` +содержимое второго раунда, а файла `…-r2.md` не существует вовсе. + +**Что это значит для этого прогона.** Публикующий шаг снова возьмёт номер из +`$CYCLE` (=2, по тому же занижению) и положит **этот** документ в +`docs/reviews/SPEC-REVIEW-449-r2.md`. Это не перезапишет существующий файл +(такого файла ещё нет), поэтому данные в этот раз не теряются — но нумерация +файла (`r2`) разойдётся с истинным порядковым номером раунда (третий), и то же +занижение на единицу останется навсегда, пока кто-то не поправит текст +комментария r1 (добавив в него подстроку `SPEC-REVIEW-449-r1`) либо саму логику +подсчёта в `guard`. Ни то, ни другое не лечится в ветке `issue/449-double-fit-all` +и не входит в скоуп ТЗ #449, поэтому заведён отдельный issue — +[#454](https://github.com/Matysh/houseplan-card/issues/454) — со ссылкой на этот +документ и точной репродукцией. + +Числа `spent`/`limit`, которые увидит владелец в шапке будущих прогонов, тоже +занижены на единицу: лимит `review-4` фактически сработает на пятом жёлтом +вердикте вместо четвёртого. На этом issue лимит не выбирается ни при +буквальном, ни при истинном счёте (2 или 3 из 4), поэтому решение по вердикту +этого раунда не меняется — расхождение зафиксировано для владельца и починки +инфраструктуры, а не потому, что оно блокирует #449. + +Дальше в этом документе использую **истинный** счёт (r3, циклов 2 уже +потрачено до этого раунда), а не буквальные числа из шапки задачи — иначе +номер в тексте противоречил бы фактической истории раунда, которую сам же +документ и восстанавливает. Это решение не влияет на будущий автоматический +подсчёт: `guard` считает по наличию подстрок `Вердикт:`/`SPEC-REVIEW` в теле +комментария, а не по значению, которое написано после «заход r». + +## Скоуп проверки — по дельте (PROCESS.md §2.10) + +Предыдущий раунд (r2 по факту истории, физически опубликован как документ +`docs/reviews/SPEC-REVIEW-449-r1.md` из-за описанного выше искажения нумерации) +получен на материале SHA `e027b2a06d62b79530840a36369651d5eea38839`. Правка — +один коммит `9238ce66` поверх него, ребейза не было +(`git merge-base origin/dev 9238ce66` = `89647c10`, та же база, что и у r1/r2). + +``` +git diff e027b2a0..9238ce66 -- docs/specs/449-double-fit-all.md +``` + +```diff +- **Touch editor: not exposed** — жест живёт только во View и kiosk; редакторы +- Плана, Устройств, Декора и Подложки его не получают, их touch-поведение и +- редакторский double-click не меняются (§6 «Режимы», AC7). Правило ++ **Touch editor: not exposed** — жест живёт только во View и kiosk; редакторы ++ Плана, Устройств и Подложки (в ней редактируется декор) его не получают, их ++ touch-поведение и редакторский double-click не меняются (§6 «Режимы», AC7). + `docs/TOUCH-SUPPORT.md` → «Documentation rule». +``` + +3 строки, ровно та формулировка, которую предыдущий раунд предложил как +исправление M2. `docs/specs/README.md` не менялся. `git diff origin/dev...HEAD` +содержит только `docs/reviews/SPEC-REVIEW-449-r1.md` (артефакт прошлого раунда), +`docs/specs/449-double-fit-all.md`, `docs/specs/README.md` — класс C целиком, +продуктовый код по-прежнему не тронут. + +Дельта локальна: не ребейз, не смена контракта, не новая подсистема, объём — +3 строки против находки в одну неточность. Разбор ограничен дельтой плюс всем, +до чего она дотягивается: сама строка и разделы, на которые она ссылается +(§6, AC7, канонический словарь редакторов). Остальные разделы ТЗ дельта не +задевает — см. «Унаследовано». + +## Как проверялось + +1. Получены оба вердикта (`gh issue view 449 --json comments`) и раскрыт их + реальный порядок и содержание — расхождение с шапкой задачи описано выше. +2. `git diff e027b2a0..9238ce66 -- docs/specs/449-double-fit-all.md` — ровно + правка из предложения r2, больше в файле ничего не менялось. +3. Независимо пересчитан состав редакторов по тем же трём источникам, что + называло r2, плюс дополнительно код: + - `docs/USER-GUIDE.ru.md:201-206` — таблица режимов называет три редактора: + План / Устройства / Подложка; + - `docs/UX-MODES.md:186` — `## Background — the decor underlay`, декор — + содержимое Подложки; + - `scripts/check-docs.mjs:115` — `[/\bDecor editor\b/gi, 'Background editor']` + нормализует устаревшее имя того же редактора; + - `grep -n -i "декор\|редактор" docs/specs/449-double-fit-all.md` — во всём + файле (шапка, «Не-скоуп» :73, AC7 :279-286) теперь ровно три редактора, + без расхождений. +4. Ссылки новой строки на §6 (`:180-188`) и AC7 (`:279-286`) открыты и + сверены построчно — оба раздела называют те же три редактора, что и + исправленная шапка. +5. `node scripts/check-docs.mjs` — прогнан лично, `Documentation checks passed + (7 files, 12 external links)`, exit 0. +6. `git diff --check e027b2a0..9238ce66 -- docs/specs/449-double-fit-all.md` — + чисто, exit 0. +7. Обязательные разделы §7.1 пересчитаны по текущему файлу + (`grep -n "^## " docs/specs/449-double-fit-all.md`) — все 15 присутствуют, + структура не пострадала от правки одной строки. +8. `docs/specs/README.md:178` — запись issue↔ТЗ на месте, дельтой не тронута. +9. Трейлеры `9238ce66` (`git show -s --format=full`) — `Issue: #449`, + `User-Visible: no`, верно для документационной правки без изменения + поведения. + +## Закрытие раунда r2 (по факту истории; физически — документ `…-r1.md`) + +| Находка r2 | Чем закрыта | Где это видно | +|---|---|---| +| **M2** (Medium, в скоупе): строка `Touch editor: not exposed` называла несуществующий четвёртый редактор («Декора» отдельно от «Подложки») | Формулировка заменена на «Плана, Устройств и Подложки (в ней редактируется декор)» — те же три редактора, что в §6/AC7/гайде | `docs/specs/449-double-fit-all.md:9-12` (коммит `9238ce66`) | + +Проверено не на слово автора: цитаты трёх источников (`USER-GUIDE.ru.md`, +`UX-MODES.md`, `check-docs.mjs`) сверены заново лично (см. «Как проверялось» +п.3), а не приняты по формулировке коммента. Новая строка теперь дословно +согласована с §6 и AC7, на которые сама же ссылается — расхождения, которое +породило M2, больше нет нигде в файле. + +## Находки + +Нет находок уровня High/Medium/Low в дельте r3 по содержанию ТЗ #449. + +Отдельно (не находка против ТЗ, а находка против инфраструктуры ревью) — +см. раздел «Расхождение нумерации» выше и заведённый +[#454](https://github.com/Matysh/houseplan-card/issues/454). Не учитывается в +счётчике High/Medium этого вердикта: предмет ревью — ТЗ #449, а не пайплайн. + +## Что проверено и корректно + +- **M2 закрыта по существу**, а не только по форме: три независимые сверки + (USER-GUIDE.ru.md, UX-MODES.md, check-docs.mjs) плюс перечитанные §6/AC7 + подтверждают, что шапка теперь называет ровно тех же трёх редакторов, что и + остальной документ. +- **Никакого нового текста, кроме согласованной формулировки, правка не + вносит** — дифф ограничен тремя строками ровно там, где была неточность. +- **`node scripts/check-docs.mjs` зелёный** (прогнан лично на этом SHA). +- **`git diff --check` чист** — не внесено пробельных дефектов. +- **Обязательные разделы §7.1 на месте**, `docs/specs/README.md` не требовал + правки и не тронут. +- **Трейлеры `9238ce66` корректны**: `Issue: #449`, `User-Visible: no`. +- **Дельта действительно локальна** — не ребейз (`merge-base` не изменился с + r1/r2), не новая подсистема, не смена контракта: полный повторный разбор не + требовался. + +## Унаследовано из r1 и r2 + +Всё, что предыдущие раунды проверили и признали корректным, а дельта r3 (3 +строки правки M2) не задевает, принято без повторной проверки: + +- продуктовая рамка — job J1, персоны Household/Guest (View) и Home admin + (kiosk), задача в скоупе `docs/SCOPE.md`; проверено в r1 + (`docs/reviews/SPEC-REVIEW-449-r1.md`@`9206ef64`, доступен по этому SHA в + истории git — рабочая копия того же пути сейчас содержит текст r2, см. + «Расхождение нумерации»); +- решения владельца Q1/Q2 корректно перенесены в контракт поведения (§5) и + таблицу §6; сама таблица §6 не менялась ни в r2, ни в r3 — построчно + перечитана в этом раунде заново только по факту ссылки новой строки на неё + (см. «Как проверялось» п.4), не как повторная приёмка всего раздела; +- построчная сверка «текущего поведения по коду» (`_lastTap`/`_swipeStart` + внутри kiosk-ветки, отсутствие `dblclick` на stage, сигнатура `_fitAll`, + `ROOM_FIT_INTERACTIVE_OWNER`, `CameraTransitionReason`, no-op на + `sameCameraState`) — код не менялся ни разу за все три раунда, повторная + сверка не требуется; +- существование всех файлов, названных в «Плане автотестов» и AC1–AC11 + (smoke/test/mutation-gate) — файлы не переименовывались и не удалялись; +- обязательные разделы §7.1 присутствуют все, AC пронумерованы и каждый несёт + способ доказательства — подтверждено в r1, пересчитано механически заново в + этом раунде (п.7 «Как проверялось»), без повторного смыслового чтения + каждого AC; +- блок «Принятые предположения» отделяет техническое от продуктового + корректно — не менялся с r1; +- вне-скоуп находка «Показать всё» / «Вписать всё» в `docs/USER-GUIDE.ru.md` + верно заведена r1 как [#452](https://github.com/Matysh/houseplan-card/issues/452) + и не относится к предмету этого раунда. + +## Чего не проверял и почему + +- **Реализацию** — её по-прежнему нет: `git diff origin/dev...HEAD` не + содержит класса A/B, только `docs/**`. +- **`npx tsc --noEmit` / `npm test` / `npm run build`** — не гонял: раунд не + меняет ни одной строки кода, а Validate на предыдущем продуктовом SHA к + этому ТЗ не относится (ТЗ ещё не имеет реализации). +- **Инварианты модели / golden / браузерные smoke** — не применимо: дифф не + трогает `src/**`, геометрию, рендер. +- **Полный текст ТЗ вне зоны дельты** (сценарий, скоуп/не-скоуп кроме списка + редакторов, модель данных, риски, план автотестов, откат, + release-артефакты) — не перечитывал заново; ничто из этого не зависит от + трёх изменённых строк, см. «Унаследовано». +- **Q1/Q2 продуктовую историю** — не переоткрывал: решения владельца + зафиксированы до r1, дельта их не касается. +- **Историческую правку комментария r1** (добавление в него маркера + `SPEC-REVIEW-449-r1`, чтобы восстановить корректный счёт `guard`) — не + делал: это чужой опубликованный комментарий, редактировать его не входит + в роль ревьюера; чинить нужно логику подсчёта, а не задним числом + переписывать историю issue. Отражено в заведённом + [#454](https://github.com/Matysh/houseplan-card/issues/454). + +## Вердикт + +High: 0 · Medium в скоупе ТЗ #449: 0 · Medium вне скоупа: 0 (обе прежние +вне-скоуп находки уже закрыты решением r1: #452 заведена, эта находка выше — +о пайплайне, а не о соседнем продуктовом поведении, заведена отдельно как +#454 в силу серьёзности, но не считается в этом тэлли, так как её предмет — +не ТЗ). + +Зелёный вердикт (PROCESS.md §2.4, §12): M2 закрыта по существу, новых находок +против содержания ТЗ #449 нет. Зелёный вердикт бюджет циклов не тратит — +истинный счёт остаётся 2/4 (r1, r2), а не увеличивается этим раундом. + +ТЗ #449 готово к `S5-ready`. + +--- + + + +## Материал раунда + +- Ветка: `issue/449-double-fit-all`, коммит `9238ce666bee` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `ee0b2f4528fb30de7b90d79323c7aa16c96af7e7` + ``` + git log --all --format='%H %T' | grep ee0b2f4528fb + ``` +- ТЗ `docs/specs/449-double-fit-all.md`, блоб `d6ddccbb3920bdffbb8414f4b6c225a4cdf4f420` + ``` + git log --all --find-object=d6ddccbb3920bdffbb8414f4b6c225a4cdf4f420 -- docs/specs/449-double-fit-all.md + ```