История изменений
Что менялось в инструментарии xbsl от версии к версии, с разбивкой по дням.
Заметные изменения инструментария xbsl – движка на Python, на котором работают линтер, серверы
LSP и MCP, индекс документации и создание метаданных. Записи сгруппированы по дням; версии,
вышедшие в этот день, перечислены в заголовке. Формат основан на
Keep a Changelog, проект следует
семантическому версионированию. У расширения VS Code своя история в
editors/vscode/CHANGELOG.ru.md.
Записи используют русские написания имён метаданных платформы (Наименование, Код, Реквизиты);
английские написания – в английской истории.
Каждая запись заканчивается ссылкой на пул-реквест, из которого она пришла –
([#12](https://github.com/keyfire/xbsl/pull/12)). Поэтому изменения и приходят пул-реквестами:
запись без такой ссылки не дописана – от строки журнала читателю некуда пойти за кодом и за
причиной правки. Внутренним идентификаторам платформы в записи тоже не место: писать надо о
поведении, а не о том, какое имя класса с чем сверялось.
08.10.2026 – 1.1.0
Добавлено
- Новое правило проверяет класс
\pв литералах клиентского Образец.code/client-pattern-unicode-classвыключено по умолчанию. Включайте его после проверки, что целевой клиент не поддерживает этот класс. Серверные и динамические шаблоны пропускаются. (#174)
Исправлено
- Тестовые наборы работают с общим хранилищем данных платформы. Пять наборов копируют логические JSON вместо физических файлов отдельных версий. Существующие проверки сохранены. (#174)
03.10.2026 – 1.0.0
Добавлено
-
Данные платформы могут хранить одинаковое содержимое разных версий в одном месте.
data-packсоздает общий каталог,data-exportвозвращает прежнюю структуру,data-verifyпроверяет содержимое.data-pruneпоказывает неиспользуемые файлы и удаляет их только с--apply. (#173) -
Стандартные методы получили описания в автодополнении. При выборе пункта загружаются сигнатуры, краткое описание и параметры объявляющего типа. (#173)
-
xbsl/reindexProjectотвечает после построения свежего индекса и проверки проекта. Стандартный прогресс LSP показывает этап, обработанные и оставшиеся файлы или правила, текущее правило. Редактор может показывать прошедшее время. Итоговые 100% следуют после публикации диагностик. (#173)
Изменено
- Загрузчики и экстракторы поддерживают общий каталог. Представления JSON, поиск справки и пути картинок сохраняют прежний смысл. Старый формат по-прежнему читается. (#173)
Удалено
- Старые команды
xbsllintи Python-импорт удалены. Используйтеxbslи его команды серверов. (#173)
Исправлено
- Автодополнение распознает числовые выражения в скобках и условные переменные. После точки предлагаются методы типа результата. (#173)
- Константы модуля показывают тип и комментарий при наведении. Локальные имена и ссылки с квалификатором сохраняют свой смысл. (#173)
01.10.2026 – 0.127.0, 0.128.0, 0.128.1
Добавлено
- Панель свойств предлагает только значения, которые допускает режим совместимости
проекта.
xbsl extractдатирует значения перечислений, которые платформа ограничивает режимом, панель читает режим так же, как сборка, а MCPmetadata_schemaотдает ограничения вenum_modes. (#171) localization-infoназывает каждый язык-кандидат и по-английски. Полеnames_enстоит рядом сnamesв команде, в MCPmeta_localization_infoи в сервере языка, так что клиент может назвать язык на языке своего интерфейса. (#170)
Изменено
translateи панель свойств пишут значение так, как его пишет его перечисление.xbsl extractкладет английское написание каждого значения вmetamodel.json, и оба берут его оттуда, а не угадывают по таблицам интерфейса. ПоэтомуВидСравненияпредиката процесса интеграции теперьEquals, а значение, которого не было в плоской таблице, получает написание. (#171)translateсохраняет префикс имени устаревшего элемента. Паре, которая не начинается сDeprecated, переводчик ставит его спереди, иnaming/presentationузнает элемент в английском дереве и требует там(not used). Слово, которое лишь начинается как префикс, им не считается. (#170)
Исправлено
xbsl extractверно читает названия обработчиков событий. Раньше большая часть пар сдвигалась на соседнее слово, и словарь компилятора предлагал неверное английское имя. Теперь экстрактор берет оба написания из пары, объявленной платформой. (#172)xbsl extractберет в словарь компилятора пары, которые класс пишет русским вперед. Такая пара только проверяла соседа слева, а теперь стала и источником с тем же отсевом, что у остальных: кодНПпараметра прописи числа получает свою паруSN. Подпись вродеHalf year– не имя, и в словарь она не идет. (#171)- Два рабочих дерева одного проекта в одном запуске больше не сливаются в один проект. Каждое
общее имя давало находку, а список принятых одного дерева судил другое. Теперь у каждого корня
своя проверка и запись в
summary.projects, аlint_pathsсcompactне длиннее 12 000 знаков. (#171) from xbsl import scaffoldработает первым импортом процесса. Раньше он падал на циклическом импорте: движок при загрузке подгружает правила, а одно из правил берет имя из модуля создания метаданных. Так же падалimport xbsl.resource_usage. (#170)xbsl extractдает значения свойств, типизированных скомпилированными перечислениями.Важностькоманды,ДниНеделииМесяцырасписания,Периодичностьнабора констант и еще десять свойств были блоками без значений, а у значений не было английского написания. Теперь их предлагают схема метаданных и панель свойств, в английском проекте – так, как значение пишет его собственное перечисление, аtranslateтоже пишет их по-английски. (#170)xbsl extractсверяет названия языков с таблицей языков. Перечисления языков и читатель описания проекта ставят название одного языка рядом с названием другого, и словарь компилятора так их и сводил, из-за чего у названия русского языка пропало общее написание. Пару, которая противоречит таблице, экстрактор теперь отбрасывает. (#170)xbsl extractбольше не принимает слово перед русским названием за его английское написание. Класс, который локализует слово сначала по-русски, а следом по-английски, оставлял слева от слова имя константы перечисления или английское имя предыдущего параметра. Проверка читает вызовы класса, а не форму слова, поэтому аббревиатуры, объявленные платформой, остаются. (#170)
30.09.2026 – 0.125.0, 0.126.0
Добавлено
new-object --periodicityсоздает периодический набор констант. Периодичность принимается на любом языке:День,Месяц,КварталилиГод. У такого набора рядом с записью есть список, поэтому--presentationпишет заголовок списка, а--record-presentation– заголовок записи, и новый набор проходитnaming/presentation. В MCPmeta_new_objectи в сервере языка параметр называетсяperiodicity. (#166)
Изменено
naming/presentationждет от английского проекта пометку(not used). С нее начинаются представление и заголовки устаревшего элемента, а пометку другого языка правило не засчитывает.translateставит(not used)сам, если пара словаря ее опускает. (#169)- Инструменты локализации знают все языки платформы.
localization-infoиadd-localizationвместе с двойниками в MCP и сервере языка берут языки из данных с режимом совместимости, который нужен каждому, поэтому к русскому и английскому добавились китайский, вьетнамский и таджикский. ЗначениеЯзыкиЛокализации, которого данные не знают, названо в заметках. (#169) yaml/duplicate-subtreeбольше не сравнивает переводы одного словаря локализованных строк. Два языка одного словаря повторяют друг друга ключ в ключ. (#169)translateменяет базу местами только с переводом на целевой язык. Его папка находится в любом регистре, а перевод на другой язык намеренно остается на месте. (#169)naming/presentationтеперь требует заголовок у обработки. Обработка держит его вИнтерфейс.Представление: так называются ее форма и команда, которая ее открывает, а без него обе называются именем элемента. Стандарт относит обработки к элементам, у которых представление обязательно, иnew-object --presentationпишет заголовок именно туда. (#167)data-diffбольше не пишет “изменений нет” там, где данные изменились. Теперь он сравнивает весь каталог stdlib, включая обработчики модулей и сигнатуры, а такжеuiterms.json,terms_full.jsonи текст страниц справки. Текстовый отчет по-прежнему дает число и первые имена,--limit 0выводит все. (#168)
Исправлено
xbsl extractизвлекает языки проекта. В данных появились таблица языков и английские названия новых языков, иtranslate --strictбольше не находит пробела данных платформы в описании проекта, где указан один из них. (#169)- Карточки справки больше не слипаются. Ссылки из сетки карточек сливались в одну строку, а пример терял значок, по которому видно, правильный он или нет. Теперь карточки-ссылки идут списком, примеры помечены словами “Правильно” и “Неправильно”, а фрагмент кода в карточке остается кодом. (#165)
- Серверы больше не отвечают по данным, замененным под ними. Рабочий процесс MCP, который
прочитал пары терминов перед самой переустановкой, так и отвечал по старым. Теперь он отказывает с
причиной
data, и на вызов отвечает новый процесс; сервер языка просит перезапуска. (#168) xbsl extractбольше не пишет в каталог пакета. Шаг grammar складывал файлы грамматики в кэш рядом с кодом пакета, что бы ни говорил--data-dir. Теперь он читает их из дистрибутива в памяти, и установленный пакет остается нетронутым. (#168)- Справка
--element-versionназывает настоящее умолчание. Там было “последняя из бандла”, а версия берется изXBSL_ELEMENT_VERSION, а без нее – изdefaultвindex.jsonкорня данных. (#168) - Переводчик пишет стандартные реквизиты плана обмена в
РасчетРазрешенийПопо-английски. Номер отправленного сообщения и этот узел оставались в списке по-русски, и английский план обмена называл поля, которых у его объекта нет. Теперь их пишет вид элемента:SentNumber,ThisNode. (#168) xbsl extractбольше не сводит имя модели элемента с соседним. Такой класс пишет сначала русское имя, и этот узел плана обмена читался какReceivedNumber, а в словаре компилятора ошибался еще десяток слов, и имя Java-константы сходило за английское написание слова, которое она хранит. Данные обновитxbsl extract --dist ... --only terms. (#168)- Повторный перевод того же файла больше не оставляет вид расписания русским. Переводчик записывал английский вид обратно в разобранный файл, который хранится при источнике, и следующий проход в том же процессе уже не находил, что менять. Теперь разбор не меняется. (#168)
- Переводчик называет объявленный стандартный реквизит так, как его называет вид. План
обмена, объявивший номер отправленного сообщения, оставлял его русским и ждал записи в
словаре проекта, хотя его же список уже писал
SentNumber. Запись словаря по-прежнему главнее. (#168)
29.09.2026 – 0.121.0, 0.122.0, 0.122.1, 0.123.0, 0.124.0
Добавлено
new-object --record-presentationпишет заголовок записи регистра сведений. Он ложится вИнтерфейс.Запись.Представлениев единственном числе рядом с заголовком списка из--presentation, и новый регистр проходитnaming/presentation. В MCP этоrecord_presentation, в сервере языка –recordPresentation. (#164)- Новое правило
code/module-type-unavailableловит тип модуля там, где его нет. Структура, исключение или перечисление формы без аннотации окружения живет на клиенте, и серверный метод той же формы роняет применение:Type "X" is unavailable in the current environment. Быстрое исправление добавляет недостающую сторону, если поля типа есть на обеих. (#164) - Новое правило
code/qualified-member-unavailableпроверяетМодуль.ИМЯобщего модуля обоих окружений. Константу, структуру или перечисление, объявленные там для одной стороны, метод для другой стороны не получит: применение отвечаетUnknown propertyилиType ... is unavailable. (#164) - Новое правило
yaml/root-url-cyrillicпредупреждает оКорневойUrlсервиса кириллицей. Сборка такой адрес принимает, но запрос до сервиса не доходит. Быстрое исправление записывает адрес латиницей. (#164) meta_resource_referencesговорит, что лимит обрезал список. Новое полеhasMoreравноtrue, когда вreferencesмест меньше, чем вtotal: раньше обрезанный список легко было принять за полный. Командаresource-referencesотдает то же поле и печатает в stderr строку с--limit, при котором список будет полным. (#163)new-object --object-presentationпишет заголовок объекта справочника или документа. Он ложится вИнтерфейс.Объект.Представлениев единственном числе рядом с заголовком списка из--presentation, и новый объект проходитnaming/presentation. В MCP этоobject_presentation, в сервере языка –objectPresentation; другие виды параметр не принимают. (#163)- Новое правило
code/constant-unavailableловит константу модуля там, где ее нет. Константа формы без аннотации окружения живет на клиенте, и когда ее читает серверный метод той же формы, применение откатывает проект сVariable "X" is not defined. Быстрое исправление добавляет константе недостающую сторону. (#163) - Три новых правила тира A ловят описания элементов, которые сборка отвергает.
yaml/document-date-requiredтребует у документа стандартный реквизитДата,yaml/soap-handler-name– имя обработчика SOAP-сервиса из латинских букв, цифр и подчеркивания, аyaml/compute-permissions-by-unknown– поле элемента для каждого имени вРасчетРазрешенийПо. (#163) - Пять правил проверяют теги документирующего комментария так, как их читает среда разработки.
Среда читает их строго: строку с опечаткой в слове тега она молча теряет. Правила включены по
умолчанию и не проверяют блок без тегов:
comment/doc-tag-unknown,comment/doc-tag-layout,comment/doc-tag-param,comment/doc-tag-resultиcomment/doc-tag-target. (#153) - Сервер языка поддерживает теги документирующего комментария. Подсказка при наведении делит
описание метода по тегам, как карточка самой среды. Новая справка по сигнатуре выводит текст
@параметрдля аргумента, который сейчас пишется. В строке///дополнение предлагает теги и еще не описанные параметры, а над объявлением подставляет заготовку всего блока. (#153) add-fieldиmeta_add_fieldдобавляют компоненту интерфейса свойства и события. Раньше команда отвечала, что пополнять у компонента нечего. Занятое имя она отвергает. Новый параметр--docзаписывает описание элемента строками##документирующего комментария. (#154, #156)xbsl fold-comments --compactпечатает краткий отчет. Без этого ключа пробный запуск по целому дереву выводил каждый перенос и все правки каждого файла. Краткий отчет считает переносы по файлам и перечисляет только спорные, в том числе в--format json. (#154)- Отказ устаревшего сервера MCP содержит команду CLI для того же вызова. Если движок на диске
сменился под работающим сервером, эта команда выполнит вызов уже на новом коде. Такую команду
возвращают инструменты линтера, словаря и метаданных
meta_*. (#154, #157) yaml/hierarchy-bare-valueнаходит слово режима без типа в иерархии динамического списка. Сервер не применяет сборку, если вИспользуемаяИерархиястоитВыключено,ПоУмолчаниюилиАвтобез типа. Исправление пишет узел с типом вида{Тип: РежимИерархии, Значение: Выключено}и убираетАвто. (#156)- Переводчик предупреждает о короткой паре в комментарии с новыми строками. Смысл строки из
одного-двух слов зависит от всего комментария. Если в комментарии есть непереведенные строки, а
его короткую строку перевела пара словаря, отчет помечает ее
short-pair. Для каждого пропуска--gapsиtranslate_gapsпоказывают соседние строки. (#156) code/handler-overrides-nothingпроверяет модули других элементов. Раньше списки обработчиков были только у компонентов интерфейса. Теперь движок берет из кода компилятора и обработчики модулей объектов, регистров, запланированных заданий, ключей доступа и команд. (#156)- В индекс документации вошли справочники свойств и глоссарий справки. Ссылки на них с других страниц раньше никуда не вели, а теперь открывают нужную страницу или термин. Термины глоссария в поиск символа не попадают: он по-прежнему отвечает страницей типа или члена. (#156, #157)
xbsl-mcp-supervisorсохраняет сессию MCP при обновлении движка. Команда держит связь с клиентом, а сервер работает у нее отдельным процессом. Когда движок на диске сменился, она запускает новый процесс и повторяет в нем вызов, так что клиент перезапускать не придется. Подключается она явно:claude mcp add xbsl -- xbsl-mcp-supervisor. (#157)xbsl form-treeдля всей формы отдает иcomponentProperties, как уже делали инструмент MCP и редактор. (#157)- Новое правило
yaml/component-member-uniqueнаходит повтор имени среди собственных свойств и событий компонента интерфейса. Сборка такой повтор отвергает, поэтому правило тира A сообщает об ошибке. (#157) - Новое правило
yaml/auto-bare-valueнаходитАвтобез типа в свойстве, которое принимает иАвто, и строку. Так бывает в заголовке кнопки и в представлении фильтра или сортировки динамического списка. Сервер такую сборку не применяет, и правило тира D выдает ошибку. (#157) - Зарезервированные слова языка запросов и типы его литералов движок берет из справки. Шаг
termsизвлекает их в данные, аdata-diffпоказывает, что в них изменилось.comment/emphasis-caps, переводчик и типизация строк запроса читают их оттуда, а без данных берут прежние списки. (#157, #158) - Новое правило
yaml/union-needs-nullableнаходит составной тип без пустого значения. Сборка не может задать значение по умолчанию типу вродеСтрока|Число. Правило тира A выдает ошибку, а быстрое исправление дописывает|?. Ошибку снимает и явное значение по умолчанию илиОбязательное: Истина. (#158) - Два новых правила сверяют реквизит с переопределенным свойством контракта сущности.
yaml/contract-facet-mismatchтребует тех же ограничений, аyaml/contract-standard-lengthтребует у свойства длину, если его переопределяютНаименование,КодилиНомер. Сборка отвергает расхождение, поэтому оба правила тира A сообщают об ошибке. (#158) - Новое правило
code/contract-method-not-abstractнаходит обычный метод в модуле объекта или строки контракта сущности. Такой модуль принимает только абстрактные методы, поэтому правило тира D сообщает об ошибке. Модуль самого типа контракта и статические методы оно не проверяет. (#158) resource-references --limitограничивает список мест так же, какmeta_resource_references. По умолчанию мест в списке не больше 100, а полеtotalпо-прежнему считает все. (#158)- Новое правило
code/mandatory-handler-missingнаходит модуль без обработчика, которого требует компилятор. Это обработчик команды или задания, обработчики доступа, которые включают настройки,ПриСозданииНаОснованиина каждый тип основания и вторая половина пары. (#160) - Новое правило
yaml/compute-permissions-byсверяетРасчетРазрешенийПос настройками доступа. Список обязателен, когда разрешение вычисляется для каждого объекта, и запрещен в остальных случаях. (#160) - Новое правило
yaml/register-entity-contractнаходит регистр, который реализует контракт сущности. Регистр может реализовать только контракт типа, остальное сервер отвергает. (#160) - Новое правило
yaml/report-parameters-aliasнаходит параметры запроса отчета под ключомПараметры. Сервер этот ключ отвергает, и исправление переименовывает его вПараметрыЗапроса. (#160) - Заготовки понимают английские слова.
add-fieldиset-field-propertyпринимают вид элемента по-английски, аset-access– права и способы доступа, как их пишет английский yaml. (#160)
Изменено
naming/presentationпроверяет заголовки регистров и наборов констант. Регистру сведений нужны заголовки списка и записи, регистру накопления – списка, набору констант – записи: егоПредставлениеверхнего уровня называет константу, а не заголовок. Заголовки в интерфейсе устаревшего элемента тоже должны начинаться с пометки(не используется). (#164)yaml/compute-permissions-by-unknownпроверяет еще план обмена, хранилище настроек и интегрируемое приложение. Правило знает их встроенные поля, называет необъявленныйНомердокумента, аПометкаУдаленияиПредставлениеотмечает как вычисляемые поля: компилятор их принимает, а применение сборки падает. (#164)yaml/soap-handler-nameпроверяет остальную пунктуацию ASCII. Правило называет знаки, которые сборка не принимает в имени обработчика (%,<,>, двойную кавычку, фигурные скобки и еще несколько), и дефис или точку в начале имени. (#164)naming/presentationтребует у справочника, документа и похожих видов оба заголовка в интерфейсе. Имя реквизита вПредставлениеверхнего уровня их больше не заменяет: по п. 2.3 стандарта имен нужныИнтерфейс.Список.Представлениево множественном числе иИнтерфейс.Объект.Представлениев единственном, а сообщение называет недостающий. (#163)- Нет общего обработчика разрешений – одно замечание, а не два.
code/per-object-permissions-need-commonуступает ошибкеcode/mandatory-handler-missing, когда в данных есть списки обработчиков, и говорит только без них.code/access-key-handler-flavourтеперь цитирует ответ сборки, а названиеyaml/union-needs-nullableназывает параметры записи. (#163) xbsl-mcpпо умолчанию запускает сервер за супервизором. Сессия MCP теперь переживает обновление движка без перезапуска клиента.xbsl-mcp --no-supervisorилиpython -m xbsl.mcp_serverзапускают сам сервер, аself-updateостанавливает только рабочий процесс и такой сервер, но не супервизор. (#161)- Переводчик переводит строку тега по частям. Слово тега и имя после него он переводит так же, как в коде, а в словарь идет только текст после имени. Поэтому переименованный параметр меняется в теге вместе с сигнатурой. Пару на всю строку переводчик по-прежнему берет первой, и с готовым словарем перевод не меняется. (#153)
- Имена в тегах
@сми@выбрасываетпроверяет толькоcomment/doc-tag-target.comment/unknown-nameих пропускает: новое правило разрешает имена строже и называет недостающее. (#153) - Правила о прокрутке учитывают иерархию динамического списка. Иерархический список всегда
подгружается при прокрутке. Поэтому
yaml/list-scroll-without-loadingпроверяет динамический список, только если узел{Тип: РежимИерархии, Значение: Выключено}объявляет его плоским. Список над таблицей без иерархии проверяет новое правилоyaml/dynlist-scroll-without-loading. (#154, #156) code/handler-overrides-nothingучитывает режим совместимости проекта. Если описание компонента допускает обработчик не во всех режимах, правило засчитывает его только там, где он есть. Например, обработчика веб-чатаПолучитьДанныеПользователяВебЧатанет с режима 8.0, и о его переопределении в таком проекте правило теперь сообщает. (#154)- Ответ
lint_pathsстал короче. Сselectблокas_ciсжимается до одной строки, а сcompactнаходки уровня info только считаются. Раньше то и другое добавляло к каждому ответу по два килобайта и больше. Полный вид по-прежнему даютas_ci_fullиlist_info. (#154, #155) - У предупреждения сервера языка о смене кода на диске появилась кнопка “Перезапустить”. Раньше
оно только называло команду. Нажатие отправляет редактору уведомление
xbsl/restartRequested, и тот перезапускает сервер. (#154) yaml/dynlist-filter-computed-aliasнаходит и фильтр по псевдониму переименованного столбца или пути. Сервер отвергает такой фильтр как неизвестное поле, а при одноименном столбце без предупреждения берет его. Сообщение предлагает указать вПолесам путь. (#156)- Правила читают режим совместимости проекта так же, как платформа. Если описание не называет
поддерживаемый режим, правила берут новейший. Так теперь работают и
code/deprecated-api,code/contract-parameter-nameиyaml/property-since-compat. Проект в режиме 5.0 больше не получает находку на каждое свойство новее 5.0. (#156, #157) comment/emphasis-capsточнее отличает цитату запроса от ударения. СловоВЫБОРотмечает запрос только вместе сКОГДА. Цитатой считаются и начало оператора, который меняет временную таблицу, и литералы вродеИСТИНА, и значение после знака сравнения. (#156)- Свойству компонента можно задать значение по умолчанию и прочие ключи. Раньше
add-fieldиset-field-propertyотвергалиЗначениеПоУмолчанию,СохраняемыеДанныеиКонтекстное. Теперь допустимые ключи команды берут из описания компонента. (#156) - Предупреждение сервера MCP об устаревших надстройках тоже содержит команду CLI. Эта команда ответит по надстройкам, которые сейчас лежат на диске. Временные папки для таких команд старше суток сервер убирает при следующем запуске. (#156)
code/unused-methodберет из данных имена обработчиков, которые вызывает платформа. Теперь правило не считает неиспользуемым переопределение без аннотации в английском написании, напримерBeforeWrite. Имена видаПередЗаписьюОбъектаправило больше не пропускает: так обработчики формы объекта назывались в режиме 5.0, а самый старый поддерживаемый режим – 6.0. (#157)- Переводчик пишет переопределенный обработчик в модуле любого элемента так, как его пишет платформа. Раньше это работало только у компонентов, теперь и в модулях справочников, запланированных заданий, ключей доступа и сущностей. Запись словаря с другим написанием переводчик считает дефектом словаря. (#157)
- Сервер MCP отказывает в вызове, если код движка сменился при той же версии. Раньше он узнавал
о
git pullв редактируемой установке только после сбоя инструмента, и первый вызов шел на смеси старого и нового кода. Теперь он сверяет код перед каждым вызовом, аxbsl-mcp-supervisorотвечает на тот же вызов из нового процесса. (#158) code/undefined-nameподсказывает ближайшее имя из всей области видимости. В выборе участвуют имена модуля, элемента, проекта и глобальные, а при равенстве выигрывает более близкая группа. Само ошибочное имя правило не предлагает. (#158)- Создание метаданных берет значение в кавычки, только когда этого требует YAML.
СобытиеСДанными<Строка>или адресhttps://...все команды пишут без кавычек, как в исходниках дистрибутива. Булево значение, заданное словом, записывается словами языка файла. Справкаadd-fieldиset-field-propertyперечисляет все виды, которые они принимают. (#158) new-object НаборКонстантсоздает набор с константой-заготовкой. Пустой набор не компилируется. Первая константа, добавленная черезadd-field, занимает место заготовки. (#158)code/handler-overrides-nothingпроверяет модули сущности и ключа доступа по настройкам доступа. Об обработчике, который настройкиКонтрольДоступане используют, правило сообщает словами компилятора. (#158)ВычислитьРазрешенияДоступабольше не числится обработчиком модулей без цели контроля доступа, например общего модуля и команд. Модуль проекта получилВычислитьСистемныеРазрешенияДоступа, и его теперь учитываютcode/unused-methodи переводчик. (#158)code/handler-overrides-nothingсудит больше модулей. Теперь он судит модули, которым компилятор не дает обработчиков вовсе,ПриСозданииНаОснованиипо спискуСозданиеНаОсновании, сервисы и обработки по настройкам доступа, а модуль проекта по его виду. (#159)- Подсказки
code/undefined-nameучитывают позицию имени. Вызову предлагается то, что вызывается, голому имени – значение или тип. Короткому имени предлагается только кандидат на одну правку, иClose(...)больше не получаетCos. (#159) - Правила контракта сущности читают базовые контракты.
yaml/contract-facet-mismatchиyaml/contract-standard-lengthсверяют реализацию и со свойствами, которые контракт наследует, как компилятор, и называют контракт, который объявляет свойство. (#159)
Исправлено
new-objectсоздает ключ доступа сРучнаяВыдача: Ложь. Проект в новейшем режиме совместимости отвергал ключ, у которого не выбрана разновидность. Свойство пишется, только если его знает режим совместимости проекта: с 8.0 и выше. (#164)xbsl translateпереводитМетодобработчика SOAP-сервиса и полеСсылкавРасчетРазрешенийПо. Обработчик называл метод, которого в переведенном модуле уже нет, аСсылкаоставалась русской; теперь этоReference, член объекта сущности. Так же переводятсяЛюбойМетодмаршрута и поля индекса. (#164)self-update --stop-holdersбольше не снимает команды xbsl других сессий. Раньше флаг останавливал все процессы пакета, в том числе идущую проверку. Теперь он снимает серверы, а идущие команды называет по pid и командной строке. Если такая команда держит пакет, self-update отказывает и просит дождаться ее конца.--stop-holders=allснимает и команды, как раньше. (#164)yaml/compute-permissions-by-unknownпринимаетМоментПометкиУдаления. Сборка берет момент пометки удаления в список, а правило называло его неизвестным реквизитом. (#164)new-objectпишет адрес HTTP- и SOAP-сервиса латиницей. Для кириллического имениКорневойUrlоставался кириллицей, и новый сервис собирался, но не отвечал; теперь имя переходит в адрес латиницей вроде/proverka-zakazov. (#164)new-object SoapСервиспишет обработчик, который сборка принимает. Обработчик операции-примера назывался кириллицей, и сборка отвергала новый сервис; теперь онOperation1, а метод модуля сохранил свое имя. (#163)set-accessзнает права хранилища настроек и обработки. Хранилище принимаетСоздание,Чтение,ИзменениеиУдаление, а не одинПоУмолчанию, обработка –Вызов, а не ничего. Разрешения для каждого объекта у сервисов и обработки отклоняются. (#163)xbsl-mcpзапускает супервизор и послеself-update. Обновление заменяет пакет, но не заглушки команд, и заглушка от прежнего выпуска продолжала запускать сам сервер. Теперь такая заглушка передает свой процесс супервизору до загрузки движка, аself-update --stop-holdersотличает супервизор от старого сервера по рабочему процессу. (#162)- Перенос строк в переведенном абзаце больше не приклеивает тег документирующего комментария к строке выше. Теперь тег всегда начинает новый абзац. (#153)
comment/emphasis-capsбольше не принимает первое слово текста тега за ударение. Текст после@параметр Имя -начинает предложение, и короткий предлог там пишется с заглавной буквы. (#153)translation/english-shapeиcomment/emphasis-capsна английских строках больше не принимают аббревиатуру проекта за ударение. Ошибка случалась, когда перенос строк уносил аббревиатуру на другую строку. Аббревиатуру, которую словарь объявляет токеном, правила не считают ударением ни на одной строке. (#153)--as-ciс исходником проекта вместо файла конвейера больше не падает с ошибкой разбора. Отказ сообщает, что это не файл конвейера, и предлагает рабочую команду, как уже было для каталога. (#154)translate --unused --sinceучитывает новый файл словаря, которого еще нет в индексе git. Такой файл не попадает вgit diff, и раньше ответ давалdictionary_files: 0. При сравнении с рабочим деревом весь такой файл теперь считается новым. (#154)comment/emphasis-capsберет слова цитаты запроса из таблицы ключевых слов платформы. В собственных списках правила не хватало десятков слов, и цитата запроса без слова-маркера считалась ударением. О тех же словах, выделенных прописными в прозе, правило по-прежнему сообщает. (#154)yaml/list-scroll-without-loadingбольше не падает на списке, у которого тип строки записан с пространством имен. (#154)- Отказ
docs_searchбольше не превращается в ошибку проверки SDK MCP. Объявленный ответ допускал только список, и отказ устаревшего сервера доходил до агента ошибкой вместо текста. (#154) translate --setбольше не записывает значение фразы с пробелами по краям. Раньше пробелы снимались только с ключа, и значение с пробелами затирало готовую пару словаря. Перезапись, которая меняет только пробелы, отчет теперь помечаетwhitespace_only. (#155)- Модуль строки табличной части проверяется по области видимости строки.
structure/xbsl-pairузнает модуль вродеТовары.Позиции.xbsl, аcode/undefined-nameучитывает в нем реквизиты строки и находит опечатки. Метод типа строки правило принимает только вызовом со скобками. (#156, #157, #158) - Команда из поля
cliбольше не зависит от текущего каталога оболочки. В Python 3.10 нет флага-P, и команда могла запустить вместо движка папкуxbslиз этого каталога. Теперь она запускается из временной папки сервера. Относительныйfilenameуlint_sourceотсчитывается от рабочего каталога сервера. (#157, #158) - Создание метаданных пишет
trueиfalseиз вызова MCP словами языка файла. Раньше в английский файл попадали русские слова, а теперь тамTrueиFalse, как в английских исходниках дистрибутива. (#157) - Редактор и сервер MCP, запущенные без данных, подхватывают их после установки. Это касается таблицы ключевых слов запросов у правил и написаний платформы у переводчика. (#157)
- Справка
set-field-propertyиadd-fieldназывает видысвойствоисобытие. Справочник команд больше не разрывает имя команды, которое справка перенесла на дефисе. (#157) new-object --presentationпишет заголовок туда, где его хранит вид объекта. У справочника, документа и похожих видов верхнееПредставлениеназывает реквизит, и заголовок там не компилировался. Теперь он попадает вИнтерфейс.Список.Представление, иnaming/presentationзасчитывает его там. (#157)- Шаг
uischemaчитаетstdlib.jsonтой версии, которую строит. Раньше он брал версию по умолчанию, и снятые компоненты пропадали молча. Теперь, если файла нет, шаг об этом предупреждает. (#157) - Движок определяет режим совместимости английского проекта для ресурсов даже без данных терминов. Режим для ресурсов и для правил проекта теперь читается одинаково. (#158)
- Метод объекта засчитывается только вызовом. В модуле элемента
Структураи в модуле объекта голыеПредставление,ЗаписатьилиЭтоНовыйтеперь находка: компилятор их отвергает и принимает только вызов. (#159) yaml/union-needs-nullableцитирует нужный отказ. Теперь правило ловит и поле ввода вокруг составного типа и больше не судит свойство контракта типа: оно компилируется. (#159)code/contract-method-not-abstractсудит и модуль самого контракта, и статические методы. Компилятор отвергает и то и другое. (#159)set-field-propertyчитаетТиптак же, какadd-fieldчитает--type. Экранирование разметки снимается, имена платформы пишутся на языке файла. (#159)- Типы в
СозданиеНаОснованиипереводятся как типы.Счета.СсылкастановитсяInvoices.Reference, а неInvoices.Link; так же с ошибками SOAP-сервиса и контрактами типа. (#160) yaml/union-needs-nullableпроверяет и одиночный тип параметра записи или удаления. Такому параметру нужно пустое значение:Булевоне компилируется, аБулево?– компилируется. (#160)- Длинным именам больше не подсказываются имена, отличающиеся целым словом.
Conditionне получаетConditionString, а настоящие опечатки подсказку сохраняют. (#160)
27.09.2026 – 0.120.0
Добавлено
yaml/dynlist-filter-computed-aliasнаходит фильтр динамического списка по псевдониму вычисляемого поля. Поле фильтра ищется среди столбцов таблиц, а не среди полей списка, и такой отбор молча шел по одноименному столбцу или ронял применение сборки. Замечание называет этот столбец, когда видит его, и предлагаетЭлементФильтраВыражениедля вычисленного значения. (#151)meta_fold_commentsотвечает кратко сcompact. По целому дереву отчет называл каждый перенос и занимал четверть мегабайта. Краткий ответ оставляет счет, файлы с наибольшим числом переносов и переносы, на которые стоит взглянуть, до десяти строк в каждом списке, и все файлы, которые не прошли проверку. (#150)- Сервер MCP говорит, когда надстройки на диске не те, что он загрузил. После обновления
надстройки под работающим сервером
lint_pathsсудил старым набором правил, а CLI и CI уже новым, и ответ об этом молчал. Инструменты по-прежнему работают, но каждый ответ-объект начинается сstaleс обеими версиями и просьбой перезапуска, аversion_infoпоказываетplugins_on_disk. (#150) - Сервер языка предупреждает, что код на диске сменился под ним. Он живет столько же, сколько
окно редактора, и после
self-update,git pullили обновления надстройки продолжал проверять старым кодом. Теперь он сверяет версию движка, надстройки и свои файлы кода с их состоянием при запуске и на каждое изменение один раз просит перезапуска. (#150) code/handler-overrides-nothingнаходит@Обработчику метода, который ничего не переопределяет. В модуле компонента компилятор такой метод отвергает, а линтеру не с чем было сверить имя. Теперь шаг stdlib сохраняет списки обработчиков из описаний компонентов в поставке, в обоих написаниях; модули других видов пока не проверяются. (#152)
Изменено
yaml/list-scroll-without-loadingнаходит и список, который прокручивает страница. Список над массивом сНавигация: Отсутствуетбез размера страницы показывает одну порцию в десять строк, и без своей прокрутки строки после десятой молча пропадали. Список над деревом правило больше не судит: он подгружается при прокрутке при любом значении свойства. (#151)- Обычный отчет
translateсчитает фразы, которые перечисляет--drift. Режим не входит в--strict, и расхождение находил только тот, кто догадывался его запустить. Теперь строка со счетом и ключом появляется, когда есть что считать, то же число несут json-отчет иtranslate_status, а код выхода не меняется. (#150)
Исправлено
comment/emphasis-capsузнает предложение ПОЛУЧИТЬ языка запросов. Оборот “предложение ПОЛУЧИТЬ”, пару “СО СМЕЩЕНИЕМ” и их английскую строку в словаре (“the FETCH clause”) правило считало ударением капсом. Теперь это цитата запроса, а тот же глагол с ударением в прозе по-прежнему находка. (#151)- Тест, который сверяет два демо-проекта, больше не зависит от установленных надстроек. Надстройка, включающая правило о русской прозе, давала русскому демо находку, которой у английского двойника быть не может, и на такой машине набор тестов падал, а CI проходил. Теперь двойники проверяются опубликованным набором правил. (#150)
- Переводчик пишет переопределенный обработчик так, как его пишет платформа.
ПослеСозданияоставался русским в английском дереве, если в словаре не было записи: любой метод считался именем проекта. Теперь такая запись попадает в список лишних, а запись с другим написанием – в дефекты словаря. (#152)
25.09.2026 – 0.119.0, 0.119.1
Добавлено
xbsl fold-commentsсворачивает комментарии yaml в описание узла. Заметку без своего места, например к свойству компонента или к ключу элемента, команда переносит в описание ближайшего узла пунктом с именем предмета. По умолчанию она только показывает план, записывает ключ--write. Спорные переносы команда предлагает, а файл пишет только после проверки: данные yaml те же, все строки комментариев на месте, правила комментариев молчат. (#144)- Инструмент MCP
meta_fold_commentsсворачивает комментарии yaml для агента. Он делает то же, чтоxbsl fold-comments, и отвечает тем же отчетом, что--format json. По умолчанию ничего не пишет: записываетdry_run=false, спорные переносы применяетtake_proposed. (#145) code/sequential-server-callsнаходит клиентский метод, который обращается к серверу несколько раз подряд. Каждый вызов – отдельный круг до сервера, и при открытии страницы ожидания складываются; находка перечисляет вызовы и советует один серверный метод с типизированным результатом. Правило информационное и выключено по умолчанию, проверяет путь открытия, покаscopeне равенall, и не трогает ветвления, циклы, кешируемые методы и вызовы в разныхпопытка. (#147)code/url-data-schemeнаходит адрес data в конструкторе Url. Конструктор разбираетdata:как путь, браузер такой адрес отвергает, и картинка не рисуется, а строку свойствоИзображениене принимает. Предупреждение советует отдавать картинку HTTP-сервисом проекта или ресурсом. (#148)code/bound-handler-annotationнаходит@Обработчику метода, который привязывает yaml. Аннотация помечает переопределение обработчика базового типа, и компилятор отвергает её у обработчика события, команды или маршрута, названного в парном yaml. Исправление снимает аннотацию. (#148)xbsl translate --driftпоказывает фразы, где имя названо не так, как в его паре. Токен переименовали после того, как написали фразу, и английский комментарий называл то, чего в английском дереве нет; замечала это толькоcomment/unknown-nameна английском дереве, у самого комментария. Список читает только словарь и дает файл и строку каждой фразы; в MCP этоtranslate_drift. (#148)
Изменено
translate_statusсagainstбольше не перечисляет дубли, которые есть и в ветке-цели. Они приходили целиком при каждом вызове в ветке, около трех тысяч знаков за раз. Теперь такие дубли только посчитаны, перечислены лишь те, что приносит ветка, а весь список даетfull=true. (#145)yaml/size-needs-no-stretchпроверяет все виды, которые растягиваются приАвто. Раньше в наборе был одинКонтейнерHtml. Живая страница показала, какие виды веб-клиент растягивает без ключа: таблицы и списки, диаграммы, просмотр PDF и ещё несколько, часть из них только по ширине, – и правило теперь идёт по этой таблице. Списку оно называет оба ключа: с однимРастягиватьПоВертикали: Ложьсписок растёт по строкам, а высота держится только вместе сПрокруткаПоВертикали: Истина. (#146)
Исправлено
translateпереводитРасположениеЗаголовкауСтандартноеКлиентскоеПриложениеСРазделамивTitleLocation. Раньше ключ получал имяParameter, и компилятор отвергал переведенный проект: такого свойства он не знает. (#149)self-updateсразу после выпуска больше не отвечает “уже актуально”. Оба списка выпусков PyPI могут минутами отставать от новой версии. Команда читает оба, запрашивает страницу следующей версии, говорит о расхождении источников и никогда не ставит более старый выпуск поверх нового. (#145)- Сервер MCP, под которым обновили движок на диске, говорит об этом, а не роняет правила. Перед
каждым вызовом он сверяет версию из
__init__.pyна диске с загруженной; инструменты тогда просят перезапуск, аversion_infoпоказывает обе версии. Правило, упавшее после смены кода, тоже называет перезапуск, аxbsl mcp-logотмечает, когда сервер это заметил. (#145) translate --setиtranslate_setчитают файл правок как yaml. Пачку, выгруженную с ключами в кавычках, команда отвергала как пустую. Теперь ее читает загрузчик самого словаря, а отказ называет ключи верхнего уровня, которые в файле есть. (#145)- Список файлов внутри проекта проверяется так же, как дерево. Файл, заданный относительно
рабочего каталога, оставался относительным, а проект вокруг него загружался полными путями, и
подсистема файла не находилась:
code/foreign-not-publicпринимал модуль за модуль проекта,code/unknown-resourceтерял ресурсы проекта. Теперь в таком запуске все файлы идут полными путями, а файловые правила пропускают контекст – проверка списка стала примерно на пятую часть быстрее. (#148)
24.09.2026 – 0.118.0
Изменено
code/row-field-nullследит и за строкамиЗапрос{...}. Колонка, прочитанная через ссылку или из присоединённой таблицы внешнего соединения, может бытьNull. Если передать её в поле структуры, параметр метода проекта, переменную или результат метода безNull, сборка упадёт, и тип с?не спасает. Раньше правило смотрело только строки динамического списка, и запрос безЗаменитьNullпадал лишь при применении сборки. (#137)- Инструменты форм принимают
Имякомпонента там, где раньше брали только путь узла. Агент, который знал компонент по имени, получал отmeta_set_component_propertyотказ “Узел не найден” и сначала читал дерево ради пути. Теперь имя работает во всех инструментах и командахform-*, которые принимают узел; повторное имя отклоняется со списком путей, неизвестное – с похожими именами. (#137)
Исправлено
comment/unknown-nameне считает устаревшим имя, рядом с которым названа другая система. Фразу вроде “аналог Y из 1С:Предприятия” правило принимало за переименованный объект проекта. Теперь имя в пределах двух слов от1С:Предприятие,БСПилиБТСне судится, а свои системы проект объявляет ключом--other-systemв строке CI, и их узнают редактор и MCP. Сообщение подсказывает, как назвать систему. На одном проекте из четырех находок осталась одна, и она настоящая. Строку-аргумент вызова в закомментированном коде правило тоже больше не судит. (#143)- Правила комментариев yaml называют узел, к которому относится комментарий. Для комментария над ключом внешнего узла сразу после вложенного сообщение называло вложенный: PyYAML заканчивает его на следующем ключе. Теперь узел определяется по ключу после комментария. Страница о комментариях yaml больше не утверждает, что у реквизитов справочника нет места для комментария. (#143)
form/handler-signatureнаходит тип события, не связанный с сигнатурой. Раньше правило такие типы не судило: казалось, что у событий перетаскивания и автоподбора в каталоге не хватает базовогоСобытиеКомпонента. Компилятор подтвердил каталог и отверг такие обработчики. Типы проекта, которых каталог не знает, правило по-прежнему не судит. (#142)form/handler-signatureпринимает более широкий тип данных события. Обработчик может взять данные события как тот же тип с?, как его предка или какОбъект, и компилятор это принимает. Правило считало находкой любое отличие аргумента и ложно срабатывало на двух сторонних библиотеках. Тип источника по-прежнему должен совпадать точно. (#142)xbsl data-diffназывает порождаемые типы и виды с менеджером, которые появились или пропали. Списки членов сравнивались только по именам, которые есть в обеих версиях, поэтому новый порождаемый тип в отчет не попадал. Теперь такие типы и виды перечислены отдельно, как фасеты. (#142)- Английское сообщение
form/handler-signatureбольше не печатает русские имена. Когда тип параметра расходился с сигнатурой события, сообщение называло событие, компонент и ожидаемый тип так, как их хранит схема интерфейса, то есть по-русски. Теперь все три имени идут в английском написании, как в сообщении о суженном параметре. (#142) yaml/col-width-needs-no-stretchучитывает ширину, заданную привязкой. Правило пропускалоШирина: =...у колонки таблицы, а растягивание превращает число из привязки в долю так же, как литерал. (#142)xbsl extractнаходит пару для заголовка шаблона с нулевым символом внутри слова. Шагtermsчитал страницы справки без той чистки, которую делает шагstdlib, и такой заголовок оставался без пары. Данные двух последних поставок от этого не меняются. (#142)- Данные из свежей справки хранят русские имена полей строки списка. Эта справка пишет поля
строки автоматической формы списка по-английски (
Code,Parent,SettingKey) и в заголовке, и в сигнатуре. Теперь экстрактор берет написание, которое для поля вида объявляет сама поставка, как и для остальных членов. (#141) - Шаблон подчиненного регистра и нижняя граница компонента больше не теряются. Порождаемые типы регистра, подчиненного регистратору, попадают к виду регистра сведений, а не пропускаются как шаблон без вида. Режим совместимости, с которого регистрируется компонент, берется прежде всего из его описания в поставке: справка его с одной страницы потеряла. (#141)
xbsl extractчитает минифицированный сайт справки. На таком сайте однословное значение атрибута пишется без кавычек (class=hash-link,href=/docs/help/...), данные боковых панелей записывают часть символов экранами JavaScript, которых не принимает JSON, а пометка@Устарелополучила аргумент с сообщением. Запуск заканчивался без предупреждений и терял большую часть данных: из 2156 страниц документации оставалось 1406, из примерно 21 600 узлов дерева – 108, из 88 компонентов схемы интерфейса – 5, а типов членов и сигнатур методов не оставалось совсем. Теперь значения атрибутов при чтении берутся в кавычки, данные панелей приводятся к записи JSON, а сообщение пометки пропускается. Данные прежних поставок не меняются. (#138)- Параметры обобщенных типов и многострочные сигнатуры тоже читаются с минифицированного
сайта. Такая страница пишет
>в тексте без экранирования (Массив<ТипЭлемента>), и каждый обобщенный тип терял список параметров, а с ним вариантность параметров. Длинная сигнатура, напечатанная в несколько строк, сохраняла отступы (Загрузить( ИмяФайла: Строка?, ...)), а тип свойства искался после двоеточия, которое может стоять в сообщении@Устарело. Теперь нормализация разметки экранирует>в тексте, сигнатура сводится в одну строку, а пометка снимается до того, как читается тип. (#139) - Каталог stdlib больше не считает тип клиентским из-за нулевого символа на его странице. В
страницах документации одной из сборок нулевые символы стоят внутри слов, и метку доступности
типа, доступного на обеих сторонах, экстрактор читал по клиентскому префиксу:
code/type-unavailableотмечал такой тип в серверном коде. Теперь страница чистится при чтении, как в шаге документации, а метка принимается только целым словом. Каталог, собранный раньше, нужно извлечь заново. (#137) form/handler-signatureнаходит обработчик, который сужает параметр события. СобытиеПриНаведенииобъявлено на базовомКомпонент, и обработчик сИсточник: Надписьне проходил сборку, хотя линтер молчал. Параметр может взять тип из сигнатуры или его предка. Наследник теперь находка, и сообщение приводит сигнатуру так, как ее печатает компилятор. (#137)yaml/size-needs-no-stretchучитывает размер, заданный привязкой. Правило пропускалоВысота: =..., а растягивание перебивает число из привязки так же, как литерал. На живом проектеКонтейнерHtmlс высотой по привязке забирал всю свободную высоту окна на телефоне и прятал кнопку под собой. (#137)
23.09.2026 – 0.115.0, 0.116.0, 0.117.0
Добавлено
-
code/resource-replace-absentиcode/resource-label-unfilledсверяют метки шаблонов в ресурсах. Модуль, который читает файл css, html или svg и заполняет его метки черезЗаменить, проверяется на самом файле: правила находят замену строки, которой в файле нет, и метку, которую не заполняет ни одна замена. На живом проекте так потеряли стили три таблицы стилей: метки переименовали в файлах, а в коде нет. Оба правила выключены по умолчанию. (#135) -
Переводчик переносит строку кода, которая вышла за предел. Английские имена длиннее русских, и на проекте примерно из четырёхсот модулей после перевода 26 строк кода выходили за 120 знаков. Теперь такая строка переносится там, где руководство по стилю переносит выражение: после запятой или открывающей скобки списка либо перед операцией. (#133)
-
code/deprecated-projectнаходит использование объявлений проекта, помеченных устаревшими. Метод, свойство, конструктор, параметр или значение перечисления с@Устарелоотмечается там, где его используют и цель определена однозначно, как предупреждает IDE платформы. Разбор теперь сохраняет аннотации значения перечисления. (#132) -
yaml/double-quoted-bindingнаходит нестроковую привязку в двойных кавычках. Сервер отвергает такое значение, а значение без кавычек или в одинарных кавычках компилируется. Правило проверяет только свойства, которые схема интерфейса объявляет нестроковыми, а быстрое исправление меняет кавычки на одинарные. (#131) -
code/type-unavailableнаходит стандартный тип вне его окружения. Серверный тип вродеКодировкив клиентском методе проходил проверку линтера и отклонялся при применении сборки. Проверке нужны данные, заново извлеченные с разделомtype_availability; на старых данных она ничего не сообщает. (#131) -
xbsl mcp-logназывает причину закрытого соединения MCP. Сервер записывает в журнал свой запуск и завершение, аself-update --stop-holdersзаписывает, какие серверы остановил. По журналу видно, сломался сервер, его закрыл клиент или его остановило обновление. (#131) -
unused-resourcesищет ресурсы без известных обращений. Команда иmeta_unused_resourcesотдельно учитывают вычисляемые и неопределенные обращения и ничего не удаляют. (#130) -
Языковой сервер поддерживает точную правку документирующих комментариев. Инспектор свойств меняет комментарии допустимых YAML-узлов, сохраняя соседний текст. (#130)
-
Новые проверки находят использование процедуры как значения и несовпадение имен параметров контракта. Они проверяют вызовы, когда метод проекта установлен однозначно; неизвестные цели пропускают. (#129)
-
Объявление, которое блокирует перевод платформенного имени, указывает на пропущенную пару словаря. Проверка работает в проектах со словарем перевода и пропускает локальные имена. (#129)
Изменено
- Тесты библиотек могут использовать локальный корпус
.xlibдля проверки открытых и внутренних типов в YAML и XBSL. Архивы поставщика остаются вне репозитория. (#127) - В комментариях и документирующих строках Python используется обычный дефис. Остальные строковые литералы сохранены. (#127)
Исправлено
-
Описание
style/redundant-union-memberследует тому, как вариантность судит IDE. Изменяемый контракт ковариантен так же, как контракт для чтения: IDE называет лишнимМассив<Строка>вИзменяемыйМассив<Объект>|Массив<Строка>. Инвариантны только конкретныеМассив,Соответствие,МножествоиКоллекция. Описание правила и один тест утверждали обратное, теперь оба сверены с IDE. (#134) -
self-update --version Xставит выпуск, которого ещё нет в простом индексе PyPI. После выхода 0.116.0 индекс больше получаса отдавал прежний выпуск, и команда отвечала, что такой версии нет, хотя её страница на PyPI уже перечисляла файлы. Теперь явно названную версию, которой нет в индексе, команда ищет на странице этой версии. (#133) -
form-edit wrapсохраняет список там, где слот объявлен массивом. Обертка однойКартинкавГруппазаписывала содержимое одним узлом, и сервер отвергал форму. Теперь вид содержимого определяет тип слота из схемы интерфейса. (#131) -
form-edit set-propertyпишет типизированную привязку без двойных кавычек. Привязка ширины сохраняла кавычки, и сервер ее отвергал. Значение, которое YAML принимает без кавычек, пишется без них, иначе в одинарных кавычках. (#131) -
Проверка ресурсов учитывает приоритет и видимость. Свой ресурс имеет приоритет перед одноименным импортированным. Линтер находит недоступные и неоднозначные ресурсы, а перенос использует тот же порядок выбора. (#129)
-
Схемы SOAP-клиента остаются вместе с объектом. Перенос, переименование и удаление теперь включают импортированные XSD. Локальные ссылки получают новое имя, внешние URL сохраняются. (#129)
-
--check-duplicates --againstсравнивает словари через общую базу Git. Односторонние удаления и переименования больше не возвращают старые переводы; разные правки ключа остаются видны, JSON содержитmerge_base. (#128) -
Проверка комментариев распознает прикрепленную рамку
////. Переразбивка поддерживает также/** ... */и последовательные рамки из звездочек, сохраняя вид комментария, текст и окончания строк. (#128) -
Проверка объединений учитывает вариантность и формулы аргументов баз. Ковариантные базы только для чтения и вложенные подстановки распознаются после повторного извлечения stdlib; старые каталоги сохраняют прежнее поведение. (#128)
-
comment/unknown-nameсохраняет читаемые имена объявлений из сломанного YAML. Синтаксическая ошибка в описании объекта больше не превращает его известные имена в неизвестные при проверке комментариев. Текст внутри значений строк не учитывается. (#127) -
code/client-available-unusedне считает метод неиспользуемым из-за сломанного клиентского описания без читаемого имени объекта. Вид элемента определяет клиентский модуль в обеих языковых формах, даже если поле имени потеряно. (#127)
22.09.2026 – 0.114.0
Добавлено
-
code/access-key-handler-flavourпроверяет обработчик разновидности ключа доступа. Вычисляемому ключу нуженПроверитьНаличиеКлючейДоступав модуле менеджера. Ключ с ручной выдачей не принимает этот обработчик. Оба недопустимых сочетания видны до компиляции. (#125) -
lint_pathsсравнивает с прошлым вызовом, как--compare. Файл называет параметрcompare. Первый вызов сохраняет запуск, а каждый следующий отвечает появившимися и исчезнувшими находками и строкой на каждое изменившееся правило, всё в виде данных. Раньше разница была только в командной строке, а агенты сверяют проекты чаще через MCP. (#122)
Исправлено
-
Схема интерфейса восстанавливает снятые компоненты по описаниям среды выполнения. Если справка оставляет только снятую страницу, из дистрибутива берутся известные свойства и предел совместимости. Текущие страницы имеют приоритет; прежние наборы данных работают как раньше. (#125)
-
translate --unused --sinceучитывает чистое переименование ресурса. Git не выводит измененных строк, если содержимое файла осталось прежним. Старый путь теперь учитывается, поэтому пара, использовавшаяся только в прежнем имени файла, попадает в список сирот. (#124) -
docs_symbolнаходит члены, создаваемые платформой у компонентов интерфейса. Поиск читает заголовки членов в статье о типах компонентов и возвращает страницу, описание и раздел. (#124) -
Перенос комментариев сохраняет строки продолжения списка с более глубоким отступом. Строки под пунктом остаются отдельными в
//и/* ... */, даже если перевод стал длиннее. (#124) -
Члены типизированного исключения сохраняют платформенное написание при переводе. Объявление
пойматьтеперь распознаетИсключениекак тип. Одноименная запись словаря проекта больше не превращаетError.Causeв неизвестное свойство. (#124) -
Записи словаря для параметров метода больше не переименовывают псевдонимы запроса. Квалифицированная запись действует на локальные имена метода. Псевдоним запроса и обращение к соответствующему полю результата получают одинаковое написание. (#124)
-
translate --unused --sinceнаходит снятые строки внутри блочных комментариев. Разбор читает старую версию файла из Git вместе с неизмененными границами блока. Удаление начала блока больше не скрывает следующие комментарии, а удаление строки внутри блока находит ее пару. (#123) -
translate --sinceвидит изменения словаря при относительном пути проекта. Путь словаря разрешается до вызова Git из каталога проекта. Пары, добавленные и оставшиеся без использования в той же правке, попадают в результат. (#123) -
translate --set --targetотвергает путь при записи в каталог словаря. Параметр принимает имя файла, например020-names.yaml. CLI и MCP сообщают об ошибке до записи любых правок, поэтому случайный вложенный словарь больше не создается. (#123) -
--compareсопоставляет каталог, набранный относительным и абсолютным путём. Ключ находки брал путь в том виде, как его набрали, и два запуска одного каталога с разным написанием ничего не сравнивали, а оба пути называли исключёнными. Теперь пути сопоставляются по каталогу, а по написанию – когда каталоги разные, как у двух рабочих деревьев одного репозитория. (#122)
19.09.2026 – 0.112.1, 0.113.0
Добавлено
--summaryи--compare: счёт по правилам и разница с прошлым запуском.--summaryпечатает вместо находок строку на правило с числом файлов и находок.--compare ФАЙЛсохраняет запуск, и следующий запуск с этим файлом печатает только появившиеся и исчезнувшие находки. Раньше сверка до и после правки шла через--format jsonи свой скрипт, и в вывод попадал текст каждой находки. (#117)meta_add_fieldдобавляет несколько элементов за вызов. Параметрnamesпринимает имена одного вида с общими типом и свойствами, например значения перечисления. Пачка планируется целиком: занятое или повторённое имя отменяет её всю, и файл остаётся прежним. (#114)- В данных появились члены, которые платформа порождает элементу вида. Экстрактор читает
шаблонные страницы справки о типах вроде
Имя.ОбъектиИмя.ПараметрыЗаписицеликом: 152 типа и 2161 член в разделеgenerated_members. Раньше правило о неизвестном имени держало таблицу из четырёх имён и называло необъявленнымЭтоНовыйв работающем коде. Имена, которые зависят от настройки элемента, напримерРодительилиПометкаУдаления, правило принимает, только когда их включает yaml элемента. (#110)
Изменено
- Переводчик переразбивает по ширине и блоки
/* ... */. Раньше проход брал только строки//, и переведённый блок вылезал за предел ширины: английский текст длиннее русского. Знак/*остаётся в начале первой строки блока, а*/– в конце последней. (#118) - Вставка фрагмента кладёт его пояснения туда, где их читает среда разработки. Комментарий
над компонентом уходит внутрь узла строками
##и больше не остаётся перед-, где визуальный редактор стирает его при первой правке. Пояснение без своего места остаётся, и ответ называет его в заметках. Где и как писать комментарии в yaml, рассказывает новая страница “Комментарии в yaml”. (#116) - Пишущие инструменты
meta_*отвечают кратким линтом. В ответе число файлов и находок и до десяти находок по строке, полный отчёт по записанным файлам даётlint_paths. Раньше даже чистый файл стоил около двадцати строк на каждый вызов. (#114) meta_rename_objectотвечает кратко. Ответ называет переименованные файлы, счёт правок и файлы вне проектов, например словарь перевода, а перечень всех правленых файлов даётfull. На проекте в 63 правленых файла ответ сократился с 12,8 до 0,6 тысячи знаков. (#114)- Краткий ответ
lint_pathsназывает набор из CI одной строкой. В строке файл относительно корня рабочей копии, задача и ключи, а длинный список ключей сосчитан:--enable ×10. Всю запись о задаче оставляетas_ci_full. (#114)
Исправлено
- Запись списка принятых удерживает находку, даже когда правило изменило текст сообщения.
Запись с прежним текстом совпадает с находкой того же правила в том же файле, если в ней те же
значения в тех же кавычках и в том же порядке. Проверка называет такие записи, а
--write-baselineпереносит их причины на новый текст. (#121) pruneвtranslate_unusedиtranslate_redundantснимает всё, что выбрали отборы. Раньше снималась только страница ответа, и вызов сlimit: 5оставлял большую часть сирот. Теперь страница задаёт только выдачу, аpruned.keysговорит, сколько пар снято. (#120)meta_rename_objectдержит комментарии и их переводы вместе. Имя в комментарии теперь меняется целиком, вместе с текстом в кавычках, и в модуле, и в yaml. Словарь перевода не переписывается как исходник: перевод каждой изменённой строки комментария переносится на новый ключ, а парыtokensстарого имени называет заметка. Раньше ключ фразы менялся, а сам комментарий нет, и пара теряла свою строку. (#119)meta_resource_referencesнаходит файл, который называют без расширения. Начальные данные называют картинку кодом, а расширение добавляет модуль при выполнении. На такой файл инструмент отвечалtotal: 0, как на мёртвый. Теперь строка с ключом файла без расширения в модуле, yaml или JSON-файле ресурсов проекта приходит местом видаstem, и перенос файла называет её в заметках. (#115)self-updateне спотыкается о резервную копию прошлого запуска. Копию, которую ещё держит работающий сервер, Windows не даёт удалить, и следующее обновление падало с сообщением о занятых файлах. Теперь текущая установка откладывается под свободным именем с номером. (#113)- Член с именем со строчной буквы попадает в данные. Экстрактор отбрасывал такие имена. В
поставке такое имя одно,
iOSу видов платформы клиента, и правило о неизвестном статическом члене ругалось на работающий код. (#110) - Модуль объекта находит yaml своего элемента. Для
Имя.Объект.xbslпоиск пары искалИмя.Объект.yaml, которого не бывает, вместоИмя.yaml. Из-за этого голое имя в модуле читалось как чужое: реквизитЗапроспринимался за тип платформы. (#110) - Правило об
УдалятьТекущийпроверяет вид элемента, который объявляет реквизит. Раньше оно брало режим удаления документа и применяло его к любому файлу. Объявить режим удаления могут только четыре вида из сорока одного, и ложные находки приходились на остальные, в том числе на регистры. (#110) - Словарь перевода читается один раз на проход. В 0.112.0 свежесть словаря стала сверяться
по байтам, и
code/translation-gapsделал это для каждого файла. На проекте в 1267 файлов это давало 234 395 чтений и лишние 83 секунды. (#110) - Правила о комментариях yaml больше не ставят
##на экземпляр компонента проекта в списке. С комментарием на таком узле сервер не применяет проект, хотя среда разработки место для него показывает. Автоисправлениеyaml/plain-commentпереносило туда блок#и этим ломало сборку. Теперь узел считается местом без комментария:yaml/doc-comment-misplacedнаходит на нём блок##и называет причину, а пояснение предлагает перенести в комментарий группы. (#112)
18.09.2026 – 0.111.0, 0.112.0
Добавлено
- Правило
yaml/plain-comment: комментарий#пропадает после правки в визуальном редакторе. Среда разработки пишет файл заново из модели и сохраняет только документирующие комментарии: строки##в первых строках файла, узла-компонента или объявления в списке. Правило находит каждый#. Если место для комментария рядом, оно само меняет маркер или переносит блок внутрь узла. Выключено по умолчанию. (#111) - Правило
yaml/doc-comment-misplaced: блок##стоит там, где среда его не читает. Перед-элемента списка, над отдельным свойством, у стандартного реквизита или у команды такой блок пропадает так же, как#. Выключено по умолчанию. (#111) - Правило
comment/doc-marker: описание над объявлением начинается с///. В модуле среда разработки показывает в подсказке только строки///перед объявлением. Блок//и блок/* ... */на том же месте она не читает. Правило находит блок//прямо над методом, структурой, полем или константой и меняет маркер автоисправлением. Выключено по умолчанию. (#111) code/computed-property-server-call– серверный вызов в вычисляемом свойстве. Правило находит форму, у которой свойство компонента пересчитывается через серверный метод без штатного кеша результата, и показывает строки свойств и доказанную цепочку вызовов. Одна находка на пару “форма – серверный метод”. События, отложенные лямбды, клиентские варианты методов и включённый или неизвестныйКешироватьРезультатв находки не попадают;Изображениекомпонента платформы по-прежнему судитcode/image-binding-server-call. Уровень info, по умолчанию выключено – включается--enable. (#105)code/resource-read-without-cache– чтение ресурса без кеша. Доступный с клиента серверный метод, который только возвращает текст файла из пакета ресурсов (ПакетРесурсов.Текущий().Получить(...).ОткрытьПотокЧтения().ПрочитатьКакСтроку()), при каждом вызове ходит на сервер за одним и тем же. Правило предлагаетКешироватьРезультат = Истинаили передачу файла параметрами работы клиента; автоисправления нет. Уровень info, включено по умолчанию. (#105)- Экстрактор пишет три необязательных раздела данных. Значения фасета
Сущность.Право, владельцев менеджеров видов элементов и английские имена картинок библиотеки платформы (пары подбираются по содержимому файлов, картинки без пары печатаются в отчёте). Чтобы разделы появились, данные нужно извлечь заново; данные без них работают как раньше. (#105) - Линтер находит кнопку рядом с картинкой в ряду без явного вертикального выравнивания.
Такой ряд равняет детей по базовой линии. У
Кнопкаона проходит по надписи, уКартинка– по нижнему краю, и на живом ряду кнопка опустилась на 19 px.yaml/insert-row-needs-alignнаходит пару, которая стоит прямо в ряду, а новое проектное правилоyaml/component-row-needs-align– пару, которую рисуют компоненты проекта. (#106) set-localizationиmeta_set_localizationпринимают пакет ключей за один вызов. Пакет берётся из файла JSON или YAML (--entries-file), из повторяемого флага--entry КЛЮЧ=JSONили из словаряentriesу MCP-инструмента и сочетается с обычной записью одного ключа; ключ, названный дважды, отклоняется. Каждый файл пакет читает один раз и переписывает один раз, и только если значение в нём правда изменилось. Плохой ключ в пакете останавливает запись раньше, чем тронут хоть один файл. (#106)list_rulesи--list-rulesпринимаютfilter. Он ищет подстроку id правила, имя группы (часть id до/) или слово из названия правила, текста его сообщений на любом из двух языков либо английского докстринга. Слово, в точности совпадающее с именем группы, сужает ответ до одной этой группы – поиск подстрокой отвечал наform70 правилами, хотя вform/их 2, и наcode120, хотя вcode/их 98; любое другое слово по-прежнему ищет широко и сочетается сselect/ignore, как раньше. Фильтр, который ничего не нашёл, предлагает ближайшие имена групп. (#106)
Изменено
- Проходы рядом с индексом перевода читаются раз на состояние исходников. Имена, типы, компоненты и области словаря считались заново на каждый вызов. Теперь их держит тот же отпечаток, что и индекс, и занимает это 2 МиБ. Указатель ресурсов намеренно оставлен снаружи: он читает имена файлов картинок и стилей, а картинка, положенная в папку, меняет его ответ и не меняет ни одного отпечатка. (#109)
- Первый вызов перевода в процессе стоит дороже, следующие – заметно дешевле. Отпечаток снимают шесть проходов там, где раньше один, поэтому первый круг по корпусу в 22 МБ вырос с 2,9 до 4,3 секунды, второй упал с 4,5 до 0,8, третий – до 0,5. Разовая команда из оболочки на этом теряет; долгоживущий сервер и всё, что переводит повторно, выигрывают. (#109)
- Кеши собирают ответ один раз, как бы ни пришли вызовы. Сборка индекса читает данные, а данные возвращаются в собственный сброс кеша на том же потоке, поэтому замок нужен повторно входимый – обычный на этом месте заклинивает, и это держит тест. (#109)
code/image-binding-server-callопирается на общие сведения о серверных вызовах. Кешированные методы и клиентские варианты больше не попадают в находки; имя, унаследованное формой (ЗаписатьИЗакрыть), не путается с общим модулем; вызовыИмя.Метод()при неизвестном базовом типе и элементы с испорченным полем метаданных пропускаются. Возможны несколько новых находок через промежуточные методы. Сообщение больше не утверждает, что запрос уходит при каждой перерисовке. (#105)- Перевод строит индекс проекта и работает дольше – на проекте в 1300–1500 файлов на 5–7 секунд. (#105)
set-localization --dry-runпечатает сводку вместо целого файла. Раньше запуск выводил полный текст каждого изменённого файла – один ключ возвращался как 103 КБ, обе локализации целиком. Теперь для каждого ключа названы язык, старое и новое значение и файл; полный текст никуда не делся – он за новым флагом--full-text(full_textу MCP-инструмента). (#106)lint_pathsсcompactпоказывает сами находки, а не только их число. До десяти находок ответ теперь перечисляет их новым ключомfindingsстрокамифайл:строка правило – сообщение; при большем числеfindings_hintназывает счёт и как получить список. Блокas_ciсжимается доenabled,adoptedи однострочногоflags(иjob, если конвейер запускает больше одной задачи линтера), но сохраняетhint,noteиunread_includes, когда они не пустые – клиент, который сверяет набор ключей ответа, эту разницу увидит. (#106)- Таблицы правил на сайте документации помещаются на страницу, а самые длинные описания переехали из них. Колонка текста стала шире – с принятых в Blume 42rem до 60rem, а длинный код в ячейке таблицы теперь переносится, а не растягивает её в горизонтальную прокрутку. 101 описание правила длиннее 200 знаков, в обеих редакциях, сократили примерно втрое; снятые подробности – исключения, примеры, история платформы – легли в пояснение под таблицей своего тира, строка даёт на него ссылку. (#106)
- Индекс проекта для перевода теперь хранится всё время жизни процесса, а не строится
заново на каждый вызов. Само построение индекса (
ProjectIndex.build) падает с 8,4 до 0,11 с, но это не то, что чувствует человек: разовый вызовxbsl translateиз командной строки – это один процесс, индекс в нём строится один раз, и такой вызов быстрее не станет. Первый вызов в процессе даже медленнее примерно на 0,19 с, потому что отпечаток исходников теперь читает байты каждого файла, а не время изменения. Выигрывает долгоживущий сервер MCP и всё, что переводит больше одного раза за один процесс: второй вызов на копии сайта падает с 55,4 до 47,1 с, на втором корпусе – с 35,4 до 28,0 с. Это та же стоимость, которую назвала запись про #105 (“Перевод строит индекс проекта и работает дольше”): она не исчезла, а теперь платится один раз за процесс. (#107) code/unused-methodбольше не считает комментарий употреблением метода. Раньше имя, названное только в комментарии, пряталось от правила как использованное – в модуле, который объявляет метод, в парном yaml, в чужом элементе. Теперь ни одно из этих мест не считается, а находка, которая держится на одном комментарии, так и говорит. На корпусах находок стало 237 вместо 216. Проект, где правило включено в конвейере, увидит новые находки, как только конвейер проверит код после обновления: это настоящие мёртвые методы, а не ложные срабатывания. Правило называет два способа их снять: аннотацию, которая называет вызывающего вне кода проекта, или список принятых замечаний с причиной для остального. Строка правила в таблице документации стала короче и получила ссылку “подробнее” – в форме, которую документации задала шестая партия: список аннотаций и путь через список принятых лежат за этой ссылкой, а не в самой строке. (#107)- Запись пары словаря теперь называет платформенные слова, которые она задевает, – в
новом поле
platform_names.translate --set, инструмент MCPtranslate_setи путь машинного перевода (--suggest-out) возвращают один и тот же список: по строке на правку, чей ключ совпадает с именем типа или члена платформы, с написанием платформы и причиной. Поле добавочное – тот, кто его не читает, ничего не заметит. (#108) - Поиск отсутствующих данных платформы теперь стоит одно обращение на проход линтера, а не одно на каждый вызов. Словари терминов и интерфейса, унаследованные свойства компонента и каталоги серверных вызовов раньше перечитывали корень данных при каждом вызове, пока данных не было. На 400 файлах без данных это дало падение с 403 обращений до 1 на повторном проходе. Сервер языка или MCP, запущенный до появления данных, по-прежнему подхватывает их без перезапуска – только на следующем проходе, а не на следующем вызове. (#108)
Исправлено
- Запуск больше не обрывается на первом файле, когда данных платформы нет. Правило картинок включено по умолчанию, а общий разбор шёл до вопроса о данных, и свежая установка без данных падала необработанной ошибкой вместо ответа. Теперь без данных разбора не происходит, и тот же заслон снимает его цену: 800 разборов модуля превращаются в ноль, 120 мс в 1,7. (#109)
- Ключ словаря, написанный словом YAML 1.1, пишется в кавычках.
On,No,Nullи прочие читаются строгим разборщиком булевым или пустым, поэтому ключ, названный по полю переключателя, возвращался какTrue. Список из двадцати шести слов взят со страниц спецификации. Обычный ключ остаётся голым, а записанный голым раньше по-прежнему читается и обновляется на месте. (#109) - Словарь держится по отпечатку байтов, а не по времени записи. Две записи подряд делят один
тик часов, поэтому правка той же длины оставалась незамеченной, и проверка линтером сразу после
translate_setотвечал по дословарной правке. Проверка свежести стоит теперь вдвое дороже – 20,8 мс против 10,2, – аcode/translation-gapsберёт её на каждый файл: около десяти секунд на проекте в тысячу файлов. Правило выключено по умолчанию; конвейер, который его включает, это почувствует. (#109) - Экстрактор берёт самую полную таблицу видов элементов из дистрибутива. В архиве
сервера с IDE таких копий может быть несколько; первая часто называет только
HttpСервисиSoapСервис, и виды вродеСправочник,ОбщийМодульиКомпонентИнтерфейсавыпадают из метамодели. Свойства форм считались неизвестными. Наблюдалось как минимум на 9.2.9+12 и 9.3.1+4; обход копий от версии платформы не зависит. (#102) - Имена платформы рядом с одноимёнными именами проекта. Аннотация платформы, ключи
типизированного узла команды (
Обработчик,Представление,Изображение,Элементы) и аргументТип<...>переводятся как имена платформы, даже если проект объявляет те же слова. (#105) - Член цепочки переводится по типу, который его объявляет.
ГраницастановитсяBound,Удалитьу массива, соответствия и строки –Remove,Пусто–IsEmpty,Проверитьу права на действие –Check,Сущность.Право.Чтение–Entity.Privilege.Read. Тип корня цепочки берётся только там, где метод видит это имя. Повторный перевод может изменить английское дерево, в том числе на старых данных. (#105) - Картинки библиотеки платформы получают английские имена в yaml, в
Ресурс{...}и в строках, записанных голым именем или черезСтд::(Стд::Аккаунт.svgстановитсяStd::Account.svg), если в данных есть таблица картинок. Файл проекта с тем же именем главнее. (#105) code/unknown-resourceзнает английские имена картинок библиотеки и не называет ошибкойResource{Std::Account.svg}в переведённом или написанном по-английски проекте. (#105)- Правила серверных вызовов не запоминают отсутствие данных платформы. Сервер языка или MCP, запущенный до установки данных, находит их в проекте, написанном по-русски, без перезапуска; проекту на английском перезапуск по-прежнему нужен. (#105)
translate --unusedбольше не предлагает снять живые пары литералов. Представление или шаблон представления в yaml, строка внутри интерполяции другой строки и имя группы образца читались только регулярным выражением по кавычкам в сыром тексте, поэтому все три вида терялись, и--pruneуносил их пары из английской сборки. Поиск сирот теперь спрашивает у самого переводящего прохода, какие тексты тот ищет, вместо того чтобы держать отдельную копию тех же правил. (#106)translate --strictпадает, если у локализуемого текста yaml нет пары. Раньше пропуск представления, заголовка приложения, сообщения о разрешении, шаблона события журнала или любого другого значения, которое метамодель метитLocalizable, только попадал в отчёт, а проверку не ронял; исключение –Описание, это документация разработчика, и другие пропуски литералов (строка в коде, нетипизированное значение с%{...}) по-прежнему её не роняют. Значение=с подстановкой теперь переводится как выражение, поэтому запись для его строки находится, а не теряется. (#106)translate --setиtranslate_setзаписывают фразу тем написанием, которое прочитает переводящий проход. Ключ фразы – это строка комментария без экранирования, но ключ, набранный по правилам литерала с экранированной кавычкой, раньше записывался как есть и при переводе не срабатывал: пара выглядела рабочей и молчала. Теперь кавычка и лишние пробелы по краям снимаются перед записью, а поправка возвращается полемnormalized. Её печатают CLI, сервер MCP и теперь ещё панель перевода расширения VS Code: раньше панель молчала, и автор искал бы в словаре ключ, который сам напечатал, и не находил его. Ключ или перевод на двух строках так не исправить, и запись отвергается с объяснением: переводящий проход ищет каждую строку комментария отдельно. (#107)translate --setиtranslate_setотвергают правку с пустым или пробельным ключом, и команда завершается кодом 1. Раньше такая правка исчезала без единого сообщения, а команда всё равно завершалась кодом 0. Тот, кто проверяет код возврата после пачки правок, теперь получит отказ там, где раньше молча терял запись. (#107)terms_full.jsonтеперь пишется в устойчивом порядке. Разделcommonраньше шёл в порядке обхода классов дистрибутива, а не по алфавиту, поэтому повторное извлечение без единой правки смысла всё равно двигало 5708 записей из 5709 – шум, в котором потерялась бы настоящая правка. Владелец шаблона при точной ничьей выбирался черезset(owners)– порядок обхода этого множества зависит от рандомизации хеша строк в процессе: один и тот же дистрибутив при разных запусках называл разного владельца, а с ним – разный список элементов. Теперь оба места детерминированы: раздел сортируется по ключу, а ничья решается по алфавиту. Экстрактор, запущенный на одном дистрибутиве дважды, теперь даёт побайтно одинаковый файл. Это исправление того, как данные собираются, а не того, что они говорят: значение каждой записи не изменилось. (#107)translate --strictтеперь может упасть на ключе словаря, который называет тип платформы. Падает это только тогда, когда проект сам объявляет тип с тем же написанием: пара переименовывает платформенный тип везде, где его читает выражение типа, – в том числе в файлах, которые ничего не знают об узле проекта, и английская сборка там перестаёт собираться. Запись такой пары (translate --set,translate_set) только предупреждает: писатель держит словарь, а не проект, и не может отличить смертельный случай от обычного. Строгий проход держит и то, и другое, поэтому ошибку ловит именно он, как правило до сборки на платформе. Ключ, названный именем члена платформы, а не типа, смертельным не бывает – предупреждение просто называет верное английское написание члена. На живом словаре в 30 274 записи смертельный случай не встретился ни разу: 42 голых ключа называют тип платформы, 39 из них повторяют её собственное написание. Но конвейер, где строгий проход уже стоит, может не пройти на следующем же запуске без единой правки кода. (#108)- Квалифицированная ссылка на картинку библиотеки теперь всегда означает библиотеку.
Раньше
Стд::Сохранить.svgрядом с файлом проектаСохранить.svgрешался в пользу файла проекта независимо от приставкиСтд::. Теперь приставка побеждает, как и читается; имя без приставки по-прежнему предпочитает файл проекта. Строка или значение yaml, которое схема считает текстом, с именами картинок библиотеки больше вообще не сверяется: путь в такой строке во время работы читает пакет ресурсов текущего пространства имён, куда библиотека не входит никогда. Поэтому строка, совпавшая с именем картинки библиотеки, переводится – или остаётся как есть – обычным текстом, так же, как до появления таблицы картинок. (#108) conventions/missing-translationтеперь учитывает собственные файлы ресурсов проекта, а не только библиотеку картинок платформы. Без них правило отдавало библиотеке любое имя, которое она держит: файл ресурса проекта, совпавший с именем картинки библиотеки, находку не получал, хотя перевод проекта оставлял его ссылку непереведённой. На проекте с таким совпадением возможны новые находки. Ни один из корпусов, на которых проверялась партия, такого совпадения не несёт, поэтому на живых данных правка не проверена. (#108)- Перевод больше не угадывает владельца у звена, чей тип объявлен объединением нескольких типов. Член, до которого добирались через такое звено, раньше переводился так, будто его типизирует только первая альтернатива. Теперь звено обрывает цепочку владельцев, и член переводится так же, как переводился до появления владельцев вообще. Переведённый фрагмент внутри интерполяции строки теперь читает ту же цепочку владельцев, что и код вокруг него, поэтому одно и то же выражение больше не выходит переведённым снаружи кавычек и русским внутри них. (#108)
code/resource-read-without-cacheбольше не пропускает элемент подключённой библиотеки, названный как корень пакета ресурсов. Элемент проекта с таким именем уже гасил проверку для всего проекта. Глобальный элемент библиотеки с тем же именем доступен проекту точно так же, голым именем, но правило имена библиотек прежде не знало и могло предложить кеш методу, который на деле обращался к этому типу. (#108)- Словари терминов и интерфейса и унаследованные свойства компонента перестали держать пустой ответ после чтения, которое не нашло данных. Проект, написанный по-английски, читался так, будто у него вовсе нет словаря платформы, пока что-то не сбрасывало процесс. Теперь следующий проход линтера смотрит на диск заново, и проект на английском языке анализируется верно сразу. (#108)
- Сломанный файл данных теперь падает, а не выглядит отсутствием данных. Те же кеши раньше ловили любое исключение при чтении своего файла и принимали неудачу за отсутствие данных. Теперь отсутствием данных считаются только не найденный файл и файл, который не разобрался, а любое другое исключение роняет проверку. Испорченная установка видна сразу, а не линтится молча по неполному каталогу. (#108)
- Экстрактор теперь описывает четыре компонента, которые справка платформы сняла с
описания. Страница справки для такого компонента только говорит, что он заменён, и не
перечисляет членов. Тип оставался без записи в
type_members, и форма на такой базе выпадала из анализа правил серверных вызовов и изstyle/shadow-own-property. Теперь экстрактор для таких компонентов читает их собственное описание – платформа по-прежнему поставляет его для конструктора форм – и делает это всякий раз, когда справка называет компонент, но больше его не описывает. Это правка экстрактора, а не новые данные сами по себе: запись вtype_membersу всех четырёх компонентов появится только после того, как экстрактор прогонят заново по каждой версии платформы, а результат опубликуют через репозиторий данных. При том же запуске экстрактор больше не считает парой путь к картинке, копии которой разные: такой путь раньше выпадал до группировки и оставлял свою группу однозначной на вид. (#108)
15.09.2026 – 0.110.0
Изменено
- Краткий ответ линта больше не содержит карту файлов. Счётчики, полные записи ошибок,
сведения о списке принятых замечаний и задаче CI сохранены;
compact=falseвозвращает полный отчёт. (#99) - Удаление неиспользуемых переводов по умолчанию отвечает счётчиками.
removedсчитает вхождения,prunedгруппирует их по видам и файлам, включая повторы за границей выбранной страницы.compact=falseвозвращает полный список; просмотр сохранил прежний формат. (#99)
Исправлено
-
Новые проверки находят отсутствие возврата, запись после захвата лямбдой и потерянный результат метода. Они учитывают поведение компилятора и отличают изменение значения от создания нового. Старые каталоги языка поддерживаются. (#103)
-
Неоднозначные короткие имена типов называются в коде и YAML. Пространства корня и пакета имеют равный приоритет; учитываются смешанные квалифицированные выражения и проектные тезки типов платформы. Привязки YAML не принимаются за типы. (#103)
-
Ошибка разбора больше не скрывает замечания инициализаторов и повторных объявлений/ветвей в здоровых соседних методах. Поврежденные методы пропускаются, смещения исправлений сохраняются относительно исходного текста. (#103)
-
В справочнике правил восстановлено оформление служебных слов и идентификаторов как кода, в том числе в последних добавленных строках. (#103)
-
Именованные аргументы проверяются по установленным сигнатурам локальных методов и модулей. Называются неизвестные и повторные имена, позиционные аргументы после именованных и пропущенные обязательные параметры. Методы структуры имеют приоритет над методами модуля; затененные приёмники и неоднозначные перегрузки не проверяются. (#101)
-
Поля структур проверяются на отсутствие значения по умолчанию и для необобщенных платформенных типов. Например,
ПозицияВТекстетребуетобз, допускаНеопределеноили инициализатора; скалярные значения по умолчанию и локальные тезки типов учитываются. (#101) -
В выражениях динамического списка ссылка явного псевдонима таблицы переводится как
Reference. Псевдонимы основной и присоединенных таблиц действуют внутри источника, включая отборы; ссылки интерфейса и другие приёмники сохраняют своё значение. Поддержаны и английские ключи выражений. (#101) -
Лишний вызов
ПропуститьНеопределено()называется для известного типа элемента безНеопределено. Исправление для перебираемой коллекции используетВМассив(), сохраняя создание массива. Для последовательности выдаётся предупреждение без автоматической правки. (#101) -
Автоисправления сохраняют принятые замечания. CLI
--fixи MCPlint_paths(fix=true)исправляют новые находки, не меняя список принятых. Эта защита сохраняется и после сдвига строк предыдущими правками. (#100) -
Снятие лишнего приведения удаляет ненужные скобки и в начале оператора. (#100)
-
Неизвестные таблицы запроса проверяются во всём списке источников через запятую, в том числе после условий соединения. (#100)
-
Объявление цикла с уже занятым именем больше не считается присваиванием исходной переменной. Чтения в теле относятся к исходному объявлению; учтены счётные циклы и регистр имён. (#100)
-
На старых данных вид перечисления переводится как
Enumeration. Написание сериализатора имеет приоритет перед именем типаEnumиз стандартной библиотеки. (#99) -
Текстовый вывод
translate --setназывает каждое изменённое место. Повторы ключа в одном файле словаря и в разных файлах различаются по пути и номеру строки. (#99)
14.09.2026 – 0.107.0, 0.108.0, 0.109.0
Добавлено
-
Семь проверок находят ошибки объявлений и устаревшие вызовы платформы до развёртывания. Они сообщают о пропущенных инициализаторах, значениях по умолчанию обязательных полей, возврате закрываемого ресурса, повторах объявлений, значений выбора и типов исключений, а также вызовах только устаревших перегрузок платформы. (#98)
-
Необязательная проверка неиспользуемых констант находит объявления, которые проект не читает.
code/unused-constantвключается явно при чистке проекта. (#98) -
Пять правил находят присваивания и переходы, которые откатывают сборку.
code/self-assignmentиcode/assign-targetловятХ = Хи левую часть вродеОбъ?.Значение,code/assign-readonly– новое значение длязнч,исп, переменной цикла илипоймать,code/unreachable-statement– код послевозврат, аcode/misplaced-jump–прерватьвне цикла. (#89) (#90) (#91) -
style/boolean-ternaryиstyle/redundant-scopeнаходят то, о чём предупреждает IDE платформы. Тернарный оператор с ветвямиИстинаиЛожьравен своему условию, аобласть, единственная в своём блоке, ничего не ограничивает. У обоих правил есть исправление. (#86) -
style/redundant-union-memberиcode/duplicate-importнаходят повторы, о которых предупреждает IDE. Член составного типа, который покрывает другой, и дважды импортированное пространство имён снимает исправление;yaml/duplicate-importделает то же для секцииИмпортэлемента. (#87) -
code/lambda-changes-outer-localнаходит лямбду, которая присваивает локальную переменную, объявленную вне её. Платформа такой код не компилирует, а линтер его пропускал. Член или элемент захваченного значения менять по-прежнему можно. (#84) -
code/redundant-castиcode/cast-to-non-nullнаходят приведения, о которых предупреждает IDE платформы. Приведение к типу, который у значения уже есть, и приведение, которое только отбрасываетНеопределено, проходили линтер, а на одном проекте их было 65. Исправление убирает приведение или ставит вместо него!. (#74) -
code/redundant-undefined-guardнаходит??,!и?.над значением, которое не бываетНеопределено. IDE платформы о такой защите предупреждает, а движок не выводил ни тип компонента по разметке, ни тип члена обобщённого типа по его аргументу. Исправление убирает?? ...и!. (#73) -
code/redundant-type-checkнаходит проверкуэтос заранее известным результатом. Такая проверка проходит всегда, аэто не– никогда, и IDE платформы о ней предупреждает. Колонка запроса получает тип выбранного поля. (#73) -
style/constructor-literalнаходит вызов конструктора, который заменяется литералом типа. IDE платформы предупреждает оновый Дата("9999-12-31")иНайтиТип("Стд::Строка"), а линтер их пропускал. Исправление ставитДата{9999-12-31}там, где литерал хранит то же значение. (#71) -
resource-referencesнаходит места, которые называют файл ресурса или папку. Исходники читаются так же, как вmove-resource. У каждого места есть файл, диапазон и строка, а обращения по строке и ключ из двух каталогов помечены. В MCP команда называетсяmeta_resource_references, в LSP –xbsl/metaResourceReferences. (#67) -
move-resource,rename-resource-folderиdelete-resource-folderработают с папками ресурсов. Файл, перенесённый вручную, оставлял ключиРесурс{...}на старом пути, пока не падала сборка. Команды переносят файлы и переписывают ключи; обращения по вычисленной строке перечисляются, но не правятся. (#62)
Изменено
-
Отброшенные выражения считаются ошибками сборки, даже если содержат вызовы.
code/statement-no-effectдопускает в качестве операторов-выражений только вызовы методов и выброс исключения. Проверка присваивания только для чтения также учитывает поля через локального получателя типа структуры. (#98) -
Диагностика версии называет каталог загруженного движка.
--version,--where, сведения об окружении MCP и журнал запуска LSP различают установленные копии и исходники с одинаковым номером версии. (#98) -
comment/emphasis-capsсудит не только служебные слова из своего списка. Теперь правило ловит заглавную букву посреди фразы, приставку капсом, обычное слово прописными и английскую строку комментария, а аббревиатуру отличает по самому файлу. Обход комментариев больше не принимает HTML-значение yaml с\'за комментарий. (#92) -
comment/first-personчитает английскую строку переведённого комментария. Значениеphrasesвроде “we build it from the name” проходило, хотя его русский ключ получал замечание. Литералы, где часто лежит текст для пользователя, не судятся. (#85) -
Правила о защите от Неопределено, о проверке
этои о приведениях читают один вывод типов. У первых двух была своя копия наборов типов и чтения колонок запроса, и каждая копия знала формы, которых не знала другая. Теперь проверка типа читает и вычисляемые колонки запроса и контракты сущностей, защита – элемент типизированного массива, приведение – значение компонента разметки. (#93) -
xbsl/formKeysотдаёт и значения перечислений. Новое полеvaluesсопоставляет английские и русские значения по свойству, а в ответе появились классы команд и члены встроенных шрифта и цвета. Клиенту, который читает английскую форму, больше не нужно угадывать. (#83) -
xbsl.typeinferотвечает множеством типов и знает имена проекта. Раньше модуль называл один тип только по каталогу платформы, поэтому тип колонки запроса, параметра-объединения или структуры из другого модуля оставался неизвестен. (#74) -
code/unused-localсообщает о неиспользуемой переменнойиспи о переменной, которой только присваивают. IDE платформы предупреждает об обеих, а правило пропускалоиспи принимало запись за чтение. Исправление снимает имя у неиспользуемойисп, и ресурс всё равно закрывается в конце области видимости. (#69) -
С
--project-rootсервер LSP не проверяет yaml вне корня, кроме словаря. Такой файл получал находки при открытии и терял их при следующем сохранении. Модули по-прежнему проверяются, где бы их ни открыли. (#59) -
delete-objectиdelete-resource-folderубирают папки, которые опустошили удаления. Пакет, из которого удалили последний объект, оставался пустым каталогом, который git всё равно не хранит. (#62)
Исправлено
-
Текущие типы свойств сохраняют пустые варианты. Экстрактор отделяет исторические формы от текущих и учитывает порядок наследования, поэтому старая сигнатура больше не стирает пустое значение из типа свойства. (#98)
-
code/ternary-and-orбольше не считает ошибкой сборки любоеА и Б ? X : Y. Такой тернарный оператор берёт условие целиком и компилируется; строку ломает только тернарный сразу послеэто Тип– он принадлежит проверке. Правило теперь судит только эту форму, а исправление берёт условие в скобки. (#97) -
Парсер читает
не Значение это Строкакак(не Значение) это Строка, как платформа. Раньше вся проверка попадала подне, и лишнее приведение или заранее известная проверка отрицания оставались без находки. (#97) -
Тип платформы сохраняет написание там, где может стоять только тип. Поле, реквизит или метод с именем типа платформы держали этот тип в выражениях типа и перед фасетом, и английское дерево смешивало написания. Теперь выражение типа, корень статического вызова и владелец фасета берут написание платформы, если проект не объявил тип с тем же именем. (#94)
-
Файл ресурса и метод своего компонента пишутся одинаково во всех местах. Файл мог получить слово платформы, пока форма просила его собственное имя, а вызов через узел формы – встроенную команду. Теперь оба следуют словарю проекта; картинки библиотеки платформы читаются как прежде. (#95)
-
Локальная переменная, скрывающая тип платформы того же английского слова, – коллизия. С таким параметром английское дерево читало параметр там, где метод имел в виду тип:
--strictпроходил, а сборка падала. Теперь отчёт называет оба места. (#96) -
Правила импорта читают больше таблиц. Присоединённая таблица настроек ввода ссылки и таблица после условия соединения (
ИЗ А ЛЕВОЕ СОЕДИНЕНИЕ Б ПО ..., В) не читались, иcode/unused-importмог назвать такой импорт лишним. Модулю проекта теперь нуженимпорт Подсистемаи для элемента корня подсистемы. (#88) -
Правила видимости читают таблицы списков и запросов. Непубличная таблица другой подсистемы в динамическом списке, настройках ввода ссылки, блоке
Запрос{...}или запросе виртуальной таблицы роняет сборку, и теперь о ней сообщаютyaml/foreign-not-publicиcode/foreign-not-public. (#88) -
yaml/wrong-namespaceиcode/wrong-namespaceсудят частичное имя элемента, который лежит в нескольких местах. Компилятор ищет только там, куда ведёт имя, поэтому находка перечисляет места и оставляет выбор автору. (#88) -
Словарь перевода больше не прячет неиспользуемые методы. Он называет каждый метод, который переводит, и
code/unused-methodпринимал эти имена за употребления: проверка проекта вместе со словарём ничего не находила. (#82) -
Правила “не используется” учитывают слова файла, который не разобрался.
code/client-available-unusedиyaml/unused-componentвыбрасывали такой файл целиком, и метод или компонент, употреблённый только там, получал ложную находку. (#79) -
--setиtranslate_setправят ключ во всех местах, где его объявляет словарь. У повторённого ключа новое значение получала одна строка, и следующая загрузка отвергала словарь, а при снятии копия продолжала переводить ключ. Ключ, названный в пакете дважды, больше не уносит соседнюю запись. (#81) -
Английский клиент SOAP-сервиса узнаётся по виду и без таблицы видов в данных. В запасном списке написаний, которым движок пользуется без данных или с данными до 0.54.1, не было
SoapServiceClient. Обзор проекта считал такой клиент отдельно, а отбор по виду его не находил. (#80) -
LSP-сервер сохраняет находки модуля, открытого вне корня проекта. Проверка всего проекта идёт при каждом сохранении и раньше стирала находки открытых файлов, которых не читала. Теперь находки остаются до закрытия файла. (#78)
-
translateсохраняет написание объявления. Локальная переменная, параметр, параметр лямбды, переменнаяпойматьили свойство своего элемента с именем типа платформы получали написание типа вИмя.Члени внутри%{...}. Английская сборка встречала переменную, которую никто не читает, и член, которого у типа нет. (#76) -
Короткая лямбда может присваивать в теле. Платформа компилирует
Список.ДляКаждого(Элемент -> Элемент.Значение = 1), а парсер находил там синтаксические ошибки. Так же было с единственным параметром без скобок, названнымТип,ЗапросилиМетод. Правила, которым нужен разбор, пропускали такой модуль, иcode/client-available-unusedназывал метод, который вызывается только из него. (#75) -
style/shadow-own-propertyнаходит переменную с именем унаследованного свойства. Правило читало только yaml самого элемента и пропускало свойства, которые компонент наследует от типа платформы, а это все семь предупреждений IDE на одном проекте. Как и в IDE, статические методы и переменные цикла больше не проверяются. (#72) -
code/unused-importповторяет поиск типов, который делает компилятор. Правило считало употреблением любое слово с именем элемента, даже строку импорта, и на проекте с пакетами пропускало все импорты, которые показывает IDE платформы. На проверенных проектах находки совпали с IDE, а исправление снимает строку. (#70) -
code/unused-localиcode/unused-loop-varбольше не сообщают о переменной, прочитанной ниже пакетного запроса, и о счётчикедля Х = А по Б. Точка с запятой внутри запроса обрывала метод раньше времени, а счётчик числового цикла IDE не проверяет. (#69) -
yaml/missing-importчитает таблицы динамического списка. Список, у которого основная или присоединённая таблица лежит в пакете другой подсистемы, проходил линтер, а серверная сборка его отвергала. Теперь такая таблица требует импорт. (#58) -
yaml/wrong-namespaceиcode/wrong-namespaceпроверяют и частичное имя. После переноса в пакетПодсистема::Имяустаревает так же, как полное имя, и сборка его отвергает. Если элемент лежит в одном месте, исправление дописывает сегмент пакета. (#58) -
code/package-resources-missingпроверяет и корень подсистемы. Проба на сервере показала: без своего каталогаРесурсывызовПакетРесурсов.Текущий()в корне подсистемы не находит ничего, даже файлов её пакетов. (#58) -
Загрузка словаря и
--check-duplicatesвидят ключ, повторённый в одном файле. Разбор yaml оставляет только последнее значение, и такая пара молча грузилась со вторым переводом. Теперь повтор считается конфликтом или дублем, а место названо файлом и строкой. (#57) -
Сервер LSP не теряет находки словаря рядом с суженным корнем проекта. Проверка проекта читала только файлы под
--project-rootи стирала находки остальных открытых файлов, поэтому файл словаря терял их при первом сохранении. Теперь словарь входит в проверку. (#59) -
move-object,rename-objectиdelete-objectбольше не теряют описания WSDL клиента SOAP-сервиса. Файл<Имя>.Wsdl.1.wsdlоставался на месте, и перенесённый или переименованный клиент не применялся. При переименовании номер описания сохраняется, а ссылка одного описания на другое по имени файла получает новое имя. (#63)
13.09.2026 – 0.106.0, 0.106.1
Добавлено
- Сторож документации ловит фразу, которая объясняет правку ссылкой на человека. У репозитория один автор, и такая фраза выглядит так, будто код писали для кого-то третьего. Сторож читает оба издания документов и комментарии исходников. (#46)
- Пять проверок слога и знаков в комментариях. Правило
typography/non-keyboardвключено по умолчанию и предлагает для стрелок и математических знаков запись с клавиатуры. Ключом--enableвключаютсяtypography/en-dash-comment,comment/subjunctive,comment/first-personиcomment/emphasis-caps. (#51) - Ещё две проверки комментариев, обе по умолчанию выключены.
comment/dash-conditionловит тире вместо “если”.comment/unknown-nameнаходит имя, которого не знают ни проект, ни платформа, например старое имя переименованного метода. (#55) translation/english-shapeпроверяет английский текст словаря перевода. Механическая правка вроде “a second icon onlies clutter the row” проходилаxbsl translate --strict, который мерит только покрытие. Правило включено по умолчанию. (#52)yaml/wrong-namespaceиcode/wrong-namespaceловят полное имя, пережившее перенос. Такое имя ведёт на старое место, и сборка отвечает “Неизвестный тип”. Если элемент с таким именем один, исправление ставит его пространство имён. (#56)code/package-resources-missingнаходитПакетРесурсов.Текущий()в пакете без каталога ресурсов. Вызов отдаёт ресурсы пакета, поэтому модуль, перенесённый в такой пакет, молча перестаёт находить файлы подсистемы. (#56)move-objectпереносит объект между пакетами и подсистемами, не ломая ссылок. При переносе руками пропадали импорты и устаревали полные имена, а заметно это было только на серверной сборке. Команда переносит и формы с модулями, а импорты и имена чинит по правилам самого линтера. (#54, #56)rename-packageпереименовывает пакет вместе со всеми именами, которые его называют. Команда переносит каталог и переписывает импорты, элементыИмпорти квалифицированные имена. В других проектах меняются только полные имена. (#54)- Сервер LSP отдаёт
project-infoзапросомxbsl/metaProjectInfo. По этому ответу дерево метаданных редактора раскладывает объекты по подсистемам и пакетам. (#54) lint_pathsпо запросу отвечает компактно, а сводка каждого отчёта получилаby_rule,by_fileиby_severity. Полный ответ MCP нёс текст каждой находки, хотя чаще спрашивали только, чисто ли дерево.compact=Trueоставляет сводку и полные записи ошибок. (#49)xbsl translate --check-duplicatesнаходит ключ, переведённый в двух файлах словаря. Git сливает такие файлы без конфликта, но разные переводы ломают загрузку. С--against origin/masterстолкновение видно ещё до слияния. (#48)translate_unusedостанавливается по истеченииbudget_secondsи отвечает тем, что успел прочитать. Раньше вызов сsinceпо большому проекту молчал, пока клиент не переставал ждать. Неполный ответ помеченpartial: true, иpruneего не трогает.xbsl translate --unusedпечатает ход работы в stderr. (#47)translate_unusedпринимает список фильтров и называет те, под которые ничего не попало. Проверка десяти снятых строк комментариев стоила десяти вызовов. Фильтр изunmatchedозначает строку, которой в словаре уже нет. (#47)translate_entriesотвечает компактно и по десять строк. Пятьдесят полных строк весили около десяти килобайт на вызов, хотя обычно спрашивают только, как слово уже переведено.compactоставляет в строке{key, kind, value}. (#47)
Изменено
project-infoотвечает на заданный вопрос без справочных разделов. Они не зависят от исходников, но приходили в каждом ответе, а теперь приходят только с--referenceили--brief. Ответ сужают--packageи--project. (#53)- Правила импорта и видимости кладут свои пространства имён в
dataнаходки. Сообщение написано на двух языках, аmove-objectчинит импорты по данным. Данные получают и JSON-отчёт, и редактор. (#54) add-subsystemсоздаёт подсистему только в корне проекта. Каталог внутри подсистемы уже пакет, и описание там ничего не меняло, поэтому такой родитель теперь отвергается.new-objectпроверяет имя нового каталога пакета. (#54)- Команды создания метаданных, которые переносят файлы, больше не оставляют пустых каталогов.
delete-objectнаходит и формы объекта с английскими именами:<Name>ObjectFormиListRow<Name>. (#54) --sinceсудит и пары, которые правка сама записала в словарь. Первая редакция комментария, переписанного в той же ветке, в сравнении с базой не видна, и её пара оставалась навсегда. Справка--unusedуказывает на--format json. (#47)
Исправлено
- Перевод переносит в английское дерево импорт пакета другой подсистемы. Список
Импортв yaml называет такой пакетПодсистема::Пакет, а переводчик оставлял это значение русским. Строгий режим этого не замечал, и переведённая сборка не узнавала типов пакета. Теперь каждый сегмент берётся из словаря, а сегмент без записи строгий режим считает пропуском. (#50) - Правила импорта знают пакеты подсистемы. Другой подсистеме нужен
импорт Подсистема::Пакет, а правила считали достаточнымимпорт Подсистема. Теперьcode/missing-importиyaml/missing-importпросят импорт пакета. (#53) - Правила импорта читают модуль проекта и запросы. Компилятор разрешает и то и другое через
импорты, а линтер их не проверял. Теперь правила просят импорт в модуле проекта, в таблицах
запроса и в литерале
Тип<...>. (#56) - Правила импорта читают имена внутри интерполяции строки.
code/missing-importне видел имени в%{...}, аcode/unused-importназывал лишним импорт, без которого сборка падала. (#53) code/unused-importвидит импорт подсистемы с пустым корнем. Если все элементы подсистемы переехали в пакеты, правило её не узнавало и лишний импорт пропускало. Ресурс, названный ключом без пространства имён, импорт сохраняет. (#56)- Команды создания метаданных находят место объекта в пакете. Подсистему искали только прямо над
объектом, и форма списка получала неверный тип строки. Теперь
object-infoиproject-infoотдаютpackageи полное пространство имён. (#53) style/redundant-tostringсудит вызовВСтроку()по его месту в выражении. Правило судило по строке кода и находило(A + B).ВСтроку() + "px", где вызов обязателен. Теперь вызов лишний только после строкового литерала в той же сумме. (#49)- Отказ словаря называет все ключи, переведённые по-разному, а не только первый. Слияние с четырьмя такими ключами стоило четырёх кругов “снять один, загрузить снова”. Теперь одна ошибка перечисляет их все с переводом в каждом файле. (#48)
12.09.2026 – 0.104.0, 0.105.0
Добавлено
tests/test_conventions.pyловит тест, затенённый однофамильцем. Тест, приехавший под именем существующего, занимает его место, и число тестов при этом растёт: новичок добавился. В выводе запуска ничто не говорит, что старый тест остановился. Проверка смотрит наtests/и называет строку, которую надо переименовать. С июля репозиторий держит на одном определении на имяtests/test_source_hygiene.py; эта пришла из общего пакетаdocsguardи читает ещё и тело класса, где pytest собираетtest_-метод точно так же. (#44)- Сторож соглашений требует указывать stdin при запуске процесса из движка. Иначе дочерний
процесс получает stdin сервера MCP или LSP и на Windows не может завершиться. Проверка
охватывает только каталог
xbsl: генераторы и тесты работают из консоли, там stdin консольный. (#42) - Машинный отчёт командной строки называет взятый набор задачи конвейера. В
--format jsonпоявилсяsummary.as_ci: задача и файл, из которого она взята, сам набор данными и строкой, которую печатает терминал, невзятые задачи и непрочитанные включения. Раньше об этом говорила только строка на stderr в текстовом режиме: читателю отчёта взять её было негде, и сводку видел лишь инструмент агента. Отказ тоже доходит до отчёта, под тем же ключом и без замечаний в ответе. (#41) - Типографика доходит до файлов ресурсов проекта. Длинное тире, символ многоточия,
кудрявые кавычки, ёлочки и буква “ё” ловятся теперь и в
.css,.js,.svg,.htmlиз каталога ресурсов. Раньше туда не смотрел никто, хотя браузер получает эти файлы как есть. Проверка читает комментарии и текст на экране; код, селекторы и значения атрибутов остаются в стороне. (#36) - Перевод читает комментарии в файлах ресурсов. Раньше
.css,.js,.htmlи.svgкопировались байт в байт, поэтому русский комментарий уезжал в английскую сборку, а--strictсчитал такой файл покрытым. Теперь их текст идёт обычной фразой словаря: комментарии, а в.svgещё<title>и<desc>. Комментарий с лицензией и минифицированный файл пропускаются. (#34) - Сервер LSP отвечает, каким набором правил судит (
xbsl/ciStatus). Раньше об этом была одна строка в канале вывода, куда никто не смотрит. Теперь запрос говорит, взят ли набор из задачи конвейера, какой именно и из какого файла. Расширение показывает это в строке состояния. (#22) translate --dry-runпоказывает, что команда запишет и что удалит. Раньше чистка шла вслепую: счётчик удалённых файлов печатался уже после удаления. Теперь команда доходит до записи и останавливается, а имена остатков видны заранее. (#21)- Паритет с CI читает включения GitLab (
include:). Задача линтера часто лежит не в корневом файле, и проверка отвечала “команды xbsl нет” про конвейер, который эту задачу запускает. Теперь локальные включения читаются, а удалённые не качаются, но названы: видно, почему задача не нашлась. (#19)
Изменено
- Общий сторож закреплён на
docsguard@v0.9.0. В этом выпуске проверки исходников читают файл черезutf-8-sig.xbsl/__init__.pyначинается с метки порядка байтов,ast.parseотвечал на неёSyntaxError, и один такой файл оставлял всю проверку без находок по всем остальным. Проверка перевода строки снова принимает каталоги целиком, а обход, читавший их по одному файлу, убран. (#44) - Сторож соглашений читает русские строки в исходниках. Раньше он смотрел только страницы, хотя справку команды и текст отказа человек читает так же, как страницу. Проверка называет четырнадцать модулей с сообщениями. Модули правил в список не попали: рядом с текстом там лежит таблица английских терминов, записанных кириллицей, и её ключ сторож принял бы за прозу. (#39)
- Сторож соглашений разбирает исходники общим пакетом
docsguard. Ту же механику делят мост и консоль, здесь осталось только то, что про этот репозиторий. Находки до и после переезда совпали. В CI пакет ставится по тегу: из ветки он менялся бы под репозиторием без коммита в нём. (#23) - Помощь
xbsl --helpи страницы расширения VS Code написаны обычными словами. В помощи стоялиджоба,пайплайн,базлайн,прогониворкеры: слова читались транслитерацией, предложения тянулись на несколько строк, и половину текста приходилось переводить обратно. Теперь там задача CI, конвейер, список принятых замечаний, проверка и процессы, а подпись значения--as-ci-jobсменилась сДЖОБАнаЗАДАЧА. (#28) - Сообщения движка написаны обычными словами. В отчёте линтера, в отказах и в журнале
сервера LSP стояли
базлайнипрогон. Теперь там список принятых замечаний и проверка. Английские строки не менялись: жаргон был только в русской половине. (#33) - Строка пробного запуска перевода больше не кричит капсом. Было
СУХОЙ ПРОГОН, сталоПробный запуск. Заодно страницы документации догнали переписанные сообщения: примеры вывода цитировали текст, которого инструмент уже не печатает. (#35)
Исправлено
.gitattributesдержит перевод строки за весь репозиторий. Строка* text=auto eol=lfхранит и выдаёт текстовые файлы с переводом строки, что бы ни стояло на машине. Раньше файл задавал толькоdiffпо расширениям, и клон сcore.autocrlf=trueполучал 546 текстовых файлов с возвратом каретки. Ключаnewline=""в генераторах на Python для этого мало: он влияет только на запись, аscripts/sync-docs.mjsкопирует байты, когда переноситCHANGELOG.mdи README расширения на страницы сайта. (#44)- Табличные режимы перевода отвергают ключи записи дерева.
--gaps,--entries,--table,--unused,--redundantи--suggestдерева не пишут, а--out,--clean,--dry-runи--missingпринимали молча: просьба показать, что будет сделано, возвращалась таблицей. Теперь такой запуск называет непрочитанные ключи и возвращает 2. (#43) translate --unused --sinceбольше не молчит внутри сервера MCP. Дочернийgitполучал stdin сервера и не мог завершиться: работа занимала четыре миллисекунды, а чтение ждало пять минут. Теперь дочернему процессу задан пустой stdin, а git, не ответивший за минуту, отвергается с подсказкой, чем спросить то же самое. На живом проекте было 302 секунды и ошибка, стало 3–7 секунд. (#42)- Конвейер читает свои включения от корня репозитория. За корень шёл каталог названного
файла, а это верно только для
.gitlab-ci.ymlнаверху репозитория. Конвейер из подкаталога искалinclude: /ci/base.ymlрядом с собой и отвечал, что команды xbsl в нём нет. Теперь корень ищется по.gitнад файлом, в том числе в рабочем деревеgit worktree, где.gitлежит файлом. От того же корня отсчитывается путь к списку принятых замечаний. (#40) - Файл, записанный инструментом на Windows, больше не возвращается с изменённой каждой
строкой. Запись в текстовом режиме переводила
\nв окончание строки платформы, поэтому экспорт шаблонов, отчётdatadiff --out, языковые данные извлечения и словарь перевода выходили там с CRLF. В рабочей копии безcore.autocrlf=inputтакой файл уходил в репозиторий одной правкой окончаний, которой никто не просил. Двадцать два места записи теперь называютnewline, и соглашение держится проверкой, как давно держится кодировка запущенного процесса. (#37) - Каталог, названный после
--as-ci, отвергается с подсказкой. Ключ ждёт файл конвейера, поэтомуxbsl --as-ci e1cсъедал путь к дереву, и линтер уходил проверять текущий каталог. Теперь отказ называет рабочую формуxbsl e1c --as-ci. (#20)
11.09.2026 – 0.102.0, 0.103.0
Добавлено
- Настройка паритета с CI просит перезапуск сервера LSP. Ключ уходит серверу аргументом, а
список настроек, из-за которых сервер перезапускается, про него не знал. Включённый в живом
окне
xbsl.linter.asCiне делал ничего до перезагрузки. (#18) - Панель “Проблемы” умеет судить набором правил из задачи конвейера. Терминал это уже умел,
панель нет, и одно дерево получало два вердикта. Включает
xbsl.linter.asCi, задачу называетxbsl.linter.asCiJob. Сервер читает тот же файл конвейера, что и CLI. (#14) --as-ci-jobвыбирает задачу, когда конвейер запускает линтер дважды.--as-ciбрал первую командуxbslв файле, и до второй задачи было не добраться. Теперь задачу можно назвать, сам ключ--as-ciрядом не нужен. Запуск без имени печатает, какие задачи он не взял. (#13)--as-ciсудит локальную проверку набором правил из задачи конвейера. Ключ читает--select,--ignore,--enableи список принятых замечаний из той же командыxbsl, которую запускает CI. Раньше разницу узнавали из красной задачи: на живом проекте обычный запуск находил 2 замечания, а задача конвейера 11. (#10)- Инструменты метаданных ссылаются друг на друга.
meta_add_fieldзаводит ключ локализованной строки, а тексты переводов пишетmeta_set_localization, и узнать об этом было неоткуда. Теперь у соседних инструментов есть строка “см. также” в описаниях MCP и в справке CLI. (#4) translate --redundantнаходит пары словаря, на которые платформа отвечает сама. Такая пара ничего не переводит и прячет за собой пробел в данных: наполовину переведённые языки проекта не были видны именно из-за неё. На живом словаре в 31 989 записей их нашлось 22;--pruneснял все, и английское дерево из 1 261 файла осталось побайтно прежним. (#3)
Изменено
- Имя, объявленное проектом, не объясняется платформенным членом того же написания. Своему
методу
Записатьподсказка отвечала карточкой проекта, а следом приписывала платформенный член, к нему отношения не имеющий. Теперь ответ проекта закрывает вопрос, а панель предлагает поиск по слову. (#16) - Наведение и панель документации отвечают блоком члена, а не страницей его типа. Над
Текст.Подстрокаподсказка писала, что такое тип “Строка”. Теперь она показывает сигнатуру и что делает вызов, а ссылка открывает страницу на заголовке члена. (#9) - Коллизия перевода называет место обоих имён. Отчёт говорил только, в каком методе или структуре встретились два слова, и дальше их искали глазами. Теперь каждое имя несёт файл, строку и колонку своего объявления, и так во всех четырёх пространствах имён, за которыми следит проход. (#7)
docs_symbolнаходит члены типов и принимает оба написания. Своей страницы у члена нет, поэтому запрос по имени отвечал пустым объектом, а английскоеArrayне находило ничего: страницы-то русские. Теперь член отвечает страницей своего типа и блоком одного этого члена. (#6)translate --outпишет репозиторий, а не россыпь файлов. Сборка берёт проект только по схеме{репозиторий}/{Поставщик}/{Имя}, а команда клала дескриптор прямо в названный каталог, и выкатить переведённое дерево можно было только переложив его руками. Теперь оба имени берутся из переведённого дескриптора. (#5)
Исправлено
- Запущенному отсюда процессу Python сказано, чем кодировать вывод. Без
PYTHONIOENCODINGпотомок на Windows пишет в кодировке консоли, а родитель ждёт utf-8: текст теряется, а код возврата говорит, что всё прошло хорошо. Таких вызовов нашлось четыре, и теперь за каждым запуском процесса следитtests/test_conventions.py. (#17) translate --out --cleanубирает из дерева вывода сирот прошлого запуска. Переименованный в исходнике файл оставлял старое отражение, и сборка увозила его вместе со всем деревом. На живом корпусе в 1261 файл переименование давало 1262 файла, а с--cleanдерево вернулось к 1261. (#15)translate --out: отказ записи объясняется словами, а не пустым выводом и кодом 1. Запись стояла перед печатью отчёта, поэтому любая беда файловой системы уносила отчёт целиком. Теперь ошибка названа с файлом и причиной, проход доходит до конца и печатает отчёт, а команда, не записавшая дерево, возвращает ненулевой код и без--strict. (#11)- Помощник тестов, объявленный дважды. В тестах перевода
_rule_findingsстоял двумя копиями подряд: вторая молча заменяла первую, и первая была мертва со дня написания. Дубль снят, а за повторением теперь следит обход всего репозитория. (#8)
10.09.2026 – 0.100.0, 0.101.0
Добавлено
translate_unused --since: сироты ОДНОЙ правки. Поживший словарь отвечает на простой вопрос тысячами строк – на живом проекте 31 628 записей дали 3 297 сирот, и каждая чья-то старая правка, – а свои приходилось вылавливать по одному имени за вызов: девятнадцать вызовов на одну правку.--since <ревизия>(sinceу инструмента MCP) оставляет только ключи, которых проект больше не пишет нигде И которые встречались лишь в строках, снятых этой правкой поgit diff; на той же правке ответ – 18 строк одним вызовом. Ветка или коммит читаются от точки расхождения с HEAD до РАБОЧЕГО ДЕРЕВА, поэтому незакоммиченное тоже считается; диапазонA..Bпередаётся git как написан.--pruneрядом снимает ровно этот список: сужение – пересечение с сиротами всего проекта, поэтому щедро прочитанный diff не может стоить живого перевода. Ответ без отбора и безsinceтеперь честно говорит, чего стоит его чтение: оно текстовое, и список описывает весь накопленный словарь, а не правку.translate_unusedотвечает кратко и считает сирот по видам.compact=trueоставляет у записи только ключ, вид, файл и строку – чистке нужны места, а не переводы, и страница из шестидесяти полных строк стоила пять тысяч знаков ради девятнадцати нужных ключей, – а каждый ответ несётcountsпо всему отобранному множеству: объём чистки известен до чтения страниц.
Исправлено
- Языки проекта переводятся тем перечислением, которым они и являются.
ЯзыкиЛокализации: [Русский, Английский]доходили до английского дерева целиком лишь там, где словарь самого проекта был научен этому слову: ветка перечислений узнавала лишь часть классов, которыми дистрибутив описывает перечисления, а свойства языка описаны другим из них – иАнглийскийпереводился плоскостью имён по случайности (платформа знает такой термин), аРусский– ничем.ЯзыкПоУмолчаниюпо той же причине оставался данными и был не виден только потому, что эту строку потом переписывает переворот языков. Теперь ветка узнаёт все классы перечислений дистрибутива; то же молчание накрывалоПротоколБезопасности(Kafka) иВозможностимобильного приложения. Проверено целым деревом на живом проекте: английское дерево выходит побайтно прежним. - Локализованная строка говорит, где пишется ТЕКСТ перевода. Добавление
строкив элемент ЛокализованныеСтроки дописывает ключ во все готовые переводы значением языка по умолчанию, а заметка говорила лишь “замените его переводом” – будто руками, тогда какmeta_set_localization(set-localization) пишет все языки одним вызовом; теперь заметка его называет. Вызов же по САМОМУ файлу перевода отвергался словами “у вида ? нет секции для ‘строка’”: у перевода нет ни вида, ни секций элемента, и всякая проверка, спрашивающая его об этом, описывает несуществующий файл. Отказ – и у правки свойств тоже – теперь называет, что это за файл, к какому элементу он относится и каким вызовом пишется строка.
09.09.2026 – 0.97.0, 0.98.0, 0.99.0
Добавлено
translateсудит сам словарь: запись против платформы, литерал против своего ключа. Запись, пишущая член платформы так, как платформа не пишет его нигде (SeverityвместоImportanceсобытия), и именованный литерал, подстановки%{...}которого расходятся с подстановками ключа, теперь роняют строгий проход – каждый с написанием, которое надо поставить. Слово с двумя платформенными написаниями не судится.tools/parity_seed.py --quietпечатает только несогласные посевы, включая известные пробелы, и итоговую строку. Полный запуск это сотни строк[ok]ради одной цифры.code/dead-interpolation: удвоенный знак интерполяции гасит выражение. Запись"%%{Запрос}%"платформа читает как экранированный знак: выражение не вычисляется, и в значение уходит его ТЕКСТ –%{Запрос}%. Ни компилятор, ни линтер об этом не говорили, и поиск подстрокой на сайте молча не находил ничего, пока код не прочитали разработчики платформы. Замер на пробнике, скомпилированном платформой: неизвестное имя внутри%{...}и${...}компилятор называет (это контроль – модуль компилировался), а внутри%%{...}и$${...}молчит – для обоих знаков. Правило файловое, уровень – ошибка, автоисправление ставит то самое экранирование ("\%%{Запрос}%"); правильно экранированная запись замечанием не считается.--list-rules --format jsonотдаёт каталог правил машине. Текстовый список несёт параметры и причину отключения строками продолжения, и клиент, разбиравший вывод регуляркой по первой строке, их терял. Сама проза к тому же меняется с языком запуска. Ключ печатает те же записи, что отдаёт инструмент MCPlist_rules:id,tier,severity,off_reason,params. Панель правил расширения читает теперь его.- У команды
xbsl new-objectпоявился ключ--base. Базовый тип компонента интерфейса задавался только через MCP и LSP, из командной строки к нему было не подобраться – компонент приходилось доводить руками. Значение проходит те же проверки, что и у остальных поверхностей. yaml/property-shadows-module: свойство компонента названо как общий модуль проекта. Имя свойства перекрывает модуль во всём компоненте, и прежние обращенияМодуль.Метод()компилятор читает как обращение к члену значения свойства: применение сборки падает “Неизвестный метод”, стенд откатывается на прежнюю сборку, а жалобы указывают на файл компонента с настоящими именами методов – модуль выглядит сломанным, хотя он всего лишь скрыт. Правило называет совпадение в строке объявления свойства, в обеих орфографиях. Судится только общий модуль, достижимый по короткому имени – своя подсистема либо импортированная в yaml компонента; тёзка-справочник, тёзка-перечисление и тёзка-компонент не трогаются: такое имя употребляют в позиции ТИПА, и свойство его не перекрывает. Автоисправления нет намеренно: лечение – переименование, за которым тянутся разметка, парный модуль и обращения снаружи.- Правило называет величину, по которой судит, а список можно спросить про одно правило.
Раньше
--list-rulesиlist_rulesв MCP отдавали id, заголовок, тир, важность и признак “включено”, а сам порог жил константой в исходниках. Узнавали его опытом: код переписывали вокруг догадки и запускали линтер по всему проекту. Тело метода в шесть строк правило ловило, оно же в четыре молчало, и два полных запуска покупали число, которое инструмент и так знает. Теперь семь параметров объявлены там же, где правила ими пользуются:code/duplicate-method-body(min-lines),yaml/duplicate-subtree(min-nodes),style/line-length(max-length),code/parse-error(max-per-file),yaml/hint-too-long(limit, margin),security/hardcoded-secret(min-literal-length). С правилом едут действующее значение, умолчание, строка описания и переменная среды, которая значение переопределяет:XBSL_плюс идентификатор правила и имя параметра. Про одно правило теперь можно спросить отдельно –--list-rules --select code/duplicate-method-bodyиlist_rules(select=...)отвечают им вместо всего реестра. Неразобранное переопределение оставляет умолчание и говорит об этом. Запуск со сдвинутыми параметрами называет их в своей сводке: изменённый порог меняет находки. Пустой отбор теперь говорит, что под него не подошло ни одно правило. Прежняя строка про пустой реестр отправляла читателя искать сломанную установку. - Устаревшие записи списка принятых замечаний названы в ответе MCP, а
baseline_pruneих снимает. Сводкаlint_pathsговорилаbaseline_stale: 9и на этом замолкала. Какие именно девять, узнавали своим скриптом по файлу, отбирая записи по прозе их поляreason, а снять их из сеанса было нечем. Теперь записи едут вместе со счётчиком вsummary.baseline_stale_entries: путь, правило, сообщение, количество, причина – так же, как их несёт json CLI. Новый инструментbaseline_pruneснимает именно их, сохраняет порядок и формат файла и отвечает каждой снятой записью;dry_runпоказывает, что ушло бы. Снятие остаётся отдельным действием: обычная проверка файла не трогает. meta_set_localization/xbsl set-localization: одна строка локализации во все языки сразу.meta_add_localizationдобавляет ЯЗЫК, а на СТРОКУ инструмента не было: заголовок набирали в элементеЛокализованныеСтрокии ещё раз в его английском двойнике, и файлы расходились молча – сверить их было нечем, кроме глаз. Теперь один вызов пишет текст языка по умолчанию в сам элемент, а каждый другой – в свойЛокализация/<Код>/<Имя>.yaml, и уже существующую строку правит на месте. Язык, названный без файла перевода, отвергается с указанием инструмента, который язык заводит; язык, о котором вызов молчит, всё равно получает строку значением языка по умолчанию и с заметкой – чтобы ни один перевод не остался на ключ короче. Секция берётся та, в которой ключ уже живёт (у нового –Строки), и принимается в любой орфографии.translate_unused: проход по сиротам словаря стал инструментом MCP, а не только флагом. Что словарь всё ещё говорит, а проекта уже нет, добывалось только из консоли: агент, только что удаливший компонент, был вынужден выходить в оболочку.filterсужает ответ до имён ИМЕННО ЭТОГО компонента, а не всей истории проекта, аprune– по умолчанию выключенный и намеренно названный отдельно от перечисления – снимает ровно ту страницу, которой инструмент отвечает. В консоли--staleпринимается как второе имя--unused.- Страница говорит, чего в ней нет.
translate_gapsотвечалtotal: 72рядом с ровно пятьюдесятью строками и обрезания ничем не помечал; собранный по такой странице словарь оказался короче на двадцать две записи – их нашёл строгий проход уже после слияния. Теперь каждый страничный ответ перевода несётtruncated,shown,remainingиhintсо следующимoffset,limit=0для всего списка и – у пропусков –--missing, который записывает весь остаток файлом. - Посевы паритета покрывают 85 правил 169 посевами (было 120 посевов на 62 правила). Пачка легла на правила, судящие текст по словарям платформы: присоединённые таблицы, поля и отбор динамического списка, режим совместимости, значение типа “объект”, слот под список, длина подсказки, всплывающий компонент в разметке, привязки и вычисляемые свойства, поля строки списка и структуры проекта, аннотации доступности с клиента, параметр в литерале запроса, имена перечислений, общих модулей и вида в имени. Английский близнец каждого посева написан руками; известных пробелов стало три – два за каталогом членов, третий за словами русского языка в стандарте именования.
Изменено
- Итог проверки называет ключи, которыми смотрят и снимают устаревшие записи списка
принятых. Итоговая строка несла только число таких записей, и сделать с ним было нечего:
чтобы узнать, что именно устарело, звали MCP
lint_pathsили вычитали живые находки из ключей файла руками. Теперь под итоговой строкой печатаются--stale-baselineи--prune-baseline. Когда устаревших нет или их только что перечислили этими ключами, подсказка молчит. - Устаревшие записи списка принятых печатаются вместе с причиной. Поле
reasonзаписи – это проза, которую человек написал о намеренном исключении, а перечисление печатало путь, правило и сообщение без неё. Теперь причину печатают строкой под записью и--stale-baseline, и--prune-baseline. Чистка говорит, сколько снятых записей её несли: после коммита этот текст остаётся только в истории git.
Исправлено
- Локальная переменная от статического члена платформенного типа типизируется.
исп Поиск = ЖурналСобытий.Найти(...)и событие, прочитанное из результата, оставались без типа: обход объявлений не читал голое имя как тип, и член такой переменной уходил в плоский словарь – и в любую запись словаря, написанную против платформы. Теперь обход держит вне ярлыка типов каждое имя, объявленное методом, а остальные читает как типы; три корпуса отвечают теми же находками. code/local-method-cross-componentвидит английское дерево: коллекция компонентов искалась только по русскому имени, иComponents.X.Y(...)не судился вовсе. Английское написание – из словаря платформы. Найдено посевом паритета.yaml/no-expression-in-literalвидит английское дерево: типы, требующие литерала, были перечислены только по-русски, иType: AbsoluteFontс выражением вSizeпроходил. Оба написания теперь берутся из пар типов. Найдено посевом паритета.- Переводчик переименовывает
Имядескриптора подсистемы вместе с её каталогом. Значение оставалось данными, а каталог получал токен, и на переведённом дереве ни один импорт, называющий подсистему, её не находил (yaml/localization-missing-importсообщало про импортированную ссылку). Найдено посевом паритета. - Посевы паритета: ещё 74, покрыто 129 правил – вычислимый контроль доступа, ссылки через границу подсистем, локализованные строки, ресурсы, объявления, число аргументов, условия, имена, идентификаторы, описание проекта.
yaml/choice-needs-static-listвидит английское дерево. Правило искало компонент и его примитивные типы по русским написаниям (ВыборЗначения<Строка>), а ключ списка – по одному имени: на переведённом проекте оно молчало о находке и ругалось там, где список есть. Теперь написания компонента, примитивов иМассивберутся из словаря платформы, а ключ списка канонизируется схемой интерфейса (ChoiceList).- Правила про ресурсы и про закрываемые видят английское дерево. Обе слепоты нашли посевы
паритета, и обе были одного рода – платформенное слово знали только по-русски.
code/resource-bare-nameиcode/unknown-resourceискали литералРесурс{...}буквально, а переведённый модуль пишетResource{...}: пара написаний теперь берётся из словаря платформы.code/unclosed-resourceобрывал вывод типа на первом же члене (.Выполнить()против.Execute()), потому что каталог хранит членов по-русски, – теперь имя типа и имя члена сверяются в обеих орфографиях, а непарный член по-прежнему заканчивает вывод молча. - Английский проект получает английские имена и там, где их придумывает сам
инструмент. Стандартный реквизит (
Наименованиесправочника,ПериодиРегистраторрегистра) дополнялся по-русски и доезжал до сгенерированных форм (Name: Наименование,Value: =Object.Наименование), потому что языковой проход бережёт имена полей как авторские. Теперь дополнение пишется в написании ФАЙЛА, вместе с реквизитом иерархии и фасетом его типа (Tasks.Reference?), а значение интерфейсного перечисления берётся из своего словаря (WidthInColumns: Singleвместо русского значения). Фасет добавлен и в общий перевод выражений типа: после точки стоит фасет, а словарь свойств зовёт то же слово иначе. - Тип нового элемента читается так же, как база компонента.
meta_add_fieldиop_add_fieldразворачивают разметочные экранирования в значении типа (Массив<Число>становитсяМассив<Число>), отвергают то, что типом не является, и пишут тип в написании ПРОЕКТА (Numberв русском проекте ложитсяЧислом). Составной тип со списком альтернатив по-прежнему проходит целиком. Значение словарной секции (строка локализации) под эту проверку не попадает: там амперсанд и точка с запятой – законный текст. - Один нечитаемый yaml больше не хоронит отчёт под призрачными находками. Файл, который
не разобрался, выпадал из модели проекта целиком, и объявленный им объект становился
неизвестным именем для всех сразу. Замер на живом проекте: сломанный компонент давал
239 находок вместо 49 (175 из них
code/undefined-name), сломанный справочник – 180 вместо 50 (63yaml/unknown-type, 34code/undefined-name, 31query/unknown-table, 2code/unused-import). Теперь такой объект известен по имени и при этом НЕЧИТАЕМ: парный модуль правилоcode/undefined-nameне судит (его область неизвестна, а не пуста), корень типа и таблица запроса неизвестными не зовутся, импорт подсистемы, в которой объект лежит, не зовётся неиспользуемым, а объявления@ДоступноСКлиентапарного модуля – невостребованными. Настоящая находка остаётся одна:yaml/validна самой поломке. - Проход по сиротам читает комментарий так же, как его пишет переводчик. У него было
своё регулярное выражение, снимавшее с маркера один пробел: документирующий комментарий
(
///) возвращался со слипшейся косой чертой, строка##– с решёткой, а блочный комментарий не читался вовсе – и любая пара, записанная с такого комментария, была бы объявлена сиротой, а это ровно та ошибка, на которой действует--prune. Теперь разбор берётся изcode.comment_payloads– функции, которую вызывает сам переводящий проход. Имя ищется и в ИМЕНАХ ФАЙЛОВ: папка и файл проходят через ту же плоскость имён. - Читатель словаря видит ключ в явной форме yaml. Длинный ключ выгрузка пишет как
? ключна одной строке и: значениена следующей, и этого никто не выбирает – в живом словаре реального проекта в такой форме лежат два литерала. Они были невидимы и таблице, и проходу по сиротам, и писателю, который добавил бы ключ, уже лежащий в файле; теперь запись и снятие правят обе строки как одну запись. meta_add_formпишет заголовки сгенерированной формы через словарь проекта. Сгенерированная форма приезжала с заголовками-литералами – своим и каждой колонки таблицы, – а на двуязычном проекте это восемь находокconventions/untranslated-visible-literalна один объект, которые переписывали руками сразу после генерации. Что писать вместо литерала, подсказали исходники, а не вкус: из 303 колонок таблиц живого проекта заголовок несут 300 (три оставшиеся – колонки-картинки), каждый из них – ссылка$Словарь.Ключ, а ключ – имя самого поля. Значит, пишется ссылка – и нужные ей ключи в той же операции добавляются в словарь подсистемы и в переводы, которые у словаря уже есть: ссылка на необъявленный ключ хуже литерала, применение сборки падает и стенд откатывается. Словарь берётся тот, что лежит рядом с объектом (чужому подсистемному понадобился быИмпорт, которого у формы нет), у проекта должно быть заявлено два языка локализации, а имя, занятое в словаре ШАБЛОНОМ, остаётся литералом – ссылка ищет ключ только среди строк. Без такого словаря всё как раньше.meta_new_objectпишет базу компонента в той орфографии, в которой проект пишет типы. Ключbaseдокументирован английскими словами, поэтомуbase="Group"передать естественно – а в русский проект уезжала строкаТип: Group, которую каждый раз правили руками: линтер на это молчит, компилятор заговорил бы только при деплое. Теперь база пишется на языке проекта в обе стороны, а принадлежность базы к ФОРМАМ – тем, которым нужна обёртка шаблона формы, – определяется по одной орфографии, так что английская форменная база больше не теряет обёртку.meta_set_component_propertyпишет блоком и однострочный вложенный фрагмент. Inline после ключа теперь уходит только FLOW-коллекция, а фрагмент видаКлюч: значениестановится вложенным блоком. Записанный inline, он давалНастройкиРедактирования: Тип: НастройкиРедактированияПереключателя- такое yaml не читает вовсе, и правка отвергалась сообщением парсера “mapping values are not allowed here”, а блок дописывали руками. Случай не редкий: у настроек редактирования переключателя (флажок в ячейке таблицы) своих свойств нет вовсе, и блок из одной строки - единственная форма этого значения.- Экранированный
baseчитается как скобки, которые он обозначает.base="Форма<Булево?>"уезжал в yaml как пришёл: файл выглядит готовым, а мусор компилятор встречает только при деплое. Экранирование приезжает от КЛИЕНТА инструмента, а не из рук человека, поэтому оно разворачивается, а не сообщается; всё, что осталось от испорченного значения после этого и не является выражением типа, отвергается, а не пишется в файл. yaml/bare-object-valueсудит и английскую запись компонента. Таблица компонентов со свойствами типа “объект” строилась по русскому имени, иТип: Надписьнаходилось, аType: Label– нет: на переведённом дереве голое слово в значении не сообщалось никогда. Имя компонента кладётся в таблицу в обоих написаниях, как это давно делает соседняя таблица того же модуля.code/unknown-structure-fieldсудит член, написанный латиницей. Оговорка досталась правилу от соседей по членам, где она защищает русский каталог платформы; здесь набор членов даёт объявление самого проекта – в том же написании, что и обращение, – и переведённый проект не судился вовсе. Латинский член, которого объявление не несёт, теперь сообщается; поле сериализационного контракта (access_token) объявление несёт, и оно молчит.- Протокол объекта распознаётся в обоих написаниях.
ПолучитьТип,ВСтрокуиПредставлениебыли записаны только по-русски, иcode/unknown-row-fieldвыдавал ошибку на законномLine.ToString(); английскую половину даёт словарь. Там же получили пары собственные члены строки динамического списка (Данные,Ключ) – каталог хранит их по-русски, а переведённый модуль пишетKey. naming/enum-vid,naming/module-suffixиnaming/kind-in-nameчитают английское имя. Слово вида в русском имени стоит впереди, а в английском – в хвосте (ApplicationType,StuckTasksReport), и постфикс окружения общего модуля в английском имени пишется парой из словаря (ExchangeClientAndServer). Все три правила искали только русское написание и на переведённом дереве молчали; английская пара берётся из словаря, а форма, которой словарь не называет (множественное число вида, слово “регистр”), не судится, а не выдумывается. Для хвоста у сообщений своя формулировка – “заканчивается”, а не “начинается”.code/bound-property-assignсводит английскую пару файлов. Ключи разметки правило хранит по каноническому имени, а свойство из модуля искало по написанию из кода: параHeight: =...в yaml иКомпоненты.Блок.Height = 640в модуле не находила друг друга, и переведённая пара не судилась вовсе. Имя свойства из кода сворачивается к каноническому перед поиском.
08.09.2026 – 0.95.0, 0.96.0
Добавлено
- Находка
yaml/list-scroll-without-loadingчинится быстрым исправлением. Правило несёт автоисправление: значение меняется наПодгрузкаПриПрокруткев той же орфографии, что и у заменяемого, с сохранением квалификатора. Раньше в редакторе предлагалось только внести находку в список принятых. yaml/list-scroll-without-loading: список прокручивают, а прокрутка ничего не догружает.Навигация: Отсутствуетзначит не “без пагинации”, а “без догрузки”: строки приходят одной порциейРазмерСтраницы, и хвост данных недостижим – документацияНавигацияВСпискеговорит это прямо, а компилятор молчит. Судится пара “прокрутка обещана (ПрокруткаПоВертикалинеЛожь) и навигацияОтсутствует” у компонентов, которым ui-схема даёт свойствоНавигация; выражение в значении и список, который прокрутку не обещает, не трогаются.
06.09.2026 – 0.94.0
Добавлено
code/param-redeclared: локальнаязнч/пер/испс именем параметра своего же метода. Компилятор отвечает “Переменная с именем X уже определена” только при применении сборки, и стенд откатывается; линтер называет совпадение в строке объявления, вложенные блоки включительно, в обеих орфографиях. Переменные цикла ипоймать, параметры и тела лямбд не судятся: в корпусах их нет.docs_symbolиdocs_pageотвечают кратко или одним разделом. Страница типа – десять тысяч знаков: конструкторы, каждое свойство, списки унаследованного, – а вопросу “что это за страница и о чём она” хватает шапки:brief=Trueотдаёт краткое описание и имена разделов,section="Свойства"– шапку и один раздел (принимается и английское имя раздела); неизвестный раздел отвечает перечнем имён на выбор.- Посевы паритета покрывают 62 правила 120 посевами (было 41 посев на 23 правила). Правила, судящие текст по словарям платформы, – свойства реквизитов, компоненты форм, окружение модулей, язык запросов, размеры и компоновка, – несут теперь русский случай и английского близнеца, написанного руками; четыре известных пробела помечены причинами: два за словарём членов, два за переводчиком.
Изменено
meta_add_fieldназывает заведённую секцию и указывает на соседнюю (то же уadd-fieldи запроса LSPxbsl/metaAddField). Данные регистра лежат вИзмеренияиРесурсы, и реквизит, запрошенный у регистра с ресурсами без реквизитов, молча заводил новую секциюРеквизитыв конце файла – поле потом переставляли руками вместе с UUID. Секция заводится по-прежнему, ноnotesговорят об этом и называют вид поля (здесьресурс, и наоборот), который положил бы элемент рядом с существующими полями; элемент существующей секции, как и раньше, встаёт в её конец – теперь это держит тест.
Исправлено
- Переводчик пишет
.Ссылкафасета проекта словомReference(Строчка.Ссылка.ЗагрузитьОбъект()!->Line.Reference.LoadObject()!): приёмник, типизированный фасетом объекта проекта – объявленным, выведенным или загруженным из ссылки, – несёт слово фасета, приёмник без типа – когда цепочка дальше зовётЗагрузитьОбъект; свойствоСсылканадписи и картинки остаётсяLink, а квалифицированная запись словаря по-прежнему отвечает первой. - Умолчание, квалифицированное своим перечислением, переводится целиком
(
ЗначениеПоУмолчанию: Состояния.Открыт) там, где соседТипназывает перечисление проекта, – форма, о которой сообщаетyaml/enum-default-value, а английское дерево не могло её нести, пока значение оставалось русским. Автоу свойства с объединённым типом переводится (МаксимальнаяШирина: Авто,Высота: Авто,Подсказка: Авто->Auto): значение, совпадающее с членом объединения свойства, – этот член в написании платформенной пары типов, а не данные.yaml/ref-needs-nullableраспознаёт ссылочный тип и по английскому написанию фасета (Applications.Reference): yaml-ветка держала фасетСсылкав регулярке и в проверке, и переведённое описание проходило без замечания.code/member-kind-mismatchсудит вид члена и в английском написании типа и члена (TimeZone.Currentбез скобок): таблица видов ключуется русскими именами каталога (ЧасовойПояс.Текущий), обе стороны теперь приводятся к ним через словарь.
05.09.2026 – 0.93.0
Добавлено
meta_add_formумеет форму записи регистра сведений (forms=["record"]). У регистра нет формы объекта – правится его ЗАПИСЬ, и формуФормаЗаписи<Регистр.Запись>с полями по измерениям и ресурсам приходилось писать руками; заодно отказ по форме объекта теперь называет форму записи, а не одну лишь форму списка.meta_new_objectпринимает базовый тип компонента интерфейса (base). Заготовка всегда наследовала форму с шаблоном, а самый частый базовый тип живого проекта –Группа(31 против 7 у голой формы): весь блокНаследуетпереписывался руками.yaml/slot-needs-list(тир D, ошибка) – слот, описанный списком, получил один компонент. Компонент, записанный подСодержимое:без дефиса, – это не список из одного: yaml разбирается, ключи на месте, а применение отвергает разметку уже на сервере и откатывает проект на прежнюю сборку. Форму значения судит ui-схема, а не имя свойства: у шаблона формы то жеСодержимоезаконно держит один компонент.
04.09.2026 – 0.92.0
Добавлено
code/member-kind-mismatch(тир D, ошибка) – метод стандартной библиотеки, прочитанный как свойство, и свойство, вызванное как метод. Член существует, неверна форма обращения: применение отвергает проект сообщениемUnknown constantлибоUnknown method, и ни одно из них не называет ни вида члена, ни лечения.code/unknown-form-component(тир D, ошибка, файловое) – обращение к компоненту, которого нет в разметке формы.Компоненты.X– статическая карта из разметки, и имя без пары в ней не существует: применение отвергает проект, а до этого не видит никто – имя переживает компонент, который вынесли из разметки и не вернули.code/server-annotation-in-client-module(тир D, ошибка) – зеркало проверки клиентских аннотаций. Модуль сОкружение: Клиент, несущий@НаСервере, компилируется для сервера, где типа модуля нет, и применение отвергает каждый такой метод сообщением, в котором нет ни окружения, ни имени модуля.xbsl translate --unusedназывает пары, которых проект уже не использует;--pruneих снимает. Удаление кода оставляет за собой имена и строки комментариев, и сказать об этом было некому: строгий проход судит непокрытое, а таблица записей показывает, где пара объявлена, а не используется ли она.- Отчёт
xbsl translateговорит, когда словарь отстал от исходников – сколько файлов правились после него и какой из них позже всех (в json – полеdictionary_behind). Сверяются времена правки, поэтому отметка остаётся примечанием и вердикта не меняет.
Исправлено
- Тень имён проекта пропадала на файлах с CRLF. Регулярка, собирающая имена yaml, кончалась якорем конца строки, а в многострочном режиме он совпадает перед переводом строки. Пустая тень – это ложные находки правила уровня ошибки: объект проекта, названный как тип платформы, объявлялся неизвестным членом.
- Неизвестное значение
kindотвергается, а не отвечает пустым списком. Имя секции во множественном числе не совпадало ни с чем, и ответ приходил пустым – неотличимо от “словарь покрывает всё”. Запуск, поверивший такому ответу, оставлял пробелы до строгого прохода. translate --setназывает перезаписанные пары. В отчёте был только счётчик, и какие именно ключи получили новое значение, оставалось искать сравнением словаря.- Строка локализации со знаком, значимым для yaml, больше не ломает файл. В кавычки берётся то, что без них не прочиталось бы обратно, а обычная фраза остаётся без кавычек. Новая строка дописывается и в готовые файлы перевода значением языка по умолчанию.
- Первое измерение регистра занимает место заглушки, а не встаёт рядом с ней, а
Длинастандартного поля проверяется инструментом: предел платформы ловил линтер следующим запуском, по файлу, который инструмент уже написал. yaml/validназывает тернарное выражение с пробелами. YAML читает такое началом вложенного отображения, и жалоба приходит на строку, где отображения нет.- Клиентский общий модуль ловится у любого серверного потребителя, а не только у HTTP-сервиса, а три проверки окружения подняты до ошибки: матрицу проверили компилятором, и каждый промах – отказ компиляции с откатом проекта.
- Номер сборки записывается в индекс только своей версии. Извлечение под чужим именем дописывало, что каталог держит сборку версии, из которой он никогда не брался.
02.09.2026 – 0.89.0, 0.90.0, 0.91.0
Добавлено
meta_add_fieldзнает стандартные реквизиты.НомериДатадокумента,Код,НаименованиеиВладелецсправочника судятся своим классом дескриптора – как их уже диспетчеризовалmetadata_schema, – поэтомуДлина,Уникальностьи блокАвтонумерацияпринимаются, а не отвергаются как неизвестные свойства обычного реквизита, иtypeможно не указывать там, где класс его задаёт. Значения свойств принимают вложенный блок словарём или ключом через точку и список последовательностью (CLI--prop, LSP и MCP одинаково); блок класса, которого метамодель не описывает, отвергается по имени как известное ограничение.meta_set_field_propertyпринимает те же формы и заменяет вложенный блок целиком.- У
lint_pathsпоявился параметрroot, как у инструментовmeta_*. Относительныеpathsиbaselineсчитаются от корня вызывающего, а не от рабочего каталога сервера. Сессия в git worktree больше не проверяет чужую рабочую копию, принимая её чистый ответ за свой. Находки несут абсолютные пути, сводка называетroot. code/foreign-not-public(тир D, error, по проекту) – сторона кода дляyaml/foreign-not-public. Обращение из модуля к элементу чужой подсистемы сОбластьВидимости: ВПодсистеме(или без свойства – это умолчание) компилятор отвергал на деплое, а линтер молчал:code/missing-importнепубличную цель нарочно не судит. Судятся позиции типов и корни цепочекМодуль.Метод(); модуль проекта вне подсистем – чужой для всех.xbsl baseline add <пути> --rule <правило> [--reason ...]дописывает в список принятых только новые находки одного правила: новый файл встаёт на своё место, остальное не двигается, чужие причины не трогаются, повтор ничего не меняет.--format jsonотдаёт{baseline, added, findings, written}. Сохранение бережёт переносы строк и BOM файла, новый файл пишется с LF.- У всех инструментов MCP
meta_*появился параметрroot– корень вызывающего: относительные пути считаются от него, а не от рабочего каталога сервера, ответы несут абсолютные пути и полеroot. - Посевы паритета: 27 новых посевов на 14 правил, судящих по словарям платформы; английский близнец посева пишется руками по данным, вывод переводчика сверяется третьим деревом.
Изменено
- Правила видимости читают биндинги и квалифицированные имена. Пробник, применённый на
сервере, отверг биндинг на непубличный элемент чужой подсистемы, квалифицированный биндинг
Подсистема::Элементи квалифицированное обращение из кода с тем жеТип "..." недоступен из-за модификатора видимости, что и позиции типов, – поэтомуyaml/foreign-not-publicсудит корни цепочек биндингов (за вычетом того, что объявляет парный модуль) и квалифицированные имена в биндингах и позициях типов, аcode/foreign-not-public– квалифицированные имена, по названной в них подсистеме. Правила импорта квалифицированную запись по-прежнему не трогают: импорт ей не нужен. - Отчёт
xbsl translateзаканчивается вердиктомГОТОВО/НЕ ГОТОВО: токенов N, фраз M– хвост вывода больше не читается как успех при сотнях пропусков; в json добавленready, код возврата прежний. - Инструменты перевода отказывают, если словаря рядом с корнем нет, и называют, где его
ищут (и где он лежит, если ниже корня);
translate_gapsотдаётdictionary. CLI так же:--gapsбез словаря отказывает, отчёт пишетdictionaryв JSON. - Список принятых замечаний судится только в пределах запрошенных путей. Записи чужих
файлов считаются непроверенными, а не устаревшими: запрос двух файлов через MCP отвечал
“0 погашено, 76 устаревших” на чистом проекте.
baseline_not_checkedразбит на_rulesи_paths. - Сводка называет, чем судили:
engine,pluginsс версиями иrules {active, total, plugin}в json CLI и в ответах MCP, а в текстовом выводе – отдельная строка с тем же набором. - Экстрактор терминов кладёт члены классов Constants под их тип и дополняет
typesпарами из классов – чтобы они заработали, данные нужно пересобрать.
Исправлено
- Закрыты два пробела паритета:
yaml/unexpected-type-argumentиyaml/enum-needs-nullableсудят английское дерево так же, как русское. Первое отсекало только по ключуТип:, не канонизировало ни компонент, ни голову типа и сочло бы английское умолчание чужим; теперь ключ, компонент, свойство и голова канонизируются, а аргумент сравнивается с умолчанием имя за именем в любом написании. Второе узнавало поле ввода по рукописномуInputField, которого не пишет ни один сериализатор: платформа пишетEdit, и написания берутся из данных.code/reserved-nameтеперь сообщает и оTypeс заглавной – живой apply отверг его так же, какТипиtype. Посевов паритета 41, расхождений 0, известный пробел остался один (каталог членов). - Экстрактор терминов заполняет пробелы общей таблицы термами, заявленными классами. У
встроенного реквизита кода не было общего написания:
Code/Кодзаявляют термом десяток классов, а чтение по соседству отвергаетCodeкак английского кандидата – так называется атрибут class-файла. Без парыyaml/unknown-attribute-propertyтерпело ключи реквизита кода у любого реквизита английского дерева с латинским именем –Lengthу числа не сообщалось. Заявленный терм отвечает только там, где соседство ничего не решило, – устоявшиеся написания на месте; данные, пересобранные с исправлением, пару несут. - Имя внутри выражения типа в коде переводится как тип. Обход токенов не отличал типовую
позицию от обращения к члену, и
.Ссылкав типе параметра, объявления, конструктора, приведения или аргумента типа уходила свойствомLink, а не фасетомReference– английское дерево не компилировалось, а посев паритетаcode/unknown-ns-objectпришлось пометить известным. Границы выражений типа теперь даёт парсер, и имя внутри них разрешается так же, как тип в yaml. - Член локальной переменной без записанного типа берётся по выведенному типу
(конструктор, приведение, литерал), написание – из таблицы владельца с проходом по базовым
типам (
Соответствие.Удалить–Remove);code/unknown-memberпринимает написание предка. - Умолчание поля, типизированного перечислением проекта, переводится и в свойствах
компонента интерфейса, тип читается как в
yaml/enum-default-value. - Две слепоты на английском дереве:
code/global-unavailableне узнавал глобальное имя в английском написании,yaml/unknown-typeне читал ключType:.
30.08.2026 – 0.86.2, 0.87.0, 0.88.0, 0.88.1, 0.88.2
Добавлено
- Каталог типов пополняется тем, что справка не описывает. Дистрибутив описывает stdlib дважды, и в разметке сервера LSP типов больше: 16 типов Std жили только там, включая всю ветку Избранного, обращения к которой читались как необъявленное имя. Состав берётся из разметки, русские написания членов – из объявлений в классах поставки.
classcode.declared_terms– пара, прочитанная вместе с полем, в которое её кладут. Вид члена говорит ИМЯ статического поля (LINK_PROPERTY_TERM,SWITCH_SCREEN_METHOD_TERM): по самой паре свойство от метода и метод от его параметра не отличить.yaml/duplicate-key(тир A, error) иcode/duplicate-annotation(тир C, error) – дубли, которые раньше показывала только серверная компиляция. Скалярный ключ, заданный в одном узле YAML дважды, загрузчик молча схлопывает – последнее значение побеждает, слитый узел проходит все проверки схемы, и первым падал деплой; правило читает composed-дерево, где дубли ещё видны, помечает повтор и называет строку первого вхождения (ключ слияния<<и нескалярные ключи не судятся). Повторная аннотация у одного объявления – ошибка “Annotation … is already placed” – тоже была видна только на деплое.- Три правила объявления динамического списка.
yaml/dynlist-joined-table-param(error) – параметры и биндинги в присоединённых таблицах: отказ списка в рантайме при молчащем компиляторе;yaml/list-form-needs-dynlist(error) –ФормаСпискас массивной таблицей без динамического списка: пункт навигации молча исчезает;yaml/dynlist-filter-disabled(warning, проектное) – выключенный отбор, включаемый парным модулем: гонка первого показа, первый кадр показывает всю таблицу. - Комбинации свойств, половину которых платформа молча не рисует.
yaml/badge-column-image(warning) –Изображениеу колонки сВид: Значок: значение рисуется тегами-пилюлями, а картинка задокументирована только дляВид: Картинка;yaml/value-choice-title(warning) –ЗаголовокуВыборЗначенияс явным видомПереключательне рисуется, и поле остаётся без подписи;yaml/popup-in-markup(warning, проектное) – всплывающий компонент, сырой тип или проектный наследник через замыкание поНаследует, размещён в yaml-разметке: содержимое рисуется в строке формы до открытия окна, лечение – собирать окно кодом (новыйВсплывающийКомпонент+ОткрытьВоВсплывающемОкне);yaml/col-width-needs-no-stretch(info, выключено по умолчанию) – числовая ширина колонки таблицы без явногоРастягиватьПоГоризонтали: при растягивании ширина работает как доля, а не пиксели – сосед семьиsize-needs-no-stretch, включается точечно при симптоме на экране. yaml/enum-default-value(тир D, error, проектное) иyaml/event-property-type(тир D, error).ЗначениеПоУмолчаниюполя с типом перечисления проекта обязано быть голым именем объявленного значения: запись с именем типа (ВидимостьМетки.Невидимая) и несуществующее имя линтер прежде пропускал, а сборка отвергала их только при применении (“Неизвестный элемент перечисления”); у английского дерева ловится и русское значение, оставленное переводчиком при английских элементах. Тип свойства события журнала вне закрытого списка платформы – перечисление проекта отвергает серверная компиляция ценой деплоя; список берётся из метамодели, в сообщении – допустимые типы и совет писать вариантные значения строковыми кодами с перечнем вОписаниесвойства.code/load-object-unwrap(тир D, warning) иcode/image-binding-server-call(тир D, info, проектное) – данные приезжают не так, как читается по коду. Форс-разворот “!” результатаЗагрузитьОбъект()у ссылки, взятой из поля другой записи или строки табличной части, – висячая ссылка после физического удаления роняет весь обход, результат нужно проверять на Неопределено. Биндинг свойстваИзображениес вызовом, разрешающимся – напрямую или транзитивно – в серверный метод: картинка приезжает отдельным серверным вызовом после отрисовки и перезапрашивается при каждой перерисовке, лечение – поле присоединённой таблицы либо клиентские данные.code/permission-right-not-computable(тир D, error, проектное). Право, выданное обработчиком вычисления разрешений, должно быть объявлено вычислимым в yaml сущности – иначе сборка применяется, а пересчёт разрешений падает уже в рантайме; права собираются из конструкторовРазрешениеДоступатранзитивно по вызовам проекта, делегирование в общий модуль прав показывается с привязкой к сущности.
Изменено
- Образцы тестов правил и примеры в документации переведены на словарь демонстрационного проекта (0.88.1). Имена в примерах должны читаться сами по себе, а не отсылать к чужому решению. К тому же словарю заодно приведены таблицы правил обоих изданий.
- Описание пакета называет перевод, MCP-сервер и расширение – и стало английским. Сводка
на карточке PyPI перечисляла линтер, LSP, документацию и создание метаданных – набор, от которого
инструментарий уже ушёл, – и была единственной русской среди соседних пакетов, хотя
возглавляет английский README. Ключевые слова пополнены
mcpиtranslation. yaml/missing-importчитает и корни цепочек в биндингах разметки. Обращение=ЧужойМодуль.Метод()из свойства-биндинга достигает чужой подсистемы так же, как позиция типа, но без строки импорта отказ приходил только серверной компиляцией ценой деплоя; всё, что объясняет имя само по себе, – объявления этого yaml, парного модуля, неявные имена платформы – вычитается.yaml/empty-group-sizedловит и размер-биндинг (Высота: =...) у пустой группы безИмя. Безымянная распорка с вычисляемым размером выглядит как пустая группа и молчала; именованные пустые контейнеры, наполняемые из кода, не флагуются.
Исправлено
- Умолчание поля-перечисления переезжает вместе со своим перечислением (0.88.2). Метамодель
типизирует
ЗначениеПоУмолчаниюобычным объектом, поэтому имя элемента оставалось русским рядом с переведённым перечислением, и сборка отвергала пару ошибкой “Неизвестный элемент перечисления” – видно это было только при применении. Судится узко: тип поля должен быть голым именем проекта, а значение – словом, которое знает словарь. --data-dirне доходил до параллельных рабочих процессов. Закреплённый корень живёт в глобальной переменной процесса, а порождённый процесс стартует без неё и брал данные установленного пакета. Проверка читала не тот набор, о котором её просили, и молчала об этом.
28.08.2026 – 0.83.0, 0.84.0, 0.85.0, 0.86.0, 0.86.1
Добавлено
yaml/computed-binding-assigned(тир D, warning, проектное). Каждый экземпляр компонента связывает свойство вычисляемым выражением, а компонент присваивает это свойство в своём модуле – на присваивании платформа падает (IllegalStateException) при каждом срабатывании этого кода. Сужения выведены разведкой: именованный аргумент – не присваивание, а экземпляр из кода, связь голым путём, литерал или экземпляр без связи делают присваивание законным – защищённый компонент из живого корпуса остаётся в тишине.yaml/inline-command-name(тир A, error). Команда, объявленная прямо в разметке (инлайновый фрагмент командного интерфейса или команда-свойство), не может нестиИмя: платформа отвергает узел на применении – “Имя команды разрешено задавать только в элементах проекта типа фрагмент командного интерфейса” – и стенд откатывается, то есть дефект стоил цикла деплоя. Фрагмент ОТДЕЛЬНЫМ элементом проекта пропускается целиком: там этот ключ и есть смысл. Оба написания компонентов-команд берутся из словарей платформы.yaml/localization-missing-import(тир D, error, проектное). Неквалифицированной ссылке$Словарь.Ключ, чей словарь лежит в другой подсистеме, нужна эта подсистема в секцииИмпортТОГО ЖЕ yaml – импорт в парном модуле разметку не покрывает, и применение отвергает узел как неимпортированное пространство имён. Правило повторяет правила разрешения из документации: локальный словарь побеждает, импортированная подсистема разрешается, квалифицированная форма$Подсистема::Словарь.Ключработает без импорта и не трогается, кандидаты – только публичные чужие словари.translate_setпринимает пачку файлом. Новыйedits_file(MCP) передаёт сотни записей без килобайтов экранированного JSON в аргументе, а--set(CLI) читает те же два формата: yaml самого словаря – секцииtokens/phrases/literals, те же кавычки, пустое значение снимает запись – рядом со списком JSON[{key, value, kind}], который отдают скрипты. Файл без единой записи отвергается, а не читается как “менять нечего”.- У
translate_gapsпоявился компактный режим. Сcompactв строке только{key, kind, count}– рабочий список, который и нужен переводчику; полная страница из сотен пропусков с местами и подсказками не влезала в ответ инструмента. tools/parity_seed.py– посевная проверка паритета двух написаний. Прежний замер сравнивал счёт находок на русском дереве и на его переводе, поэтому не видел правило, у которого счёт нулевой с обеих сторон. В этой тени и жилstructure/xbsl-pair: он сообщал о каждом английском модуле порождаемого типа, а ни одно считаемое дерево такого не несло. Теперь проверка сеет свой случай сама – маленькое русское дерево и вердикт, который правило ему должно. Английский близнец берётся из собственного переводчика инструментария, а не из второй заготовки, поэтому проверяется то самое написание, которое инструментарий порождает. Вердикт называет виноватую сторону и её промах,en-missesилиen-invents: таблица без английского написания заставляет правило пропускать, а без русского прочтения – выдумывать. Посев, переставший сеять свой случай, даётstale, а не проходит молча, и весь каталог идёт вместе с тестами (tests/test_parity_seed.py). Дыру, которую сегодня не закрыть, сеют с причиной черезknown=: она даётknown (...)вместо провала, а как только начнёт сходиться – даётfixed!и роняет тесты, чтобы отметка не пережила дыру. Первая такая уже записана:code/unknown-memberнамеренно пропускает латинские написания членов, и словаря членов пока не хватает, чтобы это снять.- Имена членов платформенных типов извлекаются в обоих написаниях. Справочная
документация существует только по-русски, поэтому каталог хранил члены типа лишь под
русскими именами – и правилу, судящему член в АНГЛИЙСКОМ проекте, сравнивать было не с чем.
Пары объявляет сам дистрибутив: 670 типов, 5251 пара, новая секция
member_namesвuiterms.json. Хранится по типам, а не одной таблицей: соответствие не однозначно – одно русское слово отвечает разным английским у разных типов, и плоская таблица потеряла бы треть секции.
Изменено
- Проблема переворота локализации называет ключ так, как он записан в ИСТОЧНИКЕ. Отчёт
говорил
'TaskCheckbox' has no en valueо строке, которая в базовом файле зовётсяЗадачаФлажок, отправляя читателя к обратному словарю; теперь первым идёт имя из источника, перевод – рядом в скобках.
Исправлено
- Английские написания членов берутся из того, что дистрибутив ОБЪЯВЛЯЕТ, а не из близости
имён друг к другу. Прежний способ мог принять за член имя параметра: замер показал две
неверные пары из 2015, и обе давали метод, которого у типа нет (
CharAtстроки выходилSymbol,Scheduleобновляющего задания –ScheduleWithoutTransaction), то есть переведённое дерево не скомпилировалось бы. Имя, объявленное и методом, и свойством, отдаёт написание метода. Данные надо пересобрать (xbsl extract --only terms,uiterms), после чегоcode/unknown-memberперестаёт сообщать о верном вызове. meta_project_info(иproject-infoв CLI) отвечает узко:kind,subsystem,brief. Всё дерево одним куском на живом проекте не помещалось в ответ инструмента – 143 КБ по исходникам живого корпуса, – и вопрос “какие объекты вида X тут есть” стоил двух лишних шагов: сохранить в файл и грепнуть. Краткий режим отвечает 5 КБ (381 объект, 22 вида), отбор по виду – 24 КБ. Счётчики по видам (object_counts) идут в КАЖДОМ ответе, отобранном или нет, чтобы отбор, не нашедший ничего, не читался как пустой проект, а полеfilterназывает, что осталось за кадром.- Список принятых замечаний стал переносимым между машинами: путь внутри текста находки приводится к общей форме. Межфайловые правила называют второй файл так, как его получил запуск: разделителями своей ОС и абсолютным путём, если абсолютным был корень. А личность записи – это её текст. Из-за этого список, записанный на Windows, в Linux-CI ничего не гасил и объявлялся устаревшим с обеих сторон: на одной ревизии живого корпуса локально вышло “погашено 97, устаревших 2”, в CI – “89 и 7”. Теперь путь в сообщении читается так же, как путь файла: POSIX, относительно каталога, где лежит список. Прежние файлы работают без переписывания, общая форма считается с обеих сторон сравнения.
- Каталог словаря перевода больше не считается исходником проекта. Корень запуска может
стоять выше проекта, в корне репозитория. Тогда рядом оказывается каталог словаря, а его
файлы это yaml той же формы, и собственные комментарии словаря возвращались непереведённой
прозой. На проекте корпуса такой запуск показывал 871 пропуск фраз и покрытие 99,19% там,
где сам проект даёт 100%: цифра выглядит достоверной и уводит в расследование несуществующей
дыры. Теперь обход пропускает каталог
xbsl-translationи одноимённый файл, а также словарь, названный вызывающей стороной, где бы он ни лежал. translate_setрапортовал о снятии записи, которого не происходило. Пакет, снимающий запись в файле и одновременно добавляющий новую с целью в ТОТ ЖЕ файл, терял снятие: добавление собирало текст файла заново с диска, затирая уже посчитанные правки, а отчёт при этом писалremoved: 1. То же касалось исправления записи в файле-цели. Теперь новые записи ложатся поверх уже посчитанного текста.code/unknown-memberсудит английские написания членов. Прежде правило глушило любой латинский член: при русском каталоге судить их значило бы сообщать о верном коде. Теперь тип, чей набор членов словари называют ЦЕЛИКОМ, судится в обоих написаниях; один член без названной пары оставляет свой тип несудимым по-английски, и правило сохраняет договор об отсутствии ложных срабатываний. Покрыты четыре типа из пяти.- Структура, объявленная самим модулем, больше не судится как одноимённый платформенный тип. Правило файловое и о проектных типах не знает, но собственные объявления модуля лежат прямо в нём – а структура проекта, чьё имя совпало с платформенным типом, получала замечания о собственных же полях.
- Дерево формы накрывает список, записанный на столбце собственного ключа. Yaml такое
написание разрешает; диапазон узла брался обходом отступов, поэтому такой список выглядел
без отступа вовсе и узел заканчивался через строку после начала. Узел, переставший
накрывать своих детей, обрывал спуск
node_at, и любая правка конструктора ниже него отклонялась. Накрытие стало инвариантом, а не следствием обхода: узел растягивается по своим детям, а их границы приходят из разметок самого yaml. - Отклонённая правка формы называет, что нашла. Сообщение не называло ни места, ни того, что там стоит; теперь оно называет строку, смещение и узел, который держит там дерево.
- Запись словаря с
::в ключе больше не рвётся надвое. Читатель записей заканчивал обычный ключ на первом двоеточии, тогда как yaml заканчивает его двоеточием С ПРОБЕЛОМ – и фраза, цитирующая платформенную форму путём видаStd::Jobs::JobsForm, разрезалась посреди слова, а хвост ключа сохранялся как часть перевода. Никто не жаловался: обе половины – годные строки, и порча всплывала лишь пропавшей из покрытия фразой. Касается всех мест записи –translate_set, ключа--setв CLI, панели редактора. naming/prefix-by-kindчитает английские имена. Голова английского составного имени – его последнее слово, поэтому переведённый элемент несёт то же слово вида ПОСТФИКСОМ – правило же требовало русский префикс дословно и сообщало о каждом таком элементе переведённого дерева; ожидаемое написание в сообщении следует алфавиту имени, английские слова берутся из словаря платформы.- Три рукописных английских написания не совпадали ни с чем и теперь берутся из данных.
Свойство веса растягивания у
yaml/card-literal-stretch-weightи фасет ссылки уyaml/ref-input-auto-commandsиcode/ref-field-needs-reqбыли написаны руками, а сериализатор пишет их иначе, и правила молчали на переведённом дереве. Один из тестов закодировал неверное написание фасета и не мог сработать в принципе. Написания берутся из словарей свойств и фасетов, а паритет замерен полной проверкой переведённого дерева против русского файл-в-файл. structure/xbsl-pairузнаёт английский модуль порождаемого типа. Модуль, расширяющий тип, который порождает элемент, несёт хвост этого типа и своего описания не имеет –Prices.RecordSet.xbslописан файломPrices.yaml. Хвосты брались из каталога, где они записаны по-русски, и латались руками единственным словомObject, поэтому любой другой английский модуль читался как модуль без описания и получал замечание – то, чего его русский близнец никогда не получал. Теперь оба написания выводятся из словарей платформы: набор суффиксов вырос с 39 до 76, и русских хвостов без английского близнеца не осталось.- Рукописная английская колонка хвостов порождаемых типов убрана. Девять её имён из
тринадцати повторяли то, что уже отвечают словари, а четыре были догадками, которых
платформа не подтверждает:
Ref,RecordManagerиSelection– привычки 1С:Предприятия (в Элементе эти роли зовутсяReferenceиRecord, аSelectionсловарь читает как выделение в интерфейсе). Стоя только на английской стороне, они прощали в одном написании ровно то, о чём правило сообщает в другом. Осталась одна ПАРА, которой в словарях нет вовсе, – она сохранена целиком, чтобы деревья не разошлись. - Таблицы каталога у правил семантики сбрасываются при смене корня данных. Четыре таблицы читали каталог одной версии и держали его в кэше без регистрации сброса, поэтому после переключения на другой корень продолжали отвечать по прежней версии.
27.08.2026 – 0.81.0, 0.82.0
Добавлено
naming/filler-wordиnaming/numberсудят английские имена. Переведённое дерево прежде проходило оба правила молча. Список пустышек ведётся в обоих написаниях, и русская пустышка-префикс ловится там, куда её ставит перевод, – в конце составного имени (УправлениеСкладами–WarehouseManagement). Голова английского составного имени – его последнее слово (BankAccounts–Accounts), число головы определяется суффиксной эвристикой с перечнем неправильных множественных – морфологический extra для этого не нужен; несчисляемые слова и неоднозначный хвост-osостаются нерешёнными, а не угадываются. Исключения стандарта (TaskData,MessageQueue) известны тоже в обоих написаниях.- Переведённое описание разбирается как исходное. Ключ имени (
Name:) и ключи секций (Attributes:,TabularParts:и остальные) правила имён и индексатор читают в любом написании; английские написания берутся из метамодели, а не из рукописного списка. - Локализуемые значения yaml переводятся планом литералов. Значение, которое метамодель
объявляет локализуемым текстом (
Localizable), – представления команд, прав доступа и перечислений – читает человек на странице: теперь оно либо названо записью плана литералов целиком, либо предъявлено пропуском, как шаблон представления события. СвойствоОписание– документация разработчика: остаётся данными и в пропуски не попадает. - Предупреждение
literal-data-value: запись словаря сдвинула литерал, равный значению из json-ресурса проекта. Такой литерал обычно сравнивается с этими данными (разбор начального заполнения), а данные перевод не трогает – после сдвига сравнение молча пустеет; класс найден ревизией английской сборки пилотного проекта, где полный пересев терял раскладку карточек. Литерал-данные помечается записью со значением, равным ключу: покрытие засчитано, текст не движется, предупреждения нет. Предупреждение выдаётся на разный текст один раз на файл. - Отчёт перевода печатает предупреждения списком – файл, строка, вид и текст (первые двадцать), а не одним числом: прежде за подробностями приходилось ходить в json-режим.
- Суффиксы литерала длительности переводятся (
300мс->300ms,2д14ч30м5с6мс->2d14h30m5s6ms). Состав русских суффиксов – справка типа Длительность, английские написания подтверждены компилятором платформы (пробная сборка принимает2d14h30m5s6ms). Число, склеенное с буквами вне набора суффиксов, не трогается.
26.08.2026 – 0.79.0, 0.79.1, 0.79.2, 0.80.0
Добавлено
yaml/duplicate-subtree– поддерево разметки, скопированное в другой файл. Слепок по устройству, имена и тексты в счёт не идут: новую форму заводят копированием соседней, и копию переименовывают. Порог 40 узлов и оба исключения выведены замером, а не выбраны; выключено по умолчанию – мера одинаковости решение проекта.yaml/toggle-command-pair– пара обычных команд с зеркальнойВидимость. Две соседние команды, из которых видима ровно одна (=Xи=не X), изображают одну команду с двумя состояниями – у платформы она есть готовой:ПереключаемаяКоманданесёт представления и изображения обоих состояний, а состоянием владеет сама платформа. Общий обработчик пары усиливает картину, но не требуется.
Исправлено
- Шаблон представления вида события переводится целиком, а не одними выражениями. Проза, которую читают в журнале, оставалась русской молча – теперь она берётся из плана литералов по всему значению, а чего план не назвал, попадает в отчёт пропусков.
- Имя именованной группы образца и вызов, который её читает, двигаются вместе. Обе стороны
берут написание из одного источника; прежде объявление в образце не смотрел никто, а
аргумент
Группа("Имя")переводился, и платформа отвечала “нет группы захвата с таким именем”. - Устаревшими считаются только записи тех правил, которые в проверке участвовали. Правило,
оставленное за набором – сужением
--select, выключенное по умолчанию, неизвестное установленной надстройке, – находок не даёт по построению, а его записи объявлялись устаревшими, будто долг выплачен. Из-за этого две среды спорили об одном списке принятых: MCP-сервер на надстройке постарше насчитывал 48 устаревших записей на дереве, которое CI с теми же правилами считал чистым. Теперь такие записи считаются отдельной строкой (ключbaseline_not_checkedв json), и--prune-baselineих больше не снимает. - Словарь перевода проекта больше не судится правилами схемы yaml. Пара
Ид: Idв файле каталогаxbsl-translation– это перевод имени, а не идентификатор объекта, иyaml/id-uuidчитал её как негодный Ид. Файл словаря распознаётся по собственному содержимому – версии формата и разделу перевода, – поэтому проверка остаётся файловой и не ходит по дереву на каждое нажатие клавиши. Остальные правила модуля молчали на словаре и раньше: у него нет ВидЭлемента. code/duplicate-method-body: какое из остальных мест названо в сообщении, не зависит от порядка обхода файлов. Прежде CLI и редактор могли назвать разные места одной и той же копии, а вместе с сообщением переставала совпадать и запись списка принятых: её ключ – это сообщение.
25.08.2026 – 0.76.0, 0.77.0, 0.78.0
Добавлено
code/duplicate-method-body– одно тело, написанное дважды в разных файлах. Сравнивается нормализованное тело от пяти строк, поэтому переформатированная копия остаётся копией. Метод-обработчик платформы отделяется аннотацией@Обработчик. Выключено по умолчанию.code/client-available-unused– метод открыт клиенту, но клиент его не зовёт. Аннотация открывает поверхность, которой никто не пользуется; употреблением считается упоминание в клиентском модуле, в клиентском методе серверного модуля, в yaml и в строковом литерале. Выключено по умолчанию, какcode/unused-method.code/access-context-read-noop– холостое расширение контекста доступа чтением. У типа в yaml стоитЧтение: РазрешеноВсем, то есть выдавать нечего, а вызов создаёт впечатление защищённости. Замечание указывает на само право: одно в списке – уходит вся строка, среди других – только оно.yaml/unused-component– компонент интерфейса, которого никто не размещает.code/unused-methodтакой компонент не видит принципиально: его методы зовёт его же yaml. Имя, написанное ключом словаря, употреблением не считается. Точка входа и глобально видимый компонент не судятся, а проверка обязана покрывать проект целиком.code/query-in-loop– запрос внутри цикладля/пока. Каждый виток – отдельное обращение к базе, поэтому цена метода растёт вместе с данными и вылезает только на настоящих объёмах. Замена – один запрос по всему набору: значения витков уходят массивом в условиеВ.
Исправлено
code/duplicate-method-bodyназывает файл второй копии, а не путь, которым до него дошли. Линтер называет файлы так, как его позвали, поэтому сообщение расходилось между CLI, редактором и другой машиной. Вместе с ним расходилась и запись списка принятых: её ключ – это сообщение.- Таблица предложения ИЗ считается употреблением объекта. Голый идентификатор не
примыкает ни к точке, ни к скобке, поэтому
ИЗ Товары КАК Т– строка, за которой обязано следовать переименование, – употреблением не была вовсе: на живом проекте индекс прибавил 374 таких ссылки. - Значение перечисления в блоке, которого нет в ui-схеме, переводится. Элемент сортировки списка и элемент его отбора схема не описывает, поэтому ключ рядом со значением становился английским, а само значение оставалось кириллическим – сборка такое отвергает. Свойство в таком блоке названо по своему перечислению, его таблица и отвечает.
- Редактор читает файлы запросов виртуальных таблиц – как давно читает CLI. Проверка
по проекту, открытый буфер и индекс проекта пропускали
.xbql, поэтому одно и то же нарушение было видно или нет в зависимости от того, кто спрашивает, а употребления объекта в запросе не попадали в поиск использований.
24.08.2026 – 0.74.0, 0.75.0
Добавлено
translate --table– записи словаря, пропуски и сводка за ОДИН проход. Таблица словаря в редакторе спрашивает движок именно об этом, и порознь ответ стоил двух одинаковых обходов исходников в двух процессах плюс третьего чтения того же словаря: на живом проекте – около девяти секунд, и повторялись они после каждой записанной ячейки.- Квалифицированная запись словаря действует и на поле СТРУКТУРЫ. Поля одной структуры живут
в общем пространстве имён, поэтому два русских имени, переведённые в одно английское, – это
структура, которую компилятор отвергает; раньше это лечилось только правкой русского исходника.
Теперь
<Структура>.<Поле>переименовывает объявление, все обращения через получателя с объявленным типом и ключ парного json-ресурса разом. Написанный получатель по-прежнему отвечает первым: запись, квалифицированная именем переменной, продолжает работать. - Коллизию полей одной структуры видит транслятор. Прежде о ней говорил только компилятор –
тот же класс, что коллизия имён методов, но без своего сообщения. Теперь она попадает в список
проблем и роняет
--strict. - Переименование и удаление объекта забирают виртуальную таблицу его списка. Пара
<Имя>СписокТаблица(.yamlплюс запрос.xbql) не входила ни в одно семейство файлов, а сами файлы.xbqlне просматривались вовсе – в них стоит имя объекта, и переименованный справочник оставлял за собой запрос к несуществующей таблице. Английское написание пары знает то же правило.
Изменено
- Член платформы без английского написания – пропуск ПЛАТФОРМЫ, а не словаря. Сводка
показывала
platform_gaps: 0, и тут же список пропусков называл метод массива недостающим именем: счётчик противоречил списку. Записать такое имя в словарь значило бы выдумать английское написание платформенного члена, которое компилятор откажется принять. Теперь имя, которое платформа объявляет своим членом, а данные не знают его написания, идёт в платформенные пропуски. --strictроняет проверку и на платформенных пропусках. Такое имя остаётся кириллическим в переведённом дереве, то есть сборка его отвергнет, и строгая проверка молчать не должна. Лечится это не словарём, а данными платформы, поэтому в отчёте пропуск по-прежнему назван отдельно.- Словарь перевода читается быстрым загрузчиком yaml. На словаре живого проекта (3.6 МБ, 39 файлов) 1.4 с против 0.11 с; чистый питоновский загрузчик оставлен запасным для сборок без libyaml.
Исправлено
- Литерал запроса для неопределённого значения переводится в
UNDEFINED, а не вNULL. Таблица ключевых слов берётся из данных компилятора, литералов в ней нет вовсе, и слово проваливалось в плоский словарь – а тот даёт емуNULL, отдельное зарезервированное слово, которому не отвечает ни одно русское написание. Компилятор принимает и то и другое, поэтому все проверки оставались зелёными; на работающем приложении условие сNULLне истинно никогда, и запрос возвращал пусто. Встречено вживую на переведённом корпусе, где разом замолчали три места, зависевшие от такого условия. ЛитералыTRUE,FALSEиUNDEFINEDтеперь называет сам движок – вместе с однословными ключевыми словами, которым экстрактор даёт неверную пару.
23.08.2026 – 0.73.0
Добавлено
form/handler-signature– обработчик, сигнатура которого противоречит событию компонента. Делегат берётся из ui-схемы с подстановкой аргументов типа самого компонента и сверяется с методом парного модуля. Аритет, базовый тип и неподставленный параметр типа не судятся: разведка на четырёх корпусах (483 обработчика) показала, что каждый из них законен.typography/yo-in-text– буква “ё” в тексте, который читает пользователь. Видимые свойства компонентов и элементов плюс каждая запись словаря локализованных строк; привязка, ссылка и техническая строка не трогаются. Есть автопочинка – кроме случая, когда буква несёт смысл. Выключено по умолчанию, как и прочая типографика.
Изменено
- Новый файл словаря создаётся с нейтральным заголовком. Раньше он сообщал о панели
редактора, кто бы его ни писал;
translate_set(..., comment=...)иxbsl translate --commentставят туда тему самой порции. Существующий файл свой заголовок сохраняет.
Исправлено
- Коллизию имён МЕТОДОВ транслятор видит. Два русских имени, которые английский пишет
одинаково, сталкиваются в общем модуле, и такой модуль компилятор отвергает – а проверка знала
имена метаданных и локальные имена метода, но не сами методы. Теперь коллизия идёт в
problems(их отдаётtranslate_status, на них падает--strict), аtranslate_setотвечает полемcollisions, когда значение уже занято в той же области. - Значение, по которому выбирается диспетчеризуемый блок, переводится. Вид расписания – не тип, не свойство и не значение перечисления, поэтому пары ему не давал ни один словарь. Аннотация метамодели называет оба написания: экстрактор несёт английское, а рукописная пара для стандартного реквизита кода ушла.
- Семь перечислений, у которых английские написания были сдвинуты на значение. Значения – аргументы конструктора, и класс объявляет их в порядке своих полей, а он не всегда начинается с английского имени. Порядок написан в самом пуле.
- Два ключевых слова языка запросов, которые экстрактор читал неверно. За словом, у которого английского написания нет, идёт его транслитерация, и при чтении подряд она становилась “английским” для следующего. Пул читается парами; список-обход на стороне транслятора снят.
- Два правила, мимо которых проходил английский проект.
yaml/standard-field-lengthчитал секцию реквизитов только русскими ключами, аyaml/presentation-fieldсверял тип реквизита с русским написанием строкового типа. Имена стандартных реквизитов берутся в написании самого файла, поэтому русский проект не страдает. - Правило о пробелах словаря больше не судит сам словарь. Его файлы русские по построению,
и на покрытом проекте правило выдавало 826 “пробелов” – все свои же. Правило остаётся
выключенным: каждый файл проходит перевод целиком, и проверка удваивается. У инструмента MCP
появился параметр
enable, близнец флага--enable. - Сервер MCP применяет список принятых замечаний проекта – как это делает CLI. Один и тот
же каталог читался чистым в терминале и грязным через агента. Файл ищется над проверяемыми
путями,
baselineназывает другой,no_baselineпросит показать замороженные. - Первый реквизит новой табличной части замещает заглушку. Заглушка узнаётся и по имени, и по типу, поэтому переименованный автором реквизит не трогается.
21.08.2026 – 0.72.0
Добавлено
- Машинный перевод предлагает записи, которых не хватает в словаре.
xbsl translate --suggestспрашивает внешний сервис – Yandex Translate или Google Translate, выбор идёт по тому, какие ключи заданы, – про каждую запись, которую словарь ещё не покрывает, и просто показывает ответ, а не записывает его сам: слово принимает человек. Секция словаряtermsуходит вместе с запросом глоссарием, поэтому термин, который проект уже закрепил, сохраняет написание и внутри переведённого сервисом предложения. Ответ кэшируется по исходному тексту и глоссарию, с которым он получен, поэтому повторный запуск по тем же пробелам не делает ни одного запроса – отчёт считает, сколько ответов взято из кэша. Ключ никогда не попадает в командную строку: движок читает его из окружения, а в панели переводов VS Code появилась кнопка “Запросить машинный перевод” – она проходит тем же запросом по открытой таблице и подставляет каждую догадку одним щелчком, как уже умело платформенное написание; свой ключ панель хранит в SecretStorage, а не в настройке.
20.08.2026 – 0.70.0, 0.71.0, 0.71.1
Добавлено
- Третий план словаря –
literals. Строковый литерал переводчик оставлял данными и молчал о нём: в переведённом дереве оставались кириллические сообщения и ключи, записанные строкой (ключ хранилища параметров, имя поля контракта). Теперь команда перечисляет такие литералы в планеliterals– ключ и значение пишутся ровно так, как текст стоит в исходнике между кавычками, – и движок заменяет литерал целиком. Код внутри интерполяций значения переводится обычным порядком, поэтому автор словаря не обязан знать английские написания имён. Литерал внутриЗапрос{},Образец{}и других разрешимых литералов не трогается: там это код. Непокрытые литералы честно попадают в отчёт, в--gaps --kind literal, в инструменты MCP и в находкуconventions/missing-translation– покрытие словаря они при этом не портят, у них свой счёт. - Комментарий переносится по ширине заново. Перевод сохраняет разбиение строк один в один, и
комментарий, ставший длиннее исходного, вылезал за предел ширины – на настоящем проекте это
давало сотни находок
style/line-lengthтам, где исходное дерево чистое. Теперь блок комментария переразбивается по той же ширине, которой пользуется правило. Рамки и разделители, списки, таблицы и образцы кода, а также строки, длинные уже в исходнике, остаются нетронутыми.
Исправлено
- Имя параметра маршрута переезжает вместе с кодом, который его читает. Шаблон
/res/{код}– это данные (адрес набирает посетитель), но имя в фигурных скобках объявляет параметр, и обработчик читает его ПО ЭТОМУ ИМЕНИ. Оставленное как есть, оно расходилось с переведённым обращением: обработчик спрашивал параметр, которого маршрут не объявляет, получал пустоту и отдавал не тот ответ – статика приезжала с типом text/plain. - Правила судили о переведённом дереве строже, чем об исходном. Компилятор платформы принимал дерево, а линтер находил в нём ошибки, которых в исходнике нет: производный тип объекта, маркер имени исключения, блок использования подсистемы, nullable у члена, значение перечисления и штатная таблица запроса узнавались только в русском написании. Теперь оба написания судятся одинаково: шесть правил, на которых расходились русское и переведённое деревья одного проекта, дают на них один и тот же набор находок.
- Значение перечисления с именем
Noпропадало из объявления. Читатель yaml разбирает документ по YAML 1.1, гдеNo– это ложь, поэтому элемент терялся, а каждое обращение к нему приходило находкойcode/unknown-enum-value– при том, что тот же файл платформа принимала. - Ключ словаря с кавычкой внутри читался неправильно и дублировался при записи. Строка комментария, которая что-то цитирует, – обычный ключ словаря; читатель обрывал его на первой внутренней кавычке, писатель не находил такую запись и добавлял её второй раз, после чего словарь отказывался грузиться дублем.
- Команда
xbsl translate– перевод исходников проекта на английские написания. Токены платформы переводятся по метамодели и словарям данных (ключевые слова – формой того же регистра, ключи yaml – по классу узла, значения перечислений – внутри своего перечисления, выражения типов – с фасетами, ключевые слова запросов – внутри блоковЗапрос{}, код внутри интерполяций строк – как обычный код); СОБСТВЕННЫЕ имена проекта и строки комментариев – по словарю проекта: каталог yaml-файлов (xbsl-translationрядом с проектом или выше) с двумя планами –tokens(идентификатор целиком -> идентификатор целиком) иphrases(строка комментария -> перевод). Файлы и каталоги переименовываются той же картой токенов,Идне меняются, а раскладка словарей локализации переворачивается: секция целевого языка становится базовой, исходные значения уезжают вЛокализация/<Код>/, языки проекта в дескрипторе следуют за этим.--coverageсчитает долю словаря по каждому объекту метаданных,--missingпишет непереведённый остаток заготовкой словаря,--strictне пропускает публикацию в CI. Всё, чему данные не знают английского написания, честно остаётся как написано и попадает в отчёт, а не угадывается. - Имена, объявленные проектом, закрыты от платформенных таблиц. Слово, которое знает и платформенный словарь – значение перечисления, реквизит, ключ словаря локализации, – переводится ТОЛЬКО словарём проекта: объявление и все обращения переезжают вместе или вместе ждут записи. Без этой связки модуль уже зовёт английское имя, пока yaml всё ещё объявляет русское значение, и сборка отвергает дерево.
- Словарь отвечает ТАБЛИЦЕЙ, а инструменты его наполняют.
xbsl translate --gapsпоказывает недостающее (по убыванию частоты, с местами употребления и собственным написанием платформы как подсказкой),--entries– то, что словарь уже говорит, с файлом и строкой каждой записи,--set– запись: добавить, исправить на месте, снять обнулением значения. Те же четыре вопроса есть инструментами MCP (translate_status,translate_gaps,translate_entries,translate_set), поэтому наполнение словаря на тысячи записей больше не требует вычитывать файлы. Писатель встраивает запись в существующий файл, копируя отступ у соседей секции: словарь, заведённый двумя пробелами, после правки остаётся валидным, а комментарий в голове секции читателю таблицы не мешает. Находкаconventions/missing-translationнесёт то, что нужно клиенту для исправления, – точный ключ, его вид и подсказку – в новомDiagnostic.data, который пробрасывают и языковой сервер, и машинный отчёт. - Ключи json-ресурсов переезжают вслед за полями структур. Структура читает свой ресурс по ИМЕНИ ПОЛЯ, поэтому ключ данных – то же имя, записанное во второй раз; переименовать поле и оставить ключ значит не связать ничего, причём молча: настройки чтения пропускают неизвестное свойство и инициализируют отсутствующее поле, и переведённый проект компилируется, применяется и стартует с пустыми данными. Переезжают только ключи, называющие поле структуры проекта; значения и ключи, которых не объявляет ни одна структура (карта по содержимому, внешний контракт), остаются как написаны, а перезапись идёт по местам – форматирование файла сохраняется. Компилятор о таком не скажет ничего: разъехавшееся имя – это данные.
- Путь ресурса в строке переезжает вслед за файлом. Дерево переименовывает файлы и
каталоги ресурсов, поэтому литерал, который адресует ресурс (путь вида
"<Каталог>/%<Поле>.svg"), обязан следовать за ними; иначе платформа не находит ресурс, а проект, поймав это исключение, рисует пустое место. Переводятся только литералы ФОРМЫ пути – оканчиваются известным суффиксом ресурса, каждый сегмент читается как имя файла: регулярное выражение с косыми чертами и именованными группами под это не подходит и остаётся данными. - Правило
conventions/missing-translation(info, выключено по умолчанию, область – проект) – имя или кириллическая строка комментария, которых ещё нет в словаре перевода проекта; одна находка на первое вхождение в файле. Область проектная не для удобства: “своё ли это имя проекта” – факт проектный, объявление может лежать в yaml, о котором модуль не знает. Слово, которое знает и платформа, тоже пробел, если его объявил проект, – пофайловая проверка молчала бы ровно там, где переведённое дерево разъезжается. Правило молчит, пока словарь не найден, поэтому его видит только проект, который переводит исходники.
19.08.2026 – 0.69.1, 0.69.2, 0.69.3
Изменено
- Примеры в описаниях правил и образцы тестов приведены к словарю демо-проекта. На поведение движка не влияет.
Исправлено
yaml/dynlist-column-sort-lostне судит колонку, которая сама выключила сортировку. СвойствоОтключитьСортировку: Истина(DisableSorting: True) правило не читало вовсе, и колонка-значок состояния с вычисляемым значением приходила замечанием. Терять там нечего: сортировки у такой колонки нет по объявлению.
17.08.2026 – 0.69.0
Добавлено
- Правило
yaml/localization-key-unique(error, в наборе по умолчанию) - ключ, объявленный в словаре локализованных строк дважды. Охват выяснил компилятор на одноразовом проекте из трёх словарей: у секций ОДНО пространство имён, файл перевода судится тоже, и все три отказа звучат “имя не уникально”. Отказ приходит на применении, то есть откатывается весь проект - один повторённый ключ стоит полного цикла деплоя, а в словаре на несколько сотен ключей дубль глазами не виден. Любой читатель yaml оставляет ПОСЛЕДНИЙ из повторов, поэтому до применения его никто не замечал; правило читает узлы разбора. - Правило
code/module-var-not-const(error, в наборе по умолчанию) - объявлениепер/знч/испна уровне МОДУЛЯ, где живёт только константа. Значение константы вычисляется при компиляции, а остальным модификаторам нужен работающий метод, чтобы вычислить выражение инициализации. Разбор принимает там все четыре (правило грамматики общее с полем объекта) - поэтому раньше это выяснялось только на деплое. - Правило
code/use-needs-closeable(error, в наборе по умолчанию) - модификаториспу типа, который описан каталогом и не наследуетЗакрываемое. Модификатор существует ради автоматическогоЗакрыть()на выходе из области видимости, поэтому компилятор отвергает объявление. Тип, до которого не дотянулся вывод, и тип, которого в каталоге нет, не судятся. - Дерево компонентов берётся частями -
meta_component_treeи CLIform-treeпринимают поддерево (по идентификатору узла или по имени компонента), предел глубины и выдачу без записей свойств. Настоящая форма дала четверть миллиона символов, и чтобы посмотреть одну группу, приходилось читать всё; та же форма отвечает на обзорный вызов семьюстами символами. Обрезанный узел об этом сообщает, а компонент без свойств называет их число.
16.08.2026 – 0.68.0, 0.68.1, 0.68.2
Добавлено
- Правило
yaml/missing-subsystem-usage(warning, в наборе по умолчанию) – подсистема импортирует другую, а в своём описании не объявила её используемой. Такой проект не применяется, и раньше это выяснялось только на деплое. - Правило
code/missing-import(warning, в наборе по умолчанию) – модуль пользуется типом или модулем чужой подсистемы, не импортировав её. Компиляция падает на этой строке, а линтер о ней молчал: проверка была только для yaml.
Изменено
- Строка из одних пробелов – замечание вида info. Отступ пустой строки ничего не меняет ни для компилятора, ни для читателя, и правила про него у платформы нет. Хвост после кода остался предупреждением: там в строке есть содержимое.
- Подсказка отвечает после данных объекта формы. Имя
Объектобъявлено аргументом базового типа формы; теперь оно типизировано, а с ним – и циклы по табличным частям. - Подсказка отвечает после значения перечисления и после переменной такого типа. Значение это член перечисления, а его члены – методы модуля рядом.
- Цикл по списку значений типизирует переменную.
для Вариант из [Роль.Админ, Роль.Обычный]берёт тип у самих элементов; если они разного типа, переменная остаётся нетипизированной. - Подсказка отвечает после пойманного исключения и после команд формы. Тип исключения
написан в самом объявлении, а команды вроде
Записатьформа получает от типа, который наследует; после таких имён точка молчала. - Подсказка отвечает после параметра лямбды.
Список.Преобразовать(Э -> Э.предлагает члены элемента коллекции, а лямбда над результатом запроса – колонки выборки. - Табличная часть в запросе отвечает своими полями.
ИЗ Товары.Состав КАК Считается как таблица, и послеС.идут реквизиты части и стандартные поля строки. - Точка после компонента формы отвечает – и методами его собственного модуля, и членами его типа; цепочка через компонент доходит до конца.
- В английском проекте подсказка называет члены платформы по-английски. Раньше список после точки был русским, каким бы ни был язык проекта.
- Вывод типа выражения отвечает чаще. Он узнал литералы запроса, образца и ресурса, а переменная цикла получает тип элемента коллекции.
Исправлено
- Метод из подсказки вставляется со скобками. Список методов собирается в двух местах, и скобки клало только одно – в остальных вставлялось голое имя.
- Тип предлагался дважды. Список членов объекта называл локальные типы и табличные части и общей строкой “тип”, и точной; теперь строка одна, точная.
- После
новый Имя.предлагаются только типы. Методы модуля и члены менеджера в конструкторе стоять не могут и лишь вытесняли типы из видимой части списка. - В 0.68.0 точка после компонента формы молчала, если у компонента нет своего модуля, а тип записан с аргументом – а так записано большинство.
- Индекс терял признак пустого значения у типа результата метода – из-за этого всякое значение, пришедшее из проекта, выглядело непустым.
- Окружение метода не различало блоки: имя, объявленное в одном цикле, отвечало и в другом. Теперь видимость считается по правилам платформы – от объявления до конца блока.
- Реквизиты своего типа не попадали в окружение, и реквизит, названный как стандартный тип, читался как этот тип.
- Операция
??называла тип по правой стороне, хотя значение бывает и левым. Теперь несогласные стороны дают “неизвестно”. - Экстрактор терминов терял имена, написанные двумя алфавитами (
FtpИсточник,SeoОписание): у них не оказывалось английской пары, хотя в дистрибутиве она есть. Заодно из словаря ушли несколько ложных пар.
15.08.2026 – 0.66.0, 0.66.1, 0.67.0
Добавлено
- Вывод типа выражения (
xbsl.typeinfer) – тип получателя, члена, конструктора, приведения и настойчивой операции по данным платформы. Там, где данные тип назвать не позволяют, модуль отвечает “неизвестно”, а не догадкой. - Правило
yaml/ref-input-auto-commands(info, выключено) – ссылочное поле ввода без своихКоманды: платформа рисует рядом кнопку открытия значения в отдельном окне. Чаще всего она и нужна, поэтому правило отвечает на вопрос “откуда кнопка”, а не сообщает об ошибке. - Запрос
xbsl/localizationStrings: движок отдаёт все локализованные строки проекта на выбранном языке. Ключ без перевода остаётся с текстом языка по умолчанию – так же, как подставляет платформа.
Изменено
- Подсказка отвечает там, где раньше молчала. На живом проекте четверть точек оставалась без
ответа; молчание сократилось на треть. Тип переменной теперь берётся из литерала
(
знч Ключ = ""– этоСтрока) и из вызова без квалификатора – метода своего же модуля, которым модуль зовёт собственный код. Настойчивая операция больше не обрывает цепочку, переменная цикла берёт элемент из записанного типа коллекции, а объявление внутри цикла опирается на переменную цикла. Значение компонента интерфейса отвечает своими свойствами, методами своего модуля и членами платформенного типа, который он наследует. Внутриновый Тип(предлагаются имена того, что тип несёт, вместе сИмя =. Запрос, объявленный черезисп, доносит колонки до цикла. - Пространство фасетов отвечает после точки. Фасет назван двумя сегментами
(
Сущность.Право), и каталог хранит его так же – первый сегмент сам по себе типом не был, поэтому молчали и подсказка, и цепочка. Теперь пространство предлагает фасеты, которые могут за ним стоять, а цепочка разрешает двухсегментный корень. - Типы, которые порождает объект, несут его данные.
Товары.Объектотвечает реквизитами и табличными частями своего yaml, табличная часть – отдельный тип со своими реквизитами, аТовары.Ссылка– тем, что вид даёт ссылке. Каталог описывает их по ВИДУ, и собственные данные объекта присоединяются к описанию. - Член типа, который расширяет модуль, доступен по голому имени. В модуле
Товары.ОбъектголоеСостав– это его табличная часть, а не неизвестное имя: точка после неё отвечает, а цикл по ней берёт тип строки. Тип объекта теперь несёт объявленный тип каждого своего члена. - Однострочный запрос отвечает колонками у самого результата. Такой запрос читают прямо с переменной, без цикла, – колонки доносились только до переменной цикла.
- Обобщённый член разрешается по аргументам, которые написаны в коде.
Массив<Каталог.Карточка>.Первый()отвечаетКаталог.Карточка,Соответствие<Строка, Число>.Получить(...)–Число: каталог называет такой результат ПАРАМЕТРОМ типа, и списки параметров теперь извлекаются вместе с ним.
Исправлено
- Обобщённый МЕТОД терял и сигнатуру, и тип результата. Параметры печатаются между именем
и скобкой (
ПрочитатьОбъект<ТипОбъекта>(...)), а разбор требовал имя сразу со скобкой – метод не получал ни того, ни другого. Устаревшая перегрузка добивала: её результат расходился с актуальным, и член отбрасывался целиком. Теперь читаются оба, актуальная форма старше формы совместимости, а параметры типа метода извлекаются –СериализацияJson.ПрочитатьОбъект(Текст, Тип<Пакет>)отвечаетПакет. - Коллекция не знала типа ничего, что возвращает. Базовые типы обобщённого печатаются с
аргументом (
Коллекция<ТипЭлемента>), а извлечение читало написание целиком как имя – и уМассивоставался единственный предокОбъект, а вместе с ним терялись все унаследованные типы результатов: 779 типов не имели ни одного. Починены обе половины – извлечение читает голову имени, а загрузчик достраивает унаследованные типы результатов и типу, у которого своих нет. - Проект на английском попадает в индекс – имя элемента и его именованные разделы читались только в русском написании, поэтому английский проект давал пустой индекс: ни дерева, ни навигации, ни подсказки. Тип, который элемент порождает, регистрируется под обоими именами, и точка отвечает на то написание, которым написан код.
- Точка после элемента предлагает то, что элемент несёт – параметры элемента вида
ПараметрыРаботыКлиентав подсказку не попадали, она перечисляла одни методы вида. - Цикл по параметру типизирует свою переменную – если коллекция это параметр с типом
Массив<...>, переменная цикла оставалась без типа и точка после неё не предлагала ничего. - Опечатка в пути больше не выглядит успешной проверкой. Несуществующий путь – ошибка с внятным сообщением, а не “проверено 0 файлов, замечаний 0” при коде успеха; если путь есть, но исходников по нему нет, линтер предупреждает.
14.08.2026 – 0.64.0, 0.65.0
Добавлено
style/shadow-own-property– локальная переменная с именем свойства своего же элемента: присваивание уходит в переменную, а свойство остаётся прежним.code/unused-import– импорт подсистемы, к которой код не обращается.- Восемь правил про поведение платформы, которое компилятор принимает, а экран потом
опровергает (142 → 150):
code/permission-handlers-need-recalc– обработчик разрешений объявлен, а пересчёта нет нигде: правка алгоритма молча не действует на существующих данных.yaml/dynlist-row-editing–ПриРедактированииСтрокиу плоского списка: платформа это событие не вызывает, по нажатию открывается автоформа.yaml/localization-ref-to-template– ссылка$Словарь.Ключна ключ из секции шаблонов: применение падает “не удалось найти локализованную строку”.yaml/insert-row-needs-align– горизонтальная группа со вставкой без явного выравнивания: элемент со вставкой съезжает вниз относительно соседей.code/url-params-partial-encoding(info, выключено) – метод Url кодирует значение параметра частично, и адрес приходит обрезанным.yaml/dynlist-column-sort-lost(info, выключено) – колонка со значением-вызовом: щелчок по заголовку сортирует не по ней.yaml/matrix-group-max-width(info, выключено) – числовой максимум ширины у матричной группы: телефон рисует страницу десктопной шириной.yaml/card-literal-stretch-weight(info, выключено) – вес растягивания у карточки: в вертикальной колонке она схлопывается в Safari.
Изменено
- Литерал коллекции называет тип.
знч Пользователи = <Строка>[]– объявление не хуже конструктора, и несуществующий член массива после него теперь виден. - Файлы запросов
.xbqlпопали под проверку. Раньше неизвестную таблицу в них находил только серверный компилятор.
Исправлено
- Английские написания аннотаций.
@OnServerи его собратья читались как отсутствие аннотации, и метод проверялся по умолчанию. Теперь обе формы равноправны – в аннотациях, областях видимости и ключах событий формы. - Две дыры в разборе. Скобка в начале строки больше не приклеивается к предыдущему
выражению, а запись
пер Попытка: (()->Булево)? = Неопределеноразбирается: раньше на ней рассыпался весь файл. - События типа.
Кнопка.ПриНажатии = &Обработатьбольше не выглядит обращением к несуществующему члену; опечатка в имени события ловится по-прежнему. - Уникальность
Идсчитается в пределах владельца. Одинаковый идентификатор у реквизитов РАЗНЫХ объектов платформа принимает – так сделано в её же демо-проекте; проверяются идентификаторы объектов по проекту и идентификаторы элементов внутри своего файла. Заодно правило читает и английский ключId. - Три правила перестали спорить с законным кодом:
Ключу строки динамического списка, обязательное поле и параметр события со ссылочным типом, стандартный реквизит безИд. - Ссылки в README снова открываются: перекладка руководства оставила по тринадцать битых на язык. Теперь их бережёт тест.
- Сброс метамодели чистит и кэш
key_aliases– после смены корня данных дерево метаданных редактора могло показывать пары старой версии. - Сторож языка проверяет и неотслеживаемые файлы – новый модуль с голой кириллицей проскакивал мимо локальной проверки и всплывал в CI.
13.08.2026 – 0.63.0
Добавлено
- Правило
yaml/binding-needs-auto: биндинг с nullable-возвратом на свойстве, у которого нет пустого значения. Клиент пишет “Неожиданное значение” в серверный журнал на каждом пересчёте – в браузере этого не видно, на живом проекте накопилось почти две тысячи записей. - Правило
yaml/date-input-needs-plain-date: поле ввода даты с nullable-типом. Применение проходит чисто, но поле не рисуется, а опустевшая группа исчезает целиком. Лечение – непустой тип: “не задано” выражается пустой датой.
Исправлено
yaml/ref-needs-nullableпроверяет и союзы. Союз со ссылкой и без пустого значения не применяется – в том числе смешанный вродеСтрока|Товары.Ссылка; подсказка – добавить|?.
11.08.2026 – 0.62.0
Добавлено
- Правило
code/component-in-server-context: компонент интерфейса в серверном окружении. Тип компонента живёт на клиенте, поэтому серверная компиляция отвечает “Переменная X не определена”, а стенд молча откатывается на прежнюю сборку. - Ключ
--outу проверки: отчёт пишется в файл UTF-8 без BOM. Перенаправление оболочки на Windows добавляет BOM, о который падает разбор JSON.
Исправлено
- Свойство события журнала событий получает
Ид. Добавление поля теперь сверяет идентификатор с метамоделью в обе стороны: где он нужен – дописывает, где лишний – снимает.
09.08.2026 – 0.58.0, 0.59.0, 0.59.1, 0.60.0, 0.61.0
Добавлено
- Файл запроса
.xbqlстал языком. Подсветка и подсказка ввода: грамматика собрана из словаря самой платформы, весь файл считается запросом, и после псевдонима таблицы приходят её поля. Тот же словарь подсвечивает блокЗапрос{...}внутри модуля. - Переменная цикла
для X из Коллекцияполучает тип – по элементу коллекции. Для этого у структуры в индексе появился тип каждого поля; коллекция с двумя параметрами типа элемента не называет, и там подсказка молчит. - Члены типов-одиночек видов появились в данных: с 12 видов из 41 до 31.
- Вызов метода вида типизируется. Тип результата берётся из сигнатур документации (25 видов
из 31), поэтому подсказка знает, что вернули
Получить()набора констант,НайтиПоКоду()иПолучитьСсылку()справочника. - Свойства и методы менеджера вида разделены – подсказка подставляет скобки методу и не подставляет свойству.
- Правило
code/unknown-structure-field: поле структуры проекта сверяется с её объявлением (правил стало 139). - Устаревшие записи списка принятых видны и вычищаются:
--stale-baselineперечисляет записи, которые больше ничего не гасят,--prune-baselineудаляет их, не трогая живые. - Линтер сам находит список принятых замечаний – ищет файл
.xbsllint-baselineвверх от проверяемых файлов и называет найденный путь. Поиск отключает--no-baseline. - Ответы инструментов называют источник данных.
--version, MCPversion_infoи журнал запуска LSP несут корень данных и то, откуда он взят. conventions/untranslated-code-literal– видимый пользователю текст, оставшийся литералом в модуле (по умолчанию выключено).
Изменено
- Подсказка после точки предлагает то, что каталог знает о виде – вместо универсального списка, из-за которого всплывали несуществующие имена.
code/unused-methodсудит публичное API общих модулей. Метод глушат только аннотации, называющие вызывающего вне проекта; аннотации видимости и окружения больше не глушат.- Словарь видов элементов выводится из дистрибутива: видов стало 41 против 35, и журнал данных, панель отчётов и процесс интеграции перестали выглядеть неизвестными платформе.
yaml/unknown-propertyсудит 18 видов вместо 13.- Правила ресурсов знают оба написания каталога – платформа принимает
Resourcesнаравне с русским именем. - Создание обработки: реквизиту не пишется
Ид(у него нет такого свойства), создаётся пара модулей, а обработчик операции дописывается в модуль объекта. - Английские сообщения говорят по-английски – имена платформы и ключевые слова в сообщениях правил и в справке CLI подставляются на языке читателя.
- Белые списки имён вычищены компилятором: из 25 заявок 12 оказались ложными, таблица имён сущности сократилась с 15 записей до 4 подтверждённых.
Исправлено
- Типы, описанные в метаданных, не давали подсказок после точки – индексатор пропускал поля структур и константы набора.
- Правило
code/unknown-structure-fieldпадало в выпущенном колесе (0.59.0) – обход дерева читал узел способом, недоступным в нативной сборке. - Итоговая строка считает записи списка принятых, а не подавления: у одной записи их может быть несколько. Прежнее число осталось в json.
- Подсказка в начале сеанса не знала объектов проекта – ждала фоновый проход. Теперь запрос, пришедший раньше, строит индекс сам.
08.08.2026 – 0.57.2
Исправлено
- Навигация LSP больше не ждёт проверку всего проекта. Индекс строится первым, а запрос, пришедший раньше, строит его сам. На проекте среднего размера навигация оживает за 1,9 с вместо 7,2 с.
07.08.2026 – 0.54.0, 0.54.1, 0.55.0, 0.56.0, 0.57.0, 0.57.1
Добавлено
- Свойства элементов секций пишет инструмент (0.57.0).
meta_add_fieldпринимаетprops, парныйmeta_set_field_propertyправит уже существующее свойство; имена сверяются с классом элемента, значение уходит скаляром и берётся в кавычки только там, где это необходимо. То же в CLI (--prop,set-field-property) и в LSP. Представлениепри создании объекта (0.57.0):meta_new_objectпринимаетpresentation. У отчёта и команд это заголовок, у справочника, документа, плана обмена и хранилища настроек – имя строкового реквизита; заголовок в этом месте отклоняется с объяснением.- Локализация элемента строк (0.57.0):
meta_add_localizationсоздаёт файл перевода со значениями языка по умолчанию,meta_localization_infoотвечает, какие языки заявлены и какие переводы уже есть. Язык принимается написанием проекта или кодом папки. - Форма обработки (0.57.0):
meta_add_formгенерируетФормаОбработки– поля по реквизитам и команды операций через типКоманды, поэтому новые операции попадают на форму сами. - Схема метаданных отвечает и на имя класса-дескриптора (0.57.0): спросить можно тем именем, которое сама схема и называет.
- Схема метаданных называет, к какому типу реквизита относится свойство (0.56.0). Пер-типовые
свойства несут
applies–string,numberилиreference, ровно так, как применимость записана в документации вида. - Английские имена служебных файлов разрешаются всюду (0.55.0). Платформа принимает
Project.yamlиSubsystem.yaml; прежде проект с такими именами не находился вовсе. meta_delete_object/xbsl delete-object: удаление объекта целиком – пара yaml с модулем, формы объекта и компонент строки списка. Каждое оставшееся упоминание имени называется файлом и строкой, но не правится; до--applyкоманда отвечает планом.- Правило
conventions/untranslated-visible-literal– видимый текст, оставшийся кириллическим литералом там, где то же свойство проект уже вынес в словарь локализации. Судятся только ключи, которые проект где-то локализует. - Повторная регистрация идентификатора правила замещает прежнее, а не дублирует находки: правило, переезжающее между плагином и движком, какое-то время живёт в обоих.
xbsl extract --keep-previousсохраняет снимок данных прежней сборки, поэтомуxbsl data-diffработает сразу после регенерации.- Окружение называет себя само:
--versionперечисляет надстройки с версиями, MCPversion_infoотдаёт тот же срез данными, LSP пишет его в журнал запуска.
Исправлено
- Модуль формы англоязычного проекта больше не полон ложных ошибок (0.57.1). Базовый тип
компонента искался по русскому ключу
Наследует, поэтому в английском проекте каждое обращение к члену базового типа объявлялось неизвестным именем. Члены базового типа теперь принимаются в обоих написаниях. - Правило перестало молчать на несуществующих командах формы (0.57.1).
ВыполнитьЗаписатьиВыполнитьЗаписатьИЗакрытьчленами платформы не являются: встроенная команда – это свойство, а её запуск –ЗаписатьИЗакрыть.Выполнить(). yaml/presentation-fieldбольше не судит набор констант (0.57.0): секции реквизитов у него нет, и правило требовало невозможного. У справочника заголовок в этом свойстве по-прежнему ошибка.- Вставка в секцию не ломает файл с CRLF (0.57.0) – прежде в файле оставался одиночный
\r, и git нормализовал перевод строки во всём файле. - Английская справка пишет английские написания имён (0.57.0) там, где платформа их объявляет.
- Объекты англоязычного проекта больше не выпадают из разрезов по видам (issue #1). Вид разрешается по таблице видов самого сериализатора; все прежние написания остаются принятыми.
- Каталог данных по умолчанию у экстракторов указывал внутрь пакета дважды – запуск без
--data-dirмолча писал не туда. - Собственные JSON-файлы терпимы к BOM, а ошибка разбора называет файл.
self-updateвыбирает колесо по платформе, а не по виду установки – прежде одно переносимое обновление навсегда оставляло установку переносимой.
03.08.2026 – 0.53.0
Добавлено
- Ключи словаря индексируются как члены. У элемента
ЛокализованныеСтрокинет модуля, поэтому переход, ссылки и подсказка не знали оСловарь.Ключ(); теперь строка становится описанием в подсказке, а число параметров шаблона считается по старшей подстановке. - Экстрактор документации читает раздел событий. Прежде каталог утверждал, что у кнопки нет
ПриНажатии, а сравнение версий отчитывалось о мнимых удалениях. Чтобы это подействовало, данные нужно перегенерировать. - Заготовка метода для обработчика, который не является событием формы – строится по соседнему обработчику того же ключа; соседа нет – заготовка без параметров, и об этом сказано.
- Маршрут добавляется без сборки его текста:
xbsl/metaAddRouteпринимает шаблон вместе с методами, аxbsl/httpMethodsотвечает списком допустимых методов.
Изменено
- Сторож языка судит и цитаты: русское имя в комментарии – находка и в обратных кавычках, если словарь компилятора знает английское написание.
31.07.2026 – 0.49.0, 0.50.0, 0.51.0, 0.52.0
Добавлено
- Карточка платформенного метода показывает параметры. Сигнатуры извлекаются из документации, унаследованный метод получает сигнатуру того типа, который его объявляет. Данные нужно перегенерировать.
- Подсказка отвечает по платформе и по глобальному каталогу, а не только по проекту: у члена платформенного типа карточки не было вовсе, а глобальные имена до неё не доходили.
- Карточка проектного метода несёт сигнатуру и описание, а возвращаемое значение получает тип:
после
знч П = Модуль.Метод(...)точка предлагает члены того, что метод вернул. - Правило
code/unclosed-resource(правил стало 136): досрочныйвозвратилипрерватьпосреди перебора результата запроса оставляет его открытым. Лечение – модификаторисп.
Изменено
- Язык исходников охраняется, а не помнится:
tools/langguard.pyчитает добавленные строки и сообщает о кириллице в комментариях, docstring’ах и именах Python; CI запускает его на каждый push. - Оба английских журнала изменений охраняются – и словарным правилом, и бессловарным, поэтому публичный клон без словаря терминов тоже под охраной.
- MCP-сервер работает на обеих мажорных версиях
mcp, закрепление снято (mcp>=1.2,<3): импорт сначала пробует новое расположение класса, затем старое.
Исправлено
self-updateсразу после релиза больше не говорит, что колеса нет: список файлов берётся из simple-индекса, а не из отстающих JSON-метаданных.- Ссылка на документацию у члена больше не ведёт в случайную статью – страница разрешается через приёмник, а не поиском по голому имени.
29.07.2026 – 0.48.0
Добавлено
- Стандарт “Имена переменных и констант” стал правилами (правил стало 135). Шесть новых правил
style/: абстрактное имя, однобуквенное имя, отрицание в имени булева, тип в имени переменной, числительное в имени константы и переменная с именем элемента проекта. Все шесть –warning.
Изменено
style/abbreviation-caseчитает и кириллические аббревиатуры (Ид,Ндс,Фио): группа заглавных в имени даёт находку с подсказкой, как латинская.
Исправлено
self-updateнативной установки обновляет сам себя. Прежде команда предлагала снять собственное дерево процессов, а общие библиотеки в корнеsite-packagesперезаписывались на месте и падали, пока их держит работающее обновление. Теперь предки и потомки команды из держателей исключены, а такие библиотеки откладываются переименованием.
28.07.2026 – 0.47.0, 0.47.1, 0.47.2
Добавлено
code/unknown-tabular-member– член, вызванный у строк табличной части, обязан быть у типа-массива. Получатель типизируется метаданными проекта, поэтому прежние правила о членах эту форму не видели:Объект.Шаги.Количество()проходил проверку, а применение отвергало вызов (у массива –Размер).code/global-unavailable– глобальное имя, вызванное вне своего окружения.Сообщитьсуществует только на клиенте,ВычислитьиВыполнить– только на сервере; окружение метода берётся из вида элемента, пока@НаСервереили@НаКлиентене закрепят сторону.code/collection-field-needs-req– поле структуры с обобщённым типом, который не построить пустым.ЧитаемыйМассив<Строка>применение отвергает, аМассив<Строка>– случай обратный; что к чему относится, теперь факт в каталоге типов.code/var-needs-init– переменная объявлена типом без конструктора и без значения по умолчанию. Лечится либоТип?с проверкой, либо чтением нужного внутри попытки.
Изменено
- Тексты двух новых правил говорят словарём демо-проекта (
Задачи/Шаги), как и остальная документация.
Исправлено
- Extra
mcpзакреплён ниже 2. Вышедший в тот же деньmcp 2.0.0убрал модуль, который импортирует MCP-сервер, и свежая установка не поднималась.
27.07.2026 – 0.41.0, 0.42.0, 0.42.1, 0.43.0, 0.44.0, 0.45.0, 0.46.0
Добавлено
code/bound-property-assign– свойство, вычисляемое выражением, из кода не присваивают. Платформа такое присваивание отвергает, а в типовомпопытка/пойматьотказ не виден вовсе. Связь с данными (=Запись.Значение) правило не трогает: судится форма выражения.style/redundant-typeвидит типизированный пустой литерал:пер Артикулы: Массив<Число> = <Число>[]называет тип дважды. Распознаётся только массив.xbsl/metaKeys– пары ключей элемента для поверхностей вне python. Дерево метаданных редактора разбирает yaml само, и у английского объекта ветки были пусты.
Изменено
- Соглашения платформы по написанию кода стали стандартом: семь правил
style/работают по умолчанию и сообщают на уровнеwarning– длина строки, сравнение сИстина/Ложь, UpperCamelCase, литералы коллекций, интерполяция, лишний.ВСтроку(), регистр аббревиатур. Накопленному долгу место в списке принятых замечаний. - Выключенное правило само говорит, почему, прямо в
--list-rules; в машинном списке причина приходит полемoff_reason. - Каталог типов хранит объединение целиком (
Авто|БулевовместоАвто), поэтому данные отличают булево от значения, которое может быть булевым. - Все тексты
self-updateуведены в каталог сообщений –--lang enотвечает по-английски.
Исправлено
- То, что движок создаёт, теперь на языке проекта. Форма, созданная в английском проекте, приходила с русскими ключами и русскими именами типов; ключи и имена берутся из данных самой платформы, имена автора не трогаются.
- О том, что данные назвать не могут, инструмент говорит – английских значений интерфейсных перечислений в поставке нет, и отчёт называет такие значения, а не выдумывает их.
style/boolean-compareбольше не срабатывает там, где сравнение обязательно. Краткая форма не компилируется, как только значение nullable или составное, поэтому операнд типизируется, и нарушением сравнение остаётся, только когда тип ровноБулево.- Создание метаданных читает проект, написанный английскими написаниями ключей. Прежде часть операций отвечала “объект не найден”, а три – успехом с неверным результатом.
- Параллельная проверка выпущенного колеса больше не обрывается. Результат рабочего процесса вёз кэш файла, который в нативной сборке не распаковывается. Кэш больше не пересекает границу процессов, и результат похудел с 1,96 МБ до 0,58 МБ.
- Переименование объекта, отличающееся только регистром, больше не отклоняется – на регистронезависимой файловой системе оно выполняется через временное имя, а сбой откатывается.
- Переименование по регистру предупреждает о системе контроля версий: git на такой файловой системе покажет кириллическое переименование как удаление и добавление.
- Проектное правило локализации больше не передаёт между процессами целые исходники – в факт едут только вызовы, стоящие рядом со сравнением.
26.07.2026 – 0.36.1, 0.37.0, 0.37.1, 0.37.2, 0.37.3, 0.38.0, 0.39.0, 0.40.0
Добавлено
- Четыре правила: права по объектам и локализация (правил стало 122).
code/per-object-permissions-need-common– общий обработчик разрешений обязателен и при per-object;code/permission-field-not-declared– поле вне объявленного списка расчёта;yaml/placeholder-key-in-strings– подстановка в секцииСтроки, которая компилируется в метод без параметров;code/compare-with-localized– сравнение с локализованным значением, которое на другом языке молча не срабатывает. yaml/delete-current-needs-immediate(правил стало 118):УдалятьТекущийу владельца, который только помечает запись, роняет применение всего проекта.- Два правила про окружение исполнения (правил стало 117):
code/client-available-needs-context–@ДоступноСКлиентау метода компонента интерфейса безстатическийили@Контекстный;code/server-module-in-client-context– обращение к серверному общему модулю из клиентского метода. Оба отказа видны только серверной компиляции. - Пять правил про то, что платформа принимает, но не делает (правил стало 115): пустая группа с
заданным размером, слишком длинная подсказка,
Закрыть()в собственномПередЗакрытием, несуществующая функция языка запросов и каталоги проекта, разошедшиеся с дескриптором.
Изменено
- Сторож английских документов: русские написания имён платформы в английских текстах бракует тест, а не глаз. Знает три законных случая – имя файла, одиночная буква как предмет разговора и ссылка на русского близнеца.
- Тексты говорят о фактах, а не о том, как они получены (0.37.1–0.37.3). Что принимает компилятор и от чего страхует правило – осталось, прочее убрано; поведение правил не менялось.
Исправлено
- Сторож синхрона смотрел четыре места из восьми, поэтому счётчики правил на страницах сайта разъехались незамеченными. Теперь проверяются все восемь.
- Обход дерева пропускал всё, что внутри условия – ветви
еслихранятся парами, а обходчик спускался только в списки узлов. - Колесо 0.36.0 не проверяло ничего: обход дерева в одном правиле опирался на способ, которого в нативной сборке нет. В тестах такой обход теперь ловится миной.
- Падение одного правила больше не роняет проверку – ошибка правила стала отдельной находкой под его же идентификатором, остальные правила отрабатывают.
25.07.2026 – 0.35.0, 0.36.0
Добавлено
- Два правила про статический метод (
code/this-in-static-method,code/instance-call-from-static): контекста объекта у него нет, поэтомуэтотв теле и голый вызов обычного метода того же владельца компилятор отвергает. code/local-method-cross-module(правил стало 101):Модуль.Метод(...)обязан звать метод с аннотацией видимости – без неё метод виден только в своём модуле.
Изменено
code/unknown-static-memberтипизирует значение, пришедшее из чужого модуля: каждый модуль публикует типы возврата своих методов, и проектная фаза связывает с нимиМодуль.Метод(...).- Создание метаданных пишет слот по его кардинальности: первый ребёнок слота-массива ложится элементом списка, а не одиночным вложенным блоком, иначе сборка отвергает форму.
Исправлено
- Проект, записанный английскими написаниями метаданных, судится наравне с русским. Прежде
правила искали
ВидЭлемента, не находили и пропускали файл целиком – в нём не ловилась даже опечатка. На русских исходниках находки остались прежними. - Формы тоже: английский компонент разбирается и судится. Модель формы читает ключи через словарь мета-объектов компилятора, поэтому конструктор, панель структуры и правка видят одно дерево независимо от языка файла.
- У демо-проекта появился английский двойник (
demo-en/), и он же сторож: тест требует, чтобы оба двойника давали одни и те же находки на тех же строках. - Создание метаданных пишет на языке проекта – язык определяется по большинству файлов, а не настройкой.
- Публичный CI был красным с прошлого релиза, и вскрыла это имитация клона без данных: три теста двуязычия ждали написаний, которых в таком клоне нет.
- Инструмент MCP с опиской в имени аргумента теперь падает, а не отрабатывает молча со значениями по умолчанию.
24.07.2026 – 0.32.0, 0.33.0, 0.34.0
Добавлено
- Правило
yaml/unexpected-type-argument(правил стало 100): параметр типа у свойства, которое ui-схема объявляет без параметра, – это другой тип, и применение его отвергает. - Ui-схема несёт раздел
type_params– параметры типа дженериков и их умолчания; без него проверка выше давала ложные срабатывания. ui_schemaотвечает и на имена вне палитры – команды, фрагменты и группы командного интерфейса, элемент списка значений.xbsl extract– генерация датасета командой CLI. Экстракторы переехали в пакет, поэтому установленный пакет генерирует данные без клона репозитория.xbsl data-diff [старая] [новая]– что изменилось в платформе между двумя версиями данных. Члены сравниваются с развёрнутым наследованием,--format text|md|json.- Индекс версий двигает умолчание только вперёд: регенерация старой версии его не сбивает.
- Правило
code/invalid-string-escape– недопустимая управляющая последовательность в строковом литерале ловится до серверной компиляции. - MCP
ui_schema: параметрыbriefиproperty– строка на свойство вместо полной схемы и полная запись одного свойства. - Схема метаданных разворачивает закрытое ограничение типа свойства в список допустимых значений.
Исправлено
code/unknown-memberсудит и переменные дженерика по его голове: уЧитаемыйМассив<Задача>набор членов тот же, что уЧитаемыйМассив, а прежде параметризованный тип пропускался целиком.- Поиск по документации не отвечает пустотой на многословный запрос – когда ни одна страница не несёт всех слов, поиск ослабляется до “любое из слов”.
xbsl extract --helpназывает команду, а не путь интерпретатора.- Экстрактор stdlib снова распознаёт компоненты интерфейса новых дистрибутивов – маркером служит и адрес ссылки, а не только квалифицированное имя.
- Переменная по имени
Запросбольше не читается ключевым словом – без{это обычное имя. - Проверка одиночного файла не теряет тень парного yaml, поэтому реквизит формы не судится как одноимённый тип stdlib.
- Подсказка при наведении не документирует как тип stdlib ни объявленную переменную с невыведенным типом, ни имя, объявленное парным yaml.
23.07.2026 – 0.31.0, 0.31.1
Изменено
- Каталог типов stdlib записывает более полные типы членов и досбирает поверхности со страниц-топиков, поэтому проверки членов и подсказка совпадают с тем, что платформа предоставляет (0.31.0).
Исправлено
code/resource-bare-nameне считает ссылкуinbase/...путём с каталогом: ресурс, загруженный в базу приложения, – это ключ поиска (0.31.0).- Ключ ресурса – путь относительно каталога
Ресурсыподсистемы: ссылки на подкаталоги легальны (0.31.1).
22.07.2026 – 0.28.0, 0.29.0, 0.30.0, 0.30.1
Добавлено
- Сайт документации (docs.keyfire.ru/xbsl), полный справочник команд и справка – целиком на русском и английском (0.29.0).
- Метамодель разрешает схему элемента коллекции – значения перечисления, реквизита, измерения, ресурса, поля структуры, – поэтому линтер видит полную схему со значениями по умолчанию (0.29.0).
- Операция удаления обработчика формы (
xbsl/removeHandler): отвязывает событие и удаляет его метод одним изменением (0.28.0).
Изменено
- Быстрее на больших проектах: кэши слоя данных, разбор YAML через libyaml, пулы рабочих процессов по размеру задачи (0.30.0).
- Подсказка при наведении на тип несёт его описание из документации, а не одну ссылку (0.28.0).
- Подсказка проходит цепочку членов за ссылкой-свойством, сторож останавливает обход на границе замыкания stdlib (0.30.1).
Исправлено
yaml/bare-object-valueдопускает$-ссылку на локализованную строку там, где ждут литерал (0.30.1).- Перегенерированные данные подхватываются без перезапуска (0.30.1).
- Серверы за необязательными extras на минимальной установке аккуратно пропускаются, а не падают импортом (0.30.1).
21.07.2026 – 0.25.0, 0.26.0, 0.26.1, 0.27.0
Добавлено
- Четыре правила линтера:
yaml/bare-object-value(голое слово там, где ждут литерал или биндинг),code/resource-bare-nameиcode/unknown-resource(ресурс голым именем файла) иyaml/no-expression-in-literal(0.26.0). - Три правила движка:
yaml/ref-needs-nullable,yaml/unknown-enum-valueиyaml/standard-field-length(0.25.0). - Единое API метамодели – типы свойств, перечисления и значения по умолчанию через один интерфейс (0.27.0).
Изменено
- Создание метаданных принимает вид элемента на любом языке платформы (0.26.0).
- Языковые данные приходят из компилятора, а не из констант (0.26.0).
code/undefined-nameчитает имена и в интерполяции строк (0.25.0).- Подсказка следует языку разработки проекта (0.26.1).
Релизы до 0.25.0 предшествуют этой истории изменений. История продукта до 0.1.0 – в CHANGELOG расширения VS Code.