Forge
markdowndeeb25a2
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
351. **`Instrument` (кабинный)** — это **именованный выбор представления в слоте внимания**, результат работы **композитора**. Это **не** синоним Avalonia-`Control` и **не** сырой канал данных (Build log, граф навигации и т.д. остаются в каналах / проекциях).
36
37<a id="adr0047-p2"></a>
38
392. **`CockpitInstrumentDescriptor`** (код) — минимальный **контрактный** дескриптор: стабильный `instrument_id`, идентификатор слота (`slot_id`, например `pfd` / `mfd` / `forward`), `schema_version` строки дескриптора. Расширение полей (параметры инструмента, ссылки на данные) — по мере появления второго и третьего инструмента в одном слоте.
40
41<a id="adr0047-p3"></a>
42
433. **CDS** по-прежнему отвечает на «**куда** имеет право попасть инструмент» при текущем `presentation` и топологии; **композитор** — на «**какой** `instrument_id` в каком `slot_id`»; **поверхность** — на «**какой** `Control`/View реализует этот дескриптор».
44
45<a id="adr0047-p4"></a>
46
474. **Примеры слотов 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
View only · write via MCP/CIDE