Решили: ключи ui.*, которые код зовёт литералом, держит гейт UiLocalizationCoverageTests — храповик со списком сегодняшних дыр; таблицы он читает с диска, а не через API локализации.

Почему храповик, а не красный тест. Заведение пятидесяти трёх ключей требует открытого редактора (таблицы правятся только редакторным API, правка YAML их рвёт), а гейт нужен раньше: без него пятьдесят четвёртый ключ появится тем же способом, что и предыдущие пятьдесят три. Список известных дыр перечислен поимённо и обязан дойти до нуля; третий тест краснеет, если в списке остался уже заведённый ключ, — иначе через месяц список стал бы отпиской.

Отвергнутая альтернатива — «просто оставить красным до заведения»: красный тест в общем дереве не информация, а шум, и через день его перестают читать все.

Почему с диска, а не через LocalizationEditorSettings. Три причины, и первая главная: гейт проверяет то, что лежит в репозитории и уедет в билд, а не то, что редактор держит в памяти. Вторая: ссылка на пакет ради чтения двух полей тянется в тестовую сборку целиком. Третья обнаружилась на месте — compile-check берёт команды компиляции из артефактов прошлой сборки редактора, поэтому свежая ссылка в .asmdef без запуска Unity не подхватывается вовсе, и проверить тест было бы нечем.

Грабли: аудит насчитал 36 незаведённых ключей, живой замер тем же правилом дал 53. Разница не в методе, а в том, что ручной подсчёт шёл по экранам, а гейт — по всем литералам кода. Число, названное человеком, снова оказалось меньше настоящего.

Владелец правды: Tests/EditMode/UI/UiLocalizationCoverageTests.cs (список дыр — там же), Data/Definitions/ContentKeys.cs (имя таблицы и префикс ключа).