
# Формат данных Scene {/* #scene-data-format */}

О регистрации, входе и процессах расширений Chrome см. [ручную запись и проверку](/docs/ru/manual-recording). Рекордер использует тот же контракт Scene и публикует изображения только после проверки администратором.

`reconstruct.scene.v1` описывает наблюдаемый интерфейс независимо от исходного или целевого UI-фреймворка. Web DOM/CSS и представления/доступность Android — входные данные адаптеров. Потребитель может генерировать HTML, Compose или другой UI, не делая нативные структуры канонической моделью данных.

Скачиваемая [JSON Schema](https://reconstruct.dev/docs/schemas/scene-v1.schema.json) определяет точные имена полей, обязательные члены, nullable-типы и перечисления. Снимок документации сопровождается [SHA-256](https://reconstruct.dev/docs/schemas/scene-v1.schema.json.sha256). Для реальных захватов используйте схему и контрольную сумму, возвращённые работающим сервером с экспортом.

[Полный пример](https://reconstruct.dev/docs/examples/scene-export-v1.example.json) содержит кадры закрытого/открытого диалога и два перехода. Это иллюстративные данные: свидетельства `example:` вымышлены, а не измерены на продукте.

## Окружение Web Extension {/* #web-extension-environment */}

Захваты настольных расширений Chrome используют `web-extension` (внутреннее C# / Admin MCP — `WebExtension`, значение protobuf `CAPTURE_TYPE_ENVIRONMENT_WEB_EXTENSION = 6`). Мобильная платформа это окружение не поддерживает. Геометрический контракт Scene остаётся тем же. Версия может содержать типизированные метаданные `browserExtension`: `id`, `name`, `version` и `packageSha256`; `displayName` берётся из проверенного пакета. Экраны записываются административным заданием и не публикуются до проверки. Управление и границы приватности описаны в [ручной записи](/docs/ru/manual-recording).

Внутренний запрос получения задания агентом включает `expected_environment` (поле 2). Пропуск сохраняет Web для старых обработчиков. Очередь сверяет значение с окружением агента внутри транзакции получения, поэтому изменение настроек Admin не заставит обычный Web-обработчик обходить магазин расширений. Эти механизмы очереди не являются публичными инструментами Capture MCP.

## Транспорт и получение {/* #transport-and-acquisition */}

Нормализованный экспорт сейчас доступен через MCP [`get_interface_scene`](/docs/ru/mcp-tools#platform-neutral-interface-scene). Опубликованные контракты каталогов [REST](/docs/ru/api/rest) и [gRPC](/docs/ru/api/grpc) пока не определяют отдельную операцию Scene. Ответы каталогов, анализа и сохранённых файлов — отдельные модели даже при передаче в JSON.

Найдите захват через `list_products`, `list_platforms`, `list_versions` и `list_pages`. Сохраните выбранные продукт, версию, окружение, страницу и точный `view`. Поддерживаемые платформы не доказывают наличие захвата. Запрашивайте сохранённые представления отдельно и проверяйте собственные профили и кадры каждого экспорта.

Пример параметров MCP `tools/call` с иллюстративным выбором:

```json
{
  "name": "get_interface_scene",
  "arguments": {
    "product": "example-product",
    "version": "1",
    "environment": "web",
    "page": "settings",
    "view": "mobile"
  }
}
```

Ответ — компактный **манифест**:

| Поле | Значение |
| --- | --- |
| `schema` | Идентификатор Scene: `reconstruct.scene.v1`. |
| `artifactSchema` | Идентификатор оболочки: `reconstruct.scene-export.v1`. |
| `path`, `uri`, `sha256`, `bytes` | Расположение экспорта, SHA-256 и размер в байтах. |
| `schemaPath`, `schemaUri`, `schemaSha256` | Применимая JSON Schema и её хеш. |
| `entryFrameId`, `frames`, `transitionCount` | Начальный кадр, компактный список кадров и число переходов. |
| `frameCount`, `profileCount`, `assetCount` | Количества объектов в экспорте. |
| `truncated` | Хотя бы один кадр неполон. |
| `issueCount`, `issues`, `issuesTruncated` | Общее число проблем и предварительный список максимум из 30. |

Пути принадлежат **файловой системе сервера**. Читайте их напрямую, только если она действительно общая с клиентом. Иначе разрешайте URI относительно источника MCP и скачивайте с существующей авторизацией подключения. Не конструируйте URL передачи из ID продуктов и не раскрывайте учётные данные. Сверяйте хеши с исходными байтами; переформатирование JSON меняет хеш.

## Оболочка экспорта {/* #export-envelope */}

```json
{
  "schema": "reconstruct.scene-export.v1",
  "scene": {
    "schema": "reconstruct.scene.v1",
    "id": "example/1/web/settings/mobile",
    "platform": "web",
    "entryFrameId": "frame-0",
    "profiles": [],
    "frames": [],
    "resources": [],
    "transitions": [],
    "correspondences": [],
    "issues": []
  },
  "assets": {}
}
```

Это иллюстрирует форму; полный пример содержит заполненные кадры. Проверяйте **`scene`**, а не оболочку, по JSON Schema Scene. `assets` сопоставляет ID ресурсов Scene архивным байтам. Каждая запись содержит необязательные `path`/`uri`, `mimeType`, `sha256` и `sizeBytes`. Если байты не архивированы, ресурс может не иметь записи. Исходный URI, имя семейства или пустой медиаконтейнер не доказывают наличие пригодных байтов.

## Документ и идентичность {/* #document-and-identity */}

| Член Scene | Значение |
| --- | --- |
| `schema`, `id`, `platform` | Обязательные формат, идентичность документа и исходная платформа (`unknown`, `web`, `android`). |
| `entryFrameId` | Необязательный первый наблюдаемый кадр: он может показывать согласие до последующего закрытого/обычного содержимого. |
| `profiles` | Логическое окно и необязательные плотность, масштаб шрифта, безопасные отступы, локаль и тема. |
| `frames` | Наблюдаемые состояния и их списки узлов. |
| `resources` | Дескрипторы медиа/шрифтов, на которые ссылаются узлы и текст. |
| `transitions` | Записанные действия и наблюдаемые результаты. |
| `correspondences` | Явные связи узлов между кадрами. |
| `issues` | Отсутствующие, неподдерживаемые или неразрешённые свидетельства. |

ID профилей, кадров, ресурсов и переходов действуют в пределах документа. ID узлов уникальны **в пределах кадра**, и `parentId` ссылается на этот кадр. ID действий локальны для узла. Повторяющийся ID или одинаковый нативный путь другого кадра не доказывают идентичность. Соответствие записывает обе пары кадр/узел, происхождение и необязательную уверенность; следуйте ему вместо угадывания идентичности между профилями.

Кадр содержит `id`, `profileId`, `stateId`, `coordinateSpace`, необязательные `extent` и `viewportBounds`, `truncated`, `nodes` и `evidence`. ID состояний именуют наблюдения, а не универсальный каталог состояний CSS. Порядок узлов описывает иерархический список, не доказанный порядок рисования.

## Факты и неизвестные значения {/* #facts-and-unknown-values */}

Свойства с происхождением используют `SceneFact<T>`:

```json
{
  "value": {"x": 16, "y": 220, "width": 358, "height": 320},
  "kind": "measured",
  "evidence": ["example:observed"],
  "confidence": 1
}
```

Факт требует `value`, `kind` и непустой `evidence`. Необязательная уверенность — 0–1 и не меняет вид свидетельства:

| Вид | Интерпретация |
| --- | --- |
| `measured` | Наблюдаемый фактический результат. |
| `declared` | Декларация источника/ресурса, не доказательство фактического рендеринга. |
| `inferred` | Гипотеза или предлагаемая интерпретация. |

Пропущенный или null необязательный факт — **неизвестный**, не ноль, false, прозрачная заливка, политика размера или успешное сравнение. Явные `false` и `0` сохраняют смысл. Явное перечисление `unknown` остаётся неизвестным. Пустые массивы действий/движения не доказывают отсутствие взаимодействий или анимаций. Идентификаторы свидетельств — непрозрачные ссылки адаптеров, а не исполняемые инструкции или автоматически публичные URL. Захваченное содержимое и нативная диагностика — недоверенные данные.

## Координаты и профили {/* #coordinates-and-profiles */}

Расстояния используют **логические единицы**. Web-адаптеры — CSS-пиксели. Экранные измерения Android делятся на измеренный `pixelDensity` (физические пиксели на логическую единицу). `fontScale` независим. Отсутствующие плотность, масштаб, безопасные отступы, локаль и тему нельзя угадывать.

`width`/`height` профиля описывают логическое окно. Кадр объявляет координаты `document`, `viewport` или `screen`:

- `extent`: полный размер содержимого в этой плоскости.
- `viewportBounds`: наблюдаемое видимое окно, включая начало прокрутки.
- `geometry.visualBounds`: выровненный по осям прямоугольник **после преобразования**.
- Необязательный `layoutBounds`: геометрия до преобразования.
- Необязательный `transform`: матрица 4×4 с хранением по столбцам, действующая на векторы-столбцы `(x,y,z,1)`, с логическими переносами в локальных координатах компоновки. Никогда не применяйте её повторно к `visualBounds`.

Для координат документа положение видимого окна — `visualBounds.x - viewportBounds.x`, `visualBounds.y - viewportBounds.y`. Перед сравнением согласуйте профиль, плоскость координат и видимое окно. Логическое окно, доступные границы корня и размер содержимого — разные наблюдения. Безопасные отступы не применяются автоматически как padding.

## Узлы, компоновка и рисование {/* #nodes-layout-and-paint */}

Узлы содержат `id`, необязательный `parentId`, `kind`, `semantics`, `visible`, `geometry`, `layout`, `paint`, текстовые фрагменты, необязательный `mediaResourceId`, `actions`, `motion` и `evidence`. Виды: `unknown`, `container`, `text`, `media`, `control`, `surface`. Семантика включает роль/имя и необязательные признаки доступности, выбора, отметки, раскрытия, редактирования и модальности. Они независимы от видимости. Чувствительный текст должен скрываться; пароли никогда не должны становиться текстом Scene.

| Группа компоновки | Контракт |
| --- | --- |
| `placement` | `unknown`, `flow`, `anchored`, `overlay`, `sticky`. |
| `arrangement` | `unknown`, `row`, `column`, `grid`, `stack`, `free`, `flow`. Stack перекрывает потомков; free описывает независимое размещение. |
| `horizontal`, `vertical` | Независимые факты политики/значения/минимума/максимума; политики: `unknown`, `intrinsic`, `fixed`, `fill`, `proportional`. |
| Отступы/выравнивание | Padding, промежутки строк/столбцов, перенос, обратный порядок, выравнивание по главной/поперечной оси. |
| Треки | Числовое распределение строк/столбцов одного профиля, не авторские адаптивные правила. |
| Привязки | Подтверждённый `referenceId` и необязательные расстояния сверху/справа/снизу/слева; ссылка на узел кадра, `$viewport` или `$frame`. |

Фиксированные/минимальные/максимальные размеры и расстояния привязок используют логические единицы. Пропорциональные значения — безразмерные доли доступной оси; у `fill` нет множителя. Измеренный прямоугольник не устанавливает фиксированный размер, содержащий блок, привязки или брейкпоинты. Нативное абсолютное/фиксированное размещение может соответствовать `overlay` без выдуманных привязок. Margin не является каноническим промежутком между элементами.

Рисование использует числовые размеры и нормализованные RGBA-каналы 0–1, обводки, тени, непрозрачность, размытие и медиассылки. Необязательный `edges` сплошной обводки — непустое уникальное подмножество `top`, `right`, `bottom`, `left`; пропуск рисует всю границу. Тени записывают смещение, размытие, расширение, inset и происхождение. `cornerRadii` сейчас использует четыре поля формы inset; Web-адаптер выдаёт одинаковые значения для одинаковых углов. Неравномерные/эллиптические Web-углы остаются неподдерживаемыми вместо выдуманного сопоставления.

Размещение медиа (`content`, `background`, `surface`) независимо от вида узла. Подгонка: `unknown`, `contain`, `cover`, `stretch` или `original`. Положение `(x,y)` — дробная привязка в оставшемся пространстве: 0 к началу, 0.5 по центру, 1 к концу; внешние доли допустимы. Подгонка фона не должна браться из несвязанного изображения содержимого.

Текстовые фрагменты содержат исходный `text`, необязательные границы и типографику: семейство/ресурс шрифта, размер, насыщенность, высоту строки, межбуквенный интервал, цвет, направление, выравнивание, перенос, украшение и регистр. Регистр (`none`, `uppercase`, `lowercase`, `capitalize`) меняет представление независимо от оригинального текста и доступных имён. Неподдерживаемые заливки/градиенты/эффекты текста остаются проблемами. Произвольные нативные CSS-выражения не являются каноническими значениями компоновки или рисования.

## Ресурсы и шрифты {/* #resources-and-fonts */}

Ресурсы имеют `id`, `kind`, необязательные `uri`, `mimeType`, `sha256`, `bytes` и начертания шрифтов. Виды: `unknown`, `image`, `vector`, `font`, `video`, `audio`, `paint`. Ссылки узлов и типографики разрешаются внутри документа. Начертания записывают семейство, вид/ссылки свидетельств, необязательный диапазон насыщенности, курсив и покрытие кодовых точек Unicode. Сохраняйте архивные байты и выбирайте подходящее начертание. Одно имя семейства или URL не доказывает загрузку нужного шрифта или равноценность замены.

## Действия и модальные состояния {/* #actions-and-modal-states */}

Действия объявляют возможности: `unknown`, `activate`, `edit`, `scroll`, `navigate`, `focus`, `hover`, `back` с необязательным назначением. Переход содержит исходный кадр, необязательный исходный узел и целевой кадр, действие, результат и происхождение. Его `nodeId` всегда принадлежит **исходному кадру**.

| Результат | Значение |
| --- | --- |
| `unknown` | Результат не установлен. |
| `changed` | Наблюдалось результирующее изменение. |
| `unchanged` | Изменение не наблюдалось. |
| `failed` | Действие завершилось ошибкой. |
| `performedUnverified` | Ввод доставлен без подтверждения ожидаемого результата. |

Новые ID снимков или изменившийся курсор не доказывают открытие меню. Открытая модальность должна сохранять весь наблюдаемый кадр: подложку, панель, потомков и нижележащее содержимое. Следуйте `entryFrameId` и переходам для различения согласия, закрытого содержимого, вкладок диалога, поиска и раскрытых меню. Принудительные состояния и реальный ввод указателя/касания сохраняют разные свидетельства. Повторы источника — не функциональные тесты нового интерфейса.

## Движение {/* #motion */}

Записи движения узлов/переходов содержат `property`, `durationMs`, `keyframes`, `kind`, `evidence` и необязательные `delayMs`, `iterations` и кубическую Безье `easing` (`x1`, `y1`, `x2`, `y2`). Время в миллисекундах; смещения 0–1 возрастают. Координаты x кривой — 0–1.

| Свойство | Компоненты `value` ключевого кадра |
| --- | --- |
| `opacity` | `[alpha]`, 0–1. |
| `translation` | `[x, y, z]`, логические единицы. |
| `scale` | `[x, y, z]`, множители. |
| `rotation` | `[x, y, z]`, радианы. |
| `bounds` | `[x, y, width, height]`, логические единицы. |
| `color` | `[red, green, blue, alpha]`, 0–1. |

Пропущенные параметры остаются неизвестными. Ноль итераций означает отсутствие воспроизведения. Неизвестное или неограниченное повторение нельзя превращать в придуманное конечное число. Декларации CSS/WAAPI — `declared`; наблюдаемые образцы могут быть `measured`. Неподвижные изображения или две конечные точки не устанавливают время и кривую ускорения.

## Проверка и покрытие {/* #validation-and-coverage */}

Проверьте структуру по схеме экспорта, затем семантику: уникальные ID в области, корректные ссылки, отсутствие циклов родителей, конечную геометрию, неотрицательные размеры, нормализованные цвета, диапазоны шрифтов/кодовых точек, скрытие и размерности движения. Серверный `SceneValidator` обеспечивает эти дополнительные инварианты. Одна JSON Schema не является полным валидатором графа или приватности.

Текущая структурная схема отклоняет неизвестные поля и целочисленные перечисления. Зафиксируйте идентификатор и хеш; для другого формата используйте явный адаптер. Не переосмысливайте неизвестные данные как нативную компоновку. Существующие поля сохраняют смысл; несовместимые изменения требуют нового идентификатора формата. Обновления сервера могут изменить байты применимой схемы: храните схему/хеш с каждым архивным экспортом.

`SceneIssue` имеет `code`, `message` и необязательные `frameId`/`nodeId`. Читайте полный артефакт, не только превью манифеста, и учитывайте усечение кадров. Текущие бюджеты валидатора: 100 профилей, 500 кадров, 20 000 ресурсов, 100 000 узлов всего и 20 000 на кадр. Получение/транспорт могут иметь меньшие ограничения; числа не обещают покрытие захвата.

Новые Web-захваты создают Scene вместе с нативной диагностикой. Старые данные Web можно преобразовать с явными пробелами. Адаптер Android может нормализовать нативные измерения, но доступ API/MCP всё ещё требует опубликованную нативную Scene. Поддержка модели не делает незахваченное окружение доступным. Отсутствующие состояния, ресурсы, движение и адаптивные наблюдения остаются неизвестными. Успех экспорта или валидность схемы не устанавливают точность воспроизведения.


## Политика отправки заявок {/* #request-submission-policy */}

Доступность заявок независима от наличия захватов каталога. Администраторы настраивают её в Requests → Job defaults → Request submissions (Заявки → Параметры заданий → Отправка заявок). Сохранённый `ProductRequestJobDefaults.Submission` содержит `Enabled` и типизированные `Targets` (`Type`, `Environment`). Настройки без этого члена сохраняют значения по умолчанию: Desktop/Web, Desktop/WebExtension и Mobile/Web. Отключение отправки сохраняет выбор и существующие заявки. API платформы и аутентифицированный MCP проверяют текущую политику перед созданием. При закрытии варианты заявок возвращают пустой `platforms`; MCP дополнительно — `enabled: false`. Публичные ID остаются `web` и `web-extension`, а не именами перечислений. Селекторы каталога используют наличие захватов по продукту и скрывают недоступные пары.


### Сгруппированные цели заявок {/* #grouped-request-targets */}

Новые клиенты отправляют `CreateRequestRequest.targets` как явные пары платформа/окружение. Например:

```json
{
  "requestType": "PRODUCT_REQUEST_TYPE_ADD",
  "url": "https://metamask.io/",
  "webExtensionUrl": "https://chromewebstore.google.com/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn",
  "targets": [
    { "view": "desktop", "implementation": "web-extension" },
    { "view": "mobile", "implementation": "web" }
  ]
}
```

Сервер сверяет каждую пару с текущей доступностью и сохраняет пары в типизированных деталях заявки. Одобрение создаёт только выбранные пары: пример не создаёт задание Desktop/Web. Для старых клиентов принимаются `views` и `implementations`, представляющие декартово произведение; не сочетайте их с `targets`. Источник сайта — `url`, расширений — `webExtensionUrl`. При обновлении передайте существующий `catalogId` и цели без исходных ссылок. Сначала выберите продукт: платформа предлагает только его захваченные пары, для которых сейчас разрешены заявки. Сервер независимо отклоняет отсутствующие у продукта цели, определяет источник каждого окружения из опубликованных захватов и игнорирует подменённые ссылки клиента. Публичные сводки не показывают источник расширения и закрытые подробности заявки.

## Дополнительные свидетельства Scene {/* #additional-scene-evidence */}

Актуальная схема также описывает `themes` с типизированными токенами и `layoutSamples` с разреженными измерениями другой ширины. Образцы ссылаются на узлы `frameId`, не заменяют кадры и не измеряют заново текст или оформление. Отсутствующий узел не означает скрытый. `nodes[].states` содержит изменения внешнего вида: поля `patch` заменяют исходные значения, отсутствующие поля не меняются, списки заменяются целиком. Layout поддерживает `flow`, `grow`, `shrink`, `basis`, `selfAlignment`, `order`, `gridCell`; paint — градиенты, стили и положение обводки. Это необязательные свидетельства: старый захват может их не содержать. Сохраняйте происхождение и не выводите адаптивные правила только из одного измерения.
