diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1
index d4a95cbd..1bc5b172 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.122 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.123 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -2824,9 +2824,10 @@ function Emit-XrFlag {
X "$indent`t$(if ($common){'true'}else{'false'})"
if ($val.roles) {
foreach ($r in $val.roles.PSObject.Properties) {
- # Forgiving: принимаем имя без префикса, с "Role." или кириллическим "Роль." → нормализуем в "Role."
+ # Forgiving: принимаем имя без префикса, с "Role." или кириллическим "Роль." → нормализуем в "Role.".
+ # Роль по GUID (заимствованная/расширение — name="" без префикса) эмитим как есть.
$rname = "$($r.Name)" -replace '^(Role|Роль)\.', ''
- $rname = "Role.$rname"
+ if ($rname -notmatch '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$') { $rname = "Role.$rname" }
$rval = if ([bool]$r.Value) { 'true' } else { 'false' }
X "$indent`t$rval"
}
diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py
index 82489d99..585391aa 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.122 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.123 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -2572,8 +2572,11 @@ def emit_xr_flag(lines, tag, val, indent):
roles = val.get('roles')
if roles:
for rname, rval in roles.items():
- # Forgiving: имя без префикса, с "Role." или кириллическим "Роль." → нормализуем в "Role."
- rn = "Role." + re.sub(r'^(Role|Роль)\.', '', rname)
+ # Forgiving: имя без префикса, с "Role." или кириллическим "Роль." → нормализуем в "Role.".
+ # Роль по GUID (заимствованная/расширение — name="" без префикса) эмитим как есть.
+ rn = re.sub(r'^(Role|Роль)\.', '', rname)
+ if not re.match(r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$', rn):
+ rn = "Role." + rn
lines.append(f"{indent}\t{'true' if rval else 'false'}")
lines.append(f"{indent}{tag}>")
diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md
index afbbbbc2..100c37fe 100644
--- a/docs/form-dsl-spec.md
+++ b/docs/form-dsl-spec.md
@@ -167,7 +167,7 @@
Семантика как в конфигураторе (три состояния флага роли): роль, **не указанная** в `roles`, наследует `common`; указанная — задаёт явный `true`/`false` (может совпадать с `common`).
-**Имя роли** — forgiving: принимается без префикса (`ПолныеПрава`), с `Role.` или кириллическим `Роль.`; нормализуется в `Role.ИмяРоли`.
+**Имя роли** — forgiving: принимается без префикса (`ПолныеПрава`), с `Role.` или кириллическим `Роль.`; нормализуется в `Role.ИмяРоли`. **Ссылка по GUID** (заимствованная роль / расширение — `name=""` без префикса): ключ роли — сам GUID, эмитится как есть (без `Role.`).
**Отсутствие ключа** = полный доступ (платформа тег не пишет) — дефолт не эмитим.
diff --git a/tests/skills/cases/form-compile/attributes-types.json b/tests/skills/cases/form-compile/attributes-types.json
index d45ed593..80680c8b 100644
--- a/tests/skills/cases/form-compile/attributes-types.json
+++ b/tests/skills/cases/form-compile/attributes-types.json
@@ -24,7 +24,7 @@
"attributes": [
{ "name": "Объект", "type": "DataProcessorObject.Типы", "main": true },
{ "name": "Строка", "type": "string(200)", "view": false, "save": true, "fillCheck": true },
- { "name": "Число", "type": "decimal(10,0,nonneg)", "edit": false },
+ { "name": "Число", "type": "decimal(10,0,nonneg)", "edit": { "common": false, "roles": { "a1b2c3d4-1111-2222-3333-444455556666": true } } },
{ "name": "Дата", "type": "dateTime", "title": "" },
{ "name": "Булево", "type": "boolean" },
{ "name": "Период", "type": "СтандартныйПериод", "save": ["Период", "EndDate", "StartDate", "Variant"] },
diff --git a/tests/skills/cases/form-compile/snapshots/attributes-types/DataProcessors/Типы/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/attributes-types/DataProcessors/Типы/Forms/Форма/Ext/Form.xml
index 64da1196..a2a374ae 100644
--- a/tests/skills/cases/form-compile/snapshots/attributes-types/DataProcessors/Типы/Forms/Форма/Ext/Form.xml
+++ b/tests/skills/cases/form-compile/snapshots/attributes-types/DataProcessors/Типы/Forms/Форма/Ext/Form.xml
@@ -79,6 +79,7 @@
false
+ true