docs: review document for #209

Issue: #209
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-28 20:01:24 +00:00
parent 43516cc15f
commit 2890b9a1ab
+145
View File
@@ -0,0 +1,145 @@
# 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-ревью, а не пробел.
## Итог
ТЗ полное, однозначное, без выданных за факт догадок, предметно
верифицировано по коду и документам. Продуктовые вопросы владельцу заданы и
закрыты до отправки на ревью. Готово к статусу «Готово к разработке».