ADR 0086: Тема UI — канон в TOML, JSON как транспорт MCP (strangler от Themes/*.json)¶
Статус: Proposed
Дата: 2026-04-21
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0028 | settings.toml, путь пользователя |
| 0029 | канон на диске, UI как фасад |
| 0008 | контракты MCP |
| 0079 | оверлеи; ортогонально цветам кистей |
Вне ADR¶
| Документ | Роль |
|---|---|
| MCP-PROTOCOL.md | ide_get_ui_theme, ide_set_ui_theme — JSON |
Контекст¶
Сейчас применение палитры к Application.Resources идёт из JSON: UiThemeApply.Apply(themeJson) — тот же формат, что возвращает и принимает MCP (ide_get_ui_theme / ide_set_ui_theme). Пресеты «светлая / тёмная / …» читают файлы Themes/*.json рядом с exe или встроенный текст (UiThemeApply). Дефолты кистей также живут в App.axaml (CascadeTheme.*).
По продуктовой линии (0028, 0029) человек и репозиторий опираются на TOML как единый канон настроек. Два параллельных «источника правды» для цветов (JSON на диске + TOML для всего остального) ухудшают discoverability и паритет агент ↔ пользователь: агент правит JSON-строкой в туле, человек — не там.
Решение (намерение)¶
- Канон для человека и для репо: описание темы UI (кисти
CascadeTheme.*, совместимые сUiThemeApply.Keys) — прежде всего в пользовательскомsettings.toml(или согласованное имя секции, например[ui_theme]с плоскими или вложенными ключами под те же семантические группы, что в JSON сегодня:main_window,editor,menu, …). Комментарии в файле — часть DX, не отдельный «секретный» JSON.
- JSON не исчезает как контракт MCP:
ide_get_ui_theme/ide_set_ui_themeостаются транспортом для агента: на чтении — сериализация resolved темы (merge дефолтов + TOML + опциональные оверлеи); на записи — применение того же merge-пайплайна, что и при сохранении TOML из UI. Так паритет «агент на равных» сохраняется без обязанности человеку руками редактировать JSON.
- Strangler: файлы
Themes/*.jsonи встроенные пресеты — временные источники дефолтов до переноса пресетов во встроенный TOML/ресурсы или генерации из одной таблицы; новые кисти (например палитра команд) сначала попадают вApp.axamlи в схему TOML, а не только в отдельный JSON без ключа вUiThemeApply.
- Реализация по этапам: (а) парсер секции TOML → тот же внутренний словарь, что сейчас строится из JSON, →
UiThemeApply.Applyбез дублирования логикиSet(res, key, hex); (б) загрузка при старте: mergeApp.axaml→ пресет →settings.toml[ui_theme]; (в) меню «Тема» и MCP вызывают один сервис; (г) документация MCP: «канон на диске — TOML; JSON — снимок».
Последствия¶
- Один взгляд в
settings.toml— видно и AI-режим, и палитру; меньше вопросов «где поменять фон». - MCP-агенты продолжают работать через JSON без смены семантики ответа
ide_get_ui_theme. - Потребуется миграция/совместимость: при наличии только старых
Themes/*.json— поведение как сейчас, пока пользователь не сохранит тему в TOML.
Отклонённые / отложенные альтернативы¶
- Только JSON как канон — противоречит 0029 для пользовательских предпочтений; оставить только как wire-формат.
- Ломать MCP и заменить на TOML-строку в теле тула в одном шаге — высокий налог на агентов и скрипты; не делаем без версии протокола.
Открытые вопросы¶
- Точная форма секции TOML: плоская
ui_theme.editor_backgroundvs вложенные таблицы[ui_theme.editor]/background— согласовать с snake_case и merge из 0028. - Нужен ли явный
ui_theme.preset = "dark"при частичном оверлее полей. - Версионирование ответа
ide_get_ui_theme(если добавится полеcanonical_path: settings.toml) — по необходимости вне этого ADR.