diff --git a/.claude/skills/cf-validate/scripts/cf-validate.ps1 b/.claude/skills/cf-validate/scripts/cf-validate.ps1
index 6e903ab6d..58424cc76 100644
--- a/.claude/skills/cf-validate/scripts/cf-validate.ps1
+++ b/.claude/skills/cf-validate/scripts/cf-validate.ps1
@@ -1,4 +1,4 @@
-# cf-validate v1.10 — Validate 1C configuration root structure
+# cf-validate v1.11 — Validate 1C configuration root structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -103,6 +103,21 @@ function Get-FormatRank([string]$ver) {
return 0
}
+# Штамп версии формата — атрибут version КОРНЕВОГО элемента файла. Копия общего эталона (семья
+# root_version, авторитет — meta-validate).
+function Get-RootVersion([string]$xmlPath) {
+ if (-not (Test-Path -LiteralPath $xmlPath -PathType Leaf)) { return $null }
+ $buf = New-Object byte[] 4096
+ $fs = [System.IO.File]::OpenRead($xmlPath)
+ try { $len = $fs.Read($buf, 0, $buf.Length) } finally { $fs.Dispose() }
+ $head = [System.Text.Encoding]::UTF8.GetString($buf, 0, $len)
+ $m = [regex]::Match($head, '<[A-Za-z_][\w.:-]*(\s[^>]*)?/?>')
+ if (-not $m.Success) { return $null }
+ $v = [regex]::Match($m.Groups[1].Value, '(?:^|\s)version="([^"]*)"')
+ if ($v.Success) { return $v.Groups[1].Value }
+ return $null
+}
+
# --- Reference tables ---
$guidPattern = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
$identPattern = '^[A-Za-z\u0410-\u042F\u0401\u0430-\u044F\u0451_][A-Za-z0-9\u0410-\u042F\u0401\u0430-\u044F\u0451_]*$'
@@ -623,6 +638,28 @@ if ($formRefsChecked -eq 0) {
foreach ($err in $formRefErrors) { Report-Error "9. $err" }
}
+# --- Check 10: тела конфигурации Ext/*.xml в версии Configuration.xml ---
+# Конфигурация для платформы — такой же объект, как остальные: Configuration.xml и штампованные тела
+# Ext/*.xml (CommandInterface, HomePageWorkArea, Splash, …) загружаются только в одной версии формата
+# («Версия формата загружаемого файла … отличается от версии формата ранее загруженных файлов»).
+$cfgExtDir = Join-Path $configDir "Ext"
+$cfgBodiesOk = 0
+$cfgBodyErrors = 0
+if ($version -and (Test-Path $cfgExtDir -PathType Container)) {
+ $bodyNames = @(Get-ChildItem $cfgExtDir -Filter "*.xml" -File | ForEach-Object { $_.Name })
+ [Array]::Sort($bodyNames, [StringComparer]::Ordinal)
+ foreach ($bn in $bodyNames) {
+ $bodyVer = Get-RootVersion (Join-Path $cfgExtDir $bn)
+ if (-not $bodyVer) { continue }
+ if ($bodyVer -eq $version) { $cfgBodiesOk++; continue }
+ $cfgBodyErrors++
+ Report-Error "10. Ext/$bn is stamped $bodyVer, Configuration.xml $version — the platform refuses to load parts of one object in different formats"
+ }
+}
+if ($cfgBodyErrors -eq 0 -and $cfgBodiesOk -gt 0) {
+ Report-OK "10. Format version: $cfgBodiesOk stamped Ext part(s) agree with Configuration.xml"
+}
+
# --- Final output ---
& $finalize
diff --git a/.claude/skills/cf-validate/scripts/cf-validate.py b/.claude/skills/cf-validate/scripts/cf-validate.py
index 04c71dfef..c734b040f 100644
--- a/.claude/skills/cf-validate/scripts/cf-validate.py
+++ b/.claude/skills/cf-validate/scripts/cf-validate.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# cf-validate v1.10 — Validate 1C configuration XML structure
+# cf-validate v1.11 — Validate 1C configuration XML structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
"""Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages."""
import sys, os, argparse, re
@@ -148,6 +148,22 @@ def format_rank(ver):
return int(m.group(1)) * 100 + int(m.group(2)) if m else 0
+# Штамп версии формата — атрибут version КОРНЕВОГО элемента файла. Копия общего эталона (семья
+# root_version, авторитет — meta-validate).
+def root_version(xml_path):
+ if not os.path.isfile(xml_path):
+ return None
+ with open(xml_path, "rb") as f:
+ head = f.read(4096).decode("utf-8", errors="ignore")
+ m = re.search(r'<[A-Za-z_][\w.:-]*(\s[^>]*)?/?>', head)
+ if not m:
+ return None
+ v = re.search(r'(?:^|\s)version="([^"]*)"', m.group(1) or "")
+ if v:
+ return v.group(1)
+ return None
+
+
class Reporter:
def __init__(self, max_errors, detailed=False):
self.errors = 0
@@ -636,6 +652,29 @@ def main():
for err in form_ref_errors:
r.error(f'9. {err}')
+ # --- Check 10: тела конфигурации Ext/*.xml в версии Configuration.xml ---
+ # Конфигурация для платформы — такой же объект, как остальные: Configuration.xml и штампованные тела
+ # Ext/*.xml (CommandInterface, HomePageWorkArea, Splash, …) загружаются только в одной версии формата
+ # («Версия формата загружаемого файла … отличается от версии формата ранее загруженных файлов»).
+ cfg_ext_dir = os.path.join(config_dir, 'Ext')
+ cfg_bodies_ok = 0
+ cfg_body_errors = 0
+ if version and os.path.isdir(cfg_ext_dir):
+ body_names = sorted(n for n in os.listdir(cfg_ext_dir)
+ if n.lower().endswith('.xml') and os.path.isfile(os.path.join(cfg_ext_dir, n)))
+ for bn in body_names:
+ body_ver = root_version(os.path.join(cfg_ext_dir, bn))
+ if not body_ver:
+ continue
+ if body_ver == version:
+ cfg_bodies_ok += 1
+ continue
+ cfg_body_errors += 1
+ r.error(f'10. Ext/{bn} is stamped {body_ver}, Configuration.xml {version} '
+ '— the platform refuses to load parts of one object in different formats')
+ if cfg_body_errors == 0 and cfg_bodies_ok > 0:
+ r.ok(f'10. Format version: {cfg_bodies_ok} stamped Ext part(s) agree with Configuration.xml')
+
# --- Final output ---
r.finalize(out_file)
sys.exit(1 if r.errors > 0 else 0)
diff --git a/tests/skills/cases/cf-validate/error-version-ext-mismatch.json b/tests/skills/cases/cf-validate/error-version-ext-mismatch.json
new file mode 100644
index 000000000..02e1ef5ff
--- /dev/null
+++ b/tests/skills/cases/cf-validate/error-version-ext-mismatch.json
@@ -0,0 +1,8 @@
+{
+ "name": "HomePageWorkArea.xml 2.18 при Configuration.xml 2.20 — ошибка: платформа такую конфигурацию не загрузит",
+ "setup": "fixture:version-ext-mismatch",
+ "expectError": true,
+ "noSnapshot": "cf-validate только читает и печатает — эталон зафиксировал бы фикстуру, а не выход проверяемого навыка; проверяется stdout",
+ "expect": { "stdoutContains": ["[ERROR] 10. Ext/HomePageWorkArea.xml is stamped 2.18, Configuration.xml 2.20"] },
+ "skipPlatformVerify": "фикстура намеренно не загружается: Configuration.xml и его тело в разных версиях формата"
+}
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Configuration.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Configuration.xml
new file mode 100644
index 000000000..5dbd6cb90
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Configuration.xml
@@ -0,0 +1,255 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ 36197842-3924-4ed9-af58-a000c60e538f
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ 5aee8ff0-4d4a-4bf1-bb50-4b4054bbb288
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 075f7faa-ceb1-4098-ac29-a4c11d4dd7a6
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ ff1dfda3-e856-49eb-afe8-e7f6dce55e16
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 71e0983f-f59b-439a-954a-7e2494108760
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 62b34336-f570-44f7-94e9-3016b5237ec9
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 66dfac93-ffbe-4b12-83cf-9ab0ed080cfa
+
+
+
+ ПроверкаВерсий
+
+
+ ru
+ ПроверкаВерсий
+
+
+
+
+ Version8_3_27
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+ TextToSpeech
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_27
+
+
+
+ Русский
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Ext/ClientApplicationInterface.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Ext/ClientApplicationInterface.xml
new file mode 100644
index 000000000..ff30bfe90
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ cbab57f2-a0f3-4f0a-89ea-4cb19570ab75
+
+
+
+
+ b553047f-c9aa-4157-978d-448ecad24248
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Ext/HomePageWorkArea.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Ext/HomePageWorkArea.xml
new file mode 100644
index 000000000..7213f1590
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Ext/HomePageWorkArea.xml
@@ -0,0 +1,6 @@
+
+
+ TwoColumnsEqualWidth
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Languages/Русский.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Languages/Русский.xml
new file mode 100644
index 000000000..dacbaac10
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-agree/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Configuration.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Configuration.xml
new file mode 100644
index 000000000..5dbd6cb90
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Configuration.xml
@@ -0,0 +1,255 @@
+
+
+
+
+
+ 9cd510cd-abfc-11d4-9434-004095e12fc7
+ 36197842-3924-4ed9-af58-a000c60e538f
+
+
+ 9fcd25a0-4822-11d4-9414-008048da11f9
+ 5aee8ff0-4d4a-4bf1-bb50-4b4054bbb288
+
+
+ e3687481-0a87-462c-a166-9f34594f9bba
+ 075f7faa-ceb1-4098-ac29-a4c11d4dd7a6
+
+
+ 9de14907-ec23-4a07-96f0-85521cb6b53b
+ ff1dfda3-e856-49eb-afe8-e7f6dce55e16
+
+
+ 51f2d5d8-ea4d-4064-8892-82951750031e
+ 71e0983f-f59b-439a-954a-7e2494108760
+
+
+ e68182ea-4237-4383-967f-90c1e3370bc7
+ 62b34336-f570-44f7-94e9-3016b5237ec9
+
+
+ fb282519-d103-4dd3-bc12-cb271d631dfc
+ 66dfac93-ffbe-4b12-83cf-9ab0ed080cfa
+
+
+
+ ПроверкаВерсий
+
+
+ ru
+ ПроверкаВерсий
+
+
+
+
+ Version8_3_27
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+ TextToSpeech
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_27
+
+
+
+ Русский
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Ext/ClientApplicationInterface.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Ext/ClientApplicationInterface.xml
new file mode 100644
index 000000000..ff30bfe90
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ cbab57f2-a0f3-4f0a-89ea-4cb19570ab75
+
+
+
+
+ b553047f-c9aa-4157-978d-448ecad24248
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Ext/HomePageWorkArea.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Ext/HomePageWorkArea.xml
new file mode 100644
index 000000000..9bc35483a
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Ext/HomePageWorkArea.xml
@@ -0,0 +1,6 @@
+
+
+ TwoColumnsEqualWidth
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Languages/Русский.xml b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Languages/Русский.xml
new file mode 100644
index 000000000..dacbaac10
--- /dev/null
+++ b/tests/skills/cases/cf-validate/fixtures/version-ext-mismatch/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cf-validate/valid-version-ext-agree.json b/tests/skills/cases/cf-validate/valid-version-ext-agree.json
new file mode 100644
index 000000000..fb43e746c
--- /dev/null
+++ b/tests/skills/cases/cf-validate/valid-version-ext-agree.json
@@ -0,0 +1,6 @@
+{
+ "name": "Тела конфигурации Ext/*.xml в версии Configuration.xml — чисто",
+ "setup": "fixture:version-ext-agree",
+ "noSnapshot": "cf-validate только читает и печатает — эталон зафиксировал бы фикстуру, а не выход проверяемого навыка; проверяется stdout",
+ "expect": { "stdoutContains": ["=== Validation OK"] }
+}
diff --git a/tests/skills/check-inline-drift.mjs b/tests/skills/check-inline-drift.mjs
index 43c9eedad..99e25150c 100644
--- a/tests/skills/check-inline-drift.mjs
+++ b/tests/skills/check-inline-drift.mjs
@@ -130,7 +130,7 @@ const FAMILIES = [
{
name: 'root_version', py: 'root_version', ps1: 'Get-RootVersion',
variants: [
- { id: 'base', authority: 'meta-validate', consumers: ['form-validate'] },
+ { id: 'base', authority: 'meta-validate', consumers: ['cf-validate', 'form-validate'] },
],
},
{