| 1 | # ADR 0066: Cockpit UI и слой presentation IDE — раздельные опоры |
| 2 | |
| 3 | **Статус:** Accepted |
| 4 | **Дата:** 2026-04-19 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR | Роль | |
| 9 | |-----|------| |
| 10 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | Модель внимания, EICAS | |
| 11 | | [0046](0046-presentation-layout-authority-and-cockpit-invariants.md) | Политика `presentation` | |
| 12 | | [0064](0064-deck-primitives-visual-language-render-layer-and-palette.md) | `PrimitivesKit`, палитра кабины | |
| 13 | | [0065](0065-instrument-categories-domain-taxonomy.md) | Категории / `graph_kind` | |
| 14 | | [0013](0013-command-surface-and-discoverability.md) | Палитра команд | |
| 15 | | [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md) | Реестр команд, hotkeys | |
| 16 | | [0079](0079-ide-display-system-ids-overlay-pipeline.md) | IDS — оверлеи shell (**не** cockpit UI) | |
| 17 | |
| 18 | **Код:** `Cockpit/PrimitivesKit/`, `Features/UiChrome/`, `Themes/*.json`. |
| 19 | |
| 20 | --- |
| 21 | ## Контекст |
| 22 | |
| 23 | В продукте одновременно существуют: |
| 24 | |
| 25 | 1. **Инструментальный слой кабины** — deck, зоны PFD/MFD/Forward, приборы, лампы, semantic map как визуальный инструмент, палитра ролей в смысле EICAS/annunciator ([0021](0021-pfd-mfd-cockpit-attention-model.md), [0064](0064-deck-primitives-visual-language-render-layer-and-palette.md)). |
| 26 | 2. **Оболочка IDE** — меню, окно, палитра команд, модальные оверлеи без семантики «прибор», типовые поля и отступы для настроек и диалогов, токены темы для **обычного** UI. |
| 27 | |
| 28 | Без явного разделения обсуждения и код ревью смешивают **Cockpit UI** и **presentation-слой IDE** (условно «UI kit» хрома): тащат примитивы кокпита в диалоги или, наоборот, дублируют оверлеи и отступы внутри `PrimitivesKit`. Это ломает смысловую границу и усложняет эволюцию темы и кокпита независимо. |
| 29 | |
| 30 | --- |
| 31 | |
| 32 | ## Решение |
| 33 | |
| 34 | Зафиксировать **две опоры** (два контекста проектирования), не два обязательных неймспейса на каждую строчку кода: |
| 35 | |
| 36 | | Опора | Смысл | Типичное место в коде / артефактах | |
| 37 | |-------|--------|-------------------------------------| |
| 38 | | **Cockpit UI** | Визуальный язык **инструментов и deck** в метафоре кабины: виды индикаторов, отрисовка приборов, семантические цвета кабины (`CockpitPrimitivesPalette`), Skia-сцены инструментов, правила Dark Cockpit для **этого** слоя. | `Cockpit/PrimitivesKit/`, палитра кокпита; ADR [0064](0064-deck-primitives-visual-language-render-layer-and-palette.md), [0063](0063-instrument-deck-named-composition-one-anchor.md), [0065](0065-instrument-categories-domain-taxonomy.md); связь с [0021](0021-pfd-mfd-cockpit-attention-model.md). | |
| 39 | | **IDE presentation (хром)** | Общие для приложения **не-приборные** вещи: оболочка окна, палитра команд, переиспользуемые **модальные оверлеи**, согласованные отступы/типографика для хрома, токены темы `CascadeTheme` / JSON для **shell**. | `Features/UiChrome/`; `Views/` для конкретных экранов; темы в `Themes/`; команды и палитра — [0013](0013-command-surface-and-discoverability.md), [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md). | |
| 40 | |
| 41 | **Правило по умолчанию:** если виджет имеет смысл **без** метафоры deck / зон внимания / прибора — он не относится к **Cockpit UI**; если смысл — «показать состояние в ячейке deck / на приборе / в кокпитной полосе» — не смешивать с общим слоем оверлеев и «просто IDE». |
| 42 | |
| 43 | **Инвариант:** семантическая палитра **кабины** ([0064](0064-deck-primitives-visual-language-render-layer-and-palette.md)) не является единственным каталогом цветов для всего приложения: **тема** и **хром** могут задавать токены для меню, редактора и модалок; совпадения по hex допустимы только как сознательное согласование, не как обязательная зависимость кокпита от shell. |
| 44 | |
| 45 | --- |
| 46 | |
| 47 | ## Последствия |
| 48 | |
| 49 | - Ревью и обсуждения явно указывают контекст: **Cockpit** vs **хром IDE**; спорные случаи решаются правилом по умолчанию из таблицы выше. |
| 50 | - Новые **переиспользуемые** не-модальные примитивы хрома (оверлеи, типовые карточки настроек) развиваются в зоне **`Features/UiChrome`** (или рядом в `Views`, без переноса в `Cockpit/`). |
| 51 | - **Cockpit** остаётся ответственным за согласованность приборов, deck и Skia-отрисовки по [0064](0064-deck-primitives-visual-language-render-layer-and-palette.md); не дублировать туда палитру меню «ради единства файла». |
| 52 | |
| 53 | ### Проверка в сборке (Roslyn) |
| 54 | |
| 55 | Граница **импортов** между `Features/UiChrome` и `Cockpit/PrimitivesKit` закреплена анализатором `CascadeIDE.ArchitectureAnalyzers`: |
| 56 | |
| 57 | - **CASCOPE011** — в `Features/UiChrome/` запрещён `using CascadeIDE.Cockpit.PrimitivesKit`. |
| 58 | - **CASCOPE012** — в `Cockpit/PrimitivesKit/` запрещён `using CascadeIDE.Features.UiChrome`. |
| 59 | |
| 60 | Подробности и ограничения (MCP / `RoslynMcpWorkspace`) — [CascadeIDE.ArchitectureAnalyzers/README.md](../../CascadeIDE.ArchitectureAnalyzers/README.md). Полный список CASCOPE* — там же. |
| 61 | |
| 62 | --- |
| 63 | |
| 64 | ## Не-цели (текущая фаза) |
| 65 | |
| 66 | - Ввести отдельную сборку «UIKit» или переименовать папки в одном коммите без потребности. |
| 67 | - Исчерпывающий каталог всех токенов темы и компонентов (это живой гайд и код, не дублирование в ADR). |
| 68 | - Запретить исключения: локальный прототип в фиче возможен, но не задаёт второй канон без пересмотра ADR. |
| 69 | |
| 70 | --- |
| 71 | |
| 72 | ## Альтернативы (кратко) |
| 73 | |
| 74 | | Вариант | Минус | |
| 75 | |--------|--------| |
| 76 | | Один «UI kit на всё», включая кокпит | Смешение семантик; кабина тянет за собой shell и наоборот | |
| 77 | | Только устная договорённость | Нет стабильной ссылки для ревью и онбординга | |
| 78 | | Новый ADR на каждый контроль (кнопка, поле) | Шум; граница слоёв достаточна на уровне этого ADR | |
| 79 | |