diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1
index aaab22215..7d86b8967 100644
--- a/.claude/skills/meta-validate/scripts/meta-validate.ps1
+++ b/.claude/skills/meta-validate/scripts/meta-validate.ps1
@@ -1,4 +1,4 @@
-# meta-validate v1.21 — Validate 1C metadata object structure
+# meta-validate v1.22 — Validate 1C metadata object structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -1466,17 +1466,69 @@ if ($childObjNode) {
}
}
+# --- Состав конфигурации (ChildObjects из Configuration.xml) ---
+# Платформа судит о существовании объекта по СОСТАВУ, а не по наличию файла. Файла может не быть
+# в частичной выгрузке: такой фрагмент грузится через /LoadConfigFromFiles -listFile слиянием с базой,
+# и ссылка на невыгруженный объект остаётся рабочей. Отсюда два разных исхода:
+# нет в составе -> платформа отвергнет загрузку всегда -> ERROR
+# в составе, файла нет -> полная загрузка упадёт, частичная пройдёт -> WARN
+# ChildObjects конфигурации — плоский список <Вид>ИмяВид>, поэтому ищем подстроку в границах секции
+# без копирования и без разбора XML: batch-режим порождает процесс на объект, и полная карта (~100 мс)
+# оплачивалась бы каждым объектом.
+
+$script:cfgText = $null
+$script:cfgChildStart = -1
+$script:cfgChildLen = 0
+$script:cfgTextLoaded = $false
+
+function Initialize-ConfigText {
+ if ($script:cfgTextLoaded) { return }
+ $script:cfgTextLoaded = $true
+ if (-not $script:configDir) { return }
+ $cfgPath = Join-Path $script:configDir "Configuration.xml"
+ if (-not (Test-Path $cfgPath)) { return }
+ try {
+ $script:cfgText = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8)
+ } catch {
+ $script:cfgText = $null
+ return
+ }
+ $s = $script:cfgText.IndexOf('', [System.StringComparison]::Ordinal)
+ $e = $script:cfgText.LastIndexOf('', [System.StringComparison]::Ordinal)
+ if ($s -ge 0 -and $e -gt $s) {
+ $script:cfgChildStart = $s
+ $script:cfgChildLen = $e - $s
+ }
+}
+
+function Test-ConfigIsExtension {
+ Initialize-ConfigText
+ if (-not $script:cfgText) { return $false }
+ return $script:cfgText.Contains("ConfigurationExtensionPurpose")
+}
+
+# $true — объект есть в составе; $false — нет; $null — состав неизвестен (нет Configuration.xml
+# или в нём нет ChildObjects), тогда вызывающий оставляет мягкий уровень.
+function Test-InConfigComposition([string]$kind, [string]$name) {
+ Initialize-ConfigText
+ if ($script:cfgChildStart -lt 0) { return $null }
+ $needle = "<$kind>$name$kind>"
+ if ($script:cfgText.IndexOf($needle, $script:cfgChildStart, $script:cfgChildLen, [System.StringComparison]::Ordinal) -ge 0) {
+ return $true
+ }
+ # Промах по точному совпадению — сверяем без учёта регистра, как это делает платформа.
+ # Порядок именно такой: Ordinal на порядок дешевле, а промахи редки.
+ return ($script:cfgText.IndexOf($needle, $script:cfgChildStart, $script:cfgChildLen, [System.StringComparison]::OrdinalIgnoreCase) -ge 0)
+}
+
# --- Check 16: Reference type existence — типы вида CatalogRef.X должны разрешаться в объекты конфигурации ---
-# WARN-уровень: ложное срабатывание на частичных выгрузках хуже пропуска. Расширения (CFE) пропускаем —
-# их типы ссылаются на объекты базовой конфигурации, которых нет в выгрузке расширения.
+# Уровень выбирается по составу конфигурации: типа нет в ChildObjects — «Неизвестное имя типа» при
+# загрузке (ERROR); объект в составе есть, а файла в выгрузке нет — частичная выгрузка (WARN).
+# Расширения (CFE) пропускаем — их типы ссылаются на объекты базовой конфигурации, которых в выгрузке
+# расширения нет.
if ($script:configDir) {
- $isExtension = $false
- $cfgXmlPath = Join-Path $script:configDir "Configuration.xml"
- if (Test-Path $cfgXmlPath) {
- $cfgContent = [System.IO.File]::ReadAllText($cfgXmlPath, [System.Text.Encoding]::UTF8)
- if ($cfgContent.Contains("ConfigurationExtensionPurpose")) { $isExtension = $true }
- }
+ $isExtension = Test-ConfigIsExtension
if (-not $isExtension) {
$refDirMap = @{
"CatalogRef"="Catalogs"; "DocumentRef"="Documents"; "EnumRef"="Enums"
@@ -1486,7 +1538,9 @@ if ($script:configDir) {
}
$typeNodes = $xmlDoc.SelectNodes("//v8:Type", $ns)
$checkedRefs = @{} # refKey -> $true если найден; для OK-условия
- $missingRefs = @{} # refKey -> refDir
+ $missingRefs = @{} # refKey -> refDir; объект есть в составе, файла в выгрузке нет
+ $absentRefs = @{} # refKey -> refDir; объекта нет в составе конфигурации
+ $unknownRefs = @{} # refKey -> refDir; состав неизвестен (Configuration.xml без ChildObjects)
foreach ($tn in $typeNodes) {
$tv = $tn.InnerText.Trim()
if (-not $tv) { continue }
@@ -1506,14 +1560,35 @@ if ($script:configDir) {
$checkedRefs[$refKey] = $true
} else {
$checkedRefs[$refKey] = $false
- $missingRefs[$refKey] = $refDir
+ # Вид метаданных в ChildObjects — это тип без суффикса Ref (CatalogRef -> Catalog);
+ # DefinedType суффикса не имеет и пишется в состав как есть.
+ $refKindTag = if ($refCat.EndsWith("Ref")) { $refCat.Substring(0, $refCat.Length - 3) } else { $refCat }
+ $inComposition = Test-InConfigComposition $refKindTag $refName
+ if ($inComposition -eq $false) {
+ $absentRefs[$refKey] = $refDir
+ } elseif ($inComposition -eq $true) {
+ $missingRefs[$refKey] = $refDir
+ } else {
+ $unknownRefs[$refKey] = $refDir
+ }
+ }
+ }
+ if ($absentRefs.Count -gt 0) {
+ foreach ($ak in ($absentRefs.Keys | Sort-Object)) {
+ Report-Error "16. Ссылочный тип '$ak' — объекта нет в составе конфигурации ($($absentRefs[$ak])/) — «Неизвестное имя типа» при загрузке"
}
}
if ($missingRefs.Count -gt 0) {
foreach ($mk in ($missingRefs.Keys | Sort-Object)) {
- Report-Warn "16. Ссылочный тип '$mk' не найден в конфигурации ($($missingRefs[$mk])/) — при загрузке будет ошибка неизвестного типа"
+ Report-Warn "16. Ссылочный тип '$mk' — объект есть в составе конфигурации, файла объекта в выгрузке нет ($($missingRefs[$mk])/)"
}
- } elseif ($checkedRefs.Count -gt 0) {
+ }
+ if ($unknownRefs.Count -gt 0) {
+ foreach ($uk in ($unknownRefs.Keys | Sort-Object)) {
+ Report-Warn "16. Ссылочный тип '$uk' не найден в конфигурации ($($unknownRefs[$uk])/)"
+ }
+ }
+ if ($absentRefs.Count -eq 0 -and $missingRefs.Count -eq 0 -and $unknownRefs.Count -eq 0 -and $checkedRefs.Count -gt 0) {
Report-OK "16. Reference types: $($checkedRefs.Count) resolved"
}
}
@@ -1590,6 +1665,11 @@ if ($mdRefNodes -and $mdRefNodes.Count -gt 0) {
# регистрацию формы в ChildObjects — работает и на одиночном файле; для чужого и общей формы нужна
# конфигурация. Заимствованные объекты расширения (ObjectBelonging=Adopted) пропускаем: их формы
# живут в основной конфигурации, в выгрузке расширения их нет.
+#
+# Уровень везде выбирается по составу, а не по наличию файла (см. Test-InConfigComposition):
+# нет в ChildObjects — платформа откажет и при полной, и при частичной загрузке (ERROR);
+# в составе есть, а файла в выгрузке нет — это фрагмент частичной выгрузки, и загрузится он или нет,
+# зависит от состояния конфигурации БД, которого валидатору не видно (WARN).
$formOwnerDirMap = @{
"Catalog"="Catalogs"; "Document"="Documents"; "DocumentJournal"="DocumentJournals"
@@ -1606,14 +1686,7 @@ $belongingNode = $typeNode.SelectSingleNode("md:Properties/md:ObjectBelonging",
$isAdopted = $belongingNode -and $belongingNode.InnerText.Trim() -eq "Adopted"
if (-not $isAdopted) {
- $isExtension20 = $false
- if ($script:configDir) {
- $cfgXmlPath20 = Join-Path $script:configDir "Configuration.xml"
- if (Test-Path $cfgXmlPath20) {
- $cfgContent20 = [System.IO.File]::ReadAllText($cfgXmlPath20, [System.Text.Encoding]::UTF8)
- if ($cfgContent20.Contains("ConfigurationExtensionPurpose")) { $isExtension20 = $true }
- }
- }
+ $isExtension20 = Test-ConfigIsExtension
# формы своего объекта: имена из ChildObjects (сравнение регистронезависимое — как у платформы)
$ownForms = @{}
@@ -1656,8 +1729,13 @@ if (-not $isAdopted) {
$cfDir = Join-Path (Join-Path $script:configDir "CommonForms") $parts[1]
$cfOk = (Test-Path "$cfDir.xml") -or (Test-Path (Join-Path (Join-Path $cfDir "Ext") "Form.xml")) -or (Test-Path (Join-Path $cfDir "Form.xml"))
if (-not $cfOk) {
- Report-Error "20. $tag '$ref' — общая форма не найдена в конфигурации (CommonForms/$($parts[1])) — «Неизвестный объект метаданных» при загрузке"
- $formRefBad = $true
+ $cfInComposition = Test-InConfigComposition "CommonForm" $parts[1]
+ if ($cfInComposition -eq $true) {
+ Report-Warn "20. $tag '$ref' — общая форма есть в составе конфигурации, файла формы в выгрузке нет (CommonForms/$($parts[1]))"
+ } else {
+ Report-Error "20. $tag '$ref' — общей формы нет в составе конфигурации (CommonForms/$($parts[1])) — «Неизвестный объект метаданных» при загрузке"
+ $formRefBad = $true
+ }
}
continue
}
@@ -1675,8 +1753,16 @@ if (-not $isAdopted) {
Report-Error "20. $tag '$ref' — форма '$refForm' не зарегистрирована в ChildObjects объекта (есть: $known) — «Неизвестный объект метаданных» при загрузке"
$formRefBad = $true
} elseif ((Test-Path $ownDir) -and -not (Test-FormFile20 $ownDir $refForm)) {
- Report-Error "20. $tag '$ref' — форма зарегистрирована в ChildObjects, но файл формы отсутствует ($objName/Forms/$refForm)"
- $formRefBad = $true
+ # Форма в составе объекта есть, файла нет. Для дерева, претендующего на полноту
+ # (рядом лежит Configuration.xml), это ошибка целостности — полная загрузка упадёт
+ # на «Файл объекта не существует». Для фрагмента частичной выгрузки — норма:
+ # такой файл грузится через -listFile слиянием с конфигурацией БД.
+ if ($script:configDir) {
+ Report-Error "20. $tag '$ref' — форма зарегистрирована в ChildObjects, но файл формы отсутствует ($objName/Forms/$refForm)"
+ $formRefBad = $true
+ } else {
+ Report-Warn "20. $tag '$ref' — форма есть в ChildObjects, файла формы в выгрузке нет ($objName/Forms/$refForm)"
+ }
}
continue
}
@@ -1690,7 +1776,15 @@ if (-not $isAdopted) {
}
$refObjXml = Join-Path (Join-Path $script:configDir $refDir20) "$refObj.xml"
if (-not (Test-Path $refObjXml)) {
- Report-Warn "20. $tag '$ref' — объект '$refKind.$refObj' не найден в конфигурации ($refDir20/)"
+ $objInComposition = Test-InConfigComposition $refKind $refObj
+ if ($objInComposition -eq $false) {
+ Report-Error "20. $tag '$ref' — объекта '$refKind.$refObj' нет в составе конфигурации ($refDir20/) — «Неизвестный объект метаданных» при загрузке"
+ $formRefBad = $true
+ } elseif ($objInComposition -eq $true) {
+ Report-Warn "20. $tag '$ref' — объект '$refKind.$refObj' есть в составе конфигурации, файла объекта в выгрузке нет ($refDir20/)"
+ } else {
+ Report-Warn "20. $tag '$ref' — объект '$refKind.$refObj' не найден в конфигурации ($refDir20/)"
+ }
continue
}
if (-not (Test-FormFile20 (Join-Path (Join-Path $script:configDir $refDir20) $refObj) $refForm)) {
diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py
index a58fe929b..0f86ee27f 100644
--- a/.claude/skills/meta-validate/scripts/meta-validate.py
+++ b/.claude/skills/meta-validate/scripts/meta-validate.py
@@ -1,4 +1,4 @@
-# meta-validate v1.21 — Validate 1C metadata object structure (Python port)
+# meta-validate v1.22 — Validate 1C metadata object structure (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import os
@@ -1388,21 +1388,77 @@ if child_obj_node is not None:
if check15_ok and cmd_count > 0:
report_ok(f"15. Commands: {cmd_count} command(s), groups valid")
+# ── Состав конфигурации (ChildObjects из Configuration.xml) ──
+# Платформа судит о существовании объекта по СОСТАВУ, а не по наличию файла. Файла может не быть
+# в частичной выгрузке: такой фрагмент грузится через /LoadConfigFromFiles -listFile слиянием с базой,
+# и ссылка на невыгруженный объект остаётся рабочей. Отсюда два разных исхода:
+# нет в составе -> платформа отвергнет загрузку всегда -> ERROR
+# в составе, файла нет -> полная загрузка упадёт, частичная пройдёт -> WARN
+# ChildObjects конфигурации — плоский список <Вид>ИмяВид>, поэтому ищем подстроку в границах секции
+# без копирования и без разбора XML: batch-режим порождает процесс на объект, и полная карта (~100 мс)
+# оплачивалась бы каждым объектом.
+
+_cfg_text = None
+_cfg_child_lower = None
+_cfg_child_start = -1
+_cfg_child_end = -1
+_cfg_text_loaded = False
+
+
+def _init_config_text():
+ global _cfg_text, _cfg_child_start, _cfg_child_end, _cfg_text_loaded
+ if _cfg_text_loaded:
+ return
+ _cfg_text_loaded = True
+ if not config_dir:
+ return
+ cfg_path = os.path.join(config_dir, "Configuration.xml")
+ if not os.path.exists(cfg_path):
+ return
+ try:
+ with open(cfg_path, "r", encoding="utf-8") as f:
+ _cfg_text = f.read()
+ except Exception:
+ _cfg_text = None
+ return
+ s = _cfg_text.find("")
+ e = _cfg_text.rfind("")
+ if s >= 0 and e > s:
+ _cfg_child_start = s
+ _cfg_child_end = e
+
+
+def config_is_extension():
+ _init_config_text()
+ return bool(_cfg_text) and "ConfigurationExtensionPurpose" in _cfg_text
+
+
+def in_config_composition(kind, name):
+ """True — объект есть в составе; False — нет; None — состав неизвестен
+ (нет Configuration.xml или в нём нет ChildObjects), тогда вызывающий оставляет мягкий уровень."""
+ global _cfg_child_lower
+ _init_config_text()
+ if _cfg_child_start < 0:
+ return None
+ needle = "<{0}>{1}{0}>".format(kind, name)
+ if _cfg_text.find(needle, _cfg_child_start, _cfg_child_end) >= 0:
+ return True
+ # Промах по точному совпадению — сверяем без учёта регистра, как это делает платформа.
+ # Порядок именно такой: точный поиск на порядок дешевле, а промахи редки. Нижний регистр
+ # берём от СРЕЗА и проверяем факт вхождения: смещения в lower() совпадать с оригиналом не обязаны.
+ if _cfg_child_lower is None:
+ _cfg_child_lower = _cfg_text[_cfg_child_start:_cfg_child_end].lower()
+ return needle.lower() in _cfg_child_lower
+
+
# ── Check 16: Reference type existence — типы вида CatalogRef.X должны разрешаться в объекты конфигурации ──
-# WARN-уровень: ложное срабатывание на частичных выгрузках хуже пропуска. Расширения (CFE) пропускаем —
-# их типы ссылаются на объекты базовой конфигурации, которых нет в выгрузке расширения.
+# Уровень выбирается по составу конфигурации: типа нет в ChildObjects — «Неизвестное имя типа» при
+# загрузке (ERROR); объект в составе есть, а файла в выгрузке нет — частичная выгрузка (WARN).
+# Расширения (CFE) пропускаем — их типы ссылаются на объекты базовой конфигурации, которых в выгрузке
+# расширения нет.
if config_dir:
- is_extension = False
- cfg_xml_path = os.path.join(config_dir, "Configuration.xml")
- if os.path.exists(cfg_xml_path):
- try:
- with open(cfg_xml_path, "r", encoding="utf-8") as f:
- cfg_content = f.read()
- if "ConfigurationExtensionPurpose" in cfg_content:
- is_extension = True
- except Exception:
- pass
+ is_extension = config_is_extension()
if not is_extension:
ref_dir_map = {
"CatalogRef": "Catalogs", "DocumentRef": "Documents", "EnumRef": "Enums",
@@ -1411,7 +1467,9 @@ if config_dir:
"ExchangePlanRef": "ExchangePlans", "TaskRef": "Tasks", "DefinedType": "DefinedTypes",
}
checked_refs = {} # ref_key -> найден ли; для условия OK
- missing_refs = {} # ref_key -> ref_dir
+ missing_refs = {} # ref_key -> ref_dir; объект есть в составе, файла в выгрузке нет
+ absent_refs = {} # ref_key -> ref_dir; объекта нет в составе конфигурации
+ unknown_refs = {} # ref_key -> ref_dir; состав неизвестен (Configuration.xml без ChildObjects)
for tn in find_all(root, ".//v8:Type"):
tv = inner_text(tn).strip()
if not tv:
@@ -1436,11 +1494,23 @@ if config_dir:
checked_refs[ref_key] = True
else:
checked_refs[ref_key] = False
- missing_refs[ref_key] = ref_dir
- if missing_refs:
- for mk in sorted(missing_refs):
- report_warn(f"16. Ссылочный тип '{mk}' не найден в конфигурации ({missing_refs[mk]}/) — при загрузке будет ошибка неизвестного типа")
- elif checked_refs:
+ # Вид метаданных в ChildObjects — это тип без суффикса Ref (CatalogRef -> Catalog);
+ # DefinedType суффикса не имеет и пишется в состав как есть.
+ ref_kind_tag = ref_cat[:-3] if ref_cat.endswith("Ref") else ref_cat
+ in_composition = in_config_composition(ref_kind_tag, ref_name)
+ if in_composition is False:
+ absent_refs[ref_key] = ref_dir
+ elif in_composition is True:
+ missing_refs[ref_key] = ref_dir
+ else:
+ unknown_refs[ref_key] = ref_dir
+ for ak in sorted(absent_refs):
+ report_error(f"16. Ссылочный тип '{ak}' — объекта нет в составе конфигурации ({absent_refs[ak]}/) — «Неизвестное имя типа» при загрузке")
+ for mk in sorted(missing_refs):
+ report_warn(f"16. Ссылочный тип '{mk}' — объект есть в составе конфигурации, файла объекта в выгрузке нет ({missing_refs[mk]}/)")
+ for uk in sorted(unknown_refs):
+ report_warn(f"16. Ссылочный тип '{uk}' не найден в конфигурации ({unknown_refs[uk]}/)")
+ if not absent_refs and not missing_refs and not unknown_refs and checked_refs:
report_ok(f"16. Reference types: {len(checked_refs)} resolved")
# ── Check 18: свойства, появившиеся в новых версиях формата ──
@@ -1510,6 +1580,11 @@ if md_ref_nodes:
# регистрацию формы в ChildObjects — работает и на одиночном файле; для чужого и общей формы нужна
# конфигурация. Заимствованные объекты расширения (ObjectBelonging=Adopted) пропускаем: их формы
# живут в основной конфигурации, в выгрузке расширения их нет.
+#
+# Уровень везде выбирается по составу, а не по наличию файла (см. in_config_composition):
+# нет в ChildObjects — платформа откажет и при полной, и при частичной загрузке (ERROR);
+# в составе есть, а файла в выгрузке нет — это фрагмент частичной выгрузки, и загрузится он или нет,
+# зависит от состояния конфигурации БД, которого валидатору не видно (WARN).
form_owner_dir_map = {
"Catalog": "Catalogs", "Document": "Documents", "DocumentJournal": "DocumentJournals",
@@ -1537,16 +1612,7 @@ def _form_file_exists_20(base_dir, form_name):
if not is_adopted:
- is_extension_20 = False
- if config_dir:
- cfg_xml_path_20 = os.path.join(config_dir, "Configuration.xml")
- if os.path.exists(cfg_xml_path_20):
- try:
- with open(cfg_xml_path_20, "r", encoding="utf-8") as f:
- if "ConfigurationExtensionPurpose" in f.read():
- is_extension_20 = True
- except Exception:
- pass
+ is_extension_20 = config_is_extension()
# формы своего объекта: имена из ChildObjects (сравнение регистронезависимое — как у платформы)
own_forms = {}
@@ -1585,9 +1651,13 @@ if not is_adopted:
or os.path.exists(os.path.join(cf_dir, "Ext", "Form.xml"))
or os.path.exists(os.path.join(cf_dir, "Form.xml")))
if not cf_ok:
- report_error(f"20. {tag} '{ref}' — общая форма не найдена в конфигурации "
- f"(CommonForms/{parts[1]}) — «Неизвестный объект метаданных» при загрузке")
- form_ref_bad = True
+ if in_config_composition("CommonForm", parts[1]) is True:
+ report_warn(f"20. {tag} '{ref}' — общая форма есть в составе конфигурации, "
+ f"файла формы в выгрузке нет (CommonForms/{parts[1]})")
+ else:
+ report_error(f"20. {tag} '{ref}' — общей формы нет в составе конфигурации "
+ f"(CommonForms/{parts[1]}) — «Неизвестный объект метаданных» при загрузке")
+ form_ref_bad = True
continue
if len(parts) != 4 or parts[2] != "Form":
@@ -1604,9 +1674,17 @@ if not is_adopted:
f"ChildObjects объекта (есть: {known}) — «Неизвестный объект метаданных» при загрузке")
form_ref_bad = True
elif os.path.isdir(own_dir) and not _form_file_exists_20(own_dir, ref_form):
- report_error(f"20. {tag} '{ref}' — форма зарегистрирована в ChildObjects, но файл "
- f"формы отсутствует ({obj_name}/Forms/{ref_form})")
- form_ref_bad = True
+ # Форма в составе объекта есть, файла нет. Для дерева, претендующего на полноту
+ # (рядом лежит Configuration.xml), это ошибка целостности — полная загрузка упадёт
+ # на «Файл объекта не существует». Для фрагмента частичной выгрузки — норма:
+ # такой файл грузится через -listFile слиянием с конфигурацией БД.
+ if config_dir:
+ report_error(f"20. {tag} '{ref}' — форма зарегистрирована в ChildObjects, но файл "
+ f"формы отсутствует ({obj_name}/Forms/{ref_form})")
+ form_ref_bad = True
+ else:
+ report_warn(f"20. {tag} '{ref}' — форма есть в ChildObjects, файла формы "
+ f"в выгрузке нет ({obj_name}/Forms/{ref_form})")
continue
# чужой объект (например журнал документов) — нужна конфигурация
@@ -1618,7 +1696,16 @@ if not is_adopted:
continue
ref_obj_xml = os.path.join(config_dir, ref_dir_20, ref_obj + ".xml")
if not os.path.exists(ref_obj_xml):
- report_warn(f"20. {tag} '{ref}' — объект '{ref_kind}.{ref_obj}' не найден в конфигурации ({ref_dir_20}/)")
+ obj_in_composition = in_config_composition(ref_kind, ref_obj)
+ if obj_in_composition is False:
+ report_error(f"20. {tag} '{ref}' — объекта '{ref_kind}.{ref_obj}' нет в составе "
+ f"конфигурации ({ref_dir_20}/) — «Неизвестный объект метаданных» при загрузке")
+ form_ref_bad = True
+ elif obj_in_composition is True:
+ report_warn(f"20. {tag} '{ref}' — объект '{ref_kind}.{ref_obj}' есть в составе "
+ f"конфигурации, файла объекта в выгрузке нет ({ref_dir_20}/)")
+ else:
+ report_warn(f"20. {tag} '{ref}' — объект '{ref_kind}.{ref_obj}' не найден в конфигурации ({ref_dir_20}/)")
continue
if not _form_file_exists_20(os.path.join(config_dir, ref_dir_20, ref_obj), ref_form):
report_error(f"20. {tag} '{ref}' — форма '{ref_form}' не найдена у объекта "
diff --git a/tests/skills/cases/meta-validate/error-commonform-absent.json b/tests/skills/cases/meta-validate/error-commonform-absent.json
new file mode 100644
index 000000000..b07cf6f92
--- /dev/null
+++ b/tests/skills/cases/meta-validate/error-commonform-absent.json
@@ -0,0 +1,9 @@
+{
+ "name": "Ссылка на общую форму, которой нет в составе конфигурации — ошибка",
+ "setup": "fixture:catalog-commonform-absent",
+ "params": { "objectPath": "Catalogs/Товары.xml" },
+ "expectError": true,
+ "expect": {
+ "stdoutContains": "общей формы нет в составе конфигурации"
+ }
+}
diff --git a/tests/skills/cases/meta-validate/error-default-form-file-missing.json b/tests/skills/cases/meta-validate/error-default-form-file-missing.json
deleted file mode 100644
index 39284204e..000000000
--- a/tests/skills/cases/meta-validate/error-default-form-file-missing.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "Валидатор находит ошибку: форма зарегистрирована в ChildObjects, но файла формы нет",
- "setup": "fixture:catalog-form-file-missing",
- "params": { "objectPath": "Catalogs/Товары.xml" },
- "expectError": true,
- "expect": {
- "stdoutContains": "файл формы отсутствует"
- }
-}
diff --git a/tests/skills/cases/meta-validate/error-default-form-foreign-absent.json b/tests/skills/cases/meta-validate/error-default-form-foreign-absent.json
new file mode 100644
index 000000000..16b9c86e9
--- /dev/null
+++ b/tests/skills/cases/meta-validate/error-default-form-foreign-absent.json
@@ -0,0 +1,9 @@
+{
+ "name": "Ссылка на форму чужого объекта, которого нет в составе конфигурации — ошибка (#84)",
+ "setup": "fixture:catalog-foreign-form-absent",
+ "params": { "objectPath": "Catalogs/Товары.xml" },
+ "expectError": true,
+ "expect": {
+ "stdoutContains": "объекта 'Document.НетТакого' нет в составе конфигурации"
+ }
+}
diff --git a/tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json b/tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json
new file mode 100644
index 000000000..94fb766c9
--- /dev/null
+++ b/tests/skills/cases/meta-validate/error-form-file-missing-full-tree.json
@@ -0,0 +1,9 @@
+{
+ "name": "Полная выгрузка: форма в ChildObjects, а файла формы нет — ошибка целостности",
+ "setup": "fixture:catalog-form-file-missing-full-tree",
+ "params": { "objectPath": "Catalogs/Товары.xml" },
+ "expectError": true,
+ "expect": {
+ "stdoutContains": "но файл формы отсутствует"
+ }
+}
diff --git a/tests/skills/cases/meta-validate/warn-reftype-missing.json b/tests/skills/cases/meta-validate/error-reftype-absent.json
similarity index 72%
rename from tests/skills/cases/meta-validate/warn-reftype-missing.json
rename to tests/skills/cases/meta-validate/error-reftype-absent.json
index a958d088d..d073696e1 100644
--- a/tests/skills/cases/meta-validate/warn-reftype-missing.json
+++ b/tests/skills/cases/meta-validate/error-reftype-absent.json
@@ -1,5 +1,5 @@
{
- "name": "Валидатор предупреждает о несуществующем ссылочном типе реквизита (Check 16)",
+ "name": "Ссылочный тип реквизита на объект, которого нет в составе конфигурации (Check 16)",
"setup": "empty-config",
"preRun": [
{
@@ -9,8 +9,9 @@
}
],
"params": { "objectPath": "Catalogs/ТестСсылкаБитая" },
+ "expectError": true,
"noSnapshot": "meta-validate только читает и печатает — эталон зафиксировал бы выход preRun (meta-compile), а не проверяемого навыка; проверяется stdout",
"expect": {
- "stdoutContains": "16. Ссылочный тип 'CatalogRef.НетТакогоСправочника'"
+ "stdoutContains": "16. Ссылочный тип 'CatalogRef.НетТакогоСправочника' — объекта нет в составе конфигурации"
}
}
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml
new file mode 100644
index 000000000..718966fb7
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Catalogs/Товары.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+ 663a8901-0032-4f18-bb1a-ce2174cbece4
+ bb20df17-ebde-4175-9079-c789e3cbd195
+
+
+ 7005f331-5c27-428e-a561-8b0f78595780
+ 39d1fb1b-dfb7-414f-af63-39a637b60657
+
+
+ ead16e67-7005-48d1-83cc-dc0b07edee35
+ 0d389498-9b1a-4b69-80e1-43a73bd2138d
+
+
+ 9c0c6357-31b4-466e-ab3d-7238b5133945
+ 791f1ff6-e378-4777-bfd5-09495fb526e0
+
+
+ cdd35860-4d89-4091-8400-c46e656a66d1
+ e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740
+
+
+
+ Товары
+
+
+ ru
+ Товары
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.Товары.StandardAttribute.Description
+ Catalog.Товары.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+ CommonForm.НетТакой
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml
new file mode 100644
index 000000000..8f2f14efb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-absent/Configuration.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ d0bb0360-4e09-4936-8e34-a3dc3851f67e
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ d9499468-cbbe-410c-b456-6f4a6ef7e4e7
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 7378dde3-6113-4bb6-93bf-b57ff8406e1f
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ 7398f41d-8349-4e40-8925-88bf7b3590bd
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 7688edd2-4e1f-4261-acd8-732c551316eb
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 2202f59a-a576-43d5-9b90-52ad63efe348
+
+
+
+ ValRepro
+
+
+ ru
+ ValRepro
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ Товары
+ Прочие
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml
new file mode 100644
index 000000000..f3cd4df56
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Catalogs/Товары.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+ 663a8901-0032-4f18-bb1a-ce2174cbece4
+ bb20df17-ebde-4175-9079-c789e3cbd195
+
+
+ 7005f331-5c27-428e-a561-8b0f78595780
+ 39d1fb1b-dfb7-414f-af63-39a637b60657
+
+
+ ead16e67-7005-48d1-83cc-dc0b07edee35
+ 0d389498-9b1a-4b69-80e1-43a73bd2138d
+
+
+ 9c0c6357-31b4-466e-ab3d-7238b5133945
+ 791f1ff6-e378-4777-bfd5-09495fb526e0
+
+
+ cdd35860-4d89-4091-8400-c46e656a66d1
+ e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740
+
+
+
+ Товары
+
+
+ ru
+ Товары
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.Товары.StandardAttribute.Description
+ Catalog.Товары.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+ CommonForm.ОбщаяФорма
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml
new file mode 100644
index 000000000..41bf33b83
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-commonform-not-dumped/Configuration.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ d0bb0360-4e09-4936-8e34-a3dc3851f67e
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ d9499468-cbbe-410c-b456-6f4a6ef7e4e7
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 7378dde3-6113-4bb6-93bf-b57ff8406e1f
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ 7398f41d-8349-4e40-8925-88bf7b3590bd
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 7688edd2-4e1f-4261-acd8-732c551316eb
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 2202f59a-a576-43d5-9b90-52ad63efe348
+
+
+
+ ValRepro
+
+
+ ru
+ ValRepro
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+ ОбщаяФорма
+ Русский
+ Товары
+ Прочие
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml
new file mode 100644
index 000000000..b2a42c0cf
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Catalogs/Товары.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+ 663a8901-0032-4f18-bb1a-ce2174cbece4
+ bb20df17-ebde-4175-9079-c789e3cbd195
+
+
+ 7005f331-5c27-428e-a561-8b0f78595780
+ 39d1fb1b-dfb7-414f-af63-39a637b60657
+
+
+ ead16e67-7005-48d1-83cc-dc0b07edee35
+ 0d389498-9b1a-4b69-80e1-43a73bd2138d
+
+
+ 9c0c6357-31b4-466e-ab3d-7238b5133945
+ 791f1ff6-e378-4777-bfd5-09495fb526e0
+
+
+ cdd35860-4d89-4091-8400-c46e656a66d1
+ e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740
+
+
+
+ Товары
+
+
+ ru
+ Товары
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.Товары.StandardAttribute.Description
+ Catalog.Товары.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+ Document.НетТакого.Form.Ф
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml
new file mode 100644
index 000000000..8f2f14efb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-form-absent/Configuration.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ d0bb0360-4e09-4936-8e34-a3dc3851f67e
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ d9499468-cbbe-410c-b456-6f4a6ef7e4e7
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 7378dde3-6113-4bb6-93bf-b57ff8406e1f
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ 7398f41d-8349-4e40-8925-88bf7b3590bd
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 7688edd2-4e1f-4261-acd8-732c551316eb
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 2202f59a-a576-43d5-9b90-52ad63efe348
+
+
+
+ ValRepro
+
+
+ ru
+ ValRepro
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ Товары
+ Прочие
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml
new file mode 100644
index 000000000..9cf52aa6c
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Catalogs/Товары.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+ 663a8901-0032-4f18-bb1a-ce2174cbece4
+ bb20df17-ebde-4175-9079-c789e3cbd195
+
+
+ 7005f331-5c27-428e-a561-8b0f78595780
+ 39d1fb1b-dfb7-414f-af63-39a637b60657
+
+
+ ead16e67-7005-48d1-83cc-dc0b07edee35
+ 0d389498-9b1a-4b69-80e1-43a73bd2138d
+
+
+ 9c0c6357-31b4-466e-ab3d-7238b5133945
+ 791f1ff6-e378-4777-bfd5-09495fb526e0
+
+
+ cdd35860-4d89-4091-8400-c46e656a66d1
+ e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740
+
+
+
+ Товары
+
+
+ ru
+ Товары
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.Товары.StandardAttribute.Description
+ Catalog.Товары.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+ Catalog.Прочие.Form.ФормаСписка
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml
new file mode 100644
index 000000000..8f2f14efb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-foreign-not-dumped/Configuration.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ d0bb0360-4e09-4936-8e34-a3dc3851f67e
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ d9499468-cbbe-410c-b456-6f4a6ef7e4e7
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 7378dde3-6113-4bb6-93bf-b57ff8406e1f
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ 7398f41d-8349-4e40-8925-88bf7b3590bd
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 7688edd2-4e1f-4261-acd8-732c551316eb
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 2202f59a-a576-43d5-9b90-52ad63efe348
+
+
+
+ ValRepro
+
+
+ ru
+ ValRepro
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ Товары
+ Прочие
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml
new file mode 100644
index 000000000..4c6ef67e5
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+ 663a8901-0032-4f18-bb1a-ce2174cbece4
+ bb20df17-ebde-4175-9079-c789e3cbd195
+
+
+ 7005f331-5c27-428e-a561-8b0f78595780
+ 39d1fb1b-dfb7-414f-af63-39a637b60657
+
+
+ ead16e67-7005-48d1-83cc-dc0b07edee35
+ 0d389498-9b1a-4b69-80e1-43a73bd2138d
+
+
+ 9c0c6357-31b4-466e-ab3d-7238b5133945
+ 791f1ff6-e378-4777-bfd5-09495fb526e0
+
+
+ cdd35860-4d89-4091-8400-c46e656a66d1
+ e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740
+
+
+
+ Товары
+
+
+ ru
+ Товары
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.Товары.StandardAttribute.Description
+ Catalog.Товары.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+ Catalog.Товары.Form.ФормаЭлемента
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl
new file mode 100644
index 000000000..5f282702b
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Catalogs/Товары/Ext/ObjectModule.bsl
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml
new file mode 100644
index 000000000..8f2f14efb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-form-file-missing-full-tree/Configuration.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ d0bb0360-4e09-4936-8e34-a3dc3851f67e
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ d9499468-cbbe-410c-b456-6f4a6ef7e4e7
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 7378dde3-6113-4bb6-93bf-b57ff8406e1f
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ 7398f41d-8349-4e40-8925-88bf7b3590bd
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 7688edd2-4e1f-4261-acd8-732c551316eb
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 2202f59a-a576-43d5-9b90-52ad63efe348
+
+
+
+ ValRepro
+
+
+ ru
+ ValRepro
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ Товары
+ Прочие
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml
new file mode 100644
index 000000000..b291157cd
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Catalogs/Товары.xml
@@ -0,0 +1,133 @@
+
+
+
+
+
+ 663a8901-0032-4f18-bb1a-ce2174cbece4
+ bb20df17-ebde-4175-9079-c789e3cbd195
+
+
+ 7005f331-5c27-428e-a561-8b0f78595780
+ 39d1fb1b-dfb7-414f-af63-39a637b60657
+
+
+ ead16e67-7005-48d1-83cc-dc0b07edee35
+ 0d389498-9b1a-4b69-80e1-43a73bd2138d
+
+
+ 9c0c6357-31b4-466e-ab3d-7238b5133945
+ 791f1ff6-e378-4777-bfd5-09495fb526e0
+
+
+ cdd35860-4d89-4091-8400-c46e656a66d1
+ e6cb5b8e-44ae-41f5-b9d7-10bfdbf41740
+
+
+
+ Товары
+
+
+ ru
+ Товары
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.Товары.StandardAttribute.Description
+ Catalog.Товары.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+ Catalog.Товары.Form.ФормаЭлемента
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+ Партнёр
+
+
+ ru
+ Партнёр
+
+
+
+
+ cfg:CatalogRef.Прочие
+
+ false
+
+
+
+ false
+
+ false
+ false
+
+
+ false
+
+ DontCheck
+ Items
+
+
+ Auto
+ Auto
+
+
+ Auto
+
+ DontIndex
+ Use
+ Use
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml
new file mode 100644
index 000000000..8f2f14efb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-reftype-not-dumped/Configuration.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ d0bb0360-4e09-4936-8e34-a3dc3851f67e
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ d9499468-cbbe-410c-b456-6f4a6ef7e4e7
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 7378dde3-6113-4bb6-93bf-b57ff8406e1f
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ 7398f41d-8349-4e40-8925-88bf7b3590bd
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 93b8f975-cd8b-4e8c-ac14-ea95b90b19bd
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 7688edd2-4e1f-4261-acd8-732c551316eb
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 2202f59a-a576-43d5-9b90-52ad63efe348
+
+
+
+ ValRepro
+
+
+ ru
+ ValRepro
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ Товары
+ Прочие
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/warn-commonform-not-dumped.json b/tests/skills/cases/meta-validate/warn-commonform-not-dumped.json
new file mode 100644
index 000000000..a56711fbf
--- /dev/null
+++ b/tests/skills/cases/meta-validate/warn-commonform-not-dumped.json
@@ -0,0 +1,13 @@
+{
+ "name": "Общая форма есть в составе конфигурации, но не выгружена — предупреждение, не ошибка",
+ "setup": "fixture:catalog-commonform-not-dumped",
+ "params": {
+ "objectPath": "Catalogs/Товары.xml"
+ },
+ "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout",
+ "skipPlatformVerify": "фикстура — неполная выгрузка: общая форма есть в составе, файла нет намеренно; полная загрузка такого дерева невозможна",
+ "expect": {
+ "stdoutContains": "общая форма есть в составе конфигурации, файла формы в выгрузке нет",
+ "stdoutNotContains": "[ERROR]"
+ }
+}
diff --git a/tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json b/tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json
new file mode 100644
index 000000000..7a3b2dae5
--- /dev/null
+++ b/tests/skills/cases/meta-validate/warn-default-form-foreign-not-dumped.json
@@ -0,0 +1,13 @@
+{
+ "name": "Чужой объект есть в составе конфигурации, но не выгружен — предупреждение, не ошибка",
+ "setup": "fixture:catalog-foreign-not-dumped",
+ "params": {
+ "objectPath": "Catalogs/Товары.xml"
+ },
+ "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout",
+ "skipPlatformVerify": "фикстура — неполная выгрузка: объект есть в составе, файла нет намеренно; полная загрузка такого дерева невозможна",
+ "expect": {
+ "stdoutContains": "есть в составе конфигурации, файла объекта в выгрузке нет",
+ "stdoutNotContains": "[ERROR]"
+ }
+}
diff --git a/tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json b/tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json
new file mode 100644
index 000000000..580cd6abd
--- /dev/null
+++ b/tests/skills/cases/meta-validate/warn-form-file-missing-fragment.json
@@ -0,0 +1,13 @@
+{
+ "name": "Фрагмент частичной выгрузки: форма в ChildObjects, файла формы нет — предупреждение, не ошибка",
+ "setup": "fixture:catalog-form-file-missing",
+ "params": {
+ "objectPath": "Catalogs/Товары.xml"
+ },
+ "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout",
+ "skipPlatformVerify": "фикстура — фрагмент частичной выгрузки (файла формы нет намеренно); платформа грузит такой фрагмент только через -listFile слиянием с базой, полная загрузка невозможна",
+ "expect": {
+ "stdoutContains": "файла формы в выгрузке нет",
+ "stdoutNotContains": "[ERROR]"
+ }
+}
diff --git a/tests/skills/cases/meta-validate/warn-reftype-not-dumped.json b/tests/skills/cases/meta-validate/warn-reftype-not-dumped.json
new file mode 100644
index 000000000..91b2c15b5
--- /dev/null
+++ b/tests/skills/cases/meta-validate/warn-reftype-not-dumped.json
@@ -0,0 +1,13 @@
+{
+ "name": "Ссылочный тип на объект, который есть в составе, но не выгружен — предупреждение (Check 16)",
+ "setup": "fixture:catalog-reftype-not-dumped",
+ "params": {
+ "objectPath": "Catalogs/Товары.xml"
+ },
+ "noSnapshot": "фикстура статична, meta-validate только читает и печатает — эталон зафиксировал бы саму фикстуру; проверяется stdout",
+ "skipPlatformVerify": "фикстура — неполная выгрузка: объект типа есть в составе, файла нет намеренно; полная загрузка такого дерева невозможна",
+ "expect": {
+ "stdoutContains": "16. Ссылочный тип 'CatalogRef.Прочие' — объект есть в составе конфигурации, файла объекта в выгрузке нет",
+ "stdoutNotContains": "[ERROR]"
+ }
+}