Решили: своя dev-консоль (Трек К) строится на явном реестре команд — модуль сам объявляет свои команды через DevCommandRegistry.Register, никаких атрибутов и сканирования сборок. Экран — ScreenKind.Modal с SuppressScrim = true, автодополнение — ghost-подсказка под полем ввода, а не цикл по Tab; отсюда моноширинный шрифт (Fira Mono, SDF с динамическим атласом).

Почему: атрибутная модель QFSW удобна ровно до первого вопроса «откуда метод возьмёт зависимости» — статический метод с [Command] вынужден сам добывать сервисы, и именно так в проект возвращаются ходы к синглтонам мимо VContainer. Явная регистрация оставляет граф зависимостей видимым и заодно делает реестр тестируемым без сцены (21 EditMode-тест). Цена — команду нужно объявить руками; на четыре десятка команд это дешевле, чем рефлексия со стриппингом на IL2CPP.

Ghost вместо Tab-цикла: цикл заставляет угадывать, сколько раз нажать, а дорисованный остаток виден сразу. Он требует совпадения символ-в-символ с полем ввода — значит моно; на пропорциональном шрифте призрак уезжает вправо на первой букве. SuppressScrim — потому что консоль открывают, чтобы РАЗГЛЯДЫВАТЬ кадр под ней: затемнять его значит работать против собственной задачи.

Грабли:

  • Числа обязаны парситься в CultureInfo.InvariantCulture. Локаль машины русская, десятичный разделитель — запятая, и gm_sep_ally 0.35 без явной культуры отвергался бы как мусор. Синтаксис инструмента не зависит от языка системы; сторожит DevConsoleRegistryTests с подменой культуры на ru-RU.
  • В UITK нет ::before/::after. Уровень строки лога поэтому показывает левая кромка (border-left-color), а не точка-маркер: маркер требовал бы второго элемента в каждой строке, то есть вдвое больше элементов на двухсотстрочный буфер.
  • Шрифты проекта — UnityEngine.TextCore.Text.FontAsset, а не TMPro.TMP_FontAsset. Загрузка существующего SDF как TMP-типа возвращает null, и creationSettings у TextCore-версии недоступен — параметры читаются через faceInfo/atlas*. Создавать новый шрифт: FontAsset.CreateFontAsset + AddObjectToAsset для материала и атласа + SaveAssetIfDirty вместо SaveAssets (последний унёс бы несохранённое у соседних сессий).
  • Дубль имени команды — исключение, а не «последний победил». Тихое замещение выключило бы часть команд молча.

Владелец правды: Assets/_Project/Scripts/Core/DevConsole/ (реестр, аргументы, хвост логов), Assets/_Project/Scripts/UI/DevConsole/DevConsoleScreen.cs (экран), секция .gm-console* в Assets/_Project/UI/Theme/components.uss; тест DevConsoleRegistryTests. Скоуп трека и приёмка — docs/ui-architecture-rework-plan.md §Трек К.