Forge
markdowndeeb25a2
1# P/F/M: геометрия зон и Skia-волны (1–3)
2
3**Статус:** Wave 1–2 — в продукте как основа и опциональный отладочный слой; Wave 3 — *in progress* (mount-инструмент и style).
4
5Один сюжет: от **топологии зон** из строки презентации до **Skia-слоя** с контентом инструмента — без смешивания с «мультиоконностью как таковой» (это [ADR 0017](../adr/0017-multi-window-workspace-and-agent-surfaces.md)) и без дублирования [черновика про оверлеи vs поверхности](../design/skia-surfaces-vs-overlays-v1.md).
6
7---
8
9## Обзор волн
10
11| Волна | Что даёт | Ключи / точки входа | Примечание |
12|-------|-----------|---------------------|------------|
13| **1** | Топология колонок **P / Forward / M** на главном окне: видимость регионов, ширины, связь с пресетом и хостом MFD | `[display].presentation` / `zone_screen_layout`, грамматика `[presentation_grammar]`, разбор в `PresentationParser`, колонки `MainGrid` через `PresentationMainGridColumnDefinitions` и композитор shell | Источник истины — **ADR 0017**; Skia здесь **не обязателен** — это Avalonia-layout и модель намерений (expand/collapse регионов). |
14| **2** | **Отладочные контуры** зон поверх текущего layout — проверить геометрию без смены контента слотов | `[display].show_skia_zone_geometry_overlay` → `DisplaySettings.ShowSkiaZoneGeometryOverlay`, привязки `IsSkiaZoneGeometryOverlayPfdVisible` и т.д., оверлеи `SkiaZoneGeometryOverlayPfd` / `Forward` / `Mfd` в `MainWindow.axaml`, аналог в `MfdHostWindow.axaml` | Включено временно для валидации; по умолчанию выключено. |
15| **3** | **Mount-слой** инструмента (контент карточки и т.п.) в зоне **поверх** базового контента слота, плюс декларативный style/registry | `[display].use_skia_instrument_mount`, `instrument_mount_style`, `[[display.instrument_mount_style_rules]]` — см. раздел ниже | Ортогонально карте «какой `instrument_id` в слоте» ([ADR 0050](../adr/0050-declarative-instrument-zone-placement-toml.md)). |
16
17Волны **накладываются**: 1 задаёт *где* рамки зон; 2 — *нарисовать рамки для глаз*; 3 — *что показать в mount поверх* при уже разрешённой геометрии.
18
19---
20
21## Волна 1 — топология зон (без Skia-инструмента)
22
23- Строка **`presentation`** (и синоним `zone_screen_layout`) задаёт **сколько групп экранов** и **какие якоря** в каждой; парсер и инварианты — ADR 0017, код: `Services/Presentation/PresentationParser.cs`, `PresentationMainGridColumnDefinitions`.
24- **Композитор shell** (`MainWindowShellSurfaceCompositor` и связанный ввод) определяет, **видны ли** колонки PFD / Forward / MFD в `MainGrid`, ширины MFD и т.д. — это *intent геометрии*, не CDS и не mount.
25- Топология **main + отдельный MFD-хост** (`AttentionLayoutSurfaceKind`, подавление колонки MFD в main при открытом `MfdHostWindow`) — всё ещё волна 1, см. ADR 0017 §про хост.
26
27---
28
29## Волна 2 — overlay контуров зон (отладка геометрии)
30
31- Назначение: **визуально сверить** границы P/F/M с моделью презентации**, не меняя** привязанный к слотам контент.
32- Реализация: полупрозрачные **Border**-оверлеи и флаги видимости из VM (`ShowSkiaZoneGeometryOverlay`, `IsSkiaZoneGeometryOverlay*`).
33- Не путать с **волной 3**: контуры — только рамки; mount — данные инструмента (IDE Health и т.д.).
34
35---
36
37## Волна 3 — mount-инструмент и style (*реализовано / in progress*)
38
39### Цель волны 3
40
41Перенос не только геометрии shell, но и **содержимого инструмента** в управляемый mount-слой (Skia-style пайплайн и общий host), с **минимально безопасным** шагом и фичей по умолчанию выключенной.
42
43### Реализовано
44
451. Первый реальный **instrument-content** в mount-слое:
46 - `Views/MainWindow.axaml`
47 - компактная PFD-карта на живых данных VM (`build/tests/debug/safety`).
482. Интеграция в PFD зону:
49 - `Views/MainWindow.axaml`
50 - overlay поверх текущего контента (`SolutionExplorerView`), без замены базовой панели.
513. Флаг в пользовательских настройках:
52 - `[display].use_skia_instrument_mount`
53 - модель: `DisplaySettings`, прокси в VM: `UseSkiaInstrumentMount`.
544. Второй реальный mini-instrument в mount-слое для MFD:
55 - `Views/MfdHostWindow.axaml`
56 - компактная MFD-карта на тех же живых данных VM для проверки паритета отдельного MFD-хоста.
575. Единый **mount-layer host**:
58 - `Views/ZoneInstrumentMountView.axaml(.cs)`
59 - PFD и MFD монтируют один и тот же host-control с параметрами темы.
606. Декларативный выбор mini-инструмента:
61 - `instrument_id` + `slot_id` + `mount_style` в `ZoneInstrumentMountView`.
62 - `Views/MainWindow.axaml` и `Views/MfdHostWindow.axaml` передают декларативные параметры.
63 - `ZoneInstrumentMountPolicy` резолвит скин/заголовок по style (`instrument_mount_v1`) и slot.
647. Источник `mount_style` в настройках:
65 - `[display].instrument_mount_style`
66 - VM-proxy: `MainWindowViewModel.InstrumentMountStyle`
67 - `MainWindow` и `MfdHostWindow` bind-ят `MountStyle` из VM.
688. Style-registry:
69 - `[[display.instrument_mount_style_rules]]` c полями `surface_id`, `slot_id`, `instrument_id`, `mount_style`.
70 - резолв в VM: `ResolveInstrumentMountStyle(surface_id, slot_id, instrument_id)` с приоритетом поверхности, затем global `*`, внутри слоя: `exact -> slot/* -> */instrument -> */* -> fallback`.
71 - `MainWindow`/`MfdHostWindow` bind-ят slot-specific style (`PfdInstrumentMountStyle`, `MfdInstrumentMountStyle`).
729. Резолв style: **Strategy + Specification**:
73 - `IInstrumentMountPolicyResolver` + `SettingsBackedInstrumentMountPolicyResolver`.
74 - `InstrumentMountPolicyRuleMatchesSpecification`.
7510. Eligibility-gate для rollout по метрикам:
76 - `RolloutMetricsEligibilitySpecification` и поля `[display]` (`enforce_instrument_mount_style_eligibility`, score-пороги, `require_instrument_mount_style_scores`).
7711. Placement-spec для host-surface:
78 - `InstrumentPlacementSpecification` + `CockpitInstrumentPlacementRules`.
79 - `MainWindowHostSurfaceCompositor` монтирует инструмент только при прохождении placement-rule.
8012. Валидация конфигурации:
81 - `DisplaySettingsValidationSpecification` при `SettingsService.Load()`.
82
83### Принцип rollout (волна 3)
84
85- Не ломаем текущий UX: mount **поверх** существующего содержимого слота.
86- Фича **выключена по умолчанию** (`use_skia_instrument_mount`).
87- Цель итерации — отладить pipeline контентного overlay на реальных данных, не ломая маршрутизацию инструментов в shell.
88
89### Следующий шаг (волна 3)
90
911. Перевести content-binding с фиксированных VM-полей на декларативный контракт payload (через `instrument_id` и typed data-source), чтобы mount не знал про конкретные поля `IdeHealth*`.
922. Перенести resolver из VM в отдельный surface/style service рядом с `CockpitInstrumentDescriptor`, а не только в UI binding.
93
94---
95
96## История файла
97
98| Было | Стало |
99|------|--------|
100| `pfm-zone-geometry-wave3.md` (только волна 3) | Этот документ: **волны 1–3** в одном месте, чтобы не плодить три черновика по одной оси. |
101
View only · write via MCP/CIDE