From 77ee8f1047dfbe739884c561d82dfe1da24b46b2 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Fri, 21 Aug 2026 17:46:20 +0300 Subject: [PATCH] =?UTF-8?q?fix(skills):=20=C2=AB=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=20=D0=BD=D0=B5=20=D0=BD=D0=B0=D0=B9=D0=B4=D0=B5=D0=BD=C2=BB=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D1=85=D0=BE=D0=B4=D0=BD=D0=BE=D0=BC=20JSO?= =?UTF-8?q?N=20=E2=80=94=20=D0=BE=D0=B4=D0=B8=D0=BD=D0=B0=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=20=D0=B2=D0=BE=20=D0=B2=D1=81=D0=B5=D1=85=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B2=D1=8B=D0=BA=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Часть навыков проверяла путь ко входному JSON сама и отвечала внятной строкой, часть — нет и роняла дамп: FileNotFoundError с traceback в py, MethodInvocationException с CategoryInfo в PS1. Один и тот же промах давал разный ответ в зависимости от навыка, а у form-edit — ещё и от порта. Проверка перенесена в тело семьи read_json_file / Read-JsonInputFile: пол одинаков везде по построению, и новые навыки получают его вместе с функцией. Навыки со своей проверкой срабатывают раньше и сохраняют прежний текст, поэтому существующие кейсы не двигаются. Заодно каталог вместо файла: раньше IsADirectoryError / отказ доступа, теперь «Expected a JSON file, got a directory». Co-Authored-By: Claude Opus 5 --- .claude/skills/cf-edit/scripts/cf-edit.ps1 | 13 +++++++++++- .claude/skills/cf-edit/scripts/cf-edit.py | 9 ++++++++- .../form-compile/scripts/form-compile.ps1 | 13 +++++++++++- .../form-compile/scripts/form-compile.py | 9 ++++++++- .../skills/form-edit/scripts/form-edit.ps1 | 13 +++++++++++- .claude/skills/form-edit/scripts/form-edit.py | 9 ++++++++- .../interface-edit/scripts/interface-edit.ps1 | 13 +++++++++++- .../interface-edit/scripts/interface-edit.py | 9 ++++++++- .../meta-compile/scripts/meta-compile.ps1 | 13 +++++++++++- .../meta-compile/scripts/meta-compile.py | 9 ++++++++- .../skills/meta-edit/scripts/meta-edit.ps1 | 13 +++++++++++- .claude/skills/meta-edit/scripts/meta-edit.py | 9 ++++++++- .../mxl-compile/scripts/mxl-compile.ps1 | 13 +++++++++++- .../skills/mxl-compile/scripts/mxl-compile.py | 9 ++++++++- .../role-compile/scripts/role-compile.ps1 | 13 +++++++++++- .../role-compile/scripts/role-compile.py | 9 ++++++++- .../skd-compile/scripts/skd-compile.ps1 | 13 +++++++++++- .../skills/skd-compile/scripts/skd-compile.py | 9 ++++++++- .../skd-decompile/scripts/skd-decompile.ps1 | 13 +++++++++++- .../skd-decompile/scripts/skd-decompile.py | 9 ++++++++- .../scripts/subsystem-compile.ps1 | 13 +++++++++++- .../scripts/subsystem-compile.py | 9 ++++++++- .../subsystem-edit/scripts/subsystem-edit.ps1 | 13 +++++++++++- .../subsystem-edit/scripts/subsystem-edit.py | 9 ++++++++- .../missing-definition-file.json | 20 +++++++++++++++++++ 25 files changed, 260 insertions(+), 24 deletions(-) create mode 100644 tests/skills/cases/interface-edit/missing-definition-file.json diff --git a/.claude/skills/cf-edit/scripts/cf-edit.ps1 b/.claude/skills/cf-edit/scripts/cf-edit.ps1 index 6c376d319..339b06f50 100644 --- a/.claude/skills/cf-edit/scripts/cf-edit.ps1 +++ b/.claude/skills/cf-edit/scripts/cf-edit.ps1 @@ -1,4 +1,4 @@ -# cf-edit v1.21 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.22 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$ConfigPath, @@ -45,6 +45,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/cf-edit/scripts/cf-edit.py b/.claude/skills/cf-edit/scripts/cf-edit.py index 2c813bfba..a59d6c15b 100644 --- a/.claude/skills/cf-edit/scripts/cf-edit.py +++ b/.claude/skills/cf-edit/scripts/cf-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-edit v1.21 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.22 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -52,7 +52,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 4181de028..8c873f651 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.194 — Compile 1C managed form from JSON or object metadata (гвард на группу additionalColumns без ключа columns) +# form-compile v1.195 — Compile 1C managed form from JSON or object metadata (гвард на группу additionalColumns без ключа columns) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -49,6 +49,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index e30d8394c..450a6444b 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.194 — Compile 1C managed form from JSON or object metadata (гвард на группу additionalColumns без ключа columns) +# form-compile v1.195 — Compile 1C managed form from JSON or object metadata (гвард на группу additionalColumns без ключа columns) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -53,7 +53,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/form-edit/scripts/form-edit.ps1 b/.claude/skills/form-edit/scripts/form-edit.ps1 index 6954f3642..6b3d29b57 100644 --- a/.claude/skills/form-edit/scripts/form-edit.ps1 +++ b/.claude/skills/form-edit/scripts/form-edit.ps1 @@ -1,4 +1,4 @@ -# form-edit v1.16 — Edit 1C managed form elements (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# form-edit v1.17 — Edit 1C managed form elements (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -45,6 +45,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/form-edit/scripts/form-edit.py b/.claude/skills/form-edit/scripts/form-edit.py index b0a0980a8..33ff98c20 100644 --- a/.claude/skills/form-edit/scripts/form-edit.py +++ b/.claude/skills/form-edit/scripts/form-edit.py @@ -1,4 +1,4 @@ -# form-edit v1.16 — Edit 1C managed form elements (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# form-edit v1.17 — Edit 1C managed form elements (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -51,7 +51,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/interface-edit/scripts/interface-edit.ps1 b/.claude/skills/interface-edit/scripts/interface-edit.ps1 index 2478e245f..fdbfbb48d 100644 --- a/.claude/skills/interface-edit/scripts/interface-edit.ps1 +++ b/.claude/skills/interface-edit/scripts/interface-edit.ps1 @@ -1,4 +1,4 @@ -# interface-edit v1.20 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) +# interface-edit v1.21 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$CIPath, @@ -51,6 +51,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/interface-edit/scripts/interface-edit.py b/.claude/skills/interface-edit/scripts/interface-edit.py index c0dfa6128..5343f7481 100644 --- a/.claude/skills/interface-edit/scripts/interface-edit.py +++ b/.claude/skills/interface-edit/scripts/interface-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# interface-edit v1.20 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) +# interface-edit v1.21 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -385,7 +385,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 9a053793a..1018cefa7 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.97 — Compile 1C metadata object from JSON +# meta-compile v1.98 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -44,6 +44,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index f0624863f..1750e0103 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.97 — Compile 1C metadata object from JSON +# meta-compile v1.98 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -61,7 +61,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/meta-edit/scripts/meta-edit.ps1 b/.claude/skills/meta-edit/scripts/meta-edit.ps1 index 133875188..7271c8da2 100644 --- a/.claude/skills/meta-edit/scripts/meta-edit.ps1 +++ b/.claude/skills/meta-edit/scripts/meta-edit.ps1 @@ -1,4 +1,4 @@ -# meta-edit v1.40 — Edit existing 1C metadata object XML +# meta-edit v1.41 — Edit existing 1C metadata object XML # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -66,6 +66,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/meta-edit/scripts/meta-edit.py b/.claude/skills/meta-edit/scripts/meta-edit.py index 411f7be30..db1eb7659 100644 --- a/.claude/skills/meta-edit/scripts/meta-edit.py +++ b/.claude/skills/meta-edit/scripts/meta-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-edit v1.40 — Edit existing 1C metadata object XML +# meta-edit v1.41 — Edit existing 1C metadata object XML # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -51,7 +51,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 index f79d75ab7..ce6115195 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 @@ -1,4 +1,4 @@ -# mxl-compile v1.53 — Compile 1C spreadsheet from JSON +# mxl-compile v1.54 — Compile 1C spreadsheet from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -44,6 +44,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py index b29af4119..a5f38de0a 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.py +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-compile v1.53 — Compile 1C spreadsheet from JSON +# mxl-compile v1.54 — Compile 1C spreadsheet from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import hashlib @@ -51,7 +51,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/role-compile/scripts/role-compile.ps1 b/.claude/skills/role-compile/scripts/role-compile.ps1 index d911c0bcd..07ce50709 100644 --- a/.claude/skills/role-compile/scripts/role-compile.ps1 +++ b/.claude/skills/role-compile/scripts/role-compile.ps1 @@ -1,4 +1,4 @@ -# role-compile v1.30 — Compile 1C role from JSON +# role-compile v1.31 — Compile 1C role from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -44,6 +44,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/role-compile/scripts/role-compile.py b/.claude/skills/role-compile/scripts/role-compile.py index 22b972503..b6b6f8db9 100644 --- a/.claude/skills/role-compile/scripts/role-compile.py +++ b/.claude/skills/role-compile/scripts/role-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-compile v1.30 — Compile 1C role from JSON +# role-compile v1.31 — Compile 1C role from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -51,7 +51,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index cba29be76..6cb0531a1 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -1,4 +1,4 @@ -# skd-compile v1.119 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) +# skd-compile v1.120 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -43,6 +43,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index c8c47948e..485a96c4d 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.py +++ b/.claude/skills/skd-compile/scripts/skd-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-compile v1.119 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) +# skd-compile v1.120 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -50,7 +50,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 b/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 index 58872a4da..297b81e9d 100644 --- a/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 +++ b/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 @@ -1,4 +1,4 @@ -# skd-decompile v0.94 — Decompile 1C DCS Template.xml to JSON DSL (draft) +# skd-decompile v0.95 — Decompile 1C DCS Template.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -44,6 +44,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/skd-decompile/scripts/skd-decompile.py b/.claude/skills/skd-decompile/scripts/skd-decompile.py index fe6014e00..642fd6083 100644 --- a/.claude/skills/skd-decompile/scripts/skd-decompile.py +++ b/.claude/skills/skd-decompile/scripts/skd-decompile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-decompile v0.94 — Decompile 1C DCS Template.xml to JSON DSL (draft) +# skd-decompile v0.95 — Decompile 1C DCS Template.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -47,7 +47,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 index c34db6656..b2c8a0e82 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 @@ -1,4 +1,4 @@ -# subsystem-compile v1.28 — Create 1C subsystem from JSON definition +# subsystem-compile v1.29 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -44,6 +44,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py index 90ccdcf53..a81d4b2a9 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-compile v1.28 — Create 1C subsystem from JSON definition +# subsystem-compile v1.29 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -51,7 +51,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 index 7561cb33c..5f8e42857 100644 --- a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 +++ b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 @@ -1,4 +1,4 @@ -# subsystem-edit v1.23 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# subsystem-edit v1.24 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$SubsystemPath, @@ -45,6 +45,17 @@ function ConvertFrom-JsonInput([string]$text, [string]$source, [string]$expected # разбирается успешно, и в конфигурацию уезжает имя из «замен». Кодовую страницу не подбираем: # угаданное имя уйдёт в метаданные так же молча. function Read-JsonInputFile([string]$path) { + # Проверка здесь, а не по навыкам: часть навыков проверяла путь сама, часть — нет, и один и тот + # же промах давал то внятную строку, то дамп MethodInvocationException. Навыки со своей + # проверкой срабатывают раньше и сохраняют свой текст. + if (-not (Test-Path -LiteralPath $path)) { + [Console]::Error.WriteLine("[ERROR] File not found: $path") + exit 1 + } + if (Test-Path -LiteralPath $path -PathType Container) { + [Console]::Error.WriteLine("[ERROR] Expected a JSON file, got a directory: $path") + exit 1 + } $bytes = [System.IO.File]::ReadAllBytes($path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return [System.Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3) diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py index 2fc257115..de897ed16 100644 --- a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py +++ b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-edit v1.23 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# subsystem-edit v1.24 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -51,7 +51,14 @@ def read_json_file(path): BOM — объявление самого файла, поэтому ему верим; без BOM ждём строгий UTF-8. Кодовую страницу не подбираем: угаданное имя уехало бы в метаданные молча. """ + import os as _pos import sys as _psys + if not _pos.path.exists(path): + print("[ERROR] File not found: %s" % path, file=_psys.stderr) + _psys.exit(1) + if _pos.path.isdir(path): + print("[ERROR] Expected a JSON file, got a directory: %s" % path, file=_psys.stderr) + _psys.exit(1) with open(path, "rb") as _fh: data = _fh.read() if data[:3] == b"\xef\xbb\xbf": diff --git a/tests/skills/cases/interface-edit/missing-definition-file.json b/tests/skills/cases/interface-edit/missing-definition-file.json new file mode 100644 index 000000000..f5ae321f3 --- /dev/null +++ b/tests/skills/cases/interface-edit/missing-definition-file.json @@ -0,0 +1,20 @@ +{ + "name": "Несуществующий файл определения: строка вместо дампа исключения", + "preRun": [ + { + "script": "subsystem-compile/scripts/subsystem-compile", + "input": { + "name": "Продажи" + }, + "args": { + "-DefinitionFile": "{inputFile}", + "-OutputDir": "{workDir}" + } + } + ], + "params": { + "ciPath": "Subsystems/Продажи/CommandInterface" + }, + "inputFrom": "нет-такого-файла.json", + "expectError": "File not found:" +}