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 Инварианты¶
- Юнит не подменяет шину доставки: не смешивать unbounded очередь и «законы сводки» в одном типе (0094 остаётся транспортом).
- Юнит не подменяет CDS: не решает, в какой регион кабины «имеет право» попасть канал — это контур 0036 п.2.
- Юнит не является поверхностью Avalonia: не владеет деревом контролов; публикация результата на UI — через существующие VM/планировщик (0004).
- Выход, если относится к Health-подобным данным, при расширении контрактов должен быть совместим с дисциплиной 0095 (не сваливать A/B/C в одно непомеченное поле без осознанного исключения).
- Тестируемость: предпочтительно тестировать юнит без загрузки
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)¶
- Новые агрегаты наблюдаемости и расширения MCP/CDS — проектировать как цепочку юнитов (возможно, один юнит на v1), с документированным входом/выходом.
- Существующий IDE Health не обязан переименовывать классы в
*ComputeUnitв одном PR; достаточно явно ссылаться на этот ADR в ревью как на канон границ. - Если юнит питается от ingestion (0094), граница: на выходе ingestion — типизированные события/чанки; на выходе юнита — смысловой снимок/DTO канала.
- Когда паттерн нарушений стабилизируется (свёртка «забылась» в типе транспорта, запрещённые
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 | IdeHealthSnapshotUnit → IIdeHealthChannel (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).