| 1 | # ADR 0047: Инструмент кабины (`Instrument`) — дескриптор композиции слота, не `Control` |
| 2 | |
| 3 | **Статус:** Accepted · Implemented |
| 4 | **Дата:** 2026-04-15 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR / документ | Роль | |
| 9 | |----------------|------| |
| 10 | | [0036](0036-cds-channel-compositor-surface-pipeline.md) | Канал → CDS → композитор → поверхность | |
| 11 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | Зоны внимания | |
| 12 | | [0039](0039-workspace-navigation-affordances.md) | Semantic Map, навигация | |
| 13 | | [0046](0046-presentation-layout-authority-and-cockpit-invariants.md) | Инварианты `presentation` | |
| 14 | | [`cds-contract-v0.md`](../design/cds-contract-v0.md) | Чертёж дескрипторов и слотов | |
| 15 | |
| 16 | **Имя файла (история):** ранее черновик назывался `*widget*`; канонический термин продукта — **Instrument** (см. п.1). |
| 17 | |
| 18 | ### Снимок реализации |
| 19 | |
| 20 | | Элемент | Значение | |
| 21 | |---------|----------| |
| 22 | | — | термин **Instrument**, `CockpitInstrumentDescriptor`, `MainWindowHostSurfaceFrame`, `MainWindowInstrumentMountRegistry` | |
| 23 | | — | см. [`cds-contract-v0.md`](../design/cds-contract-v0.md) | |
| 24 | | — | расширение списка инструментов — по дорожной карте | |
| 25 | |
| 26 | --- |
| 27 | ## Контекст |
| 28 | |
| 29 | В разговоре о **Solution Explorer** и **Semantic Map** всплыла путаница уровней: «данные», «представление данных», «поверхность Avalonia» и «слот внимания» смешивались. Нужен **устойчивый термин** для единицы, которую **композитор** выбирает для слота и которую **поверхность** монтирует — без подмены смысла «любым `Control`». Слово **instrument** в английском многозначно (авиа-прибор, измерительный прибор, музыкальный инструмент и т.д.); в этом ADR оно закреплено в значении **кабинного инструмента**: логическая единица индикации/представления в зоне внимания, в духе метафоры PFD/MFD, **не** обязательно «стрелка на приборной доске». |
| 30 | |
| 31 | ## Решение |
| 32 | |
| 33 | <a id="adr0047-p1"></a> |
| 34 | |
| 35 | 1. **`Instrument` (кабинный)** — это **именованный выбор представления в слоте внимания**, результат работы **композитора**. Это **не** синоним Avalonia-`Control` и **не** сырой канал данных (Build log, граф навигации и т.д. остаются в каналах / проекциях). |
| 36 | |
| 37 | <a id="adr0047-p2"></a> |
| 38 | |
| 39 | 2. **`CockpitInstrumentDescriptor`** (код) — минимальный **контрактный** дескриптор: стабильный `instrument_id`, идентификатор слота (`slot_id`, например `pfd` / `mfd` / `forward`), `schema_version` строки дескриптора. Расширение полей (параметры инструмента, ссылки на данные) — по мере появления второго и третьего инструмента в одном слоте. |
| 40 | |
| 41 | <a id="adr0047-p3"></a> |
| 42 | |
| 43 | 3. **CDS** по-прежнему отвечает на «**куда** имеет право попасть инструмент» при текущем `presentation` и топологии; **композитор** — на «**какой** `instrument_id` в каком `slot_id`»; **поверхность** — на «**какой** `Control`/View реализует этот дескриптор». |
| 44 | |
| 45 | <a id="adr0047-p4"></a> |
| 46 | |
| 47 | 4. **Примеры слотов PFD:** `solution_explorer_tree` и `workspace_navigation_map` (Semantic Map) — **два разных инструмента** одного класса слота «представление workspace», взаимоисключаемо или с явным split — решает композитор + capabilities, не произвольный код View. |
| 48 | |
| 49 | ## Последствия |
| 50 | |
| 51 | - Появляется язык для MCP/агента: «смонтировать инструмент X в слот Y» без привязки к имени контрола в дереве. |
| 52 | - Регрессии «сломали не данные, а представление» локализуются в композиторе и **реестре инструментов**. |
| 53 | |
| 54 | ## Не цели (v1) |
| 55 | |
| 56 | - Полный реестр инструментов и hot-swap всех панелей — отдельными итерациями после стабилизации дескриптора. |
| 57 | - Замена `UiLayoutSnapshot` для автоматизации дерева UI. |
| 58 | |
| 59 | ## Отклонённые альтернативы |
| 60 | |
| 61 | - **`Widget`** — перегружен (веб, Flutter, «виджеты ОС»); заменён на **Instrument** для ясной связи с кабинной метафорой и меньшей коллизией с UI-фреймворками. |
| 62 | - Называть любой `UserControl` «инструментом» без дескриптора — отклонено: размывает границу композитор/поверхность. |
| 63 | - Вешать выбор SE vs Semantic Map только на TOML без слоя композитора — отклонено: не масштабируется на MCP и тесты. |
| 64 | |