diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1
index 7b1691cb4..4f1813e0e 100644
--- a/.claude/skills/form-compile/scripts/form-compile.ps1
+++ b/.claude/skills/form-compile/scripts/form-compile.ps1
@@ -2503,9 +2503,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py
index 7513379a3..671593ab1 100644
--- a/.claude/skills/form-compile/scripts/form-compile.py
+++ b/.claude/skills/form-compile/scripts/form-compile.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python3
# form-compile v1.199 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -3912,14 +3912,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
diff --git a/.claude/skills/form-edit/scripts/form-edit.ps1 b/.claude/skills/form-edit/scripts/form-edit.ps1
index 9bb9ff78f..afbb6fdfe 100644
--- a/.claude/skills/form-edit/scripts/form-edit.ps1
+++ b/.claude/skills/form-edit/scripts/form-edit.ps1
@@ -410,9 +410,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/form-edit/scripts/form-edit.py b/.claude/skills/form-edit/scripts/form-edit.py
index 7e2539583..1b52d293e 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.19 — Edit 1C managed form elements (Python port)
+# form-edit v1.19 — Edit 1C managed form elements (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -534,14 +534,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
diff --git a/.claude/skills/meta-compile/reference/code.md b/.claude/skills/meta-compile/reference/code.md
index db35ac9b4..a4be927c1 100644
--- a/.claude/skills/meta-compile/reference/code.md
+++ b/.claude/skills/meta-compile/reference/code.md
@@ -43,7 +43,7 @@
| Ключ | Умолчание | Значения |
|------|-----------|----------|
-| `source` | `[]` | объекты-источники: `["CatalogObject.Контрагенты", "DocumentObject.Реализация"]` |
+| `source` | `[]` | объекты-источники (формы ниже): `["CatalogObject.Контрагенты", "DocumentObject.Реализация"]` |
| `event` | `BeforeWrite` | `BeforeWrite` / `OnWrite` / `BeforeDelete` / `OnReadAtServer` / `FillCheckProcessing` … |
| `handler` | пусто | метод-обработчик `"МодульСервер.Процедура"` (дополняется до `CommonModule.…`) |
@@ -53,4 +53,23 @@
"handler": "ОбщегоНазначенияСервер.ПередЗаписьюКонтрагента" }
```
+**Формы источника.** Кроме конкретного объекта (`DocumentObject.Реализация`) источник бывает:
+
+| Форма | Смысл | Пример |
+|-------|-------|--------|
+| голый объектный вид | ВСЕ объекты класса | `"DocumentObject"`, `"CatalogObject"`, `"InformationRegisterRecordSet"`, `"ConstantValueManager"` |
+| `DefinedType.<Имя>` | состав определяемого типа | `"DefinedType.ПрисоединенныйФайлОбъект"` |
+| `Characteristic.<Имя>` | значение характеристики ПВХ | `"Characteristic.ДополнительныеРеквизитыИСведения"` |
+| менеджер объекта | сам менеджер, не класс | `"DocumentManager.Реализация"`, `"CatalogManager.Контрагенты"` |
+
+В типовых конфигурациях источник чаще задан классом или определяемым типом, чем перечислением:
+в выгрузке ERP так задана треть подписок. Русские имена принимаются наравне с английскими
+(`"ДокументОбъект"`, `"ОпределяемыйТип.Коллекция"`).
+
+```json
+{ "type": "EventSubscription", "name": "ПроверкаЗаполненияЛюбогоДокумента",
+ "source": ["DocumentObject", "DefinedType.ПрисоединенныйФайлОбъект"],
+ "event": "FillCheckProcessing", "handler": "ОбщегоНазначенияСервер.ПроверитьЗаполнение" }
+```
+
> Процедура-обработчик (`methodName` / `handler`) должна существовать в указанном общем модуле (экспортная).
diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1
index 79c0c72f1..00de753be 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.ps1
+++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1
@@ -739,9 +739,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py
index ad9006509..1a3f142fe 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.py
+++ b/.claude/skills/meta-compile/scripts/meta-compile.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python3
# meta-compile v1.113 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
@@ -873,14 +873,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
diff --git a/.claude/skills/meta-edit/scripts/meta-edit.ps1 b/.claude/skills/meta-edit/scripts/meta-edit.ps1
index 521198dcc..1c9a1baa1 100644
--- a/.claude/skills/meta-edit/scripts/meta-edit.ps1
+++ b/.claude/skills/meta-edit/scripts/meta-edit.ps1
@@ -625,9 +625,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/meta-edit/scripts/meta-edit.py b/.claude/skills/meta-edit/scripts/meta-edit.py
index 31d025a59..b4c0971ab 100644
--- a/.claude/skills/meta-edit/scripts/meta-edit.py
+++ b/.claude/skills/meta-edit/scripts/meta-edit.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python3
# meta-edit v1.53 — Edit existing 1C metadata object XML
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
@@ -649,14 +649,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
diff --git a/.claude/skills/meta-info/scripts/meta-info.ps1 b/.claude/skills/meta-info/scripts/meta-info.ps1
index 874372c47..cf1a233e7 100644
--- a/.claude/skills/meta-info/scripts/meta-info.ps1
+++ b/.claude/skills/meta-info/scripts/meta-info.ps1
@@ -250,7 +250,6 @@ function Resolve-DefinedType([string]$dtName) {
$dtNs.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
$tn = $dtDoc.SelectSingleNode("/md:MetaDataObject/md:DefinedType/md:Properties/md:Type", $dtNs)
if ($tn) {
- $res.Found = $true
$members = @()
$script:inTypeSetExpansion = $true
try {
@@ -264,6 +263,9 @@ function Resolve-DefinedType([string]$dtName) {
}
} finally { $script:inTypeSetExpansion = $false }
$res.Members = $members
+ # Found только после успешного разбора: иначе упавшее раскрытие
+ # печаталось бы как «состав пуст» — ложь вместо «не разобран».
+ $res.Found = $true
}
} catch { $res.Broken = $true }
if (-not $res.Found) { $res.Broken = $true }
@@ -728,6 +730,12 @@ function Format-SourceType([string]$raw) {
$prefix = $Matches[1]; $name = $Matches[2]
if ($objectTypeMap.ContainsKey($prefix)) { return "$($objectTypeMap[$prefix]).$name" }
}
+ # Голый вид без точки тоже бывает источником: meta-compile пишет менеджера (ДокументМенеджер)
+ # обычным v8:Type. Суффикса «(все)» тут НЕ ставим — это сам тип менеджера, а не класс объектов;
+ # множеством голый вид приходит через v8:TypeSet, и его форматирует Format-SingleTypeSet.
+ if ($raw -match '^cfg:(\w+)$' -and $objectTypeMap.ContainsKey($Matches[1])) {
+ return $objectTypeMap[$Matches[1]]
+ }
if ($raw -match '^cfg:(.+)$') { return $Matches[1] }
return $raw
}
@@ -1440,12 +1448,10 @@ if (-not $drillDone) {
Out "Источники ($total):"
# full печатает всё: режим для этого и нужен, а длину держит постраничник.
# В overview явные типы сворачиваем в счётчик — их бывает больше тысячи.
- $listTypes = ($Mode -eq "full") -or ($total -le $script:composedTypeThreshold)
+ $listTypes = ($Mode -eq "full") -or ($srcTypes.Count -le $script:composedTypeThreshold)
if ($listTypes) { foreach ($s in $srcTypes) { Out " $s" } }
foreach ($s in $srcSets) { Out " $s" }
- if (-not $listTypes -and $srcTypes.Count -gt 0) {
- Out " и ещё явных типов: $($srcTypes.Count) (-Mode full)"
- }
+ if (-not $listTypes) { Out " явных типов: $($srcTypes.Count) (-Mode full)" }
}
}
}
diff --git a/.claude/skills/meta-info/scripts/meta-info.py b/.claude/skills/meta-info/scripts/meta-info.py
index 00ea08aa9..b44b4fd80 100644
--- a/.claude/skills/meta-info/scripts/meta-info.py
+++ b/.claude/skills/meta-info/scripts/meta-info.py
@@ -328,7 +328,6 @@ def resolve_defined_type(dt_name):
dt_root = etree.parse(dt_path, parser_xml).getroot()
tn = find(dt_root, "/md:MetaDataObject/md:DefinedType/md:Properties/md:Type")
if tn is not None:
- res["found"] = True
members = []
_in_type_set_expansion["on"] = True
try:
@@ -340,6 +339,9 @@ def resolve_defined_type(dt_name):
finally:
_in_type_set_expansion["on"] = False
res["members"] = members
+ # found только после успешного разбора: иначе упавшее раскрытие
+ # печаталось бы как «состав пуст» — ложь вместо «не разобран».
+ res["found"] = True
except Exception:
res["broken"] = True
if not res["found"]:
@@ -793,6 +795,12 @@ def format_source_type(raw):
name = m.group(2)
if prefix in object_type_map:
return f"{object_type_map[prefix]}.{name}"
+ # Голый вид без точки тоже бывает источником: meta-compile пишет менеджера (ДокументМенеджер)
+ # обычным v8:Type. Суффикса «(все)» тут НЕ ставим — это сам тип менеджера, а не класс объектов;
+ # множеством голый вид приходит через v8:TypeSet, и его форматирует format_single_type_set.
+ m = re.match(r'^cfg:(\w+)$', raw)
+ if m and m.group(1) in object_type_map:
+ return object_type_map[m.group(1)]
m = re.match(r'^cfg:(.+)$', raw)
if m:
return m.group(1)
@@ -883,19 +891,9 @@ def get_object_support_status(obj_uuid):
try:
if _sg_is_external_root(object_path):
return None
- d = os.path.dirname(object_path)
- bin_path = None
- for _ in range(8):
- if not d:
- break
- cand = os.path.join(d, "Ext", "ParentConfigurations.bin")
- if os.path.exists(cand) or os.path.exists(os.path.join(d, "Configuration.xml")):
- bin_path = cand
- break
- parent = os.path.dirname(d)
- if parent == d:
- break
- d = parent
+ # Корень конфигурации ищем тем же климбом, что и состав определяемых типов.
+ root = get_config_root_dir()
+ bin_path = os.path.join(root, "Ext", "ParentConfigurations.bin") if root else None
if not bin_path or not os.path.exists(bin_path):
return "не на поддержке"
data = open(bin_path, "rb").read()
@@ -1474,14 +1472,14 @@ if not drill_done:
out(f"Источники ({total}):")
# full печатает всё: режим для этого и нужен, а длину держит постраничник.
# В overview явные типы сворачиваем в счётчик — их бывает больше тысячи.
- list_types = mode == "full" or total <= COMPOSED_TYPE_THRESHOLD
+ list_types = mode == "full" or len(src_types) <= COMPOSED_TYPE_THRESHOLD
if list_types:
for s in src_types:
out(f" {s}")
for s in src_sets:
out(f" {s}")
- if not list_types and src_types:
- out(f" и ещё явных типов: {len(src_types)} (-Mode full)")
+ if not list_types:
+ out(f" явных типов: {len(src_types)} (-Mode full)")
# HTTPService
if md_type == "HTTPService":
diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1
index 27b94a256..d781b6cd7 100644
--- a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1
+++ b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1
@@ -783,9 +783,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py
index 294f4a7f4..cf86ac71d 100644
--- a/.claude/skills/mxl-compile/scripts/mxl-compile.py
+++ b/.claude/skills/mxl-compile/scripts/mxl-compile.py
@@ -577,14 +577,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1
index da1bb2d7e..5111da16d 100644
--- a/.claude/skills/skd-compile/scripts/skd-compile.ps1
+++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1
@@ -443,9 +443,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py
index 3e84d4cfd..8f7ec6283 100644
--- a/.claude/skills/skd-compile/scripts/skd-compile.py
+++ b/.claude/skills/skd-compile/scripts/skd-compile.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python3
# skd-compile v1.123 — Compile 1C DCS from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -427,14 +427,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1
index f7deec875..273a58d4e 100644
--- a/.claude/skills/skd-edit/scripts/skd-edit.ps1
+++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1
@@ -274,9 +274,6 @@ function Resolve-TypeStr {
$typeStr = ($typeStr -replace '\s*\((?:все|all)\)\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '').Trim()
$typeStr = ($typeStr -replace '\s*\((?:типов|types):\s*\d+\)\s*$', '').Trim()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- if ($typeStr -match '^(.+?)\s*(?:→|->)\s*.+$') { $typeStr = $Matches[1].Trim() }
# Параметризованные типы: Number(15,2), Строка(100)
if ($typeStr -match '^([^(]+)\((.+)\)$') {
diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py
index e0c550680..65c0993cc 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.41 — Atomic 1C DCS editor (Python port)
+# skd-edit v1.41 — Atomic 1C DCS editor (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import json
@@ -386,14 +386,9 @@ def resolve_type_str(type_str):
# и счётчик состава. Копипаста строки оттуда — обычный путь, поэтому хвост снимаем молча.
# Срезаем ТОЛЬКО эти известные формы: круглые скобки заняты параметризованными типами
# (Число(15,2)), слепой срез скобок сломал бы их.
- type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str).strip()
- type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str).strip()
- # Строка глоссария целиком: «ОпределяемыйТип.X -> Число(15,2)». Имя множества стоит слева,
- # раскрытие справа — берём левую часть, она и есть тип.
- m = re.match(r'^(.+?)\s*(?:→|->)\s*.+$', type_str)
- if m:
- type_str = m.group(1).strip()
+ type_str = re.sub(r'\s*\((?:все|all)\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*[—-]\s*(?:типов|types):\s*\d+\s*$', '', type_str, flags=re.IGNORECASE).strip()
+ type_str = re.sub(r'\s*\((?:типов|types):\s*\d+\)\s*$', '', type_str, flags=re.IGNORECASE).strip()
# Параметризованные типы: Number(15,2), Строка(100)
m = re.match(r'^([^(]+)\((.+)\)$', type_str)
if m:
diff --git a/tests/skills/cases/meta-info/event-subscription-bare-manager.json b/tests/skills/cases/meta-info/event-subscription-bare-manager.json
new file mode 100644
index 000000000..7eb7c20d2
--- /dev/null
+++ b/tests/skills/cases/meta-info/event-subscription-bare-manager.json
@@ -0,0 +1,66 @@
+{
+ "name": "Подписка: голый менеджер в источниках — по-русски и без «(все)»",
+ "setup": "empty-config",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "CommonModule",
+ "name": "Обработчики",
+ "server": true
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "Document",
+ "name": "Заказ"
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "EventSubscription",
+ "name": "Менеджеры",
+ "event": "BeforeWrite",
+ "handler": "Обработчики.ПередЗаписью",
+ "source": [
+ "DocumentManager",
+ "DocumentManager.Заказ",
+ "DocumentObject"
+ ]
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ }
+ ],
+ "params": {
+ "objectPath": "EventSubscriptions/Менеджеры.xml"
+ },
+ "args_extra": [
+ "-Mode",
+ "full"
+ ],
+ "expect": {
+ "stdoutContains": [
+ "Источники (3):",
+ " ДокументМенеджер",
+ " ДокументМенеджер.Заказ",
+ " ДокументОбъект (все)"
+ ],
+ "stdoutNotContains": [
+ "DocumentManager",
+ "ДокументМенеджер (все)"
+ ]
+ }
+}
diff --git a/tests/skills/cases/meta-info/event-subscription-explicit-collapsed.json b/tests/skills/cases/meta-info/event-subscription-explicit-collapsed.json
index 6b148d001..dcbad9ade 100644
--- a/tests/skills/cases/meta-info/event-subscription-explicit-collapsed.json
+++ b/tests/skills/cases/meta-info/event-subscription-explicit-collapsed.json
@@ -114,7 +114,7 @@
"stdoutContains": [
"Источники (7):",
" СправочникОбъект (все)",
- " и ещё явных типов: 6 (-Mode full)"
+ " явных типов: 6 (-Mode full)"
],
"stdoutNotContains": [
"ДокументОбъект.Д3"
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/CommonModules/Обработчики.xml b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/CommonModules/Обработчики.xml
new file mode 100644
index 000000000..08f9b3d33
--- /dev/null
+++ b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/CommonModules/Обработчики.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ Обработчики
+
+
+ ru
+ Обработчики
+
+
+
+ false
+ false
+ true
+ false
+ false
+ false
+ false
+ DontUse
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/CommonModules/Обработчики/Ext/Module.bsl b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/CommonModules/Обработчики/Ext/Module.bsl
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Configuration.xml b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Configuration.xml
new file mode 100644
index 000000000..b25feeca2
--- /dev/null
+++ b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Configuration.xml
@@ -0,0 +1,254 @@
+
+
+
+
+
+ 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-info/snapshots/event-subscription-bare-manager/Documents/Заказ.xml b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Documents/Заказ.xml
new file mode 100644
index 000000000..32fa05878
--- /dev/null
+++ b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Documents/Заказ.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+
+ Заказ
+
+
+ ru
+ Заказ
+
+
+
+ true
+
+ String
+ 11
+ Variable
+ Year
+ true
+ true
+
+
+
+ Document.Заказ.StandardAttribute.Number
+
+ Use
+ Begin
+ DontUse
+ Directly
+
+
+
+
+
+
+ Allow
+ Deny
+ AutoDelete
+ WriteSelected
+ AutoFill
+
+ true
+ true
+ false
+
+ Managed
+ Use
+
+
+
+
+
+ Auto
+ DontUse
+ false
+ false
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Documents/Заказ/Ext/ObjectModule.bsl b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Documents/Заказ/Ext/ObjectModule.bsl
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/EventSubscriptions/Менеджеры.xml b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/EventSubscriptions/Менеджеры.xml
new file mode 100644
index 000000000..91c4e92b7
--- /dev/null
+++ b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/EventSubscriptions/Менеджеры.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ Менеджеры
+
+
+ ru
+ Менеджеры
+
+
+
+
+ cfg:DocumentManager
+ cfg:DocumentManager.Заказ
+ cfg:DocumentObject
+
+ BeforeWrite
+ CommonModule.Обработчики.ПередЗаписью
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Ext/ClientApplicationInterface.xml
new file mode 100644
index 000000000..3c1161b2d
--- /dev/null
+++ b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ UUID-002
+
+
+
+
+ UUID-004
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Languages/Русский.xml b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Languages/Русский.xml
new file mode 100644
index 000000000..37c60d786
--- /dev/null
+++ b/tests/skills/cases/meta-info/snapshots/event-subscription-bare-manager/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file