ADR 0010: Данные UI-режимов (Focus / Balanced / …) в TOML¶
Статус: Accepted · Implemented
Дата: 2026-04-02
Обновлено: 2026-04-25 — в [capabilities] ключи IDE Health: ide_health_*. Подробности — § История.
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0003 | Отдельный UI-режим Debug (не кокпит Power) |
| 0006 | Слои, вертикальные срезы и роль MainWindowViewModel |
| 0017 | мультиоконность и топология |
| 0022 | канон имён и эволюция для IDE Health (пересечение с таблицей ide_health_* ниже). |
Вне ADR¶
| Документ | Роль |
|---|---|
attention-zone-panel-playbook-v1.md |
зона ↔ панель ↔ топология |
Снимок реализации¶
| Элемент | Значение |
|---|---|
| — | загрузчик TOML, UiModeCatalog, capabilities, bundle UiModes/ |
| — | override и docs/ui-ux — по мере нужды |
Резюме¶
- Режимы UI (Focus/Balanced/…) — данные в TOML (
UiModes/), не только константы в C#. - Bundle + merge с
.cascade/workspace.toml; override без обратной записи динамики в шип. [capabilities]и ключиide_health_*— контур IDE Health в том же каталоге режимов.- Tomlyn, snake_case; JSON не дублируем как второй канон конфигов.
Контекст¶
Сейчас спеки режимов (видимость панелей, группы редактора, слот темы, ширина развёрнутого чата и т.д.) зашиты в C# (UiModeLayoutRegistry, связанные константы). Глобальные размеры хрома (сплиттеры, минимумы строк и пр.) собраны в UiWorkspaceLayoutDimensions и применяются через UiWorkspaceLayout.
Потребность: менять раскладку режимов без пересборки (дизайн, пресеты, эксперименты), в одном стиле с уже принятым в продукте хранением настроек в settings.toml (Tomlyn уже в зависимостях).
JSON для этого не предлагается как основной формат: пользовательские настройки уже TOML; дублировать второй «официальный» текстовый формат для конфигов режимов нежелательно.
Решение¶
1. Источник данных режимов — несколько файлов TOML: индекс задаёт порядок и полный список id режимов в меню (включая встроенные и дополнительные, см. ниже) + отдельный файл на режим (Focus.toml, Balanced.toml, …; шипнутый набор дублирует дефолты из UiModeLayoutRegistry / DefaultsForFamily), чтобы диффы и смысл «один режим — один файл» были очевидны. Если файла режима нет — загрузчик берёт те же дефолты из кода. Версионируем с приложением (как темы: копия рядом с exe или встроенный ресурс + fallback на диск). Расположение шипнутого набора — подкаталог UiModes/ рядом с exe (тот же паттерн, что Themes/: копия в вывод сборки рядом с exe). Отдельный путь в настройках пользователя — возможное расширение позже, в первой версии не обязательно.
2. Глобальные метрики хрома (ширина дерева по умолчанию, толщина сплиттеров, минимумы высот нижней зоны, политика «свёрнуто» и т.п.) — один раз в отдельном файле workspace.toml рядом с индексом и режимами (не копировать в каждый Debug.toml).
3. Схема окна (инварианты): число колонок MainGrid, смысл колонок, привязка контролов к колонкам — намеренно остаются в коде/XAML в рамках этого ADR. TOML описывает режимы поверх этого каркаса (видимость, метрики, слот темы и т.д.), а не альтернативную разметку окна. Возможный вынос схемы окна в данные — отдельное ADR, если появится продуктовая необходимость (несколько каркасов, плагины и т.п.).
4. Загрузка при старте: десериализация в модель, совместимую по смыслу с UiModeLayoutSpec (+ числа вроде ширины правой колонки в развёрнутом виде для режима, если остаётся в данных).
5. Fallback: если файл отсутствует, битый или не прошёл валидацию — встроенные значения по умолчанию из кода, без падения IDE. См. ниже про роль этих дефолтов.
6. Версия схемы: поле schema_version — только в корне файла индекса (первый читаемый файл набора). Оно задаёт версию всего бандла UiModes/ — индекс, workspace.toml, per-mode файлы. В workspace.toml отдельного schema_version нет (избегаем двух чисел и рассинхрона). Миграции формата — по одному номеру из индекса.
7. Валидация при загрузке (минимум): неизвестный theme_slot → fallback; в шипнутом наборе отсутствует спека для обязательного id → предупреждение + встроенная спека из кода. Минимальный набор обязательных id (который продукт не имеет права «потерять» в данных) задаётся в коде — сейчас это совпадает с UiModeLayoutRegistry.OrderedModeIds. Индекс может перечислять больше id, чем этот минимум (дополнительные пользовательские или пресетные режимы). См. ниже про наследование и отдельный пункт меню без замены Debug.
8. Capabilities — тип UiModeCapabilities (Features/UiChrome/UiModeCapabilities.cs). В UiModes/<id>.toml ключи предметные (что в интерфейсе), в snake_case; десериализация через CascadeTomlSerializer (имена свойств модели в PascalCase → snake_case). Мердж: явное значение → при inherits — от родителя → иначе DefaultsForFamily. API: GetCapabilities, GetWindowTitleOverride.
| Ключ TOML | Смысл |
|---|---|
active_task_strip |
Полоса активной задачи / Task Cockpit под тулбаром |
main_window_title |
Полный заголовок главного окна |
quick_actions |
Быстрые действия у задачи |
agent_operations_panel |
Блок операций агента в чате (Balanced) |
agent_trace |
Панель trace агента (Power) |
autonomous_agent_telemetry |
Кокпит Power: явный доступ к выводу (терминал и подсказки); не канал IDE Health |
ide_health_on_terminal_tab |
Дубль IDE Health на вкладке «Терминал» (Power) |
ide_health_main_column_span |
Column span области IDE Health в основной сетке (Power) |
ide_health_strip |
Показывать полосу IDE Health под редактором |
ide_health_surface |
bottom_strip или dedicated_page — слой представления IDE Health |
instrumentation_tabs |
Вкладки событий/тестов/отладки в нижнем доке |
hypotheses_tab |
Вкладка «Гипотезы» |
risk_summary_card / result_summary_card |
Карточки риска и результата в чате |
Слои модели (шпаргалка для автора UiModes/*.toml)¶
Чтобы не путать id режима, раскладку, семью и capabilities, удобно держать в голове такие уровни:
| Слой | Что это | Откуда берётся |
|---|---|---|
| Id режима | Стабильная строка (пункт меню, ключ в каталоге, имя файла Id.toml) |
index.toml → modes, плюс таблица встроенных id в коде для fallback |
| Раскладка | Видимость панелей, число групп редактора, слот темы, флаги вроде «выбирать вкладку терминала» | База: UiModeLayoutRegistry для встроенных id; мердж с полями текущего *.toml; при inherits — база = разрешённый родитель |
workspace.toml |
Общие числа хрома (сплиттеры, ширины чата по правилу Power / AgentChat / остальные, минимумы строк и т.д.) | Один файл на бандл; без копирования в каждый режим |
family |
Продуктовая роль: Focus, Balanced, Power, AgentChat, Debug — влияет на дефолты capabilities и ветки в коде (UiModeFamily) |
Порядок: явный family в файле режима → при inherits — семья разрешённого родителя → для встроенных id — таблица в коде по id → иначе Balanced |
| Capabilities | Что показывать в интерфейсе (гипотезы, quick actions, хром кокпита Power и т.д.) | База: при inherits — capabilities разрешённого родителя; без inherits — DefaultsForFamily(family). Поверх — явные ключи в *.toml |
Узкий ключ в том же workspace.toml про где монтировать превью Markdown (не путать с будущей общей топологией нескольких TopLevel) — 0026.
Конечный пользователь IDE в комбо «режим интерфейса» видит в основном id пресета; оси family / capabilities ему не обязательны, пока в UI нет отдельных переключателей под них.
Топология презентации зон (будущее расширение)¶
Сейчас в коде одна топология — MainWindowDockedGrid (AttentionLayoutSurfaceKind, одно главное окно, колонки MainGrid). Когда в продукте появятся альтернативы (несколько TopLevel, сценарии 0017), логично связывать выбранную топологию с merge слоёв 0010 и отдельным учётом персональной раскладки по мониторам (см. следующий абзац). Без обратной записи динамического ресайза окон в шипнутые файлы (см. подраздел про рантайм ниже).
Не смешивать с картой панель → зона (attention_zone_panels / AttentionZonePanelRuntime): там семантика «какая панель в какой зоне», здесь — в какой геометрии (одно окно vs несколько) воплощены регионы. Подробнее: attention-zone-panel-playbook-v1.md.
Поля presentation / zone_screen_layout (корень settings.toml) и токены грамматики в секции [presentation_grammar] (screen_markers, screen_separator, zone_separator, литералы якорей pfd_zone_identifier / forward_zone_identifier / mfd_zone_identifier) — строка раскладки по физическим дисплеям из 0017 («Несколько мониторов»), например (PFD+Forward) (MFD) или (P+F) (M) при коротких идентификаторах в TOML (таблица); между якорями внутри одной пары скобок допускается только литерал zone_separator (Z, по умолчанию +); при Z = "|" в строке — только |, без подстановки «второго стиля». EBNF — 0017. Где хранить: прежде всего settings.toml пользователя (0028). Репозиторный .cascade/workspace.toml (0021 §2.1) — для командных соглашений по панелям и зонам, не для обязательной для всех схемы мониторов; при merge пользовательские значения presentation и токенов перекрывают одноимённые в бандле/репо. Альтернативное имя ключа — zone_screen_layout; в одном конфиге задаётся одно из двух. Перечисление значений AttentionLayoutSurfaceKind и валидация — в реализации; отдельный ADR под схему TOML не требуется, пока объём правил укладывается в этот подпункт.
inherits = "BaseId" — один родитель: наследуется весь уже разрешённый режим (раскладка, capabilities, ширина чата, полоса задачи, заголовок окна — по правилам мержа в коде). В дочернем файле задаются только отличия от родителя. Отдельная секция вроде [inherits] со списком «какие поля наследовать» не используется: при такой модели список дельт в файле и так короче, чем перечисление срезов.
Порядок разрешения family (формально)¶
- Если в
Id.tomlзаданоfamily = "…"(регистр не важен) — используется оно. - Иначе, если задано
inherits— берётсяfamilyуже разрешённого родителя (рекурсивно). - Иначе — для известных встроенных id (
Focus,Balanced, …) —BuiltinFamily(id)в коде. - Иначе — Balanced (неизвестный id без явной семьи).
Примеры: inherits и опционально family¶
Дополнительный режим как Debug, но с полосой задачи и своим заголовком — без дублирования всей спеки:
index.toml (фрагмент; полный индекс см. шипнутый UiModes/index.toml):
schema_version = 1
modes = [ "Focus", "Balanced", "Power", "AgentChat", "Debug", "MySuperDebug" ]
MySuperDebug.toml:
inherits = "Debug"
active_task_strip = true
main_window_title = "CascadeIDE — мой отладочный пресет"
Поле family не нужно: семья остаётся Debug (как у разрешённого родителя), поведение гипотез/инструментирования — как у отладки.
Цепочка из двух уровней: каждый файл задаёт только дельту; корень цепочки — встроенный id с полной спекой (или другой уже разрешённый режим).
# DeepWork.toml — ответвление от Focus
inherits = "Focus"
editor_group_count = 1
main_window_title = "CascadeIDE — Deep work"
# MyDeep.toml — ответвление от DeepWork
inherits = "DeepWork"
chat_expanded_width_pixels = 400
Оба новых id должны быть перечислены в modes в index.toml.
Редкий случай: inherits от Debug и явный family (ось UiModeFamily отличается от родителя; см. пояснение после примера):
inherits = "Debug"
family = "Balanced"
Раскладка — мердж спеки Debug с полями файла. Ось family для кода (UiModeFamily, предикаты вроде IsDebugFamily) становится Balanced. Важно: при inherits базовый слой capabilities в загрузчике берётся от разрешённого родителя (parentResolved.Capabilities), а не от DefaultsForFamily(family) — то есть флаги интерфейса по умолчанию остаются «как у Debug», пока их не переопределить ключами в том же *.toml. Если когда-нибудь понадобится стартовать capabilities от DefaultsForFamily выбранной семьи при наследовании раскладки — это отдельное изменение контракта загрузчика.
См. также подраздел inherits и family: это не одно и то же ниже — там про помодульный мердж и ширину чата.
Динамический ресайз после старта и TOML (источник правды)¶
Файлы UiModes/*.toml, workspace.toml и индекс набора режимов — пресет: они задают раскладку и метрики на момент загрузки конфигурации (старт приложения и, если когда-нибудь появится, явная команда «перечитать конфиг»). Это не живой журнал геометрии окна.
Перетаскивание сплиттеров, изменение ширин/высот панелей и любой динамический ресайз хрома после запуска — рантайм-состояние в памяти. Оно ни при каком сценарии по умолчанию не записывается обратно в шипнутые рядом с exe UiModes/*.toml и workspace.toml: ни при каждом движении сплиттера, ни при смене режима, ни при выходе из IDE. Так редактор и диффы по репозиторию остаются источником дизайна режима; случайный дрейф окна пользователя не портит файлы пресета.
Если позже понадобится сохранять геометрию между сеансами, это оформляется отдельным каналом (например поля в settings.toml, отдельный пользовательский override в %LocalAppData% — см. «Границы» ниже), а не обратной записью в дистрибутивные TOML режимов.
MCP (ide_set_panel_size и аналоги) и снимки UI для тестов/агента меняют текущую раскладку в процессе работы; контракт тот же: не считать, что вызов перезаписывает TOML на диске, пока это явно не задокументировано как отдельная операция «экспорт пресета в файл».
Один и тот же Debug vs отдельный MySuperDebug (наследование)¶
- Правка
Debug.tomlили override наDebugменяет сам режимDebugдля того набора файлов, к которому относится конфиг: штатный Debug в том виде, как в дистрибутиве, рядом не живёт — это ожидаемо, если цель именно «переопределить Debug». Для сценария «и стоковый Debug доступен, и мой вариант рядом» нужны два разных id. - Дополнительный режим с новым id (например
MySuperDebug), по смыслу близкий кDebug, но с другой раскладкой под контекст: объявляется в индексе (отдельная строка в меню, своё сохранённое значение в настройках), отдельный файлMySuperDebug.toml. Чтобы не дублировать всю спеку, в файле режима поддерживается наследование от базового id, например полеinherits = "Debug"(имя уточняется при реализации): загрузчик мержит разрешённую спекуDebugс переопределениями изMySuperDebug.toml. Так не нужно копипастить десятки полей и не нужно менять C# только ради нового id — достаточно индекса + файла режима (и при необходимости общих правил для «неизвестных» id в коде: разрешённые базы, fallback). - Подпись в UI для id (отображаемое имя вместо сырого
MySuperDebug) — при необходимости отдельные поля в индексе/TOML или локализация; не смешивать с обязательным минимумом id из п. 7.
Семантика для кода: «family» и устаревшие флаги Is*Mode¶
Контекст (проблема до одной оси): проверки вроде «это Debug для гипотез?» через UiMode == "Debug" или булевы IsDebugMode ломаются для производного id (MySuperDebug): строка id другая, а продуктовый смысл «семья отладки» тот же.
Текущий код уже переведён на UiModeFamily и предикаты расширения — см. подраздел «Реализация в коде» ниже. Таблица вариантов и family в TOML — про данные после загрузчика; там family после мержа должна попадать в ту же ось, что и сегодняшний UiModeFamily.
Дополнительно, NormalizeUiMode сейчас сводит неизвестный режим к Balanced. Режимы с новыми id из индекса должны сохраняться (после проверки «id есть в загруженном списке»), иначе пользовательский MySuperDebug превратится в Balanced без предупреждения.
История обсуждения альтернатив (зафиксировано для контекста; реализован подход A):
| Подход | Суть | Плюсы | Минусы |
|---|---|---|---|
A. Семейство (family) в данных |
После мержа в результирующей модели есть поле family (enum или строка: debug, power, …). В TOML — опционально family = "debug"; если не задано — наследуется от базы при inherits (у корня цепочки — как у встроенного id). Код переводит IsDebugMode на family == debug (или переименование в IsDebugFamily). |
Явная семантика; MySuperDebug без копипаста получает «debug» через наследование; проще тестировать. |
Нужна миграция существующих проверок по строке id; перечень family всё равно конечный в коде. |
B. Только цепочка inherits |
«Отладочность» выводится обходом inherits до известного встроенного id (ResolvesToBuiltIn("Debug")). |
Не дублировать поле family в TOML. |
Сложнее рассуждать и отлаживать; глубина/циклы; неочевидно, когда оборвать цепочку для UX. |
C. Явный family в каждом TOML без автонаследования |
Каждый режим, включая производные, пишет family руками. |
Максимально явно. | Дублирование; легко ошибиться и задать MySuperDebug без family. |
| D. Только точное совпадение id | IsDebugMode остаётся == "Debug"; производные режимы не считаются Debug для гипотез и т.д. |
Минимум кода. | Противоречит сценарию «MySuperDebug как Debug»; пользователь вводит в заблуждение. |
Реализовано: подход A — в результирующей модели после загрузки есть UiModeFamily; в TOML опционально family; проверки в VM/вью — по семье и capabilities, не по сырой строке id там, где нужна продуктовая роль.
inherits и family: это не одно и то же (разделение ответственности)¶
inheritsзадаёт разрешённого родителя: от него берутсяUiModeLayoutSpecи базовый слойUiModeCapabilities(не только «каркас»); дочерний файл накладывает помодульные переопределения. Дляchat_expanded_width_pixels: явное значение в файле → иначе у родителя поinherits→ иначе у корневого режима —workspace.toml(черезUiWorkspaceLayoutRuntimeMetrics) и правило Power / AgentChat / остальные.familyотвечает за продуктовую роль в коде: какие вкладки/инструменты/политики считать «режимом отладки», «power» и т.д. Это другое измерение, не дублирениеinherits: теоретически можно представить раскладку, унаследованную отDebug, но явно переопределённую семантику (редкий кейс).
Чтобы не казалось, что в TOML две ручки про одно, правило умолчаний может быть таким:
- Для встроенных id
familyзадаётся таблицей в коде (тот же смысл, что сейчас заложен в id). - Для режима с
inheritsполеfamilyв TOML не обязательно: по умолчаниюfamily= семья разрешённого родителя (напримерMySuperDebug→inherits = "Debug"→ Debug). Тогда в файле достаточноinherits, без отдельной строкиfamily, пока семантика совпадает с базой. - Явный
familyв TOML — когда нужно перебить вычисленную семью дляUiModeFamily(редко; см. ограничение про базу capabilities приinheritsв примере выше).
Так inherits не «задаёт family» сам по себе — он задаёт цепочку родителя для мержа раскладки и capabilities; family либо задаётся явно, либо наследуется от родителя, либо берётся из таблицы встроенных id, либо Balanced для неизвестного id. Разделение: мердж данных по файлу/родителю vs ось семьи для кода.
Связанные места (не исчерпывающе): MainWindowViewModel.Presentation (UiModeFamily, инструментация), UiChromeViewModel.NormalizeUiMode, bloom по строке режима, GetChatPanelExpandedWidthPixels, MCP-обработчики с особыми правилами для режима отладки.
Не плодить Is*Mode в VM¶
Набор булевых IsFocusMode, IsPowerMode, IsDebugMode и т.д. был типичным запахом. В коде они сняты в пользу UiModeFamily и предикатов (см. «Реализация в коде»). После загрузчика TOML предпочтительно иметь один вычисляемый контекст после загрузки: enum UiModeFamily и/или компактный объект capabilities (что показывать: гипотезы, элементы кокпита Power, …), заполняемый из резолвнутой спеки и правил по умолчанию. Не возвращать очередной IsNewThingMode и не плодить сравнения с сырой строкой id там, где нужна семья.
Реализация в коде (зафиксировано до загрузчика TOML)¶
Это не отдельный документ: договорённости по оси режима фиксируются здесь, в ADR про режимы и TOML, чтобы и люди, и агент не искали разрозненные заметки.
| Элемент | Назначение |
|---|---|
UiModeFamily + UiModeFamilyResolver.FromNormalizedMode |
Одна ось после NormalizeUiMode(UiMode); производные id маппятся в семью так же, как сегодня встроенные строки. |
UiModeFamilyExtensions (IsFocusFamily, IsBalancedFamily, IsPowerFamily, IsAgentChatFamily, IsDebugFamily) |
Симметричные предикаты вместо размножения == UiModeFamily.* по VM. |
| Доменное имя там, где не хватает «голого» enum | Например приватное AutonomousCockpitActive в автономной сессии: смысл «кокпит автономного агента», внутри — тот же IsPowerFamily(). |
| XAML | Привязки к UiModeFamily через конвертеры UiModeFamilyEq / UiModeFamilyNe (параметр — имя члена enum). |
| После TOML | Загрузчик мержит спеку, family → UiModeFamily, UiModeCapabilities (и опционально main_window_title), без отката к набору Is*Mode. |
Fallback и встроенные дефолты (код vs TOML)¶
Встроенный fallback не претендует быть «главным» источником красивой раскладки: его задача — предсказуемо поднять IDE, если данных на диске нет или они битые. Нормальный путь — шипнутые TOML рядом с exe; тогда fallback срабатывает редко (чистая установка, сломанный каталог, разработка без копии файлов).
Качество текущих констант в коде (в том числе режимы вокруг Power) может быть средним — это отдельная ветка работы: доводка дефолтов, выравнивание с дизайном, возможно приближение built-in к содержимому шипнутых файлов. Это не блокирует механику «TOML + fallback из кода»: сначала надёжная загрузка и тесты, параллельно или позже — полировка встроенных значений (или генерация одного из другого в сборке — вне скоупа этого ADR, пока не понадобится).
Видимость панелей vs «0 px»¶
В конфиге режима и в смысле продукта первична семантика видимости (visible / hidden для панели; при необходимости позже — отдельное состояние вроде «свёрнуто с полоской», если появится политика не нулевой полоски). «Скрыто» не должно задаваться главным образом как width = 0 в режиме TOML: нулевая ширина колонки и скрытый сплиттер — производное от правил видимости и глобальных метрик из workspace.toml (и кода инвариантов). Так одна и та же идея покрывает любую сворачиваемую колонку/зону, не только чат.
Границы (что точно не входит в этот ADR)¶
- Схема окна (каркас MainGrid, новые колонки/зоны из данных) — см. п. 3 решения; не входит.
- Подсветка синтаксиса
.tomlв редакторе — отдельно (см. EDITOR-LANGUAGES.md: грамматики TOML в бандле нет); на загрузку конфига не влияет. - Пользовательский override в
%LocalAppData%\…поверх шипнутого файла — возможное расширение после базовой схемы, не обязательно в первом коммите.
Последствия¶
- Плюсы: единый человекочитаемый формат с настройками; правки режимов без компилятора; проще ревью диффов раскладки; дополнительные режимы с наследованием без дублирования спеки и без обязательной правки C# под каждый новый id.
- Минусы: парсинг, ошибки на диске, тесты на fallback; документация полей TOML для контрибьюторов; загрузчик с мержем
inherits; комбо режимов в UI — от загруженного индекса (код хранит минимум для валидации и fallback);familyи capabilities должны оставаться согласованы сUiModeFamilyиUiModeCapabilities.DefaultsForFamily;NormalizeUiModeсохраняет пользовательские id из индекса; в коде VM булевыеIs*Modeсняты (см. «Реализация в коде»). Основныеdocs/ui-uxприведены кUiModeFamily/ capabilities (обзор:docs/ui-ux/ui-modes-overview-v1.md). - Связь с MCP: поведение
ide_set_panel_sizeи снимков UI не должно ломаться; контракт с диском — см. подраздел «Динамический ресайз после старта и TOML» выше (рантайм и MCP не перезаписываютUiModes/*.toml/workspace.tomlпо умолчанию).
Документация (в scope)¶
Навигационные и UX-доки должны описывать UiModeFamily, capabilities и при необходимости TOML, а не устаревшие булевы Is*Mode. Обзор для читателя: docs/ui-ux/ui-modes-overview-v1.md; макет окна и карта концепт→код — docs/ui-ux/cascade-ide-ui-layout-v1.md, docs/ui-ux/concept-to-implementation-map-v1.md. Исторические ADR (например сравнение подходов A–D) могут упоминать старые имена в прошедшем времени — это норма.
Отклонённые альтернативы¶
- Только JSON — расходится с
settings.tomlи выбранным стеком Tomlyn для пользовательских конфигов. - Только код — оставляет текущее состояние; отклоняется как основной путь из-за цели «файл режима» без релиза.
Следующий шаг (опционально)¶
Пользовательский override каталога UiModes/ из %LocalAppData% при продуктовой необходимости; точечные правки docs/ui-ux при изменении поведения режимов в коде.
История изменений¶
| Дата | Изменение |
|---|---|
| 2026-04-08 | намерение задать топологию презентации зон в TOML после появления альтернатив одному MainGrid (0017); см. подраздел ниже. |
| 2026-04-11 | presentation / zone_screen_layout: прежде всего settings.toml, не командный репо — 0017, п. 4; токены грамматики — секция [presentation_grammar] (без отдельных pfd_zone_alias — короткие имена через pfd_zone_identifier и т.д.); screen_markers / screen_separator / zone_separator, EBNF — 0017. |
| 2026-04-11 | якоря adr0010-p1…p8 в разделе «Решение» и ссылки на п. 3, п. 7; соглашение — README ADR. |
| 2026-04-25 | в [capabilities] ключи контура IDE Health в TOML: ide_health_* (свойства UiModeCapabilities — IdeHealth*). |