Перейти к содержанию

ADR 0097: Вычислительные блоки кабины (CCU; аналог LRU Unit) — слой между транспортом, смыслом и каналом

Статус: Accepted · Implemented
Дата: 2026-04-24
Актуализировано: 2026-04-25 — второй тег: эталон CCU в канале IDE Health (§5), граница Build в CASCOPE019 (см. 0099 и IdeHealthPipelineAnalyzer).

Связанные ADR

ADR Роль
0036 канал → CDS → композитор поверхности → поверхность
0094 шина доставки в UI, аналогия AFDX
0095 три уровня смысла A/B/C и поле stratum
0102 явная граница DAL: добыча внешних данных отдельно от CCU
0068 полезная нагрузка vs проекция
0021 зоны внимания; EICAS отдельно от «работы»
0089 IDE Health как продуктовый канал
0055 другой контур compute для Skia-инструментов

Вне ADR

Документ Роль
workspace-health-implementation-map-v1.md фактическая цепочка IDE Health
CascadeIDE.ArchitectureAnalyzers/README.md Roslyn CASCOPE* — закрепление границ слоёв на сборке; CCU — см. §4

Резюме

  • CCU (cockpit compute unit) — слой свёртки смысла между сырыми событиями и DTO канала; аналог LRU Unit, не узел графа.
  • 0094 доставляет; 0095 классифицирует страту; CCU считает, что показать.
  • 0036 маршрутизирует уже готовый снимок в кабину; CDS не строит законы из сырого MSBuild.
  • Эталон в коде — IDE Health (IdeHealthInputSnapshot, formatting unit, compositor; CASCOPE019 на Build).
  • Массовое переименование типов не обязательно; новые каналы — по той же дисциплине (strangler).

1. Анализ: что уже есть и где «дыра»

1.1 Авиационная опора (без претензии на сертификацию)

В авионике рядом с шиной (ограниченный транспорт) и индикацией (CDS/дисплей) стоят вычислительные LRU (Line Replaceable Unit): блоки, которые из сырых или частично нормализованных данных строят согласованное состояние и законы отображения для экипажа (интеграция навигации, фильтрация, лимиты, приоритеты). Последняя буква в аббревиатуре — Unit; в инженерном языке Cascade для этого слоя каноничнее говорить compute unit** (юнит/блок свёртки), а не «node», чтобы не расходиться с привычным LRU и не путать с узлом графа, сети или AST.

Они не заменяют шину и не рисуют пиксели — они вычисляют, что именно имеет смысл показать.

1.2 Что в Cascade уже покрыто другими ADR

Слой ADR / артефакт Отвечает на вопрос
Доставка потоков в UI без лавины обновлений 0094 Как донести куски лога/событий до VM с backpressure и батчингом
Семантика «о чём сигнал» (папка vs решение vs процесс IDE) 0095 К какому уровню (A/B/C) отнести поле контракта
Канал кабины → маршрут внимания → композиция слота → контролы 0036 Куда в кабине и как связать слот с представлением
Полезная нагрузка строки vs то, как её рисуют 0068 Разделение DTO канала и проекции в шаблон
Guardrails слоёв на сборке (импорты, чувствительные места) CascadeIDE.ArchitectureAnalyzers (CASCOPE*, в т.ч. в духе 0036, 0066, 0079) Меньше дрейфа архитектуры при рефакторинге (человек и агент): нарушение — диагностика компилятора, не только заметка в ревью

Между сырьём (лог сборки, события DAP, git, LSP) и DTO канала / снимком для CDS часто нужен ещё один смысл: агрегация, нормализация, разрешение конфликтов, дебаунс смысла — это не всё автоматически делает ни шина 0094, ни таблица уровней 0095.

1.3 Факт в коде: IDE Health уже близок к эталону

По workspace-health-implementation-map-v1.md цепочка уже разведена:

  • IdeHealthInputSnapshot — нормализованные входы до композиции сегментов.
  • IdeHealthFormattingUnit — чистая логика строк (unit-test без VM).
  • IdeHealthSurfaceCompositor — порядок и состав сегментов для канала.
  • IIdeHealthChannel / IdeHealthSnapshotUnit — сбор снимка из делегатов и окружения.

То есть юниты свёртки уже есть, но именованный архитектурный слой в глоссарии ADR не был выделен; новые фичи рискуют снова свалить свёртку в MainWindowViewModel или в транспорт 0094 «по пути».

1.4 Дыра в формулировке

  • Нет единого термина для «LRU-подобного» модуля между ingestion и каналом.
  • Нет явного инварианта: «транспорт не считает смысл», «CDS не строит законы из сырого MSBuild», «VM в идеале оркестрирует, а не содержит всю математику сводки».
  • Для CCU как общего слоя полный набор CASCOPE ещё впереди; для IDE Health уже действует CASCOPE019 (единая точка IIdeHealthChannel.Build(...) в MainWindowViewModel.IdeHealth, см. 0099). Для остальных каналов риск частично остаётся документарным*, пока анти-паттерны не оформлены в анализаторах (§3 — направление на реализацию).

Этот ADR закрывает формулировку и связку с 0036 / 0094 / 0095 без обязательного массового переименования типов.


2. Решение

2.1 Термин

Вводится архитектурное (инженерное) понятие вычислительный блок кабины — в русском тексте допустимо и «вычислительный юнит» как разговорный кальк с англ. cockpit compute unit, сокращение CCU только как внутренний ярлык в комментариях и ADR. Не продуктовое имя для пользователя и не замена слову «канал» в смысле 0036. Английский канон имени слоя — cockpit compute unit (CCU), не compute node: так сохраняется созвучие с U в LRU.

Определение: модуль с явным контрактом входа и выхода, который из данных источников (в т.ч. после слоя 0094, если он используется) формирует снимок или DTO для канала кабины (или для следующего шага композиции в духе 0036 п.1–3), применяя правила свёртки, приоритеты и — где уместно — теги уровня из 0095 (stratum и дискриминаторы источника).

Специализация по стратам: один CCU на весь мир не обязателен и часто вреден; типичная декомпозиция — несколько юнитов (например по уровням A/B/C из 0095: рабочие имена WSCU / SSCU / ISCU) плюс отдельная композиция в единый снимок канала. Подробнее и оговорка про ISCU vs IDS — в том же § примера в 0095.

2.2 Инварианты

  1. Юнит не подменяет шину доставки: не смешивать unbounded очередь и «законы сводки» в одном типе (0094 остаётся транспортом).
  2. Юнит не подменяет CDS: не решает, в какой регион кабины «имеет право» попасть канал — это контур 0036 п.2.
  3. Юнит не является поверхностью Avalonia: не владеет деревом контролов; публикация результата на UI — через существующие VM/планировщик (0004).
  4. Выход, если относится к Health-подобным данным, при расширении контрактов должен быть совместим с дисциплиной 0095 (не сваливать A/B/C в одно непомеченное поле без осознанного исключения).
  5. Тестируемость: предпочтительно тестировать юнит без загрузки MainWindow и без полного дерева UI (как IdeHealthFormattingUnit и композитор в тестах из чертежа IDE Health).

2.3 Роль MainWindowViewModel и оркестраторов

Подписка на PropertyChanged, вызов RebuildIdeHealth() и связывание делегатов с IdeHealthSnapshotUnit — это оркестрация (клей между миром IDE и каналом). По мере роста правил свёртки их следует опускать вниз в Cockpit/* (или выделенные сервисы снимков), оставляя VM тоньше — в духе уже принятого разделения в чертеже IDE Health.

2.4 Другие контуры

Конвейеры вроде 0055 (Intent → … → Render) — отдельное семейство compute для графики; этот ADR не унифицирует их API с IdeHealth*, но признаёт ту же архитектурную идею: снимок/модель на входе, структурированный результат на выходе, тесты без лишнего UI.


3. Направление на реализацию (strangler)

  1. Новые агрегаты наблюдаемости и расширения MCP/CDS — проектировать как цепочку юнитов (возможно, один юнит на v1), с документированным входом/выходом.
  2. Существующий IDE Health не обязан переименовывать классы в *ComputeUnit в одном PR; достаточно явно ссылаться на этот ADR в ревью как на канон границ.
  3. Если юнит питается от ingestion (0094), граница: на выходе ingestion — типизированные события/чанки; на выходе юнита — смысловой снимок/DTO канала.
  4. Когда паттерн нарушений стабилизируется (свёртка «забылась» в типе транспорта, запрещённые using между CCU и Avalonia/UiChrome/ingestion и т.п.) — оформлять правило в CascadeIDE.ArchitectureAnalyzers (новые или расширение существующих CASCOPE, с тестами диагностик по образцу проекта анализаторов). Ограничения загрузки анализаторов при RoslynMcpWorkspace — как в README анализаторов; канон проверки границ для человека и CI — обычный dotnet build*.

4. Последствия

  • Появляется короткое слово для ревью: «это должно быть в CCU (юните), не в транспорте» / «не в CDS».
  • Roslyn: тот же контур, что уже даёт архитектурную строгость для кабины и IDS (CASCOPE в CascadeIDE.ArchitectureAnalyzers), естественно расширяется на границы CCU: отдельные диагностики увеличивают число правил на сборке, зато меньше тихого дрейфа — и у тебя в IDE, и у агента, который правит код без полного контекста ADR; markdown остаётся нормативом, компилятор — сторожем*.
  • Меньше риска дублировать сводку для UI и для MCP в двух местах без общего снимка.
  • Дополнительная дисциплина документации: новые ADR про наблюдаемость могут ссылаться на 0095 + 0097 вместе.

5. Состояние реализации (эталон в коде)

Канал IDE Health уже реализует паттерн CCU end-to-end без суффикса *ComputeUnit в именах типов (см. §3 ADR: strangler). В коде закреплены контракты ICockpitComputeUnit и ICockpitComputeUnitPayload (Cockpit/ComputingUnits/ICockpitComputeUnit.cs). Карта файлов и поток: workspace-health-implementation-map-v1.md; краткий указатель: Cockpit/Channels/IdeHealth/README.md.

Слой 0097 Реализация
Вход → снимок IdeHealthInputSnapshot (ICockpitComputeUnitPayload) / IdeHealthSegmentInput + IdeHealthStratum (ADR 0095)
Свёртка текста (pure) IdeHealthFormattingUnit (ICockpitComputeUnit, Default)
Сбор снимка из делегатов / DAP IdeHealthSnapshotUnitIIdeHealthChannel (ICockpitComputeUnit)
Композиция сегментов для канала IIdeHealthSurfaceCompositor / IdeHealthSurfaceCompositor (ICockpitComputeUnit, Cockpit/Composition/IdeHealth/)

Новые каналы наблюдаемости — по той же дисциплине: отдельный снимок, чистая свёртка, композиция, без смешения с 0094. Для IDE Health CASCOPE019 уже закрепляет одну из инвариантных границ; прочие CASCOPE под CCU — §3 — направление на реализацию (по мере устойчивых анти-паттернов).


6. Кандидаты на следующий CCU (практический shortlist)

Ниже — инженерный приоритет для следующих шагов после IDE Health. Это не обязательство сделать всё сразу, а порядок, где CCU обычно даёт максимальный эффект.

P1 (сразу после текущего цикла)

  • Build/Test сводка: сырой поток билд/тест событий → BuildStateSnapshot (phase, progress, errors/warnings, duration, last-failure).
  • Debug session сводка: DAP события → DebugSessionSnapshot (attached/running/stopped, stop reason, current frame, breakpoint health).
  • Launch readiness: launchSettings + startup project + env/fs-проверки → LaunchReadinessSnapshot (ready/not-ready + причины).

P2 (когда закрепим P1 контрактами)

  • Git workspace health: status/branch/ahead-behind/submodule state → RepoHealthSnapshot.
  • LSP health: состояние C#/Markdown language services → LanguageServiceHealthSnapshot (connected/degraded, diagnostics delta).
  • MCP health: доступность и деградации по инструментам → McpHealthSnapshot (availability, last error, latency buckets).

P3 (после стабилизации graph-backed контура)

  • Semantic map input snapshot: индекс/источники/инвалидации → SemanticMapInputSnapshot как вход в graph-backed surfaces.
  • Terminal attention snapshot: поток терминалов → TerminalAttentionSnapshot (active command, failure streak, long-running suspicion).

Граница для semantic map (что в CCU, а что нет)

  • В CCU: нормализация источников, дедупликация/приоритизация сигналов, вычисление derived-полей, версия/свежесть snapshot.
  • Вне CCU: графовые интеракции, layout, selection, навигационный UX и логика конкретной поверхности (0067).
  • Правило по умолчанию: если модуль отвечает на вопрос «какой смысловой снимок сейчас каноничен», это кандидат в CCU; если «как пользователь работает с этим снимком на экране», это не CCU.

7. Не цели

  • Сертификация, DO-178, физические LRU.
  • Обязательное введение нового namespace или суффикса во всех типах Cockpit/.
  • Слияние юнита с EICAS (0021): оповещения W/C/A остаются отдельным контуром данных, как в чертеже IDE Health §7.

8. Отклонённые альтернативы

  • Называть любой сервис «юнитом» — отклонено: без контракта снимка/DTO термин бессмыслен.
  • Расширять 0094, чтобы он же строил сводки Health — отклонено: смешивает транспорт и вычисление смысла.
  • Вкладывать всю математику в «композитор» из 0036 — отклонено: в 0036 композитор отвечает на связку слота и представления канала; чистая свёрка сырья в снимок логичнее как предыдущий или вложенный шаг (как IdeHealthFormattingUnit до IdeHealthSurfaceCompositor).