ADR 0055: Skia instrument composition pipeline (Intent -> Declutter -> Layout -> Render)¶
Статус: Accepted
Дата: 2026-04-17
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0036 | Канал → CDS → surface |
| 0047 | Instrument / slot |
| 0049 | Поэтапный Skia rollout |
| 0053 | Semantic Map, control flow |
| 0056 | Первый consumer — карта намерений |
| 0064 | Стадия Render, примитивы deck |
Резюме¶
- Общий pipeline Skia-инструментов: Intent → Declutter → Layout → Render.
- Единые invariants для semantic map, deck и будущих приборов.
- Потребители — 0056, 0057.
Контекст¶
Skia-инструменты в CIDE (workspace_navigation_map, будущие приборы и overlays) размещаются через host surface compositor, но внутренняя композиция каждого инструмента (данные, declutter, геометрия, рендер-правила) исторически смешивалась в конкретной фиче.
Это дало два системных эффекта:
- Граница ответственности размыта: "surface" и "instrument internals" смешиваются в обсуждении и коде.
- Каждая новая Skia-фича рискует заново изобретать собственный мини-pipeline без общих invariants.
- На примере
controlFlowпо 0053 видно, что без отдельного declutter-слоя читаемость деградирует на маленьком viewport.
Решение¶
1) Ввести единый pipeline для всех Skia-инструментов¶
Для каждого Skia-инструмента фиксируется внутренняя последовательность:
- Intent: построение доменной модели состояния инструмента (source-of-truth для содержимого).
- Declutter: policy-фильтрация/агрегация и приоритизация перед геометрией.
- Layout: геометрическая раскладка.
- Render: отрисовка готовой scene без бизнес-логики.
Surface compositor при этом остаётся внешним слоем и отвечает только за "куда инструмент монтируется" (slot/surface), но не за внутреннюю геометрию/declutter инструмента.
2) Внутренний композитор инструмента обязателен¶
В каждом инструменте вводится отдельный композитор (например *Compositor), который:
- выбирает layout-движок по доменному уровню детализации;
- применяет policy высоты/плотности viewport;
- возвращает готовую scene и параметры отображения.
Это канонический путь для новых Skia-фич, чтобы не дублировать логику в VM и контролах.
3) Declutter — общий слой политики, не "if'ы" в layout¶
Правила снижения шума (плотность, агрегация повторов, приоритет главного сценария над вторичными деталями — у графа: main-flow vs второстепенные рёбра) вводятся как отдельный policy-слой с единым интерфейсом для разных инструментов.
Layout не должен решать "что скрывать", а только "как раскладывать то, что уже отобрано".
4) Layout / Render: инварианты читаемости (ориентиры HF / кабина)¶
Ниже — инструмент-агностичные правила: они относятся к любому Skia-инструменту с pipeline из §1 (таймлайн чата, шкала, граф потока управления, схема и т.д.). Примеры в скобках иллюстрируют частный случай; каноническая детализация для control-flow — 0053. Связь с моделью внимания кокпита: 0021, 0046.
-
Иерархия внимания и порядок отрисовки (Render). У инструмента задаётся фиксированный порядок слоёв базовой сцены: сначала фон/сетка и «несущие» примитивы, затем основной контент, затем подписи и вспомогательная разметка в пределах своих зон. Сигналы внимания из CDS/каналов (0036) — подсветки, трассы, health — рисуются поверх этой базы, без перестройки доменной геометрии под «алерт». Интерактивный фокус (курсор, выделение) — верхний читаемый слой относительно статики. (Пример: граф — рёбра → узлы → подписи в полосе; чат — фон ветки → пузыри → метки времени.)
-
Бюджет шума: Declutter выбирает что, Layout ограничивает сколько помещается. Declutter задаёт набор видимых сущностей и агрегацию; Layout навешивает плотностные и геометрические потолки под viewport (минимальные зазоры между блоками, лимиты строк/колонок, резервы под вспомогательные колонки). Нельзя компенсировать перегруз контентом одним масштабом, если policy уже сигнализирует «слишком много» — сначала снизить объём или уровень детализации. (Пример: граф — шаг по вертикали и ширина полосы; чат — число видимых сообщений и высота превью.)
-
Уровни детализации (Glance / Normal / Inspect) — прежде всего Declutter, не только геометрия. Доменный уровень детализации (в т.ч. общие
glance/normal/inspectиз плана внедрения) задаёт отбор и агрегацию до Layout. Layout меняет метрики раскладки, но не подменяет решение «сколько сущностей показывать» между Glance и Inspect. (Пример:CodeNavigationMapDetailLevelдля карты; для другого инструмента — свой enum/шкала, тот же принцип разделения ролей.) -
Минимумы читаемости в Glance (Render / тема). При сжатии viewport сохранять нижние пороги читаемости: размер глифа, толщина линий, контраст обводок — чтобы режим «взгляд сбоку» не превращался в неразличимый шум. Числа задаются темой/константами инструмента; инвариант — не жертвовать различимостью ради влезания в rect. (Пример: минимальная толщина связей и обводок узлов; минимальная высота строки в списке.)
-
Стабильные пространственные роли (Layout). Подписи, легенды, шкалы и прочая вспомогательная графика привязываются к якорной зоне основного контента (смежная область, фиксированный отступ от «полосы» данных), а не прыгают в произвольный угол viewport — ниже стоимость сопоставления метки с объектом. (Пример: легенда у полосы графа 0053; подпись оси у края той же области, что и данные.)
-
Алертинг поверх базы. Композиторы каналов (TraceFlow, health и т.д.) добавляют overlay к уже собранной базовой scene инструмента: они не дублируют Intent/Layout доменной модели, а только отображают состояние внимания/трасс/статуса поверх неё — для любого типа базового прибора.
Контрактные проверки (тесты pipeline): на малом viewport — нет запрещённых для инструмента пересечений layout-примитивов (коллизии, нечитаемое наложение) при заявленном уровне детализации; при переходе к более глубокому уровню (например Glance → Inspect) объём полезной информации не сужается без явной policy-деградации (пустое состояние, ошибка данных). Конкретика «что считать коллизией» — в контракте каждого инструмента.
Последствия¶
Плюсы¶
- Чёткая архитектурная граница: host surface vs instrument internals.
- Единый контракт для всех будущих Skia-фич и приборов.
- Можно независимо эволюционировать declutter/layout/render без регрессий в slot-композиции.
Минусы¶
- Больше сущностей и контрактов в слое Skia-инструментов.
- Нужны отдельные тесты pipeline-уровня (не только layout unit tests).
Не-цели¶
- Не менять ADR 0036 и 0047: внешняя surface-композиция остаётся как есть.
- Не фиксировать здесь конечный UI-стиль всех edge-кейсов и всех инструментов (это эволюция в рамках pipeline и policy).
План внедрения (минимум)¶
- Зафиксировать базовый контракт общего pipeline для Skia-инструментов.
- Канонизировать
CodeNavigationMapCompositorкак первый внедрённый адаптер этого контракта. - Выделить общий
DeclutterPolicyинтерфейс (минимум:glance,normal,inspect) и инструмент-специфичные реализации. - Зафиксировать контрактные тесты pipeline:
- стабильная композиция scene при одинаковом входе;
- читаемость на малом viewport (без критических коллизий/наложений по контракту инструмента);
- корректная деградация при неполных входных данных (без ложного контента).