Спецификация v3: вёрстка «По Душе» по исходнику Figma (.fig) до абсолютного паритета

Версия 3.0 · 08.09.2026 · один автор и владелец документа — исполняющий агент; заказчик решений — владелец продукта. Заменяет FIGMA_PARITY_SPEC.md v2.5 как порядок работы и критерии приёмки. Раздел 6 старой спеки (описания экранов) остаётся справочником, но подчинён ноде: где проза и нода расходятся, верна нода (см. К-1).

Документ живой: меняется после каждой фазы, каждое изменение — запись в разделе 12. Замороженная спека хуже отсутствующей: ей верят.


0. Мандат (слова заказчика, обязательны дословно)

Ты обязан абсолютно строго и со всей важностью подойти к этому вопросу. Тебе строго запрещается доверять такую работу агентам, субагентам или выполнять её через код. Ты обязан проверять всё руками: буквально брать каждый экран нашего приложения, смотреть его каждое состояние и сверять его с Figma. Задачу нельзя сужать до чего-то меньшего — выполнять в полном объёме. Всегда сам себя перепроверять. Задавать себе множество вопросов «как, почему, зачем, откуда, для чего» и идти выяснять ответы. Время и токены не ограничены. Важен результат, и результат должен быть абсолютным: в точности как в Figma.

Всё ниже — развёртка этого мандата в проверяемые правила.


1. Конституция агента

Правила К-1…К-12 действуют на каждом шаге каждой фазы. Каждое сопровождается причиной (почему оно есть) и способом проверки (как узнать, что оно соблюдено). Нарушение любого — задача не закрыта, независимо от результата.

К-1 · Нода — истина

Правило. Единственный источник размеров, координат, цветов, текстов, порядка слоёв, видимости и вариантов — дерево ноды в файле .fig. Иерархия доказательств, по убыванию: 1. дерево ноды из .fig (/root/figma/podushe-2026-09-08.fig); 2. настоящий рендер кадра из Figma (docs/figma/export/screens/, docs/figma/reference/, съёмка ×3); 3. docs/figma/redlines.md (выдержка из дерева, может быть обрезана по глубине); 4. проза FIGMA_PARITY_SPEC.md раздела 6 и PROGRESS.md. Каждое число в коде обязано иметь адрес ноды (guid = «sessionID:localID», совпадает с id из URL Figma). Число без адреса — выдумка. Почему. Сверка 08.09 нашла не меньше десяти мест, где проза спеки противоречила ноде (карточка города A5, экраны A6/A7, шапка B7, панели CTA B10, шторка жалобы, дата в строке B6). Все они попали в код, потому что агент верил прозе. Проверка. У каждого элемента в карточке сверки (раздел 7) есть колонка «нода → значение». Пустая колонка = нарушение.

К-2 · Сам, руками, глазами

Правило. Всю работу выполняет сам агент: чтение дерева, вёрстка, съёмка, сравнение, вердикт. Субагенты, фоновые агенты и делегирование не используются ни для чего. Скрипты допустимы как инструмент измерения и рутины (разбор .fig, нарезка картинок, подсчёт пикселей, экспорт ассетов) при трёх условиях: агент прочитал код скрипта целиком, проверил его выход на одном примере вручную (открыл картинку, посчитал число сам) и записал эту проверку в карточку. Вердикт «совпадает / не совпадает» выносит только агент, посмотрев на кадр и на цифры. Почему. Субагент и скрипт могут ошибаться и не знают, что ошибаются; ответственность не делегируется. Скриншотный тест на JVM в этом проекте уже давал ложные результаты (Coil, тени, шрифт). Проверка. В журнале каждой задачи есть фраза «проверил вручную: …» с конкретным примером. Вердикт написан от первого лица с описанием того, что агент увидел.

К-3 · Полный объём

Правило. Задача — это все состояния всех кадров экрана, перечисленные в индексе (раздел 8), а не «основное состояние». Закрыть задачу можно только когда каждое состояние прошло ритуал раздела 7. Если часть невозможна (нет решения владельца, нет устройства), агент доводит всё остальное до конца, а невозможное записывает как блокер с доказательством невозможности и точной формулировкой того, что нужно от владельца. Почему. Прошлые вехи закрывались по «основному» состоянию: у B1 сняты 1 из 5 состояний блока «Куда иду», у B10 — 8 из 19 нод. Заказчик прямо запретил сужение. Проверка. В карточке экрана перечислены все guid кадров экрана из индекса, у каждого — статус. Нет строки «остальные аналогично».

К-4 · Протокол вопросов

Правило. Перед вёрсткой каждого экрана и после неё агент письменно задаёт себе и отвечает на вопросы. Обязательный минимум — раздел 7.3 (22 вопроса). Ответ «не знаю» допустим только с планом выяснения и результатом выяснения ниже. Ответ «очевидно» запрещён: очевидное записывается словами. Почему. Все найденные структурные ошибки предотвращались одним вопросом: «откуда это число?», «есть ли этот слой в ноде?», «почему в ноде кнопка справа, а у меня слева?». Вопрос, который не задан, не имеет ответа. Проверка. Карточка сверки содержит заполненный протокол. Пустой пункт = задача не закрыта.

К-5 · Двойная самопроверка

Правило. Каждая задача проверяется дважды. Первый раз — сразу после реализации, по ритуалу. Второй раз — после того, как агент закрыл файлы экрана, заново открыл дерево ноды и рендер и прошёл карточку с чистого листа, как чужую работу. Цель второго прохода — найти хотя бы одну ошибку. Если не найдена, агент записывает, какие именно проверки сделал повторно и почему уверен. Почему. Первый проход видит то, что ожидает увидеть. Автор сверки 08.09 нашёл перевёрнутую карточку города только при втором взгляде на дерево. Проверка. Две датированные записи в карточке: «проход 1», «проход 2» с находками.

К-6 · Ничего не выдумывать

Правило. Если в ноде нет данных (текста, цвета, размера, состояния) или макет противоречит сам себе, агент не выбирает «разумный вариант». Он пишет маркер [ТРЕБУЕТ РЕШЕНИЯ: <точный вопрос с guid и двумя вариантами>] в раздел 4 и в карточку, продолжает всё, что от решения не зависит, и останавливает только зависимую часть. Почему. Каждая догадка — это отклонение, которое потом ищут часами. Заказчик: «нельзя угадывать на авось». Проверка. Все FIGMA-CHECK в коде имеют пару в разделе 4. В коде нет значений с комментарием «примерно», «похоже», «на глаз».

К-7 · Красный diff — не закрыто

Правило. Доказательство соответствия — только сравнение картинок: скриншот экрана приложения с устройства/эмулятора в ×3 против рендера ноды в ×3, выровненные по верхнему инсету, с числовым результатом (раздел 6). Допуск «±2 dp» отменён. Пока сравнение красное, задача открыта. «Совпало визуально» без цифр не принимается. Почему. Снимки Paparazzi 462×1000 и оценка «в допуске» пропустили сдвиги в 20–96 dp (A4, B6, B7). Проверка. В карточке лежат три файла: скриншот, рендер, diff, и число расхождения.

К-8 · Журнал с доказательствами

Правило. После каждой задачи — запись в docs/figma/PROGRESS.md по шаблону раздела 9 и карточка сверки в docs/figma/cards/<guid>.md. Запись содержит только факты, которые можно перепроверить: guid, файлы, числа, команды. Слова «готово», «совпадает», «исправлено» без файла-доказательства запрещены. Почему. Журнал v2 содержал «совпали с нодами» для экранов, которые с нодами не совпадали. Проверка. Каждое утверждение в записи имеет ссылку на файл или guid.

К-9 · Границы кода

Правило. Изменения только внутри android-events/. Строки — только res/values/strings.xml, дословно из ноды (включая «ё», пробелы и многоточия). Цвета — только токены PodusheColors, значения из ноды. Типографика — PodusheType, стили из ноды (вес, кегль, интерлиньяж, трекинг). Ассеты — только из .fig. Нет ручки на бэке — Fake*Repository с // BACKEND-GAP: <что нужно>. backend/, ios/, web-* не трогать. Токены и ключи не коммитить. Почему. Унаследовано из v2.5, раздел 2 и 3; проверено, работает. Проверка. grep -rn '"[А-Яа-яЁё]' app/src/main/java/ru/podushe/app/ui пуст; git diff --stat не выходит за android-events/.

К-10 · Сборка и тесты зелёные всегда

Правило. Перед каждым коммитом: ./gradlew :app:assembleDushaDebug, :app:lintDushaDebug, :app:testDushaDebugUnitTest — все зелёные. Один коммит — одна задача, сообщение по формату репозитория, в теле — guid нод и ссылка на карточку. Проверка. Вывод команд в записи журнала.

К-11 · Время и токены не ограничены

Правило. Агент не ускоряется за счёт глубины. Если проверка требует открыть 40 нод — открыть 40 нод. Если ритуал нужно повторить пять раз — повторить пять раз. Единственный критерий остановки — раздел 2. Почему. Заказчик: «мне всё равно, сколько времени и токенов; важен абсолютный результат».

К-12 · Читать этот документ перед каждой задачей

Правило. Перед началом каждой задачи агент перечитывает разделы 1, 6 и 7 целиком и раздел 4 (открытые решения). Перед началом каждой фазы — весь документ. Проверка. Первая строка записи журнала задачи: «Перечитал К-1…К-12, разделы 6, 7, 4 в версии <номер>».


2. Цель и определение готовности

Цель. Каждый кадр каждого рабочего раздела макета присутствует в приложении и неотличим от макета при сравнении по правилам раздела 6.

Рабочие разделы и объём (по дереву .fig, кадры шириной 390):

Страница guid страницы Кадров
Авторизация и регистрация 112:160 62
Афиша 579:52323 117
Создание и управление событием 579:52328 99
Взаимодействие участников с событием 792:36278 80
Свайпы событий 579:52324 17
Уведомления 579:52326 6
Избранные 579:52327 9
Профиль 579:52329 54
Чаты и другие пользователи 579:52330 23
Настройки 634:54612 23
Итого 490

Страницы «Прототип» (270 копий), «Архив» (81), «Дизайн концепт» (7), «Cover», «Internal Only Canvas» — не объём работы; секции с пометкой «NEW … от 25 авг 2026» имеют приоритет над старыми версиями тех же экранов (решение владельца из v2.5 сохраняется).

Готово (DoD) — все пункты для каждого из 490 кадров:

# Критерий Метод проверки
Г-1 Каждый видимый слой ноды имеет соответствие в приложении: тот же тип (текст, картинка, фигура), та же вложенность, тот же порядок отрисовки. Скрытые слои (visible=false) отсутствуют. Инспекция дерева против дерева Compose, карточка 7.4
Г-2 Геометрия: положение и размер каждого элемента совпадают с нодой с отклонением не больше 0,5 dp (1,5 px при ×3). Измерение по скриншоту ×3, раздел 6.3
Г-3 Цвета и прозрачности совпадают точно (hex и alpha из ноды), включая заливки, обводки, тени, градиенты, материал стекла. Инспекция токенов + пипетка по скриншоту в трёх точках на элемент
Г-4 Тексты совпадают побайтно с characters ноды, стиль совпадает (семейство, начертание, кегль, интерлиньяж, трекинг, регистр, выравнивание, перенос). Сравнение строк + измерение блока текста
Г-5 Ассеты (иконки, 3D, фото, тайлы карт) взяты из .fig, а не заменены похожими. Список ассетов экрана с sha1 источника
Г-6 Состояние воспроизведено на устройстве с теми же данными, что в ноде (раздел 5.4). Скриншот
Г-7 Сравнение скриншота с рендером ноды по правилам раздела 6 зелёное. Число diff в карточке
Г-8 Переходы из ноды (коннекторы .fig, flows.md) работают, либо стоят BACKEND-GAP с указанием ручки. Список переходов в карточке
Г-9 В коде экрана нет FIGMA-ASSET, FIGMA-CHECK, CONTENT-GAP, legacy_*. grep

Готовность проекта: все 490 кадров с Г-1…Г-9, все [ТРЕБУЕТ РЕШЕНИЯ] закрыты владельцем, финальный REPORT.md (раздел 9.3) собран, полный повторный проход раздела 6 по всем кадрам зелёный.

Не-цели (без изменений с v2.5): серверная логика, пуши/FCM, платежи, распознавание лица, геокодер, ios/, web-*, backend/. Живая карта MapLibre не сравнивается с картинкой карты в макете попиксельно (раздел 6.4, исключения).


3. Входы и инструменты

3.1 Исходник макета

3.2 Что уже есть в репозитории (справочно, подчинено .fig)

3.3 Устройство для съёмки

Сравнение раздела 6 требует экрана 390×844 dp при плотности 3× (1170×2532 px). Варианты: AVD с такими параметрами на машине с KVM; физический телефон с последующим приведением к 390 dp (только если ширина экрана в dp ровно 390, иначе масштаб искажает 1 px линии). Текущий сервер без KVM — это блокер Б-1, снимается владельцем (раздел 4).


4. Открытые решения владельца

Формат: [ТРЕБУЕТ РЕШЕНИЯ] · вопрос · варианты · что блокирует · дата. Агент дописывает сюда каждый новый вопрос (К-6) и не двигает зависимую часть, пока строка не закрыта.

ID Вопрос Варианты Что блокирует
Р-3 Шрифт. Макет набран SF Pro; на Android его лицензионно ставить нельзя; без него текст не совпадёт по форме букв никогда. а) дизайнер переводит макет на шрифт, разрешённый для APK, присылает новый .fig; б) остаётся Inter, критерий Г-4/Г-7 для текста меняется на «ширина и высота блока ±1 px, форма букв не сравнивается»; в) иное Г-4, Г-7 для всех кадров
Р-4 Верхний инсет. Кадр макета — iPhone со статус-баром 54 dp. а) фиксированный отступ 54 dp на любом Android (совпадение с макетом гарантировано); б) системный инсет (на большинстве устройств контент выше макета на 6–30 dp) Г-2 для всех кадров с шапкой
Р-5 Стекло. Liquid Glass с размытием требует RenderEffect (Android 12+). а) minSdk 31; б) ниже 31 — плоское стекло, кадры на таких устройствах из сравнения исключаются Г-3 для стеклянных элементов
Р-6 Порог diff (раздел 6.3). Предложение: ≤ 0,3 % пикселей кадра с ΔE > 6 вне области живой карты и, при Р-3-б, вне ограничивающих прямоугольников текста. принять / изменить числа Г-7
Р-7 Карта. Живая MapLibre не совпадёт с картинкой карты макета. а) исключить область карты из diff (предложение); б) статичная подложка из .fig для превью в A5/B3/B10 Г-5, Г-7 для карт
Р-8 Устройство. Нет KVM на сервере. а) машина с KVM; б) телефон 390 dp шириной по adb Б-1, все Г-7
Р-9 Противоречия макета (передать дизайнеру): поле номера 44 (261:25228, 582:52876, 579:52473) или 46 (260:24430); короткий юридический текст в 261:25228; полоса шагов на «Шаг 2» (291:25219 — половина у второго сегмента, первый пуст) против правила остальных шагов; подписи дней недели в 194:27047 сдвинуты («Сб Вс Пн…»); базовое состояние фильтров 194:24494 с выбранным районом и одной кнопкой; карточка рельса 300×228 (610:75563) против 300×262 (NEW-ноды); кнопка «назад» на A2 (слот пустой во всех четырёх нодах). ответ по каждому пункту Соответствующие кадры
Р-10 Формат рендеров. Съёмка кадров ×3: экспорт из интерфейса Figma владельцем (по страницам: выделить кадры → PNG 3x → Export) или досъёмка tools/figma_shots.py с device_scale_factor=3 (нужна живая сессия Figma в браузере). а / б Ф0 шаг 6

Решения v2.5 остаются в силе: Р-1 (сжатие 0,72 для весов 650/760 — действует, пока не решён Р-3), Р-2 (Paparazzi допустим только как черновая проверка, доказательством не является).


5. Фазы работы

Фазы строго последовательны. Фаза закрыта, когда выполнен её критерий завершения и запись о закрытии есть в PROGRESS.md. Внутри фазы задачи идут по ритуалу раздела 7.

Ф0 · Подготовка: инструменты, ассеты, индекс

  1. Развернуть разбор .fig (3.1). Критерий: скрипт tools/fig_dump.py пишет docs/figma/fig/<page-guid>.json (полное дерево страницы) для 10 рабочих страниц и docs/figma/fig/index.md — таблица всех 490 кадров: guid, страница, секция, имя, размер, число видимых слоёв, есть ли рендер. Агент открывает пять случайных строк индекса и сверяет с деревом вручную (К-2).
  2. Иконки: все 74 мастер-компонента icon-* из .fig → SVG → res/drawable/ic_<name>.xml (VectorDrawable). Критерий: для каждой иконки — растр ×8 из SVG рядом с растром той же иконки из настоящего рендера кадра, где она встречается; агент смотрит каждую пару глазами и записывает вердикт в docs/figma/fig/icons.md. AppIcons.kt переключён на ресурсы; Icons.Outlined/Filled в ui/ больше не импортируются.
  3. 3D-иллюстрации: 23 мастер-компонента 3D-icon-* → PNG из images/ (исходный размер) → drawable-xxxhdpi (×4 при необходимости, без апскейла), -xxhdpi (×3), -xhdpi (×2). Критерий: Icon3d получает ресурсы, пустых слотов не остаётся; docs/figma/fig/3d.md с таблицей имя → sha1 → размеры.
  4. Фото и растры экранов: фото коллажа A1 (слои ноды 158:9505), обложки демонстрационных событий, аватары, тайлы карт из images/. Коллаж A1 собирается из слоёв по дереву, welcome_collage.png удаляется. Критерий: docs/figma/fig/rasters.md — какая картинка где используется, с guid.
  5. Данные макета для съёмки: из characters текстовых нод собрать data/mock/DesignFixture.kt — события, люди, чаты, счётчики, даты ровно как в нодах (например, событие «WATT Conf 2026: AI продукты», «14 марта, 10:00 - 18:00», «66 Идёт», «Данил Колбасенко, Андро и ещё 64»). Критерий: каждая строка фикстуры имеет guid текстовой ноды в комментарии.
  6. Рендеры ×3 всех 490 кадров (Р-10). Критерий: docs/figma/fig/renders/<guid>.png, 1170×N; индекс отмечает наличие; кадров без рендера — ноль, либо перечень с причиной и [ТРЕБУЕТ РЕШЕНИЯ].
  7. Устройство (Р-8) и скрипт съёмки tools/shoot.py: по имени состояния поднимает экран с фикстурой и сохраняет docs/figma/shots/<guid>.png. Критерий: снимок A1 сделан и совпадает по размеру с рендером.
  8. Инструмент сравнения tools/diff.py по разделу 6: вход — два PNG и маска исключений, выход — число, тепловая карта, список прямоугольников расхождений. Критерий: агент проверил инструмент на трёх заведомых парах: одинаковые кадры (0), кадр со сдвигом на 1 px (число и прямоугольник видны), кадр с другим цветом кнопки (найдено). Результаты в docs/figma/fig/diff-selftest.md.
  9. Шрифт по Р-3, инсет по Р-4, стекло по Р-5 — применить решения. Пока решения нет — в журнале строка о том, что Ф1 идёт с текущими значениями, и все Г-7 помечены «предварительно».

Критерий завершения Ф0: пункты 1–8 закрыты с доказательствами; запись «Ф0 закрыта» с перечнем файлов.

Ф1 · Ревизия готового

Объём: все экраны, отмеченные в v2.5 как собранные (A1–A12, B1–B7, B9–B14), по всем кадрам этих экранов из индекса, а не по 55 снимкам. Это 62 кадра раздела A и все кадры раздела B соответствующих экранов.

  1. Для каждого кадра — карточка сверки (7.4) с полным ритуалом 7.1–7.3, кроме шага «исправить»: в Ф1 код не правится. Найденное записывается в реестр расхождений docs/figma/fig/ledger.md (формат 9.2).
  2. Реестр 8.2 этого документа (находки 08.09) проверяется первым: каждая строка либо подтверждается карточкой, либо опровергается с доказательством.
  3. По итогам — обновить этот документ: раздел 8.1 (статусы), раздел 4 (новые [ТРЕБУЕТ РЕШЕНИЯ]), и заменить в FIGMA_PARITY_SPEC.md разделе 6 каждую фразу, противоречащую ноде, на значение из ноды с guid (правки перечислить в 12).

Критерий завершения Ф1: у каждого кадра ревизуемых экранов есть карточка с числом diff и списком расхождений; реестр полон; спека обновлена; запись «Ф1 закрыта» с количеством кадров, расхождений по классам (структура / геометрия / цвет / текст / ассет / поведение).

Ф2 · Исправления

  1. Порядок — по весу из реестра: сначала структурные (не тот слой, не та кнопка, не тот порядок), потом геометрия, цвет, текст, ассеты.
  2. Каждое исправление проходит ритуал целиком, включая повторный diff всех кадров экрана (правка одного состояния ломает соседние).
  3. Компонентные дефекты (FilterChip без галочки, EventRow без даты и с ценой из скрытого слоя, обложка r8 вместо r12, PodusheActionSheet вместо алерта 300) правятся в компоненте и затем перепроверяются на всех экранах, где компонент используется — список берётся grep-ом и записывается в карточку.

Критерий завершения Ф2: реестр Ф1 пуст или содержит только строки с закрытым [ТРЕБУЕТ РЕШЕНИЯ], у каждого кадра ревизуемых экранов Г-1…Г-9 зелёные.

Ф3 · Вёрстка остального

Порядок (по зависимостям v2.5): M3 (B10 остаток: 232:26455, D3 регистрация с вопросами; B11 остаток; I4 личный чат; I1 список чатов) → M4 (C1–C13, D4–D5 — секция NEW от 25 авг) → M5 (H1–H9, I2–I5, J1–J5) → M6 (E1–E6, F1–F2, G1–G2). Для каждого экрана: 1. Составить из индекса список всех его кадров (состояний). Список — часть карточки. 2. Прочитать дерево каждого кадра целиком, выписать структуру слоёв (7.2). 3. Сверстать, снять, сравнить, править до зелёного — ритуал 7.1. 4. Старый экран удаляется только после того, как новый прошёл все кадры; маршрут не остаётся пустым.

Критерий завершения Ф3: все 490 кадров с Г-1…Г-9.

Ф4 · Финиш

  1. Снять все пометки FIGMA-ASSET, FIGMA-CHECK, CONTENT-GAP, ключи legacy_*, мёртвый код старых экранов.
  2. Полный повторный проход раздела 6 по всем 490 кадрам заново (не по старым карточкам) — регрессия после всех правок.
  3. docs/figma/REPORT.md (9.3).

Критерий завершения Ф4: отчёт собран, в нём 490 строк с зелёным diff, [ТРЕБУЕТ РЕШЕНИЯ] нет.


6. Правила сравнения

6.1 Эталон

Рендер ноды из Figma ×3 (1170 px шириной). Локальная отрисовка по дереву (docs/figma/local/) эталоном не является. Рендер ×2 допускается только временно, с пометкой «предварительно», до Ф0-6.

6.2 Снимок

Скриншот приложения на устройстве 390×844 dp ×3 с фикстурой макета (Ф0-5), в состоянии кадра. Снимок делается после завершения всех анимаций и загрузок; Coil получает картинки из .fig локально, без сети.

6.3 Выравнивание и метрика

  1. Снимок и рендер приводятся к одной системе координат: при Р-4-а без сдвига; при Р-4-б снимок сдвигается на (54 − инсет устройства) dp.
  2. Маска исключений: область живой карты (Р-7-а); при Р-3-б — прямоугольники текстовых нод (их положение и размер при этом всё равно измеряются по Г-4).
  3. Метрика: доля пикселей вне маски с ΔE2000 > 6; порог по Р-6 (предложение 0,3 %). Дополнительно — для каждого элемента кадра из дерева измеряется его ограничивающий прямоугольник на снимке (по цвету/краям) и сравнивается с нодой: Г-2 требует ≤ 0,5 dp по каждой стороне.
  4. Зелёный = обе проверки прошли. Красный = хотя бы одна нет. Число и тепловая карта сохраняются в карточку.

6.4 Что не сравнивается попиксельно и почему


7. Ритуал задачи

7.1 Шаги (по порядку, каждый — с критерием завершения)

  1. Перечитать К-1…К-12, разделы 4, 6, 7. Критерий: строка в журнале (К-12).
  2. Собрать кадры экрана из индекса. Критерий: список guid со ссылками на рендеры, ни один кадр экрана не пропущен (проверить по индексу и по секции страницы в дереве — два независимых источника).
  3. Прочитать дерево каждого кадра до листьев. Выписать структуру (7.2). Критерий: у каждого видимого слоя есть строка в структуре; скрытые отмечены как скрытые.
  4. Протокол вопросов 7.3 — до вёрстки. Критерий: все 22 пункта заполнены.
  5. Сверстать по структуре: каждый размер, цвет, текст — с guid в комментарии кода или в карточке. Критерий: сборка зелёная; grep кириллицы в ui/ пуст.
  6. Снять каждый кадр (6.2). Критерий: файл снимка на каждый guid.
  7. Сравнить (6.3). Критерий: число и тепловая карта на каждый guid.
  8. Разобрать красное: для каждого прямоугольника расхождения — какой слой, какое значение в ноде, какое в коде, почему. Критерий: у каждого прямоугольника есть объяснение и правка либо [ТРЕБУЕТ РЕШЕНИЯ].
  9. Править и повторять 5–8 до зелёного на всех кадрах экрана. Критерий: все кадры зелёные одновременно.
  10. Протокол вопросов 7.3 — после вёрстки, второй проход (К-5). Критерий: заполнен; найденные ошибки исправлены и снова 5–9.
  11. Компоненты: если менялся общий компонент — список всех экранов, где он используется, и повторные снимки их кадров. Критерий: все они зелёные.
  12. Журнал и карточка (9.1, 7.4). Критерий: файлы записаны, коммит сделан.

7.2 Структура слоёв (что выписывать из дерева)

Для каждого слоя: guid · тип · имя · видимость · x, y, w, h относительно кадра · auto-layout (направление, паддинги, gap, выравнивание, fill/hug/fixed) · скругления · заливки (тип, цвет, alpha, blend) · обводки (цвет, толщина, положение) · эффекты (тень, blur, background blur) · для текста: characters, шрифт, кегль, интерлиньяж, трекинг, выравнивание, перенос, максимум строк · для инстансов: мастер-компонент и переопределения (overrides) · для картинок: sha1 · для векторов: наличие vectorNetwork. Особое внимание: слои с opacity < 1 и слои Liquid Glass Material (стекло) — их материал воспроизводится, а не заменяется белой заливкой.

7.3 Протокол вопросов (обязательный минимум, письменно)

  1. Откуда взято каждое число на экране? (guid для каждого; числа без guid — искать)
  2. Какие кадры у этого экрана есть в .fig, все ли они в моём списке? Чем я доказал, что не пропустил ни одного?
  3. Какие слои в ноде скрыты? Почему я уверен, что не нарисовал скрытый и не пропустил видимый?
  4. Есть ли у инстанса переопределения, и учтены ли они? (например, текст, иконка, вариант)
  5. Что в ноде лежит поверх чего? Совпадает ли порядок отрисовки?
  6. Из какого материала элемент: сплошная заливка, стекло, градиент, картинка? Чем это доказано?
  7. Какой шрифт, кегль, вес у каждого текста в ноде, и что стоит в PodusheType?
  8. Где текст переносится в ноде и где у меня? Почему?
  9. Что происходит с элементом при инсете 24, 48, 54 dp? Где это в ноде?
  10. Почему элемент именно здесь, а не выше/ниже? Какой auto-layout это задаёт?
  11. Как этот экран получает данные, и совпадают ли данные снимка с текстами ноды?
  12. Какие переходы ведут в этот кадр и из него (коннекторы)? Все ли работают?
  13. Что общего у этого экрана с уже сделанными компонентами, и не сломает ли правка компонента другие экраны? Какие именно (grep)?
  14. Что в прозе v2.5 об этом экране противоречит ноде? Что я сделал с этим противоречием?
  15. Что в ноде противоречит другой ноде того же экрана? Записано ли в Р-9?
  16. Где я мог принять «похоже» за «совпадает»? Перепроверил ли это число измерением?
  17. Что показал diff, и объяснён ли каждый прямоугольник?
  18. Что бы сказал дизайнер, глядя на мой снимок рядом с рендером? Что первым бросится в глаза?
  19. Что я не проверил, потому что было долго? (ответ «ничего» требует перечисления того, что было проверено)
  20. Зачем этот экран пользователю, и не потерял ли я элемент, ради которого он нужен (кнопка, статус, подсказка)?
  21. Как я узнаю, что ошибся, если ошибся? Какая проверка это поймает?
  22. Что нужно от владельца, чтобы закрыть кадр полностью, и записано ли это в раздел 4?

7.4 Карточка сверки docs/figma/cards/<guid>.md

# <guid> · <страница> · <секция> · <имя кадра>
Экран: <код экрана из v2.5>   Состояние: <описание>   Рендер: <путь>   Снимок: <путь>   Diff: <путь>, <число>, порог <число>, маска <что исключено>
## Структура (7.2)
| guid | слой | видим | x y w h | стиль | значение в коде (файл:строка) | статус |
## Протокол вопросов до / после (7.3)
1. … 22. …
## Расхождения
| # | слой | нода | приложение | класс | правка / [ТРЕБУЕТ РЕШЕНИЯ] |
## Проход 1 (дата) · Проход 2 (дата)
## Переходы
## Вердикт: зелёный / красный — что именно измерено

8. Реестр экранов

8.1 Статус на 08.09.2026 (до Ф1; уточняется в Ф1)

Экран Кадры (guid, основные) Статус Куда
A1, A2, A3, A8, A9, A10, A11, A12 158:9505; 260:24430 261:25228 582:52876 579:52473; 261:26902; 291:25219 292:25695 292:25797 + 16 кадров состояний; 284:25333 284:25738; 284:26282 286:26404 287:26637; 287:26990 287:27445 287:27198 732:79437; 287:27892 по нодам, отличия только шрифт и ассеты Ф1 → Ф2 (ассеты)
A4 261:26987 261:27203 261:27297 592:5040 261:27386 расхождения: 6 ячеек, подзаголовок 1 строка (сдвиг 20 dp), стёртые цифры при лимите Ф2
A5, A6, A7 597:55329 597:56595 730:75312 + 7; 597:56057 + 4; 609:74123 609:74208 структурные расхождения (8.2) Ф2
B1, B12 180:8884 181:9778 693:70691…73689 + 6 карточка «Куда иду» не стекло; 4 состояния не сняты Ф1 → Ф2
B2, B5, B9, B13 180:9724; 194:27047 194:27117 229:16403 229:16598; 194:36070 229:14429 229:14668 229:14863; 693:76501 693:74315 по нодам Ф1
B3, B4, B6, B7 194:24494 + 11; 604:65659 605:67468 605:67692; 192:19379 + 4; 610:75563 + 10 расхождения (8.2) Ф2
B10, B11 230:19369 + 18; 232:22272 + 22 расхождения (8.2), не все кадры сделаны Ф2 → Ф3
B14 794:161851 794:161397 804:77055 не сверено (нет рендера) Ф1
C0–C13, D1–D2, E1–E5, F1–F2, G1, H1, H2, H8, I1, I5, J1–J4 по индексу старая вёрстка, не по нодам Ф3
C2, C4, C6, C8, C9, C11, C12, D3–D5, E3, E6, G2, H3–H7, H9, I2–I4, J5 по индексу экрана нет Ф3

8.2 Реестр расхождений, найденных 08.09 (проверить первыми в Ф1)

  1. B10 231:20559, 232:28174: низ — button-delete «Отменить» 116×48 на (24, 772) + button-secondary «Перейти в чат» 218×48 на (148, 772) с иконкой чата; snackbar 342×50 r20 на (24, 706) «Вы участвуете в событии» / «Вам одобрили участие». В коде — «Перейти в чат» + «✓ Вы идёте» / подпись + «✓ Заявка одобрена»; в навигации onOpenChat = null.
  2. B10 232:28673: snackbar «Организатор отклонил ваше участие», кнопка «Участие отклонено» стиля delete. В коде «Заявка отклонена» стиля primary.
  3. B10 232:27767 и 232:26224: иконки в кнопках (галочка; icon-user-group). В коде нет.
  4. B10 232:26455: «Подать заявку на участие» (button-brand-large). В коде текста нет.
  5. B10 348:42416: пилюля «✓ Событие завершено» вместо кнопки. В коде «Оставить отзыв».
  6. B10 230:19369: кнопка «открыть в картах» 40 r12 на (326, 809) — правый нижний угол мини-карты. В коде правый верхний. Пейджер обложек (бейдж 66×19 на y=457) отсутствует.
  7. B10 608:70144–70529: девять причин жалобы; второй шаг «Расскажите, что произошло» с подписью и полем «Ваша жалоба…» для любой причины. В коде один шаг.
  8. B10 231:21452: алерт 300×284 на (45, 280) «Вы действительно хотите отменить участие?» с описанием, «Отменить участие», «Назад». В коде диалог 250 без описания и с другим заголовком.
  9. A5 597:55329 (Frame 2147225622): строка 358×64 (плитка 40 r8 с icon-map-pin-fill, «Москва», «Определили по геопозиции», «Изменить») над картой 358×140 r20. В коде порядок обратный, плитки нет. icon-Buildings в чипе «Весь город». Галочка у выбранного чипа.
  10. A6/A7 597:56057, 609:74123: белый блок 390×184 r0/0/32/32 с тенью 8 (шапка + поле 358×48 на y=120), список на #F5F5F5, строки 60 (A6) / 64 (A7), чекбокс 24 на x=16 слева от названия. В коде обычный лист с верхними углами, строки 44/65, чекбокс справа.
  11. B6 192:20640: строки с шагом 141 (gap 16 + разделитель 1 + gap 16), дата «29 июля · 11:00» 590/14@40 % справа от бейджа, цена скрыта (Frame 2147225420 visible=false); чипы категорий 3 + 2. В коде шаг 109, даты нет, цена есть, чипы 2 + 2 + 1.
  12. B7 610:75563: шапка — слева icon-calendar, справа icon-magnifying-glass, «Москва» с icon-chevron-down, «Алтуфьевский» без шеврона; «Афиша города» на y=132. В коде: «назад» / календарь, шеврон у района, заголовок на y=156.
  13. B1 693:70691: Upcoming Events Card — Liquid Glass Material (r24, слой Fill+Shadow r34). В коде белая непрозрачная r20.
  14. B3 194:24494: чипы районов по ширине (2 / 3 / 1), галочка у выбранного; превью карты — картинка. В коде chunked(2), без галочки, плашка с пином.
  15. B11 232:22272: кнопка «•••» 48 на (326, 64); обложка карточки 52 r12; иконка часов перед «Уже завтра в 10:00»; голубая кнопка отправки. 232:25394: пустое состояние по центру ленты (3D на y=421). В коде: кнопки нет и onMenu не передаётся, r8, часов нет, пустое состояние под карточкой.
  16. A1 158:9505: welcome_collage.png содержит iOS-статус-бар; слои коллажа не собраны.
  17. A4: подзаголовок в две строки («+7 ( 912 ) 888-92-62» второй строкой), 4 ячейки 84×96 (решение по 6 ячейкам — записать в Р-9), цифры при лимите остаются.
  18. A2: слот «назад» пустой во всех четырёх нодах (Р-9); поле 44 в трёх нодах.
  19. B9 229:14429: галочка перед «Вы подписаны». Цена в строках событий (скрытый слой) — во всех списках.
  20. B5 194:27047: подписи дней «Сб Вс Пн Вт Ср Чт Пт» (Р-9).
  21. B14 794:161851: карточки 300×228, иконка 24×32 справа от заголовков блоков.
  22. Компоненты: FilterChip без галочки в активном состоянии; EventRow (см. 11 и 19); PodusheActionSheet (см. 8); стекло liquidGlass не проверено на устройстве.

8.3 Ловушки (проверять при каждом кадре)


9. Отчётность

9.1 Запись в PROGRESS.md после каждой задачи

### <дата> · <экран> · кадры: <guid, …>
Перечитал К-1…К-12, разделы 4, 6, 7 в версии <x.y>.
Кадров всего/зелёных: N/N. Diff по кадрам: <guid>: <число> …
Проверил вручную: <что именно, на каком примере>.
Расхождения найдены/закрыты: <ссылки на ledger>.
[ТРЕБУЕТ РЕШЕНИЯ]: <новые строки раздела 4 или «нет»>.
Команды: assemble ✓ lint ✓ test N ✓. Коммит <hash>.
Карточки: docs/figma/cards/<guid>.md …

9.2 Реестр расхождений docs/figma/fig/ledger.md

Одна строка — одно расхождение: id · guid кадра · guid слоя · класс (структура / геометрия / цвет / текст / ассет / поведение / материал) · нода → приложение · вес (1 — не тот элемент или порядок; 2 — сдвиг ≥ 4 dp или не тот размер; 3 — цвет, материал, ассет; 4 — до 4 dp, трекинг, перенос) · статус · карточка.

9.3 Итоговый docs/figma/REPORT.md

Таблица 490 строк: guid · экран · рендер · снимок · diff · число · вердикт · карточка. Плюс: список решений владельца с ответами; список исключений масок; список BACKEND-GAP; список удалённого кода.


10. Формат требований в этом документе

Требования пишутся по EARS: «<система> ДОЛЖНА <ответ>» (постоянные), «КОГДА <событие>, … ДОЛЖНА …», «ПОКА <состояние>, …», «ЕСЛИ <нежелательное>, ТО …». Одно требование — одно условие; у каждого — способ проверки и адрес ноды. Слова «примерно», «похоже», «как правило», «по возможности» в требованиях запрещены; неясность помечается [ТРЕБУЕТ РЕШЕНИЯ] и не реализуется.


11. Глоссарий

Кадр — фрейм шириной 390 на рабочей странице, одно состояние экрана. Экран — код из v2.5 (A1…K5), объединяющий кадры. Нода — узел дерева .fig с guid. Рендер — картинка кадра из Figma. Снимок — скриншот приложения. Diff — результат сравнения по разделу 6. Карточка — файл сверки кадра (7.4). Реестр — ledger расхождений (9.2). Зелёный/красный — вердикт diff по порогу Р-6.


12. Журнал изменений документа