From d544071b1e3f56644fb97c559c4a6e71ccc8147f Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 25 Jul 2026 17:54:20 +0300 Subject: [PATCH] =?UTF-8?q?feat(meta-validate):=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=81=D0=B2=D0=BE=D0=B9?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=B0=20=D0=B8=20=D0=B4=D0=B8=D0=B0=D0=BF?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D0=BD=20LineNumberLength?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Две проверки, обе про формат 2.20. Проверка 18 — реестр versionedProps «тег → минимальная версия формата». Если свойство присутствует в файле со слишком старым штампом, при сборке на платформе той версии оно будет молча отброшено: платформа рапортует успех (exit 0), а свойство теряется — проверено экспериментально на 8.3.24. Реестр расширяется одной строкой на свойство и служит заделом под 2.21 (8.5) и последующие: он же подсказывает, что конструкция требует более нового формата. Проверка 19 — LineNumberLength вне диапазона 5..9 (границы из документации 1С). Компаратор версий числовой по компонентам: строковое сравнение дало бы "2.9" > "2.17". Кейсы: error-lnl-out-of-range, error-220-props-in-217. Регресс 25/25 ps1+py. Co-Authored-By: Claude Opus 5 (1M context) --- .../meta-validate/scripts/meta-validate.ps1 | 37 +- .../meta-validate/scripts/meta-validate.py | 35 +- .../meta-validate/error-220-props-in-217.json | 9 + .../meta-validate/error-lnl-out-of-range.json | 9 + .../Catalogs/Договоры.xml | 437 ++++++++++++++++++ .../Catalogs/Договоры.xml | 437 ++++++++++++++++++ 6 files changed, 962 insertions(+), 2 deletions(-) create mode 100644 tests/skills/cases/meta-validate/error-220-props-in-217.json create mode 100644 tests/skills/cases/meta-validate/error-lnl-out-of-range.json create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-220-props-in-217/Catalogs/Договоры.xml create mode 100644 tests/skills/cases/meta-validate/fixtures/catalog-lnl-out-of-range/Catalogs/Договоры.xml diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1 index 55809ee8..d2005e7b 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.11 — Validate 1C metadata object structure (+корневой : скаляр без структуры = ошибка) +# meta-validate v1.12 — Validate 1C metadata object structure (+корневой : скаляр без структуры = ошибка) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -1493,6 +1493,41 @@ if ($script:configDir) { } } +# --- Check 18: свойства, появившиеся в новых версиях формата --- +# Реестр «тег → минимальная версия формата». Служит двум целям: (1) поймать свойство в файле со +# слишком старым штампом — при сборке на старой платформе оно будет молча отброшено (платформа +# рапортует успех, а свойство теряется); (2) подсказать, что конструкция требует более нового +# формата. Расширяется одной строкой на свойство — задел под 2.21 (8.5) и последующие. +$versionedProps = @{ + "TypeReductionMode" = "2.20" # режим приведения типов (стандартные реквизиты, измерения РС) + "LineNumberLength" = "2.20" # длина номера строки ТЧ (5..9) +} +# Версия формата как число: "2.20" → 220. Строковое сравнение неверно ("2.9" > "2.17"). +function Get-FormatRank([string]$v) { + if ($v -match '^(\d+)\.(\d+)$') { return [int]$Matches[1] * 100 + [int]$Matches[2] } + return 0 +} +$fileRank = Get-FormatRank $version +if ($fileRank -gt 0) { + foreach ($vp in ($versionedProps.Keys | Sort-Object)) { + $nodes = $xmlDoc.SelectNodes("//md:$vp | //xr:$vp", $ns) + if ($nodes -and $nodes.Count -gt 0 -and $fileRank -lt (Get-FormatRank $versionedProps[$vp])) { + Report-Error "18. <$vp> появился в формате $($versionedProps[$vp]), а файл объявлен как $version — на платформе этой версии свойство будет отброшено при загрузке" + } + } +} + +# --- Check 19: LineNumberLength — допустимый диапазон 5..9 --- +# Длина номера строки ТЧ: 5 (до 99 999 строк) … 9 (до 999 999 999). Границы — из документации 1С. +foreach ($lnl in @($xmlDoc.SelectNodes("//md:LineNumberLength", $ns))) { + $raw = $lnl.InnerText.Trim() + if ($raw -notmatch '^\d+$') { + Report-Error "19. LineNumberLength='$raw' — должно быть целое число 5..9" + } elseif ([int]$raw -lt 5 -or [int]$raw -gt 9) { + Report-Error "19. LineNumberLength=$raw вне допустимого диапазона 5..9" + } +} + # --- Check 17: MDObjectRef form — ссылка должна указывать на ОБЪЕКТ метаданных, а не на тип ссылки --- # Owners/BasedOn/RegisterRecords/RegisteredDocuments/References содержат путь вида "Catalog.Валюты". # "CatalogRef.Валюты" — частая ошибка (тип ссылки вместо объекта): платформа отвечает diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py index 994e423a..110eac41 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.11 — Validate 1C metadata object structure (Python port) (+корневой : скаляр без структуры = ошибка) +# meta-validate v1.12 — Validate 1C metadata object structure (Python port) (+корневой : скаляр без структуры = ошибка) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -1395,6 +1395,39 @@ if config_dir: elif checked_refs: report_ok(f"16. Reference types: {len(checked_refs)} resolved") +# ── Check 18: свойства, появившиеся в новых версиях формата ── +# Реестр «тег → минимальная версия формата». Служит двум целям: (1) поймать свойство в файле со +# слишком старым штампом — при сборке на старой платформе оно будет молча отброшено (платформа +# рапортует успех, а свойство теряется); (2) подсказать, что конструкция требует более нового +# формата. Расширяется одной строкой на свойство — задел под 2.21 (8.5) и последующие. +versioned_props = { + "TypeReductionMode": "2.20", # режим приведения типов (стандартные реквизиты, измерения РС) + "LineNumberLength": "2.20", # длина номера строки ТЧ (5..9) +} + + +def format_rank(v): + """"2.20" → 220. Строковое сравнение неверно ("2.9" > "2.17").""" + m = re.match(r'^(\d+)\.(\d+)$', v or '') + return int(m.group(1)) * 100 + int(m.group(2)) if m else 0 + + +file_rank = format_rank(version) +if file_rank > 0: + for vp in sorted(versioned_props): + nodes = find_all(root, f"//md:{vp} | //xr:{vp}") + if nodes and file_rank < format_rank(versioned_props[vp]): + report_error(f"18. <{vp}> появился в формате {versioned_props[vp]}, а файл объявлен как {version} — на платформе этой версии свойство будет отброшено при загрузке") + +# ── Check 19: LineNumberLength — допустимый диапазон 5..9 ── +# Длина номера строки ТЧ: 5 (до 99 999 строк) … 9 (до 999 999 999). Границы — из документации 1С. +for lnl in find_all(root, "//md:LineNumberLength"): + raw = inner_text(lnl).strip() + if not re.match(r'^\d+$', raw): + report_error(f"19. LineNumberLength='{raw}' — должно быть целое число 5..9") + elif int(raw) < 5 or int(raw) > 9: + report_error(f"19. LineNumberLength={raw} вне допустимого диапазона 5..9") + # ── Check 17: MDObjectRef form — ссылка на ОБЪЕКТ метаданных, а не на тип ссылки ── # Owners/BasedOn/RegisterRecords/RegisteredDocuments/References содержат путь вида "Catalog.Валюты". # "CatalogRef.Валюты" — частая ошибка (тип ссылки вместо объекта): платформа отвечает diff --git a/tests/skills/cases/meta-validate/error-220-props-in-217.json b/tests/skills/cases/meta-validate/error-220-props-in-217.json new file mode 100644 index 00000000..521c9eec --- /dev/null +++ b/tests/skills/cases/meta-validate/error-220-props-in-217.json @@ -0,0 +1,9 @@ +{ + "name": "Валидатор находит ошибку: свойства формата 2.20 в файле со штампом 2.17", + "setup": "fixture:catalog-220-props-in-217", + "params": { "objectPath": "Catalogs/Договоры.xml" }, + "expectError": true, + "expect": { + "stdoutContains": "появился в формате 2.20, а файл объявлен как 2.17" + } +} diff --git a/tests/skills/cases/meta-validate/error-lnl-out-of-range.json b/tests/skills/cases/meta-validate/error-lnl-out-of-range.json new file mode 100644 index 00000000..75534de3 --- /dev/null +++ b/tests/skills/cases/meta-validate/error-lnl-out-of-range.json @@ -0,0 +1,9 @@ +{ + "name": "Валидатор находит ошибку: LineNumberLength вне диапазона 5..9", + "setup": "fixture:catalog-lnl-out-of-range", + "params": { "objectPath": "Catalogs/Договоры.xml" }, + "expectError": true, + "expect": { + "stdoutContains": "19. LineNumberLength=12 вне допустимого диапазона 5..9" + } +} diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-220-props-in-217/Catalogs/Договоры.xml b/tests/skills/cases/meta-validate/fixtures/catalog-220-props-in-217/Catalogs/Договоры.xml new file mode 100644 index 00000000..1a05395b --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-220-props-in-217/Catalogs/Договоры.xml @@ -0,0 +1,437 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + + Договоры + + + ru + Договоры + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + Catalog.Валюты + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + ShowError + false + true + Auto + Deny + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + true + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + ShowError + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + Auto + InDialog + false + BothWays + + Catalog.Договоры.StandardAttribute.Description + Catalog.Договоры.StandardAttribute.Code + + Begin + DontUse + Directly + + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + + + + + UUID-013 + UUID-014 + + + UUID-015 + UUID-016 + + + + Условия + + + ru + Условия + + + + + DontCheck + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + ForItem + 9 + + + + + Условие + + + ru + Условие + + + + + xs:string + + 100 + Variable + + + false + + + + false + + false + false + + + DontCheck + Items + + + Auto + Auto + + + Auto + DontIndex + Use + Use + + + + + + + diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-lnl-out-of-range/Catalogs/Договоры.xml b/tests/skills/cases/meta-validate/fixtures/catalog-lnl-out-of-range/Catalogs/Договоры.xml new file mode 100644 index 00000000..009d1cf0 --- /dev/null +++ b/tests/skills/cases/meta-validate/fixtures/catalog-lnl-out-of-range/Catalogs/Договоры.xml @@ -0,0 +1,437 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + + Договоры + + + ru + Договоры + + + + false + HierarchyFoldersAndItems + false + 2 + true + true + + Catalog.Валюты + + ToItems + 9 + 25 + String + Variable + WholeCatalog + false + true + AsDescription + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + ShowError + false + true + Auto + Deny + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + true + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + ShowError + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + + Auto + InDialog + false + BothWays + + Catalog.Договоры.StandardAttribute.Description + Catalog.Договоры.StandardAttribute.Code + + Begin + DontUse + Directly + + + + + + + + + + + false + + + Managed + Use + + + + + + Use + Auto + DontUse + false + false + + + + + + UUID-013 + UUID-014 + + + UUID-015 + UUID-016 + + + + Условия + + + ru + Условия + + + + + DontCheck + + + + DontCheck + false + false + Auto + TransformValues + + + false + + + Auto + Auto + + false + Use + false + + + + Use + + + + + + + ForItem + 12 + + + + + Условие + + + ru + Условие + + + + + xs:string + + 100 + Variable + + + false + + + + false + + false + false + + + DontCheck + Items + + + Auto + Auto + + + Auto + DontIndex + Use + Use + + + + + + +