From e229fc487384f7d6bb900749a4cff36e06cf78b2 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Tue, 10 Feb 2026 13:29:50 +0300 Subject: [PATCH] Auto-register role in Configuration.xml role-compile: after generating files, automatically inserts Name into Configuration.xml ChildObjects (idempotent). role-validate: checks that the role is registered, warns if not. Co-Authored-By: Claude Opus 4.6 --- .claude/skills/role-compile/SKILL.md | 2 +- .../role-compile/scripts/role-compile.ps1 | 78 ++++++++++++++++++- .../role-validate/scripts/role-validate.ps1 | 50 +++++++++++- 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/.claude/skills/role-compile/SKILL.md b/.claude/skills/role-compile/SKILL.md index afcf83b9..03e473ec 100644 --- a/.claude/skills/role-compile/SKILL.md +++ b/.claude/skills/role-compile/SKILL.md @@ -24,7 +24,7 @@ allowed-tools: powershell.exe -NoProfile -File .claude\skills\role-compile\scripts\role-compile.ps1 -JsonPath "" -OutputDir "" ``` -После генерации: добавить `ИмяРоли` в `` файла `Configuration.xml`. +`ИмяРоли` автоматически добавляется в `` файла `Configuration.xml` (ожидается в parent от `RolesDir`). ## JSON DSL diff --git a/.claude/skills/role-compile/scripts/role-compile.ps1 b/.claude/skills/role-compile/scripts/role-compile.ps1 index 32e2db71..83e08de9 100644 --- a/.claude/skills/role-compile/scripts/role-compile.ps1 +++ b/.claude/skills/role-compile/scripts/role-compile.ps1 @@ -628,10 +628,86 @@ $enc = New-Object System.Text.UTF8Encoding($true) [System.IO.File]::WriteAllText($metadataPath, $metadataXml, $enc) [System.IO.File]::WriteAllText($rightsPath, $rightsXml, $enc) -# --- 12. Summary --- +# --- 12. Register in Configuration.xml --- + +$configDir = Split-Path $outDir -Parent +$configXmlPath = Join-Path $configDir "Configuration.xml" +$regResult = $null + +if (Test-Path $configXmlPath) { + $configDoc = New-Object System.Xml.XmlDocument + $configDoc.PreserveWhitespace = $true + $configDoc.Load($configXmlPath) + + $nsMgr = New-Object System.Xml.XmlNamespaceManager($configDoc.NameTable) + $nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses") + + $childObjects = $configDoc.SelectSingleNode("//md:Configuration/md:ChildObjects", $nsMgr) + if ($childObjects) { + $existing = $childObjects.SelectNodes("md:Role", $nsMgr) + $alreadyExists = $false + foreach ($r in $existing) { + if ($r.InnerText -eq $roleName) { + $alreadyExists = $true + break + } + } + + if ($alreadyExists) { + $regResult = "already" + } else { + $roleElem = $configDoc.CreateElement("Role", "http://v8.1c.ru/8.3/MDClasses") + $roleElem.InnerText = $roleName + + if ($existing.Count -gt 0) { + # Insert after last existing + $lastRole = $existing[$existing.Count - 1] + $newWs = $configDoc.CreateWhitespace("`n`t`t`t") + $childObjects.InsertAfter($newWs, $lastRole) | Out-Null + $childObjects.InsertAfter($roleElem, $newWs) | Out-Null + } else { + # No existing roles — insert before closing whitespace + $lastChild = $childObjects.LastChild + if ($lastChild.NodeType -eq [System.Xml.XmlNodeType]::Whitespace) { + $newWs = $configDoc.CreateWhitespace("`n`t`t`t") + $childObjects.InsertBefore($newWs, $lastChild) | Out-Null + $childObjects.InsertBefore($roleElem, $lastChild) | Out-Null + } else { + $childObjects.AppendChild($configDoc.CreateWhitespace("`n`t`t`t")) | Out-Null + $childObjects.AppendChild($roleElem) | Out-Null + $childObjects.AppendChild($configDoc.CreateWhitespace("`n`t`t")) | Out-Null + } + } + + # Save + $cfgSettings = New-Object System.Xml.XmlWriterSettings + $cfgSettings.Encoding = New-Object System.Text.UTF8Encoding($true) + $cfgSettings.Indent = $false + $stream = New-Object System.IO.FileStream($configXmlPath, [System.IO.FileMode]::Create) + $writer = [System.Xml.XmlWriter]::Create($stream, $cfgSettings) + $configDoc.Save($writer) + $writer.Close() + $stream.Close() + + $regResult = "added" + } + } else { + $regResult = "no-childobj" + } +} else { + $regResult = "no-config" +} + +# --- 13. Summary --- Write-Host "[OK] Role '$roleName' compiled" Write-Host " UUID: $uuid" Write-Host " Metadata: $metadataPath" Write-Host " Rights: $rightsPath" Write-Host " Objects: $($parsedObjects.Count), Rights: $totalRights, Templates: $templateCount" +switch ($regResult) { + "added" { Write-Host " Configuration.xml: $roleName added to ChildObjects" } + "already" { Write-Host " Configuration.xml: $roleName already registered" } + "no-childobj" { Write-Warning "Configuration.xml found but not found" } + "no-config" { Write-Warning "Configuration.xml not found at $configXmlPath — register manually" } +} diff --git a/.claude/skills/role-validate/scripts/role-validate.ps1 b/.claude/skills/role-validate/scripts/role-validate.ps1 index a9eacc44..ccad6b59 100644 --- a/.claude/skills/role-validate/scripts/role-validate.ps1 +++ b/.claude/skills/role-validate/scripts/role-validate.ps1 @@ -401,7 +401,55 @@ if ($MetadataPath) { } } -# --- 5. Summary --- +# --- 5. Check registration in Configuration.xml --- + +# Infer paths: RightsPath = .../Roles/Name/Ext/Rights.xml +$extDir2 = Split-Path (Resolve-Path $RightsPath).Path -Parent +$roleDir2 = Split-Path $extDir2 -Parent +$rolesDir2 = Split-Path $roleDir2 -Parent +$configDir2 = Split-Path $rolesDir2 -Parent +$configXmlPath2 = Join-Path $configDir2 "Configuration.xml" +$inferredRoleName = Split-Path $roleDir2 -Leaf + +# Use metadata name if available +if ($MetadataPath -and (Test-Path $MetadataPath)) { + try { + [xml]$metaXml2 = Get-Content -Path $MetadataPath -Encoding UTF8 + $nameNode2 = $metaXml2.DocumentElement.SelectSingleNode("//*[local-name()='Role']//*[local-name()='Name']") + if ($nameNode2 -and $nameNode2.InnerText) { + $inferredRoleName = $nameNode2.InnerText + } + } catch { } +} + +if (Test-Path $configXmlPath2) { + $script:lines += "" + try { + [xml]$cfgXml = Get-Content -Path $configXmlPath2 -Encoding UTF8 + $cfgNs = New-Object System.Xml.XmlNamespaceManager($cfgXml.NameTable) + $cfgNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses") + $childObj = $cfgXml.SelectSingleNode("//md:Configuration/md:ChildObjects", $cfgNs) + if ($childObj) { + $roleNodes = $childObj.SelectNodes("md:Role", $cfgNs) + $found = $false + foreach ($rn in $roleNodes) { + if ($rn.InnerText -eq $inferredRoleName) { + $found = $true + break + } + } + if ($found) { + Out-OK "Configuration.xml: $inferredRoleName registered" + } else { + Out-WARN "Configuration.xml: $inferredRoleName NOT found in ChildObjects" + } + } + } catch { + Out-WARN "Configuration.xml: parse error — $($_.Exception.Message)" + } +} + +# --- 6. Summary --- $script:lines += "---" $script:lines += "Result: $($script:errors) error(s), $($script:warnings) warning(s)"