| 1 | # ADR 0029: Конфигурация — **TOML-first** (канон на диске); **целостный** UI настроек — **deferred**; точечный UI — **фасад канона**, не вторая правда |
| 2 | |
| 3 | **Статус:** Accepted · Implemented (TOML-first на диске; целостный UI настроек — deferred; точечный UI — фасад) |
| 4 | **Дата:** 2026-04-08 |
| 5 | **Обновлено:** 2026-04-08 — целостный центр deferred; подраздел «Зачем точечный UI»; перспектива динамического UI от модели; точечный UI = вес кода. Подробности — [§ История](#adr0029-history). |
| 6 | |
| 7 | ## Связанные ADR |
| 8 | |
| 9 | | ADR | Роль | |
| 10 | |-----|------| |
| 11 | | [0028](0028-user-settings-toml-localappdata-and-secrets.md) | путь и формат `settings.toml` | |
| 12 | | [0010](0010-ui-modes-toml-configuration.md) | режимы и merge `workspace.toml` | |
| 13 | | [0015](0015-editor-toml-syntax-highlighting.md) | TOML во встроенном редакторе; внешний редактор с богатым тулингом — осознанный вариант | |
| 14 | | [0013](0013-command-surface-and-discoverability.md) | палитра, хоткеи отдельным файлом | |
| 15 | | [0027](0027-small-team-focus-vs-public-maturity.md) | ось B: отдельное приложение настроек и тяжёлый онбординг — в отложенном бэклоге до триггеров | |
| 16 | | [0026](0026-markdown-preview-surfaces-and-placement.md) | часть ключей в merged `workspace.toml` — канон для команды в репо | |
| 17 | |
| 18 | ## Резюме |
| 19 | |
| 20 | - **TOML-first** конфигурация; целостный UI настроек — deferred. |
| 21 | - Точечный UI — **фасад** над тем же файлом, не второй источник истины. |
| 22 | |
| 23 | --- |
| 24 | ## Контекст |
| 25 | |
| 26 | В продукте одновременно верны три факта: |
| 27 | |
| 28 | 1. **Файлы** — принятый канон хранения: пользовательский `settings.toml`, бандл/репо для режимов и хрома ([0010](0010-ui-modes-toml-configuration.md), [0028](0028-user-settings-toml-localappdata-and-secrets.md)). |
| 29 | 2. **UI** уже меняет часть предпочтений (видимость панелей, режим UI, провайдеры, LSP и т.д.) через модель и сохранение на диск. |
| 30 | 3. В обсуждении периодически всплывает полюс **«только TOML»** vs **«полноценные экраны настроек»** — без отдельного ADR легко смешать ожидания: что «настоящая» правда, обязан ли существовать UI для каждого ключа, допустимо ли жить одним файлом. |
| 31 | |
| 32 | Нужно зафиксировать **одну модель приоритета**: диск и формат файлов **задают канон**; любой UI, который касается настроек, **не** создаёт вторую правду — но **объём** экранного UI (одна кнопка vs целый «центр настроек») — отдельное продуктовое решение, согласованное с [0027](0027-small-team-focus-vs-public-maturity.md). |
| 33 | |
| 34 | --- |
| 35 | |
| 36 | ## Решение |
| 37 | |
| 38 | ### 1. Канон — **текстовые конфиги на диске** (TOML там, где уже принято) |
| 39 | |
| 40 | - Пользовательские предпочтения — **`settings.toml`** и связанные файлы в `%LocalAppData%\CascadeIDE\` ([0028](0028-user-settings-toml-localappdata-and-secrets.md)). |
| 41 | - Раскладка/метрики/пресеты режимов — **`UiModes/`** и merge с **`.cascade/workspace.toml`** ([0010](0010-ui-modes-toml-configuration.md)). |
| 42 | - **Секреты** — в отдельном файле **`ai-keys.toml`**, не в `settings.toml` ([0028](0028-user-settings-toml-localappdata-and-secrets.md)). |
| 43 | |
| 44 | Расширение набора ключей по смыслу — **сначала модель + файл + сериализация**, затем (по необходимости и по оси B) элементы UI. |
| 45 | |
| 46 | ### 2. **Целостный** UI настроек — **deferred** ([0027](0027-small-team-focus-vs-public-maturity.md)) |
| 47 | |
| 48 | Под **целостным** имеется в виду: **единая страница/центр «все настройки»**, отдельное **приложение** настроек, крупные мастера — то, что в [0027](0027-small-team-focus-vs-public-maturity.md) явно отнесено к отложенному бэклогу до триггеров (внешний контрибьютор, RC, явная боль и т.д.). |
| 49 | |
| 50 | - Это **не** запрет на точечные переключатели в основном окне, которые уже есть или появятся по мере фич. |
| 51 | - Это **не** запрет документации «правь `settings.toml`» как основного пути для части аудитории. |
| 52 | |
| 53 | Итого: **не планируем сейчас** вкладываться в полноэкранный discoverability-слой настроек как в отдельный продукт; **планируем** жить на TOML + доке + примерах ([0027](0027-small-team-focus-vs-public-maturity.md)), пока очередь не скажет иначе. |
| 54 | |
| 55 | ### 3. Точечный UI — если есть, то **фасад канона** (не параллельная база) |
| 56 | |
| 57 | Когда элемент управления в приложении меняет предпочтение, сохраняемое в `settings.toml` (или другом каноничном файле): |
| 58 | |
| 59 | - он работает с **той же** моделью (`CascadeIdeSettings` и др.), что и сериализация; |
| 60 | - сохранение — через **`SettingsService.Save`** (и аналоги), **без** «теневого» реестра только в памяти как источника правды; |
| 61 | - **нет** политики «настройки живут только в UI и иногда экспортируются» — см. отклонённые альтернативы. |
| 62 | |
| 63 | Термин **«фасад»** в этом ADR = **архитектурное правило** для уже существующего или точечно добавляемого UI: он отражает файл, а не заменяет его скрытой копией. Это **не** обещание **свернуть** весь конфиг в богатый UI в ближайшем релизе (см. §2). |
| 64 | |
| 65 | #### Зачем точечный UI, если всё можно править в TOML? |
| 66 | |
| 67 | Канон по-прежнему **файл**; точечный UI **не** добавляет вторую правду и **не** обязателен для каждого пользователя. |
| 68 | |
| 69 | - **Трение:** частые действия (видимость панелей, режим UI и т.п.) дешевле кликом в кокпите, чем каждый раз открывать каталог `%LocalAppData%\CascadeIDE\`, искать ключ в snake_case, сохранять файл, при необходимости перезапускать сессию. |
| 70 | - **Редкий разовый заход** — нормальный паттерн: например **один раз** включить внешнего агента (ACP), указать путь к `cursor-agent` — удобно из UI **или** тем же ключом в `settings.toml` по доке; оба входа ведут в один канон ([0016](0016-agent-client-protocol-external-agent.md)). |
| 71 | - Паттерн «в настройки в UI почти не лезу, всё держу в TOML» — **допустим и ожидаем** для части аудитории; паттерн «зашла в UI только на одну опцию» — тоже **не противоречит** TOML-first: это альтернативный **вход**, а не отмена файла. |
| 72 | |
| 73 | ### 4. Режим **TOML-only** — полноправный |
| 74 | |
| 75 | - Правка `settings.toml` (и прочих каноничных файлов) вручную, во **встроенном** редакторе или **внешнем** ([0015](0015-editor-toml-syntax-highlighting.md)), — нормальный рабочий процесс, в том числе для агента и для «диффов в Git» при переносе машин. |
| 76 | - Отсутствие **целостного** UI настроек (§2) **не** считается пробелом само по себе. Отсутствие UI для отдельных ключей — тоже ок; чекбокс на каждое поле модели **не** обязателен ([0027](0027-small-team-focus-vs-public-maturity.md)). |
| 77 | |
| 78 | ### 5. Когда имеет смысл добавлять/расширять **точечный** UI поверх TOML |
| 79 | |
| 80 | - Высокая **частота** переключений, **безопасность** (маскирование секретов), **валидация** на лету — естественные кандидаты на **точечный** контрол (по-прежнему по правилам §3). |
| 81 | - Сложные структуры (списки MCP-серверов JSON и т.п.) — допустимы **как** UI, если снимают ошибки ручного редактирования; сериализованный результат по-прежнему лежит в каноничном поле файла. |
| 82 | - **Целостный** «центр настроек» — только после триггеров [0027](0027-small-team-focus-vs-public-maturity.md) или явной боли, не как дефолтная очередь. |
| 83 | |
| 84 | ### 6. Ограничение по сессии (честность реализации) |
| 85 | |
| 86 | - Загрузка **`SettingsService.Load()`** в типичном сценарии выполняется при старте приложения; **прямое** изменение `settings.toml` на диске во время работы сессии **может** потребовать перезапуска, чтобы все подсистемы подхватили значения (если для конкретного ключа не сделана отдельная перезагрузка). Это **не** аргумент против TOML-first; это повод при необходимости добавить явное «перечитать настройки» или watcher — **отдельной** задачей, не смешивая с вопросом канона. |
| 87 | |
| 88 | --- |
| 89 | |
| 90 | ## Последствия |
| 91 | |
| 92 | - Новые настройки: проектировать **ключ в модели и файле**; **целостный** UI — не обязателен и по умолчанию **не** в очереди; точечный UI — по необходимости. |
| 93 | - Документация для пользователей и агентов: «как поменять X» может начинаться с **пути к файлу и ключа**; экранные формы — опциональное удобство и альтернативный вход, не предпосылка (см. §3, подраздел «Зачем точечный UI»). |
| 94 | - [0027](0027-small-team-focus-vs-public-maturity.md): отложенное **приложение/центр настроек** согласуется с этим ADR: канон на диске уже есть, богатый UI — позже по триггерам. |
| 95 | - Точечный UI **увеличивает объём кода** (привязки, VM, тесты) — добавлять осознанно; альтернатива раздуванию ручных форм при появлении **целостного** центра — см. раздел «Перспектива» ниже. |
| 96 | |
| 97 | --- |
| 98 | |
| 99 | ## Перспектива (не обязательство реализации) |
| 100 | |
| 101 | Когда **целостный** центр настроек перестанет быть deferred по [0027](0027-small-team-focus-vs-public-maturity.md), разумно **рассмотреть** не набор ручных экранов, а **динамическую форму**, построенную из **той же модели**, что и сериализация в `settings.toml` (например рефлексия/генератор по `CascadeIdeSettings` + слой **метаданных**). |
| 102 | |
| 103 | **Плюс:** новое поле в модели и в TOML — при наличии метаданных появляется в UI **без** N новых ручных биндингов; канон один. |
| 104 | |
| 105 | **Не сводится к «только CLR-тип»:** нужны подписи, порядок, группы, скрытие полей, локализация; **секреты** остаются вне этой формы ([0028](0028-user-settings-toml-localappdata-and-secrets.md)); **JSON-блобы** и нестандартные поля — отдельные шаблоны или многострочный редактор. |
| 106 | |
| 107 | Это **не** решение «делаем сейчас» и **не** отменяет §2 (целостный слой по-прежнему не в дефолтной очереди); фиксируется как **направление на будущее**, если триггер вытащит центр настроек из бэклога. |
| 108 | |
| 109 | --- |
| 110 | |
| 111 | ## Отклонённые альтернативы |
| 112 | |
| 113 | - **Только UI, TOML как скрытый экспорт** — отклонено: ломает прозрачность, диффы, работу агента и сценарий «починил в блокноте». |
| 114 | - **Два источника правды** (часть в реестре Windows, часть в TOML) без явного канона — отклонено: дублирование и рассинхрон. |
| 115 | - **Обязательный UI для каждого поля `CascadeIdeSettings`** — отклонено: избыточно для текущей оси B ([0027](0027-small-team-focus-vs-public-maturity.md)); TOML-only остаётся допустимым навсегда для продвинутого пути. |
| 116 | |
| 117 | --- |
| 118 | |
| 119 | ## История изменений |
| 120 | |
| 121 | <a id="adr0029-history"></a> |
| 122 | |
| 123 | | Дата | Изменение | |
| 124 | |------|-----------| |
| 125 | | 2026-04-08 | целостный центр deferred; подраздел «Зачем точечный UI»; перспектива динамического UI от модели; точечный UI = вес кода. | |
| 126 | |