12 KiB
SPEC-REVIEW — issue #209 · заход r1
- Этап: spec (PROCESS.md §2.4)
- Артефакт ТЗ:
docs/specs/209-vacuum-trail-smoothing.md(SHA43516cc1, веткаissue/209-vacuum-trail-smoothing) - Вердикт: зелёный
- Блокирующих циклов израсходовано: 0 из 4
Скоуп ревью
Первый раунд, дельта не применяется (§2.9 — правило дельты действует только для r2+). Разобрано полностью:
- Тело issue #209 и все 3 комментария (анализ Codex, два решения владельца, финальная передача на ревью).
- Полный текст
docs/specs/209-vacuum-trail-smoothing.md. docs/SCOPE.md— соответствие Core user jobs.PROCESS.md§2.4, §7.1 — обязательные разделы ТЗ и порог продуктовых вопросов.docs/VACUUM.md,docs/USER-GUIDE.ru.md(раздел «Позиция и путь»),docs/USER-GUIDE.md(раздел «Robot vacuums»),docs/ARCHITECTURE.md— как канонические источники терминологии и текущего контракта.- Исходный код
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) — сверка каждого факта, на который ссылается ТЗ. 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-ревью, а не пробел.
Итог
ТЗ полное, однозначное, без выданных за факт догадок, предметно верифицировано по коду и документам. Продуктовые вопросы владельцу заданы и закрыты до отправки на ревью. Готово к статусу «Готово к разработке».