diff --git a/.claude/skills/cfe-patch-method/SKILL.md b/.claude/skills/cfe-patch-method/SKILL.md
index 2d355c2bd..3cc4915cb 100644
--- a/.claude/skills/cfe-patch-method/SKILL.md
+++ b/.claude/skills/cfe-patch-method/SKILL.md
@@ -88,7 +88,7 @@ allowed-tools:
Правила:
- Маркеры — на **отдельной строке с 0-й колонки** (без отступа), даже внутри отступов и текста запроса (`|…`).
-- **Незамеченные (unmarked) строки должны совпадать с оригиналом дословно** — это и есть «контроль». Если оригинал в конфигурации-источнике изменится, unmarked-контекст разойдётся → метод потребует актуализации (см. ниже; проверить пачкой — `-Check`).
+- **Незамеченные (unmarked) строки должны совпадать с оригиналом дословно** — это и есть «контроль». Дословно — включая комментарии, регистр и пробелы внутри строки (`Х = Х + 1` ≠ `Х=Х+1`); свободны только отступ и пустые строки. Если оригинал в конфигурации-источнике изменится, unmarked-контекст разойдётся → метод потребует актуализации (см. ниже; проверить пачкой — `-Check`).
- Меняешь только свои `#Вставка`/`#Удаление`; чужой оригинал не трогай.
## Актуализация
diff --git a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1
index 069e9a45a..30e0f5567 100644
--- a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1
+++ b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1
@@ -1,4 +1,4 @@
-# cfe-patch-method v2.9 — Source-aware method interceptor for 1C extension (CFE)
+# cfe-patch-method v2.10 — Source-aware method interceptor for 1C extension (CFE)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -362,6 +362,14 @@ function Get-Normalized {
return (($line -replace '\s+', ' ').Trim())
}
+# Control comparison key, as the platform compares a &ИзменениеИКонтроль copy with the original:
+# each line trimmed, blank lines dropped, everything else byte-for-byte and case-sensitive
+# (inner spaces, comments and letter case are significant). Measured on 8.3.24 and 8.3.27.
+function Get-ControlKey {
+ param($lines)
+ return (@($lines | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }) -join "`n")
+}
+
# Reconstruct v1 body and edit ops from a marked body
function Parse-MarkedBody {
param($bodyLines)
@@ -651,7 +659,7 @@ function Invoke-Resync {
$v1norm = @($v1 | ForEach-Object { Get-Normalized $_ })
$v2norm = @($v2 | ForEach-Object { Get-Normalized $_ })
- if (($v1norm -join "`n") -eq ($v2norm -join "`n")) {
+ if ([string]::Equals((Get-ControlKey $v1), (Get-ControlKey $v2), 'Ordinal')) {
return @{ Id = $methodId; Status = 'АКТУАЛЕН'; ExtBsl = $extBsl }
}
diff --git a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py
index e7cfc3461..8fbacef1e 100644
--- a/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py
+++ b/.claude/skills/cfe-patch-method/scripts/cfe-patch-method.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# cfe-patch-method v2.9 — Source-aware method interceptor for 1C extension (CFE)
+# cfe-patch-method v2.10 — Source-aware method interceptor for 1C extension (CFE)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -491,6 +491,13 @@ def normalize(line):
return re.sub(r'\s+', ' ', line).strip()
+# Control comparison key, as the platform compares a &ИзменениеИКонтроль copy with the original:
+# each line trimmed, blank lines dropped, everything else byte-for-byte and case-sensitive
+# (inner spaces, comments and letter case are significant). Measured on 8.3.24 and 8.3.27.
+def control_key(lines):
+ return "\n".join([k for k in (x.strip() for x in lines) if k != ""])
+
+
def parse_marked_body(body_lines):
v1 = []
ops = []
@@ -1146,7 +1153,7 @@ def resync_one(ext_bsl, ext_lines, dup, method, logical_module, conflict_folder,
v1norm = [normalize(x) for x in v1]
v2norm = [normalize(x) for x in v2]
- if "\n".join(v1norm) == "\n".join(v2norm):
+ if control_key(v1) == control_key(v2):
return {"id": method_id, "status": "АКТУАЛЕН", "ext_bsl": ext_bsl}
insert_top = []; insert_after = {}; del_start = set(); del_end = set(); disputed = []; transferred = 0; absorbed = 0; absorbed_notes = []
diff --git a/tests/skills/cases/cfe-patch-method/check-blankskew.json b/tests/skills/cases/cfe-patch-method/check-blankskew.json
new file mode 100644
index 000000000..e6062b3db
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/check-blankskew.json
@@ -0,0 +1,55 @@
+{
+ "name": "-Check: контекст отличается только пустыми строками, отступом и хвостовыми пробелами — актуален, как у платформы",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "CommonModule",
+ "name": "БатчМод",
+ "context": "server"
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "CommonModules/БатчМод/Ext/Module.bsl",
+ "content": "#Область ПрограммныйИнтерфейс\n\nФункция РасчётА() Экспорт\n\t\n\tХ = 1;\n\t\n\tВозврат Х;\n\t\nКонецФункции\n\nФункция РасчётБ() Экспорт\n\tY = 2;\n\n\tВозврат Y;\nКонецФункции\n\n#КонецОбласти\n"
+ }
+ },
+ {
+ "script": "cfe-init/scripts/cfe-init",
+ "args": {
+ "-Name": "Тест",
+ "-OutputDir": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}"
+ }
+ },
+ {
+ "script": "cfe-borrow/scripts/cfe-borrow",
+ "args": {
+ "-ExtensionPath": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}",
+ "-Object": "CommonModule.БатчМод"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "cfe/CommonModules/БатчМод/Ext/Module.bsl",
+ "content": "#Область ПрограммныйИнтерфейс\n&ИзменениеИКонтроль(\"РасчётА\")\nФункция Тест_РасчётА()\n\n\tХ = 1;\n#Вставка\n\tХ = Х + 1;\n#КонецВставки\n\n\t\t\tВозврат Х; \nКонецФункции\n&ИзменениеИКонтроль(\"РасчётБ\")\nФункция Тест_РасчётБ()\n\tY = 2;\n\tВозврат Y;\nКонецФункции\n#КонецОбласти\n"
+ }
+ }
+ ],
+ "params": {
+ "extensionPath": "cfe"
+ },
+ "args_extra": [
+ "-Check"
+ ],
+ "expect": {
+ "stdoutContains": "2/2 актуальны",
+ "stdoutNotContains": "ДРЕЙФ"
+ }
+}
diff --git a/tests/skills/cases/cfe-patch-method/check-case-drift.json b/tests/skills/cases/cfe-patch-method/check-case-drift.json
new file mode 100644
index 000000000..71d3d5fb8
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/check-case-drift.json
@@ -0,0 +1,55 @@
+{
+ "name": "-Check: контекст отличается регистром идентификатора — дрейф, как у платформы",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "CommonModule",
+ "name": "БатчМод",
+ "context": "server"
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "CommonModules/БатчМод/Ext/Module.bsl",
+ "content": "#Область ПрограммныйИнтерфейс\n\nФункция РасчётА() Экспорт\n\t\n\tХ = 1;\n\t\n\tВозврат Х;\n\t\nКонецФункции\n\nФункция РасчётБ() Экспорт\n\tY = 2;\n\n\tВозврат Y;\nКонецФункции\n\n#КонецОбласти\n"
+ }
+ },
+ {
+ "script": "cfe-init/scripts/cfe-init",
+ "args": {
+ "-Name": "Тест",
+ "-OutputDir": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}"
+ }
+ },
+ {
+ "script": "cfe-borrow/scripts/cfe-borrow",
+ "args": {
+ "-ExtensionPath": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}",
+ "-Object": "CommonModule.БатчМод"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "cfe/CommonModules/БатчМод/Ext/Module.bsl",
+ "content": "#Область ПрограммныйИнтерфейс\n&ИзменениеИКонтроль(\"РасчётА\")\nФункция Тест_РасчётА()\n\n\tХ = 1;\n\n\tВозврат Х;\nКонецФункции\n&ИзменениеИКонтроль(\"РасчётБ\")\nФункция Тест_РасчётБ()\n\ty = 2;\n\tВозврат Y;\nКонецФункции\n#КонецОбласти\n"
+ }
+ }
+ ],
+ "params": {
+ "extensionPath": "cfe"
+ },
+ "args_extra": [
+ "-Check"
+ ],
+ "expectError": true,
+ "expect": {
+ "stdoutContains": "ДРЕЙФ"
+ }
+}
diff --git a/tests/skills/cases/cfe-patch-method/check-innerspace-drift.json b/tests/skills/cases/cfe-patch-method/check-innerspace-drift.json
new file mode 100644
index 000000000..fdbb7cc1a
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/check-innerspace-drift.json
@@ -0,0 +1,55 @@
+{
+ "name": "-Check: контекст отличается пробелами между токенами — дрейф, как у платформы",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "CommonModule",
+ "name": "БатчМод",
+ "context": "server"
+ },
+ "args": {
+ "-JsonPath": "{inputFile}",
+ "-OutputDir": "{workDir}"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "CommonModules/БатчМод/Ext/Module.bsl",
+ "content": "#Область ПрограммныйИнтерфейс\n\nФункция РасчётА() Экспорт\n\t\n\tХ = 1;\n\t\n\tВозврат Х;\n\t\nКонецФункции\n\nФункция РасчётБ() Экспорт\n\tY = 2;\n\n\tВозврат Y;\nКонецФункции\n\n#КонецОбласти\n"
+ }
+ },
+ {
+ "script": "cfe-init/scripts/cfe-init",
+ "args": {
+ "-Name": "Тест",
+ "-OutputDir": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}"
+ }
+ },
+ {
+ "script": "cfe-borrow/scripts/cfe-borrow",
+ "args": {
+ "-ExtensionPath": "{workDir}/cfe",
+ "-ConfigPath": "{workDir}",
+ "-Object": "CommonModule.БатчМод"
+ }
+ },
+ {
+ "writeFile": {
+ "path": "cfe/CommonModules/БатчМод/Ext/Module.bsl",
+ "content": "#Область ПрограммныйИнтерфейс\n&ИзменениеИКонтроль(\"РасчётА\")\nФункция Тест_РасчётА()\n\n\tХ = 1;\n\n\tВозврат Х;\nКонецФункции\n&ИзменениеИКонтроль(\"РасчётБ\")\nФункция Тест_РасчётБ()\n\tY = 2;\n\tВозврат Y;\nКонецФункции\n#КонецОбласти\n"
+ }
+ }
+ ],
+ "params": {
+ "extensionPath": "cfe"
+ },
+ "args_extra": [
+ "-Check"
+ ],
+ "expectError": true,
+ "expect": {
+ "stdoutContains": "ДРЕЙФ"
+ }
+}
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/CommonModules/БатчМод.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/CommonModules/БатчМод.xml
new file mode 100644
index 000000000..9c0c5d4fe
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/CommonModules/БатчМод.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ БатчМод
+
+
+ ru
+ Батч мод
+
+
+
+ false
+ false
+ true
+ false
+ false
+ true
+ false
+ DontUse
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/CommonModules/БатчМод/Ext/Module.bsl b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/CommonModules/БатчМод/Ext/Module.bsl
new file mode 100644
index 000000000..dd026d7ca
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/CommonModules/БатчМод/Ext/Module.bsl
@@ -0,0 +1,17 @@
+#Область ПрограммныйИнтерфейс
+
+Функция РасчётА() Экспорт
+
+ Х = 1;
+
+ Возврат Х;
+
+КонецФункции
+
+Функция РасчётБ() Экспорт
+ Y = 2;
+
+ Возврат Y;
+КонецФункции
+
+#КонецОбласти
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Configuration.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Configuration.xml
new file mode 100644
index 000000000..aa563d1ca
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Configuration.xml
@@ -0,0 +1,252 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+
+ TestConfig
+
+
+ ru
+ TestConfig
+
+
+
+
+ Version8_3_24
+ 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
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ БатчМод
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Ext/ClientApplicationInterface.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Ext/ClientApplicationInterface.xml
new file mode 100644
index 000000000..3c1161b2d
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ UUID-002
+
+
+
+
+ UUID-004
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Languages/Русский.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Languages/Русский.xml
new file mode 100644
index 000000000..37c60d786
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/CommonModules/БатчМод.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/CommonModules/БатчМод.xml
new file mode 100644
index 000000000..3c8082530
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/CommonModules/БатчМод.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Adopted
+ БатчМод
+
+ UUID-002
+ false
+ false
+ true
+ false
+ false
+ true
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/CommonModules/БатчМод/Ext/Module.bsl b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/CommonModules/БатчМод/Ext/Module.bsl
new file mode 100644
index 000000000..e30110190
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/CommonModules/БатчМод/Ext/Module.bsl
@@ -0,0 +1,17 @@
+#Область ПрограммныйИнтерфейс
+&ИзменениеИКонтроль("РасчётА")
+Функция Тест_РасчётА()
+
+ Х = 1;
+#Вставка
+ Х = Х + 1;
+#КонецВставки
+
+ Возврат Х;
+КонецФункции
+&ИзменениеИКонтроль("РасчётБ")
+Функция Тест_РасчётБ()
+ Y = 2;
+ Возврат Y;
+КонецФункции
+#КонецОбласти
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Configuration.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Configuration.xml
new file mode 100644
index 000000000..1c31ae0fd
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Configuration.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+
+ Adopted
+ Тест
+
+
+ ru
+ Тест
+
+
+
+ Customization
+ true
+ Тест_
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+ Role.Тест_ОсновнаяРоль
+
+
+
+ Language.Русский
+
+
+
+
+
+ TaxiEnableVersion8_2
+
+
+ Русский
+ Тест_ОсновнаяРоль
+ БатчМод
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Languages/Русский.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Languages/Русский.xml
new file mode 100644
index 000000000..c21624f52
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Languages/Русский.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Adopted
+ Русский
+
+ UUID-002
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Roles/Тест_ОсновнаяРоль.xml b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Roles/Тест_ОсновнаяРоль.xml
new file mode 100644
index 000000000..ec9dfbaf6
--- /dev/null
+++ b/tests/skills/cases/cfe-patch-method/snapshots/check-blankskew/cfe/Roles/Тест_ОсновнаяРоль.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ Тест_ОсновнаяРоль
+
+
+
+
+
\ No newline at end of file