| 1 | # ADR 0068: Полезная нагрузка строки канала и проекция на поверхность (layout vs cell content) |
| 2 | |
| 3 | **Статус:** Accepted |
| 4 | **Дата:** 2026-04-19 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR / документ | Роль | |
| 9 | |----------------|------| |
| 10 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | Канал vs слот; глоссарий presentation | |
| 11 | | [0021 § глоссарий](0021-pfd-mfd-cockpit-attention-model.md#glossary-presentation-vs-channel) | Слот презентации vs проекция строки (**не путать**) | |
| 12 | | [0023](0023-environment-readiness-glance.md) | Канал readiness vs IDE Health | |
| 13 | | [0036](0036-cds-channel-compositor-surface-pipeline.md) | Канал → композитор → UI | |
| 14 | | [0063](0063-instrument-deck-named-composition-one-anchor.md) | ContentRepresentation vs instrument deck | |
| 15 | | [0064](0064-deck-primitives-visual-language-render-layer-and-palette.md) | Примитивы лампы, отрисовка | |
| 16 | | [0066](0066-cockpit-ui-vs-ide-presentation-layer.md) | Cockpit UI vs хром IDE | |
| 17 | | [`environment-readiness-glance-v1.md`](../design/environment-readiness-glance-v1.md) | Чертёж readiness | |
| 18 | |
| 19 | **Не путать:** «проекция представления» здесь — как **строка снимка** становится лампой/глифом; это уровень **ниже**, чем слот региона в [0021](0021-pfd-mfd-cockpit-attention-model.md) и не замена **ContentRepresentation** в [0063](0063-instrument-deck-named-composition-one-anchor.md). |
| 20 | |
| 21 | --- |
| 22 | ## Контекст |
| 23 | |
| 24 | По мере развития продукта один и тот же **логический снимок канала** (например готовность окружения) показывается **несколькими способами**: компактная полоса ламп, список карточек, «таблица» с колонками, возможные будущие режимы (плотность, только бейджи, отдельный MFD-блок). |
| 25 | |
| 26 | В разговоре и в коде легко **слить**: |
| 27 | |
| 28 | 1. **Раскладку** — где на экране лежат строки (сетка, полоса, колонки шапки «Компонент / Сведения», узкий vs широкий режим). |
| 29 | 2. **Содержимое ячейки** — что именно пользователь видит в позиции строки: примитив лампы, текстовый глиф, ссылка, кнопка, смешанный блок. |
| 30 | 3. **Доменную строку снимка** — стабильный id, уровень сигнала, заголовок, деталь, короткая подпись на линзе и т.д. |
| 31 | |
| 32 | Пока все строки **однородны** (один record-тип, например `AnnunciatorLampItem`), слияние не болит. Когда появятся **разные виды строк** (действие в ячейке, Rich-текст, вторичный индикатор), без именованного разделения рефакторинг превращается в разрастание `DataTemplate` и дублирование полосы и таблицы. |
| 33 | |
| 34 | Нужен **устойчивый словарь слоёв**, не обязательно отдельная сборка типов на каждый экран с первого дня. |
| 35 | |
| 36 | --- |
| 37 | |
| 38 | ## Решение |
| 39 | |
| 40 | <a id="adr0068-p1"></a> |
| 41 | |
| 42 | **1. Три осмысленных слоя (термины для ADR, ревью и кода):** |
| 43 | |
| 44 | | Слой | Вопрос | Примечание | |
| 45 | |------|--------|------------| |
| 46 | | **Полезная нагрузка строки / ячейки (row payload)** | Что **канал** утверждает о мире в этой строке? | Снимок домена: идентичность, статус, тексты, будущие варианты вида строки. Строится в `Services/` / у источника данных, **без** Avalonia. | |
| 47 | | **Идентичность слота (slot identity)** | Где строка **стоит** в упорядоченном наборе и как на неё ссылаются тесты и пресеты? | Стабильные id ячеек, порядок в deck (напр. `EnvironmentReadinessInstrumentDeck.OrderedCellIds`), связь с каналом readiness ([0023](0023-environment-readiness-glance.md)). Ортогонально тому, **как** нарисована ячейка. | |
| 48 | | **Проекция представления (presentation projection)** | Как **конкретная поверхность** отображает **ту же** полезную нагрузку: линза в полосе, та же линза в первой колонке таблицы, текстовый глиф-заглушка, интерактив в хроме IDE? | Выбор примитива и шаблона; может переиспользовать `AnnunciatorLampMetrics` / `LabeledAnnunciatorLampFace` ([0064](0064-deck-primitives-visual-language-render-layer-and-palette.md)); интерактив и «не прибор» — по [0066](0066-cockpit-ui-vs-ide-presentation-layer.md). | |
| 49 | |
| 50 | **Инвариант:** смена **раскладки** (полоса ↔ таблица ↔ карточки) **не** меняет контракт **полезной нагрузки**; меняется только проекция и композитор/View. Смена **семантики строки** (новый вид содержимого) — расширение payload и/или дискриминатор вида строки, затем отдельные проекции по виду. |
| 51 | |
| 52 | <a id="adr0068-p2"></a> |
| 53 | |
| 54 | **2. Связь с осями [0063](0063-instrument-deck-named-composition-one-anchor.md):** ось **ContentRepresentation** (Strip / Page / …) задаёт **форму контейнера** региона; **instrument deck** — **что и в каком порядке** в этом контейнере. **Проекция представления** в этом ADR — уровень **ниже**: *внутри* выбранной формы, как **каждая строка снимка** превращается в пиксели/контролы. Три слоя выше **не заменяют** ContentRepresentation и deck; они уточняют, **где не смешивать** данные канала и варианты отрисовки одной строки. |
| 55 | |
| 56 | <a id="adr0068-p3"></a> |
| 57 | |
| 58 | **3. Прагматичный v1:** допустимо хранить снимок в **одном** типе строки (`AnnunciatorLampItem` и аналоги), пока все строки **однородны**. Это не отменяет различения слоёв в голове и в ревью: полоса и таблица — **две проекции** одного payload, а не два разных «канала». |
| 59 | |
| 60 | <a id="adr0068-p4"></a> |
| 61 | |
| 62 | **4. Когда появляется гетерогенность ячеек:** вводить явное различение в **модели полезной нагрузки** (discriminated union, несколько record-типов, ключ шаблона) и сопоставлять **проекции** по виду строки; не размножать несовместимые снимки одного канала без причины. |
| 63 | |
| 64 | <a id="adr0068-p5"></a> |
| 65 | |
| 66 | **5. Дублирование одной и той же проекции** (например полоса ламп сверху и снова лампы в первом столбце таблицы) — **продуктовый** выбор: осознанное дублирование glance vs деталь или удаление избыточности. Архитектурно это решение на уровне **какие проекции включены в режим**, а не смешение payload с layout. |
| 67 | |
| 68 | --- |
| 69 | |
| 70 | ## Последствия |
| 71 | |
| 72 | - Новые экраны каналов с deck-метафорой **явно разделяют** сборку снимка, стабильные id/order и выбор проекций в View / композиторе. |
| 73 | - Рефакторинг «лампа в ячейке таблицы вместо глифа» трогает **проекцию** и переиспользование примитива ([0064](0064-deck-primitives-visual-language-render-layer-and-palette.md)), а не обязан менять `EnvironmentReadinessSnapshotBuilder`, если семантика строки не менялась. |
| 74 | - Тесты: контракт **payload** и порядок id — отдельно от визуальных тестов **проекции** (если они появляются). |
| 75 | |
| 76 | ## Открыто |
| 77 | |
| 78 | - Имена типов/интерфейсов в коде (`IRowPayload`, `PresentationProjection` и т.д.) — вводить **по мере** появления второго гетерогенного канала или повторяющегося паттерна; этот ADR задаёт **терминологию**, не обязательную сущность в репозитории на дату принятия. |
| 79 | |