diff --git a/.claude/skills/db-load-git/scripts/db-load-git.ps1 b/.claude/skills/db-load-git/scripts/db-load-git.ps1 index a2ed49e3..6bebcf5c 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.ps1 +++ b/.claude/skills/db-load-git/scripts/db-load-git.ps1 @@ -1,4 +1,4 @@ -# db-load-git v1.19 — Load Git changes into 1C database +# db-load-git v1.20 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -110,6 +110,12 @@ param( [Parameter(Mandatory=$false)] [switch]$UpdateDB, + [Parameter(Mandatory=$false)] + # Ключ для регрессов и верификации снапшотов, не для повседневного вызова: в SKILL.md + # намеренно не выносится. Поднимает код возврата, если платформа отчиталась об успехе, + # но в логе есть отбраковка. + [switch]$StrictLog, + [Parameter(Mandatory=$false)] [string[]]$AdditionalV8Arguments = @(), @@ -394,6 +400,41 @@ function Write-PlatformOutput { Write-Host "--- End ---" } +# Строки лога, о которых платформа сообщает, НЕ поднимая код возврата: метаданные отброшены или +# конфигурация нерабочая, а операция при этом «успешна». Возвращает подошедшие строки. +# +# Копия этой функции есть в каждом навыке, который читает /Out-лог загрузки (навыки автономны). +# Держать копии одинаковыми — сознательно: разошедшиеся копии сводят на нет весь смысл. +function Find-SilentRejections { + param([string]$LogText) + $patterns = @( + 'Неверное свойство объекта метаданных', + 'не входит в состав объекта метаданных', + 'Неизвестное имя типа', + 'Неизвестный объект метаданных', + 'Ни один из документов не является регистратором для регистра', + 'Неверное значение перечисления', + 'не может быть приведен к типу', + # Режим совместимости выше платформы: объекты в базу не попадают, отказ приходит в рантайме. + # Обрезано до инвариантной части — конкретная версия в сообщении меняется. + 'Для работы с конфигурацией необходима версия платформы не меньше' + ) + $found = @() + if ($LogText) { + foreach ($line in ($LogText -split "`r?`n")) { + foreach ($pat in $patterns) { + if ($line -match [regex]::Escape($pat)) { + $found += $line.Trim() + break + } + } + } + } + # Возвращаем массив БЕЗ запятой-обёртки: вызывающий берёт результат в @(), а `return ,$found` + # дал бы массив из одного пустого массива — фантомное срабатывание на чистом логе. + return $found +} + $engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" } if ($engine -eq "ibcmd") { @@ -667,6 +708,7 @@ try { Write-Host "Error loading configuration (code: $exitCode)$(Get-ExitAnnotation $exitCode)" -ForegroundColor Red } + $logContent = $null if (Test-Path $outFile) { $logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue if ($logContent) { @@ -677,6 +719,16 @@ try { } Write-PlatformOutput $__v8.Output + # Причину не называем: строки лога печатаются следом и говорят за себя, а класс проблемы + # разный — от отброшенного свойства до нерабочей на этой платформе конфигурации. Подсказку + # про -StrictLog не даём: операция уже выполнена, повторять её ради того же текста незачем. + $silentFailures = @(Find-SilentRejections $logContent) + if ($silentFailures.Count -gt 0) { + Write-Host "[warning] platform reported success, but the log contains $($silentFailures.Count) problem(s):" -ForegroundColor Yellow + foreach ($f in $silentFailures) { Write-Host " $f" -ForegroundColor Yellow } + if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 } + } + exit $exitCode } finally { diff --git a/.claude/skills/db-load-git/scripts/db-load-git.py b/.claude/skills/db-load-git/scripts/db-load-git.py index 0def43e4..93d8342e 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.py +++ b/.claude/skills/db-load-git/scripts/db-load-git.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-git v1.19 — Load Git changes into 1C database +# db-load-git v1.20 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -344,6 +344,38 @@ def print_platform_output(result): print("--- End ---") +def find_silent_rejections(log_text): + """Строки лога, о которых платформа сообщает, НЕ поднимая код возврата. + + Метаданные отброшены или конфигурация нерабочая, а операция при этом «успешна». + Возвращает подошедшие строки. + + Копия этой функции есть в каждом навыке, который читает /Out-лог загрузки (навыки + автономны). Держать копии одинаковыми — сознательно: разошедшиеся копии сводят на нет + весь смысл. + """ + patterns = [ + "Неверное свойство объекта метаданных", + "не входит в состав объекта метаданных", + "Неизвестное имя типа", + "Неизвестный объект метаданных", + "Ни один из документов не является регистратором для регистра", + "Неверное значение перечисления", + "не может быть приведен к типу", + # Режим совместимости выше платформы: объекты в базу не попадают, отказ приходит в + # рантайме. Обрезано до инвариантной части — конкретная версия в сообщении меняется. + "Для работы с конфигурацией необходима версия платформы не меньше", + ] + found = [] + if log_text: + for line in log_text.splitlines(): + for pat in patterns: + if pat in line: + found.append(line.strip()) + break + return found + + def run_ibcmd(cmd, has_username=False, warn_no_user=True): """Run an ibcmd command non-interactively. @@ -446,6 +478,10 @@ def main(): ) parser.add_argument("-DryRun", action="store_true", help="Only show what would be loaded (no actual load)") parser.add_argument("-UpdateDB", action="store_true", help="Also update database configuration after load") + # Ключ для регрессов и верификации снапшотов, не для повседневного вызова: в SKILL.md + # намеренно не выносится. Поднимает код возврата, если платформа отчиталась об успехе, + # но в логе есть отбраковка. + parser.add_argument("-StrictLog", action="store_true") parser.add_argument("-AdditionalV8Arguments", nargs="*", default=[], help="Extra 1cv8 arguments, e.g. /UseHwLicenses+") parser.add_argument("-AdditionalIbcmdArguments", nargs="*", default=[], @@ -705,6 +741,7 @@ def main(): else: print(f"Error loading configuration (code: {exit_code}){describe_exit(exit_code)}", file=sys.stderr) + log_content = "" if os.path.isfile(out_file): try: with open(out_file, "r", encoding="utf-8-sig") as f: @@ -717,6 +754,21 @@ def main(): pass print_platform_output(result) + + # Причину не называем: строки лога печатаются следом и говорят за себя, а класс проблемы + # разный — от отброшенного свойства до нерабочей на этой платформе конфигурации. Подсказку + # про -StrictLog не даём: операция уже выполнена, повторять её ради того же текста незачем. + silent_failures = find_silent_rejections(log_content) + if silent_failures: + print( + f"[warning] platform reported success, but the log contains " + f"{len(silent_failures)} problem(s):" + ) + for line in silent_failures: + print(f" {line}") + if args.StrictLog and exit_code == 0: + exit_code = 1 + sys.exit(exit_code) finally: diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 index cbe8d415..90ea0cd7 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 @@ -1,4 +1,4 @@ -# db-load-xml v1.20 — Load 1C configuration from XML files +# db-load-xml v1.21 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -416,6 +416,41 @@ function Write-PlatformOutput { Write-Host "--- End ---" } +# Строки лога, о которых платформа сообщает, НЕ поднимая код возврата: метаданные отброшены или +# конфигурация нерабочая, а операция при этом «успешна». Возвращает подошедшие строки. +# +# Копия этой функции есть в каждом навыке, который читает /Out-лог загрузки (навыки автономны). +# Держать копии одинаковыми — сознательно: разошедшиеся копии сводят на нет весь смысл. +function Find-SilentRejections { + param([string]$LogText) + $patterns = @( + 'Неверное свойство объекта метаданных', + 'не входит в состав объекта метаданных', + 'Неизвестное имя типа', + 'Неизвестный объект метаданных', + 'Ни один из документов не является регистратором для регистра', + 'Неверное значение перечисления', + 'не может быть приведен к типу', + # Режим совместимости выше платформы: объекты в базу не попадают, отказ приходит в рантайме. + # Обрезано до инвариантной части — конкретная версия в сообщении меняется. + 'Для работы с конфигурацией необходима версия платформы не меньше' + ) + $found = @() + if ($LogText) { + foreach ($line in ($LogText -split "`r?`n")) { + foreach ($pat in $patterns) { + if ($line -match [regex]::Escape($pat)) { + $found += $line.Trim() + break + } + } + } + } + # Возвращаем массив БЕЗ запятой-обёртки: вызывающий берёт результат в @(), а `return ,$found` + # дал бы массив из одного пустого массива — фантомное срабатывание на чистом логе. + return $found +} + $engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" } @@ -607,28 +642,7 @@ try { } # --- Scan log for silent rejections --- - # Platform often writes load-time rejections into /Out but exits with code 0. - # These patterns flag cases where metadata was dropped or rejected silently. - $fatalLogPatterns = @( - 'Неверное свойство объекта метаданных', - 'не входит в состав объекта метаданных', - 'Неизвестное имя типа', - 'Неизвестный объект метаданных', - 'Ни один из документов не является регистратором для регистра', - 'Неверное значение перечисления', - 'не может быть приведен к типу' - ) - $silentFailures = @() - if ($logContent) { - foreach ($line in ($logContent -split "`r?`n")) { - foreach ($pat in $fatalLogPatterns) { - if ($line -match [regex]::Escape($pat)) { - $silentFailures += $line.Trim() - break - } - } - } - } + $silentFailures = @(Find-SilentRejections $logContent) # --- Result --- # Default: mirror platform's verdict via exit code. Log content (including any @@ -647,10 +661,11 @@ try { } Write-PlatformOutput $__v8.Output + # Причину не называем: строки лога печатаются следом и говорят за себя, а класс проблемы + # разный — от отброшенного свойства до нерабочей на этой платформе конфигурации. Подсказку + # про -StrictLog не даём: загрузка уже выполнена, повторять её ради того же текста незачем. if ($silentFailures.Count -gt 0) { - $msg = "[warning] log contains $($silentFailures.Count) rejection(s) — platform loaded config but dropped properties/refs" - if (-not $StrictLog) { $msg += " (pass -StrictLog to treat as error)" } - Write-Host $msg -ForegroundColor Yellow + Write-Host "[warning] platform reported success, but the log contains $($silentFailures.Count) problem(s):" -ForegroundColor Yellow foreach ($f in $silentFailures) { Write-Host " $f" -ForegroundColor Yellow } if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 } } diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.py b/.claude/skills/db-load-xml/scripts/db-load-xml.py index c0495f65..7e443532 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.py +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-xml v1.20 — Load 1C configuration from XML files +# db-load-xml v1.21 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -344,6 +344,38 @@ def print_platform_output(result): print("--- End ---") +def find_silent_rejections(log_text): + """Строки лога, о которых платформа сообщает, НЕ поднимая код возврата. + + Метаданные отброшены или конфигурация нерабочая, а операция при этом «успешна». + Возвращает подошедшие строки. + + Копия этой функции есть в каждом навыке, который читает /Out-лог загрузки (навыки + автономны). Держать копии одинаковыми — сознательно: разошедшиеся копии сводят на нет + весь смысл. + """ + patterns = [ + "Неверное свойство объекта метаданных", + "не входит в состав объекта метаданных", + "Неизвестное имя типа", + "Неизвестный объект метаданных", + "Ни один из документов не является регистратором для регистра", + "Неверное значение перечисления", + "не может быть приведен к типу", + # Режим совместимости выше платформы: объекты в базу не попадают, отказ приходит в + # рантайме. Обрезано до инвариантной части — конкретная версия в сообщении меняется. + "Для работы с конфигурацией необходима версия платформы не меньше", + ] + found = [] + if log_text: + for line in log_text.splitlines(): + for pat in patterns: + if pat in line: + found.append(line.strip()) + break + return found + + def run_ibcmd(cmd, has_username=False, warn_no_user=True): """Run an ibcmd command non-interactively. @@ -636,22 +668,7 @@ def main(): # --- Scan log for silent rejections --- # Platform often writes load-time rejections into /Out but exits with code 0. # These patterns flag cases where metadata was dropped or rejected silently. - fatal_log_patterns = [ - "Неверное свойство объекта метаданных", - "не входит в состав объекта метаданных", - "Неизвестное имя типа", - "Неизвестный объект метаданных", - "Ни один из документов не является регистратором для регистра", - "Неверное значение перечисления", - "не может быть приведен к типу", - ] - silent_failures = [] - if log_content: - for line in log_content.splitlines(): - for pat in fatal_log_patterns: - if pat in line: - silent_failures.append(line.strip()) - break + silent_failures = find_silent_rejections(log_content) # --- Result --- # Default: mirror platform's verdict via exit code. Log content (including any @@ -668,15 +685,19 @@ def main(): print("--- End ---") print_platform_output(result) + # Причину не называем: строки лога печатаются следом и говорят за себя, а класс проблемы + # разный — от отброшенного свойства до нерабочей на этой платформе конфигурации. Подсказку + # про -StrictLog не даём: загрузка уже выполнена, повторять её ради того же текста незачем. + # Поток — stdout, как у PS1-порта: предупреждение относится к содержимому загрузки, а не к + # отказу навыка, и при code 0 остаётся предупреждением. Раньше py писал его в stderr — + # наблюдаемое поведение портов расходилось, и один кейс не мог проверить оба. if silent_failures: - suffix = "" if args.StrictLog else " (pass -StrictLog to treat as error)" print( - f"[warning] log contains {len(silent_failures)} rejection(s) — " - f"platform loaded config but dropped properties/refs{suffix}", - file=sys.stderr, + f"[warning] platform reported success, but the log contains " + f"{len(silent_failures)} problem(s):" ) for f in silent_failures: - print(f" {f}", file=sys.stderr) + print(f" {f}") if args.StrictLog and exit_code == 0: exit_code = 1 diff --git a/.claude/skills/db-update/scripts/db-update.ps1 b/.claude/skills/db-update/scripts/db-update.ps1 index 224bfbc3..ebe18ba4 100644 --- a/.claude/skills/db-update/scripts/db-update.ps1 +++ b/.claude/skills/db-update/scripts/db-update.ps1 @@ -1,4 +1,4 @@ -# db-update v1.14 — Update 1C database configuration +# db-update v1.15 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -91,6 +91,12 @@ param( [Parameter(Mandatory=$false)] [switch]$WarningsAsErrors, + [Parameter(Mandatory=$false)] + # Ключ для регрессов и верификации снапшотов, не для повседневного вызова: в SKILL.md + # намеренно не выносится. Поднимает код возврата, если платформа отчиталась об успехе, + # но в логе есть отбраковка. + [switch]$StrictLog, + [Parameter(Mandatory=$false)] [string[]]$AdditionalV8Arguments = @(), @@ -395,6 +401,41 @@ function Write-PlatformOutput { Write-Host "--- End ---" } +# Строки лога, о которых платформа сообщает, НЕ поднимая код возврата: метаданные отброшены или +# конфигурация нерабочая, а операция при этом «успешна». Возвращает подошедшие строки. +# +# Копия этой функции есть в каждом навыке, который читает /Out-лог загрузки (навыки автономны). +# Держать копии одинаковыми — сознательно: разошедшиеся копии сводят на нет весь смысл. +function Find-SilentRejections { + param([string]$LogText) + $patterns = @( + 'Неверное свойство объекта метаданных', + 'не входит в состав объекта метаданных', + 'Неизвестное имя типа', + 'Неизвестный объект метаданных', + 'Ни один из документов не является регистратором для регистра', + 'Неверное значение перечисления', + 'не может быть приведен к типу', + # Режим совместимости выше платформы: объекты в базу не попадают, отказ приходит в рантайме. + # Обрезано до инвариантной части — конкретная версия в сообщении меняется. + 'Для работы с конфигурацией необходима версия платформы не меньше' + ) + $found = @() + if ($LogText) { + foreach ($line in ($LogText -split "`r?`n")) { + foreach ($pat in $patterns) { + if ($line -match [regex]::Escape($pat)) { + $found += $line.Trim() + break + } + } + } + } + # Возвращаем массив БЕЗ запятой-обёртки: вызывающий берёт результат в @(), а `return ,$found` + # дал бы массив из одного пустого массива — фантомное срабатывание на чистом логе. + return $found +} + $engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" } @@ -496,6 +537,7 @@ try { Write-Host "Error updating database configuration (code: $exitCode)$(Get-ExitAnnotation $exitCode)" -ForegroundColor Red } + $logContent = $null if (Test-Path $outFile) { $logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue if ($logContent) { @@ -506,6 +548,16 @@ try { } Write-PlatformOutput $__v8.Output + # Причину не называем: строки лога печатаются следом и говорят за себя, а класс проблемы + # разный — от отброшенного свойства до нерабочей на этой платформе конфигурации. Подсказку + # про -StrictLog не даём: операция уже выполнена, повторять её ради того же текста незачем. + $silentFailures = @(Find-SilentRejections $logContent) + if ($silentFailures.Count -gt 0) { + Write-Host "[warning] platform reported success, but the log contains $($silentFailures.Count) problem(s):" -ForegroundColor Yellow + foreach ($f in $silentFailures) { Write-Host " $f" -ForegroundColor Yellow } + if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 } + } + exit $exitCode } finally { diff --git a/.claude/skills/db-update/scripts/db-update.py b/.claude/skills/db-update/scripts/db-update.py index 61b64761..e36b2896 100644 --- a/.claude/skills/db-update/scripts/db-update.py +++ b/.claude/skills/db-update/scripts/db-update.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-update v1.14 — Update 1C database configuration +# db-update v1.15 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -344,6 +344,38 @@ def print_platform_output(result): print("--- End ---") +def find_silent_rejections(log_text): + """Строки лога, о которых платформа сообщает, НЕ поднимая код возврата. + + Метаданные отброшены или конфигурация нерабочая, а операция при этом «успешна». + Возвращает подошедшие строки. + + Копия этой функции есть в каждом навыке, который читает /Out-лог загрузки (навыки + автономны). Держать копии одинаковыми — сознательно: разошедшиеся копии сводят на нет + весь смысл. + """ + patterns = [ + "Неверное свойство объекта метаданных", + "не входит в состав объекта метаданных", + "Неизвестное имя типа", + "Неизвестный объект метаданных", + "Ни один из документов не является регистратором для регистра", + "Неверное значение перечисления", + "не может быть приведен к типу", + # Режим совместимости выше платформы: объекты в базу не попадают, отказ приходит в + # рантайме. Обрезано до инвариантной части — конкретная версия в сообщении меняется. + "Для работы с конфигурацией необходима версия платформы не меньше", + ] + found = [] + if log_text: + for line in log_text.splitlines(): + for pat in patterns: + if pat in line: + found.append(line.strip()) + break + return found + + def run_ibcmd(cmd, has_username=False, warn_no_user=True): """Run an ibcmd command non-interactively. @@ -411,6 +443,10 @@ def main(): parser.add_argument("-Dynamic", default="", choices=["", "+", "-"]) parser.add_argument("-Server", action="store_true") parser.add_argument("-WarningsAsErrors", action="store_true") + # Ключ для регрессов и верификации снапшотов, не для повседневного вызова: в SKILL.md + # намеренно не выносится. Поднимает код возврата, если платформа отчиталась об успехе, + # но в логе есть отбраковка. + parser.add_argument("-StrictLog", action="store_true") parser.add_argument("-AdditionalV8Arguments", nargs="*", default=[], help="Extra 1cv8 arguments, e.g. /UseHwLicenses+") parser.add_argument("-AdditionalIbcmdArguments", nargs="*", default=[], @@ -527,6 +563,7 @@ def main(): else: print(f"Error updating database configuration (code: {exit_code}){describe_exit(exit_code)}", file=sys.stderr) + log_content = "" if os.path.isfile(out_file): try: with open(out_file, "r", encoding="utf-8-sig") as f: @@ -539,6 +576,21 @@ def main(): pass print_platform_output(result) + + # Причину не называем: строки лога печатаются следом и говорят за себя, а класс проблемы + # разный — от отброшенного свойства до нерабочей на этой платформе конфигурации. Подсказку + # про -StrictLog не даём: операция уже выполнена, повторять её ради того же текста незачем. + silent_failures = find_silent_rejections(log_content) + if silent_failures: + print( + f"[warning] platform reported success, but the log contains " + f"{len(silent_failures)} problem(s):" + ) + for line in silent_failures: + print(f" {line}") + if args.StrictLog and exit_code == 0: + exit_code = 1 + sys.exit(exit_code) finally: diff --git a/tests/skills/cases/db-load-xml/clean-log-no-warning.json b/tests/skills/cases/db-load-xml/clean-log-no-warning.json new file mode 100644 index 00000000..1c7e8240 --- /dev/null +++ b/tests/skills/cases/db-load-xml/clean-log-no-warning.json @@ -0,0 +1,42 @@ +{ + "name": "Чистый лог: предупреждения нет (иначе паттерн, ловящий всё подряд, прошёл бы остальные кейсы)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Загрузка конфигурации из файлов.\r\nЗагрузка завершена. Суммарное время выполнения операции: 780 миллисекунд.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + }, + { + "writeFile": { + "path": "src/Configuration.xml", + "content": "\n" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib", + "-ConfigDir", + "{workDir}\\src" + ], + "expect": { + "stdoutNotContains": "[warning] platform reported success, but the log contains" + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы" +} diff --git a/tests/skills/cases/db-load-xml/compat-mode-above-platform.json b/tests/skills/cases/db-load-xml/compat-mode-above-platform.json new file mode 100644 index 00000000..085c7dfb --- /dev/null +++ b/tests/skills/cases/db-load-xml/compat-mode-above-platform.json @@ -0,0 +1,45 @@ +{ + "name": "Режим совместимости выше платформы: сообщение классифицируется как отказ (issue #63)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Для работы с конфигурацией необходима версия платформы не меньше, чем 8.3.27.\r\nТекущая версия 8.3.24.1691.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + }, + { + "writeFile": { + "path": "src/Configuration.xml", + "content": "\n" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib", + "-ConfigDir", + "{workDir}\\src" + ], + "expect": { + "stdoutContains": [ + "[warning] platform reported success, but the log contains 1 problem(s):", + "необходима версия платформы не меньше" + ] + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы" +} diff --git a/tests/skills/cases/db-load-xml/silent-rejection-detected.json b/tests/skills/cases/db-load-xml/silent-rejection-detected.json new file mode 100644 index 00000000..15652fca --- /dev/null +++ b/tests/skills/cases/db-load-xml/silent-rejection-detected.json @@ -0,0 +1,46 @@ +{ + "name": "Тихий отказ в логе: платформа вернула 0, навык предупреждает (fake platform)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + }, + { + "writeFile": { + "path": "src/Configuration.xml", + "content": "\n" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib", + "-ConfigDir", + "{workDir}\\src" + ], + "expect": { + "stdoutContains": [ + "[warning] platform reported success, but the log contains 1 problem(s):", + "Свойство LineNumberLength не входит в состав объекта метаданных" + ], + "stdoutNotContains": "-StrictLog" + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы" +} diff --git a/tests/skills/cases/db-load-xml/silent-rejection-strict.json b/tests/skills/cases/db-load-xml/silent-rejection-strict.json new file mode 100644 index 00000000..ea70396b --- /dev/null +++ b/tests/skills/cases/db-load-xml/silent-rejection-strict.json @@ -0,0 +1,44 @@ +{ + "name": "Тот же лог под -StrictLog: код возврата поднимается до 1 (fake platform)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + }, + { + "writeFile": { + "path": "src/Configuration.xml", + "content": "\n" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib", + "-ConfigDir", + "{workDir}\\src", + "-StrictLog" + ], + "expect": { + "stdoutContains": "[warning] platform reported success, but the log contains 1 problem(s):" + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы", + "expectError": true +} diff --git a/tests/skills/cases/db-update/clean-log-no-warning.json b/tests/skills/cases/db-update/clean-log-no-warning.json new file mode 100644 index 00000000..7bc600f1 --- /dev/null +++ b/tests/skills/cases/db-update/clean-log-no-warning.json @@ -0,0 +1,34 @@ +{ + "name": "Чистый лог: предупреждения нет (иначе паттерн, ловящий всё подряд, прошёл бы остальные кейсы)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Загрузка конфигурации из файлов.\r\nЗагрузка завершена. Суммарное время выполнения операции: 780 миллисекунд.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib" + ], + "expect": { + "stdoutNotContains": "[warning] platform reported success, but the log contains" + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы" +} diff --git a/tests/skills/cases/db-update/compat-mode-above-platform.json b/tests/skills/cases/db-update/compat-mode-above-platform.json new file mode 100644 index 00000000..49fc7571 --- /dev/null +++ b/tests/skills/cases/db-update/compat-mode-above-platform.json @@ -0,0 +1,37 @@ +{ + "name": "Режим совместимости выше платформы: сообщение классифицируется как отказ (issue #63)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Для работы с конфигурацией необходима версия платформы не меньше, чем 8.3.27.\r\nТекущая версия 8.3.24.1691.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib" + ], + "expect": { + "stdoutContains": [ + "[warning] platform reported success, but the log contains 1 problem(s):", + "необходима версия платформы не меньше" + ] + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы" +} diff --git a/tests/skills/cases/db-update/silent-rejection-detected.json b/tests/skills/cases/db-update/silent-rejection-detected.json new file mode 100644 index 00000000..0e60b47a --- /dev/null +++ b/tests/skills/cases/db-update/silent-rejection-detected.json @@ -0,0 +1,38 @@ +{ + "name": "Тихий отказ в логе: платформа вернула 0, навык предупреждает (fake platform)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib" + ], + "expect": { + "stdoutContains": [ + "[warning] platform reported success, but the log contains 1 problem(s):", + "Свойство LineNumberLength не входит в состав объекта метаданных" + ], + "stdoutNotContains": "-StrictLog" + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы" +} diff --git a/tests/skills/cases/db-update/silent-rejection-strict.json b/tests/skills/cases/db-update/silent-rejection-strict.json new file mode 100644 index 00000000..2d04c0ec --- /dev/null +++ b/tests/skills/cases/db-update/silent-rejection-strict.json @@ -0,0 +1,36 @@ +{ + "name": "Тот же лог под -StrictLog: код возврата поднимается до 1 (fake platform)", + "osOnly": "win32", + "preRun": [ + { + "writeFile": { + "path": "fake.cmd", + "content": "@echo off\r\nrem SELF запоминаем ДО цикла: shift сдвигает и %0, после него %~dp0 указывает не на скрипт\r\nset SELF=%~dp0\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif /i \"%~1\"==\"/Out\" set OUT=%~2\r\nshift\r\ngoto loop\r\n:done\r\ncopy /y \"%SELF%log.txt\" \"%OUT%\" >nul\r\nexit /b 0\r\n" + } + }, + { + "writeFile": { + "path": "log.txt", + "content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n" + } + }, + { + "writeFile": { + "path": "ib/1Cv8.1CD", + "content": "stub" + } + } + ], + "args_extra": [ + "-V8Path", + "{workDir}\\fake.cmd", + "-InfoBasePath", + "{workDir}\\ib", + "-StrictLog" + ], + "expect": { + "stdoutContains": "[warning] platform reported success, but the log contains 1 problem(s):" + }, + "noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы", + "expectError": true +} diff --git a/tests/skills/check-inline-drift.mjs b/tests/skills/check-inline-drift.mjs index e9c33703..743ecc27 100644 --- a/tests/skills/check-inline-drift.mjs +++ b/tests/skills/check-inline-drift.mjs @@ -214,6 +214,15 @@ const FAMILIES = [ }, // ─── Обвязка вызова платформы 1С (db-* и потребители) ──────────────────── + // Детектор строк, о которых платформа сообщает, НЕ поднимая код возврата. Живёт во всех + // навыках, читающих /Out-лог загрузки: разъехавшийся список паттернов означал бы, что один + // навык ловит тихий отказ, а соседний по той же операции — нет. + { + name: 'platform: silent_rejections', py: 'find_silent_rejections', ps1: 'Find-SilentRejections', + variants: [ + { id: 'base', authority: 'db-load-xml', consumers: ['db-load-git', 'db-update'] }, + ], + }, { name: 'platform: resolve_extra_args', py: 'resolve_extra_args', ps1: 'Resolve-ExtraArgs', variants: [