diff --git a/.claude/skills/cf-edit/scripts/cf-edit.ps1 b/.claude/skills/cf-edit/scripts/cf-edit.ps1 index a4f63f1b..e9a3364f 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.16 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.17 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$ConfigPath, diff --git a/.claude/skills/cf-edit/scripts/cf-edit.py b/.claude/skills/cf-edit/scripts/cf-edit.py index a9d8e1df..2c127e30 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.16 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.17 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -12,6 +12,28 @@ import uuid as _uuid from html import escape as html_escape from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -380,7 +402,7 @@ def main(): parser.add_argument("-Operation", default=None, choices=["modify-property", "add-childObject", "remove-childObject", "add-defaultRole", "remove-defaultRole", "set-defaultRoles", "set-panels", "set-home-page"]) parser.add_argument("-Value", default=None) parser.add_argument("-NoValidate", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) if args.DefinitionFile and args.Operation: print("Cannot use both -DefinitionFile and -Operation", file=sys.stderr) diff --git a/.claude/skills/cf-info/scripts/cf-info.ps1 b/.claude/skills/cf-info/scripts/cf-info.ps1 index b2d5a1b2..8af66524 100644 --- a/.claude/skills/cf-info/scripts/cf-info.ps1 +++ b/.claude/skills/cf-info/scripts/cf-info.ps1 @@ -1,4 +1,4 @@ -# cf-info v1.4 — Compact summary of 1C configuration root +# cf-info v1.5 — Compact summary of 1C configuration root # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$ConfigPath, diff --git a/.claude/skills/cf-info/scripts/cf-info.py b/.claude/skills/cf-info/scripts/cf-info.py index eada7323..045bf11e 100644 --- a/.claude/skills/cf-info/scripts/cf-info.py +++ b/.claude/skills/cf-info/scripts/cf-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-info v1.4 — Compact summary of 1C configuration root +# cf-info v1.5 — Compact summary of 1C configuration root # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -12,6 +12,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Argument parsing --- parser = argparse.ArgumentParser(description="Analyze 1C configuration structure", allow_abbrev=False) parser.add_argument("-ConfigPath", "-Path", required=True, help="Path to Configuration.xml or directory") @@ -20,7 +42,7 @@ parser.add_argument("-Section", "-Name", choices=["home-page"], default=None, he parser.add_argument("-Limit", type=int, default=150, help="Max lines to show") parser.add_argument("-Offset", type=int, default=0, help="Lines to skip") parser.add_argument("-OutFile", default="", help="Write output to file") -args = parser.parse_args() +args = ci_parse_args(parser) # --- Output helper (collect all, paginate at the end) --- lines_buf = [] diff --git a/.claude/skills/cf-init/scripts/cf-init.ps1 b/.claude/skills/cf-init/scripts/cf-init.ps1 index e09e0790..64a12896 100644 --- a/.claude/skills/cf-init/scripts/cf-init.ps1 +++ b/.claude/skills/cf-init/scripts/cf-init.ps1 @@ -1,4 +1,4 @@ -# cf-init v1.10 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) +# cf-init v1.11 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cf-init/scripts/cf-init.py b/.claude/skills/cf-init/scripts/cf-init.py index fae61faf..20ac5e5b 100644 --- a/.claude/skills/cf-init/scripts/cf-init.py +++ b/.claude/skills/cf-init/scripts/cf-init.py @@ -1,9 +1,31 @@ #!/usr/bin/env python3 -# cf-init v1.10 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) +# cf-init v1.11 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C configuration.""" import sys, os, argparse, re, uuid +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def esc_xml_text(s): # Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми. return s.replace('&', '&').replace('<', '<').replace('>', '>') @@ -43,7 +65,7 @@ def main(): # Дефолт консервативный: 2.17 читается всеми платформами. parser.add_argument('-FormatVersion', dest='FormatVersion', default='2.17', choices=['2.17', '2.18', '2.19', '2.20', '2.21']) - args = parser.parse_args() + args = ci_parse_args(parser) name = args.Name synonym = args.Synonym if args.Synonym else name diff --git a/.claude/skills/cf-validate/scripts/cf-validate.ps1 b/.claude/skills/cf-validate/scripts/cf-validate.ps1 index 83c0bd9f..fb692c55 100644 --- a/.claude/skills/cf-validate/scripts/cf-validate.ps1 +++ b/.claude/skills/cf-validate/scripts/cf-validate.ps1 @@ -1,4 +1,4 @@ -# cf-validate v1.5 — Validate 1C configuration root structure +# cf-validate v1.6 — Validate 1C configuration root structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cf-validate/scripts/cf-validate.py b/.claude/skills/cf-validate/scripts/cf-validate.py index b16e1e2c..fe8406fc 100644 --- a/.claude/skills/cf-validate/scripts/cf-validate.py +++ b/.claude/skills/cf-validate/scripts/cf-validate.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# cf-validate v1.5 — Validate 1C configuration XML structure +# cf-validate v1.6 — Validate 1C configuration XML structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages.""" import sys, os, argparse, re from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NS = { 'md': 'http://v8.1c.ru/8.3/MDClasses', 'v8': 'http://v8.1c.ru/8.1/data/core', @@ -170,7 +192,7 @@ def main(): parser.add_argument('-Detailed', action='store_true') parser.add_argument('-MaxErrors', dest='MaxErrors', type=int, default=30) parser.add_argument('-OutFile', dest='OutFile', default='') - args = parser.parse_args() + args = ci_parse_args(parser) config_path = args.ConfigPath max_errors = args.MaxErrors diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 index 42033f17..856f55a6 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 @@ -1,4 +1,4 @@ -# cfe-borrow v1.19 — Borrow objects from configuration into extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# cfe-borrow v1.20 — Borrow objects from configuration into extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][string]$ExtensionPath, diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.py b/.claude/skills/cfe-borrow/scripts/cfe-borrow.py index 15928de8..38fa68fb 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.py +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cfe-borrow v1.19 — Borrow objects from configuration into extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# cfe-borrow v1.20 — Borrow objects from configuration into extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -9,6 +9,28 @@ import sys import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + MD_NS = "http://v8.1c.ru/8.3/MDClasses" XR_NS = "http://v8.1c.ru/8.3/xcf/readable" XSI_NS = "http://www.w3.org/2001/XMLSchema-instance" @@ -479,7 +501,7 @@ def main(): parser.add_argument("-ConfigPath", required=True) parser.add_argument("-Object", required=True) parser.add_argument("-BorrowMainAttribute", nargs="?", const="Form", default=None) - args = parser.parse_args() + args = ci_parse_args(parser) # --- 1. Resolve paths --- ext_path = args.ExtensionPath diff --git a/.claude/skills/cfe-diff/scripts/cfe-diff.ps1 b/.claude/skills/cfe-diff/scripts/cfe-diff.ps1 index 155c7f42..1ca683e7 100644 --- a/.claude/skills/cfe-diff/scripts/cfe-diff.ps1 +++ b/.claude/skills/cfe-diff/scripts/cfe-diff.ps1 @@ -1,4 +1,4 @@ -# cfe-diff v1.1 — Analyze and compare 1C configuration extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# cfe-diff v1.2 — Analyze and compare 1C configuration extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cfe-diff/scripts/cfe-diff.py b/.claude/skills/cfe-diff/scripts/cfe-diff.py index 9af62d93..709fa500 100644 --- a/.claude/skills/cfe-diff/scripts/cfe-diff.py +++ b/.claude/skills/cfe-diff/scripts/cfe-diff.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cfe-diff v1.1 — Analyze and compare 1C configuration extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# cfe-diff v1.2 — Analyze and compare 1C configuration extension (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -8,6 +8,28 @@ import re import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Namespace maps --- MD_NSMAP = { @@ -474,7 +496,7 @@ def main(): parser.add_argument("-ExtensionPath", required=True, help="Path to extension dump root") parser.add_argument("-ConfigPath", required=True, help="Path to base config dump root") parser.add_argument("-Mode", choices=["A", "B"], default="A", help="A=overview, B=transfer check") - args = parser.parse_args() + args = ci_parse_args(parser) extension_path = args.ExtensionPath config_path = args.ConfigPath diff --git a/.claude/skills/cfe-init/scripts/cfe-init.ps1 b/.claude/skills/cfe-init/scripts/cfe-init.ps1 index bee16f04..d2e9efa8 100644 --- a/.claude/skills/cfe-init/scripts/cfe-init.ps1 +++ b/.claude/skills/cfe-init/scripts/cfe-init.ps1 @@ -1,4 +1,4 @@ -# cfe-init v1.9 — Create 1C configuration extension scaffold (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) +# cfe-init v1.10 — Create 1C configuration extension scaffold (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cfe-init/scripts/cfe-init.py b/.claude/skills/cfe-init/scripts/cfe-init.py index 735a327e..7f11ce82 100644 --- a/.claude/skills/cfe-init/scripts/cfe-init.py +++ b/.claude/skills/cfe-init/scripts/cfe-init.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# cfe-init v1.9 — Create 1C configuration extension scaffold (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) +# cfe-init v1.10 — Create 1C configuration extension scaffold (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C configuration extension.""" import sys, os, re, argparse, uuid from xml.etree import ElementTree as ET +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def esc_xml_text(s): # Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми. return s.replace('&', '&').replace('<', '<').replace('>', '>') @@ -49,7 +71,7 @@ def main(): parser.add_argument('-CompatibilityMode', dest='CompatibilityMode', default='Version8_3_24') parser.add_argument('-ConfigPath', dest='ConfigPath', default=None) parser.add_argument('-NoRole', dest='NoRole', action='store_true') - args = parser.parse_args() + args = ci_parse_args(parser) name = args.Name synonym = args.Synonym if args.Synonym else name diff --git a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 index f04966aa..1876ef7a 100644 --- a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 +++ b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 @@ -1,4 +1,4 @@ -# cfe-patch-method v2.6 — Source-aware method interceptor for 1C extension (CFE) (+прощающий ввод: имя каталога наравне с именем типа) +# cfe-patch-method v2.7 — Source-aware method interceptor for 1C extension (CFE) (+прощающий ввод: имя каталога наравне с именем типа) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py index 33fda80c..fb38814b 100644 --- a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py +++ b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cfe-patch-method v2.6 — Source-aware method interceptor for 1C extension (CFE) (+прощающий ввод: имя каталога наравне с именем типа) +# cfe-patch-method v2.7 — Source-aware method interceptor for 1C extension (CFE) (+прощающий ввод: имя каталога наравне с именем типа) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -10,6 +10,28 @@ import sys import tempfile import xml.etree.ElementTree as ET +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + TYPE_DIR_MAP = { "Catalog": "Catalogs", "Document": "Documents", "Enum": "Enums", "CommonModule": "CommonModules", "Report": "Reports", "DataProcessor": "DataProcessors", @@ -557,7 +579,7 @@ def main(): choices=["", "Before", "After", "Instead", "ModificationAndControl"]) parser.add_argument("-Check", action="store_true") parser.add_argument("-Actualize", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) extension_path = args.ExtensionPath config_path = args.ConfigPath diff --git a/.claude/skills/cfe-validate/scripts/cfe-validate.ps1 b/.claude/skills/cfe-validate/scripts/cfe-validate.ps1 index 9f88a401..b956f0bd 100644 --- a/.claude/skills/cfe-validate/scripts/cfe-validate.ps1 +++ b/.claude/skills/cfe-validate/scripts/cfe-validate.ps1 @@ -1,4 +1,4 @@ -# cfe-validate v1.6 — Validate 1C configuration extension structure (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# cfe-validate v1.7 — Validate 1C configuration extension structure (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cfe-validate/scripts/cfe-validate.py b/.claude/skills/cfe-validate/scripts/cfe-validate.py index e300ebde..131f6db9 100644 --- a/.claude/skills/cfe-validate/scripts/cfe-validate.py +++ b/.claude/skills/cfe-validate/scripts/cfe-validate.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# cfe-validate v1.6 — Validate 1C configuration extension XML structure (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# cfe-validate v1.7 — Validate 1C configuration extension XML structure (CFE) (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates extension Configuration.xml: root, InternalInfo, extension properties, ChildObjects, borrowed objects.""" import sys, os, argparse, re from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NS = { 'md': 'http://v8.1c.ru/8.3/MDClasses', 'v8': 'http://v8.1c.ru/8.1/data/core', @@ -155,7 +177,7 @@ def main(): parser.add_argument('-Detailed', action='store_true') parser.add_argument('-MaxErrors', dest='MaxErrors', type=int, default=30) parser.add_argument('-OutFile', dest='OutFile', default='') - args = parser.parse_args() + args = ci_parse_args(parser) extension_path = args.ExtensionPath max_errors = args.MaxErrors diff --git a/.claude/skills/db-create/scripts/db-create.ps1 b/.claude/skills/db-create/scripts/db-create.ps1 index b730eabe..f3372fb0 100644 --- a/.claude/skills/db-create/scripts/db-create.ps1 +++ b/.claude/skills/db-create/scripts/db-create.ps1 @@ -1,4 +1,4 @@ -# db-create v1.10 — Create 1C information base +# db-create v1.11 — Create 1C information base # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-create/scripts/db-create.py b/.claude/skills/db-create/scripts/db-create.py index 83b2d16c..5419cb0f 100644 --- a/.claude/skills/db-create/scripts/db-create.py +++ b/.claude/skills/db-create/scripts/db-create.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-create v1.10 — Create 1C information base +# db-create v1.11 — Create 1C information base # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -355,7 +377,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 index b0b61107..b9289f6d 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 @@ -1,4 +1,4 @@ -# db-dump-cf v1.12 — Dump 1C configuration to CF file +# db-dump-cf v1.13 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py index ab2d2699..e28541b0 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-cf v1.12 — Dump 1C configuration to CF file +# db-dump-cf v1.13 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -375,7 +397,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 index 7a4670c8..3d77f629 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 @@ -1,4 +1,4 @@ -# db-dump-dt v1.11 — Dump 1C information base to DT file +# db-dump-dt v1.12 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py index de60d4d5..1e82509f 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-dt v1.11 — Dump 1C information base to DT file +# db-dump-dt v1.12 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -373,7 +395,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 index 5070cfbe..a7217710 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 @@ -1,4 +1,4 @@ -# db-dump-xml v1.14 — Dump 1C configuration to XML files +# db-dump-xml v1.15 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py index f8da552d..0053002f 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-xml v1.14 — Dump 1C configuration to XML files +# db-dump-xml v1.15 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -388,7 +410,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 index f549fd68..d885b850 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 @@ -1,4 +1,4 @@ -# db-load-cf v1.13 — Load 1C configuration from CF file +# db-load-cf v1.14 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.py b/.claude/skills/db-load-cf/scripts/db-load-cf.py index 4059f8cd..c828d870 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.py +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-cf v1.13 — Load 1C configuration from CF file +# db-load-cf v1.14 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -393,7 +415,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 index 6ae411e7..3422969a 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 @@ -1,4 +1,4 @@ -# db-load-dt v1.12 — Load 1C information base from DT file +# db-load-dt v1.13 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.py b/.claude/skills/db-load-dt/scripts/db-load-dt.py index 52032b55..d48f1b2d 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.py +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-dt v1.12 — Load 1C information base from DT file +# db-load-dt v1.13 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -393,7 +415,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-load-git/scripts/db-load-git.ps1 b/.claude/skills/db-load-git/scripts/db-load-git.ps1 index ad0b7991..a2ed49e3 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.ps1 +++ b/.claude/skills/db-load-git/scripts/db-load-git.ps1 @@ -1,4 +1,4 @@ -# db-load-git v1.18 — Load Git changes into 1C database +# db-load-git v1.19 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-load-git/scripts/db-load-git.py b/.claude/skills/db-load-git/scripts/db-load-git.py index fcc64f83..0def43e4 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.py +++ b/.claude/skills/db-load-git/scripts/db-load-git.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-git v1.18 — Load Git changes into 1C database +# db-load-git v1.19 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -430,7 +452,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 index a5515b6d..cbe8d415 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 @@ -1,4 +1,4 @@ -# db-load-xml v1.19 — Load 1C configuration from XML files +# db-load-xml v1.20 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.py b/.claude/skills/db-load-xml/scripts/db-load-xml.py index 111bc858..c0495f65 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.py +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-xml v1.19 — Load 1C configuration from XML files +# db-load-xml v1.20 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -413,7 +435,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-run/scripts/db-run.ps1 b/.claude/skills/db-run/scripts/db-run.ps1 index c809cb0d..b20d6488 100644 --- a/.claude/skills/db-run/scripts/db-run.ps1 +++ b/.claude/skills/db-run/scripts/db-run.ps1 @@ -1,4 +1,4 @@ -# db-run v1.7 — Launch 1C:Enterprise +# db-run v1.8 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-run/scripts/db-run.py b/.claude/skills/db-run/scripts/db-run.py index b1ceadd6..9fc0b6d2 100644 --- a/.claude/skills/db-run/scripts/db-run.py +++ b/.claude/skills/db-run/scripts/db-run.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-run v1.7 — Launch 1C:Enterprise +# db-run v1.8 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -11,6 +11,28 @@ import subprocess import sys import time +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -281,7 +303,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/db-update/scripts/db-update.ps1 b/.claude/skills/db-update/scripts/db-update.ps1 index 6eb52344..224bfbc3 100644 --- a/.claude/skills/db-update/scripts/db-update.ps1 +++ b/.claude/skills/db-update/scripts/db-update.ps1 @@ -1,4 +1,4 @@ -# db-update v1.13 — Update 1C database configuration +# db-update v1.14 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/db-update/scripts/db-update.py b/.claude/skills/db-update/scripts/db-update.py index 8ff02429..61b64761 100644 --- a/.claude/skills/db-update/scripts/db-update.py +++ b/.claude/skills/db-update/scripts/db-update.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-update v1.13 — Update 1C database configuration +# db-update v1.14 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -395,7 +417,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/epf-build/scripts/epf-build.ps1 b/.claude/skills/epf-build/scripts/epf-build.ps1 index 7f79cc5d..d238a19c 100644 --- a/.claude/skills/epf-build/scripts/epf-build.ps1 +++ b/.claude/skills/epf-build/scripts/epf-build.ps1 @@ -1,4 +1,4 @@ -# epf-build v1.12 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.13 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/epf-build/scripts/epf-build.py b/.claude/skills/epf-build/scripts/epf-build.py index e62af3c5..37fa1d11 100644 --- a/.claude/skills/epf-build/scripts/epf-build.py +++ b/.claude/skills/epf-build/scripts/epf-build.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-build v1.12 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.13 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -374,7 +396,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/epf-dump/scripts/epf-dump.ps1 b/.claude/skills/epf-dump/scripts/epf-dump.ps1 index 472d711b..3c68eab6 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.ps1 +++ b/.claude/skills/epf-dump/scripts/epf-dump.ps1 @@ -1,4 +1,4 @@ -# epf-dump v1.11 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.12 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# diff --git a/.claude/skills/epf-dump/scripts/epf-dump.py b/.claude/skills/epf-dump/scripts/epf-dump.py index 55de0ce5..0fc28e64 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.py +++ b/.claude/skills/epf-dump/scripts/epf-dump.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-dump v1.11 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.12 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -14,6 +14,28 @@ import subprocess import sys import tempfile +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -380,7 +402,7 @@ def main(): help="Extra ibcmd arguments in --key=value form") known_opts = {s.lower() for a in parser._actions for s in a.option_strings} argv, v8_extra, ibcmd_extra = extract_extra_args(sys.argv[1:], known_opts) - args = parser.parse_args(argv) + args = ci_parse_args(parser, argv) args.V8Path = clean_path(args.V8Path, "-V8Path") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") diff --git a/.claude/skills/epf-init/scripts/init.ps1 b/.claude/skills/epf-init/scripts/init.ps1 index 86c914c8..0e8ad671 100644 --- a/.claude/skills/epf-init/scripts/init.ps1 +++ b/.claude/skills/epf-init/scripts/init.ps1 @@ -1,4 +1,4 @@ -# epf-init v1.6 — Init 1C external data processor scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) +# epf-init v1.7 — Init 1C external data processor scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/epf-init/scripts/init.py b/.claude/skills/epf-init/scripts/init.py index 319ff7c2..7f0c4f63 100644 --- a/.claude/skills/epf-init/scripts/init.py +++ b/.claude/skills/epf-init/scripts/init.py @@ -1,9 +1,31 @@ #!/usr/bin/env python3 -# epf-init v1.6 — Init 1C external data processor scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) +# epf-init v1.7 — Init 1C external data processor scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C external data processor.""" import sys, os, re, argparse, uuid +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def esc_xml_text(s): # Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми. return s.replace('&', '&').replace('<', '<').replace('>', '>') @@ -46,7 +68,7 @@ def main(): # навыки берут уже отсюда: их детектор читает version из корня этого файла. parser.add_argument('-FormatVersion', dest='FormatVersion', default='2.17', choices=['2.17', '2.18', '2.19', '2.20', '2.21']) - args = parser.parse_args() + args = ci_parse_args(parser) name = args.Name synonym = args.Synonym if args.Synonym else name diff --git a/.claude/skills/epf-validate/scripts/epf-validate.ps1 b/.claude/skills/epf-validate/scripts/epf-validate.ps1 index a63273b4..bce7a851 100644 --- a/.claude/skills/epf-validate/scripts/epf-validate.ps1 +++ b/.claude/skills/epf-validate/scripts/epf-validate.ps1 @@ -1,4 +1,4 @@ -# epf-validate v1.3 — Validate 1C external data processor / report structure +# epf-validate v1.4 — Validate 1C external data processor / report structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Works for both EPF (ExternalDataProcessor) and ERF (ExternalReport) — auto-detects param( diff --git a/.claude/skills/epf-validate/scripts/epf-validate.py b/.claude/skills/epf-validate/scripts/epf-validate.py index 841c283e..6f5192cc 100644 --- a/.claude/skills/epf-validate/scripts/epf-validate.py +++ b/.claude/skills/epf-validate/scripts/epf-validate.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-validate v1.3 — Validate 1C external data processor / report structure +# epf-validate v1.4 — Validate 1C external data processor / report structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Works for both EPF (ExternalDataProcessor) and ERF (ExternalReport) — auto-detects @@ -10,6 +10,28 @@ import sys from io import StringIO from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + MD_NS = "http://v8.1c.ru/8.3/MDClasses" V8_NS = "http://v8.1c.ru/8.1/data/core" XR_NS = "http://v8.1c.ru/8.3/xcf/readable" @@ -50,7 +72,7 @@ def main(): parser.add_argument("-Detailed", action="store_true") parser.add_argument("-MaxErrors", type=int, default=30) parser.add_argument("-OutFile", default=None) - args = parser.parse_args() + args = ci_parse_args(parser) max_errors = args.MaxErrors diff --git a/.claude/skills/erf-init/scripts/init.ps1 b/.claude/skills/erf-init/scripts/init.ps1 index 7906a1a3..ec0e071c 100644 --- a/.claude/skills/erf-init/scripts/init.ps1 +++ b/.claude/skills/erf-init/scripts/init.ps1 @@ -1,4 +1,4 @@ -# erf-init v1.6 — Init 1C external report scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) +# erf-init v1.7 — Init 1C external report scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/erf-init/scripts/init.py b/.claude/skills/erf-init/scripts/init.py index 74587649..82b9e182 100644 --- a/.claude/skills/erf-init/scripts/init.py +++ b/.claude/skills/erf-init/scripts/init.py @@ -1,9 +1,31 @@ #!/usr/bin/env python3 -# erf-init v1.6 — Init 1C external report scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) +# erf-init v1.7 — Init 1C external report scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C external report.""" import sys, os, re, argparse, uuid +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def esc_xml_text(s): # Эскейп ТЕКСТА элемента: только & < > — кавычку и апостроф платформа держит сырыми. return s.replace('&', '&').replace('<', '<').replace('>', '>') @@ -47,7 +69,7 @@ def main(): parser.add_argument('-FormatVersion', dest='FormatVersion', default='2.17', choices=['2.17', '2.18', '2.19', '2.20', '2.21']) parser.add_argument('-WithSKD', dest='WithSKD', action='store_true') - args = parser.parse_args() + args = ci_parse_args(parser) name = args.Name synonym = args.Synonym if args.Synonym else name diff --git a/.claude/skills/form-add/scripts/form-add.ps1 b/.claude/skills/form-add/scripts/form-add.ps1 index 730d0293..7e6c1b5a 100644 --- a/.claude/skills/form-add/scripts/form-add.ps1 +++ b/.claude/skills/form-add/scripts/form-add.ps1 @@ -1,4 +1,4 @@ -# form-add v1.24 — Add managed form to 1C config object (+write_xml_file/write_utf8_bom: общий эталон записи) +# form-add v1.25 — Add managed form to 1C config object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/form-add/scripts/form-add.py b/.claude/skills/form-add/scripts/form-add.py index 35f2d89e..eedec6f0 100644 --- a/.claude/skills/form-add/scripts/form-add.py +++ b/.claude/skills/form-add/scripts/form-add.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-add v1.24 — Add managed form to 1C config object (+write_xml_file/write_utf8_bom: общий эталон записи) +# form-add v1.25 — Add managed form to 1C config object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -11,6 +11,28 @@ import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -303,7 +325,7 @@ def main(): parser.add_argument("-Synonym", default=None) parser.add_argument("-Purpose", default="Object") parser.add_argument("-SetDefault", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) object_path = args.ObjectPath form_name = args.FormName diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 1500053c..7e772354 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.189 — Compile 1C managed form from JSON or object metadata (+write_xml_file/write_utf8_bom: общий эталон записи) +# form-compile v1.190 — Compile 1C managed form from JSON or object metadata (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 057d42c0..78218b29 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.189 — Compile 1C managed form from JSON or object metadata (+write_xml_file/write_utf8_bom: общий эталон записи) +# form-compile v1.190 — Compile 1C managed form from JSON or object metadata (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -13,6 +13,28 @@ from collections import OrderedDict from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -6223,7 +6245,7 @@ def main(): parser.add_argument('-Purpose', type=str, default=None) parser.add_argument('-Preset', type=str, default='erp-standard') parser.add_argument('-EmitDsl', type=str, default=None) - args = parser.parse_args() + args = ci_parse_args(parser) # Form name -> purpose mapping _FORM_NAME_TO_PURPOSE = { diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index d0da6b0e..1e1ff248 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.ps1 +++ b/.claude/skills/form-decompile/scripts/form-decompile.ps1 @@ -1,4 +1,4 @@ -# form-decompile v0.147 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.148 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( diff --git a/.claude/skills/form-decompile/scripts/form-decompile.py b/.claude/skills/form-decompile/scripts/form-decompile.py index ec3a0f42..e3cbb9ff 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.py +++ b/.claude/skills/form-decompile/scripts/form-decompile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-decompile v0.147 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.148 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. # @@ -13,6 +13,28 @@ import xml.etree.ElementTree as ET from collections import OrderedDict from decimal import Decimal +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- 1. Namespaces --- NS_LF = "http://v8.1c.ru/8.3/xcf/logform" NS_V8 = "http://v8.1c.ru/8.1/data/core" @@ -3115,7 +3137,7 @@ def main(): parser = argparse.ArgumentParser(description='Decompile 1C managed Form.xml to JSON DSL', allow_abbrev=False) parser.add_argument('-FormPath', '-Path', dest='FormPath', type=str, required=True) parser.add_argument('-OutputPath', dest='OutputPath', type=str, default=None) - args = parser.parse_args() + args = ci_parse_args(parser) form_path = args.FormPath output_path = args.OutputPath diff --git a/.claude/skills/form-edit/scripts/form-edit.ps1 b/.claude/skills/form-edit/scripts/form-edit.ps1 index b4d7f812..5284c703 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.12 — Edit 1C managed form elements (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# form-edit v1.13 — Edit 1C managed form elements (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/form-edit/scripts/form-edit.py b/.claude/skills/form-edit/scripts/form-edit.py index 51bfa4fb..cdd47d6e 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.12 — Edit 1C managed form elements (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# form-edit v1.13 — 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 @@ -11,6 +11,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md # Blocks edits of vendor objects "на замке" / read-only configs. Trigger = bin @@ -192,7 +214,7 @@ def assert_edit_allowed(target_path, require): parser = argparse.ArgumentParser(allow_abbrev=False) parser.add_argument("-FormPath", "-Path", required=True) parser.add_argument("-JsonPath", required=True) -args = parser.parse_args() +args = ci_parse_args(parser) form_path = args.FormPath json_path = args.JsonPath diff --git a/.claude/skills/form-info/scripts/form-info.ps1 b/.claude/skills/form-info/scripts/form-info.ps1 index ab443bc6..858a0d0d 100644 --- a/.claude/skills/form-info/scripts/form-info.ps1 +++ b/.claude/skills/form-info/scripts/form-info.ps1 @@ -1,4 +1,4 @@ -# form-info v1.6 — Analyze 1C managed form structure (+единое имя хелпера состояния поддержки) +# form-info v1.7 — Analyze 1C managed form structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] diff --git a/.claude/skills/form-info/scripts/form-info.py b/.claude/skills/form-info/scripts/form-info.py index a6454e5c..a739cc3d 100644 --- a/.claude/skills/form-info/scripts/form-info.py +++ b/.claude/skills/form-info/scripts/form-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-info v1.6 — Analyze 1C managed form structure (+единое имя хелпера состояния поддержки) +# form-info v1.7 — Analyze 1C managed form structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -8,6 +8,28 @@ import re import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Namespace map --- NSMAP = { @@ -433,7 +455,7 @@ def main(): parser.add_argument("-Limit", type=int, default=150, help="Max lines to show") parser.add_argument("-Offset", type=int, default=0, help="Line offset for pagination") parser.add_argument("-Expand", default="", help="Expand collapsed section by name, or * for all") - args = parser.parse_args() + args = ci_parse_args(parser) form_path = args.FormPath limit = args.Limit diff --git a/.claude/skills/form-remove/scripts/remove-form.ps1 b/.claude/skills/form-remove/scripts/remove-form.ps1 index 3795e04b..20b9113b 100644 --- a/.claude/skills/form-remove/scripts/remove-form.ps1 +++ b/.claude/skills/form-remove/scripts/remove-form.ps1 @@ -1,4 +1,4 @@ -# form-remove v1.8 — Remove form from 1C object +# form-remove v1.9 — Remove form from 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/form-remove/scripts/remove-form.py b/.claude/skills/form-remove/scripts/remove-form.py index a433f25b..4d171fdb 100644 --- a/.claude/skills/form-remove/scripts/remove-form.py +++ b/.claude/skills/form-remove/scripts/remove-form.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-remove v1.8 — Remove form from 1C object +# form-remove v1.9 — Remove form from 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -10,6 +10,28 @@ import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} @@ -68,7 +90,7 @@ def main(): parser.add_argument("-ObjectName", "-ProcessorName", required=True) parser.add_argument("-FormName", required=True) parser.add_argument("-SrcDir", default="src") - args = parser.parse_args() + args = ci_parse_args(parser) object_name = args.ObjectName form_name = args.FormName diff --git a/.claude/skills/form-validate/scripts/form-validate.ps1 b/.claude/skills/form-validate/scripts/form-validate.ps1 index 8f231547..b72996f8 100644 --- a/.claude/skills/form-validate/scripts/form-validate.ps1 +++ b/.claude/skills/form-validate/scripts/form-validate.ps1 @@ -1,4 +1,4 @@ -# form-validate v1.9 — Validate 1C managed form +# form-validate v1.10 — Validate 1C managed form # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/form-validate/scripts/form-validate.py b/.claude/skills/form-validate/scripts/form-validate.py index 43adcf71..acad4f63 100644 --- a/.claude/skills/form-validate/scripts/form-validate.py +++ b/.claude/skills/form-validate/scripts/form-validate.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-validate v1.9 — Validate 1C managed form +# form-validate v1.10 — Validate 1C managed form # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -8,6 +8,28 @@ import re import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + F_NS = "http://v8.1c.ru/8.3/xcf/logform" V8_NS = "http://v8.1c.ru/8.1/data/core" @@ -60,7 +82,7 @@ def main(): parser.add_argument("-FormPath", "-Path", required=True) parser.add_argument("-Detailed", action="store_true") parser.add_argument("-MaxErrors", type=int, default=30) - args = parser.parse_args() + args = ci_parse_args(parser) form_path = args.FormPath detailed = args.Detailed diff --git a/.claude/skills/help-add/scripts/add-help.ps1 b/.claude/skills/help-add/scripts/add-help.ps1 index 673e241b..136b52fd 100644 --- a/.claude/skills/help-add/scripts/add-help.ps1 +++ b/.claude/skills/help-add/scripts/add-help.ps1 @@ -1,4 +1,4 @@ -# help-add v1.18 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) +# help-add v1.19 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/help-add/scripts/add-help.py b/.claude/skills/help-add/scripts/add-help.py index 29230f26..8707f997 100644 --- a/.claude/skills/help-add/scripts/add-help.py +++ b/.claude/skills/help-add/scripts/add-help.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# help-add v1.18 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) +# help-add v1.19 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -10,6 +10,28 @@ import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} @@ -290,7 +312,7 @@ def main(): parser.add_argument("-ObjectName", required=True) parser.add_argument("-Lang", default="ru") parser.add_argument("-SrcDir", default="src") - args = parser.parse_args() + args = ci_parse_args(parser) object_name = args.ObjectName lang = args.Lang diff --git a/.claude/skills/img-grid/scripts/overlay-grid.py b/.claude/skills/img-grid/scripts/overlay-grid.py index e0505230..1606cf31 100644 --- a/.claude/skills/img-grid/scripts/overlay-grid.py +++ b/.claude/skills/img-grid/scripts/overlay-grid.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# img-grid v1.1 — Overlay numbered grid on image +# img-grid v1.2 — Overlay numbered grid on image # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Overlay a numbered grid on an image to help determine column/row proportions. @@ -16,6 +16,28 @@ import os import sys from PIL import Image, ImageDraw, ImageFont +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + MARGIN_TOP = 20 MARGIN_LEFT = 24 @@ -30,7 +52,7 @@ def main(): parser.add_argument("-r", "--rows", type=int, default=0, help="Number of horizontal divisions (0 = auto, match cell aspect ratio)") parser.add_argument("-o", "--output", help="Output path (default: -grid.)") - args = parser.parse_args() + args = ci_parse_args(parser) if args.cols <= 0: parser.error("--cols must be greater than 0") diff --git a/.claude/skills/interface-edit/scripts/interface-edit.ps1 b/.claude/skills/interface-edit/scripts/interface-edit.ps1 index 1a02d931..79a6c85b 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.15 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) +# interface-edit v1.16 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$CIPath, diff --git a/.claude/skills/interface-edit/scripts/interface-edit.py b/.claude/skills/interface-edit/scripts/interface-edit.py index b149104c..2057e81e 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.15 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) +# interface-edit v1.16 — Edit 1C CommandInterface.xml (+русские алиасы типов: формы с ё и без) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -10,6 +10,28 @@ import subprocess import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -420,7 +442,7 @@ def main(): parser.add_argument("-Value", default=None) parser.add_argument("-CreateIfMissing", action="store_true") parser.add_argument("-NoValidate", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) # --- Mode validation --- if args.DefinitionFile and args.Operation: diff --git a/.claude/skills/interface-validate/scripts/interface-validate.ps1 b/.claude/skills/interface-validate/scripts/interface-validate.ps1 index f0c8acb2..eafc6a31 100644 --- a/.claude/skills/interface-validate/scripts/interface-validate.ps1 +++ b/.claude/skills/interface-validate/scripts/interface-validate.ps1 @@ -1,4 +1,4 @@ -# interface-validate v1.2 — Validate 1C CommandInterface.xml structure (+Report-*: общий эталон вывода валидаторов) +# interface-validate v1.3 — Validate 1C CommandInterface.xml structure (+Report-*: общий эталон вывода валидаторов) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$CIPath, diff --git a/.claude/skills/interface-validate/scripts/interface-validate.py b/.claude/skills/interface-validate/scripts/interface-validate.py index 79568416..fd707b8f 100644 --- a/.claude/skills/interface-validate/scripts/interface-validate.py +++ b/.claude/skills/interface-validate/scripts/interface-validate.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# interface-validate v1.2 — Validate 1C CommandInterface.xml structure (+Report-*: общий эталон вывода валидаторов) +# interface-validate v1.3 — Validate 1C CommandInterface.xml structure (+Report-*: общий эталон вывода валидаторов) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates CommandInterface.xml sections, command references, order, duplicates.""" import sys, os, argparse, re from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NS_CI = 'http://v8.1c.ru/8.3/xcf/extrnprops' NS_XR = 'http://v8.1c.ru/8.3/xcf/readable' NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance' @@ -83,7 +105,7 @@ def main(): parser.add_argument('-Detailed', action='store_true') parser.add_argument('-MaxErrors', dest='MaxErrors', type=int, default=30) parser.add_argument('-OutFile', dest='OutFile', default='') - args = parser.parse_args() + args = ci_parse_args(parser) ci_path = args.CIPath detailed = args.Detailed diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index c84af042..d476bcde 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 @@ -1,4 +1,4 @@ -# meta-decompile v0.63 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.64 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.py b/.claude/skills/meta-decompile/scripts/meta-decompile.py index e1fe8cd7..5850e021 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.py +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-decompile v0.63 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.64 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Зеркало meta-decompile.ps1 (КАНОН). Структура 1:1 — те же имена функций, порядок, комментарии. @@ -20,6 +20,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Namespaces (зеркало XmlNamespaceManager) --- NS_MD = "http://v8.1c.ru/8.3/MDClasses" NS_V8 = "http://v8.1c.ru/8.1/data/core" @@ -2099,7 +2121,7 @@ def main(): parser = argparse.ArgumentParser(description='Decompile 1C metadata object XML to JSON DSL (draft)', allow_abbrev=False) parser.add_argument('-ObjectPath', '-Path', dest='ObjectPath', type=str, required=True) parser.add_argument('-OutputPath', dest='OutputPath', type=str, default=None) - args = parser.parse_args() + args = ci_parse_args(parser) object_path = args.ObjectPath if not os.path.exists(object_path): diff --git a/.claude/skills/meta-edit/scripts/meta-edit.ps1 b/.claude/skills/meta-edit/scripts/meta-edit.ps1 index 5e26d5ae..e919b164 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.35 — Edit existing 1C metadata object XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# meta-edit v1.36 — Edit existing 1C metadata object XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, diff --git a/.claude/skills/meta-edit/scripts/meta-edit.py b/.claude/skills/meta-edit/scripts/meta-edit.py index 5da17060..7776d0b6 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.35 — Edit existing 1C metadata object XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# meta-edit v1.36 — Edit existing 1C metadata object XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -11,6 +11,28 @@ import sys import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -3174,7 +3196,7 @@ def main(): parser.add_argument("-Operation", default=None, choices=valid_operations, help="Inline operation") parser.add_argument("-Value", default=None, help="Inline value") parser.add_argument("-NoValidate", action="store_true", help="Skip auto-validation") - args = parser.parse_args() + args = ci_parse_args(parser) # --- Mode validation --- if args.DefinitionFile and args.Operation: diff --git a/.claude/skills/meta-info/scripts/meta-info.ps1 b/.claude/skills/meta-info/scripts/meta-info.ps1 index e656bafb..4895708e 100644 --- a/.claude/skills/meta-info/scripts/meta-info.ps1 +++ b/.claude/skills/meta-info/scripts/meta-info.ps1 @@ -1,4 +1,4 @@ -# meta-info v1.9 — Compact summary of 1C metadata object (+единое имя хелпера состояния поддержки) +# meta-info v1.10 — Compact summary of 1C metadata object (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$ObjectPath, diff --git a/.claude/skills/meta-info/scripts/meta-info.py b/.claude/skills/meta-info/scripts/meta-info.py index b2f72bd3..3027b5d4 100644 --- a/.claude/skills/meta-info/scripts/meta-info.py +++ b/.claude/skills/meta-info/scripts/meta-info.py @@ -1,4 +1,4 @@ -# meta-info v1.9 — Compact summary of 1C metadata object (Python port) (+единое имя хелпера состояния поддержки) +# meta-info v1.10 — Compact summary of 1C metadata object (Python port) (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -10,6 +10,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ── arg parsing ────────────────────────────────────────────── parser = argparse.ArgumentParser(allow_abbrev=False) @@ -19,7 +41,7 @@ parser.add_argument("-Name", default="") parser.add_argument("-Limit", type=int, default=150) parser.add_argument("-Offset", type=int, default=0) parser.add_argument("-OutFile", default="") -args = parser.parse_args() +args = ci_parse_args(parser) object_path = args.ObjectPath mode = args.Mode diff --git a/.claude/skills/meta-remove/scripts/meta-remove.ps1 b/.claude/skills/meta-remove/scripts/meta-remove.ps1 index 17008256..d632da56 100644 --- a/.claude/skills/meta-remove/scripts/meta-remove.ps1 +++ b/.claude/skills/meta-remove/scripts/meta-remove.ps1 @@ -1,4 +1,4 @@ -# meta-remove v1.8 — Remove metadata object from 1C configuration dump +# meta-remove v1.9 — Remove metadata object from 1C configuration dump # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/meta-remove/scripts/meta-remove.py b/.claude/skills/meta-remove/scripts/meta-remove.py index a8a49c26..67224a18 100644 --- a/.claude/skills/meta-remove/scripts/meta-remove.py +++ b/.claude/skills/meta-remove/scripts/meta-remove.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-remove v1.8 — Remove metadata object from 1C configuration dump +# meta-remove v1.9 — Remove metadata object from 1C configuration dump # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -10,6 +10,28 @@ import sys import shutil from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -331,7 +353,7 @@ def main(): parser.add_argument("-DryRun", action="store_true") parser.add_argument("-KeepFiles", action="store_true") parser.add_argument("-Force", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) config_dir = args.ConfigDir if not os.path.isabs(config_dir): diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1 index f5ea46bc..a78a8cd1 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.17 — Validate 1C metadata object structure +# meta-validate v1.18 — Validate 1C metadata object structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py index be177063..b6734834 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.17 — Validate 1C metadata object structure (Python port) +# meta-validate v1.18 — Validate 1C metadata object structure (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -11,6 +11,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ── arg parsing ────────────────────────────────────────────── parser = argparse.ArgumentParser(allow_abbrev=False) @@ -18,7 +40,7 @@ parser.add_argument("-ObjectPath", "-Path", required=True) parser.add_argument("-Detailed", action="store_true") parser.add_argument("-MaxErrors", type=int, default=30) parser.add_argument("-OutFile", default="") -args = parser.parse_args() +args = ci_parse_args(parser) detailed = args.Detailed max_errors = args.MaxErrors diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 index 6f16ffab..950c5b07 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.12 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) +# mxl-compile v1.13 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py index e8bdfe4e..15b0ab44 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.12 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) +# mxl-compile v1.13 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -10,6 +10,28 @@ import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -244,7 +266,7 @@ def main(): parser = argparse.ArgumentParser(description='Compile 1C spreadsheet from JSON', allow_abbrev=False) parser.add_argument('-JsonPath', type=str, required=True) parser.add_argument('-OutputPath', type=str, required=True) - args = parser.parse_args() + args = ci_parse_args(parser) # --- Detect XML format version --- # У корня нет атрибута version, поэтому версию берём из конфигурации, в дерево diff --git a/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 b/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 index f1c66696..60e9e6a7 100644 --- a/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 +++ b/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 @@ -1,4 +1,4 @@ -# mxl-decompile v1.0 — Decompile 1C spreadsheet to JSON +# mxl-decompile v1.1 — Decompile 1C spreadsheet to JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/mxl-decompile/scripts/mxl-decompile.py b/.claude/skills/mxl-decompile/scripts/mxl-decompile.py index 280eb0ef..f28e8720 100644 --- a/.claude/skills/mxl-decompile/scripts/mxl-decompile.py +++ b/.claude/skills/mxl-decompile/scripts/mxl-decompile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-decompile v1.0 — Decompile 1C spreadsheet to JSON +# mxl-decompile v1.1 — Decompile 1C spreadsheet to JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -9,6 +9,28 @@ import sys from collections import OrderedDict from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Namespace map --- NSMAP = { @@ -49,7 +71,7 @@ def main(): parser = argparse.ArgumentParser(description="Decompile 1C spreadsheet to JSON", allow_abbrev=False) parser.add_argument("-TemplatePath", "-Path", required=True, help="Path to Template.xml") parser.add_argument("-OutputPath", default=None, help="Output JSON path (stdout if omitted)") - args = parser.parse_args() + args = ci_parse_args(parser) template_path = args.TemplatePath output_path = args.OutputPath diff --git a/.claude/skills/mxl-info/scripts/mxl-info.ps1 b/.claude/skills/mxl-info/scripts/mxl-info.ps1 index 66bca779..7c0e6c93 100644 --- a/.claude/skills/mxl-info/scripts/mxl-info.ps1 +++ b/.claude/skills/mxl-info/scripts/mxl-info.ps1 @@ -1,4 +1,4 @@ -# mxl-info v1.3 — Analyze 1C spreadsheet structure (+единое имя хелпера состояния поддержки) +# mxl-info v1.4 — Analyze 1C spreadsheet structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Alias('Path')] diff --git a/.claude/skills/mxl-info/scripts/mxl-info.py b/.claude/skills/mxl-info/scripts/mxl-info.py index c092462d..b32ad16e 100644 --- a/.claude/skills/mxl-info/scripts/mxl-info.py +++ b/.claude/skills/mxl-info/scripts/mxl-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-info v1.3 — Analyze 1C spreadsheet structure (+единое имя хелпера состояния поддержки) +# mxl-info v1.4 — Analyze 1C spreadsheet structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -12,6 +12,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Argument parsing --- parser = argparse.ArgumentParser(description="Analyze 1C spreadsheet (MXL) structure", allow_abbrev=False) parser.add_argument("-TemplatePath", "-Path", default="", help="Path to Template.xml") @@ -23,7 +45,7 @@ parser.add_argument("-WithText", action="store_true", default=False, help="Inclu parser.add_argument("-MaxParams", type=int, default=10, help="Max parameters to show per area") parser.add_argument("-Limit", type=int, default=150, help="Max lines to show") parser.add_argument("-Offset", type=int, default=0, help="Lines to skip") -args = parser.parse_args() +args = ci_parse_args(parser) # --- Resolve template path --- template_path = args.TemplatePath diff --git a/.claude/skills/mxl-validate/scripts/mxl-validate.ps1 b/.claude/skills/mxl-validate/scripts/mxl-validate.ps1 index b12cb5ef..7cf6338f 100644 --- a/.claude/skills/mxl-validate/scripts/mxl-validate.ps1 +++ b/.claude/skills/mxl-validate/scripts/mxl-validate.ps1 @@ -1,4 +1,4 @@ -# mxl-validate v1.1 — Validate 1C spreadsheet +# mxl-validate v1.2 — Validate 1C spreadsheet # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Alias('Path')] diff --git a/.claude/skills/mxl-validate/scripts/mxl-validate.py b/.claude/skills/mxl-validate/scripts/mxl-validate.py index 94b88842..dd4bef79 100644 --- a/.claude/skills/mxl-validate/scripts/mxl-validate.py +++ b/.claude/skills/mxl-validate/scripts/mxl-validate.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# mxl-validate v1.1 — Validate 1C spreadsheet document Template.xml +# mxl-validate v1.2 — Validate 1C spreadsheet document Template.xml # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates spreadsheet Template.xml: height, palette refs, column/row indices, areas, merges.""" import sys, os, argparse from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NS_D = 'http://v8.1c.ru/8.2/data/spreadsheet' NS_V8 = 'http://v8.1c.ru/8.1/data/core' NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance' @@ -61,7 +83,7 @@ def main(): parser.add_argument('-SrcDir', dest='SrcDir', default='src') parser.add_argument('-Detailed', action='store_true') parser.add_argument('-MaxErrors', dest='MaxErrors', type=int, default=20) - args = parser.parse_args() + args = ci_parse_args(parser) template_path = args.TemplatePath processor_name = args.ProcessorName diff --git a/.claude/skills/role-compile/scripts/role-compile.ps1 b/.claude/skills/role-compile/scripts/role-compile.ps1 index 5dfe6264..2e0df6ca 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.22 — Compile 1C role from JSON (+русские алиасы типов: формы с ё и без) +# role-compile v1.23 — Compile 1C role from JSON (+русские алиасы типов: формы с ё и без) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/role-compile/scripts/role-compile.py b/.claude/skills/role-compile/scripts/role-compile.py index a912cbe7..7f7e56e2 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.22 — Compile 1C role from JSON (+русские алиасы типов: формы с ё и без) +# role-compile v1.23 — Compile 1C role from JSON (+русские алиасы типов: формы с ё и без) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -10,6 +10,28 @@ import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -667,7 +689,7 @@ def main(): parser = argparse.ArgumentParser(description='Compile 1C role from JSON', allow_abbrev=False) parser.add_argument('-JsonPath', type=str, required=True) parser.add_argument('-OutputDir', type=str, required=True) - args = parser.parse_args() + args = ci_parse_args(parser) # --- 1. Load and validate JSON --- json_path = args.JsonPath diff --git a/.claude/skills/role-info/scripts/role-info.ps1 b/.claude/skills/role-info/scripts/role-info.ps1 index 253190b9..3ff657ff 100644 --- a/.claude/skills/role-info/scripts/role-info.ps1 +++ b/.claude/skills/role-info/scripts/role-info.ps1 @@ -1,4 +1,4 @@ -# role-info v1.3 — Analyze 1C role rights (+единое имя хелпера состояния поддержки) +# role-info v1.4 — Analyze 1C role rights (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$RightsPath, diff --git a/.claude/skills/role-info/scripts/role-info.py b/.claude/skills/role-info/scripts/role-info.py index 4ba5dc86..aef4feb2 100644 --- a/.claude/skills/role-info/scripts/role-info.py +++ b/.claude/skills/role-info/scripts/role-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-info v1.3 — Analyze 1C role rights (+единое имя хелпера состояния поддержки) +# role-info v1.4 — Analyze 1C role rights (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -12,6 +12,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Argument parsing --- parser = argparse.ArgumentParser(description="Analyze 1C role rights", allow_abbrev=False) parser.add_argument("-RightsPath", "-Path", required=True, help="Path to Rights.xml") @@ -19,7 +41,7 @@ parser.add_argument("-ShowDenied", action="store_true", default=False, help="Sho parser.add_argument("-Limit", type=int, default=150, help="Max lines to show") parser.add_argument("-Offset", type=int, default=0, help="Lines to skip") parser.add_argument("-OutFile", default="", help="Write output to file") -args = parser.parse_args() +args = ci_parse_args(parser) # --- Output helper (collect all, paginate at the end) --- lines_buf = [] diff --git a/.claude/skills/role-validate/scripts/role-validate.ps1 b/.claude/skills/role-validate/scripts/role-validate.ps1 index 98ca95c9..fdac6ebe 100644 --- a/.claude/skills/role-validate/scripts/role-validate.ps1 +++ b/.claude/skills/role-validate/scripts/role-validate.ps1 @@ -1,4 +1,4 @@ -# role-validate v1.1 — Validate 1C role structure +# role-validate v1.2 — Validate 1C role structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/role-validate/scripts/role-validate.py b/.claude/skills/role-validate/scripts/role-validate.py index c4bb580a..2836998a 100644 --- a/.claude/skills/role-validate/scripts/role-validate.py +++ b/.claude/skills/role-validate/scripts/role-validate.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# role-validate v1.1 — Validate 1C role Rights.xml structure +# role-validate v1.2 — Validate 1C role Rights.xml structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates role Rights.xml: root element, global flags, objects, rights, RLS, templates.""" import sys, os, argparse, re from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + GUID_PATTERN = re.compile( r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.IGNORECASE @@ -183,7 +205,7 @@ def main(): parser.add_argument('-OutFile', dest='OutFile', default='') parser.add_argument('-Detailed', dest='Detailed', action='store_true') parser.add_argument('-MaxErrors', dest='MaxErrors', type=int, default=30) - args = parser.parse_args() + args = ci_parse_args(parser) rights_path = args.RightsPath out_file = args.OutFile diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index 5fd3ca24..7cc4a7df 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.115 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) +# skd-compile v1.116 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index f4713253..a6165a09 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.115 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) +# skd-compile v1.116 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -10,6 +10,28 @@ import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -2985,7 +3007,7 @@ def main(): parser.add_argument('-DefinitionFile', type=str, default=None) parser.add_argument('-Value', type=str, default=None) parser.add_argument('-OutputPath', type=str, required=True) - args = parser.parse_args() + args = ci_parse_args(parser) # --- 1. Load and validate JSON --- if args.DefinitionFile and args.Value: diff --git a/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 b/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 index 74b95ab5..daf3b8c7 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.91 — Decompile 1C DCS Template.xml to JSON DSL (draft) +# skd-decompile v0.92 — Decompile 1C DCS Template.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/skd-decompile/scripts/skd-decompile.py b/.claude/skills/skd-decompile/scripts/skd-decompile.py index 4b32fc35..723c9281 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.91 — Decompile 1C DCS Template.xml to JSON DSL (draft) +# skd-decompile v0.92 — Decompile 1C DCS Template.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -7,6 +7,28 @@ import re import sys import xml.etree.ElementTree as ET +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- 1. Namespace manager --- NS_SCHEMA = "http://v8.1c.ru/8.1/data-composition-system/schema" @@ -281,7 +303,7 @@ def main(): parser = argparse.ArgumentParser(description='Decompile 1C DCS Template.xml to JSON DSL', allow_abbrev=False) parser.add_argument('-TemplatePath', '-Path', dest='TemplatePath', type=str, required=True) parser.add_argument('-OutputPath', type=str, default=None) - args = parser.parse_args() + args = ci_parse_args(parser) global TemplatePath, OutputPath TemplatePath = args.TemplatePath diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1 index 7c0d02b8..1efdd2fd 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.ps1 +++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1 @@ -1,4 +1,4 @@ -# skd-edit v1.35 — Atomic 1C DCS editor (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# skd-edit v1.36 — Atomic 1C DCS editor (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: парный .py собирает выражения автодат вне f-string ради совместимости с python 3.9 (PEP 701). param( diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py index 448b8062..749176c4 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.py +++ b/.claude/skills/skd-edit/scripts/skd-edit.py @@ -1,4 +1,4 @@ -# skd-edit v1.35 — Atomic 1C DCS editor (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# skd-edit v1.36 — Atomic 1C DCS editor (Python port) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -12,6 +12,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # Dirty flag — set to True by every successful mutation. If still False at save time, # the file is left untouched (NO-OP operations like [WARN] not found don't rewrite). dirty = False @@ -36,7 +58,7 @@ parser.add_argument("-Value", required=True) parser.add_argument("-DataSet", default="") parser.add_argument("-Variant", default="") parser.add_argument("-NoSelection", action="store_true") -args = parser.parse_args() +args = ci_parse_args(parser) template_path = args.TemplatePath operation = args.Operation diff --git a/.claude/skills/skd-info/scripts/skd-info.ps1 b/.claude/skills/skd-info/scripts/skd-info.ps1 index b1cfcba1..4547a12e 100644 --- a/.claude/skills/skd-info/scripts/skd-info.ps1 +++ b/.claude/skills/skd-info/scripts/skd-info.ps1 @@ -1,4 +1,4 @@ -# skd-info v1.10 — Analyze 1C DCS structure (+единое имя хелпера состояния поддержки) +# skd-info v1.11 — Analyze 1C DCS structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] diff --git a/.claude/skills/skd-info/scripts/skd-info.py b/.claude/skills/skd-info/scripts/skd-info.py index 79c5476b..c9d19b83 100644 --- a/.claude/skills/skd-info/scripts/skd-info.py +++ b/.claude/skills/skd-info/scripts/skd-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-info v1.10 — Analyze 1C DCS structure (+единое имя хелпера состояния поддержки) +# skd-info v1.11 — Analyze 1C DCS structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -9,6 +9,28 @@ import sys from collections import OrderedDict from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + S_NS = "http://v8.1c.ru/8.1/data-composition-system/schema" DCSCOM_NS = "http://v8.1c.ru/8.1/data-composition-system/common" DCSCOR_NS = "http://v8.1c.ru/8.1/data-composition-system/core" @@ -362,7 +384,7 @@ def main(): parser.add_argument("-Offset", type=int, default=0) parser.add_argument("-OutFile", default=None) parser.add_argument("-Raw", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) # --- Resolve path --- original_path = args.TemplatePath diff --git a/.claude/skills/skd-validate/scripts/skd-validate.ps1 b/.claude/skills/skd-validate/scripts/skd-validate.ps1 index a8c9458f..def284d1 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.2 — Validate 1C DCS structure +# skd-validate v1.3 — Validate 1C DCS structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/skd-validate/scripts/skd-validate.py b/.claude/skills/skd-validate/scripts/skd-validate.py index fc0555ca..3228b55b 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.2 — Validate 1C DCS structure (Python port) +# skd-validate v1.3 — Validate 1C DCS structure (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -9,6 +9,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ── arg parsing ────────────────────────────────────────────── parser = argparse.ArgumentParser(allow_abbrev=False) @@ -16,7 +38,7 @@ parser.add_argument("-TemplatePath", "-Path", required=True) parser.add_argument("-Detailed", action="store_true") parser.add_argument("-MaxErrors", type=int, default=20) parser.add_argument("-OutFile", default="") -args = parser.parse_args() +args = ci_parse_args(parser) template_path = args.TemplatePath detailed = args.Detailed diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 index 4b514610..a79a11b0 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.23 — Create 1C subsystem from JSON definition (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# subsystem-compile v1.24 — Create 1C subsystem from JSON definition (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py index 8902e679..0db65347 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.23 — Create 1C subsystem from JSON definition (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# subsystem-compile v1.24 — Create 1C subsystem from JSON definition (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -11,6 +11,28 @@ import uuid import xml.etree.ElementTree as ET from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -338,7 +360,7 @@ def main(): parser.add_argument('-OutputDir', type=str, required=True) parser.add_argument('-Parent', type=str, default=None) parser.add_argument('-NoValidate', action='store_true', default=False) - args = parser.parse_args() + args = ci_parse_args(parser) # --- 1. Load JSON --- if args.DefinitionFile and args.Value: diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 index 015bda01..ea29e995 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.18 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# subsystem-edit v1.19 — 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, diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py index b6fbd1ef..956a5852 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.18 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) +# subsystem-edit v1.19 — Edit existing 1C subsystem XML (+тип Bot; cfe-diff/cfe-borrow: недостающие типы) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -11,6 +11,28 @@ import sys import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # ============================================================ # Support guard (Ext/ParentConfigurations.bin) — see docs/1c-support-state-spec.md @@ -521,7 +543,7 @@ def main(): parser.add_argument("-Operation", default=None, choices=["add-content", "remove-content", "add-child", "remove-child", "set-property"]) parser.add_argument("-Value", default=None) parser.add_argument("-NoValidate", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) # --- Mode validation --- if args.DefinitionFile and args.Operation: diff --git a/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 b/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 index b3275a2f..98006ec7 100644 --- a/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 +++ b/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 @@ -1,4 +1,4 @@ -# subsystem-info v1.3 — Compact summary of 1C subsystem structure (+единое имя хелпера состояния поддержки) +# subsystem-info v1.4 — Compact summary of 1C subsystem structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$SubsystemPath, diff --git a/.claude/skills/subsystem-info/scripts/subsystem-info.py b/.claude/skills/subsystem-info/scripts/subsystem-info.py index 2f5e1f9a..d2d48e02 100644 --- a/.claude/skills/subsystem-info/scripts/subsystem-info.py +++ b/.claude/skills/subsystem-info/scripts/subsystem-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-info v1.3 — Compact summary of 1C subsystem structure (+единое имя хелпера состояния поддержки) +# subsystem-info v1.4 — Compact summary of 1C subsystem structure (+единое имя хелпера состояния поддержки) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -12,6 +12,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + # --- Argument parsing --- parser = argparse.ArgumentParser(description="Analyze 1C subsystem structure", allow_abbrev=False) parser.add_argument("-SubsystemPath", "-Path", required=True, help="Path to subsystem XML or Subsystems/ directory") @@ -20,7 +42,7 @@ parser.add_argument("-Name", default="", help="Filter by name/type") parser.add_argument("-Limit", type=int, default=150, help="Max lines to show") parser.add_argument("-Offset", type=int, default=0, help="Lines to skip") parser.add_argument("-OutFile", default="", help="Write output to file") -args = parser.parse_args() +args = ci_parse_args(parser) # --- Output helper --- lines_buf = [] diff --git a/.claude/skills/subsystem-validate/scripts/subsystem-validate.ps1 b/.claude/skills/subsystem-validate/scripts/subsystem-validate.ps1 index 1a479919..84d0af28 100644 --- a/.claude/skills/subsystem-validate/scripts/subsystem-validate.ps1 +++ b/.claude/skills/subsystem-validate/scripts/subsystem-validate.ps1 @@ -1,4 +1,4 @@ -# subsystem-validate v1.3 — Validate 1C subsystem XML structure (+Report-*: общий эталон вывода валидаторов) +# subsystem-validate v1.4 — Validate 1C subsystem XML structure (+Report-*: общий эталон вывода валидаторов) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$SubsystemPath, diff --git a/.claude/skills/subsystem-validate/scripts/subsystem-validate.py b/.claude/skills/subsystem-validate/scripts/subsystem-validate.py index 1e32214e..407fa663 100644 --- a/.claude/skills/subsystem-validate/scripts/subsystem-validate.py +++ b/.claude/skills/subsystem-validate/scripts/subsystem-validate.py @@ -1,10 +1,32 @@ #!/usr/bin/env python3 -# subsystem-validate v1.3 — Validate 1C subsystem XML structure (+Report-*: общий эталон вывода валидаторов) +# subsystem-validate v1.4 — Validate 1C subsystem XML structure (+Report-*: общий эталон вывода валидаторов) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Validates subsystem XML file structure, properties, content items, child objects.""" import sys, os, argparse, re from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NS = { 'md': 'http://v8.1c.ru/8.3/MDClasses', 'v8': 'http://v8.1c.ru/8.1/data/core', @@ -86,7 +108,7 @@ def main(): parser.add_argument('-Detailed', action='store_true') parser.add_argument('-MaxErrors', dest='MaxErrors', type=int, default=30) parser.add_argument('-OutFile', dest='OutFile', default='') - args = parser.parse_args() + args = ci_parse_args(parser) subsystem_path = args.SubsystemPath detailed = args.Detailed diff --git a/.claude/skills/support-edit/scripts/support-edit.ps1 b/.claude/skills/support-edit/scripts/support-edit.ps1 index f50a89ee..0966f25f 100644 --- a/.claude/skills/support-edit/scripts/support-edit.ps1 +++ b/.claude/skills/support-edit/scripts/support-edit.ps1 @@ -1,4 +1,4 @@ -# support-edit v1.0 — Toggle 1C configuration support state (Ext/ParentConfigurations.bin) +# support-edit v1.1 — Toggle 1C configuration support state (Ext/ParentConfigurations.bin) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$TargetPath, diff --git a/.claude/skills/support-edit/scripts/support-edit.py b/.claude/skills/support-edit/scripts/support-edit.py index ce1a9ed4..9c30eda2 100644 --- a/.claude/skills/support-edit/scripts/support-edit.py +++ b/.claude/skills/support-edit/scripts/support-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# support-edit v1.0 — Toggle 1C configuration support state (Ext/ParentConfigurations.bin) +# support-edit v1.1 — Toggle 1C configuration support state (Ext/ParentConfigurations.bin) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -12,11 +12,33 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + parser = argparse.ArgumentParser(description="Toggle 1C support state", allow_abbrev=False) parser.add_argument("-Path", "-TargetPath", dest="Path", required=True, help="Путь к объекту/форме/макету или каталогу дампа") parser.add_argument("-Set", choices=["editable", "off-support", "locked"], default=None) parser.add_argument("-Capability", choices=["on", "off"], default=None) -args = parser.parse_args() +args = ci_parse_args(parser) if (not args.Set and not args.Capability) or (args.Set and args.Capability): sys.stderr.write("Укажите ровно одно: -Set editable|off-support|locked ЛИБО -Capability on|off\n") diff --git a/.claude/skills/template-add/scripts/add-template.ps1 b/.claude/skills/template-add/scripts/add-template.ps1 index 56b46bd7..6cb1e330 100644 --- a/.claude/skills/template-add/scripts/add-template.ps1 +++ b/.claude/skills/template-add/scripts/add-template.ps1 @@ -1,4 +1,4 @@ -# template-add v1.22 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) +# template-add v1.23 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/template-add/scripts/add-template.py b/.claude/skills/template-add/scripts/add-template.py index 97b0524d..e88422af 100644 --- a/.claude/skills/template-add/scripts/add-template.py +++ b/.claude/skills/template-add/scripts/add-template.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# template-add v1.22 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) +# template-add v1.23 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -11,6 +11,28 @@ import uuid from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} @@ -309,7 +331,7 @@ def main(): parser.add_argument("-Synonym", default=None) parser.add_argument("-SrcDir", default="src") parser.add_argument("-SetMainSKD", action="store_true") - args = parser.parse_args() + args = ci_parse_args(parser) object_name = args.ObjectName template_name = args.TemplateName diff --git a/.claude/skills/template-remove/scripts/remove-template.ps1 b/.claude/skills/template-remove/scripts/remove-template.ps1 index 721fa4b6..46706e2f 100644 --- a/.claude/skills/template-remove/scripts/remove-template.ps1 +++ b/.claude/skills/template-remove/scripts/remove-template.ps1 @@ -1,4 +1,4 @@ -# template-remove v1.7 — Remove template from 1C object +# template-remove v1.8 — Remove template from 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/template-remove/scripts/remove-template.py b/.claude/skills/template-remove/scripts/remove-template.py index 5b910fc5..adc548f3 100644 --- a/.claude/skills/template-remove/scripts/remove-template.py +++ b/.claude/skills/template-remove/scripts/remove-template.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# template-remove v1.7 — Remove template from 1C object +# template-remove v1.8 — Remove template from 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -10,6 +10,28 @@ import sys from lxml import etree +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} @@ -68,7 +90,7 @@ def main(): parser.add_argument("-ObjectName", "-ProcessorName", required=True) parser.add_argument("-TemplateName", required=True) parser.add_argument("-SrcDir", default="src") - args = parser.parse_args() + args = ci_parse_args(parser) object_name = args.ObjectName template_name = args.TemplateName diff --git a/.claude/skills/web-info/scripts/web-info.ps1 b/.claude/skills/web-info/scripts/web-info.ps1 index f616e812..710c296f 100644 --- a/.claude/skills/web-info/scripts/web-info.ps1 +++ b/.claude/skills/web-info/scripts/web-info.ps1 @@ -1,4 +1,4 @@ -# web-info v1.3 — Apache & 1C publication status +# web-info v1.4 — Apache & 1C publication status # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills <# .SYNOPSIS diff --git a/.claude/skills/web-info/scripts/web-info.py b/.claude/skills/web-info/scripts/web-info.py index 7f4e34cf..98fc3751 100644 --- a/.claude/skills/web-info/scripts/web-info.py +++ b/.claude/skills/web-info/scripts/web-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# web-info v1.3 — Apache & 1C publication status +# web-info v1.4 — Apache & 1C publication status # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """ @@ -16,6 +16,28 @@ import sys import psutil +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def get_httpd_by_exe(httpd_exe_norm): """Get httpd processes matching our exe path.""" @@ -38,7 +60,7 @@ def main(): sys.stderr.reconfigure(encoding="utf-8") parser = argparse.ArgumentParser(description='Apache & 1C publication status', allow_abbrev=False) parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)') - args = parser.parse_args() + args = ci_parse_args(parser) # --- Resolve ApachePath --- apache_path = args.ApachePath diff --git a/.claude/skills/web-publish/scripts/web-publish.ps1 b/.claude/skills/web-publish/scripts/web-publish.ps1 index 1b11d424..b495f738 100644 --- a/.claude/skills/web-publish/scripts/web-publish.ps1 +++ b/.claude/skills/web-publish/scripts/web-publish.ps1 @@ -1,4 +1,4 @@ -# web-publish v1.6 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) +# web-publish v1.7 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills <# .SYNOPSIS diff --git a/.claude/skills/web-publish/scripts/web-publish.py b/.claude/skills/web-publish/scripts/web-publish.py index 3ac4947a..8b0677e6 100644 --- a/.claude/skills/web-publish/scripts/web-publish.py +++ b/.claude/skills/web-publish/scripts/web-publish.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# web-publish v1.6 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) +# web-publish v1.7 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """ @@ -24,6 +24,28 @@ import zipfile import psutil +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def _find_project_v8path(): """Walk up from CWD to find .v8-project.json and read its v8path.""" @@ -108,7 +130,7 @@ def main(): parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)') parser.add_argument('-Port', type=int, default=8081, help='Port (default: 8081)') parser.add_argument('-Manual', action='store_true', help='Do not download Apache — only check and give instructions') - args = parser.parse_args() + args = ci_parse_args(parser) # --- Resolve V8Path --- v8_path = args.V8Path diff --git a/.claude/skills/web-stop/scripts/web-stop.ps1 b/.claude/skills/web-stop/scripts/web-stop.ps1 index c7025bb7..01bc618c 100644 --- a/.claude/skills/web-stop/scripts/web-stop.ps1 +++ b/.claude/skills/web-stop/scripts/web-stop.ps1 @@ -1,4 +1,4 @@ -# web-stop v1.0 — Stop Apache HTTP Server +# web-stop v1.1 — Stop Apache HTTP Server # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills <# .SYNOPSIS diff --git a/.claude/skills/web-stop/scripts/web-stop.py b/.claude/skills/web-stop/scripts/web-stop.py index 08182bb8..3283e854 100644 --- a/.claude/skills/web-stop/scripts/web-stop.py +++ b/.claude/skills/web-stop/scripts/web-stop.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# web-stop v1.0 — Stop Apache HTTP Server +# web-stop v1.1 — Stop Apache HTTP Server # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """ @@ -14,6 +14,28 @@ import time import psutil +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def get_our_httpd(httpd_exe_norm): """Filter httpd processes by our ApachePath.""" @@ -47,7 +69,7 @@ def main(): sys.stderr.reconfigure(encoding="utf-8") parser = argparse.ArgumentParser(description='Stop Apache HTTP Server', allow_abbrev=False) parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)') - args = parser.parse_args() + args = ci_parse_args(parser) # --- Resolve ApachePath --- apache_path = args.ApachePath diff --git a/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 b/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 index a8622738..6207ecdb 100644 --- a/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 +++ b/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 @@ -1,4 +1,4 @@ -# web-unpublish v1.0 — Remove 1C web publication +# web-unpublish v1.1 — Remove 1C web publication # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills <# .SYNOPSIS diff --git a/.claude/skills/web-unpublish/scripts/web-unpublish.py b/.claude/skills/web-unpublish/scripts/web-unpublish.py index 1aa4fd04..07980ebc 100644 --- a/.claude/skills/web-unpublish/scripts/web-unpublish.py +++ b/.claude/skills/web-unpublish/scripts/web-unpublish.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# web-unpublish v1.0 — Remove 1C web publication +# web-unpublish v1.1 — Remove 1C web publication # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """ @@ -19,6 +19,28 @@ import time import psutil +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + def get_our_httpd(httpd_exe_norm): """Filter httpd processes by our ApachePath.""" @@ -42,7 +64,7 @@ def main(): parser.add_argument('-AppName', type=str, default='', help='Publication name') parser.add_argument('-ApachePath', type=str, default='', help='Apache root (default: tools\\apache24)') parser.add_argument('-All', action='store_true', help='Remove all publications') - args = parser.parse_args() + args = ci_parse_args(parser) # --- Resolve ApachePath --- apache_path = args.ApachePath diff --git a/.claude/skills/xdto-compile/scripts/xdto-compile.ps1 b/.claude/skills/xdto-compile/scripts/xdto-compile.ps1 index d4146423..985f3b7e 100644 --- a/.claude/skills/xdto-compile/scripts/xdto-compile.ps1 +++ b/.claude/skills/xdto-compile/scripts/xdto-compile.ps1 @@ -1,4 +1,4 @@ -# xdto-compile v1.10 — Build a 1C XDTO package from an XML Schema (XSD) (+support-guard: общая реализация вместо урезанной) +# xdto-compile v1.11 — Build a 1C XDTO package from an XML Schema (XSD) (+support-guard: общая реализация вместо урезанной) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true, ParameterSetName='File')] diff --git a/.claude/skills/xdto-compile/scripts/xdto-compile.py b/.claude/skills/xdto-compile/scripts/xdto-compile.py index 8cdcea09..c2488062 100644 --- a/.claude/skills/xdto-compile/scripts/xdto-compile.py +++ b/.claude/skills/xdto-compile/scripts/xdto-compile.py @@ -1,4 +1,4 @@ -# xdto-compile v1.10 — Build a 1C XDTO package from an XML Schema (XSD) (Python port) (+support-guard: общая реализация вместо урезанной) +# xdto-compile v1.11 — Build a 1C XDTO package from an XML Schema (XSD) (Python port) (+support-guard: общая реализация вместо урезанной) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -24,6 +24,28 @@ PLATFORM_NS = { sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + XDTO_NS = "http://v8.1c.ru/8.1/xdto" XS_NS = "http://www.w3.org/2001/XMLSchema" XSI_NS = "http://www.w3.org/2001/XMLSchema-instance" @@ -37,7 +59,7 @@ parser.add_argument("-Name", default="") parser.add_argument("-Synonym", default="") parser.add_argument("-Comment", default="") parser.add_argument("-Force", action="store_true") -args = parser.parse_args() +args = ci_parse_args(parser) def _parse_xml(source, from_string=False): diff --git a/.claude/skills/xdto-decompile/scripts/xdto-decompile.ps1 b/.claude/skills/xdto-decompile/scripts/xdto-decompile.ps1 index 06180359..71e0ad66 100644 --- a/.claude/skills/xdto-decompile/scripts/xdto-decompile.ps1 +++ b/.claude/skills/xdto-decompile/scripts/xdto-decompile.ps1 @@ -1,4 +1,4 @@ -# xdto-decompile v1.0 — Convert 1C XDTO package to XML Schema (XSD) +# xdto-decompile v1.1 — Convert 1C XDTO package to XML Schema (XSD) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] diff --git a/.claude/skills/xdto-decompile/scripts/xdto-decompile.py b/.claude/skills/xdto-decompile/scripts/xdto-decompile.py index 75e711cf..592467d8 100644 --- a/.claude/skills/xdto-decompile/scripts/xdto-decompile.py +++ b/.claude/skills/xdto-decompile/scripts/xdto-decompile.py @@ -1,4 +1,4 @@ -# xdto-decompile v1.0 — Convert 1C XDTO package to XML Schema (XSD) (Python port) +# xdto-decompile v1.1 — Convert 1C XDTO package to XML Schema (XSD) (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -11,6 +11,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8", newline="") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + XDTO_NS = "http://v8.1c.ru/8.1/xdto" XS_NS = "http://www.w3.org/2001/XMLSchema" XSI_NS = "http://www.w3.org/2001/XMLSchema-instance" @@ -20,7 +42,7 @@ V8_NS = "http://v8.1c.ru/8.1/data/core" parser = argparse.ArgumentParser(allow_abbrev=False) parser.add_argument("-PackagePath", "-Path", required=True) parser.add_argument("-OutFile", default="") -args = parser.parse_args() +args = ci_parse_args(parser) def _parse_xml(source, from_string=False): diff --git a/.claude/skills/xdto-edit/scripts/xdto-edit.ps1 b/.claude/skills/xdto-edit/scripts/xdto-edit.ps1 index 048dbd1d..938d989a 100644 --- a/.claude/skills/xdto-edit/scripts/xdto-edit.ps1 +++ b/.claude/skills/xdto-edit/scripts/xdto-edit.ps1 @@ -1,4 +1,4 @@ -# xdto-edit v1.5 — Point edits of a 1C XDTO package (+support-guard: общая реализация вместо урезанной) +# xdto-edit v1.6 — Point edits of a 1C XDTO package (+support-guard: общая реализация вместо урезанной) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] diff --git a/.claude/skills/xdto-edit/scripts/xdto-edit.py b/.claude/skills/xdto-edit/scripts/xdto-edit.py index 4e0da549..00fbcf98 100644 --- a/.claude/skills/xdto-edit/scripts/xdto-edit.py +++ b/.claude/skills/xdto-edit/scripts/xdto-edit.py @@ -1,4 +1,4 @@ -# xdto-edit v1.5 — Point edits of a 1C XDTO package (Python port) (+support-guard: общая реализация вместо урезанной) +# xdto-edit v1.6 — Point edits of a 1C XDTO package (Python port) (+support-guard: общая реализация вместо урезанной) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -15,6 +15,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + XDTO_NS = "http://v8.1c.ru/8.1/xdto" XS_NS = "http://www.w3.org/2001/XMLSchema" MD_NS = "http://v8.1c.ru/8.3/MDClasses" @@ -29,7 +51,7 @@ parser.add_argument("-Operation", required=True, choices=OPS) parser.add_argument("-Target", default="") parser.add_argument("-Value", default="") parser.add_argument("-NoValidate", action="store_true") -args = parser.parse_args() +args = ci_parse_args(parser) def die(msg): diff --git a/.claude/skills/xdto-info/scripts/xdto-info.ps1 b/.claude/skills/xdto-info/scripts/xdto-info.ps1 index ff281af8..d8ef403d 100644 --- a/.claude/skills/xdto-info/scripts/xdto-info.ps1 +++ b/.claude/skills/xdto-info/scripts/xdto-info.ps1 @@ -1,4 +1,4 @@ -# xdto-info v1.0 — Analyze 1C XDTO package structure +# xdto-info v1.1 — Analyze 1C XDTO package structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] diff --git a/.claude/skills/xdto-info/scripts/xdto-info.py b/.claude/skills/xdto-info/scripts/xdto-info.py index c660b69b..1d6d254c 100644 --- a/.claude/skills/xdto-info/scripts/xdto-info.py +++ b/.claude/skills/xdto-info/scripts/xdto-info.py @@ -1,4 +1,4 @@ -# xdto-info v1.0 — Analyze 1C XDTO package structure (Python port) +# xdto-info v1.1 — Analyze 1C XDTO package structure (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -10,6 +10,28 @@ from lxml import etree sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + XS_NS = "http://www.w3.org/2001/XMLSchema" XSI_NS = "http://www.w3.org/2001/XMLSchema-instance" @@ -24,7 +46,7 @@ parser.add_argument("-RequiredOnly", action="store_true") parser.add_argument("-Limit", type=int, default=150) parser.add_argument("-Offset", type=int, default=0) parser.add_argument("-OutFile", default="") -args = parser.parse_args() +args = ci_parse_args(parser) LIMIT, OFFSET, DEPTH = args.Limit, args.Offset, args.Depth diff --git a/.claude/skills/xdto-validate/scripts/xdto-validate.ps1 b/.claude/skills/xdto-validate/scripts/xdto-validate.ps1 index 6f589b86..d8fc5d52 100644 --- a/.claude/skills/xdto-validate/scripts/xdto-validate.ps1 +++ b/.claude/skills/xdto-validate/scripts/xdto-validate.ps1 @@ -1,4 +1,4 @@ -# xdto-validate v1.2 — Validate a 1C XDTO package (+Report-*: общий эталон вывода валидаторов) +# xdto-validate v1.3 — Validate a 1C XDTO package (+Report-*: общий эталон вывода валидаторов) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/xdto-validate/scripts/xdto-validate.py b/.claude/skills/xdto-validate/scripts/xdto-validate.py index 9f5654c5..6ef404ef 100644 --- a/.claude/skills/xdto-validate/scripts/xdto-validate.py +++ b/.claude/skills/xdto-validate/scripts/xdto-validate.py @@ -1,4 +1,4 @@ -# xdto-validate v1.2 — Validate a 1C XDTO package (Python port) (+Report-*: общий эталон вывода валидаторов) +# xdto-validate v1.3 — Validate a 1C XDTO package (Python port) (+Report-*: общий эталон вывода валидаторов) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -21,6 +21,28 @@ PLATFORM_NS = { sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") +# Регистронезависимый ввод — паритет с PS1: в PowerShell имена параметров и [ValidateSet] +# регистр не различают, в argparse совпадение точное. +def ci_parse_args(parser, argv=None): + """parse_args по правилам PS: имена параметров и значения choices регистронезависимы.""" + argv = list(sys.argv[1:] if argv is None else argv) + names = {s.lower(): s for a in parser._actions for s in a.option_strings} + for i, tok in enumerate(argv): + if tok.startswith('-') and tok.lower() in names: + argv[i] = names[tok.lower()] + # choices — зеркало [ValidateSet]; канонизируем ДО разбора, иначе argparse отвергнет регистр + choice_map = {} + for a in parser._actions: + if a.choices: + for s in a.option_strings: + choice_map[s] = {str(c).lower(): c for c in a.choices} + for i in range(len(argv) - 1): + m = choice_map.get(argv[i]) + if m and argv[i + 1].lower() in m: + argv[i + 1] = m[argv[i + 1].lower()] + return parser.parse_args(argv) + + XS_NS = "http://www.w3.org/2001/XMLSchema" XSI_NS = "http://www.w3.org/2001/XMLSchema-instance" MD_NS = "http://v8.1c.ru/8.3/MDClasses" @@ -31,7 +53,7 @@ parser.add_argument("-ConfigDir", default="") parser.add_argument("-Detailed", action="store_true") parser.add_argument("-MaxErrors", type=int, default=20) parser.add_argument("-OutFile", default="") -args = parser.parse_args() +args = ci_parse_args(parser) package_path = os.path.abspath(args.PackagePath) detailed = args.Detailed diff --git a/tests/skills/check-inline-drift.mjs b/tests/skills/check-inline-drift.mjs index 27d6d5da..60e3ed31 100644 --- a/tests/skills/check-inline-drift.mjs +++ b/tests/skills/check-inline-drift.mjs @@ -283,8 +283,24 @@ const FAMILIES = [ variants: [{ id: 'base', authority: 'meta-compile', consumers: [] }], }, { + // Единственная из трёх, которая нужна КАЖДОМУ порту: DSL читают не все навыки, а параметры — все. name: 'case-insensitive input: ci_parse_args', py: 'ci_parse_args', ps1: null, - variants: [{ id: 'base', authority: 'meta-compile', consumers: [] }], + variants: [ + { id: 'base', authority: 'meta-compile', + consumers: [ + 'cf-edit', 'cf-info', 'cf-init', 'cf-validate', 'cfe-borrow', 'cfe-diff', 'cfe-init', + 'cfe-patch-method', 'cfe-validate', 'db-create', 'db-dump-cf', 'db-dump-dt', 'db-dump-xml', + 'db-load-cf', 'db-load-dt', 'db-load-git', 'db-load-xml', 'db-run', 'db-update', 'epf-build', + 'epf-dump', 'epf-init', 'epf-validate', 'erf-init', 'form-add', 'form-compile', + 'form-decompile', 'form-edit', 'form-info', 'form-remove', 'form-validate', 'help-add', + 'img-grid', 'interface-edit', 'interface-validate', 'meta-decompile', 'meta-edit', 'meta-info', + 'meta-remove', 'meta-validate', 'mxl-compile', 'mxl-decompile', 'mxl-info', 'mxl-validate', + 'role-compile', 'role-info', 'role-validate', 'skd-compile', 'skd-decompile', 'skd-edit', + 'skd-info', 'skd-validate', 'subsystem-compile', 'subsystem-edit', 'subsystem-info', + 'subsystem-validate', 'support-edit', 'template-add', 'template-remove', 'web-info', + 'web-publish', 'web-stop', 'web-unpublish', 'xdto-compile', 'xdto-decompile', 'xdto-edit', + 'xdto-info', 'xdto-validate'] }, + ], }, ];