diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1
index f2fac8c8..b12fe6e7 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.ps1
+++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1
@@ -1,4 +1,4 @@
-# meta-compile v1.56 — Compile 1C metadata object from JSON
+# meta-compile v1.57 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -468,7 +468,7 @@ $script:typeNamespaceMap = @{
$script:cfgBareTypes = @("ConstantsSet", "ReportBuilder", "FilterCriterion")
$script:cfgObjectKinds = @("Catalog","Document","Enum","ChartOfAccounts","ChartOfCharacteristicTypes",
"ChartOfCalculationTypes","ExchangePlan","BusinessProcess","Task","InformationRegister","AccumulationRegister",
- "AccountingRegister","CalculationRegister","DataProcessor","Report","DocumentJournal","Constant","ConstantValue")
+ "AccountingRegister","CalculationRegister","DataProcessor","Report","DocumentJournal","Constant","ConstantValue","Sequence","Recalculation")
$script:typeSynonyms["таблицазначений"] = "ValueTable"
$script:typeSynonyms["деревозначений"] = "ValueTree"
$script:typeSynonyms["списокзначений"] = "ValueListType"
@@ -631,6 +631,18 @@ function Emit-TypeContent {
X "$indentcfg:$typeStr"
return
}
+ # Голый объектный метатип (без имени) — напр. в Source подписки на событие:
+ # - Object/RecordSet → «любой объект категории» = TypeSet cfg: (множество);
+ # - Manager/List/Selection/RecordKey/RecordManager → сам тип менеджера/списка = Type cfg: (единичный).
+ # ConstantValueManager (голый) — исключение: множество менеджеров значений констант = TypeSet (прочие *Manager → Type).
+ if (($typeStr -match '^(\w+)(Object|RecordSet)$' -and $script:cfgObjectKinds -contains $Matches[1]) -or $typeStr -eq 'ConstantValueManager') {
+ X "$indentcfg:$typeStr"
+ return
+ }
+ if ($typeStr -match '^(\w+)(Manager|List|Selection|RecordKey|RecordManager)$' -and $script:cfgObjectKinds -contains $Matches[1]) {
+ X "$indentcfg:$typeStr"
+ return
+ }
# Reference types — use local xmlns declaration for 1C compatibility
if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef)\.(.+)$') {
@@ -2640,7 +2652,7 @@ function Emit-CommonModuleProperties {
X "$i$(Esc-Xml $objName)"
Emit-MLText $i "Synonym" $synonym
- X "$i"
+ if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" }
# Context shortcuts
$context = if ($def.context) { "$($def.context)" } else { "" }
@@ -2682,7 +2694,7 @@ function Emit-ScheduledJobProperties {
X "$i$(Esc-Xml $objName)"
Emit-MLText $i "Synonym" $synonym
- X "$i"
+ if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" }
$methodName = if ($def.methodName) { "$($def.methodName)" } else { "" }
# Ensure CommonModule. prefix
@@ -2691,9 +2703,9 @@ function Emit-ScheduledJobProperties {
}
X "$i$(Esc-Xml $methodName)"
- # $synonym может быть {ru,en}; здесь Description — плоская строка, берём ru-текст.
- $description = if ($def.description) { "$($def.description)" } elseif ($synonym -is [string]) { $synonym } else { "" }
- X "$i$(Esc-Xml $description)"
+ # Description — плоская строка (дефолт ПУСТО: корпус 662 пустых / 209 заданы; не подставляем синоним — иначе роундтрип рвётся).
+ $description = if ($def.description) { "$($def.description)" } else { "" }
+ if ($description) { X "$i$(Esc-XmlText $description)" } else { X "$i" }
$key = if ($def.key) { "$($def.key)" } else { "" }
X "$i$(Esc-Xml $key)"
@@ -2716,17 +2728,15 @@ function Emit-EventSubscriptionProperties {
X "$i$(Esc-Xml $objName)"
Emit-MLText $i "Synonym" $synonym
- X "$i"
+ if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" }
- # Source — array of v8:Type
+ # Source — набор типов-источников (объектные типы CatalogObject.X/DocumentObject.X/…RecordSet/…Manager →
+ # cfg:; ссылочные → d5p1). Единый эмиттер Emit-TypeContent (см. §cfg-типы). Прощающий ввод русских корней типа.
$sources = @()
if ($def.source) { $sources = @($def.source) }
if ($sources.Count -gt 0) {
X "$i"
- foreach ($src in $sources) {
- $resolved = Resolve-TypeStr "$src"
- X "$i`td5p1:$resolved"
- }
+ foreach ($src in $sources) { Emit-TypeContent "$i`t" (Resolve-TypeStr "$src") }
X "$i"
} else {
X "$i"
diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py
index 4306d9fc..f9163701 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.py
+++ b/.claude/skills/meta-compile/scripts/meta-compile.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# meta-compile v1.56 — Compile 1C metadata object from JSON
+# meta-compile v1.57 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -542,7 +542,7 @@ cfg_bare_types = {"ConstantsSet", "ReportBuilder", "FilterCriterion"}
cfg_object_kinds = {"Catalog", "Document", "Enum", "ChartOfAccounts", "ChartOfCharacteristicTypes",
"ChartOfCalculationTypes", "ExchangePlan", "BusinessProcess", "Task", "InformationRegister",
"AccumulationRegister", "AccountingRegister", "CalculationRegister", "DataProcessor", "Report",
- "DocumentJournal", "Constant", "ConstantValue"}
+ "DocumentJournal", "Constant", "ConstantValue", "Sequence", "Recalculation"}
def resolve_type_str(type_str):
if not type_str:
@@ -660,6 +660,16 @@ def emit_type_content(indent, type_str):
if m3 and m3.group(1) in cfg_object_kinds:
X(f'{indent}cfg:{type_str}')
return
+ # Голый объектный метатип (без имени): Object/RecordSet + ConstantValueManager → «любой объект категории» = TypeSet cfg:;
+ # прочие Manager/List/Selection → сам тип менеджера/списка = Type cfg: (напр. в Source подписки на событие).
+ mbs = re.match(r'^(\w+)(Object|RecordSet)$', type_str)
+ if (mbs and mbs.group(1) in cfg_object_kinds) or type_str == 'ConstantValueManager':
+ X(f'{indent}cfg:{type_str}')
+ return
+ mbt = re.match(r'^(\w+)(Manager|List|Selection|RecordKey|RecordManager)$', type_str)
+ if mbt and mbt.group(1) in cfg_object_kinds:
+ X(f'{indent}cfg:{type_str}')
+ return
# Reference types — use local xmlns declaration for 1C compatibility
m = re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef)\.(.+)$', type_str)
@@ -2648,7 +2658,10 @@ def emit_common_module_properties(indent):
i = indent
X(f'{i}{esc_xml(obj_name)}')
emit_mltext(i, 'Synonym', synonym)
- X(f'{i}')
+ if defn.get('comment'):
+ X(f'{i}{esc_xml_text(str(defn["comment"]))}')
+ else:
+ X(f'{i}')
context = str(defn['context']) if defn.get('context') else ''
global_val = 'true' if defn.get('global') is True else 'false'
server = 'false'
@@ -2692,15 +2705,21 @@ def emit_scheduled_job_properties(indent):
i = indent
X(f'{i}{esc_xml(obj_name)}')
emit_mltext(i, 'Synonym', synonym)
- X(f'{i}')
+ if defn.get('comment'):
+ X(f'{i}{esc_xml_text(str(defn["comment"]))}')
+ else:
+ X(f'{i}')
method_name = str(defn['methodName']) if defn.get('methodName') else ''
# Ensure CommonModule. prefix
if method_name and not method_name.startswith('CommonModule.'):
method_name = f'CommonModule.{method_name}'
X(f'{i}{esc_xml(method_name)}')
- # synonym может быть {ru,en}; Description — плоская строка, берём ru-текст.
- description = str(defn['description']) if defn.get('description') else (synonym if isinstance(synonym, str) else '')
- X(f'{i}{esc_xml(description)}')
+ # Description — плоская строка (дефолт ПУСТО, не синоним — иначе роундтрип рвётся).
+ description = str(defn['description']) if defn.get('description') else ''
+ if description:
+ X(f'{i}{esc_xml_text(description)}')
+ else:
+ X(f'{i}')
key = str(defn['key']) if defn.get('key') else ''
X(f'{i}{esc_xml(key)}')
use = 'true' if defn.get('use') is True else 'false'
@@ -2716,13 +2735,15 @@ def emit_event_subscription_properties(indent):
i = indent
X(f'{i}{esc_xml(obj_name)}')
emit_mltext(i, 'Synonym', synonym)
- X(f'{i}')
+ if defn.get('comment'):
+ X(f'{i}{esc_xml_text(str(defn["comment"]))}')
+ else:
+ X(f'{i}')
sources = list(defn.get('source', []))
if sources:
X(f'{i}')
for src in sources:
- resolved = resolve_type_str(str(src))
- X(f'{i}\td5p1:{resolved}')
+ emit_type_content(f'{i}\t', resolve_type_str(str(src)))
X(f'{i}')
else:
X(f'{i}')
diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
index 1e1e3a63..d6d32140 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.47 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
+# meta-decompile v0.48 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
#
# Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document,
@@ -92,8 +92,8 @@ foreach ($c in $rootEl.ChildNodes) { if ($c.NodeType -eq 'Element') { $objNode =
if (-not $objNode) { [Console]::Error.WriteLine("meta-decompile: пустой MetaDataObject"); exit 3 }
$objType = $objNode.LocalName
-if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage')) {
- [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (…, Sequence, FilterCriterion, DocumentNumerator, SettingsStorage)"); exit 3
+if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage', 'CommonModule', 'EventSubscription', 'ScheduledJob')) {
+ [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (…, CommonModule, EventSubscription, ScheduledJob)"); exit 3
}
$props = $objNode.SelectSingleNode('md:Properties', $nsm)
@@ -656,6 +656,38 @@ if ($objType -eq 'SettingsStorage') {
$fv = P $fp[0]; if ($fv) { $dsl[$fp[1]] = $fv }
}
}
+# CommonModule — общий модуль: флаги контекста компиляции + повторное использование значений (тело .bsl вне скоупа).
+if ($objType -eq 'CommonModule') {
+ Add-BoolProp 'global' 'Global' $false
+ Add-BoolProp 'clientManagedApplication' 'ClientManagedApplication' $false
+ Add-BoolProp 'server' 'Server' $false
+ Add-BoolProp 'externalConnection' 'ExternalConnection' $false
+ Add-BoolProp 'clientOrdinaryApplication' 'ClientOrdinaryApplication' $false
+ Add-BoolProp 'serverCall' 'ServerCall' $false
+ Add-BoolProp 'privileged' 'Privileged' $false
+ Add-EnumProp 'returnValuesReuse' 'ReturnValuesReuse' 'DontUse'
+}
+# EventSubscription — подписка на событие: источники (набор типов), событие, обработчик.
+if ($objType -eq 'EventSubscription') {
+ $srcNode = $props.SelectSingleNode('md:Source', $nsm)
+ if ($srcNode) {
+ # Источник — набор v8:Type (конкретный CatalogObject.X) И/ИЛИ v8:TypeSet (голый метатип ExchangePlanObject).
+ $srcTypes = @($srcNode.SelectNodes('v8:Type|v8:TypeSet', $nsm) | ForEach-Object { Strip-NsPrefix $_.InnerText.Trim() })
+ if ($srcTypes.Count -gt 0) { $dsl['source'] = [System.Collections.ArrayList]@($srcTypes) }
+ }
+ Add-EnumProp 'event' 'Event' 'BeforeWrite'
+ $h = P 'Handler'; if ($h) { $dsl['handler'] = $h }
+}
+# ScheduledJob — регламентное задание: метод, ключ, флаги, рестарт.
+if ($objType -eq 'ScheduledJob') {
+ $mn = P 'MethodName'; if ($mn) { $dsl['methodName'] = $mn }
+ $descr = P 'Description'; if ($descr) { $dsl['description'] = $descr }
+ $k = P 'Key'; if ($k) { $dsl['key'] = $k }
+ Add-BoolProp 'use' 'Use' $false
+ Add-BoolProp 'predefined' 'Predefined' $false
+ Add-IntProp 'restartCountOnFailure' 'RestartCountOnFailure' 3
+ Add-IntProp 'restartIntervalOnFailure' 'RestartIntervalOnFailure' 10
+}
# Constant — богатый одиночный реквизит: Type + свойства значения (как у реквизита) + object-уровень.
if ($objType -eq 'Constant') {
$vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm))
diff --git a/tests/skills/cases/meta-compile/event-subscription-sources.json b/tests/skills/cases/meta-compile/event-subscription-sources.json
new file mode 100644
index 00000000..ee4e4811
--- /dev/null
+++ b/tests/skills/cases/meta-compile/event-subscription-sources.json
@@ -0,0 +1,21 @@
+{
+ "name": "Подписка на событие — смешанные источники (Type/TypeSet)",
+ "input": {
+ "type": "EventSubscription",
+ "name": "МоиОбработчики",
+ "source": [
+ "CatalogObject.Номенклатура",
+ "DocumentObject",
+ "DocumentManager",
+ "ConstantValueManager",
+ "InformationRegisterRecordSet"
+ ],
+ "event": "OnWrite",
+ "handler": "ОбработкаСобытий.Обработать"
+ },
+ "validatePath": "EventSubscriptions/МоиОбработчики",
+ "skipValidation": true,
+ "expect": {
+ "files": ["EventSubscriptions/МоиОбработчики.xml"]
+ }
+}
diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Configuration.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Configuration.xml
new file mode 100644
index 00000000..c66cc840
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/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-compile/snapshots/event-subscription-sources/EventSubscriptions/МоиОбработчики.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/EventSubscriptions/МоиОбработчики.xml
new file mode 100644
index 00000000..211e7f56
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/EventSubscriptions/МоиОбработчики.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ МоиОбработчики
+
+
+ ru
+ Мои обработчики
+
+
+
+
+ cfg:CatalogObject.Номенклатура
+ cfg:DocumentObject
+ cfg:DocumentManager
+ cfg:ConstantValueManager
+ cfg:InformationRegisterRecordSet
+
+ OnWrite
+ CommonModule.ОбработкаСобытий.Обработать
+
+
+
diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Ext/ClientApplicationInterface.xml
new file mode 100644
index 00000000..3c1161b2
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ UUID-002
+
+
+
+
+ UUID-004
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Languages/Русский.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Languages/Русский.xml
new file mode 100644
index 00000000..37c60d78
--- /dev/null
+++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml
index c643a80f..f7f3feb7 100644
--- a/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml
+++ b/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml
@@ -11,7 +11,7 @@
- d5p1:DocumentObject.ПриходнаяНакладная
+ cfg:DocumentObject.ПриходнаяНакладная
BeforeWrite
CommonModule.ОбработкаСобытий.ПриЗаписиДокумента
diff --git a/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml b/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml
index c9714ef4..acc206d9 100644
--- a/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml
+++ b/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml
@@ -11,7 +11,7 @@
CommonModule.ОбменДаннымиСервер.Выполнить
- Обмен данными
+
false