19 KiB
Ревью ТЗ — issue #211, цикл r1
- Issue: https://github.com/Matysh/houseplan-card/issues/211
- ТЗ:
docs/specs/211-device-icons-visual-parity.md(коммит93200eb, веткаissue/211-device-icons-visual-parity) - Трек: обычный (аналитика явно исключила
small/trivial) - Вердикт: жёлтый · цикл r1/4 · High: 0 · Medium: 1 (в скоупе задачи) · Low: 2
Скоуп ревью
Проверялось только ТЗ как артефакт этапа S4-spec-review: обязательные разделы
§7.1 PROCESS.md, однозначность и доказуемость AC1…AC10, соответствие
docs/SCOPE.md (J1/J2), docs/USER-GUIDE.ru.md, docs/TOUCH-SUPPORT.md, и
отдельно — фактическое соответствие числовых утверждений ТЗ нормативному
источнику: тому же архиву дизайнера, что и в #179, плюс текущей реализации в
src/styles.ts (описанной как «до»). Продуктовый код по #211 не существует
(issue не дошёл до S5-ready, диапазон origin/dev..HEAD содержит только
docs/specs/211-*.md и правку docs/specs/README.md), поэтому код не
проверялся и гейты §8 PROCESS.md к этому циклу неприменимы.
Как проверялось
- Прочитаны
docs/SCOPE.md,AGENTS.md,PROCESS.mdцеликом. - Прочитано тело issue #211 и оба комментария (аналитика + «ТЗ готово»), а
также issue #179 целиком — тело и все 15 комментариев обоих циклов ревью
ТЗ и код-ревью, чтобы знать, какие решения владельца уже приняты и что
именно было принято/исправлено там (
M1–M5,L1–L2вSPEC-REVIEW-179-r1.md/r2.md). - Прочитан файл ТЗ
211-device-icons-visual-parity.mdцеликом (354 строки) иdocs/specs/179-device-icons-redesign.mdцеликом — как источник приоритета №4 по собственной цепочке разрешения расхождений ТЗ #211. - Архив дизайнера скачан заново и распакован (
curlпо той же ссылке из тела issue #179,sha256sumсовпал с указанным в ТЗ #21163670C73E25D1E59DDAF1BE236F3D7F2FAC827B9B5D6DD4B77125EA9BC012025) — независимая проверка, не пересказ ТЗ #179:- подтверждена геометрия shell/core (
<path>/<rect>вLight/Dark Icon Default*.svg: shell — круг диаметром101.5, core —<rect rx="40">80×80, отношение1.26875); - подтверждён pill value-badge (
Double Default Right.svg:Frame_2— путьy: 24…87, высота63 = 0.7875×80, радиус скруглений31.5 = 0.39375×80, то есть ровно половина высоты); - подтверждены цвета состояний построчным
grepпоfill/strokeвIcon Hover/Active/Alert Value/Selected/Focus Visible/Lock/Unlock.svgдля обеих тем; - подтверждён
stroke="#252525" stroke-opacity="0.75"вDark/Icon Default No Blur.svg(Dark shell default) иstroke-dasharray "6 6"вVirtual Device *.svg(Virtual shell); - подтверждена сама регрессия, зафиксированная в Dark/Unlock.svg архива
(
fill="#1DC21D", зелёный) — и то, что ТЗ №211 корректно, вслед за ТЗ #179, отвергает этот файл в пользу решения владельца («Unlock — янтарный в обеих темах»), а не проецирует его буквально; - измерена реальная bounding box глифа (
svgpathtools, путьid="Vector") вIcon Default/Hover/Active/Default No Blur.svg(общий «колокольчик») и вLock.svg/Unlock.svg— см. M1 ниже; - проверено существование каждого документа, который ТЗ №211 §4 называет
нормативным источником (
SPECIFICATION.md,DEVELOPER_HANDOFF.md,ACTIVE_ANIMATION_SPEC.md,COMPARISON_NOTES.md) — см. L1.
- подтверждена геометрия shell/core (
- Сверено с текущей реализацией
src/styles.ts(строки 1860–2214): каждое из шести «подтверждённых расхождений» ТЗ §3 сопоставлено построчно с кодом —border-radius: 28%(:1961),--mdc-icon-size: … * 0.62(:1984), value-sectionborder-radius: … * 0.18при высоте.7875(:2180,:2188), безусловныйborder: 1px solid #BCBCBCбез тёмного варианта (:1912). - Прочитаны релевантные фрагменты
docs/USER-GUIDE.ru.md(термин «маркер», отсутствие конфликтующей терминологии) и целикомdocs/TOUCH-SUPPORT.md(«Documentation rule», канонические тегиTouch editor: …). - Код не запускался, гейты не прогонялись — на этапе ревью ТЗ кода нет.
Находки
M1 — целевое соотношение «MDI viewport = 0.5 × core» не подтверждено ни одним источником архива и расходится с прямым измерением SVG
Файл: docs/specs/211-device-icons-visual-parity.md:44-45 (§3, п.2),
:123 (§7.1, таблица), AC1 (:241-244)
ТЗ утверждает как факт: «пакет использует 40 × 40 внутри core 80 × 80, то
есть 0.5 × core» и заносит MDI viewport | width = height = 0.5 в таблицу
геометрического контракта §7.1 с допуском не более 0,5 CSS px на 32/56/96
px (тот же допуск, что и для проверенно точных чисел вроде 1.26875 и
0.7875). Это число прямо используется в AC1 как критерий приёмки.
Проверка источников:
SPECIFICATION.md,DEVELOPER_HANDOFF.md,ACTIVE_ANIMATION_SPEC.md,PACKAGE_ANNOTATION.txt— ни один не называет размер/долю icon-viewport внутри core;SPECIFICATION.md§8 говорит только о shell/core/border/shadow.- Прямое измерение bounding box самого глифа (
svgpathtools, путьid="Vector") в реальных SVG даёт не 0.5:Icon Default/Hover/Active/Default No Blur.svg(общий глиф-колокольчик) —33.33 × 33.33=0.417 × core;Lock.svg/Unlock.svg—26.67 × 35.0=0.333–0.4375 × core. - Единственное место архива, где встречается ровно
50%, — файлIndex.html(.new .glyph { width: 50%; height: 50%; }), интерактивный demo-компаратор «старый/новый» дизайн. Но: (а) он не входит в список источников §4 ТЗ (там перечислены только owner-решения, три.md-документа, «SVG архива» и ТЗ #179 — безIndex.html); (б) сам этот демо-файл использует приближённые круглые px-значения (--core-size: 42pxпри--s: 56px, то есть core/marker≈0.75, тогда как в реальных экспортных SVG это отношение0.7882— расхождение ~5%), то есть он иллюстративный прототип, а не пиксель-точная копия экспортных assets.
Итог: 0.5 — правдоподобное производное значение (bbox глифа + типичный
внутренний padding самих MDI-иконок ≈10–15% могли бы дать assigned-frame
≈39–41), но ТЗ подаёт его как прямую цитату архива наравне с числами, которые
я независимо проверил и подтвердил буквально (1.26875, 0.7875,
0.39375, все цвета состояний). Ни один текстовый документ этого числа не
называет, а единственный SVG-источник с буквальным 50% не упомянут в §4 и
сам не является пиксель-точным.
Почему это важно: AC1 — единственный количественный критерий именно для
формы/масштаба глифа, то есть сердцевина задачи «маркер визуально совпадает с
пакетом». Раздел §11 требует построить независимую таблицу «Reference SVG ↔
Runtime» именно для того, чтобы новый golden не мог сам стать себе эталоном
(это и есть причина, по которой заведён #211). Если строка «Reference SVG»
для glyph viewport унаследует непроверенное число 0.5, фикстура будет
защищать неверную/неподтверждённую цель с той же уверенностью, что и
корректные строки — то есть повторит тот самый механизм регрессии, из-за
которого возник этот баг.
Требуется одно из:
- явно сослаться на
Index.htmlкак источник и показать расчёт (bbox + допущение о внутреннем padding MDI) в §4/§7.1, чтобы ревьюер кода видел основание числа, а не готовый вывод; либо - перенести именно эту строку в §16 «Принятые технические предположения» — как единственную геометрическую величину, не имеющую прямого текстового или однозначного SVG-подтверждения, — и явно разрешить реализации/ревью скорректировать её при визуальном сравнении с реальным MDI-глифом (в отличие от статичного примера-«колокольчика» из пакета).
Находка в скоупе задачи (это её собственный AC1); блокирующей не является — одна Medium без High даёт жёлтый вердикт и правку в этом же ТЗ.
L1 — §4 называет нормативным источником несуществующий файл COMPARISON_NOTES.md
Файл: docs/specs/211-device-icons-visual-parity.md:62-63
Порядок приоритета источников перечисляет «SPECIFICATION.md,
DEVELOPER_HANDOFF.md, ACTIVE_ANIMATION_SPEC.md и COMPARISON_NOTES.md
архива #179». В реально скачанном и распакованном архиве (тот же SHA-256,
что и в ТЗ) присутствуют README.md, SPECIFICATION.md,
DEVELOPER_HANDOFF.md, ACTIVE_ANIMATION_SPEC.md, PACKAGE_ANNOTATION.txt,
manifest.json, Index.html — файла COMPARISON_NOTES.md нет и не было ни
в одной версии архива, которую видел я или которую цитировал разбор #179.
Не блокирует ни один AC (все содержательные факты, которые могли бы там быть, взяты из реально существующих документов и подтверждены), но при реализации кто-то потратит время, разыскивая несуществующий файл как «третий по приоритету» источник истины. Снять правкой — убрать имя файла из списка либо заменить на реально существующий (вероятно, опечатка/перенос из не-#179 контекста).
L2 — обязательный тег Touch editor: … присутствует по смыслу, но не дословно
Файл: docs/specs/211-device-icons-visual-parity.md:183-186 (§8)
docs/TOUCH-SUPPORT.md («Documentation rule») требует, чтобы спецификации,
затрагивающие редактор, буквально называли один из трёх канонических тегов:
Touch editor: supported / best effort / intentionally degraded / not exposed. §8 ТЗ №211 говорит «Device editor остаётся desktop-first / touch
best effort» — по смыслу корректно (совпадает с уже принятым в #179 «best
effort / intentionally degraded») и задача не меняет интерактивность
(в отличие от #179, где отсутствие этого тега было Medium именно потому, что
там вводился новый keyboard/focus контракт), поэтому не блокирует. Для
единообразия с остальными спецификациями и grep-совместимости стоит заменить
на буквальный Touch editor: best effort / intentionally degraded. — на
решение автора.
Проверено и признано корректным
- SHA-256 архива совпадает с указанным в ТЗ; архив идентичен тому, что проверялся в цикле #179.
- Геометрия shell/core (
1.26875) и value-badge pill (0.7875высота,0.39375радиус = половина высоты) — оба подтверждены прямым измерением реальных<path>/<rect>координат, не переписаны на глаз. - Описание регрессии (§3, пп. 1, 3, 4) сверено построчно с текущим
src/styles.tsи подтверждено буквально:border-radius: 28%(core не круг),border-radius: calc(... * 0.18)при pill-высоте0.7875(радиус должен быть0.39375), безусловный светлый#BCBCBCshell-stroke без тёмного варианта. - Цвета состояний (§7.3): hover
#0C82F0, active/unlock#F0A00C, alert#F0410C, Dark shell#252525/opacity .75, virtualstroke-dasharray 6 6, selected#F0A00Cringr=41.5, focus#0C82F0ringr=41.5поверх видимого base shell — все сверены построчнымgrepпо реальным SVG обеих тем и совпадают с таблицей §7.2/§7.3. - Корректно разрешённая ошибка пакета:
Dark/Unlock.svgв архиве реально закрашен зелёным (#1DC21D, устаревшая dark-ревизия) — ТЗ №211 правильно, вслед за уже принятым решением владельца в #179, отвергает этот файл в пользу «янтарный в обеих темах», а не проецирует его буквально. - Обязательные разделы §7.1 PROCESS.md — все присутствуют: сценарий, что видит пользователь до/после, проблема, скоуп/не-скоуп, контракт поведения, UX/touch/доступность, данные/совместимость/i18n, AC1…AC10 с доказательством, план автотестов, риски, откат, release-артефакты.
- Скоуп корректно ограничен восстановлением уже принятого дизайна #179 —
никаких новых состояний, resolvers, LQI-порогов, actions или config-модели
не вводится (§6); это отличает задачу от #179 и обосновывает отсутствие
открытых продуктовых вопросов владельцу без
blocked. - Трассируемость:
docs/specs/README.mdобновлён тем же коммитом с двусторонней ссылкой issue↔ТЗ; коммит93200ebнесёт трейлерыIssue: #211иUser-Visible: no— корректно для документации без изменения продукта. - Секьюрность и touch-инвариант не задеты: §8 явно называет secure confirmation/keyboard/dialog focus return как поведение, которое обязано остаться без изменений, а не переопределяет его.
Чего не проверял
- Figma-фреймы (
99:1290,104:1539) напрямую не открывались — ревью ограничено содержимым скачанного архива, тем же источником, которым пользовался автор ТЗ. - Полная построчная сверка всех Double/Text/LQI SVG всех четырёх сторон —
выборочно проверены
Double Default Right.svg(value pill) и сопутствующийFrame_2; остальные три стороны иText *.svgне измерялись отдельно, поскольку геометрия pill и текста не зависит от стороны по самому контракту §7.1 ТЗ. - PNG-визуализации архива не открывались — не источник геометрических фактов, только иллюстрация.
- Производительность не измерялась (кода нет).
- Гейты
typecheck/test/build/smoke/golden не запускались — на этапе ревью ТЗ продуктового кода не существует, раздел неприменим.
Итог
Находка блокирующей силы не имеет: единственный Medium (M1) устраняется точечной правкой текста ТЗ — либо явной ссылкой на источник и расчёт, либо переносом числа в блок технических предположений §16, — без изменения скоупа, AC или архитектурного решения. Два Low — на усмотрение автора. Вердикт — жёлтый, возврат автору в рамках текущего issue.