Перейти к содержанию

ADR 0079: IDS (Ide Display System) — пайплайн оверлеев IDE, ортогонально CDS

Статус: Accepted
Дата: 2026-04-20

Связанные ADR

ADR Роль
0036 CDS: кабина, канал → CDS → композитор → поверхность
0066 Cockpit UI vs presentation IDE: хром и оверлеи
0070 Command Palette как прямой overlay в активном TopLevel
0057 чат: композитор снимка поверхности; аналогия по слою «композиция»
0013 палитра и discoverability
0115 CDS — общий слой graph-backed приборов (реализация в кабине, не IDS)

Резюме

  • IDS — пайплайн IDE-оверлеев (intent → композитор → снимок → поверхность).
  • Ортогонально CDS 0036; Roslyn CASCOPE013–016.

Контекст

0036 задаёт цепочку для семантики кабины (PFD/MFD/инструменты, CockpitSurfaceState, слоты приборов). Она не должна разрастаться до «всех пикселей IDE», иначе CDS станет God-слоем и смешается с 0066.

Параллельно продукту нужны глобальные IDE-оверлеи: командная палитра (Ctrl+Q), позже — toast, блокирующие диалоги, иные «поверх всего workspace» поверхности. У них другие инварианты:

  • привязка к активному TopLevel и возврат фокуса (0070);
  • keyboard-first и предсказуемый перехват ввода;
  • по возможности — снимки для тестов и наблюдаемости агента без привязки к конкретному дереву Control.

Без явного имени и границ этот контур расползается по Views/* и *ViewModel, дублируя логику «кто сверху» и «кто ест клавиши».


Решение

Вводится отдельный продуктовый контур IDS — Ide Display System (неймспейс и типы в коде: CascadeIDE.IdeDisplay.*).

1. Назначение IDS

IDS описывает presentation IDE для модальных и полумодальных оверлеев (и в перспективе — других IDE-surfaces, которые не являются приборами кабины): отделение данных/намерения и композиции снимка от конкретного рендера (Avalonia Control, Skia-хост, гибрид).

CDS остаётся каноном кабины; IDS — канон оверлеев IDE. Смешивать семантику слотов кабины и стек IDE-оверлеев в одном типе — анти-паттерн; при необходимости общ only на уровне слов «канал / композитор / снимок», не на уровне одного DTO.

Различение CDS и IDS (одно приложение, два домена)

Оба контура выполняются внутри одного процесса CascadeIDE (географически «всё это IDE»). Путаница снимается вопросом домена смысла, а не exe-файла:

CDS (и кабина вокруг него) IDS
Вопрос Куда в модели внимания кабины попадает содержимое: PFD / Forward / MFD, слот прибора, страница вторичного контура? Как показать оверлей оболочки поверх workspace: палитра, модалка, toast; фокус, z-order, перехват ввода?
Типичный тест «На какой странице MFD / в какой зоне deck / в каком слоте прибора?» «Модально поверх всего окна, как в обычном приложении, без семантики прибора?»
Норматив 0036, 0021 этот ADR, 0070
Слои «прибор vs хром» Семантика приборов и зон (0036) Не-приборный presentation shell (0066)

Мнемоника: решаешь «куда в кабине» → CDS; «глобально поверх workspace, не слот прибора» → IDS. Границу закрепляет CASCOPE016: Cockpit/ не импортирует IdeDisplay.

2. Та же дисциплина цепочки, что у 0036 (по смыслу, не по типам)

Для каждого оверлея в IDS соблюдается цепочка:

  1. Канал / состояние — что пользователь ввёл, что отфильтровано, какой режим (команды / go-to / melody), без координат пикселей.
  2. Композитор поверхности — чистая функция (или близко): из канала строит снимок для рендера и навигации (строки, выделение, подсказки, opacity).
  3. Поверхность — Avalonia/Skia: фокус, hit-test, анимации; не источник семантики оверлея.

Обобщающий контракт композиторов: IIdsSurfaceCompositor<TIntent, TSnapshot> с методом TSnapshot Compose(TIntent intent) (параметр без in при контравариантном TIntent — ограничение языка C#).

3. Единый хост ввода (input capture)

Инвариант направления: перехват клавиатуры/фокуса для стека оверлеев IDE сходится к одному месту — условный IdsOverlayHost / input router на корне активного host, а не к разрозненным PreviewKeyDown в каждом оверлее без политики.

На момент принятия ADR полная реализация хоста может быть strangler; палитра может временно оставаться self-contained (0070), но новые оверлеи не должны добавлять третий независимый «глобальный перехват» без явного согласования в этом ADR или отдельном ADR.

4. Слоты (SurfaceSlot) — опционально

SurfaceSlot (или IdsSurfaceSlot) вводится, когда появляется несколько одновременно конкурирующих IDS-поверхностей или нужен явный z-order / mount id для наблюдаемости и тестов.

Для одной палитры как единственного верхнего оверлея слот не обязателен. Для «палитра + toast + блокирующий диалог» — слот или эквивалентный стек становится частью IDS-хоста.

Именование: по умолчанию Ids* в коде, чтобы не путать с CockpitInstrumentDescriptor и слотами CDS (0047).

5. Наблюдаемость агента

Снимки IDS (например, состав строк палитры и выбранный индекс) могут поставляться в MCP/контракт агента отдельно от cockpit_surface, либо тонким полем «overlay» в общей сводке — решение по полю JSON не фиксирует этот ADR; фиксируется только разделение семантики CDS vs IDS.

6. Roslyn-guardrails (CASCOPE013–016)

На сборке CascadeIDE.ArchitectureAnalyzers:

  • CASCOPE013 / CASCOPE014 / CASCOPE015 — в каталоге IdeDisplay/ запрещены зависимости от CascadeIDE.Cockpit…, от Avalonia UI и от CascadeIDE.Features.UiChrome (в т.ч. типы в членах классов в CascadeIDE.IdeDisplay.*).
  • CASCOPE016 — в Cockpit/ запрещён using CascadeIDE.IdeDisplay… (кабина не тянет IDS).

Полные формулировки и уровни — в README анализаторов.


Состояние реализации (фиксация на дату ADR)

  • Сделано: контракт IIdsSurfaceCompositor<TIntent, TSnapshot>; для палитры — CommandPaletteSurfaceIntent, CommandPaletteSurfaceSnapshot, CommandPaletteSurfaceCompositor; обновление снимка из MainWindowViewModel при открытой палитре; тесты композитора; Roslyn CASCOPE013–016 (см. §6).
  • По плану (strangler): единый IdsOverlayHost / router ввода; опциональные IdsSurfaceSlot при втором оверлее; при необходимости — проекция в MCP без смешения с CDS.

Последствия

  • Новые IDE-оверлеи по умолчанию проектируются через IDS (intent → compositor → snapshot → surface), а не «сразу в AXAML логикой наполовину в VM».
  • CDS и реестр приборов кабины не раздуваются ответственностью за глобальные IDE-модалки.
  • Тесты могут опираться на снимок IDS там, где важна семантика списка/выбора, без хрупкой привязки к визуальному дереву.

Не цели

  • Замена Avalonia как host для оверлеев.
  • Переименование или перепрофилирование CDS под IDE-chrome.
  • Полная спецификация JSON для агента в этом ADR.

Отклонённые альтернативы (кратко)

  • Всё в CDS: отклонено — смешивает кабину и IDE-shell, ломает 0066.
  • Отдельный ADR на каждый оверлей без общего IDS-имени: допустимо как временная мера, но ведёт к дублированию политики input/stack.