docs: review document for #449

Issue: #449
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-04 18:18:14 +03:00
committed by Sergey Matyunin
parent 85a064430b
commit b39f99b3a4
+269
View File
@@ -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`.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `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
```