feat(validate): auto-resolve directory paths, fix SKILL.md placeholders

Scripts now accept directory paths (e.g. Forms/ИмяФормы) and auto-resolve
to the target XML file. Silent fallbacks handle missing Ext/ level and
descriptor-to-file resolution. SKILL.md: concrete placeholders, unified
quotes, auto-resolve notes, role-validate MaxErrors in params.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-03-09 18:41:38 +03:00
co-authored by Claude Opus 4.6
parent 422e397381
commit b2a2534b5a
19 changed files with 191 additions and 18 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/cfe-validate/scripts/cfe-validate.ps1 -ExtensionPath src
powershell.exe -NoProfile -File .claude/skills/cfe-validate/scripts/cfe-validate.ps1 -ExtensionPath "<путь>"
```
## Проверки (9 шагов)
+1 -1
View File
@@ -33,7 +33,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/epf-validate/scripts/epf-validate.ps1 -ObjectPath "<путь>"
powershell.exe -NoProfile -File .claude/skills/epf-validate/scripts/epf-validate.ps1 -ObjectPath "<путь_к_обработке>"
```
## Проверки
+3 -1
View File
@@ -30,9 +30,11 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/form-validate/scripts/form-validate.ps1 -FormPath "<путь>"
powershell.exe -NoProfile -File .claude/skills/form-validate/scripts/form-validate.ps1 -FormPath "<.../Forms/ИмяФормы>"
```
Можно указать директорию формы — скрипт найдёт Ext/Form.xml автоматически.
## Проверки
| # | Проверка | Серьёзность |
@@ -12,6 +12,27 @@ param(
$ErrorActionPreference = "Stop"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- Resolve path ---
# A: Directory → Ext/Form.xml
if (Test-Path $FormPath -PathType Container) {
$FormPath = Join-Path (Join-Path $FormPath "Ext") "Form.xml"
}
# B1: Missing Ext/ (e.g. Forms/Форма/Form.xml → Forms/Форма/Ext/Form.xml)
if (-not (Test-Path $FormPath)) {
$fn = [System.IO.Path]::GetFileName($FormPath)
if ($fn -eq "Form.xml") {
$c = Join-Path (Join-Path (Split-Path $FormPath) "Ext") $fn
if (Test-Path $c) { $FormPath = $c }
}
}
# B2: Descriptor (Forms/Форма.xml → Forms/Форма/Ext/Form.xml)
if (-not (Test-Path $FormPath) -and $FormPath.EndsWith(".xml")) {
$stem = [System.IO.Path]::GetFileNameWithoutExtension($FormPath)
$dir = Split-Path $FormPath
$c = Join-Path (Join-Path (Join-Path $dir $stem) "Ext") "Form.xml"
if (Test-Path $c) { $FormPath = $c }
}
# --- Load XML ---
if (-not (Test-Path $FormPath)) {
@@ -31,6 +31,27 @@ def main():
detailed = args.Detailed
max_errors = args.MaxErrors
if not os.path.isabs(form_path):
form_path = os.path.join(os.getcwd(), form_path)
# A: Directory → Ext/Form.xml
if os.path.isdir(form_path):
form_path = os.path.join(form_path, 'Ext', 'Form.xml')
# B1: Missing Ext/ (e.g. Forms/Форма/Form.xml → Forms/Форма/Ext/Form.xml)
if not os.path.exists(form_path):
fn = os.path.basename(form_path)
if fn == 'Form.xml':
c = os.path.join(os.path.dirname(form_path), 'Ext', fn)
if os.path.exists(c):
form_path = c
# B2: Descriptor (Forms/Форма.xml → Forms/Форма/Ext/Form.xml)
if not os.path.exists(form_path) and form_path.endswith('.xml'):
stem = os.path.splitext(os.path.basename(form_path))[0]
parent = os.path.dirname(form_path)
c = os.path.join(parent, stem, 'Ext', 'Form.xml')
if os.path.exists(c):
form_path = c
if not os.path.isfile(form_path):
print(f"File not found: {form_path}", file=sys.stderr)
sys.exit(1)
+3 -1
View File
@@ -31,9 +31,11 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File '.claude/skills/interface-validate/scripts/interface-validate.ps1' -CIPath '<path>'
powershell.exe -NoProfile -File ".claude/skills/interface-validate/scripts/interface-validate.ps1" -CIPath "<Subsystems/ИмяПодсистемы>"
```
Можно указать директорию подсистемы — скрипт найдёт Ext/CommandInterface.xml автоматически.
## Проверки (13)
| # | Проверка | Серьёзность |
@@ -14,6 +14,18 @@ $ErrorActionPreference = "Stop"
if (-not [System.IO.Path]::IsPathRooted($CIPath)) {
$CIPath = Join-Path (Get-Location).Path $CIPath
}
# A: Directory → Ext/CommandInterface.xml
if (Test-Path $CIPath -PathType Container) {
$CIPath = Join-Path (Join-Path $CIPath "Ext") "CommandInterface.xml"
}
# B1: Missing Ext/ (e.g. Subsystems/X/CommandInterface.xml → Subsystems/X/Ext/CommandInterface.xml)
if (-not (Test-Path $CIPath)) {
$fn = [System.IO.Path]::GetFileName($CIPath)
if ($fn -eq "CommandInterface.xml") {
$c = Join-Path (Join-Path (Split-Path $CIPath) "Ext") $fn
if (Test-Path $c) { $CIPath = $c }
}
}
if (-not (Test-Path $CIPath)) {
Write-Host "[ERROR] File not found: $CIPath"
exit 1
@@ -94,6 +94,17 @@ def main():
if not os.path.isabs(ci_path):
ci_path = os.path.join(os.getcwd(), ci_path)
# A: Directory → Ext/CommandInterface.xml
if os.path.isdir(ci_path):
ci_path = os.path.join(ci_path, 'Ext', 'CommandInterface.xml')
# B1: Missing Ext/
if not os.path.exists(ci_path):
fn = os.path.basename(ci_path)
if fn == 'CommandInterface.xml':
c = os.path.join(os.path.dirname(ci_path), 'Ext', fn)
if os.path.exists(c):
ci_path = c
if not os.path.exists(ci_path):
print(f'[ERROR] File not found: {ci_path}')
sys.exit(1)
+1 -1
View File
@@ -33,7 +33,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/meta-validate/scripts/meta-validate.ps1 -ObjectPath "<путь>"
powershell.exe -NoProfile -File .claude/skills/meta-validate/scripts/meta-validate.ps1 -ObjectPath "<Catalogs/ИмяСправочника/ИмяСправочника.xml>"
```
## Поддерживаемые типы (23)
+3 -1
View File
@@ -35,9 +35,11 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/mxl-validate/scripts/mxl-validate.ps1 -TemplatePath "<путь>"
powershell.exe -NoProfile -File .claude/skills/mxl-validate/scripts/mxl-validate.ps1 -TemplatePath "<.../Templates/ИмяМакета>"
```
Можно указать директорию макета — скрипт найдёт Ext/Template.xml автоматически.
## Проверки
| # | Проверка | Серьёзность |
@@ -22,6 +22,26 @@ if (-not $TemplatePath) {
$TemplatePath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $SrcDir $ProcessorName) "Templates") $TemplateName) "Ext") "Template.xml"
}
# A: Directory → Ext/Template.xml
if (Test-Path $TemplatePath -PathType Container) {
$TemplatePath = Join-Path (Join-Path $TemplatePath "Ext") "Template.xml"
}
# B1: Missing Ext/ (e.g. Templates/Макет/Template.xml → Templates/Макет/Ext/Template.xml)
if (-not (Test-Path $TemplatePath)) {
$fn = [System.IO.Path]::GetFileName($TemplatePath)
if ($fn -eq "Template.xml") {
$c = Join-Path (Join-Path (Split-Path $TemplatePath) "Ext") $fn
if (Test-Path $c) { $TemplatePath = $c }
}
}
# B2: Descriptor (Templates/Макет.xml → Templates/Макет/Ext/Template.xml)
if (-not (Test-Path $TemplatePath) -and $TemplatePath.EndsWith(".xml")) {
$stem = [System.IO.Path]::GetFileNameWithoutExtension($TemplatePath)
$dir = Split-Path $TemplatePath
$c = Join-Path (Join-Path (Join-Path $dir $stem) "Ext") "Template.xml"
if (Test-Path $c) { $TemplatePath = $c }
}
if (-not (Test-Path $TemplatePath)) {
Write-Error "File not found: $TemplatePath"
exit 1
@@ -81,6 +81,24 @@ def main():
if not os.path.isabs(template_path):
template_path = os.path.join(os.getcwd(), template_path)
# A: Directory → Ext/Template.xml
if os.path.isdir(template_path):
template_path = os.path.join(template_path, 'Ext', 'Template.xml')
# B1: Missing Ext/ (e.g. Templates/Макет/Template.xml → Templates/Макет/Ext/Template.xml)
if not os.path.exists(template_path):
fn = os.path.basename(template_path)
if fn == 'Template.xml':
c = os.path.join(os.path.dirname(template_path), 'Ext', fn)
if os.path.exists(c):
template_path = c
# B2: Descriptor (Templates/Макет.xml → Templates/Макет/Ext/Template.xml)
if not os.path.exists(template_path) and template_path.endswith('.xml'):
stem = os.path.splitext(os.path.basename(template_path))[0]
parent = os.path.dirname(template_path)
c = os.path.join(parent, stem, 'Ext', 'Template.xml')
if os.path.exists(c):
template_path = c
if not os.path.exists(template_path):
print(f'File not found: {template_path}', file=sys.stderr)
sys.exit(1)
+5 -2
View File
@@ -1,7 +1,7 @@
---
name: role-validate
description: Валидация роли 1С. Используй после создания или модификации роли для проверки корректности
argument-hint: <RightsPath> [-Detailed] [-MetadataPath <path>]
argument-hint: <RightsPath> [-Detailed] [-MaxErrors 30] [-MetadataPath <path>]
allowed-tools:
- Bash
- Read
@@ -25,6 +25,7 @@ allowed-tools:
| RightsPath | да | — | Путь к `Rights.xml` роли |
| MetadataPath | нет | — | Путь к метаданным роли (`Roles/ИмяРоли.xml`) |
| Detailed | нет | — | Показывать [OK] для каждой проверки |
| MaxErrors | нет | 30 | Макс. ошибок до остановки (по умолчанию 30) |
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
**Важно:** Для кириллических путей используй `-OutFile` и читай результат через Read tool.
@@ -32,9 +33,11 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/role-validate/scripts/role-validate.ps1 -RightsPath <path> [-MetadataPath <path>]
powershell.exe -NoProfile -File .claude/skills/role-validate/scripts/role-validate.ps1 -RightsPath "<Roles/ИмяРоли>" [-MetadataPath "<path>"]
```
Можно указать директорию роли — скрипт найдёт Ext/Rights.xml автоматически.
## Проверки
| # | Проверка | Серьёзность |
@@ -189,6 +189,23 @@ function Find-Similar {
return $result
}
# --- Resolve path ---
if (-not [System.IO.Path]::IsPathRooted($RightsPath)) {
$RightsPath = Join-Path (Get-Location).Path $RightsPath
}
# A: Directory → Ext/Rights.xml
if (Test-Path $RightsPath -PathType Container) {
$RightsPath = Join-Path (Join-Path $RightsPath "Ext") "Rights.xml"
}
# B1: Missing Ext/ (e.g. Roles/МояРоль/Rights.xml → Roles/МояРоль/Ext/Rights.xml)
if (-not (Test-Path $RightsPath)) {
$fn = [System.IO.Path]::GetFileName($RightsPath)
if ($fn -eq "Rights.xml") {
$c = Join-Path (Join-Path (Split-Path $RightsPath) "Ext") $fn
if (Test-Path $c) { $RightsPath = $c }
}
}
# --- 3. Validate Rights.xml ---
if (-not (Test-Path $RightsPath)) {
@@ -193,6 +193,17 @@ def main():
if not os.path.isabs(rights_path):
rights_path = os.path.join(os.getcwd(), rights_path)
# A: Directory → Ext/Rights.xml
if os.path.isdir(rights_path):
rights_path = os.path.join(rights_path, 'Ext', 'Rights.xml')
# B1: Missing Ext/
if not os.path.exists(rights_path):
fn = os.path.basename(rights_path)
if fn == 'Rights.xml':
c = os.path.join(os.path.dirname(rights_path), 'Ext', fn)
if os.path.exists(c):
rights_path = c
# --- Output helpers ---
lines = []
errors = 0
+3 -1
View File
@@ -33,9 +33,11 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File .claude/skills/skd-validate/scripts/skd-validate.ps1 -TemplatePath "<путь>"
powershell.exe -NoProfile -File .claude/skills/skd-validate/scripts/skd-validate.ps1 -TemplatePath "<.../Templates/ИмяМакета>"
```
Можно указать директорию макета — скрипт найдёт Ext/Template.xml автоматически.
## Проверки (~30)
| Группа | Что проверяется |
@@ -16,12 +16,28 @@ $ErrorActionPreference = "Stop"
# --- Resolve path ---
if (-not $TemplatePath.EndsWith(".xml")) {
$candidate = Join-Path (Join-Path $TemplatePath "Ext") "Template.xml"
if (Test-Path $candidate) {
$TemplatePath = $candidate
if (-not [System.IO.Path]::IsPathRooted($TemplatePath)) {
$TemplatePath = Join-Path (Get-Location).Path $TemplatePath
}
# A: Directory → Ext/Template.xml
if (Test-Path $TemplatePath -PathType Container) {
$TemplatePath = Join-Path (Join-Path $TemplatePath "Ext") "Template.xml"
}
# B1: Missing Ext/ (e.g. Templates/СКД/Template.xml → Templates/СКД/Ext/Template.xml)
if (-not (Test-Path $TemplatePath)) {
$fn = [System.IO.Path]::GetFileName($TemplatePath)
if ($fn -eq "Template.xml") {
$c = Join-Path (Join-Path (Split-Path $TemplatePath) "Ext") $fn
if (Test-Path $c) { $TemplatePath = $c }
}
}
# B2: Descriptor (Templates/СКД.xml → Templates/СКД/Ext/Template.xml)
if (-not (Test-Path $TemplatePath) -and $TemplatePath.EndsWith(".xml")) {
$stem = [System.IO.Path]::GetFileNameWithoutExtension($TemplatePath)
$dir = Split-Path $TemplatePath
$c = Join-Path (Join-Path (Join-Path $dir $stem) "Ext") "Template.xml"
if (Test-Path $c) { $TemplatePath = $c }
}
if (-not (Test-Path $TemplatePath)) {
Write-Error "File not found: $TemplatePath"
@@ -25,10 +25,23 @@ out_file = args.OutFile
# ── resolve path ─────────────────────────────────────────────
if not template_path.endswith(".xml"):
candidate = os.path.join(template_path, "Ext", "Template.xml")
if os.path.exists(candidate):
template_path = candidate
# A: Directory → Ext/Template.xml
if os.path.isdir(template_path):
template_path = os.path.join(template_path, 'Ext', 'Template.xml')
# B1: Missing Ext/ (e.g. Templates/СКД/Template.xml → Templates/СКД/Ext/Template.xml)
if not os.path.exists(template_path):
fn = os.path.basename(template_path)
if fn == 'Template.xml':
c = os.path.join(os.path.dirname(template_path), 'Ext', fn)
if os.path.exists(c):
template_path = c
# B2: Descriptor (.xml → dir/Ext/Template.xml)
if not os.path.exists(template_path) and template_path.endswith('.xml'):
stem = os.path.splitext(os.path.basename(template_path))[0]
parent = os.path.dirname(template_path)
c = os.path.join(parent, stem, 'Ext', 'Template.xml')
if os.path.exists(c):
template_path = c
if not os.path.exists(template_path):
print(f"File not found: {template_path}", file=sys.stderr)
+3 -1
View File
@@ -31,9 +31,11 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File '.claude/skills/subsystem-validate/scripts/subsystem-validate.ps1' -SubsystemPath '<путь>'
powershell.exe -NoProfile -File ".claude/skills/subsystem-validate/scripts/subsystem-validate.ps1" -SubsystemPath "<Subsystems/ИмяПодсистемы>"
```
Можно указать директорию подсистемы — скрипт найдёт XML-файл автоматически.
## Проверки (13)
| # | Проверка | Серьёзность |