Forge
markdowndeeb25a2
1# ADR 0012: Плавающий и отцепляемый хром workspace (к нижней зоне и ситуационной осведомлённости)
2
3**Статус:** Accepted (направление; объём v1 и конкретные контролы — по итерациям)
4**Дата:** 2026-04-02
5
6## Связанные ADR
7
8| ADR | Роль |
9|-----|------|
10| [0011](0011-debug-situational-awareness.md) | осведомлённость без раздувания низа |
11| [0010](0010-ui-modes-toml-configuration.md) | пресеты и `workspace.toml` |
12| [0006](0006-presentation-layers-and-feature-slices.md) | границы VM/UI |
13| [0013](0013-command-surface-and-discoverability.md) | см. [раздел «Разделение с 0013»](#scope-split-0013 |
14
15## Разделение с [0013](0013-command-surface-and-discoverability.md)
16
17- **0012 (этот ADR)** — размещение и плавающий хром workspace.
18- **[0013](0013-command-surface-and-discoverability.md)** — поверхность команд: как пользователь вызывает действия и как обеспечивается discoverability без раздувания toolbar.
19
20---
21## Контекст
22
23> **Flight (актуально):** длинные потоки терминала, сборки и Git — **страницы колонки MFD** (`MfdShellPageStack` внутри `MfdShellView`, регион для снимков **`MfdContourStackHost`**). Ниже — описание **исторического макета** с полной шириной нижней зоны для той же продуктовой боли (**бюджет высоты** vs редактор).
24
25В **старой топологии** **нижняя часть главного окна** была задана **жёсткой сеткой** `MainWindow`: строка с **полосой IDE Health** (сводка сборки/тестов/отладки/git — канал IDE Health), сплиттер и **`BottomPanelView`** (терминал, сборка, отладка, git и т.д.) занимали **один вертикальный слой** (`MainGrid` row 5, внутренние строки `Auto` / сплиттер / `*`). Полоса **IDE Health** (**`IdeHealthStripView`**) физически **над** вкладками низа и **не плавает** — она привязана к той же колоночной разметке, что и рабочая область.
26
27Следствие: любой **ситуационный** или **короткий** UI (статус, полоса IDE Health, будущая компактная полоска отладки из [0011](0011-debug-situational-awareness.md)) оказывается в **одном бюджете высоты** с **длинным выводом** (лог, терминал). Поднять низ, чтобы что-то увидеть, — значит **отдать пиксели редактору**; это уже зафиксировано как продуктовая боль.
28
29Отдельно: в разметке документов явно заложено **одно окно доков** без floating (`DocumentsDockView` — комментарий в XAML). Это **не** тот же класс задач, что **хром** вокруг редактора; смешивать в одном решении опасно по объёму.
30
31**Верхняя полоса команд** (toolbar: «Открыть решение» и соседние действия) сейчас **длинная и смешанная по смыслу** — та же перегрузка фиксированного хрома, что и низ, только по **горизонтали**: много кнопок в одной линейке без явного разделения по задачам.
32
33## Решение
34
35<a id="adr0012-p1"></a>
361. **Направление продукта:** переносить **вторичный и ситуационный хром** workspace к модели **плавающих / отцепляемых** панелей (в смысле: **не обязаны жить в фиксированной строке `MainGrid`** и конкурировать с высотой редактора). Пользователь может держать полоску у края экрана, на втором мониторе или поверх — в пределах реализуемой модели окна ([см. п. 3](#adr0012-p3)).
37
38<a id="adr0012-p2"></a>
392. **Первые кандидаты на вынос из жёсткой нижней колонки (приоритет):**
40 - **IDE Health** (`IdeHealthStripView` и логически родственное «узкое» состояние), в старом макете застрявшие **над** `BottomPanelView` в одной нижней ячейке.
41 - Далее — **компактные полоски состояния** (в т.ч. отладка из [0011](0011-debug-situational-awareness.md)), чтобы не дублировать их только в нижнем доке.
42
43<a id="adr0012-p3"></a>
443. **Механика (направление, не привязка к одному контролу Avalonia в этом ADR):**
45 - допустимы **внутренние** плавающие слои (overlay, `Popup`, панель с drag в клиентской области) и/или **отдельные окна** (`Window` / tool-window стиль) — выбор по итерации: доступность, мультимонитор, Alt+Tab, сохранение позиций.
46 - **Сохранение геометрии** новых плавающих элементов — в общем потоке настроек workspace ([0010](0010-ui-modes-toml-configuration.md): глобальные метрики и при необходимости расширение), без отдельного «тихого» хранилища только для одной полоски, если можно унифицировать.
47
48<a id="adr0012-p4"></a>
494. **Что остаётся привязанным к доку в v1 направления:** **длинный поток вывода** (терминал, журнал сборки, развёрнутый список locals/stack) — разумный дом для **нижней панели с вкладками**; цель ADR — не уничтожить её, а **не заставлять** короткий статус и полосу IDE Health **обязательно** делить с ней одну ось высоты.
50
51<a id="adr0012-p5"></a>
525. **Документы (редакторы) как floating MDI:** **вне объёма этого ADR**. Отдельное обсуждение/ADR, если появится продуктовая необходимость; текущий комментарий в XAML остаётся фактом до тех пор.
53
54<a id="adr0012-p6"></a>
556. **Связь с режимами UI:** пресеты режимов ([0010](0010-ui-modes-toml-configuration.md)) могут задавать **видимость и слот** плавающего хрома (например в Debug показывать полоску отладки по умолчанию, в Focus — свернуть полосу IDE Health в иконку), не переписывая всю схему `MainGrid` под каждый режим.
56
57<a id="adr0012-p7"></a>
587. **Панели инструментов (toolbars):** верхняя и прочие полосы с кнопками — **тот же класс разгрузки**, что и плавающий хром: **скрываемость** (целиком полосу или по **группам/категориям**), **разбиение по категориям** (например: файл/решение, сборка, отладка, вид, агент — состав групп уточняется по UX), вместо одной длинной смешанной линейки. Видимость групп может пересекаться с режимами UI ([0010](0010-ui-modes-toml-configuration.md)). Пока toolbars живут **внутри `MainWindow`**, для MCP это то же дерево — паритет без расширения контракта; отдельное окно только под toolbar — по тем же правилам, что в разделе «Связь с MCP». **Сколько** команд держать на полосе и **как** обеспечивать discoverability (палитра; ситуационные чеклисты — [0014](0014-situational-checklists.md)) — см. [0013](0013-command-surface-and-discoverability.md), не дублировать здесь.
59
60## Связь с MCP и корнем UI (агент)
61
62**Паритет человек/агент** для автоматизируемого UI ([0002](0002-debug-human-agent-parity.md)) здесь **не оспаривается**: отдельное окно не «освобождает» от доступа агента — наоборот, **требует** довести контракт до нескольких корней, иначе паритет нарушен.
63
64Снимок лэйаута `ide_get_ui_layout` строится по **всем** окнам верхнего уровня процесса: JSON с массивом `windows` (у каждого элемента `role`, `window_type`, `title`, `is_active`, `root` — дерево контролов с bounds относительно этого окна). Второй `TopLevel` под зону Mfd (`MfdHostWindow`, `role` = `mfd_host`) и прочие `Window` входят в ответ. Действия по имени контрола (`ide_set_control_text`, `ide_click_control`, `ide_set_focus`, `ide_get_control_appearance` и т.д.) ищут имя **сначала в главном окне, затем в остальных** — паритет с человеком, который видит оба экрана.
65
66Варианты [п. 3](#adr0012-p3):
67
68- **Плавающий хром внутри клиентской области** (overlay, `Popup`, drag в пределах `MainWindow`) — то же дерево внутри соответствующего `root`.
69- **Вынесение хрома в отдельное окно** — удобно для мультимонитора и Alt+Tab; дерево этого окна попадает в `ide_get_ui_layout` как отдельный элемент `windows[]`. Уточнения контракта при новых типах окон — см. [0008](0008-mcp-contracts-and-testable-infrastructure.md) (контракт, тесты).
70
71Это **не** запрещает отдельные окна в продукте и **не** отменяет [п. 5](#adr0012-p5) (floating MDI доков — отдельная тема).
72
73## Последствия
74
75- Потребуется **миграция лэйаута**: вынести часть содержимого из вложенной сетки row 5 в отдельный слой или окно, не ломая биндинги VM и **единый слой отладки** ([0002](0002-debug-human-agent-parity.md)).
76- При выборе **отдельного окна** для хрома — базовый **мульти-`TopLevel`** в MCP (`ide_get_ui_layout`, поиск контрола по имени по всем окнам) уже есть; новые сценарии могут потребовать уточнения контракта в **scope** поставки вместе с фичей (см. «Связь с MCP», [0008](0008-mcp-contracts-and-testable-infrastructure.md)).
77- Тесты и MCP, которые опираются на **имена регионов** / скриншоты UI, могут потребовать обновления при смене дерева визуального дерева.
78- Документация для пользователя (позже): как «прикрепить обратно», где сохраняется позиция.
79
80## Отклонённые альтернативы (как финальное состояние)
81
82- **Оставить весь хром навсегда в фиксированной нижней сетке** — отклонено как противоречащее цели осведомлённости без постоянной потери высоты редактора ([0011](0011-debug-situational-awareness.md)).
83- **Сразу сделать floating всё, включая доки** — отклонено как слишком дорого и не требуется для решения конфликта «полоска vs лог».
84
85## Обсуждение (открытые вопросы для следующих итераций)
86
87- **Overlay vs отдельное окно** для первой полоски: что даёт меньше сюрпризов на Windows с несколькими мониторами; при отдельном окне дерево уже видно в `ide_get_ui_layout`, остаётся продуктовый выбор и при необходимости точечные доп. поля в контракте.
88- **Один** универсальный «контейнер для плавающих островов» vs отдельные окна на каждый тип хрома.
89- Как не размножить **дубли IDE Health** (полоска в Power и узкий режим) — одна модель данных, разные представления.
90- **Toolbar:** состав **категорий** и что по умолчанию видно в Power / Focus / Debug; не раздувать число отдельных полос без нужды.
View only · write via MCP/CIDE