From ca328e3e8f94225445c9074a4f2c092d08769685 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 7 Mar 2026 22:00:37 +0300 Subject: [PATCH] feat(meta-validate): add cross-object register-registrar check Detect configDir by walking up from object path to find Configuration.xml. For AccumulationRegister, AccountingRegister, CalculationRegister, and InformationRegister (RecorderSubordinate) scan Documents/*.xml to verify at least one document references the register in RegisterRecords. Warn if no registrar found. Co-Authored-By: Claude Opus 4.6 --- .../meta-validate/scripts/meta-validate.ps1 | 45 +++++++++++++++++++ .../meta-validate/scripts/meta-validate.py | 41 +++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/.claude/skills/meta-validate/scripts/meta-validate.ps1 b/.claude/skills/meta-validate/scripts/meta-validate.ps1 index ed26a2a6..96bce120 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.ps1 +++ b/.claude/skills/meta-validate/scripts/meta-validate.ps1 @@ -54,6 +54,19 @@ if (-not (Test-Path $ObjectPath)) { $resolvedPath = (Resolve-Path $ObjectPath).Path +# --- Detect config directory (for cross-object checks) --- + +$script:configDir = $null +$probe = Split-Path $resolvedPath +for ($depth = 0; $depth -lt 4; $depth++) { + if (-not $probe) { break } + if (Test-Path (Join-Path $probe "Configuration.xml")) { + $script:configDir = $probe + break + } + $probe = Split-Path $probe +} + # --- Output infrastructure --- $script:errors = 0 @@ -990,6 +1003,38 @@ if ($propsNode) { } } } + + # Register: must have at least one registrar document + $registerTypes = @("AccumulationRegister","AccountingRegister","CalculationRegister","InformationRegister") + if ($registerTypes -contains $mdType -and $script:configDir -and $objName -ne "(unknown)") { + $needsRegistrar = $true + # InformationRegister with WriteMode=Independent does not need a registrar + if ($mdType -eq "InformationRegister") { + $writeMode = $propsNode.SelectSingleNode("md:WriteMode", $ns) + if (-not $writeMode -or $writeMode.InnerText -ne "RecorderSubordinate") { + $needsRegistrar = $false + } + } + if ($needsRegistrar) { + $regRef = "$mdType.$objName" + $docsDir = Join-Path $script:configDir "Documents" + $hasRegistrar = $false + if (Test-Path $docsDir) { + $docXmls = Get-ChildItem $docsDir -Filter "*.xml" -File -ErrorAction SilentlyContinue + foreach ($docXml in $docXmls) { + $content = [System.IO.File]::ReadAllText($docXml.FullName, [System.Text.Encoding]::UTF8) + if ($content.Contains($regRef)) { + $hasRegistrar = $true + break + } + } + } + if (-not $hasRegistrar) { + Report-Warn "10. $mdType`: no registrar document found (none references '$regRef' in RegisterRecords)" + $check10Issues++ + } + } + } } if ($check10Ok -and $check10Issues -eq 0) { diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py index 7bf07bf1..a98a3429 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.py +++ b/.claude/skills/meta-validate/scripts/meta-validate.py @@ -59,6 +59,18 @@ if not os.path.exists(object_path): resolved_path = os.path.abspath(object_path) +# ── detect config directory (for cross-object checks) ──────── + +config_dir = None +probe = os.path.dirname(resolved_path) +for _ in range(4): + if not probe: + break + if os.path.exists(os.path.join(probe, "Configuration.xml")): + config_dir = probe + break + probe = os.path.dirname(probe) + # ── output infrastructure ──────────────────────────────────── errors = 0 @@ -934,6 +946,35 @@ if props_node is not None: check10_issues += 1 print('[HINT] /meta-edit -Operation modify-property -Value "ExtDimensionTypes=ChartOfCharacteristicTypes.XXX"') + # Register: must have at least one registrar document + register_types = ('AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'InformationRegister') + if md_type in register_types and config_dir and obj_name != '(unknown)': + needs_registrar = True + # InformationRegister with WriteMode=Independent does not need a registrar + if md_type == 'InformationRegister': + write_mode = find(props_node, 'md:WriteMode') + if write_mode is None or inner_text(write_mode) != 'RecorderSubordinate': + needs_registrar = False + if needs_registrar: + reg_ref = f'{md_type}.{obj_name}' + docs_dir = os.path.join(config_dir, 'Documents') + has_registrar = False + if os.path.isdir(docs_dir): + for fname in os.listdir(docs_dir): + if not fname.endswith('.xml'): + continue + fpath = os.path.join(docs_dir, fname) + if not os.path.isfile(fpath): + continue + with open(fpath, 'r', encoding='utf-8-sig') as f: + content = f.read() + if reg_ref in content: + has_registrar = True + break + if not has_registrar: + report_warn(f"10. {md_type}: no registrar document found (none references '{reg_ref}' in RegisterRecords)") + check10_issues += 1 + if check10_ok and check10_issues == 0: report_ok("10. Cross-property consistency")