fix(db-load-git,db-update): ловить тихие отказы платформы, как db-load-xml

Платформа рапортует об успехе (exit 0) и одновременно пишет в /Out-лог, что часть
метаданных отброшена. Детектор этого был только в db-load-xml, хотя db-load-git гоняет
тот же /LoadConfigFromFiles (и дописывает /UpdateDBCfg в тот же вызов), а db-update —
вторую половину той же цепочки. Оба лог печатали, но не разбирали.

Детектор извлечён в Find-SilentRejections / find_silent_rejections и внесён в реестр
семей check-inline-drift: инлайн-код гард сверять не умеет, а именно расхождение копий
и было бы главным риском такого дублирования.

Добавлен восьмой паттерн — «Для работы с конфигурацией необходима версия платформы не
меньше». Замерено при работе над issue #63: конфигурация с режимом совместимости выше
платформы грузится с кодом 0, db-update тоже отвечает 0, объекты в базу не попадают, а
отказ приходит только в рантайме. Строка обрезана до инвариантной части — конкретная
версия в сообщении меняется.

Текст предупреждения переписан. Убрана подсказка «pass -StrictLog to treat as error»:
ключ предназначен для регрессов (его передаёт verify-snapshots), а совет бессмысленный —
операция уже выполнена, и повторять её ради того же текста незачем. Формулировка больше
не утверждает «dropped properties/refs»: класс проблемы разный, а строки лога печатаются
следом и говорят за себя.

Две правки по дороге:

- `return ,$found` в паре с `@()` у вызывающего давал массив из одного пустого массива,
  то есть предупреждение «1 problem(s)» на чистом логе. Возврат без запятой-обёртки.
- py-порт писал предупреждение в stderr, PS1 — в stdout. В самом py-порте stderr занят
  исключительно фатальными «Error:» перед exit 1, так что не-фатальное предупреждение там
  было единственным исключением. Приведено к stdout — и к соглашению своего же файла, и к
  поведению PS1; verify-snapshots на падении читает `stderr || stdout`, поэтому диагностика
  не теряется.

Тесты: фейковая платформа .cmd, которая вычитывает путь из /Out и кладёт туда готовый лог,
— по четыре кейса на db-load-xml и db-update (отбраковка, она же под -StrictLog, новый
паттерн, чистый лог без предупреждения). Раньше детектор не был покрыт вообще.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-13 15:14:36 +03:00
co-authored by Claude Opus 5
parent 06f21ab3d1
commit a024b7da9c
15 changed files with 627 additions and 52 deletions
@@ -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/<ver>/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 {
@@ -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:
@@ -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/<ver>/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 }
}
@@ -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
+53 -1
View File
@@ -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/<ver>/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 {
+53 -1
View File
@@ -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:
@@ -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": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-ConfigDir",
"{workDir}\\src"
],
"expect": {
"stdoutNotContains": "[warning] platform reported success, but the log contains"
},
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
}
@@ -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": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
}
}
],
"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": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
}
@@ -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": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
}
}
],
"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": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
}
@@ -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": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
}
}
],
"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
}
@@ -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": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
}
@@ -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": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
}
@@ -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": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
}
@@ -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
}
+9
View File
@@ -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: [