Контур проверки XML-структур метаданных 1С: корректность файлов объектов, форм, схем компоновки, ролей и макетов; регистрация объекта в составе конфигурации; сверка «диск ↔ состав» в обе стороны; права на объекты в ролях расширения. Вызывается оркестратором quality-gate при изменении XML; напрямую — по запросу «проверь метаданные», «провалидируй расширение», «почему объект не попал в сборку».
Scanned 8/30/2026
Install to Claude Code
npx -y skills add Romandredan/1c-quality-gate --skill xml-structure-review --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Xml Structure Review?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/romandredan-xml-structure-review)More formats (shields.io, HTML) on the badges page.
---
name: xml-structure-review
description: >-
Контур проверки XML-структур метаданных 1С: корректность файлов объектов, форм, схем
компоновки, ролей и макетов; регистрация объекта в составе конфигурации; сверка «диск ↔
состав» в обе стороны; права на объекты в ролях расширения. Вызывается оркестратором
quality-gate при изменении XML; напрямую — по запросу «проверь метаданные»,
«провалидируй расширение», «почему объект не попал в сборку».
license: MIT
---
# xml-structure-review — контур XML метаданных
Проверяет структуру выгрузки конфигурации и расширений. Применимость определяется не объёмом
правки, а фактом: **менялись ли XML метаданных**.
| Класс | Глубина |
|---|---|
| C0 | пропуск |
| C1 | не применим, если XML не менялся; иначе — валидация изменённых файлов |
| C2 | валидация изменённых объектов **плюс проверка регистрации** |
| C3 | полный проход: валидация, сверка диск↔состав в обе стороны, права в ролях |
## Прогон механики — субагент `xml-runner`
Запуск скриптов и разбор их вывода делегируй субагенту `xml-runner`, передав список изменённых
файлов и каталог выгрузки. Он вернёт вердикт, находки с путями и строками, а также раздел «не
проверено».
Причина в контексте: валидаторы печатают до тридцати ошибок на файл, и на правке класса C3 их
вывод вытесняет всё остальное раньше, чем дело дойдёт до отчёта. Твоя работа начинается после
его отчёта — триаж находок, привязка к типовым дефектам и решение, что чинить.
Субагента может не быть — тогда прогоняй скрипты сам по разделам ниже. Записи следа в обоих
случаях формируешь **ты**: субагент возвращает факты и в формат следа их не оформляет.
---
## 1. Сверка «диск ↔ состав» — главная проверка контура
```bash
node "$QG/tools/xml/orphan-check.mjs" <каталог выгрузки>
```
**Почему это первое, что нужно проверять.** Объект метаданных, лежащий на диске, но не
внесённый в секцию `ChildObjects` файла `Configuration.xml`, **не попадает в собранный
артефакт**. При этом:
- загрузка конфигурации из файлов такие файлы молча игнорирует и не разрешает ссылки на них
вглубь BSL — сборка проходит «успешно», лог пуст;
- валидаторы структуры это тоже не ловят: они проверяют порядок **уже зарегистрированных**
объектов и про файл вне состава ничего не знают.
Итог: объект отсутствует в поставке, все проверки зелёные, падение происходит в рантайме у
пользователя. Это слепое пятно всей штатной цепочки, и закрывает его только явная сверка.
Обратное направление не менее важно: имя в составе без файла на диске ломает саму сборку.
**Коды возврата:** 0 — расхождений нет, 2 — есть сироты либо отсутствующие файлы.
**Каталоги вне карты типов** скрипт не додумывает, а выносит в раздел «не проверено»:
молчаливый пропуск здесь означал бы ровно ту дыру, ради которой проверка и написана.
### Как чинить
Найденную сироту **регистрируют**, а не пересоздают: добавляют строку `<Тип>Имя</Тип>` в
нужную группу `ChildObjects`. Пересоздание объекта средствами генерации перезапишет его XML и
может затереть уже описанные реквизиты, измерения и ресурсы.
---
## 2. Уникальность UUID — вторая проверка того же класса
```bash
node "$QG/tools/xml/uuid-unique.mjs" <каталог выгрузки>
```
Объект, скопированный вместе со своим `uuid`, и заглушка вида `a1b2c3d4-…` дают два разных
объекта с одним идентификатором. Платформа при загрузке либо отвергает выгрузку, либо
оставляет один из двух — второй исчезает бесшумно, ровно как файл-сирота. Валидаторы
структуры это пропускают по устройству: каждый разбирает свой файл и проверяет формат GUID,
а совпадение с соседним файлом лежит за пределами его области зрения.
Проверяются файлы с корневым элементом `MetaDataObject`; повтор внутри одного файла — тоже
находка, продублированный блок реквизита уносит с собой `uuid` оригинала.
**Графические схемы не читаются.** Это измерено, а не предположено: на полной выгрузке УТ
(19 693 файла метаданных, 63 837 идентификаторов) дублей между объектами ноль, а все повторы
пришлись на `Ext/Flowchart.xml` — точки карты маршрута бизнес-процесса, которые платформа
копирует между процессами. Скан схем давал бы находку на каждой типовой конфигурации.
**Коды возврата:** 0 — дублей нет, 2 — есть дубли либо каталог не прочитан.
**Как чинить:** менять UUID у **нового** объекта, а не у исходного. Правка идентификатора
существующего объекта в рабочей базе равносильна его удалению и созданию заново — ссылки на
него теряются.
---
## 3. Валидация структуры файлов
**Путь передавай параметром `-Path`** — он принимается всеми валидаторами без исключения:
```bash
python "$QG/tools/xml/meta-validate.py" -Path "<путь>"
```
У каждого скрипта есть ещё собственное имя параметра, и они разные (`-ObjectPath`,
`-FormPath`, `-RightsPath`, `-SubsystemPath`, `-TemplatePath`, `-CIPath`, `-ConfigPath`,
`-ExtensionPath`). Не подставляй имя от одного скрипта другому: `allow_abbrev=False`, и
вызов упадёт с ошибкой разбора аргументов. `-Path` снимает вопрос целиком.
| Что проверяется | Валидатор | Что передавать |
|---|---|---|
| Объект метаданных (справочник, документ, регистр, перечисление) | `meta-validate.py` | файл `Объект.xml` |
| Управляемая форма | `form-validate.py` | файл `Form.xml` |
| Схема компоновки данных | `skd-validate.py` | файл макета СКД |
| Роль и права | `role-validate.py` | любое из трёх: `Roles/Имя.xml`, каталог `Roles/Имя`, `Roles/Имя/Ext/Rights.xml` |
| Подсистема | `subsystem-validate.py` | файл подсистемы |
| Макет табличного документа | `mxl-validate.py` | файл макета |
| Командный интерфейс | `interface-validate.py` | файл командного интерфейса |
| Конфигурация целиком | `cf-validate.py` | корень выгрузки |
| Расширение конфигурации | `cfe-validate.py` | корень расширения |
| Внешняя обработка или отчёт | `epf-validate.py` | корень исходников обработки |
Роль — единственный объект, где проверяется не файл объекта, а `Rights.xml`; валидатор
приводит к нему любую из трёх форм пути сам. До версии 0.4.3 файл `Roles/Имя.xml` не
распознавался и разбирался как `Rights.xml`, давая **ложную ошибку** при меньшем числе
проверок — то есть выглядел как находка в чужом коде.
Флаги: `-Detailed` — подробный вывод, `-MaxErrors N` — ограничение числа сообщений,
`-OutFile <путь>` — вывод в файл.
**Если Python недоступен** — запиши `[qg skipped: layer=xml, scope=structure-validation,
reason=python_unavailable]` и всё равно выполни пункт 1: сверка диск↔состав работает на Node и
от Python не зависит. Она же и есть самая ценная часть контура.
**Если валидатор упал с `ModuleNotFoundError: No module named 'lxml'`** — это не находка в
проверяемом коде, а недоступность инструмента: все валидаторы разбирают XML через `lxml`.
Запиши `[qg skipped: layer=xml, scope=structure-validation, reason=lxml_unavailable]`, назови
лечение (`pip install lxml`) и так же выполни пункт 1. Молча выдать это за ошибку файла —
худший исход: правка пойдёт в исправный XML.
---
## 4. Права на объекты в ролях расширения
Для расширений, содержащих собственные роли: **собственный объект расширения без явно
выданных прав невидим пользователю**, и ни сборка, ни валидаторы этого не показывают.
Проверяй, что для каждого нового объекта расширения права заданы в файле прав роли. Симптом
пропуска — объект существует, механизм работает, но у пользователя пустой список или
отсутствующая команда.
**Контр-сигналы — где отсутствие прав законно.** Прежде чем выпускать находку, сверься с
`references/role-rights-model.md`:
- у `Перечисление` и `РегламентноеЗадание` объектных прав **не существует** — пустой набор
здесь никогда не находка, а запись о правах в роли, наоборот, дефект;
- право `Use` у HTTP- и веб-сервисов выдаётся точке вызова
(`HTTPService.<Имя>.URLTemplate.<Шаблон>.Method.<Метод>`, `WebService.<Имя>.Operation.<Имя>`),
а не сервису целиком;
- отсутствующий `Ext/Rights.xml` — валидное состояние пустой роли, а не потерянный файл.
**Собственное против заимствованного.** Права требуются собственным объектам и собственным
реквизитам расширения; у заимствованных они наследуются от конфигурации. Признак
принадлежности задан **отсутствием** тега, а не пометкой — разбор в
`references/cfe-object-belonging.md`.
---
## 5. Дефекты, которые проходят валидацию
Валидаторы разбирают XML по схеме формата и молчат о конструкциях, законных по схеме, но
ломающих платформу. Такой дефект опаснее обычного: отчёт зелёный, а артефакт не собирается.
**`AutoCommandBar` таблицы с `Autofill` и вложенным `ExtendedTooltip`.** Загрузка внешней
обработки или отчёта уходит в бесконечный цикл со 100% CPU — не ошибка и не диалог, а
зависание. `form-validate.py` при этом даёт «OK».
```xml
<!-- Вешает загрузку -->
<AutoCommandBar name="ТаблицаКоманднаяПанель" id="10">
<Autofill>false</Autofill>
<ExtendedTooltip name="…" id="11"/>
</AutoCommandBar>
<!-- Законные формы -->
<AutoCommandBar name="ТаблицаКоманднаяПанель" id="10"/>
<AutoCommandBar name="ТаблицаКоманднаяПанель" id="10">
<ChildItems>…кнопки и группы…</ChildItems>
</AutoCommandBar>
```
**Контр-сигнал:** `Autofill` и вложенный `ExtendedTooltip` законны у `CommandBar` —
это отдельный элемент формы, и там конструкция встречается штатно. Признак действует только
внутри `AutoCommandBar` **таблицы**.
**Заявленная неточность:** в том же разборе снят заодно `<TitleLocation>Top</TitleLocation>` у
`Table`, но отдельно он не изолирован. Как самостоятельная находка не выпускается — только как
кандидат при продолжении бисекции.
**Правило времени вместо ожидания.** Загрузка обработки на пустой базе — секунды; на рабочей
базе штатное время порядка семи-восьми минут. Прогон дольше трёх-пяти минут **на пустой базе**
означает зацикливание: процесс снимают и бисектят форму по группам элементов, а не ждут.
---
## 6. Типовые дефекты структуры
| Дефект | Признак | Чем ловится |
|---|---|---|
| Файл-сирота | объект на диске вне состава | пункт 1 |
| Отсутствующий файл | имя в составе без файла | пункт 1 |
| Дубль UUID | два объекта или реквизита с одним идентификатором | пункт 2 |
| Нарушен порядок объектов в составе | несоответствие каноническому порядку типов | `cfe-validate.py` |
| Невалидные элементы формы | элементы вне схемы формата | `form-validate.py` |
| Рассогласованные версии формата | разные версии в связанных файлах | `meta-validate.py` |
| Обработчик формы без процедуры | `qg:XML-FORM-HANDLER-MISSING`: `<Event>` называет имя, которого нет ни в модуле формы, ни в модуле базовой формы. Открытию формы это не мешает (проверено на платформе) — дефект спит до наступления события, отсюда 🟠, а не блокировка | `form-validate.py` |
| Действие команды без процедуры | `qg:XML-FORM-ACTION-MISSING`: то же для `<Action>` команды формы | `form-validate.py` |
| Отсутствие хранилища вариантов у отчёта | не задано хранилище настроек | `epf-validate.py` |
| Права объекта не заданы в роли | объект расширения не виден пользователю | пункт 4 |
| Права выданы типу, у которого их нет | запись `Enum.*` или `ScheduledJob.*` в файле прав | `role-validate.py`, пункт 4 |
| Неполное заимствование | `Adopted` без `ExtendedConfigurationObject` | `cfe-validate.py`, пункт 4 |
| Зависание загрузки на командной панели | `Autofill` и `ExtendedTooltip` внутри `AutoCommandBar` таблицы | пункт 5, валидаторами не ловится |
| Параметр СКД против виртуальной таблицы | `qg:SKD-PARAM-VT-COLLISION`: параметр `Период`/`НачалоПериода`/`КонецПериода` типа `StandardPeriod` при периодической ВТ без явных слотов — «Несоответствие типов» при формировании | `skd-validate.py` |
| Недопустимое поле в выборке группировки СКД | `qg:SKD-GROUP-NONAGGREGATE-FIELD`: поле — не поле группировки (с учётом родителей и реквизитов) и не ресурс — полный отказ формирования | `skd-validate.py` |
| Группировка СКД без выбранных полей | `qg:SKD-GROUP-EMPTY-SELECTION`: ни полей, ни Авто — запрос выполняется, отчёт молча пуст (предупреждение) | `skd-validate.py` |
---
## Записи следа
```
[qg applied: layer=xml, scope=registration-check, ids=[qg:XML-ORPHAN], verdict=violation:qg:XML-ORPHAN]
[qg applied: layer=xml, scope=uuid-uniqueness, ids=[qg:XML-UUID-DUP], verdict=clean]
[qg applied: layer=xml, scope=structure-validation, ids=[qg:XML-STRUCT], verdict=clean]
[qg applied: layer=xml, scope=form-binding, ids=[qg:XML-FORM-HANDLER-MISSING,qg:XML-FORM-ACTION-MISSING], verdict=clean]
[qg skipped: layer=xml, reason=not_applicable]
```
**Первые три строки печатают сами инструменты** — переноси их вывод дословно. Запись
`structure-validation` печатает любой из валидаторов XML (`meta-`, `form-`, `role-`, `skd-` и
остальные семь): проверка структуры называется одним именем независимо от вида файла. Каждый
инструмент отмечается в журнале прогонов, и валидатор следа сверяет: запись `applied` по
проверке, инструмент которой не запускался, снятие гейта не пройдёт.
Семантические находки СКД (`qg:SKD-PARAM-VT-COLLISION`, `qg:SKD-GROUP-NONAGGREGATE-FIELD`,
`qg:SKD-GROUP-EMPTY-SELECTION`) печатает тот же `skd-validate.py` внутри прогона
`structure-validation` — отдельного вызова для них нет. **Тексты запросов в `<query>` схемы
он не разбирает** — их проверяет `query-lint.mjs` контура `code`, которому изменённые XML
передаются наравне с `.bsl`.
Формат — `../quality-gate/references/evidence-format.md`.
**Валидность структуры не означает компилируемость.** Валидаторы разбирают XML и не
компилируют тела модулей; синтаксическая ошибка внутри процедуры проходит их все. Если
проверка конфигурации платформой не запускалась, нужна запись
`[qg not_verified: dimension=compilation, reason=no_platform]`.
---
## Принципы
- **Регистрация проверяется раньше структуры.** Идеально валидный XML вне состава бесполезен.
- **Сверка идёт в обе стороны.** Сирота ломает рантайм, отсутствующий файл ломает сборку.
- **Зелёная сборка ничего не доказывает.** Загрузка конфигурации из файлов игнорирует
незарегистрированное молча.
- **Сироту регистрируют, а не пересоздают** — пересоздание затирает содержимое объекта.
- **Отсутствие прав — не всегда упущение.** У части типов объектных прав не существует, и
требование выдать их отправляет искать несуществующую настройку.
- **Валидатор молчит и о законном, и о неразобранном.** «OK» на форме, которая вешает
загрузку, — не вердикт о работоспособности, а граница схемы формата.
> `$QG` — каталог установленного плагина. Как его разрешить (переменная `CLAUDE_PLUGIN_ROOT`
> в оболочке пуста) — см. раздел «Путь к инструментам плагина» в навыке `quality-gate`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!