Forge
markdowndeeb25a2
1# IDE Health — полоса и страница (реализация: `IdeHealth*`) — implementation map (v1)
2
3**Статус:** живой чертёж (не ADR). **Обновлено:** 2026-04-25 — ссылка на [ADR 0097](../adr/0097-cockpit-compute-units-transport-to-channel-dto.md): цепочка `IdeHealthInputSnapshot` → `IdeHealthFormattingUnit` / `IdeHealthSurfaceCompositor` — пример **вычислительных юнитов (CCU)** между источниками и UI. 2026-04-25 — в коде VM: **`IdeHealthSegments`**, метод **`RebuildIdeHealth()`** (ранее `WorkspaceHealthSegments` / `RebuildWorkspaceHealth`). 2026-04-24 — продуктовое имя и типы в документе выровнены с [ADR 0089](../adr/0089-ide-omnibus-naming-and-ide-health-channel-rename.md) (**IDE Health**, `IdeHealth*`); ключи TOML `ide_health_*` (см. [0010](../adr/0010-ui-modes-toml-configuration.md), `UiModeCapabilities`). Ранее: 2026-04-17 — legacy-слой удалён; канон `IIdeHealthChannel.Build(...) -> IdeHealthSurfaceCompositor.Compose(...)`. Ранее: 2026-04-11 — **имя файла:** `workspace-health-implementation-map-v1.md` (ранее `workspace-health-compositor-implementation-v1.md` — переименовано: документ про **канал** IDE Health и карту намерений, а не про «композитор стекла» IDE целиком). Ранее: 2026-04-11 — каноническое имя контура: **IDE Health** (ранее *Workspace Health*); §1: «слот презентации vs канал»; ссылка на ADR 0021 §1.2. Ранее: 2026-04-06 — `WorkspaceHealthSecondaryPageView` (ныне `IdeHealthMfdPageView`) + строка в §3/§4; отсылка к ADR: [содержимое якоря PFD/MFD vs Page канала](../adr/0021-pfd-mfd-cockpit-attention-model.md#anchor-pfd-mfd-content-vs-telemetry-page). Ранее: 2026-04-05 — §7.1: **решение v1 = вариант A** (отдельный контур EICAS); ранее — union types / вариант B, углубление, фазы.
4**Решения и термины** — в [ADR 0021](../adr/0021-pfd-mfd-cockpit-attention-model.md) (PFD/MFD/EICAS, ARINC 661-идеи); **канонический словарь** «канал / слой представления / имена в коде» — [§1.1](../adr/0021-pfd-mfd-cockpit-attention-model.md#glossary-channel-presentation). Лексикон и эволюция имён — [ADR 0022](../adr/0022-workspace-health-lexicon.md), переименование канала — [ADR 0089](../adr/0089-ide-omnibus-naming-and-ide-health-channel-rename.md). Слой **свёртки** сырья в снимок/DTO канала (LRU-подобный модуль) — [ADR 0097](../adr/0097-cockpit-compute-units-transport-to-channel-dto.md). Здесь — **где в коде** и **что дальше**, чтобы не раздувать ADR.
5
6---
7
8## 1. Термины (глоссарий)
9
10| Термин | Смысл |
11|--------|--------|
12| **Зона PFD / MFD / EICAS** | Семантическая роль участка UI из ADR 0021: первичный контекст, вторичные потоки, канал оповещений. **Где** на экране задаётся **пресетом** (TOML/capabilities), не перетаскиванием в сессии. |
13| **Снимок IDE Health** | `IdeHealthInputSnapshot`: нормализованные входы (build/tests/debug/git) до компоновки поверхности. Не привязан к форме «полоски». |
14| **Композиция поверхности канала** | `IdeHealthSurfaceCompositor`: из снимка собирает упорядоченные `IdeHealthSegment` (порядок, флаги вроде `IsBuildRunning`). Отвечает за **состав канала** IDE Health, не за пиксели и не за зону PFD/MFD. |
15| **Раскладка зоны / страницы (chrome layout)** | Куда на экране попадают блоки: полоса снизу, сетка на странице MFD, карточка в PFD. Задаётся **пресетом** и шаблонами (AXAML) и/или отдельным слоем в коде; рабочее имя в дизайне — *layout страницы зоны* / *display page layout*. Только **геометрия контейнера** в зоне, не дублирует порядок build/tests — тот уже зафиксирован `IdeHealthSurfaceCompositor`. |
16| **Поверхность (surface)** | **Слой представления:** как **показать** те же сегменты (полоса, страница, карточка в хроме). Выбор Strip vs Page (`ide_health_surface`, enum `IdeHealthUiSurface`) — пресет и разметка; **снимок и `IdeHealthSurfaceCompositor` не зависят** от этого слоя. Это не «хост событий» и не шина сообщений — только UI. Каноническое имя оси «форма» в ADR: **`ContentRepresentation`** (`Strip` / `Page`); см. [ADR 0063 § две оси](../adr/0063-instrument-deck-named-composition-one-anchor.md#adr0063-two-axes). |
17| **Strip (полоса)** | Конкретная поверхность представления: узкая горизонтальная полоса — [`IdeHealthStripView`](../../Views/IdeHealthStripView.axaml) (CLR-класс в AXAML может ещё называться `WorkspaceHealthStripView` до полной зачистки). |
18| **Page (страница)** | Другая поверхность представления **только для канала IDE Health** (`ide_health_surface`): те же сегменты в регионе PFD/MFD вместо полосы. Это **не** определение всего содержимого якоря — см. [ADR 0021](../adr/0021-pfd-mfd-cockpit-attention-model.md#anchor-pfd-mfd-content-vs-telemetry-page). |
19| **Канал EICAS** | Оповещения W/C/A — отдельный **семантический** контур от IDE Health (ADR §5). Визуально — полоса, список, оверлей и т.д.; контейнер в текущей разметке: `EicasAlertsBarView`, TOML `eicas_alerts_bar`. **Не путать** со Strip/Page: те относятся к **представлению** build/tests/debug/git, а не к каналу CAS. |
20
21Типы `IdeHealth*` задают **смысл** сегментов (build/tests/debug/git); [`IdeHealthStripView`](../../Views/IdeHealthStripView.axaml) — одна из **поверхностей представления**; при странице MFD / блоке PFD те же данные идут в **другую разметку** без смены `IdeHealthSurfaceCompositor`.
22
23**Показ и данные развязаны:** **Strip** или **Page** — это только **слой представления** (настройки пресета), не ветвление логики снимка и не хост событий. Strip отнимает высоту у лобового; Page не отнимает ту же полосу, но требует перехода взгляда — пользователь сам решает, что важнее, **не меняя** источники данных и `IdeHealthSurfaceCompositor`.
24
25| Уровень | Смысл | Заметка |
26|--------|--------|--------|
27| **Слот презентации** | Геометрия и роль поверхности: полоса vs **полная страница** региона MFD/PFD и т.д. | Разговорное «dedicated page» как «отдельная страница» часто про этот уровень. |
28| **Канал содержимого** | Какой поток данных заполняет слот | IDE Health (этот документ), EICAS, статус окружения, другие инструменты — **разные** каналы. |
29
30**`DedicatedPage` в пресете IDE Health** (`ide_health_surface`, enum `IdeHealthUiSurface`) относится **только** к **каналу IDE Health**: те же **`IdeHealthSegments`**, другая разметка ([`IdeHealthMfdPageView`](../../Views/IdeHealthMfdPageView.axaml)). Это **не** имя для «любой» полноэкранной страницы оболочки Mfd. Полное разведение терминов и рекомендуемые формулировки — [ADR 0021 §1.2](../adr/0021-pfd-mfd-cockpit-attention-model.md#glossary-presentation-vs-channel).
31
32---
33
34## 2. Идея в одном абзаце
35
36Несколько источников (сборка, тесты, отладка, git) **подают состояние и строки**; **один** слой (`IdeHealthSurfaceCompositor`) задаёт **порядок и состав** сегментов — независимо от **слоя представления** (**Strip** или **Page**). Текущая разметка полосы: [`IdeHealthStripView`](../../Views/IdeHealthStripView.axaml) (Balanced/Focus vs Power cockpit).
37
38---
39
40## 3. Карта файлов
41
42| Компонент | Путь | Роль |
43|-----------|------|------|
44| Снимок входов | `Cockpit/ComputingUnits/IdeHealth/IdeHealthInputSnapshot.cs` | `IdeHealthInputSnapshot` + `IdeHealthSegmentInput` (build/tests/debug/git + `Stratum` по ADR 0095). Точка расширения без раздувания сигнатур. |
45| Композитор поверхности | `Cockpit/Composition/IdeHealth/IdeHealthSurfaceCompositor.cs` | `Compose(ObservableCollection<IdeHealthSegment>, IdeHealthInputSnapshot, IdeHealthSurfaceDecision)`; порядок: Build → Tests → Debug → Git; `IsBuildRunning` только на сегменте Build. |
46| Модель сегмента | `Cockpit/Channels/IdeHealth/IdeHealthSegment.cs` | `LineText` (полная строка), `CockpitShort` (Power), флаги для шаблона. |
47| Источник enum | `Cockpit/Channels/IdeHealth/IdeHealthSource.cs` | `Build`, `Tests`, `Debug`, `Git`. |
48| Форматирование строк | `Cockpit/ComputingUnits/IdeHealth/IdeHealthFormattingUnit.cs` | CCU: `IdeHealthFormattingUnit : ICockpitComputeUnit`, singleton `Default`; сегменты `BuildSegment` / `TestsSegment` / `DebugSegment` / `GitSegment` и `Compose(...)` — чистая логика без VM/DAP; удобно для юнит-тестов. |
49| Канал снимка | `Cockpit/Channels/IdeHealth/IIdeHealthChannel.cs`, `Cockpit/ComputingUnits/IdeHealth/IdeHealthSnapshotUnit.cs` | `Build(IdeHealthChannelContext)` собирает входы из делегатов и DAP (строки git и счётчики отладки подставляет `MainWindowViewModel` с `Chrome` / `InstrumentationPanel`). Сам канал **не** ссылается на `UiChromeViewModel`. |
50| VM | `ViewModels/MainWindowViewModel.IdeHealth.cs` | `RebuildIdeHealth()` вызывает `_workspaceHealth.Build(...)` и `_workspaceHealthSurfaceCompositor.Compose(...)`. |
51| Инвалидация | `ViewModels/MainWindowViewModel.LayoutNotifications.cs` | `RebuildIdeHealth` при смене данных build/tests/debug. |
52| Git-строки | `Features/UiChrome/UiChromeViewModel.cs` | `WorkspaceHealthGitText`, `WorkspaceHealthGitCockpitShort`; подписка в `MainWindowViewModel` на `Chrome.PropertyChanged`. |
53| Свойства для UI | `ViewModels/MainWindowViewModel.Presentation.cs` | `IdeHealthBuild*` / `IdeHealthTests*` / `IdeHealthDebug*` — строки из кэша `_lastIdeHealthInputSnapshot` (один `IIdeHealthChannel.Build` на `RebuildIdeHealth`); Skia mount — `IdeHealthMountPayload` с тем же тиком. Флаги сессии отладки — из DAP. |
54| Полоса хрома над нижним доком | `Views/WorkspaceChromeBandView.axaml` | Сетка колонок как у `MainGrid` (0–4); слот `EicasAlertsBarView` и вложенный `IdeHealthStripView`. Включение полосы IDE Health: `ShowIdeHealthStrip` (`ide_health_strip` + `IdeHealthUiSurface.BottomStrip` в capabilities). По смыслу — контейнер **представления** нижней зоны (EICAS + Strip), не «хост событий». |
55| UI полосы | `Views/IdeHealthStripView.axaml` | `ItemsControl` по `IdeHealthSegments`; разные шаблоны для Power vs остальные режимы. |
56| Страница оболочки Mfd (v1 — зона Mfd) | `Views/IdeHealthMfdPageView.axaml` | Тот же `IdeHealthSegments` при `ShowIdeHealthMfdPage` (`ide_health_strip` + `DedicatedPage`); в `MainWindow` — над `ChatPanelView` в колонке зоны Mfd. |
57| Тесты | `CascadeIDE.Tests/IdeHealthSurfaceCompositorTests.cs`, `IdeHealthFormattingUnitTests.cs` | Композитор поверхности: порядок, `IsBuildRunning`. Формат: сегменты и `Compose` для снимка (`IdeHealthFormattingUnitTests`). |
58
59---
60
61## 4. Поток данных (кратко)
62
631. Состояние меняется (сборка, тесты, DAP, git, …).
642. Свойства `WorkspaceHealth*` / `IdeHealth*` уведомляют UI (частично через `[NotifyPropertyChangedFor]`, частично явный `OnPropertyChanged` для отладки).
653. `RebuildIdeHealth()` берёт снимок через `_workspaceHealth.Build(...)` (внутри — делегаты/DAP/`UiChromeViewModel` + `IdeHealthFormattingUnit`) и вызывает `_workspaceHealthSurfaceCompositor.Compose(...)`.
664. `IdeHealthSegments` обновляется; привязка к `IdeHealthStripView` (через `WorkspaceChromeBandView`) или к `IdeHealthMfdPageView` в колонке зоны Mfd при `DedicatedPage`.
67
68Альтернативная реализация канала (агент, MCP, моки в тестах VM) подменяет только сбор снимка, не `IdeHealthSurfaceCompositor` и не разметку полосы.
69
70---
71
72## 5. Статус vs ADR 0021 (первая строка таблицы ARINC)
73
74| Идея ADR | В коде сейчас |
75|----------|----------------|
76| Принцип ADR: единый слой смысла над источниками (не разрозненные toast) | Да: канал IDE Health — `_workspaceHealth.Build(...)` + `_workspaceHealthSurfaceCompositor.Compose(...)` + `IdeHealthInputSnapshot`. |
77| Источники не владеют отдельным слоем toast без правил | Частично: строки централизованы; отдельные toast-цепочки не сводились сюда. |
78| EICAS / Warning–Caution–Advisory | Нет: сегменты без уровня приоритета; полоса не EICAS-лента. |
79| Декларативный merge из TOML | Частично: видимость полосы через capabilities/режимы; **порядок/состав** сегментов пока не из конфига. |
80
81---
82
83## 6. Краткий backlog (приоритет на усмотрение продукта)
84
851. **Пустые / placeholder-сегменты** — см. §7.2; согласовать с Dark Cockpit ([ADR 0021 §6](../adr/0021-pfd-mfd-cockpit-attention-model.md)).
862. **Приоритет / EICAS** — отдельный контур оповещений и уровни W/C/A ([ADR §5](../adr/0021-pfd-mfd-cockpit-attention-model.md)); см. §7.1 и §7.3.
873. **Конфиг** — порядок/видимость сегментов IDE Health по режиму (TOML / capabilities); §7.4.
884. **Раскладка без нижней полосы** — Page / карточка PFD; тот же снимок + `IdeHealthSurfaceCompositor`, **другой слой представления** (§1, §7.5).
895. **Канал снимка** — сделано: `IIdeHealthChannel`, `IdeHealthSnapshotUnit`, `IdeHealthFormattingUnit`.
90
91---
92
93## 7. Углубление: два контура, приоритет, Dark Cockpit
94
95Ниже — рабочая модель для реализации **без смешения** «статуса работы» (сборка, тесты, отладка, git) и **оповещений EICAS** (Warning / Caution / Advisory). ADR уже разводит их по смыслу; в коде это стоит закрепить явно.
96
97### 7.1 Два контура данных
98
99| Контур | Назначение | Примеры | Приоритет W/C/A |
100|--------|------------|---------|------------------|
101| **IDE Health** | Ориентир «что происходит с задачей» (build/tests/debug/git) | Сборка, тесты, сессия отладки, git | **Не применяется** — фиксированный канонический порядок в `IdeHealthSurfaceCompositor` (Build → Tests → Debug → Git) |
102| **EICAS / CAS** | Оповещения, требующие внимания или действия | Падение MCP при L3, блокировка агента, критичная ошибка по файлу в фокусе | **Да** — сортировка и отсечение по уровню ([ADR §5](../adr/0021-pfd-mfd-cockpit-attention-model.md)) |
103
104**Почему «просто один список» опасен без дисциплины:** смешение в одной коллекции без явного тега «work vs alert» ведёт к спецслучаям в шаблонах и к риску раздуть полосу (Dark Cockpit). Это **не** запрет на один `ItemsControl`: при **явном** дискриминаторе проблема «полуслучайного порядка» снимается на уровне типов.
105
106- **Вариант A:** `IdeHealthSurfaceCompositor` остаётся только про **IDE Health**. EICAS — отдельная модель (`EicasMessage`, коллекция для UI), упорядочивание для UI — `EicasMessageSorter` (по `Severity` и времени); **размещение и представление** (`MainWindow` / зона `eicas` по пресету) задают, рисовать ли полосу над доком, оверлей или компактный список ([ADR §5](../adr/0021-pfd-mfd-cockpit-attention-model.md) уже допускает варианты). Это не тот же выбор, что Strip/Page для IDE Health.
107- **Вариант B:** дискриминированное объединение — один список элементов ленты, каждый элемент знает вариант: **работа** (build/tests/…) или **EICAS**; один `ItemsControl` с шаблоном по типу/варианту; `Rebuild` строит упорядоченную последовательность с **разными** правилами сортировки для каждой группы (сначала канон работы, внутри EICAS — по W/C/A), без смешения в одну «кучу».
108
109**Решение для v1:** принят **вариант A** — отдельный контур EICAS в коде и в источниках данных. Это **сознательная цена** за ясность двух смыслов (работа vs оповещение), простые границы тестов и соответствие ADR; **не** избегание объединённого списка ради осторожности. Вариант B остаётся запасной траекторией для последующих версий (в т.ч. при зрелом C# union types и явном продуктовом решении о «одном ментальном канале»).
110
111**C# и union types:** в языке появляются [union types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/union) (`union` / закрытый набор кейсов, исчерпывающий pattern matching) — удобный носитель для варианта B на уровне модели. На **.NET 11 Preview 2** атрибуты/интерфейс для unions в BCL ещё не обязательны в рантайме; в документации указано объявлять их в проекте до стабилизации превью. Пока целевой LangVersion репо ниже — тот же смысл можно выразить вручную через `[Union]`/ручной union-шаблон из спеки или остаться на record-иерархии + общий интерфейс, с пониманием, что компилятор не выгонит за забытую ветку так же жёстко.
112
113Вариант B после принятия union types в toolchain становится **существенно привлекательнее**: меньше страха перед «if в разметке», больше ответственности за то, **должен** ли пользователь видеть работу и оповещения в одном ментальном канале (продукт/ADR), а не только за типобезопасность.
114
115Текущий код (`IdeHealthSegment` без уровня приоритета) соответствует **только** первому контуру; расширение под EICAS — **новые типы**, а не «добавить поле Priority в Build».
116
117```mermaid
118flowchart LR
119 subgraph work [IDE Health]
120 Snap[IdeHealthInputSnapshot]
121 Comp[IdeHealthSurfaceCompositor]
122 Seg[IdeHealthSegments]
123 end
124 subgraph eicas [EICAS]
125 Feed[EicasFeed / провайдер]
126 Rank[EicasMessageSorter]
127 Cas[Eicas UI]
128 end
129 Snap --> Comp --> Seg
130 Feed --> Rank --> Cas
131```
132
133Визуально слои могут быть **рядом** (полоса IDE Health + узкая EICAS под/над ней по пресету), но **логика и источники** остаются раздельными.
134
135### 7.2 Пустые сегменты и Dark Cockpit
136
137**Проблема:** при пустых строках (нет git, тесты не запускались) либо пропадают «слоты», либо остаётся шум из placeholder’ов.
138
139| Политика | Поведение | Плюсы / минусы |
140|----------|-----------|----------------|
141| **Compact** | В полосу попадают только сегменты с непустым `LineText` (после trim) | Меньше шума, соответствует «не показывать лишнее» ([Dark Cockpit §6](../adr/0021-pfd-mfd-cockpit-attention-model.md)); меняется длина полосы |
142| **Fixed slots** | Всегда 4 (или N) ячеек; пустые — «—» / приглушённый placeholder | Стабильный scan pattern; риск визуального мусора в тихом режиме |
143| **Режим-зависимый** | Focus/Balanced — compact; Power — fixed для нижнего ряда кокпита | Согласуется с разными шаблонами в `IdeHealthStripView` |
144
145**Рекомендация для первой итерации:** ввести флаг политики на уровне VM или пресета (`StripEmptySegmentPolicy: Compact | FixedFour`), реализовать **фильтрацию или placeholder** в одном месте — либо внутри `IdeHealthSurfaceCompositor` (не добавлять пустые), либо в отдельном шаге **после** `Compose` (нормализация коллекции). Не размазывать условия по AXAML.
146
147### 7.3 Приоритет и сортировка
148
149- **IDE Health:** порядок **не** конфигурируется приоритетом опасности — только **фиксированная пермутация** (при необходимости единственный конфиг: массив enum порядка в TOML, без W/C/A).
150- **EICAS:** сортировка по **уровню** и времени/идентификатору; дубликаты сообщений — политика слияния (одна строка на источник). Связь с **escalation** и таймерами — в [ADR §5](../adr/0021-pfd-mfd-cockpit-attention-model.md), не в `IdeHealthFormattingUnit`.
151
152### 7.4 Конфиг сегментов IDE Health
153
154Цель: **какие** источники включены в каком `UiMode` / capability, без смешения с EICAS.
155
156- **Минимум:** расширение capabilities (например скрыть git в Focus).
157- **Полный вариант:** в `workspace.toml` опциональный блок в духе `attention_strip_order = ["build", "tests", "debug", "git"]` и/или `attention_strip_enabled = { git = false }` — парсится в структуру рядом с `UiWorkspaceToml`, merge с бандлом ([ADR 0021 §2.1 / §17](../adr/0021-pfd-mfd-cockpit-attention-model.md)).
158- **`IdeHealthSurfaceCompositor`:** читает не сырой TOML, а **уже слитый** `IdeHealthLayoutPolicy` (immutable) на один вызов `Compose`, чтобы тестировать без файлов.
159
160### 7.5 Page и нижняя полоса
161
162Тот же `IdeHealthInputSnapshot` и тот же порядок сегментов подаются в **другую разметку представления** (Page): полноэкранная страница MFD или блок в PFD. Меняются только шаблоны (не одна строка на сегмент, допускается многострочный вывод). `IdeHealthSurfaceCompositor` **не** ветвится по Strip/Page.
163
164### 7.6 Фазы внедрения (предложение)
165
166| Фаза | Содержание | Критерий готовности |
167|------|------------|---------------------|
168| **F1** | Политика пустых сегментов + тесты на `IdeHealthSurfaceCompositor` / нормализацию | Предсказуемое поведение в Focus vs Power |
169| **F2** | Модель `EicasMessage`, провайдер, представление канала EICAS в зоне пресета (хотя бы список + цвет W/C/A) | Один Warning виден без охоты по вкладкам ([§18 / EICAS в ADR](../adr/0021-pfd-mfd-cockpit-attention-model.md)) |
170| **F3** | Dark Cockpit transition: из «тихо» в Warning (бейдж/полоса/оверлей по пресету) | Нет постоянной четвёртой колонки |
171| **F4** | TOML / merge для порядка и включения сегментов IDE Health | Согласовано с roadmap `.cascade/workspace.toml` |
172| **F5** | Страница IDE Health (Page) как альтернатива Strip | Тот же снимок, другой AXAML |
173
174---
175
176## 8. Связанные документы
177
178- [`environment-readiness-glance-v1.md`](environment-readiness-glance-v1.md) — канал **готовности окружения** (LSP, инструменты, glance); **не** IDE Health. ADR: [0023](../adr/0023-environment-readiness-glance.md).
179- [ADR 0021](../adr/0021-pfd-mfd-cockpit-attention-model.md) — модель внимания, зоны, EICAS (§5), Dark Cockpit (§6), метрики.
180- [ADR 0010](../adr/0010-ui-modes-toml-configuration.md) — режимы UI и capabilities.
181- [`cascade-ide-ui-layout-v1.md`](../ui-ux/cascade-ide-ui-layout-v1.md) — раскладка окон.
182
View only · write via MCP/CIDE