mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
docs: specify the beta polish batch (#400)
User-Visible: no Issue: #400
This commit is contained in:
Executable
+191
@@ -0,0 +1,191 @@
|
||||
# ТЗ #400 — Полиш v1.70.0-beta.1: ручки мебели, вес помощи, мёртвое исключение
|
||||
|
||||
- Issue: https://github.com/Matysh/houseplan-card/issues/400
|
||||
- Приоритет: P3, polish; полный трек — три несвязанные поверхности (SVG-рамка
|
||||
редактора декора, состав ленивых чанков, направляющие выравнивания), критерий
|
||||
«одна поверхность» для `small` не выполняется — прецеденты #369, #385
|
||||
- Ревизия: 1 (2026-08-31)
|
||||
|
||||
## Сценарий
|
||||
|
||||
Три шероховатости свежей беты, каждая мала по отдельности. Владелец расставляет
|
||||
мелкую мебель (тумба 40 см) и замечает, что за угол рамки ухватиться труднее,
|
||||
чем за бок. Пользователь на медленном канале грузит карточку чуть тяжелее,
|
||||
чем нужно: тексты подсказок редактора приезжают вместе с холодным View.
|
||||
Разработчик читает код направляющих и видит исключение, которое ничего не
|
||||
исключает.
|
||||
|
||||
## Что человек увидит до и после
|
||||
|
||||
**До**: (1) на мебели уже примерно 80 см осевая ручка лежит поверх угловой и
|
||||
забирает часть её зоны — угол остаётся доступен, но площадь попадания меньше;
|
||||
(2) 38 строк помощи (EN 3,0 КБ + RU 6,3 КБ сырого текста) едут в initial-чанке,
|
||||
хотя видны только в редакторе; (3) видимой разницы нет — это внутренняя правка.
|
||||
**После**: угол мелкой мебели тянется так же уверенно, как бок; вес initial не
|
||||
несёт редакторских текстов (либо решение зафиксировано осознанно); направляющие
|
||||
опираются на актуальный источник перетаскивания.
|
||||
|
||||
## Проблема и контракты по пунктам
|
||||
|
||||
### (1) M5 — осевые ручки перекрывают угловые на мелкой мебели
|
||||
|
||||
`src/houseplan-card.ts:8439` задаёт единый радиус хита
|
||||
`hr = max(view.w, view.h) * 0.018`, одинаковый для угловых (`:8467`) и осевых
|
||||
(`:8471`) ручек. Осевые рисуются **после** угловых, поэтому в зоне пересечения
|
||||
хит забирают они.
|
||||
|
||||
**Замер, а не расчёт** (браузер, режим декора, `.dtframe` на реальной мебели):
|
||||
радиус обеих ручек — **14 px** на экране; перекрытие возникает, когда
|
||||
полуширина объекта меньше `2·hr`, то есть примерно до 80 см.
|
||||
|
||||
**Уточнение серьёзности против формулировки аудита.** В отчёте было сказано,
|
||||
что «пропорциональный ресайз углом становится недоступен». Это неверно: центр
|
||||
угловой ручки лежит **вне** круга осевой (для 40 см — 20 единиц плана против
|
||||
радиуса 18), попасть в угол можно, сужается лишь зона. Поэтому пункт остаётся
|
||||
полишем, а не багом. Честная формулировка: **на мебели до ~80 см зона угловой
|
||||
ручки урезана примерно вдвое, потому что осевая лежит поверх неё**.
|
||||
|
||||
**Контракт**: у угловой ручки приоритет хита над осевой. Достигается порядком
|
||||
отрисовки (угловые кладутся последними) и/или скрытием осевых, когда сторона
|
||||
меньше `4·hr` — на такой стороне осевая ручка всё равно неотличима от угловых.
|
||||
Выбор — за реализацией; критерий один: на мебели 40 см клик в геометрический
|
||||
угол рамки достаётся угловой ручке.
|
||||
|
||||
### (2) Low «б» — тексты помощи в холодном чанке
|
||||
|
||||
38 ключей помощи #86 лежат в `dist/houseplan-assets/houseplan-card-*.js`
|
||||
(проверено grep'ом по собранному дереву), а не в ленивом чанке редактора. Это
|
||||
не дефект #86: словари `en` и `ru` по архитектуре ленивой поставки всегда в
|
||||
initial, лениво грузятся только `de` и `fr`. Но текст, который виден
|
||||
исключительно в редакторе, оплачивается каждым холодным просмотром: запас
|
||||
бюджета сейчас 15 945 Б при потолке 300 000, а за сутки беты израсходовано
|
||||
6,1 КБ.
|
||||
|
||||
**Контракт**: решение принимается явно и записывается. Два честных исхода:
|
||||
|
||||
1. вынести `*.help*`-ключи в ленивый чанк редактора (он и так грузится, когда
|
||||
помощь может понадобиться) — тогда initial худеет на величину, которую
|
||||
нужно замерить и указать в отчёте;
|
||||
2. зафиксировать, что `en`/`ru` неделимы, и планировать бюджет с этим знанием
|
||||
— тогда в `docs/ARCHITECTURE.md` появляется строка о том, что стоимость
|
||||
редакторских текстов входит в initial по построению.
|
||||
|
||||
Исход (1) предпочтителен, если механика ленивых словарей допускает раздельные
|
||||
секции без второго сетевого запроса на каждое открытие подсказки; если нет —
|
||||
честнее (2), чем ломать поставку ради 9 КБ.
|
||||
|
||||
### (3) Low «г» — исключение по мёртвому источнику
|
||||
|
||||
`src/houseplan-editor-runtime.ts:10970` в ветке `_mode === 'devices'`
|
||||
пропускает перетаскиваемый маркер по `this.host._drag?.id`. Но перетаскивание
|
||||
устройств после #74 живёт в отдельном состоянии `_deviceDrag`
|
||||
(`houseplan-card.ts:2548`, заполняется на `:6736`), а `_drag` (`:2547`) в этом
|
||||
режиме остаётся `null` — проверено чтением обоих объявлений и всех присваиваний.
|
||||
|
||||
Следствие: маркер, который тянут, попадает в собственный список кандидатов
|
||||
выравнивания. Видимого сбоя нет только потому, что `alignGuides`
|
||||
(`src/logic.ts:1981`) сравнивает точку с кандидатами по допуску, и точка
|
||||
совпадает сама с собой — направляющая рисуется «от себя к себе» и визуально
|
||||
неотличима от честной. `demo/smoke_align_guides.mjs` после `a6b0850a`
|
||||
проверяет `guides() >= 1` и такую подмену не различает.
|
||||
|
||||
**Контракт**: исключение опирается на актуальный источник перетаскивания
|
||||
(`_deviceDrag?.id` в режиме устройств), а смок различает направляющую от
|
||||
другого маркера и направляющую от самого себя.
|
||||
|
||||
## Скоуп / не-скоуп
|
||||
|
||||
**В скоупе**: `_renderTextFrame` в `src/houseplan-card.ts` (порядок и/или
|
||||
видимость ручек), состав ленивых чанков для help-ключей либо запись решения,
|
||||
`_alignCandidates` в `src/houseplan-editor-runtime.ts`,
|
||||
`demo/smoke_align_guides.mjs`, тесты и мутанты.
|
||||
|
||||
**Не в скоупе**: радиус ручек (`hr`, решение владельца 2026-08-05 «уменьшить в
|
||||
4 раза»), механика ресайза мебели (#383), содержание текстов помощи (#86),
|
||||
архитектура ленивой поставки словарей (#352–#355).
|
||||
|
||||
## UX
|
||||
|
||||
Пункт (1) видим: угол мелкой мебели становится так же надёжен, как бок.
|
||||
Пункты (2) и (3) видимого поведения не меняют.
|
||||
|
||||
## Модель данных и миграция
|
||||
|
||||
Не применимо: ни конфиг, ни layout не затрагиваются.
|
||||
|
||||
## i18n
|
||||
|
||||
Новых строк нет. При исходе (1) пункта (2) ключи не меняются — меняется чанк,
|
||||
в котором они лежат.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- **AC1**. На мебели 40 см клик в геометрический угол рамки достаётся угловой
|
||||
ручке, а не осевой. Доказательство: браузерный смок с синтетическим
|
||||
`pointerdown` в точку угла и перехватом обработчика — `elementFromPoint`
|
||||
через shadow root недостаточно (проверено: возвращает саму карточку).
|
||||
- **AC2**. На крупной мебели (160 см) поведение не меняется: доступны и
|
||||
угловые, и осевые ручки. Доказательство: тот же смок, вторая ветка.
|
||||
- **AC3**. Пункт (2) закрыт явным решением: либо help-ключи не попадают в
|
||||
initial-чанк (доказательство: `grep` по собранному дереву + замер бюджета до
|
||||
и после), либо решение «`en`/`ru` неделимы» записано в
|
||||
`docs/ARCHITECTURE.md` с причиной.
|
||||
- **AC4**. В режиме устройств перетаскиваемый маркер исключён из кандидатов
|
||||
выравнивания по `_deviceDrag`. Доказательство: юнит на `_alignCandidates` —
|
||||
при активном `_deviceDrag` список не содержит позицию тянущегося маркера.
|
||||
- **AC5**. Смок направляющих различает «от другого маркера» и «от себя»:
|
||||
проверка падает, если исключение убрать. Доказательство: отрицательный
|
||||
прогон, зафиксированный в документе ревью.
|
||||
- **AC6**. Бюджет initial не растёт: при исходе (1) он уменьшается, при
|
||||
исходе (2) остаётся прежним. Доказательство: `npm run bundle:budget` до и
|
||||
после.
|
||||
|
||||
## План автотестов
|
||||
|
||||
**Unit** (`test/align-candidates.test.mjs` либо существующий файл):
|
||||
|
||||
1. `_alignCandidates` в режиме `devices` при активном `_deviceDrag` не
|
||||
возвращает позицию тянущегося маркера (AC4).
|
||||
2. Тот же вызов без активного перетаскивания возвращает все маркеры
|
||||
пространства — исключение не «съедает» лишнего.
|
||||
|
||||
**Browser smoke** (`demo/smoke_furniture_polish.mjs` — дополнение,
|
||||
`demo/smoke_align_guides.mjs` — правка):
|
||||
|
||||
3. Мебель 40 см: `pointerdown` в геометрический угол рамки вызывает
|
||||
обработчик угловой ручки (AC1).
|
||||
4. Мебель 160 см: доступны обе ручки, поведение прежнее (AC2).
|
||||
5. Направляющие: при перетаскивании маркера направляющая строится от ДРУГОГО
|
||||
маркера, а не от самого себя (AC5).
|
||||
|
||||
**Мутанты** (`scripts/mutation-gate.mjs`):
|
||||
|
||||
- `furniture-edge-handles-steal-the-corner`: вернуть прежний порядок
|
||||
отрисовки → смок AC1 красный.
|
||||
- `align-guides-exclude-dead-source`: вернуть `_drag?.id` в ветке устройств →
|
||||
юнит AC4 и смок AC5 красные.
|
||||
|
||||
## Риски
|
||||
|
||||
- **Порядок отрисовки меняет и видимую рамку.** Бусины (`.dtknob`) рисуются
|
||||
рядом с хит-кругами; перестановка не должна менять картинку. Смягчение:
|
||||
golden-кадры рамки мебели — если они есть в матрице, они это и покажут; при
|
||||
расхождении кадр пересматривается осознанно.
|
||||
- **Скрытие осевых ручек ниже порога может удивить.** Пользователь, привыкший
|
||||
тянуть за бок, на мелкой мебели его не найдёт. Смягчение: предпочтителен
|
||||
порядок отрисовки, а не скрытие; скрытие — только если порядок не решает.
|
||||
- **Вынос help-ключей ломает ленивую загрузку словаря.** Второй сетевой запрос
|
||||
на открытие подсказки хуже, чем 9 КБ в initial. Смягчение: исход (2)
|
||||
остаётся честным ответом, если механика не позволяет.
|
||||
|
||||
## Откат
|
||||
|
||||
Три независимые правки. Пункт (1) — порядок двух блоков в шаблоне; пункт (2)
|
||||
при исходе (1) — состав чанка, при исходе (2) — строка документации; пункт (3)
|
||||
— одно поле в условии. Данные пользователя не затрагиваются.
|
||||
|
||||
## Release-артефакты
|
||||
|
||||
- `docs/CHANGELOG.md` / `docs/CHANGELOG.ru.md`: один пункт про угол мелкой
|
||||
мебели (User-Visible: yes). Пункты (2) и (3) — `User-Visible: no`.
|
||||
- Скриншоты: пересматриваются, только если golden покажет расхождение рамки.
|
||||
Reference in New Issue
Block a user