| 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> |
| 36 | 1. **Направление продукта:** переносить **вторичный и ситуационный хром** workspace к модели **плавающих / отцепляемых** панелей (в смысле: **не обязаны жить в фиксированной строке `MainGrid`** и конкурировать с высотой редактора). Пользователь может держать полоску у края экрана, на втором мониторе или поверх — в пределах реализуемой модели окна ([см. п. 3](#adr0012-p3)). |
| 37 | |
| 38 | <a id="adr0012-p2"></a> |
| 39 | 2. **Первые кандидаты на вынос из жёсткой нижней колонки (приоритет):** |
| 40 | - **IDE Health** (`IdeHealthStripView` и логически родственное «узкое» состояние), в старом макете застрявшие **над** `BottomPanelView` в одной нижней ячейке. |
| 41 | - Далее — **компактные полоски состояния** (в т.ч. отладка из [0011](0011-debug-situational-awareness.md)), чтобы не дублировать их только в нижнем доке. |
| 42 | |
| 43 | <a id="adr0012-p3"></a> |
| 44 | 3. **Механика (направление, не привязка к одному контролу 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> |
| 49 | 4. **Что остаётся привязанным к доку в v1 направления:** **длинный поток вывода** (терминал, журнал сборки, развёрнутый список locals/stack) — разумный дом для **нижней панели с вкладками**; цель ADR — не уничтожить её, а **не заставлять** короткий статус и полосу IDE Health **обязательно** делить с ней одну ось высоты. |
| 50 | |
| 51 | <a id="adr0012-p5"></a> |
| 52 | 5. **Документы (редакторы) как floating MDI:** **вне объёма этого ADR**. Отдельное обсуждение/ADR, если появится продуктовая необходимость; текущий комментарий в XAML остаётся фактом до тех пор. |
| 53 | |
| 54 | <a id="adr0012-p6"></a> |
| 55 | 6. **Связь с режимами UI:** пресеты режимов ([0010](0010-ui-modes-toml-configuration.md)) могут задавать **видимость и слот** плавающего хрома (например в Debug показывать полоску отладки по умолчанию, в Focus — свернуть полосу IDE Health в иконку), не переписывая всю схему `MainGrid` под каждый режим. |
| 56 | |
| 57 | <a id="adr0012-p7"></a> |
| 58 | 7. **Панели инструментов (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; не раздувать число отдельных полос без нужды. |