mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 21:58:56 +00:00
146 lines
12 KiB
Markdown
146 lines
12 KiB
Markdown
# SPEC-REVIEW — issue #209 · заход r1
|
||
|
||
- Этап: spec (PROCESS.md §2.4)
|
||
- Артефакт ТЗ: `docs/specs/209-vacuum-trail-smoothing.md` (SHA `43516cc1`, ветка `issue/209-vacuum-trail-smoothing`)
|
||
- Вердикт: **зелёный**
|
||
- Блокирующих циклов израсходовано: 0 из 4
|
||
|
||
## Скоуп ревью
|
||
|
||
Первый раунд, дельта не применяется (§2.9 — правило дельты действует только
|
||
для r2+). Разобрано полностью:
|
||
|
||
1. Тело issue #209 и все 3 комментария (анализ Codex, два решения владельца,
|
||
финальная передача на ревью).
|
||
2. Полный текст `docs/specs/209-vacuum-trail-smoothing.md`.
|
||
3. `docs/SCOPE.md` — соответствие Core user jobs.
|
||
4. `PROCESS.md` §2.4, §7.1 — обязательные разделы ТЗ и порог продуктовых
|
||
вопросов.
|
||
5. `docs/VACUUM.md`, `docs/USER-GUIDE.ru.md` (раздел «Позиция и путь»),
|
||
`docs/USER-GUIDE.md` (раздел «Robot vacuums»), `docs/ARCHITECTURE.md` — как
|
||
канонические источники терминологии и текущего контракта.
|
||
6. Исходный код `src/houseplan-card.ts` (`_renderVacuums`, ~11819–11905) и
|
||
`src/vacuum.ts` (`normalizeVacPath`, `resolveCurrentVacPath`,
|
||
`trimVacPathTarget`, `VAC_PATH_MAX_SEGMENTS/POINTS`, `TRAIL_MAX`) и
|
||
`custom_components/houseplan/trails.py` (`TRAIL_CAP`) — сверка каждого
|
||
факта, на который ссылается ТЗ.
|
||
7. `docs/TESTING.md` — существование `scripts/mutation-gate.mjs` и практики
|
||
мутационных гвардов, на которые ссылается план автотестов ТЗ.
|
||
|
||
## Как проверялось
|
||
|
||
Продуктовая часть (docs/SCOPE.md, персона, сценарий) читалась первой и
|
||
отдельно от технической, как требует §7.1. Технические утверждения ТЗ
|
||
(номера строк, имена функций, константы лимитов, порядок affine → build →
|
||
`_scenePoint()`) верифицированы построчным чтением текущего кода, а не
|
||
доверием тексту ТЗ. Отдельно перепроверено математическое обоснование предела
|
||
17,5 см в §6.2 (см. ниже) — это не тривиальное утверждение, и ложное
|
||
доказательство было бы поводом для High.
|
||
|
||
## Находки
|
||
|
||
Находок нет — ни High, ни Medium, ни Low.
|
||
|
||
Разобранные кандидаты, которые не подтвердились как дефект:
|
||
|
||
- **Отсутствие docs/USER-GUIDE.md (EN) в списке release-артефактов §13.**
|
||
Проверено: `docs/USER-GUIDE.md` раздел «16. Robot vacuums» не описывает
|
||
форму линии следа (M/L vs кривая) — он делегирует детали в `VACUUM.md`
|
||
одной фразой. `VACUUM.md` (канонический для этого контракта, EN) в списке
|
||
§13 присутствует. Правки нечего вносить в `USER-GUIDE.md`, значит его
|
||
отсутствие в перечне не является пропуском.
|
||
- **Утверждение issue-body про поверхность «статический рендер».** Тело issue
|
||
перечисляет «View, киоск, статический рендер» как поверхности показа следа.
|
||
Проверено: `src/space-card.ts` и `src/space-render.ts` (инертная
|
||
`houseplan-space-card`) не содержат ни одного упоминания vacuum/trail —
|
||
сейчас след там не рисуется. Само ТЗ, однако, этой ошибки не наследует: §1
|
||
описывает только View/киоск/редакторы, а §4 Scope формулирует охват как
|
||
«поверхности, где след уже рисуется» — не перечисляя конкретный список.
|
||
§5 Non-scope прямо запрещает «добавление следа ... на поверхности, которые
|
||
его сейчас не имеют». Формулировка ТЗ самодостаточно корректна независимо
|
||
от неточности в исходном issue-анализе.
|
||
- **Математика предела в §6.2.** Проверено: для точки на `conv{P, B, Q}`
|
||
расстояние до `B` ограничено `r = min(17.5см, |AB|/2, |BC|/2)` в силу
|
||
выпуклости нормы (максимум выпуклой функции на симплексе достигается в
|
||
вершине); P и Q лежат на исходных отрезках, поэтому граница до исходной
|
||
ломаной действительно ≤ r ≤ 17,5 см. Отдельно проверено недопущение
|
||
наложения соседних скруглений: раз `r_B2 ≤ |s2|/2` и `r_B3 ≤ |s2|/2` для
|
||
общего отрезка `s2`, точка `Q` вершины `B2` не может оказаться дальше по
|
||
отрезку, чем точка `P` вершины `B3` — соседние скругления не меняются
|
||
местами. Довод в тексте ТЗ корректен, не голословен.
|
||
- **Эпсилон разворота ~180°.** Помечен явно как техническое решение автора
|
||
реализации, фиксируемое unit-тестом (§14 п.3), а не выдан за факт — это
|
||
ровно то отличие «предположения» от «незамеченной догадки», которое требует
|
||
проверять инструкция ревью.
|
||
|
||
## Что проверено и корректно
|
||
|
||
- **Персона/сценарий/до-после** — первые два раздела (§7.1) заполнены
|
||
корректно и без терминов реализации; соответствуют J1 (`docs/SCOPE.md`:
|
||
«Show the whole home and what's happening right now»).
|
||
- **Продуктовые вопросы владельцу** заданы по существу (граница сглаживания,
|
||
вкл/выкл, previous run) — все три ровно того типа, что разрешён §7.1
|
||
(«что видно», «объём видимых изменений»), без технических вопросов,
|
||
вынесенных наружу. Ответы получены и зафиксированы в issue до отправки ТЗ
|
||
на ревью — блокировка снята в срок.
|
||
- **Все обязательные разделы §7.1 присутствуют**: сценарий, до/после,
|
||
проблема, scope/non-scope, контракт поведения, UX/a11y/touch/i18n, модель
|
||
данных и совместимость, AC1–AC11 с методом доказательства для каждого,
|
||
план автотестов, риски, release-артефакты, откат.
|
||
- **AC однозначны и проверяемы**: каждый сформулирован как измеримое
|
||
утверждение (endpoints совпадают, отклонение ≤17,5 см, число команд ≤2N,
|
||
таблица режимов не меняется и т.д.), не «сделать нормально»/«работает как
|
||
ожидается».
|
||
- **Факты о коде подтверждены построчно**: `VAC_PATH_MAX_SEGMENTS = 64`,
|
||
`VAC_PATH_MAX_POINTS = 4000` (`src/vacuum.ts:14-15`), `TRAIL_MAX = 600`
|
||
(`src/vacuum.ts:477`), `TRAIL_CAP = 2000`
|
||
(`custom_components/houseplan/trails.py:27`), `resolveCurrentVacPath`,
|
||
`trimVacPathTarget`, `normalizeVacPath` (`src/vacuum.ts:169,201,222`) —
|
||
все совпадают с ТЗ. Текущий рендер (`_renderVacuums`,
|
||
`src/houseplan-card.ts:11819-11905`) действительно строит current как
|
||
единый `path` с `M`/`L` по подпутям и previous — отдельным `polyline`
|
||
(`:11855`), обе ветки применяют affine и затем `_scenePoint()` на каждую
|
||
точку — план ТЗ перенести этот порядок на «affine всего подпути → builder →
|
||
проекция» архитектурно согласован с существующим кодом, не выдумка.
|
||
`src/vacuum.ts` уже существует и уже владеет `normalizeVacPath`/
|
||
`resolveCurrentVacPath`/`trimVacPathTarget` — ровно тот модуль, куда ТЗ
|
||
просит добавить pure builder (§9), это не новый файл и не смена владения.
|
||
- **Non-scope согласован со scope**: явно исключены изменения хранения,
|
||
лимитов, arbitration, trail modes, добавление следа туда, где его нет —
|
||
ни один пункт scope не противоречит этому списку.
|
||
- **Терминология согласована** с `docs/USER-GUIDE.ru.md` («Никогда/Во время
|
||
уборки/Всегда», «текущий путь»/«последний завершённый путь») — таблица
|
||
§6.4 ТЗ не меняет и не путает этот контракт.
|
||
- **i18n/touch/миграция/откат** — по каждому пункту явное «нет изменений» с
|
||
обоснованием, а не молчание.
|
||
- **Track = полный** обоснован верно: видимый контракт подачи меняется,
|
||
задействовано несколько поверхностей и golden-эталоны — критерий `small`
|
||
не проходит.
|
||
- **Продуктовая оценка (польза/сложность/риск)** реалистична и не
|
||
противоречит `docs/SCOPE.md`: ценность признана косметической (4/10), что
|
||
корректно для P3-полировки, не блокирующей и не требующей ускоренного
|
||
трека.
|
||
|
||
## Чего не проверял
|
||
|
||
- Реализацию — её не существует, стадия spec.
|
||
- `npx tsc --noEmit` / `npm test` / `npm run build` — не прогонял: гейт не
|
||
применим к этапу ревью ТЗ (нет кода для компиляции), а не пропущен по
|
||
экономии.
|
||
- Golden/смоки/инварианты модели — не прогонял: задача геометрию модели
|
||
(рёбра, `layout`, `marker.space`, `open_spans`) не трогает (явный
|
||
non-scope), это этап spec, инструментальные гейты этого раунда не
|
||
применимы.
|
||
- Не проверял, действительно ли выбранный владельцем способ (quadratic
|
||
Bézier по хордам) — лучший вариант из трёх предложенных в issue
|
||
(Catmull-Rom/Chaikin/Безье): ТЗ прямо отдаёт выбор техники автору
|
||
реализации, зафиксировав только измеримую границу (17,5 см) и семантику
|
||
(endpoints, gaps, no bridge) — это корректная граница ответственности
|
||
spec-ревью, а не пробел.
|
||
|
||
## Итог
|
||
|
||
ТЗ полное, однозначное, без выданных за факт догадок, предметно
|
||
верифицировано по коду и документам. Продуктовые вопросы владельцу заданы и
|
||
закрыты до отправки на ревью. Готово к статусу «Готово к разработке».
|