Forge

docs/ / design/workspace-health-implementation-map-v1.md · branch develop

IDE Health — полоса и страница (реализация: IdeHealth*) — implementation map (v1)

Статус: живой чертёж (не ADR). Обновлено: 2026-04-25 — ссылка на ADR 0097: цепочка IdeHealthInputSnapshotIdeHealthFormattingUnit / IdeHealthSurfaceCompositor — пример вычислительных юнитов (CCU) между источниками и UI. 2026-04-25 — в коде VM: IdeHealthSegments, метод RebuildIdeHealth() (ранее WorkspaceHealthSegments / RebuildWorkspaceHealth). 2026-04-24 — продуктовое имя и типы в документе выровнены с ADR 0089 (IDE Health, IdeHealth*); ключи TOML ide_health_* (см. 0010, 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 канала. Ранее: 2026-04-05 — §7.1: решение v1 = вариант A (отдельный контур EICAS); ранее — union types / вариант B, углубление, фазы.
Решения и термины — в ADR 0021 (PFD/MFD/EICAS, ARINC 661-идеи); канонический словарь «канал / слой представления / имена в коде» — §1.1. Лексикон и эволюция имён — ADR 0022, переименование канала — ADR 0089. Слой свёртки сырья в снимок/DTO канала (LRU-подобный модуль) — ADR 0097. Здесь — где в коде и что дальше, чтобы не раздувать ADR.


1. Термины (глоссарий)

Термин Смысл
Зона PFD / MFD / EICAS Семантическая роль участка UI из ADR 0021: первичный контекст, вторичные потоки, канал оповещений. Где на экране задаётся пресетом (TOML/capabilities), не перетаскиванием в сессии.
Снимок IDE Health IdeHealthInputSnapshot: нормализованные входы (build/tests/debug/git) до компоновки поверхности. Не привязан к форме «полоски».
Композиция поверхности канала IdeHealthSurfaceCompositor: из снимка собирает упорядоченные IdeHealthSegment (порядок, флаги вроде IsBuildRunning). Отвечает за состав канала IDE Health, не за пиксели и не за зону PFD/MFD.
Раскладка зоны / страницы (chrome layout) Куда на экране попадают блоки: полоса снизу, сетка на странице MFD, карточка в PFD. Задаётся пресетом и шаблонами (AXAML) и/или отдельным слоем в коде; рабочее имя в дизайне — layout страницы зоны / display page layout. Только геометрия контейнера в зоне, не дублирует порядок build/tests — тот уже зафиксирован IdeHealthSurfaceCompositor.
Поверхность (surface) Слой представления: как показать те же сегменты (полоса, страница, карточка в хроме). Выбор Strip vs Page (ide_health_surface, enum IdeHealthUiSurface) — пресет и разметка; снимок и IdeHealthSurfaceCompositor не зависят от этого слоя. Это не «хост событий» и не шина сообщений — только UI. Каноническое имя оси «форма» в ADR: ContentRepresentation (Strip / Page); см. ADR 0063 § две оси.
Strip (полоса) Конкретная поверхность представления: узкая горизонтальная полоса — IdeHealthStripView (CLR-класс в AXAML может ещё называться WorkspaceHealthStripView до полной зачистки).
Page (страница) Другая поверхность представления только для канала IDE Health (ide_health_surface): те же сегменты в регионе PFD/MFD вместо полосы. Это не определение всего содержимого якоря — см. ADR 0021.
Канал EICAS Оповещения W/C/A — отдельный семантический контур от IDE Health (ADR §5). Визуально — полоса, список, оверлей и т.д.; контейнер в текущей разметке: EicasAlertsBarView, TOML eicas_alerts_bar. Не путать со Strip/Page: те относятся к представлению build/tests/debug/git, а не к каналу CAS.

Типы IdeHealth* задают смысл сегментов (build/tests/debug/git); IdeHealthStripView — одна из поверхностей представления; при странице MFD / блоке PFD те же данные идут в другую разметку без смены IdeHealthSurfaceCompositor.

Показ и данные развязаны: Strip или Page — это только слой представления (настройки пресета), не ветвление логики снимка и не хост событий. Strip отнимает высоту у лобового; Page не отнимает ту же полосу, но требует перехода взгляда — пользователь сам решает, что важнее, не меняя источники данных и IdeHealthSurfaceCompositor.

Уровень Смысл Заметка
Слот презентации Геометрия и роль поверхности: полоса vs полная страница региона MFD/PFD и т.д. Разговорное «dedicated page» как «отдельная страница» часто про этот уровень.
Канал содержимого Какой поток данных заполняет слот IDE Health (этот документ), EICAS, статус окружения, другие инструменты — разные каналы.

DedicatedPage в пресете IDE Health (ide_health_surface, enum IdeHealthUiSurface) относится только к каналу IDE Health: те же IdeHealthSegments, другая разметка (IdeHealthMfdPageView). Это не имя для «любой» полноэкранной страницы оболочки Mfd. Полное разведение терминов и рекомендуемые формулировки — ADR 0021 §1.2.


2. Идея в одном абзаце

Несколько источников (сборка, тесты, отладка, git) подают состояние и строки; один слой (IdeHealthSurfaceCompositor) задаёт порядок и состав сегментов — независимо от слоя представления (Strip или Page). Текущая разметка полосы: IdeHealthStripView (Balanced/Focus vs Power cockpit).


3. Карта файлов

Компонент Путь Роль
Снимок входов Cockpit/ComputingUnits/IdeHealth/IdeHealthInputSnapshot.cs IdeHealthInputSnapshot + IdeHealthSegmentInput (build/tests/debug/git + Stratum по ADR 0095). Точка расширения без раздувания сигнатур.
Композитор поверхности Cockpit/Composition/IdeHealth/IdeHealthSurfaceCompositor.cs Compose(ObservableCollection<IdeHealthSegment>, IdeHealthInputSnapshot, IdeHealthSurfaceDecision); порядок: Build → Tests → Debug → Git; IsBuildRunning только на сегменте Build.
Модель сегмента Cockpit/Channels/IdeHealth/IdeHealthSegment.cs LineText (полная строка), CockpitShort (Power), флаги для шаблона.
Источник enum Cockpit/Channels/IdeHealth/IdeHealthSource.cs Build, Tests, Debug, Git.
Форматирование строк Cockpit/ComputingUnits/IdeHealth/IdeHealthFormattingUnit.cs CCU: IdeHealthFormattingUnit : ICockpitComputeUnit, singleton Default; сегменты BuildSegment / TestsSegment / DebugSegment / GitSegment и Compose(...) — чистая логика без VM/DAP; удобно для юнит-тестов.
Канал снимка Cockpit/Channels/IdeHealth/IIdeHealthChannel.cs, Cockpit/ComputingUnits/IdeHealth/IdeHealthSnapshotUnit.cs Build(IdeHealthChannelContext) собирает входы из делегатов и DAP (строки git и счётчики отладки подставляет MainWindowViewModel с Chrome / InstrumentationPanel). Сам канал не ссылается на UiChromeViewModel.
VM ViewModels/MainWindowViewModel.IdeHealth.cs RebuildIdeHealth() вызывает _workspaceHealth.Build(...) и _workspaceHealthSurfaceCompositor.Compose(...).
Инвалидация ViewModels/MainWindowViewModel.LayoutNotifications.cs RebuildIdeHealth при смене данных build/tests/debug.
Git-строки Features/UiChrome/UiChromeViewModel.cs WorkspaceHealthGitText, WorkspaceHealthGitCockpitShort; подписка в MainWindowViewModel на Chrome.PropertyChanged.
Свойства для UI ViewModels/MainWindowViewModel.Presentation.cs IdeHealthBuild* / IdeHealthTests* / IdeHealthDebug* — строки из кэша _lastIdeHealthInputSnapshot (один IIdeHealthChannel.Build на RebuildIdeHealth); Skia mount — IdeHealthMountPayload с тем же тиком. Флаги сессии отладки — из DAP.
Полоса хрома над нижним доком Views/WorkspaceChromeBandView.axaml Сетка колонок как у MainGrid (0–4); слот EicasAlertsBarView и вложенный IdeHealthStripView. Включение полосы IDE Health: ShowIdeHealthStrip (ide_health_strip + IdeHealthUiSurface.BottomStrip в capabilities). По смыслу — контейнер представления нижней зоны (EICAS + Strip), не «хост событий».
UI полосы Views/IdeHealthStripView.axaml ItemsControl по IdeHealthSegments; разные шаблоны для Power vs остальные режимы.
Страница оболочки Mfd (v1 — зона Mfd) Views/IdeHealthMfdPageView.axaml Тот же IdeHealthSegments при ShowIdeHealthMfdPage (ide_health_strip + DedicatedPage); в MainWindow — над ChatPanelView в колонке зоны Mfd.
Тесты CascadeIDE.Tests/IdeHealthSurfaceCompositorTests.cs, IdeHealthFormattingUnitTests.cs Композитор поверхности: порядок, IsBuildRunning. Формат: сегменты и Compose для снимка (IdeHealthFormattingUnitTests).

4. Поток данных (кратко)

  1. Состояние меняется (сборка, тесты, DAP, git, …).
  2. Свойства WorkspaceHealth* / IdeHealth* уведомляют UI (частично через [NotifyPropertyChangedFor], частично явный OnPropertyChanged для отладки).
  3. RebuildIdeHealth() берёт снимок через _workspaceHealth.Build(...) (внутри — делегаты/DAP/UiChromeViewModel + IdeHealthFormattingUnit) и вызывает _workspaceHealthSurfaceCompositor.Compose(...).
  4. IdeHealthSegments обновляется; привязка к IdeHealthStripView (через WorkspaceChromeBandView) или к IdeHealthMfdPageView в колонке зоны Mfd при DedicatedPage.

Альтернативная реализация канала (агент, MCP, моки в тестах VM) подменяет только сбор снимка, не IdeHealthSurfaceCompositor и не разметку полосы.


5. Статус vs ADR 0021 (первая строка таблицы ARINC)

Идея ADR В коде сейчас
Принцип ADR: единый слой смысла над источниками (не разрозненные toast) Да: канал IDE Health — _workspaceHealth.Build(...) + _workspaceHealthSurfaceCompositor.Compose(...) + IdeHealthInputSnapshot.
Источники не владеют отдельным слоем toast без правил Частично: строки централизованы; отдельные toast-цепочки не сводились сюда.
EICAS / Warning–Caution–Advisory Нет: сегменты без уровня приоритета; полоса не EICAS-лента.
Декларативный merge из TOML Частично: видимость полосы через capabilities/режимы; порядок/состав сегментов пока не из конфига.

6. Краткий backlog (приоритет на усмотрение продукта)

  1. Пустые / placeholder-сегменты — см. §7.2; согласовать с Dark Cockpit (ADR 0021 §6).
  2. Приоритет / EICAS — отдельный контур оповещений и уровни W/C/A (ADR §5); см. §7.1 и §7.3.
  3. Конфиг — порядок/видимость сегментов IDE Health по режиму (TOML / capabilities); §7.4.
  4. Раскладка без нижней полосы — Page / карточка PFD; тот же снимок + IdeHealthSurfaceCompositor, другой слой представления (§1, §7.5).
  5. Канал снимка — сделано: IIdeHealthChannel, IdeHealthSnapshotUnit, IdeHealthFormattingUnit.

7. Углубление: два контура, приоритет, Dark Cockpit

Ниже — рабочая модель для реализации без смешения «статуса работы» (сборка, тесты, отладка, git) и оповещений EICAS (Warning / Caution / Advisory). ADR уже разводит их по смыслу; в коде это стоит закрепить явно.

7.1 Два контура данных

Контур Назначение Примеры Приоритет W/C/A
IDE Health Ориентир «что происходит с задачей» (build/tests/debug/git) Сборка, тесты, сессия отладки, git Не применяется — фиксированный канонический порядок в IdeHealthSurfaceCompositor (Build → Tests → Debug → Git)
EICAS / CAS Оповещения, требующие внимания или действия Падение MCP при L3, блокировка агента, критичная ошибка по файлу в фокусе Да — сортировка и отсечение по уровню (ADR §5)

Почему «просто один список» опасен без дисциплины: смешение в одной коллекции без явного тега «work vs alert» ведёт к спецслучаям в шаблонах и к риску раздуть полосу (Dark Cockpit). Это не запрет на один ItemsControl: при явном дискриминаторе проблема «полуслучайного порядка» снимается на уровне типов.

  • Вариант A: IdeHealthSurfaceCompositor остаётся только про IDE Health. EICAS — отдельная модель (EicasMessage, коллекция для UI), упорядочивание для UI — EicasMessageSorter (по Severity и времени); размещение и представление (MainWindow / зона eicas по пресету) задают, рисовать ли полосу над доком, оверлей или компактный список (ADR §5 уже допускает варианты). Это не тот же выбор, что Strip/Page для IDE Health.
  • Вариант B: дискриминированное объединение — один список элементов ленты, каждый элемент знает вариант: работа (build/tests/…) или EICAS; один ItemsControl с шаблоном по типу/варианту; Rebuild строит упорядоченную последовательность с разными правилами сортировки для каждой группы (сначала канон работы, внутри EICAS — по W/C/A), без смешения в одну «кучу».

Решение для v1: принят вариант A — отдельный контур EICAS в коде и в источниках данных. Это сознательная цена за ясность двух смыслов (работа vs оповещение), простые границы тестов и соответствие ADR; не избегание объединённого списка ради осторожности. Вариант B остаётся запасной траекторией для последующих версий (в т.ч. при зрелом C# union types и явном продуктовом решении о «одном ментальном канале»).

C# и union types: в языке появляются union types (union / закрытый набор кейсов, исчерпывающий pattern matching) — удобный носитель для варианта B на уровне модели. На .NET 11 Preview 2 атрибуты/интерфейс для unions в BCL ещё не обязательны в рантайме; в документации указано объявлять их в проекте до стабилизации превью. Пока целевой LangVersion репо ниже — тот же смысл можно выразить вручную через [Union]/ручной union-шаблон из спеки или остаться на record-иерархии + общий интерфейс, с пониманием, что компилятор не выгонит за забытую ветку так же жёстко.

Вариант B после принятия union types в toolchain становится существенно привлекательнее: меньше страха перед «if в разметке», больше ответственности за то, должен ли пользователь видеть работу и оповещения в одном ментальном канале (продукт/ADR), а не только за типобезопасность.

Текущий код (IdeHealthSegment без уровня приоритета) соответствует только первому контуру; расширение под EICAS — новые типы, а не «добавить поле Priority в Build».

flowchart LR
  subgraph work [IDE Health]
    Snap[IdeHealthInputSnapshot]
    Comp[IdeHealthSurfaceCompositor]
    Seg[IdeHealthSegments]
  end
  subgraph eicas [EICAS]
    Feed[EicasFeed / провайдер]
    Rank[EicasMessageSorter]
    Cas[Eicas UI]
  end
  Snap --> Comp --> Seg
  Feed --> Rank --> Cas

Визуально слои могут быть рядом (полоса IDE Health + узкая EICAS под/над ней по пресету), но логика и источники остаются раздельными.

7.2 Пустые сегменты и Dark Cockpit

Проблема: при пустых строках (нет git, тесты не запускались) либо пропадают «слоты», либо остаётся шум из placeholder’ов.

Политика Поведение Плюсы / минусы
Compact В полосу попадают только сегменты с непустым LineText (после trim) Меньше шума, соответствует «не показывать лишнее» (Dark Cockpit §6); меняется длина полосы
Fixed slots Всегда 4 (или N) ячеек; пустые — «—» / приглушённый placeholder Стабильный scan pattern; риск визуального мусора в тихом режиме
Режим-зависимый Focus/Balanced — compact; Power — fixed для нижнего ряда кокпита Согласуется с разными шаблонами в IdeHealthStripView

Рекомендация для первой итерации: ввести флаг политики на уровне VM или пресета (StripEmptySegmentPolicy: Compact | FixedFour), реализовать фильтрацию или placeholder в одном месте — либо внутри IdeHealthSurfaceCompositor (не добавлять пустые), либо в отдельном шаге после Compose (нормализация коллекции). Не размазывать условия по AXAML.

7.3 Приоритет и сортировка

  • IDE Health: порядок не конфигурируется приоритетом опасности — только фиксированная пермутация (при необходимости единственный конфиг: массив enum порядка в TOML, без W/C/A).
  • EICAS: сортировка по уровню и времени/идентификатору; дубликаты сообщений — политика слияния (одна строка на источник). Связь с escalation и таймерами — в ADR §5, не в IdeHealthFormattingUnit.

7.4 Конфиг сегментов IDE Health

Цель: какие источники включены в каком UiMode / capability, без смешения с EICAS.

  • Минимум: расширение capabilities (например скрыть git в Focus).
  • Полный вариант: в workspace.toml опциональный блок в духе attention_strip_order = ["build", "tests", "debug", "git"] и/или attention_strip_enabled = { git = false } — парсится в структуру рядом с UiWorkspaceToml, merge с бандлом (ADR 0021 §2.1 / §17).
  • IdeHealthSurfaceCompositor: читает не сырой TOML, а уже слитый IdeHealthLayoutPolicy (immutable) на один вызов Compose, чтобы тестировать без файлов.

7.5 Page и нижняя полоса

Тот же IdeHealthInputSnapshot и тот же порядок сегментов подаются в другую разметку представления (Page): полноэкранная страница MFD или блок в PFD. Меняются только шаблоны (не одна строка на сегмент, допускается многострочный вывод). IdeHealthSurfaceCompositor не ветвится по Strip/Page.

7.6 Фазы внедрения (предложение)

Фаза Содержание Критерий готовности
F1 Политика пустых сегментов + тесты на IdeHealthSurfaceCompositor / нормализацию Предсказуемое поведение в Focus vs Power
F2 Модель EicasMessage, провайдер, представление канала EICAS в зоне пресета (хотя бы список + цвет W/C/A) Один Warning виден без охоты по вкладкам (§18 / EICAS в ADR)
F3 Dark Cockpit transition: из «тихо» в Warning (бейдж/полоса/оверлей по пресету) Нет постоянной четвёртой колонки
F4 TOML / merge для порядка и включения сегментов IDE Health Согласовано с roadmap .cascade/workspace.toml
F5 Страница IDE Health (Page) как альтернатива Strip Тот же снимок, другой AXAML

8. Связанные документы

View only · write via MCP/CIDE