diff --git a/.claude/skills/cf-edit/scripts/cf-edit.ps1 b/.claude/skills/cf-edit/scripts/cf-edit.ps1 index 0973ae9c..71f356e3 100644 --- a/.claude/skills/cf-edit/scripts/cf-edit.ps1 +++ b/.claude/skills/cf-edit/scripts/cf-edit.ps1 @@ -1,4 +1,4 @@ -# cf-edit v1.8 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.9 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$ConfigPath, @@ -44,6 +44,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -80,10 +90,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/cf-edit/scripts/cf-edit.py b/.claude/skills/cf-edit/scripts/cf-edit.py index 9aa6c5c8..4fbdf2fe 100644 --- a/.claude/skills/cf-edit/scripts/cf-edit.py +++ b/.claude/skills/cf-edit/scripts/cf-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-edit v1.8 — Edit 1C configuration root (Configuration.xml) +# cf-edit v1.9 — Edit 1C configuration root (Configuration.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -33,6 +33,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -72,6 +84,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -79,6 +94,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/form-add/scripts/form-add.ps1 b/.claude/skills/form-add/scripts/form-add.ps1 index 7bdb5d1c..e4d15755 100644 --- a/.claude/skills/form-add/scripts/form-add.ps1 +++ b/.claude/skills/form-add/scripts/form-add.ps1 @@ -1,4 +1,4 @@ -# form-add v1.8 — Add managed form to 1C config object +# form-add v1.9 — Add managed form to 1C config object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -33,6 +33,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -69,10 +79,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/form-add/scripts/form-add.py b/.claude/skills/form-add/scripts/form-add.py index 244304db..b77a6379 100644 --- a/.claude/skills/form-add/scripts/form-add.py +++ b/.claude/skills/form-add/scripts/form-add.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-add v1.8 — Add managed form to 1C config object +# form-add v1.9 — Add managed form to 1C config object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -32,6 +32,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -71,6 +83,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -78,6 +93,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 7c7a0a6d..199943c2 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.174 — Compile 1C managed form from JSON or object metadata +# form-compile v1.175 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -1362,6 +1362,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -1398,10 +1408,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 7f466a75..6f4cbd9d 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.174 — Compile 1C managed form from JSON or object metadata +# form-compile v1.175 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -34,6 +34,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -73,6 +85,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -80,6 +95,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/form-edit/scripts/form-edit.ps1 b/.claude/skills/form-edit/scripts/form-edit.ps1 index 9f171d2f..7c35378d 100644 --- a/.claude/skills/form-edit/scripts/form-edit.ps1 +++ b/.claude/skills/form-edit/scripts/form-edit.ps1 @@ -1,4 +1,4 @@ -# form-edit v1.3 — Edit 1C managed form elements +# form-edit v1.4 — Edit 1C managed form elements # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -27,6 +27,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -63,10 +73,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/form-edit/scripts/form-edit.py b/.claude/skills/form-edit/scripts/form-edit.py index d313f388..4307e27d 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.3 — Edit 1C managed form elements (Python port) +# form-edit v1.4 — Edit 1C managed form elements (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -31,6 +31,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -70,6 +82,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -77,6 +92,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/form-info/scripts/form-info.ps1 b/.claude/skills/form-info/scripts/form-info.ps1 index 7b9e36cc..309cc63a 100644 --- a/.claude/skills/form-info/scripts/form-info.ps1 +++ b/.claude/skills/form-info/scripts/form-info.ps1 @@ -1,4 +1,4 @@ -# form-info v1.4 — Analyze 1C managed form structure +# form-info v1.5 — Analyze 1C managed form structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] @@ -372,6 +372,16 @@ if ($formsIdx -ge 0 -and ($formsIdx + 1) -lt $parts.Count) { # See docs/1c-support-state-spec.md. Walks up from the target path, taking the # uuid of the nearest element meta-xml (form/template/etc.) and the config root # bin. Never throws — degrades to "не на поддержке". +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Get-SupportStatusForPath([string]$targetPath) { try { $rp = (Resolve-Path $targetPath).Path @@ -390,8 +400,10 @@ function Get-SupportStatusForPath([string]$targetPath) { } # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). $elemUuid = Get-RootUuid $rp + if (Test-ExternalObjectRoot $rp) { return $null } $d = [System.IO.Path]::GetDirectoryName($rp) for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return $null } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $binPath) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" @@ -448,7 +460,8 @@ if ($formTitle) { $header += " — `"$formTitle`"" } if ($objectContext) { $header += " ($objectContext)" } $header += " ===" $lines += $header -$lines += "Поддержка: $(Get-SupportStatusForPath $FormPath)" +$support = Get-SupportStatusForPath $FormPath +if ($null -ne $support) { $lines += "Поддержка: $support" } # --- Form properties (Title excluded — shown in header) --- diff --git a/.claude/skills/form-info/scripts/form-info.py b/.claude/skills/form-info/scripts/form-info.py index f7b9b70d..0cab83b8 100644 --- a/.claude/skills/form-info/scripts/form-info.py +++ b/.claude/skills/form-info/scripts/form-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-info v1.4 — Analyze 1C managed form structure +# form-info v1.5 — Analyze 1C managed form structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -353,14 +353,29 @@ def get_support_status_for_path(target_path): except Exception: pass return None + def is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False rp = os.path.abspath(target_path) # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). elem_uuid = root_uuid(rp) + if is_external_root(rp): + return None bin_path = None d = os.path.dirname(rp) for _ in range(12): if not d: break + if is_external_root(d + ".xml"): + return None if not elem_uuid: elem_uuid = root_uuid(d + ".xml") if not bin_path: @@ -513,7 +528,9 @@ def main(): header += f" ({object_context})" header += " ===" lines.append(header) - lines.append(f"Поддержка: {get_support_status_for_path(form_path)}") + _support = get_support_status_for_path(form_path) + if _support is not None: + lines.append(f"Поддержка: {_support}") # --- Form properties (Title excluded -- shown in header) --- prop_names = [ diff --git a/.claude/skills/help-add/scripts/add-help.ps1 b/.claude/skills/help-add/scripts/add-help.ps1 index df9a2ac8..f1f502f6 100644 --- a/.claude/skills/help-add/scripts/add-help.ps1 +++ b/.claude/skills/help-add/scripts/add-help.ps1 @@ -1,4 +1,4 @@ -# help-add v1.7 — Add built-in help to 1C object +# help-add v1.8 — Add built-in help to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -28,6 +28,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -64,10 +74,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/help-add/scripts/add-help.py b/.claude/skills/help-add/scripts/add-help.py index a8769acf..38056ef3 100644 --- a/.claude/skills/help-add/scripts/add-help.py +++ b/.claude/skills/help-add/scripts/add-help.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# add-help v1.7 — Add built-in help to 1C object +# add-help v1.8 — Add built-in help to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -33,6 +33,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -72,6 +84,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -79,6 +94,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/interface-edit/scripts/interface-edit.ps1 b/.claude/skills/interface-edit/scripts/interface-edit.ps1 index 4cc77886..759df166 100644 --- a/.claude/skills/interface-edit/scripts/interface-edit.ps1 +++ b/.claude/skills/interface-edit/scripts/interface-edit.ps1 @@ -1,4 +1,4 @@ -# interface-edit v1.6 — Edit 1C CommandInterface.xml +# interface-edit v1.7 — Edit 1C CommandInterface.xml # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$CIPath, @@ -39,6 +39,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -75,10 +85,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/interface-edit/scripts/interface-edit.py b/.claude/skills/interface-edit/scripts/interface-edit.py index b3987ac5..3967aae0 100644 --- a/.claude/skills/interface-edit/scripts/interface-edit.py +++ b/.claude/skills/interface-edit/scripts/interface-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# interface-edit v1.6 — Edit 1C CommandInterface.xml +# interface-edit v1.7 — Edit 1C CommandInterface.xml # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -31,6 +31,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -70,6 +82,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -77,6 +92,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index e8153d3b..9ba047d5 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.65 — Compile 1C metadata object from JSON +# meta-compile v1.66 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -36,6 +36,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -72,10 +82,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index e71950b2..cff57fa9 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.65 — Compile 1C metadata object from JSON +# meta-compile v1.66 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,6 +36,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -75,6 +87,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -82,6 +97,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/meta-edit/scripts/meta-edit.ps1 b/.claude/skills/meta-edit/scripts/meta-edit.ps1 index 136b45fc..e201bf20 100644 --- a/.claude/skills/meta-edit/scripts/meta-edit.ps1 +++ b/.claude/skills/meta-edit/scripts/meta-edit.ps1 @@ -1,4 +1,4 @@ -# meta-edit v1.19 — Edit existing 1C metadata object XML (+add-predefined предопределённые Ext/Predefined.xml) +# meta-edit v1.20 — Edit existing 1C metadata object XML (+add-predefined предопределённые Ext/Predefined.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -170,6 +170,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -206,10 +216,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/meta-edit/scripts/meta-edit.py b/.claude/skills/meta-edit/scripts/meta-edit.py index 9d7241a9..34328088 100644 --- a/.claude/skills/meta-edit/scripts/meta-edit.py +++ b/.claude/skills/meta-edit/scripts/meta-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-edit v1.19 — Edit existing 1C metadata object XML (+add-predefined предопределённые Ext/Predefined.xml) +# meta-edit v1.20 — Edit existing 1C metadata object XML (+add-predefined предопределённые Ext/Predefined.xml) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -32,6 +32,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -71,6 +83,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -78,6 +93,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/meta-info/scripts/meta-info.ps1 b/.claude/skills/meta-info/scripts/meta-info.ps1 index 0fe3818c..c7f1e4fa 100644 --- a/.claude/skills/meta-info/scripts/meta-info.ps1 +++ b/.claude/skills/meta-info/scripts/meta-info.ps1 @@ -1,4 +1,4 @@ -# meta-info v1.3 — Compact summary of 1C metadata object +# meta-info v1.4 — Compact summary of 1C metadata object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$ObjectPath, @@ -418,8 +418,19 @@ function Get-WSOperations($childObjs) { # --- Support status of this object (Ext/ParentConfigurations.bin) --- # See docs/1c-support-state-spec.md. Walks up to the config root, decodes the # object's support rule. Never throws — degrades to "не на поддержке". +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Get-ObjectSupportStatus([string]$objUuid) { try { + if (Test-ExternalObjectRoot $ObjectPath) { return $null } # Walk up to the config root (dir with Configuration.xml or Ext/ParentConfigurations.bin). $d = [System.IO.Path]::GetDirectoryName($ObjectPath) $binPath = $null @@ -653,7 +664,8 @@ if (-not $drillDone) { if ($synonym -and $synonym -ne $objName) { $header += " — `"$synonym`"" } $header += " ===" Out $header - Out "Поддержка: $(Get-ObjectSupportStatus $typeNode.GetAttribute('uuid'))" + $support = Get-ObjectSupportStatus $typeNode.GetAttribute('uuid') + if ($null -ne $support) { Out "Поддержка: $support" } # --- Type presentation (ref objects) --- if ($isRefObject) { diff --git a/.claude/skills/meta-info/scripts/meta-info.py b/.claude/skills/meta-info/scripts/meta-info.py index ab00b7b9..fd334341 100644 --- a/.claude/skills/meta-info/scripts/meta-info.py +++ b/.claude/skills/meta-info/scripts/meta-info.py @@ -1,4 +1,4 @@ -# meta-info v1.3 — Compact summary of 1C metadata object (Python port) +# meta-info v1.4 — Compact summary of 1C metadata object (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -472,8 +472,23 @@ def get_ws_operations(child_objs): # ── Support status of this object (Ext/ParentConfigurations.bin) ── # See docs/1c-support-state-spec.md. Walks up to the config root, decodes the # object's support rule. Never throws — degrades to "не на поддержке". +def _meta_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + + def get_object_support_status(obj_uuid): try: + if _meta_is_external_root(object_path): + return None d = os.path.dirname(object_path) bin_path = None for _ in range(8): @@ -703,7 +718,9 @@ if not drill_done: header += f' \u2014 "{synonym}"' header += " ===" out(header) - out(f"Поддержка: {get_object_support_status(type_node.get('uuid', ''))}") + _support = get_object_support_status(type_node.get('uuid', '')) + if _support is not None: + out(f"Поддержка: {_support}") # Type presentation (ref objects) if is_ref_object: diff --git a/.claude/skills/meta-remove/scripts/meta-remove.ps1 b/.claude/skills/meta-remove/scripts/meta-remove.ps1 index 8560bb0f..b51228d5 100644 --- a/.claude/skills/meta-remove/scripts/meta-remove.ps1 +++ b/.claude/skills/meta-remove/scripts/meta-remove.ps1 @@ -1,4 +1,4 @@ -# meta-remove v1.3 — Remove metadata object from 1C configuration dump +# meta-remove v1.4 — Remove metadata object from 1C configuration dump # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -93,6 +93,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -129,10 +139,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/meta-remove/scripts/meta-remove.py b/.claude/skills/meta-remove/scripts/meta-remove.py index fd00e131..63cd5bdc 100644 --- a/.claude/skills/meta-remove/scripts/meta-remove.py +++ b/.claude/skills/meta-remove/scripts/meta-remove.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-remove v1.3 — Remove metadata object from 1C configuration dump +# meta-remove v1.4 — Remove metadata object from 1C configuration dump # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -31,6 +31,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -70,6 +82,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -77,6 +92,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 index 7bcb22ae..9a229067 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 @@ -1,4 +1,4 @@ -# mxl-compile v1.3 — Compile 1C spreadsheet from JSON +# mxl-compile v1.4 — Compile 1C spreadsheet from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -26,6 +26,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -62,10 +72,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py index 8de3bb76..383d59c2 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.py +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-compile v1.3 — Compile 1C spreadsheet from JSON +# mxl-compile v1.4 — Compile 1C spreadsheet from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -31,6 +31,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -70,6 +82,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -77,6 +92,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/mxl-info/scripts/mxl-info.ps1 b/.claude/skills/mxl-info/scripts/mxl-info.ps1 index ce65dd96..eb675f0c 100644 --- a/.claude/skills/mxl-info/scripts/mxl-info.ps1 +++ b/.claude/skills/mxl-info/scripts/mxl-info.ps1 @@ -1,4 +1,4 @@ -# mxl-info v1.1 — Analyze 1C spreadsheet structure +# mxl-info v1.2 — Analyze 1C spreadsheet structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Alias('Path')] @@ -321,6 +321,16 @@ if ($Format -eq "json") { exit 0 } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Get-SupportStatusForPath([string]$targetPath) { try { $rp = (Resolve-Path $targetPath).Path @@ -339,8 +349,10 @@ function Get-SupportStatusForPath([string]$targetPath) { } # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). $elemUuid = Get-RootUuid $rp + if (Test-ExternalObjectRoot $rp) { return $null } $d = [System.IO.Path]::GetDirectoryName($rp) for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return $null } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $binPath) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" @@ -385,7 +397,8 @@ function Get-SupportStatusForPath([string]$targetPath) { $lines = @() $lines += "=== $templateName ===" -$lines += "Поддержка: $(Get-SupportStatusForPath $TemplatePath)" +$support = Get-SupportStatusForPath $TemplatePath +if ($null -ne $support) { $lines += "Поддержка: $support" } $lines += " Rows: $docHeight, Columns: $defaultColCount" if ($columnSets.Count -eq 0) { diff --git a/.claude/skills/mxl-info/scripts/mxl-info.py b/.claude/skills/mxl-info/scripts/mxl-info.py index 716a7bfd..f606f8c7 100644 --- a/.claude/skills/mxl-info/scripts/mxl-info.py +++ b/.claude/skills/mxl-info/scripts/mxl-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-info v1.1 — Analyze 1C spreadsheet structure +# mxl-info v1.2 — Analyze 1C spreadsheet structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -321,14 +321,29 @@ def get_support_status_for_path(target_path): except Exception: pass return None + def is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False rp = os.path.abspath(target_path) # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). elem_uuid = root_uuid(rp) + if is_external_root(rp): + return None bin_path = None d = os.path.dirname(rp) for _ in range(12): if not d: break + if is_external_root(d + ".xml"): + return None if not elem_uuid: elem_uuid = root_uuid(d + ".xml") if not bin_path: @@ -380,7 +395,9 @@ def get_support_status_for_path(target_path): lines = [] lines.append(f"=== {template_name} ===") -lines.append(f"Поддержка: {get_support_status_for_path(template_path)}") +_support = get_support_status_for_path(template_path) +if _support is not None: + lines.append(f"Поддержка: {_support}") lines.append(f" Rows: {doc_height}, Columns: {default_col_count}") if len(column_sets) == 0: diff --git a/.claude/skills/role-compile/scripts/role-compile.ps1 b/.claude/skills/role-compile/scripts/role-compile.ps1 index e192d4b5..1ad8e824 100644 --- a/.claude/skills/role-compile/scripts/role-compile.ps1 +++ b/.claude/skills/role-compile/scripts/role-compile.ps1 @@ -1,4 +1,4 @@ -# role-compile v1.7 — Compile 1C role from JSON +# role-compile v1.8 — Compile 1C role from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -26,6 +26,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -62,10 +72,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/role-compile/scripts/role-compile.py b/.claude/skills/role-compile/scripts/role-compile.py index 1cd45da4..990bd9bd 100644 --- a/.claude/skills/role-compile/scripts/role-compile.py +++ b/.claude/skills/role-compile/scripts/role-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-compile v1.7 — Compile 1C role from JSON +# role-compile v1.8 — Compile 1C role from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -31,6 +31,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -70,6 +82,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -77,6 +92,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/role-info/scripts/role-info.ps1 b/.claude/skills/role-info/scripts/role-info.ps1 index 766fa6fd..3edc22d9 100644 --- a/.claude/skills/role-info/scripts/role-info.ps1 +++ b/.claude/skills/role-info/scripts/role-info.ps1 @@ -1,4 +1,4 @@ -# role-info v1.1 — Analyze 1C role rights +# role-info v1.2 — Analyze 1C role rights # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$RightsPath, @@ -145,6 +145,16 @@ foreach ($tpl in $tplNodes) { } } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Get-SupportStatusForPath([string]$targetPath) { try { $rp = (Resolve-Path $targetPath).Path @@ -163,8 +173,10 @@ function Get-SupportStatusForPath([string]$targetPath) { } # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). $elemUuid = Get-RootUuid $rp + if (Test-ExternalObjectRoot $rp) { return $null } $d = [System.IO.Path]::GetDirectoryName($rp) for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return $null } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $binPath) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" @@ -209,7 +221,8 @@ $header = "=== Role: $roleName" if ($roleSynonym) { $header += " --- `"$roleSynonym`"" } $header += " ===" Out $header -Out "Поддержка: $(Get-SupportStatusForPath $RightsPath)" +$support = Get-SupportStatusForPath $RightsPath +if ($null -ne $support) { Out "Поддержка: $support" } Out "" Out "Properties: setForNewObjects=$setForNew, setForAttributesByDefault=$setForAttrs, independentRightsOfChildObjects=$independentChild" diff --git a/.claude/skills/role-info/scripts/role-info.py b/.claude/skills/role-info/scripts/role-info.py index a15e759f..fa70ce6c 100644 --- a/.claude/skills/role-info/scripts/role-info.py +++ b/.claude/skills/role-info/scripts/role-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-info v1.1 — Analyze 1C role rights +# role-info v1.2 — Analyze 1C role rights # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -161,14 +161,29 @@ def get_support_status_for_path(target_path): except Exception: pass return None + def is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False rp = os.path.abspath(target_path) # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). elem_uuid = root_uuid(rp) + if is_external_root(rp): + return None bin_path = None d = os.path.dirname(rp) for _ in range(12): if not d: break + if is_external_root(d + ".xml"): + return None if not elem_uuid: elem_uuid = root_uuid(d + ".xml") if not bin_path: @@ -222,7 +237,9 @@ if role_synonym: header += f' --- "{role_synonym}"' header += " ===" out(header) -out(f"Поддержка: {get_support_status_for_path(rights_path)}") +_support = get_support_status_for_path(rights_path) +if _support is not None: + out(f"Поддержка: {_support}") out() out(f"Properties: setForNewObjects={set_for_new}, setForAttributesByDefault={set_for_attrs}, independentRightsOfChildObjects={independent_child}") diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index 3bd81e3b..c613e42e 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -1,4 +1,4 @@ -# skd-compile v1.107 — Compile 1C DCS from JSON +# skd-compile v1.108 — Compile 1C DCS from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -25,6 +25,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -61,10 +71,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index 2faff1e4..bc85253c 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.py +++ b/.claude/skills/skd-compile/scripts/skd-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-compile v1.107 — Compile 1C DCS from JSON +# skd-compile v1.108 — Compile 1C DCS from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -31,6 +31,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -70,6 +82,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -77,6 +92,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1 index 7ae894a2..da131019 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.ps1 +++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1 @@ -1,4 +1,4 @@ -# skd-edit v1.28 — Atomic 1C DCS editor +# skd-edit v1.29 — Atomic 1C DCS editor # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: парный .py собирает выражения автодат вне f-string ради совместимости с python 3.9 (PEP 701). param( @@ -64,6 +64,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -100,10 +110,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py index f281a849..2491034a 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.28 — Atomic 1C DCS editor (Python port) +# skd-edit v1.29 — Atomic 1C DCS editor (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -141,6 +141,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -180,6 +192,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -187,6 +202,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/skd-info/scripts/skd-info.ps1 b/.claude/skills/skd-info/scripts/skd-info.ps1 index 14cdefaa..10be42c1 100644 --- a/.claude/skills/skd-info/scripts/skd-info.ps1 +++ b/.claude/skills/skd-info/scripts/skd-info.ps1 @@ -1,4 +1,4 @@ -# skd-info v1.7 — Analyze 1C DCS structure +# skd-info v1.8 — Analyze 1C DCS structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)] @@ -334,6 +334,16 @@ for ($i = $pathParts.Count - 1; $i -ge 0; $i--) { $totalXmlLines = (Get-Content $resolvedPath).Count +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Get-SupportStatusForPath([string]$targetPath) { try { $rp = (Resolve-Path $targetPath).Path @@ -352,8 +362,10 @@ function Get-SupportStatusForPath([string]$targetPath) { } # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). $elemUuid = Get-RootUuid $rp + if (Test-ExternalObjectRoot $rp) { return $null } $d = [System.IO.Path]::GetDirectoryName($rp) for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return $null } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $binPath) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" @@ -395,7 +407,8 @@ function Get-SupportStatusForPath([string]$targetPath) { function Show-Overview { $lines.Add("=== DCS: $templateName ($totalXmlLines lines) ===") - $lines.Add("Поддержка: $(Get-SupportStatusForPath $TemplatePath)") + $support = Get-SupportStatusForPath $TemplatePath + if ($null -ne $support) { $lines.Add("Поддержка: $support") } $lines.Add("") # Sources diff --git a/.claude/skills/skd-info/scripts/skd-info.py b/.claude/skills/skd-info/scripts/skd-info.py index 8821dd77..bec0476e 100644 --- a/.claude/skills/skd-info/scripts/skd-info.py +++ b/.claude/skills/skd-info/scripts/skd-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-info v1.7 — Analyze 1C DCS structure +# skd-info v1.8 — Analyze 1C DCS structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -278,14 +278,29 @@ def get_support_status_for_path(target_path): except Exception: pass return None + def is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False rp = os.path.abspath(target_path) # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). elem_uuid = root_uuid(rp) + if is_external_root(rp): + return None bin_path = None d = os.path.dirname(rp) for _ in range(12): if not d: break + if is_external_root(d + ".xml"): + return None if not elem_uuid: elem_uuid = root_uuid(d + ".xml") if not bin_path: @@ -424,7 +439,9 @@ def main(): def show_overview(): lines.append(f"=== DCS: {template_name} ({total_xml_lines} lines) ===") - lines.append(f"Поддержка: {get_support_status_for_path(template_path)}") + _support = get_support_status_for_path(template_path) + if _support is not None: + lines.append(f"Поддержка: {_support}") lines.append("") # Sources diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 index 3a19581f..fa318f6e 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 @@ -1,4 +1,4 @@ -# subsystem-compile v1.8 — Create 1C subsystem from JSON definition +# subsystem-compile v1.9 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -63,6 +63,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -99,10 +109,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py index f3f56aad..c604ecb5 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-compile v1.8 — Create 1C subsystem from JSON definition +# subsystem-compile v1.9 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -32,6 +32,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -71,6 +83,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -78,6 +93,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 index 7cf74907..7acf7b6c 100644 --- a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 +++ b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 @@ -1,4 +1,4 @@ -# subsystem-edit v1.5 — Edit existing 1C subsystem XML +# subsystem-edit v1.6 — Edit existing 1C subsystem XML # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$SubsystemPath, @@ -136,6 +136,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -172,10 +182,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py index 4aade197..d1f9335d 100644 --- a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py +++ b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-edit v1.5 — Edit existing 1C subsystem XML +# subsystem-edit v1.6 — Edit existing 1C subsystem XML # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -32,6 +32,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -71,6 +83,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -78,6 +93,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 b/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 index 8ad7fc63..dbf8686f 100644 --- a/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 +++ b/.claude/skills/subsystem-info/scripts/subsystem-info.ps1 @@ -1,4 +1,4 @@ -# subsystem-info v1.1 — Compact summary of 1C subsystem structure +# subsystem-info v1.2 — Compact summary of 1C subsystem structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory=$true)][Alias('Path')][string]$SubsystemPath, @@ -17,6 +17,16 @@ $ErrorActionPreference = 'Stop' $script:lines = @() function Out([string]$text) { $script:lines += $text } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Get-SupportStatusForPath([string]$targetPath) { try { $rp = (Resolve-Path $targetPath).Path @@ -35,8 +45,10 @@ function Get-SupportStatusForPath([string]$targetPath) { } # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). $elemUuid = Get-RootUuid $rp + if (Test-ExternalObjectRoot $rp) { return $null } $d = [System.IO.Path]::GetDirectoryName($rp) for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return $null } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $binPath) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" @@ -175,7 +187,8 @@ function Get-SubsystemDir([string]$xmlPath) { # --- Show functions for full mode --- function Show-Overview { Out "Подсистема: $subName" - Out "Поддержка: $(Get-SupportStatusForPath $SubsystemPath)" + $support = Get-SupportStatusForPath $SubsystemPath + if ($null -ne $support) { Out "Поддержка: $support" } if ($synonym -and $synonym -ne $subName) { Out "Синоним: $synonym" } if ($commentText) { Out "Комментарий: $commentText" } Out "ВключатьВКомандныйИнтерфейс: $inclCI" diff --git a/.claude/skills/subsystem-info/scripts/subsystem-info.py b/.claude/skills/subsystem-info/scripts/subsystem-info.py index 73c5935e..6be82ca1 100644 --- a/.claude/skills/subsystem-info/scripts/subsystem-info.py +++ b/.claude/skills/subsystem-info/scripts/subsystem-info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-info v1.1 — Compact summary of 1C subsystem structure +# subsystem-info v1.2 — Compact summary of 1C subsystem structure # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -150,14 +150,29 @@ def get_support_status_for_path(target_path): except Exception: pass return None + def is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False rp = os.path.abspath(target_path) # The target file itself may be the element meta-xml (e.g. Subsystems/X.xml). elem_uuid = root_uuid(rp) + if is_external_root(rp): + return None bin_path = None d = os.path.dirname(rp) for _ in range(12): if not d: break + if is_external_root(d + ".xml"): + return None if not elem_uuid: elem_uuid = root_uuid(d + ".xml") if not bin_path: @@ -208,7 +223,9 @@ def get_support_status_for_path(target_path): def show_overview(sub_name, synonym, comment_text, incl_ci, use_one_cmd, explanation, pic_text, content_items, groups, child_names, has_ci): out(f"Подсистема: {sub_name}") - out(f"Поддержка: {get_support_status_for_path(subsystem_path)}") + _support = get_support_status_for_path(subsystem_path) + if _support is not None: + out(f"Поддержка: {_support}") if synonym and synonym != sub_name: out(f"Синоним: {synonym}") if comment_text: diff --git a/.claude/skills/template-add/scripts/add-template.ps1 b/.claude/skills/template-add/scripts/add-template.ps1 index e4b3cf6c..6addff85 100644 --- a/.claude/skills/template-add/scripts/add-template.ps1 +++ b/.claude/skills/template-add/scripts/add-template.ps1 @@ -1,4 +1,4 @@ -# template-add v1.7 — Add template to 1C object +# template-add v1.8 — Add template to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -38,6 +38,16 @@ function Get-RootUuid([string]$xmlPath) { } catch {} return $null } +function Test-ExternalObjectRoot([string]$xmlPath) { + if (-not (Test-Path $xmlPath)) { return $false } + try { + [xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8 + $el = $mx.DocumentElement.FirstChild + while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling } + if ($el) { return @('ExternalDataProcessor','ExternalReport') -contains $el.LocalName } + } catch {} + return $false +} function Find-V8Project([string]$startDir) { $d = $startDir for ($i = 0; $i -lt 20 -and $d; $i++) { @@ -74,10 +84,13 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) { try { $rp = $targetPath try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {} + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if (Test-ExternalObjectRoot $rp) { return } $elemUuid = Get-RootUuid $rp $cfgDir = $null; $binPath = $null $d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) } for ($i = 0; $i -lt 12 -and $d; $i++) { + if (Test-ExternalObjectRoot "$d.xml") { return } if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" } if (-not $cfgDir) { $cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin" diff --git a/.claude/skills/template-add/scripts/add-template.py b/.claude/skills/template-add/scripts/add-template.py index ae15edf1..dcaf132e 100644 --- a/.claude/skills/template-add/scripts/add-template.py +++ b/.claude/skills/template-add/scripts/add-template.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# add-template v1.7 — Add template to 1C object +# add-template v1.8 — Add template to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -34,6 +34,18 @@ def _sg_root_uuid(xml_path): return None +def _sg_is_external_root(xml_path): + if not os.path.isfile(xml_path): + return False + try: + mx = etree.parse(xml_path).getroot() + for child in mx: + if isinstance(child.tag, str): + return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport") + except Exception: + return False + return False + def _sg_find_v8project(start_dir): d = start_dir for _ in range(20): @@ -73,6 +85,9 @@ def _sg_get_edit_mode(cfg_dir): def assert_edit_allowed(target_path, require): try: rp = os.path.abspath(target_path) + # Autonomous external object (EPF/ERF): never part of a config on support (issue #39). + if _sg_is_external_root(rp): + return elem_uuid = _sg_root_uuid(rp) cfg_dir = None bin_path = None @@ -80,6 +95,8 @@ def assert_edit_allowed(target_path, require): for _ in range(12): if not d: break + if _sg_is_external_root(d + ".xml"): + return if not elem_uuid: elem_uuid = _sg_root_uuid(d + ".xml") if not cfg_dir: diff --git a/hooks/common/support-state.mjs b/hooks/common/support-state.mjs index 43fe3e77..734e3206 100644 --- a/hooks/common/support-state.mjs +++ b/hooks/common/support-state.mjs @@ -1,4 +1,4 @@ -// support-state.mjs v1.0 — decode 1C support state (Ext/ParentConfigurations.bin) for Claude Code hooks +// support-state.mjs v1.1 — decode 1C support state (Ext/ParentConfigurations.bin) for Claude Code hooks // Source: https://github.com/Nikolay-Shirokov/cc-1c-skills // // Canonical port of the in-skill guard Assert-EditAllowed / assert_edit_allowed @@ -13,6 +13,20 @@ import { readFileSync, existsSync, statSync } from 'node:fs'; import { dirname, join } from 'node:path'; const GUID_RE = /\buuid="([0-9a-fA-F-]{36})"/; +// Root child of an autonomous external object dump (EPF/ERF). Such an object is never +// part of a configuration on support, even when its dump sits inside the config tree — +// the climb must stop at this boundary instead of attributing it to the enclosing config. +const EXT_ROOT_RE = /]*>\s*<(?:\w+:)?(?:ExternalDataProcessor|ExternalReport)\b/; + +// True when xmlPath is the root file of an autonomous ExternalDataProcessor / ExternalReport. +export function isExternalObjectRoot(xmlPath) { + try { + if (!existsSync(xmlPath) || !statSync(xmlPath).isFile()) return false; + return EXT_ROOT_RE.test(readFileSync(xmlPath, 'utf8').slice(0, 1000)); + } catch { + return false; + } +} // First uuid="..." in an object XML == root element uuid (the wrapper // carries none), matching the reference's "first element child uuid" semantics. @@ -40,7 +54,11 @@ export function findConfigRoot(startPath) { } catch { d = dirname(startPath); } + // startPath itself may be the external object root file. + if (isExternalObjectRoot(startPath)) return { cfgDir: null, binPath: null, isExtension: false }; for (let i = 0; i < 12 && d; i++) { + // Crossed the boundary of an autonomous external object → not part of any config. + if (isExternalObjectRoot(d + '.xml')) return { cfgDir: null, binPath: null, isExtension: false }; const cand = join(d, 'Ext', 'ParentConfigurations.bin'); const cfgX = join(d, 'Configuration.xml'); if (existsSync(cand) || existsSync(cfgX)) { @@ -70,6 +88,9 @@ export function findConfigRoot(startPath) { export function decideSupport(targetPath, require = 'editable') { const result = { blocked: false, reason: '', code: null, cfgDir: null, targetPath }; try { + // Autonomous external object (EPF/ERF): its root is never part of a configuration on + // support, even when the dump sits inside the config tree — do not attribute it (issue #39). + if (isExternalObjectRoot(targetPath)) return result; let elemUuid = rootUuid(targetPath); // Walk up: collect elemUuid (from .xml of a sub-element) and the config root. let cfgDir = null, binPath = null; @@ -80,6 +101,8 @@ export function decideSupport(targetPath, require = 'editable') { d = dirname(targetPath); } for (let i = 0; i < 12 && d; i++) { + // Crossed the boundary of an autonomous external object → allow (not on support). + if (isExternalObjectRoot(d + '.xml')) return result; if (!elemUuid) elemUuid = rootUuid(d + '.xml'); if (!cfgDir) { const cand = join(d, 'Ext', 'ParentConfigurations.bin'); diff --git a/hooks/test/run.mjs b/hooks/test/run.mjs index f4358e77..e29e5884 100644 --- a/hooks/test/run.mjs +++ b/hooks/test/run.mjs @@ -4,7 +4,7 @@ // No live hook registration needed: exercises decideSupport / getEditMode / findConfigRoot // directly. Run: node hooks/test/run.mjs -import { decideSupport, findConfigRoot, rootUuid } from '../common/support-state.mjs'; +import { decideSupport, findConfigRoot, rootUuid, isExternalObjectRoot } from '../common/support-state.mjs'; import { getEditMode, getSuggesterMode } from '../common/project.mjs'; import { processInput as guard } from '../support-guard.mjs'; import { processInput as suggest } from '../skill-suggester.mjs'; @@ -96,6 +96,45 @@ console.log('=== support-state: synthetic per-object f1 (G=0) ==='); check('synth remove removed (f1=2) → NOT blocked', rmRemoved.blocked === false, JSON.stringify(rmRemoved)); } +console.log('=== support-state: external object boundary (issue #39) ==='); +{ + // Autonomous EPF/ERF parked INSIDE a config tree whose capability is off (G=1). The + // climb must stop at the external object's root and NOT attribute it to the config. + const ROOT = join(REPO, 'test-tmp', 'hooks-ext'); + const cat = '66666666-6666-6666-6666-666666666666'; + mkdirSync(join(ROOT, 'Ext'), { recursive: true }); + mkdirSync(join(ROOT, 'Catalogs'), { recursive: true }); + mkdirSync(join(ROOT, 'print-forms', 'Демо', 'Templates', 'Макет', 'Ext'), { recursive: true }); + // G=1 (capability off), K=1 — blocks every config object unconditionally. + const binText = `{6,1,1,aaaaaaaa-0000-0000-0000-000000000000,0,bbbbbbbb-0000-0000-0000-000000000000,` + + `"1.0","Vendor","Name",1,0,0,${cat}}`; + writeFileSync(join(ROOT, 'Ext', 'ParentConfigurations.bin'), + Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), Buffer.from(binText, 'utf8')])); + writeFileSync(join(ROOT, 'Configuration.xml'), + `\n`); + writeFileSync(join(ROOT, 'Catalogs', 'InConfig.xml'), + `\n`); + writeFileSync(join(ROOT, 'print-forms', 'Демо.xml'), + `\n\n\tДемо\n`); + writeFileSync(join(ROOT, 'print-forms', 'Демо', 'Templates', 'Макет', 'Ext', 'Template.xml'), + ``); + + const epfRoot = join(ROOT, 'print-forms', 'Демо.xml'); + const epfTpl = join(ROOT, 'print-forms', 'Демо', 'Templates', 'Макет', 'Ext', 'Template.xml'); + const cfgObj = join(ROOT, 'Catalogs', 'InConfig.xml'); + + check('isExternalObjectRoot(EPF root) → true', isExternalObjectRoot(epfRoot) === true); + check('isExternalObjectRoot(config Catalog) → false', isExternalObjectRoot(cfgObj) === false); + check('EPF root → NOT blocked (G=1 config ignored)', decideSupport(epfRoot, 'editable').blocked === false, JSON.stringify(decideSupport(epfRoot, 'editable'))); + const rTpl = decideSupport(epfTpl, 'editable'); + check('EPF template → NOT blocked (climb stops at EPF root)', rTpl.blocked === false, JSON.stringify(rTpl)); + const rCfg = decideSupport(cfgObj, 'editable'); + check('control: config object under G=1 → blocked', rCfg.blocked === true && rCfg.code === 'capability-off', JSON.stringify(rCfg)); + check('findConfigRoot(EPF template) → no cfgDir', findConfigRoot(epfTpl).cfgDir === null, JSON.stringify(findConfigRoot(epfTpl))); + const rGuard = guard({ tool_name: 'Edit', cwd: REPO, tool_input: { file_path: epfTpl } }); + check('guard on EPF template → allow (no stdout)', rGuard.stdout === '' && rGuard.exitCode === 0, JSON.stringify(rGuard)); +} + console.log('=== project: reaction modes ==='); { const m = getEditMode(ACC, REPO); diff --git a/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/Configuration.xml b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/Configuration.xml new file mode 100644 index 00000000..9651836d --- /dev/null +++ b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/Configuration.xml @@ -0,0 +1,2 @@ + +ТестКонфа diff --git a/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/Ext/ParentConfigurations.bin b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/Ext/ParentConfigurations.bin new file mode 100644 index 00000000..46cae23e --- /dev/null +++ b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/Ext/ParentConfigurations.bin @@ -0,0 +1 @@ +{6,1,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфа",1,0,0,cccccccc-cccc-cccc-cccc-cccccccccccc} \ No newline at end of file diff --git a/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/print-forms/Демо.xml b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/print-forms/Демо.xml new file mode 100644 index 00000000..539b8a57 --- /dev/null +++ b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/print-forms/Демо.xml @@ -0,0 +1,4 @@ + + + Демо + diff --git a/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/print-forms/Демо/Templates/Макет/Ext/Template.xml b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/print-forms/Демо/Templates/Макет/Ext/Template.xml new file mode 100644 index 00000000..c93a196d --- /dev/null +++ b/tests/skills/cases/mxl-compile/fixtures/epf-in-locked-config/print-forms/Демо/Templates/Макет/Ext/Template.xml @@ -0,0 +1,54 @@ + + + + ru + ru + + ru + Русский + Русский + + + + 1 + + + 0 + + + 0 + + 2 + + + ru + Значение + + + + + + + true + 1 + 1 + 1 + + Ячейка + + Rows + 0 + 0 + -1 + -1 + + + + + 10 + + + 0 + Text + + diff --git a/tests/skills/cases/mxl-compile/guard-allow-external.json b/tests/skills/cases/mxl-compile/guard-allow-external.json new file mode 100644 index 00000000..3da38dcd --- /dev/null +++ b/tests/skills/cases/mxl-compile/guard-allow-external.json @@ -0,0 +1,23 @@ +{ + "name": "Guard #39: автономная EPF внутри конфигурации на поддержке (G=1) НЕ блокируется", + "setup": "fixture:epf-in-locked-config", + "input": { + "columns": 2, + "areas": [ + { + "name": "О", + "rows": [ + { + "cells": [ + { + "col": 1, + "text": "a" + } + ] + } + ] + } + ] + }, + "outputPath": "print-forms/Демо/Templates/Макет/Ext/Template.xml" +} diff --git a/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/Configuration.xml b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/Configuration.xml new file mode 100644 index 00000000..9651836d --- /dev/null +++ b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/Configuration.xml @@ -0,0 +1,2 @@ + +ТестКонфа diff --git a/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/Ext/ParentConfigurations.bin b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/Ext/ParentConfigurations.bin new file mode 100644 index 00000000..46cae23e --- /dev/null +++ b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/Ext/ParentConfigurations.bin @@ -0,0 +1 @@ +{6,1,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфа",1,0,0,cccccccc-cccc-cccc-cccc-cccccccccccc} \ No newline at end of file diff --git a/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/print-forms/Демо.xml b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/print-forms/Демо.xml new file mode 100644 index 00000000..539b8a57 --- /dev/null +++ b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/print-forms/Демо.xml @@ -0,0 +1,4 @@ + + + Демо + diff --git a/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/print-forms/Демо/Templates/Макет/Ext/Template.xml b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/print-forms/Демо/Templates/Макет/Ext/Template.xml new file mode 100644 index 00000000..b85248b2 --- /dev/null +++ b/tests/skills/cases/mxl-compile/snapshots/guard-allow-external/print-forms/Демо/Templates/Макет/Ext/Template.xml @@ -0,0 +1,54 @@ + + + + ru + ru + + ru + Русский + Русский + + + + 2 + + + 0 + + + 0 + + 2 + + + ru + a + + + + + + + true + 1 + 1 + 1 + + О + + Rows + 0 + 0 + -1 + -1 + + + + + 10 + + + 0 + Text + + diff --git a/tests/skills/cases/mxl-info/external-omit-support.json b/tests/skills/cases/mxl-info/external-omit-support.json new file mode 100644 index 00000000..bf9353ea --- /dev/null +++ b/tests/skills/cases/mxl-info/external-omit-support.json @@ -0,0 +1,6 @@ +{ + "name": "Info #39: для автономной EPF строка «Поддержка:» не выводится", + "setup": "fixture:epf-in-locked-config", + "params": { "templatePath": "print-forms/Демо/Templates/Макет/Ext/Template.xml" }, + "expect": { "stdoutNotContains": "Поддержка:" } +} diff --git a/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/Configuration.xml b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/Configuration.xml new file mode 100644 index 00000000..9651836d --- /dev/null +++ b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/Configuration.xml @@ -0,0 +1,2 @@ + +ТестКонфа diff --git a/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/Ext/ParentConfigurations.bin b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/Ext/ParentConfigurations.bin new file mode 100644 index 00000000..46cae23e --- /dev/null +++ b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/Ext/ParentConfigurations.bin @@ -0,0 +1 @@ +{6,1,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфа",1,0,0,cccccccc-cccc-cccc-cccc-cccccccccccc} \ No newline at end of file diff --git a/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/print-forms/Демо.xml b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/print-forms/Демо.xml new file mode 100644 index 00000000..539b8a57 --- /dev/null +++ b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/print-forms/Демо.xml @@ -0,0 +1,4 @@ + + + Демо + diff --git a/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/print-forms/Демо/Templates/Макет/Ext/Template.xml b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/print-forms/Демо/Templates/Макет/Ext/Template.xml new file mode 100644 index 00000000..4ff772e3 --- /dev/null +++ b/tests/skills/cases/mxl-info/fixtures/epf-in-locked-config/print-forms/Демо/Templates/Макет/Ext/Template.xml @@ -0,0 +1,228 @@ + + + + ru + ru + + ru + Русский + Русский + + + + 5 + + + 0 + + + 0 + + 2 + ТекстЗаголовка + + + + + + 1 + + + 0 + + 3 + + + ru + Поставщик: + + + + + + 2 + + 2 + ПредставлениеПоставщика + Поставщик + + + + + + 2 + + + 0 + + 5 + НомерСтроки + + + + 1 + + 5 + Товар + Номенклатура + + + + 2 + + 6 + Количество + + + + 3 + + 6 + Цена + + + + 4 + + 6 + Сумма + + + + + + 3 + + + 3 + + 7 + + + ru + Итого: + + + + + + 4 + + 8 + Всего + + + + + true + 1 + 4 + 4 + + 0 + 0 + 4 + + + 1 + 0 + 1 + + + 1 + 2 + 2 + + + Заголовок + + Rows + 0 + 0 + -1 + -1 + + + + Поставщик + + Rows + 1 + 1 + -1 + -1 + + + + Строка + + Rows + 2 + 2 + -1 + -1 + + + + Итого + + Rows + 3 + 3 + -1 + -1 + + + + Solid + + + + + 10 + + + 0 + Parameter + + + 0 + Text + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + Parameter + + + 0 + 0 + 0 + 0 + 0 + Right + Parameter + + + 1 + 0 + Right + Text + + + 1 + 0 + Right + Parameter + + diff --git a/tests/skills/cases/mxl-info/snapshots/external-omit-support/Configuration.xml b/tests/skills/cases/mxl-info/snapshots/external-omit-support/Configuration.xml new file mode 100644 index 00000000..9651836d --- /dev/null +++ b/tests/skills/cases/mxl-info/snapshots/external-omit-support/Configuration.xml @@ -0,0 +1,2 @@ + +ТестКонфа diff --git a/tests/skills/cases/mxl-info/snapshots/external-omit-support/Ext/ParentConfigurations.bin b/tests/skills/cases/mxl-info/snapshots/external-omit-support/Ext/ParentConfigurations.bin new file mode 100644 index 00000000..46cae23e --- /dev/null +++ b/tests/skills/cases/mxl-info/snapshots/external-omit-support/Ext/ParentConfigurations.bin @@ -0,0 +1 @@ +{6,1,1,aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,0,bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb,"1.0","ТестВендор","ТестКонфа",1,0,0,cccccccc-cccc-cccc-cccc-cccccccccccc} \ No newline at end of file diff --git a/tests/skills/cases/mxl-info/snapshots/external-omit-support/print-forms/Демо.xml b/tests/skills/cases/mxl-info/snapshots/external-omit-support/print-forms/Демо.xml new file mode 100644 index 00000000..539b8a57 --- /dev/null +++ b/tests/skills/cases/mxl-info/snapshots/external-omit-support/print-forms/Демо.xml @@ -0,0 +1,4 @@ + + + Демо + diff --git a/tests/skills/cases/mxl-info/snapshots/external-omit-support/print-forms/Демо/Templates/Макет/Ext/Template.xml b/tests/skills/cases/mxl-info/snapshots/external-omit-support/print-forms/Демо/Templates/Макет/Ext/Template.xml new file mode 100644 index 00000000..4ff772e3 --- /dev/null +++ b/tests/skills/cases/mxl-info/snapshots/external-omit-support/print-forms/Демо/Templates/Макет/Ext/Template.xml @@ -0,0 +1,228 @@ + + + + ru + ru + + ru + Русский + Русский + + + + 5 + + + 0 + + + 0 + + 2 + ТекстЗаголовка + + + + + + 1 + + + 0 + + 3 + + + ru + Поставщик: + + + + + + 2 + + 2 + ПредставлениеПоставщика + Поставщик + + + + + + 2 + + + 0 + + 5 + НомерСтроки + + + + 1 + + 5 + Товар + Номенклатура + + + + 2 + + 6 + Количество + + + + 3 + + 6 + Цена + + + + 4 + + 6 + Сумма + + + + + + 3 + + + 3 + + 7 + + + ru + Итого: + + + + + + 4 + + 8 + Всего + + + + + true + 1 + 4 + 4 + + 0 + 0 + 4 + + + 1 + 0 + 1 + + + 1 + 2 + 2 + + + Заголовок + + Rows + 0 + 0 + -1 + -1 + + + + Поставщик + + Rows + 1 + 1 + -1 + -1 + + + + Строка + + Rows + 2 + 2 + -1 + -1 + + + + Итого + + Rows + 3 + 3 + -1 + -1 + + + + Solid + + + + + 10 + + + 0 + Parameter + + + 0 + Text + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + Parameter + + + 0 + 0 + 0 + 0 + 0 + Right + Parameter + + + 1 + 0 + Right + Text + + + 1 + 0 + Right + Parameter + +