Forge
markdowndeeb25a2
1# ADR 0055: Skia instrument composition pipeline (Intent -> Declutter -> Layout -> Render)
2
3**Статус:** Accepted
4**Дата:** 2026-04-17
5
6## Связанные ADR
7
8| ADR | Роль |
9|-----|------|
10| [0036](0036-cds-channel-compositor-surface-pipeline.md) | Канал → CDS → surface |
11| [0047](0047-cockpit-instrument-descriptor-and-slot-composition.md) | Instrument / slot |
12| [0049](0049-skia-surface-rollout-over-avalonia-host.md) | Поэтапный Skia rollout |
13| [0053](0053-semantic-map-control-flow-pfd.md) | Semantic Map, control flow |
14| [0056](0056-semantic-map-pipeline-adoption.md) | Первый consumer — карта намерений |
15| [0064](0064-deck-primitives-visual-language-render-layer-and-palette.md) | Стадия Render, примитивы deck |
16
17## Резюме
18
19- Общий pipeline Skia-инструментов: **Intent → Declutter → Layout → Render**.
20- Единые invariants для semantic map, deck и будущих приборов.
21- Потребители — [0056](0056-semantic-map-pipeline-adoption.md), [0057](0057-chat-surface-pipeline-adoption.md).
22
23
24---
25## Контекст
26
27Skia-инструменты в CIDE (`workspace_navigation_map`, будущие приборы и overlays) размещаются через host surface compositor, но внутренняя композиция каждого инструмента (данные, declutter, геометрия, рендер-правила) исторически смешивалась в конкретной фиче.
28
29Это дало два системных эффекта:
30
311. Граница ответственности размыта: "surface" и "instrument internals" смешиваются в обсуждении и коде.
322. Каждая новая Skia-фича рискует заново изобретать собственный мини-pipeline без общих invariants.
333. На примере `controlFlow` по [0053](0053-semantic-map-control-flow-pfd.md) видно, что без отдельного declutter-слоя читаемость деградирует на маленьком viewport.
34
35---
36
37## Решение
38
39<a id="adr0055-p1"></a>
40### 1) Ввести единый pipeline для всех Skia-инструментов
41
42Для каждого Skia-инструмента фиксируется внутренняя последовательность:
43
441. **Intent**: построение доменной модели состояния инструмента (source-of-truth для содержимого).
452. **Declutter**: policy-фильтрация/агрегация и приоритизация перед геометрией.
463. **Layout**: геометрическая раскладка.
474. **Render**: отрисовка готовой scene без бизнес-логики.
48
49Surface compositor при этом остаётся внешним слоем и отвечает только за "куда инструмент монтируется" (slot/surface), но не за внутреннюю геометрию/declutter инструмента.
50
51<a id="adr0055-p2"></a>
52### 2) Внутренний композитор инструмента обязателен
53
54В каждом инструменте вводится отдельный композитор (например `*Compositor`), который:
55
56- выбирает layout-движок по доменному уровню детализации;
57- применяет policy высоты/плотности viewport;
58- возвращает готовую scene и параметры отображения.
59
60Это канонический путь для новых Skia-фич, чтобы не дублировать логику в VM и контролах.
61
62<a id="adr0055-p3"></a>
63### 3) Declutter — общий слой политики, не "if'ы" в layout
64
65Правила снижения шума (плотность, агрегация повторов, приоритет главного сценария над вторичными деталями — у графа: main-flow vs второстепенные рёбра) вводятся как отдельный policy-слой с единым интерфейсом для разных инструментов.
66Layout не должен решать "что скрывать", а только "как раскладывать то, что уже отобрано".
67
68<a id="adr0055-p4"></a>
69### 4) Layout / Render: инварианты читаемости (ориентиры HF / кабина)
70
71Ниже — **инструмент-агностичные** правила: они относятся к любому Skia-инструменту с pipeline из §1 (таймлайн чата, шкала, граф потока управления, схема и т.д.). Примеры в скобках иллюстрируют частный случай; каноническая детализация для control-flow — [0053](0053-semantic-map-control-flow-pfd.md). Связь с моделью внимания кокпита: [0021](0021-pfd-mfd-cockpit-attention-model.md), [0046](0046-presentation-layout-authority-and-cockpit-invariants.md).
72
731. **Иерархия внимания и порядок отрисовки (Render).** У инструмента задаётся **фиксированный порядок слоёв** базовой сцены: сначала фон/сетка и «несущие» примитивы, затем основной контент, затем подписи и вспомогательная разметка в пределах своих зон. Сигналы внимания из CDS/каналов ([0036](0036-cds-channel-compositor-surface-pipeline.md)) — подсветки, трассы, health — рисуются **поверх** этой базы, без перестройки доменной геометрии под «алерт». Интерактивный фокус (курсор, выделение) — верхний читаемый слой относительно статики. *(Пример: граф — рёбра → узлы → подписи в полосе; чат — фон ветки → пузыри → метки времени.)*
74
752. **Бюджет шума: Declutter выбирает *что*, Layout ограничивает *сколько помещается*.** Declutter задаёт набор видимых сущностей и агрегацию; Layout навешивает **плотностные и геометрические потолки** под viewport (минимальные зазоры между блоками, лимиты строк/колонок, резервы под вспомогательные колонки). Нельзя компенсировать перегруз контентом одним масштабом, если policy уже сигнализирует «слишком много» — сначала снизить объём или уровень детализации. *(Пример: граф — шаг по вертикали и ширина полосы; чат — число видимых сообщений и высота превью.)*
76
773. **Уровни детализации (Glance / Normal / Inspect) — прежде всего Declutter, не только геометрия.** Доменный уровень детализации (в т.ч. общие `glance` / `normal` / `inspect` из плана внедрения) задаёт **отбор и агрегацию до Layout**. Layout меняет метрики раскладки, но не подменяет решение «сколько сущностей показывать» между Glance и Inspect. *(Пример: `CodeNavigationMapDetailLevel` для карты; для другого инструмента — свой enum/шкала, тот же принцип разделения ролей.)*
78
794. **Минимумы читаемости в Glance (Render / тема).** При сжатии viewport сохранять **нижние пороги** читаемости: размер глифа, толщина линий, контраст обводок — чтобы режим «взгляд сбоку» не превращался в неразличимый шум. Числа задаются темой/константами инструмента; инвариант — **не жертвовать различимостью ради влезания в rect**. *(Пример: минимальная толщина связей и обводок узлов; минимальная высота строки в списке.)*
80
815. **Стабильные пространственные роли (Layout).** Подписи, легенды, шкалы и прочая вспомогательная графика **привязываются к якорной зоне основного контента** (смежная область, фиксированный отступ от «полосы» данных), а не прыгают в произвольный угол viewport — ниже стоимость сопоставления метки с объектом. *(Пример: легенда у полосы графа [0053](0053-semantic-map-control-flow-pfd.md); подпись оси у края той же области, что и данные.)*
82
836. **Алертинг поверх базы.** Композиторы каналов (TraceFlow, health и т.д.) добавляют **overlay** к уже собранной базовой scene инструмента: они не дублируют Intent/Layout доменной модели, а только отображают состояние внимания/трасс/статуса поверх неё — для любого типа базового прибора.
84
85**Контрактные проверки (тесты pipeline):** на малом viewport — нет **запрещённых для инструмента** пересечений layout-примитивов (коллизии, нечитаемое наложение) при заявленном уровне детализации; при переходе к более глубокому уровню (например Glance → Inspect) объём полезной информации **не сужается** без явной policy-деградации (пустое состояние, ошибка данных). Конкретика «что считать коллизией» — в контракте каждого инструмента.
86
87---
88
89## Последствия
90
91### Плюсы
92
93- Чёткая архитектурная граница: host surface vs instrument internals.
94- Единый контракт для всех будущих Skia-фич и приборов.
95- Можно независимо эволюционировать declutter/layout/render без регрессий в slot-композиции.
96
97### Минусы
98
99- Больше сущностей и контрактов в слое Skia-инструментов.
100- Нужны отдельные тесты pipeline-уровня (не только layout unit tests).
101
102---
103
104## Не-цели
105
106- Не менять ADR [0036](0036-cds-channel-compositor-surface-pipeline.md) и [0047](0047-cockpit-instrument-descriptor-and-slot-composition.md): внешняя surface-композиция остаётся как есть.
107- Не фиксировать здесь конечный UI-стиль всех edge-кейсов и всех инструментов (это эволюция в рамках pipeline и policy).
108
109---
110
111## План внедрения (минимум)
112
1131. Зафиксировать базовый контракт общего pipeline для Skia-инструментов.
1142. Канонизировать `CodeNavigationMapCompositor` как первый внедрённый адаптер этого контракта.
1153. Выделить общий `DeclutterPolicy` интерфейс (минимум: `glance`, `normal`, `inspect`) и инструмент-специфичные реализации.
1164. Зафиксировать контрактные тесты pipeline:
117 - стабильная композиция scene при одинаковом входе;
118 - читаемость на малом viewport (без критических коллизий/наложений по контракту инструмента);
119 - корректная деградация при неполных входных данных (без ложного контента).
120
121
View only · write via MCP/CIDE