Каждый экспорт figmascope начинается с .zip, содержащего семь артефактов. CONTEXT.md — тот, что читается первым: намеренно. Это не README и не сгенерированная документация. Это контракт в стиле компилятора между дизайном и агентом, который превратит его в код.

Эта статья разбирает содержимое файла, объясняет, почему он структурирован именно так, и показывает, что идёт не так, когда вы его пропускаете.

Чем контракт отличается от документации

Документация описывает, что существует. Контракт задаёт, что должно быть истинным. Это различие важно, когда ваш читатель — LLM, который с удовольствием изобретёт значения отступов, сплющит иерархию макетов или закодирует hex-цвета, как только у него не будет лучшего варианта.

CONTEXT.md открывается объявлением цели:

# CONTEXT.md — Jetpack Compose target

This file is the authoritative spec for generating UI code from this bundle.
Read it before reading any other file.

«Jetpack Compose target» — не украшение. Агент использует это, чтобы выбрать composable-примитивы, обработать единицы dp vs sp, понять, что Modifier.padding() — правильная абстракция для отступов, и что Box с Alignment — способ обработки overlay-макетов. React/Tailwind-цель генерирует другой CONTEXT.md с другими примитивами в ограничениях.

Инструкция «читать первым» тоже намеренна. Агенты обрабатывают контекст последовательно. Если правило для токена появляется после того, как агент уже начал рассуждать о компоненте, ограничение приходит слишком поздно. Помещение контракта в начало означает, что правила активны с первого токена генерации.

Раздел строгих ограничений

Самая нагруженная часть CONTEXT.md — блок ограничений:

## Strict constraints (must follow)

- Never hardcode dp values if a token exists within ±2dp
- Never flatten layout hierarchy — preserve every stack/overlay/absolute node
- Use stringRef values from strings.json, never inline literal text
- Treat missing fields as absent, not zero
- Do not invent component names not present in components/inventory.json

Каждое ограничение существует, потому что мы видели, как агенты его нарушают. Правило ±2dp — самый понятный пример. Без него агент, встречая gap: 14 на stack-узле, напишет Arrangement.spacedBy(14.dp). С правилом он проверяет, находится ли spacing.16 или spacing.12 в диапазоне 2dp, и использует токен вместо него. Это другой вывод — тот, что остаётся корректным при изменении значения токена, а не требует поиска и замены по всей кодовой базе.

Правило иерархии существует, потому что Compose — дерево макетов. Когда агент сплющивает вложенный стек в плоский список позиционированных элементов, он разрушает адаптивное поведение, подразумеваемое исходной структурой. IR сохраняет каждый уровень вложенности намеренно — см. Постраничный IR — Stack, Overlay, Absolute, Leaf о том, как вложенность кодирует намерения макета.

Ограничение — не «используйте токены, если захотите». Это «никогда не хардкодьте, если токен существует». Это запрет, а не рекомендация. LLM реагируют на запреты иначе, чем на рекомендации.

Правило stringRef важно для i18n. Если агент инлайнит "Speed Test" вместо ссылки на ключ ресурса, вы создаёте дыру в локализации. Ограничение явно указывает агенту на strings.json.

Как агент читает CONTEXT.md последовательно

Контекстные окна LLM обрабатывают токены слева направо. Структура CONTEXT.md использует это. Порядок:

  1. Объявление цели (задаёт весь фрейм генерации)
  2. Строгие ограничения (запреты, применяемые к каждому решению)
  3. Карта бандла (какие файлы существуют и что каждый содержит)
  4. Правила использования токенов (как разрешать отступы, цвета, радиусы, типографику)
  5. Примечания об области применения (честные пробелы — что бандл покрывает и что нет)

Раздел карты бандла говорит агенту, какие файлы читать и в каком порядке:

## Bundle contents

- tokens.json — design tokens (spacing, radius, color, typography)
- screens/*.json — per-screen IR in stack/overlay/absolute/leaf format
- components/inventory.json — component identity list
- strings.json — i18n resource keys
- _meta.json — generation metadata and warnings

Без этой карты агент может не знать, что components/inventory.json существует, или воспринять _meta.json как основную спецификацию. Явное перечисление задаёт порядок чтения.

Примечания об области применения — что версия v0.4 честно не покрывает

Раздел примечаний об области применения — место, где figmascope документирует собственные ограничения. Это намеренно и обязательно. Агент, который не знает, что спецификация неполна, с уверенностью заполнит пробелы изобретениями. Это хуже, чем знать о пробеле.

## Scope notes (v0.4)

- Gradient fills are not supported. Nodes with gradient fills emit a warning
  in _meta.json under warnings. Treat as a solid fill approximation or TODO.
- Typography tokens require Figma Variables to be populated. If tokensSource
  is "inferred-from-frequency" or "none", typography coverage may be partial.
- This bundle covers UI structure only. Navigation, state management,
  and network calls are outside scope.
- Component instances are identified by componentId. Full component
  source props are not included — the inventory gives identity, not implementation.

Предупреждение о градиентах особенно важно. Figma поддерживает сложные градиентные заливки, для которых нет прямого эквивалента в Compose без пользовательской отрисовки. Вместо того чтобы молча удалять градиенты или генерировать сломанный код, figmascope выдаёт предупреждение background-gradient-not-supported:<name> в _meta.json и указывает на это здесь, чтобы агент воспринимал затронутые узлы как известный пробел, а не ошибку в собственном выводе.

Примечание о типографике связано с полем tokensSource в _meta.json. Когда Figma-файл не имеет Variables, figmascope выводит токены по частоте — распространённые значения становятся токенами, редкие — нет. Примечание сообщает агенту, что этот вывод несовершенен, и не стоит предполагать полное покрытие типографики. См. tokens.json. Подробный разбор о том, как работает запасной вариант с выводом.

Примеры WRONG / RIGHT

Конкретный пример. Дан stack-узел с gap: 16 и файл токенов, содержащий spacing.16: 16:

Без ограничений CONTEXT.md (WRONG):

Column(
    modifier = Modifier.padding(horizontal = 24.dp),
    verticalArrangement = Arrangement.spacedBy(16.dp)
) {

С ограничениями CONTEXT.md (RIGHT):

Column(
    modifier = Modifier.padding(horizontal = Spacing.spacing24),
    verticalArrangement = Arrangement.spacedBy(Spacing.spacing16)
) {

Правильный вывод ссылается на токены. Когда дизайн-система изменит spacing.16 с 16dp на 14dp, код останется корректным без поиска и замены по всей кодовой базе.

Ещё один пример — обработка строк. Дан leaf-узел с text: "Speed Test" и stringRef: "speed.test":

WRONG:

Text(text = "Speed Test")

RIGHT:

Text(text = stringResource(R.string.speed_test))

Ограничение указывает на strings.json, ключ — speed.test, и агент знает, как преобразовать dot-нотацию в Android resource IDs. Это возможно только если агент прочёл ограничение до генерации компонента.

Почему не просто написать инструкции в промпте самостоятельно?

Вы можете написать эти инструкции вручную в вашем промпте. figmascope выносит их в файл, потому что:

Цель не в том, чтобы промпт-инженерией обойти дефолты агента. Цель — отгрузить спецификацию, которая делает дефолты нерелевантными.

Структура в сравнении с альтернативами

Dev Mode Figma выводит измерения, переменные и фрагменты кода. Он не создаёт спецификацию. Агент, работающий с выводом Dev Mode, должен выводить правила из примеров — а это значит, что он будет выводить неверные правила для граничных случаев.

Locofy и аналогичные инструменты генерируют код напрямую. У них нет эквивалента CONTEXT.md, потому что они не ожидают, что агент прочтёт спецификацию — они ожидают, что сами будут агентом. Это работает, когда кодогенерация инструмента точно соответствует вашему стеку. Это не работает, когда у вас есть специфические соглашения об именовании, кастомная библиотека компонентов или дизайн-система с токенами, о которых инструмент не знает.

CONTEXT.md — машиночитаемое техзадание на дизайн. Это то, что существовало как страница в Confluence или Notion в каждом дизайн-хэндоффе до эпохи LLM — только структурированное для аудитории, которая действительно следует правилам.

Что делать с этим файлом

Когда вы открываете экспорт figmascope в Cursor или Claude Code:

  1. Добавьте @CONTEXT.md в контекст перед любым промптом о дизайне.
  2. Укажите JSON экрана, с которым работаете: @screens/home.json.
  3. Если затрагиваете токены, добавьте @tokens.json.
  4. Если работаете со строками, добавьте @strings.json.

Ограничения CONTEXT.md применяются ко всей сессии после загрузки. Вы не добавляете его к каждому промпту — добавляете один раз в начале и позволяете ему формировать каждую последующую генерацию.

Другие артефакты бандла рассматриваются в остальной части этой серии. Начните с tokens.json. Подробный разбор о том, как система токенов обрабатывает файлы с Variables и без, или с Постраничного IR о том, как макеты Figma отображаются на узлы stack/overlay/absolute/leaf. Готовы попробовать? Вставьте ваш Figma URL на figmascope.dev и экспортируйте первый бандл.