Перейти к содержимому
XBSL (1C:Element)
Русский
Esc
navigateopen⌘Jpreview
На этой странице

История изменений

Что менялось в инструментарии xbsl от версии к версии, с разбивкой по дням.

Заметные изменения инструментария xbsl – движка на Python, на котором работают линтер, серверы LSP и MCP, индекс документации и скаффолдинг метаданных. Записи сгруппированы по дням; версии, вышедшие в этот день, перечислены в заголовке. Формат основан на Keep a Changelog, проект следует семантическому версионированию. У расширения VS Code своя история в editors/vscode/CHANGELOG.ru.md. Записи используют русские написания имён метаданных платформы (Наименование, Код, Реквизиты); английские написания – в английской истории.

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 и запроса LSP xbsl/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_infoproject-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). Голова английского составного имени – его последнее слово (BankAccountsAccounts), число головы определяется суффиксной эвристикой с перечнем неправильных множественных – морфологический 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 и CLI form-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, MCP version_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). Пер-типовые свойства несут appliesstring, 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 перечисляет надстройки с версиями, MCP version_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.

Последнее обновление 30 августа 2026 г.

Эта страница была полезной?