diff --git a/.claude/skills/skd-validate/SKILL.md b/.claude/skills/skd-validate/SKILL.md index f5ae14cbc..6930df652 100644 --- a/.claude/skills/skd-validate/SKILL.md +++ b/.claude/skills/skd-validate/SKILL.md @@ -31,9 +31,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-validate.ps1" - ## Проверка по XSD -Если в проекте есть XSD-схемы платформы (`/v8-xsd-fetch`), дополнительно проверяет порядок элементов, типы и значения по схеме версии формата выгрузки. Строки вида `XSD 2.20, line N: <родитель>/<элемент>: …`: +Порядок элементов, типы и значения дополнительно сверяются с XSD-схемами платформы, если они скачаны в проект. Иначе итоговая строка заканчивается на `XSD not checked: <причина>` — это не «проверено всё». Когда проверка нужна (например, платформа пишет «нарушен порядок следования»), скачай схемы версии формата выгрузки — атрибут `version` в `Configuration.xml` — через `/v8-xsd-fetch -Versions <версия>` и запусти снова. То же при `[WARN] XSD: no schemas for format <версия>`. -- `must come before ` — элемент не на своём месте: перенести его перед ``, содержимое не менять. `duplicate` — лишний повтор. `not allowed in

` — в этом месте такого элемента быть не должно. Остальное — недопустимое значение, текст говорит какое. -- `[ERROR]` — по схемам своей версии формата. `[WARN]` с `(no schemas for X)` — по более новой версии, ориентир, а не окончательный вердикт. -- Шаблон собран `/skd-compile` или изменён `/skd-edit` — нарушение означает дефект навыка: сообщи пользователю, а не правь XML вручную молча. -- `no schemas for format X — not checked` — предложи `/v8-xsd-fetch -Versions X`. +Нарушение: `XSD <версия>, line N: <родитель>/<элемент>: <что не так>`. + +- `must come before ` — перенеси элемент непосредственно перед ``, содержимое не меняй. `duplicate` — удали повтор. `not allowed in

` — элементу здесь не место. Иначе — текст о недопустимом значении. +- `[WARN]` с `(no schemas for <версия>)` — сверено по схемам более новой версии: ориентир, не вердикт. +- Если шаблон ты только что собрал или изменил `/skd-compile` или `/skd-edit`, нарушение — дефект навыка: сообщи о нём пользователю. diff --git a/.claude/skills/skd-validate/scripts/skd-validate.ps1 b/.claude/skills/skd-validate/scripts/skd-validate.ps1 index ce04ba565..19360fcc2 100644 --- a/.claude/skills/skd-validate/scripts/skd-validate.ps1 +++ b/.claude/skills/skd-validate/scripts/skd-validate.ps1 @@ -1,4 +1,4 @@ -# skd-validate v1.6 — Validate 1C DCS structure +# skd-validate v1.7 — Validate 1C DCS structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills [CmdletBinding(PositionalBinding=$false)] param( @@ -55,6 +55,9 @@ $script:errors = 0 $script:warnings = 0 $script:okCount = 0 $script:stopped = $false +# Проверка, которая не выполнялась, — в итоговую строку: без этого «Validation OK» читается как +# «проверено всё» (модель так и докладывала пользователю при нарушенном порядке) +$script:xsdNote = $null $script:output = New-Object System.Text.StringBuilder 4096 function Out-Line { @@ -86,10 +89,12 @@ function Report-Warn { $finalize = { $checks = $script:okCount + $script:errors + $script:warnings if ($script:errors -eq 0 -and $script:warnings -eq 0 -and -not $Detailed) { - $result = "=== Validation OK: $fileName ($checks checks) ===" + $note = if ($script:xsdNote) { "; $($script:xsdNote)" } else { "" } + $result = "=== Validation OK: $fileName ($checks checks$note) ===" } else { Out-Line "" - Out-Line "=== Result: $($script:errors) errors, $($script:warnings) warnings ($checks checks) ===" + $note = if ($script:xsdNote) { "; $($script:xsdNote)" } else { "" } + Out-Line "=== Result: $($script:errors) errors, $($script:warnings) warnings ($checks checks$note) ===" $result = $script:output.ToString() } Write-Host $result @@ -141,10 +146,15 @@ $root = $xmlDoc.DocumentElement # --- 3. Root element checks --- -if ($root.LocalName -ne "DataCompositionSchema") { - Report-Error "Root element is '$($root.LocalName)', expected 'DataCompositionSchema'" -} else { +# Регистр значим: -ne его не различает, и корень со строчной пропускался молча. Строчную +# (dataCompositionSchema — имя из XSD, так пишет сериализатор XDTO) платформа загружает, но +# конфигуратор всегда пишет DataCompositionSchema — это предупреждение, не ошибка. +if ($root.LocalName -ceq "DataCompositionSchema") { Report-OK "Root element: DataCompositionSchema" +} elseif ($root.LocalName -eq "DataCompositionSchema") { + Report-Warn "Root element is '$($root.LocalName)' — the platform loads it, but the Designer writes 'DataCompositionSchema'" +} else { + Report-Error "Root element is '$($root.LocalName)', expected 'DataCompositionSchema'" } $expectedNs = "http://v8.1c.ru/8.1/data-composition-system/schema" @@ -918,6 +928,10 @@ foreach ($vn in $valueNodes) { } elseif (-not ($text -match '^[A-Za-zА-Яа-яЁё]+\.[A-Za-zА-Яа-яЁё0-9_]+')) { Report-Warn "$text — doesn't look like a typical ref path" } + } elseif ($xsiType -ceq 'xs:boolean' -and @('true', 'false', '1', '0') -cnotcontains $text.Trim()) { + # Платформа прощает True/False, чтение по схеме (XDTO) — нет + Report-Error "$text — boolean must be true or false (lowercase)" + $vOk = $false } } if ($vChecked -gt 0 -and $vOk) { @@ -1191,10 +1205,10 @@ function Compress-XsdMessage([string]$m) { function Invoke-XsdCheck { $xsdRoot = Resolve-XsdRoot ([System.IO.Path]::GetDirectoryName($resolvedPath)) - if (-not $xsdRoot) { Report-OK "XSD: no schemas in project — not checked"; return } + if (-not $xsdRoot) { $script:xsdNote = "XSD not checked: no schemas (/v8-xsd-fetch)"; return } $anchor = Find-DumpAnchor ([System.IO.Path]::GetDirectoryName($resolvedPath)) $ver = if ($anchor) { Get-RootVersion $anchor } else { $null } - if (-not $ver -or (Get-FormatRank $ver) -eq 0) { Report-OK "XSD: format version unknown (template outside a dump) — not checked"; return } + if (-not $ver -or (Get-FormatRank $ver) -eq 0) { $script:xsdNote = "XSD not checked: template outside a dump"; return } # Точная версия — ошибки; ближайшая более новая — предупреждения; только старше — пропуск $cands = @(Get-ChildItem -LiteralPath $xsdRoot -Directory | @@ -1264,6 +1278,8 @@ function Invoke-XsdCheck { $info = @{ elem = $top.name; parent = $(if ($st.Count -gt 1) { $st[$st.Count - 2].name } else { '' }); xsiNs = $top.xsiNs; xsiLocal = $top.xsiLocal } } if (Test-XsdPlatformNoise $info) { return } + # Недопустимое булево значение уже сообщила собственная проверка значений (раздел 17) + if ($info.elem -ceq 'value' -and $info.xsiNs -ceq 'http://www.w3.org/2001/XMLSchema' -and $info.xsiLocal -ceq 'boolean') { return } $script:xsdFound++ $hint = $null if ($sender.NodeType -eq 'Element') { diff --git a/.claude/skills/skd-validate/scripts/skd-validate.py b/.claude/skills/skd-validate/scripts/skd-validate.py index ea0cab440..825c6f86f 100644 --- a/.claude/skills/skd-validate/scripts/skd-validate.py +++ b/.claude/skills/skd-validate/scripts/skd-validate.py @@ -1,4 +1,4 @@ -# skd-validate v1.6 — Validate 1C DCS structure (Python port) +# skd-validate v1.7 — Validate 1C DCS structure (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -78,6 +78,9 @@ errors = 0 warnings = 0 ok_count = 0 stopped = False +# Проверка, которая не выполнялась, — в итоговую строку: без этого «Validation OK» читается как +# «проверено всё» (модель так и докладывала пользователю при нарушенном порядке) +xsd_note = None output_lines = [] @@ -109,10 +112,12 @@ def report_warn(msg): def finalize(): checks = ok_count + errors + warnings if errors == 0 and warnings == 0 and not detailed: - result = f"=== Validation OK: {file_name} ({checks} checks) ===" + note = f"; {xsd_note}" if xsd_note else "" + result = f"=== Validation OK: {file_name} ({checks} checks{note}) ===" else: out_line("") - out_line(f"=== Result: {errors} errors, {warnings} warnings ({checks} checks) ===") + note = f"; {xsd_note}" if xsd_note else "" + out_line(f"=== Result: {errors} errors, {warnings} warnings ({checks} checks{note}) ===") result = "\n".join(output_lines) print(result) if out_file: @@ -187,10 +192,14 @@ def inner_text(node): # ── 3. Root element checks ─────────────────────────────────── -if local_name(root) != "DataCompositionSchema": - report_error(f"Root element is '{local_name(root)}', expected 'DataCompositionSchema'") -else: +# Строчную (dataCompositionSchema — имя из XSD, так пишет сериализатор XDTO) платформа загружает, +# но конфигуратор всегда пишет DataCompositionSchema — это предупреждение, не ошибка. +if local_name(root) == "DataCompositionSchema": report_ok("Root element: DataCompositionSchema") +elif local_name(root).lower() == "datacompositionschema": + report_warn(f"Root element is '{local_name(root)}' — the platform loads it, but the Designer writes 'DataCompositionSchema'") +else: + report_error(f"Root element is '{local_name(root)}', expected 'DataCompositionSchema'") expected_ns = "http://v8.1c.ru/8.1/data-composition-system/schema" root_ns = etree.QName(root.tag).namespace or "" @@ -877,6 +886,10 @@ for vn in value_nodes: v_ok = False elif not _re_vt.match(r'^[A-Za-zА-Яа-яЁё]+\.[A-Za-zА-Яа-яЁё0-9_]+', stripped): report_warn(f"{text} — doesn't look like a typical ref path") + elif xsi_type == 'xs:boolean' and text.strip() not in ('true', 'false', '1', '0'): + # Платформа прощает True/False, чтение по схеме (XDTO) — нет + report_error(f"{text} — boolean must be true or false (lowercase)") + v_ok = False if v_checked > 0 and v_ok: report_ok(f"{v_checked} element(s) with xsi:type: content OK") @@ -1289,13 +1302,14 @@ def compress_xsd_message(m): def xsd_check(): xsd_root = resolve_xsd_root(os.path.dirname(resolved_path)) + global xsd_note if not xsd_root: - report_ok("XSD: no schemas in project — not checked") + xsd_note = "XSD not checked: no schemas (/v8-xsd-fetch)" return anchor = find_dump_anchor(os.path.dirname(resolved_path)) ver = root_version(anchor) if anchor else None if not ver or format_rank(ver) == 0: - report_ok("XSD: format version unknown (template outside a dump) — not checked") + xsd_note = "XSD not checked: template outside a dump" return # Точная версия — ошибки; ближайшая более новая — предупреждения; только старше — пропуск @@ -1331,6 +1345,9 @@ def xsd_check(): info = _xsd_elem_info(el) if xsd_platform_noise(info): continue + # Недопустимое булево значение уже сообщила собственная проверка значений (раздел 17) + if info["elem"] == "value" and info["xsiNs"] == XS_NS and info["xsiLocal"] == "boolean": + continue found += 1 hint = None # «Лишний/не на месте» у libxml2 — «This element is not expected» (текст не локализуется) diff --git a/tests/skills/cases/skd-edit/fixtures/drilldown-base/Template.xml b/tests/skills/cases/skd-edit/fixtures/drilldown-base/Template.xml index b86478951..6752103b2 100644 --- a/tests/skills/cases/skd-edit/fixtures/drilldown-base/Template.xml +++ b/tests/skills/cases/skd-edit/fixtures/drilldown-base/Template.xml @@ -1,5 +1,5 @@ - + Источник Local @@ -94,4 +94,4 @@ Основной - + diff --git a/tests/skills/cases/skd-edit/snapshots/add-drilldown/Template.xml b/tests/skills/cases/skd-edit/snapshots/add-drilldown/Template.xml index ac6fb98e1..1ac2d50ce 100644 --- a/tests/skills/cases/skd-edit/snapshots/add-drilldown/Template.xml +++ b/tests/skills/cases/skd-edit/snapshots/add-drilldown/Template.xml @@ -1,5 +1,5 @@ - + Источник Local @@ -118,4 +118,4 @@ Основной - + diff --git a/tests/skills/cases/skd-validate/bool-value-case.json b/tests/skills/cases/skd-validate/bool-value-case.json new file mode 100644 index 000000000..1f10e7a47 --- /dev/null +++ b/tests/skills/cases/skd-validate/bool-value-case.json @@ -0,0 +1,22 @@ +{ + "name": "Булево True/False без схем — ловит собственная проверка значений", + "setup": "fixture:xsd-bad-220", + "preRun": [ + { + "writeFile": { + "path": ".v8-project.json", + "content": { + "xsdPath": "нет-такого-каталога" + } + } + } + ], + "params": { + "templatePath": "Reports/Отчет/Templates/Схема/Ext/Template.xml" + }, + "expect": { + "stdoutContains": "False — boolean must be true or false (lowercase)" + }, + "noSnapshot": "результат — только вывод", + "expectError": true +} diff --git a/tests/skills/cases/skd-validate/fixtures/root-lowercase/Template.xml b/tests/skills/cases/skd-validate/fixtures/root-lowercase/Template.xml new file mode 100644 index 000000000..b86478951 --- /dev/null +++ b/tests/skills/cases/skd-validate/fixtures/root-lowercase/Template.xml @@ -0,0 +1,97 @@ + + + + Источник + Local + + + Основной + + Ресурс1 + Ресурс1 + + + Ресурс2 + Ресурс2 + + + Счет + Счет + + Источник + ВЫБРАТЬ 1 + + + + + Основной + + + diff --git a/tests/skills/cases/skd-validate/fixtures/xsd-bad-211/Reports/Отчет/Templates/Схема/Ext/Template.xml b/tests/skills/cases/skd-validate/fixtures/xsd-bad-211/Reports/Отчет/Templates/Схема/Ext/Template.xml index fc71280e1..65ff62bd5 100644 --- a/tests/skills/cases/skd-validate/fixtures/xsd-bad-211/Reports/Отчет/Templates/Схема/Ext/Template.xml +++ b/tests/skills/cases/skd-validate/fixtures/xsd-bad-211/Reports/Отчет/Templates/Схема/Ext/Template.xml @@ -49,7 +49,7 @@ xs:boolean - False + false false diff --git a/tests/skills/cases/skd-validate/fixtures/xsd-no-anchor/Template.xml b/tests/skills/cases/skd-validate/fixtures/xsd-no-anchor/Template.xml index fc71280e1..7ae404c19 100644 --- a/tests/skills/cases/skd-validate/fixtures/xsd-no-anchor/Template.xml +++ b/tests/skills/cases/skd-validate/fixtures/xsd-no-anchor/Template.xml @@ -9,6 +9,7 @@ Число Число + Формат(Число, "ЧГ=") xs:decimal @@ -17,7 +18,6 @@ Any - Формат(Число, "ЧГ=") Флаг @@ -32,6 +32,9 @@ Удвоенное Число * 2 + + true + xs:decimal @@ -40,16 +43,13 @@ Any - - true - П xs:boolean - False + false false @@ -73,6 +73,13 @@ true + + + П + false + 0eb70b37-3a01-40a0-81c1-98028ef06a05 + + Заголовок @@ -84,13 +91,6 @@ - - - П - false - 0930043f-cf2a-42c1-ae8c-4accf2fd2604 - - diff --git a/tests/skills/cases/skd-validate/warn-root-lowercase.json b/tests/skills/cases/skd-validate/warn-root-lowercase.json new file mode 100644 index 000000000..38720bee1 --- /dev/null +++ b/tests/skills/cases/skd-validate/warn-root-lowercase.json @@ -0,0 +1,10 @@ +{ + "name": "Корень dataCompositionSchema со строчной — предупреждение: платформа загружает, конфигуратор пишет с заглавной", + "setup": "fixture:root-lowercase", + "params": { "templatePath": "Template.xml" }, + "expect": { + "stdoutContains": "[WARN] Root element is 'dataCompositionSchema' — the platform loads it, but the Designer writes 'DataCompositionSchema'", + "stdoutNotContains": "[ERROR]" + }, + "noSnapshot": "результат — только вывод" +} diff --git a/tests/skills/cases/skd-validate/xsd-exact-errors.json b/tests/skills/cases/skd-validate/xsd-exact-errors.json index ef2bd1d58..3e6c5f608 100644 --- a/tests/skills/cases/skd-validate/xsd-exact-errors.json +++ b/tests/skills/cases/skd-validate/xsd-exact-errors.json @@ -1,5 +1,5 @@ { - "name": "XSD точной версии: подсказки по порядку и сжатый текст без пространств имён", + "name": "XSD точной версии: подсказки по порядку; False — один раз, собственной проверкой", "setup": "fixture:xsd-bad-220", "requires": ".v8-xsd/2.20", "preRun": [ @@ -20,10 +20,14 @@ "stdoutContains": [ "[ERROR] XSD 2.20, line 20: field/presentationExpression: must come before ", "[ERROR] XSD 2.20, line 43: calculatedField/useRestriction: must come before ", - "[ERROR] XSD 2.20, line 52: parameter/value:", - "[ERROR] XSD 2.20, line 87: settings/dataParameters: must come before " + "[ERROR] XSD 2.20, line 87: settings/dataParameters: must come before ", + "False — boolean must be true or false (lowercase)", + "=== Result: 4 errors" ], - "stdoutNotContains": "http://v8.1c.ru" + "stdoutNotContains": [ + "http://v8.1c.ru", + "parameter/value" + ] }, "noSnapshot": "результат — только вывод; схемы 1С не должны попасть в эталон" } diff --git a/tests/skills/cases/skd-validate/xsd-no-anchor.json b/tests/skills/cases/skd-validate/xsd-no-anchor.json index a71f28e52..3d0d46cd1 100644 --- a/tests/skills/cases/skd-validate/xsd-no-anchor.json +++ b/tests/skills/cases/skd-validate/xsd-no-anchor.json @@ -1,5 +1,5 @@ { - "name": "Шаблон вне выгрузки — версия формата неизвестна, проверка не выполняется", + "name": "Шаблон вне выгрузки — версия формата неизвестна, пометка в итоговой строке", "setup": "fixture:xsd-no-anchor", "preRun": [ { @@ -24,7 +24,7 @@ "-Detailed" ], "expect": { - "stdoutContains": "[OK] XSD: format version unknown (template outside a dump) — not checked", + "stdoutContains": "checks; XSD not checked: template outside a dump) ===", "stdoutNotContains": [ "[ERROR]", "[WARN]" diff --git a/tests/skills/cases/skd-validate/xsd-no-schemas-detailed.json b/tests/skills/cases/skd-validate/xsd-no-schemas-detailed.json index 42a412ad9..d0c6ac75d 100644 --- a/tests/skills/cases/skd-validate/xsd-no-schemas-detailed.json +++ b/tests/skills/cases/skd-validate/xsd-no-schemas-detailed.json @@ -1,6 +1,6 @@ { - "name": "Каталога схем нет, -Detailed — строка о пропуске", - "setup": "fixture:xsd-bad-220", + "name": "Каталога схем нет, -Detailed — пометка в итоговой строке", + "setup": "fixture:xsd-good-220", "preRun": [ { "writeFile": { @@ -18,7 +18,7 @@ "-Detailed" ], "expect": { - "stdoutContains": "[OK] XSD: no schemas in project — not checked", + "stdoutContains": "checks; XSD not checked: no schemas (/v8-xsd-fetch)) ===", "stdoutNotContains": [ "[ERROR]", "[WARN]" diff --git a/tests/skills/cases/skd-validate/xsd-no-schemas.json b/tests/skills/cases/skd-validate/xsd-no-schemas.json index f6eb537a9..e6b295ff5 100644 --- a/tests/skills/cases/skd-validate/xsd-no-schemas.json +++ b/tests/skills/cases/skd-validate/xsd-no-schemas.json @@ -1,6 +1,6 @@ { - "name": "Каталога схем нет — проверки нет, строк XSD в выводе нет", - "setup": "fixture:xsd-bad-220", + "name": "Каталога схем нет — проверки нет, итоговая строка говорит об этом", + "setup": "fixture:xsd-good-220", "preRun": [ { "writeFile": { @@ -15,8 +15,14 @@ "templatePath": "Reports/Отчет/Templates/Схема/Ext/Template.xml" }, "expect": { - "stdoutContains": "=== Validation OK", - "stdoutNotContains": "XSD" + "stdoutContains": [ + "=== Validation OK: Template.xml (", + "checks; XSD not checked: no schemas (/v8-xsd-fetch)) ===" + ], + "stdoutNotContains": [ + "[ERROR]", + "[WARN]" + ] }, "noSnapshot": "результат — только вывод" } diff --git a/tests/skills/cases/skd-validate/xsd-only-older.json b/tests/skills/cases/skd-validate/xsd-only-older.json index c4be474bb..fcc73e7cc 100644 --- a/tests/skills/cases/skd-validate/xsd-only-older.json +++ b/tests/skills/cases/skd-validate/xsd-only-older.json @@ -1,6 +1,6 @@ { "name": "В каталоге схем только старшие версии — предупреждение, проверка не выполняется", - "setup": "fixture:xsd-bad-220", + "setup": "fixture:xsd-good-220", "preRun": [ { "writeFile": {