Files
houseplan-card/docs/reviews/SPEC-REVIEW-209-r1.md
T
2026-08-28 20:01:24 +00:00

12 KiB
Raw Blame History

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-ревью, а не пробел.

Итог

ТЗ полное, однозначное, без выданных за факт догадок, предметно верифицировано по коду и документам. Продуктовые вопросы владельцу заданы и закрыты до отправки на ревью. Готово к статусу «Готово к разработке».