| 1 | # ADR 0036: Канал → CDS → композитор поверхности → поверхность (Agent-first отображение) |
| 2 | |
| 3 | **Статус:** Accepted · Implemented |
| 4 | **Дата:** 2026-04-11 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR / документ | Роль | |
| 9 | |----------------|------| |
| 10 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | Зоны внимания; CDS vs `UiLayoutSnapshot` | |
| 11 | | [0097](0097-cockpit-compute-units-transport-to-channel-dto.md) | CCU: DTO канала **до** CDS | |
| 12 | | [0017](0017-multi-window-workspace-and-agent-surfaces.md) | `presentation`, топология окон | |
| 13 | | [0008](0008-mcp-contracts-and-testable-infrastructure.md) | Контракты, тестируемые границы | |
| 14 | | [0035](0035-mfd-embedded-webview-external-llm-and-mcp-boundary.md) | Веб-поверхность ≠ MCP | |
| 15 | | [0115](0115-cds-graph-backed-shared-layer.md) | Общий слой graph-backed в кабине | |
| 16 | | [0067](0067-graph-backed-surfaces-contract.md) | Контракт измерений graph-backed | |
| 17 | | [`cds-contract-v0.md`](../design/cds-contract-v0.md) | Чертёж полей и DTO | |
| 18 | |
| 19 | ### Снимок реализации |
| 20 | |
| 21 | | Элемент | Значение | |
| 22 | |---------|----------| |
| 23 | | — | слои `Cockpit/Cds`, `Cockpit/Channels`, `Cockpit/Composition`, `Cockpit/Surface` | |
| 24 | | — | чертёж полей — [`cds-contract-v0.md`](../design/cds-contract-v0.md) §6–7, [`Features/README.md`](../Features/README.md) | |
| 25 | |
| 26 | ## Резюме |
| 27 | |
| 28 | - Цепочка: **канал** (смысл и payload) → **CDS** (куда данные *имеют право* попасть) → **композитор** (слот и разметка) → **поверхность** (Avalonia/Skia). |
| 29 | - **Agent-first:** целевые команды агента — на уровне CDS/композитора, не прямой доступ к произвольному `Control` (исключения — явный strangler). |
| 30 | - **`UiLayoutSnapshot`** остаётся для дерева контролов и отладки; **ортогонален** CDS ([0021](0021-pfd-mfd-cockpit-attention-model.md)). |
| 31 | - Канал **не** импортирует `MainWindow.axaml`; CDS **не** дублирует полное дерево UI. |
| 32 | - Реализация: `Cockpit/Cds`, `Channels`, `Composition`, `Surface` — см. [cds-contract-v0.md](../design/cds-contract-v0.md). |
| 33 | |
| 34 | --- |
| 35 | ## Контекст |
| 36 | |
| 37 | В авионике **CDS** (Cockpit Display System в смысле ARINC) — идея **единого контура отображения**: прикладные системы подают данные и команды, а **композиция** экрана (слои, приоритеты, допустимые регионы) — у согласованного рантайма. Cascade **не** копирует профиль 661 и не требует сертификации ([0021 § ARINC 661](0021-pfd-mfd-cockpit-attention-model.md#arinc-661-borrow)); переносим **принцип разделения**: агент и каналы не должны напрямую «рисовать» произвольный UI, если цель — **предсказуемая кабина** и Agent-first дисциплина. |
| 38 | |
| 39 | Уже зафиксировано: **CDS в продукте** — слой **семантики кабины** (какая топология, какие зоны/страницы активны), ортогонально **дереву контролов** (`UiLayoutSnapshot`) и тонкому чертежу полей в [`cds-contract-v0.md`](../design/cds-contract-v0.md). Не хватает **явной цепочки ответственности** от потока данных до пикселей, чтобы новые фичи не пробивали дыру «сразу в Avalonia». |
| 40 | |
| 41 | ## Решение |
| 42 | |
| 43 | <a id="adr0036-p1"></a> |
| 44 | |
| 45 | 1. **Канал / поток** — слой **данных и смысла** для конкретного инструмента внимания: здоровье workspace, EICAS, readiness, позже — иные каналы. Отвечает на вопросы: *что* показать, *в каком приоритете*, *какой полезной нагрузкой* (сегменты, сообщения, метрики). **Не** отвечает на вопрос «в какой пиксельной координате» и **не** привязан к конкретному `Control` в дереве. |
| 46 | |
| 47 | <a id="adr0036-p2"></a> |
| 48 | |
| 49 | 2. **CDS (контракт кабины)** — слой **маршрутизации в модели внимания**: *куда данные канала **имеют право** попасть* при текущем пресете и топологии. Агрегирует семантику: режим UI, эффективная строка `presentation`, вид поверхности (`AttentionLayoutSurfaceKind`), видимость зон PFD/Forward/MFD, состояние окна-хоста Mfd, активная страница вторичного контура (`SecondaryShellPage`), и т.д. — в духе полей [`cds-contract-v0.md`](../design/cds-contract-v0.md). Реализация в коде: **снимок** (например `CockpitSurfaceState` / `CockpitSurfaceSnapshotBuilder`), а не «один God-class» на весь UI. |
| 50 | |
| 51 | <a id="adr0036-p3"></a> |
| 52 | |
| 53 | 3. **Композитор поверхности** — слой **связки слота канала с конкретным представлением** внутри региона: полоса vs страница MFD, порядок сегментов, правила EICAS/HUD относительно канонов [0021](0021-pfd-mfd-cockpit-attention-model.md). Отвечает на вопрос: *как из допустимого места CDS и данных канала получить **разметку** для VM/представления* (без дублирования полного текста канала в CDS — см. таблицу терминов в чертеже v0). |
| 54 | |
| 55 | <a id="adr0036-p4"></a> |
| 56 | |
| 57 | 4. **Поверхность** — конкретные **контролы Avalonia** (и привязки к `MainWindowViewModel`), фокус, анимации. **Avalonia намеренно узкая по смыслу:** окно, ввод, хост для контролов; **не** первичный источник семантики зон кокпита (он в CDS / композиторе). Кастомная отрисовка (например Skia) допускается как реализация региона поверхности поверх этого хоста. MCP-инструменты вроде `ide_get_ui_layout` остаются на этом слое; **целевые** команды агента на изменение кабины формулируются **на уровне CDS / композитора**, а не прямого доступа к произвольному имени контрола — за исключением осознанных исключений (автоматизация, strangler), которые документируются отдельно. |
| 58 | |
| 59 | <a id="adr0036-p5"></a> |
| 60 | |
| 61 | 5. **Инвариант:** канал **не** импортирует знание о `MainWindow.axaml`; CDS **не** дублирует полное дерево UI; композитор **не** подменяет политику зон из [0021](0021-pfd-mfd-cockpit-attention-model.md). Нарушение — отдельное решение или временная мера с явной меткой. **Уточнение:** типы в `Cockpit/Channels` **не** зависят от конкретных VM фич (`UiChromeViewModel`, панели instrumentation и т.п.) — только от DTO, делегатов (`Func<…>`) и не-UI сервисов; подстановка живых источников — в корне композиции (например `MainWindowViewModel`). Это не запрещает VM знать каналы, CDS и видимость — это его роль. |
| 62 | |
| 63 | ## Последствия |
| 64 | |
| 65 | - Agent-first и расширения по MCP получают **устойчивый язык**: «куда в кабине» (CDS) отдельно от «что в полосе» (канал) и от «какой контрол» (поверхность). |
| 66 | - Тесты и снапшоты могут опираться на **CDS-снимок** без хрупкой привязки к дереву контролов для сценариев «внимание и раскладка». |
| 67 | - Реализация остаётся **поэтапной**: корневой VM по-прежнему связывает источники с каналом; этот ADR задаёт **направление**, к которому новые фичи стараются сходиться. |
| 68 | |
| 69 | ## Не цели |
| 70 | |
| 71 | - Полная реализация **ARINC 661** или **CDS** как в сертифицированной авионике. |
| 72 | - Замена `UiLayoutSnapshot` для отладки и автоматизации дерева — слой **ортогонален** CDS ([0021 §1.1](0021-pfd-mfd-cockpit-attention-model.md#glossary-cds-contract)). |
| 73 | |