diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1
index cd99b51b..fa508288 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.6 — Validate 1C metadata object structure
+# meta-validate v1.7 — Validate 1C metadata object structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -240,6 +240,11 @@ $childObjectRules = @{
"EventSubscription" = @()
}
+# Группы командного интерфейса (зеркало meta-compile): раздела — без commandParameterType; формы — с параметром.
+$sectionCommandGroups = @("NavigationPanelImportant","NavigationPanelOrdinary","NavigationPanelSeeAlso","ActionsPanelCreate","ActionsPanelReports","ActionsPanelTools")
+$formCommandGroups = @("FormCommandBarImportant","FormCommandBarCreateBasedOn","FormNavigationPanelImportant","FormNavigationPanelGoTo","FormNavigationPanelSeeAlso")
+$validCommandGroups = $sectionCommandGroups + $formCommandGroups
+
# Valid enum property values
$validPropertyValues = @{
"CodeType" = @("String","Number")
@@ -1346,6 +1351,46 @@ if ($mdType -eq "DocumentJournal" -and $childObjNode) {
}
}
+if ($script:stopped) { & $finalize; exit 1 }
+
+# --- Check 15: Commands — Group обязателен/валиден; секц.группа несовместима с CommandParameterType ---
+
+if ($childObjNode) {
+ $commands = $childObjNode.SelectNodes("md:Command", $ns)
+ $check15Ok = $true
+ $cmdCount = 0
+ foreach ($cmd in $commands) {
+ if ($script:stopped) { break }
+ $cmdCount++
+ $cuuid = $cmd.GetAttribute("uuid")
+ $cmdProps = $cmd.SelectSingleNode("md:Properties", $ns)
+ $cmdNameNode = if ($cmdProps) { $cmdProps.SelectSingleNode("md:Name", $ns) } else { $null }
+ $cmdName = if ($cmdNameNode -and $cmdNameNode.InnerText) { $cmdNameNode.InnerText } else { "(unnamed)" }
+ if (-not $cuuid -or $cuuid -notmatch $guidPattern) {
+ Report-Error "15. Command '$cmdName': missing or invalid uuid"; $check15Ok = $false
+ }
+ if ($cmdName -eq "(unnamed)") {
+ Report-Error "15. Command (uuid=$cuuid): missing or empty Name"; $check15Ok = $false
+ }
+ $groupNode = if ($cmdProps) { $cmdProps.SelectSingleNode("md:Group", $ns) } else { $null }
+ $groupVal = if ($groupNode) { $groupNode.InnerText.Trim() } else { "" }
+ if (-not $groupVal) {
+ Report-Error "15. Command '$cmdName': не задана группа (Group) — 1С отвергает при загрузке"; $check15Ok = $false
+ } elseif (($validCommandGroups -notcontains $groupVal) -and ($groupVal -notmatch '^CommandGroup\.')) {
+ Report-Error "15. Command '$cmdName': неизвестная группа '$groupVal'. Валидные: $($validCommandGroups -join ', '); либо CommandGroup.<Имя>"; $check15Ok = $false
+ } elseif ($sectionCommandGroups -contains $groupVal) {
+ $cptNode = if ($cmdProps) { $cmdProps.SelectSingleNode("md:CommandParameterType", $ns) } else { $null }
+ $hasCpt = $cptNode -and (($cptNode.SelectNodes("v8:Type", $ns).Count -gt 0) -or ($cptNode.SelectNodes("v8:TypeSet", $ns).Count -gt 0))
+ if ($hasCpt) {
+ Report-Error "15. Command '$cmdName': тип параметра (CommandParameterType) недоступен для команд командного интерфейса раздела ('$groupVal')"; $check15Ok = $false
+ }
+ }
+ }
+ if ($check15Ok -and $cmdCount -gt 0) {
+ Report-OK "15. Commands: $cmdCount command(s), groups valid"
+ }
+}
+
# --- Final output ---
& $finalize
diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py
index 87f7c8cb..ac0eaa04 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.6 — Validate 1C metadata object structure (Python port)
+# meta-validate v1.7 — Validate 1C metadata object structure (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import os
@@ -240,6 +240,13 @@ child_object_rules = {
"EventSubscription": [],
}
+# Группы командного интерфейса (зеркало meta-compile): раздела — без commandParameterType; формы — с параметром.
+SECTION_COMMAND_GROUPS = ["NavigationPanelImportant", "NavigationPanelOrdinary", "NavigationPanelSeeAlso",
+ "ActionsPanelCreate", "ActionsPanelReports", "ActionsPanelTools"]
+FORM_COMMAND_GROUPS = ["FormCommandBarImportant", "FormCommandBarCreateBasedOn",
+ "FormNavigationPanelImportant", "FormNavigationPanelGoTo", "FormNavigationPanelSeeAlso"]
+VALID_COMMAND_GROUPS = SECTION_COMMAND_GROUPS + FORM_COMMAND_GROUPS
+
# Valid enum property values
valid_property_values = {
"CodeType": ["String", "Number"],
@@ -1252,6 +1259,49 @@ if md_type == "DocumentJournal" and child_obj_node is not None:
elif col_count == 0:
report_ok("14. DocumentJournal Columns: none")
+if stopped:
+ finalize()
+ sys.exit(1)
+
+# ── Check 15: Commands — Group обязателен/валиден; секц.группа несовместима с CommandParameterType ──
+
+if child_obj_node is not None:
+ commands = find_all(child_obj_node, "md:Command")
+ check15_ok = True
+ cmd_count = 0
+ for cmd in commands:
+ if stopped:
+ break
+ cmd_count += 1
+ cuuid = cmd.get("uuid", "")
+ cmd_props = find(cmd, "md:Properties")
+ cmd_name_node = find(cmd_props, "md:Name") if cmd_props is not None else None
+ cmd_name = inner_text(cmd_name_node) if (cmd_name_node is not None and inner_text(cmd_name_node)) else "(unnamed)"
+ if not cuuid or not guid_pattern.match(cuuid):
+ report_error(f"15. Command '{cmd_name}': missing or invalid uuid")
+ check15_ok = False
+ if cmd_name == "(unnamed)":
+ report_error(f"15. Command (uuid={cuuid}): missing or empty Name")
+ check15_ok = False
+ group_node = find(cmd_props, "md:Group") if cmd_props is not None else None
+ group_val = inner_text(group_node).strip() if group_node is not None else ""
+ if not group_val:
+ report_error(f"15. Command '{cmd_name}': не задана группа (Group) — 1С отвергает при загрузке")
+ check15_ok = False
+ elif group_val not in VALID_COMMAND_GROUPS and not group_val.startswith("CommandGroup."):
+ report_error(f"15. Command '{cmd_name}': неизвестная группа '{group_val}'. "
+ f"Валидные: {', '.join(VALID_COMMAND_GROUPS)}; либо CommandGroup.<Имя>")
+ check15_ok = False
+ elif group_val in SECTION_COMMAND_GROUPS:
+ cpt_node = find(cmd_props, "md:CommandParameterType") if cmd_props is not None else None
+ has_cpt = cpt_node is not None and (len(find_all(cpt_node, "v8:Type")) > 0 or len(find_all(cpt_node, "v8:TypeSet")) > 0)
+ if has_cpt:
+ report_error(f"15. Command '{cmd_name}': тип параметра (CommandParameterType) недоступен "
+ f"для команд командного интерфейса раздела ('{group_val}')")
+ check15_ok = False
+ if check15_ok and cmd_count > 0:
+ report_ok(f"15. Commands: {cmd_count} command(s), groups valid")
+
# ── Final output ──────────────────────────────────────────────
finalize()
diff --git a/tests/skills/cases/meta-validate/error-command-no-group.json b/tests/skills/cases/meta-validate/error-command-no-group.json
new file mode 100644
index 00000000..a9a7b9dd
--- /dev/null
+++ b/tests/skills/cases/meta-validate/error-command-no-group.json
@@ -0,0 +1,6 @@
+{
+ "name": "Валидатор ловит команду без группы (пустой Group)",
+ "setup": "fixture:catalog-command-no-group",
+ "params": { "objectPath": "Catalogs/ТестКоманд.xml" },
+ "expectError": true
+}
diff --git a/tests/skills/cases/meta-validate/error-command-section-param.json b/tests/skills/cases/meta-validate/error-command-section-param.json
new file mode 100644
index 00000000..0228c8a9
--- /dev/null
+++ b/tests/skills/cases/meta-validate/error-command-section-param.json
@@ -0,0 +1,6 @@
+{
+ "name": "Валидатор ловит секционную группу команды + commandParameterType",
+ "setup": "fixture:catalog-command-section-param",
+ "params": { "objectPath": "Catalogs/ТестКоманд.xml" },
+ "expectError": true
+}
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-command-no-group/Catalogs/ТестКоманд.xml b/tests/skills/cases/meta-validate/fixtures/catalog-command-no-group/Catalogs/ТестКоманд.xml
new file mode 100644
index 00000000..6837f4dc
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-command-no-group/Catalogs/ТестКоманд.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+ 3cdf7826-a007-4b57-b642-76a5580e5817
+ 05277e8d-89bb-480b-8553-11dae4c0f7a3
+
+
+ 4fb61896-02c8-4858-9f8d-e55395c779f0
+ 1b5f89ca-683c-493a-adb0-2f46daaaa20d
+
+
+ 3e13d099-e6f5-4d85-b111-82981622fd0a
+ 3d90f58f-18d0-4dcd-818f-b578c54dd55c
+
+
+ 33cc0cf3-2241-41cf-8979-da215ab282e6
+ 6d5a7d96-6ad7-461d-af62-bb63b57a06a1
+
+
+ f65a6d7a-57df-4e94-aece-d9c31ccaa832
+ a71dd300-6b90-4c3a-8cb9-bc984baa3b5e
+
+
+
+ ТестКоманд
+
+
+ ru
+ Тест команд
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.ТестКоманд.StandardAttribute.Description
+ Catalog.ТестКоманд.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+ Печать
+
+
+ ru
+ Печать
+
+
+
+
+
+ d5p1:CatalogRef.ТестКоманд
+
+ Single
+ false
+ Auto
+
+
+
+ Auto
+
+
+
+
+
diff --git a/tests/skills/cases/meta-validate/fixtures/catalog-command-section-param/Catalogs/ТестКоманд.xml b/tests/skills/cases/meta-validate/fixtures/catalog-command-section-param/Catalogs/ТестКоманд.xml
new file mode 100644
index 00000000..33dc5ee8
--- /dev/null
+++ b/tests/skills/cases/meta-validate/fixtures/catalog-command-section-param/Catalogs/ТестКоманд.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+ 3cdf7826-a007-4b57-b642-76a5580e5817
+ 05277e8d-89bb-480b-8553-11dae4c0f7a3
+
+
+ 4fb61896-02c8-4858-9f8d-e55395c779f0
+ 1b5f89ca-683c-493a-adb0-2f46daaaa20d
+
+
+ 3e13d099-e6f5-4d85-b111-82981622fd0a
+ 3d90f58f-18d0-4dcd-818f-b578c54dd55c
+
+
+ 33cc0cf3-2241-41cf-8979-da215ab282e6
+ 6d5a7d96-6ad7-461d-af62-bb63b57a06a1
+
+
+ f65a6d7a-57df-4e94-aece-d9c31ccaa832
+ a71dd300-6b90-4c3a-8cb9-bc984baa3b5e
+
+
+
+ ТестКоманд
+
+
+ ru
+ Тест команд
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.ТестКоманд.StandardAttribute.Description
+ Catalog.ТестКоманд.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+ Печать
+
+
+ ru
+ Печать
+
+
+
+ NavigationPanelOrdinary
+
+ d5p1:CatalogRef.ТестКоманд
+
+ Single
+ false
+ Auto
+
+
+
+ Auto
+
+
+
+
+
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд.xml b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд.xml
new file mode 100644
index 00000000..58e825af
--- /dev/null
+++ b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд.xml
@@ -0,0 +1,136 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+
+ ТестКоманд
+
+
+ ru
+ Тест команд
+
+
+
+ false
+ HierarchyFoldersAndItems
+ false
+ 2
+ true
+ true
+
+ ToItems
+ 9
+ 25
+ String
+ Variable
+ WholeCatalog
+ false
+ true
+ AsDescription
+
+ Auto
+ InDialog
+ false
+ BothWays
+
+ Catalog.ТестКоманд.StandardAttribute.Description
+ Catalog.ТестКоманд.StandardAttribute.Code
+
+ Begin
+ DontUse
+ Directly
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ Managed
+ Use
+
+
+
+
+
+ Use
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
+ Печать
+
+
+ ru
+ Печать
+
+
+
+ FormCommandBarImportant
+
+ d5p1:CatalogRef.ТестКоманд
+
+ Single
+ false
+ Auto
+
+
+
+ Auto
+
+
+
+
+ Обновить
+
+
+ ru
+ Обновить
+
+
+
+ NavigationPanelOrdinary
+
+ Single
+ false
+ Auto
+
+
+
+ Auto
+
+
+
+
+
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Commands/Обновить/Ext/CommandModule.bsl b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Commands/Обновить/Ext/CommandModule.bsl
new file mode 100644
index 00000000..d7ec0aeb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Commands/Обновить/Ext/CommandModule.bsl
@@ -0,0 +1,6 @@
+&НаКлиенте
+Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
+
+ // Вставьте обработчик команды.
+
+КонецПроцедуры
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Commands/Печать/Ext/CommandModule.bsl b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Commands/Печать/Ext/CommandModule.bsl
new file mode 100644
index 00000000..d7ec0aeb
--- /dev/null
+++ b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Commands/Печать/Ext/CommandModule.bsl
@@ -0,0 +1,6 @@
+&НаКлиенте
+Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
+
+ // Вставьте обработчик команды.
+
+КонецПроцедуры
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Ext/ObjectModule.bsl b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Catalogs/ТестКоманд/Ext/ObjectModule.bsl
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Configuration.xml b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Configuration.xml
new file mode 100644
index 00000000..7baaca3b
--- /dev/null
+++ b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Configuration.xml
@@ -0,0 +1,252 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+
+ TestConfig
+
+
+ ru
+ TestConfig
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ ТестКоманд
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Ext/ClientApplicationInterface.xml
new file mode 100644
index 00000000..3c1161b2
--- /dev/null
+++ b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ UUID-002
+
+
+
+
+ UUID-004
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Languages/Русский.xml b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Languages/Русский.xml
new file mode 100644
index 00000000..37c60d78
--- /dev/null
+++ b/tests/skills/cases/meta-validate/snapshots/valid-catalog-commands/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-validate/valid-catalog-commands.json b/tests/skills/cases/meta-validate/valid-catalog-commands.json
new file mode 100644
index 00000000..3280a144
--- /dev/null
+++ b/tests/skills/cases/meta-validate/valid-catalog-commands.json
@@ -0,0 +1,18 @@
+{
+ "name": "Каталог с валидными командами (группы раздела/формы) проходит валидацию",
+ "setup": "empty-config",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "Catalog", "name": "ТестКоманд", "useStandardCommands": true,
+ "commands": {
+ "Печать": { "group": "FormCommandBarImportant", "commandParameterType": "CatalogRef.ТестКоманд" },
+ "Обновить": { "group": "NavigationPanelOrdinary" }
+ }
+ },
+ "args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
+ }
+ ],
+ "params": { "objectPath": "Catalogs/ТестКоманд" }
+}