fix(db-load-xml): surface silent platform rejections + opt-in -StrictLog

Platform writes load-time property/type/enum rejections ("Неверное
свойство объекта метаданных", "Неизвестное имя типа" и т.п.) into the
/Out log but still exits with code 0, silently dropping the offending
metadata. db-load-xml now parses the log for these patterns and prints
a yellow "[warning] N rejection(s)" block to stdout so users (and the
model) can see them immediately.

Exit code still mirrors the platform by default — we don't second-guess
its verdict. With the new -StrictLog switch, rejection patterns are
elevated to exit code 1, which is the mode verify-snapshots.mjs uses
for honest E2E verdicts. All three db-load-xml call sites in the
verifier (main config, CFE base, CFE extension) now pass -StrictLog.

Found while investigating upload/form-baseline/gotchas.md #4 where AR
attribute emission was wrong but verify-snapshots showed green because
the old exit-code-only check missed the silent drops.

Bumped db-load-xml.ps1 + .py to v1.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-04-11 17:59:50 +03:00
parent 83b289de32
commit 96d1dea552
3 changed files with 107 additions and 23 deletions
@@ -1,4 +1,4 @@
# db-load-xml v1.1 — Load 1C configuration from XML files
# db-load-xml v1.3 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<#
.SYNOPSIS
@@ -98,7 +98,10 @@ param(
[string]$Format = "Hierarchical",
[Parameter(Mandatory=$false)]
[switch]$UpdateDB
[switch]$UpdateDB,
[Parameter(Mandatory=$false)]
[switch]$StrictLog
)
$OutputEncoding = [System.Text.Encoding]::UTF8
@@ -213,20 +216,58 @@ try {
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
$exitCode = $process.ExitCode
# --- Read log ---
$logContent = $null
if (Test-Path $outFile) {
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
}
# --- 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
}
}
}
}
# --- Result ---
# Default: mirror platform's verdict via exit code. Log content (including any
# rejection warnings) is always printed to stdout for visibility. With -StrictLog,
# elevate exit code to 1 when rejection patterns are found even if platform said 0.
if ($exitCode -eq 0) {
Write-Host "Load completed successfully" -ForegroundColor Green
} else {
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
}
if (Test-Path $outFile) {
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
if ($logContent) {
Write-Host "--- Log ---"
Write-Host $logContent
Write-Host "--- End ---"
}
if ($logContent) {
Write-Host "--- Log ---"
Write-Host $logContent
Write-Host "--- End ---"
}
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
foreach ($f in $silentFailures) { Write-Host " $f" -ForegroundColor Yellow }
if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 }
}
exit $exitCode
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# db-load-xml v1.1 — Load 1C configuration from XML files
# db-load-xml v1.3 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -63,6 +63,11 @@ def main():
help="File format (default: Hierarchical)",
)
parser.add_argument("-UpdateDB", action="store_true", help="Also update database configuration after load")
parser.add_argument(
"-StrictLog",
action="store_true",
help="Treat silent rejection warnings in the log as errors (elevate exit code to 1)",
)
args = parser.parse_args()
# --- Resolve V8Path ---
@@ -157,22 +162,60 @@ def main():
)
exit_code = result.returncode
# --- Read log ---
log_content = ""
if os.path.isfile(out_file):
try:
with open(out_file, "r", encoding="utf-8-sig") as f:
log_content = f.read()
except Exception:
log_content = ""
# --- 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
# --- Result ---
# Default: mirror platform's verdict via exit code. Log content (including any
# rejection warnings) is always printed to stdout for visibility. With -StrictLog,
# elevate exit code to 1 when rejection patterns are found even if platform said 0.
if exit_code == 0:
print("Load completed successfully")
else:
print(f"Error loading configuration (code: {exit_code})", file=sys.stderr)
if os.path.isfile(out_file):
try:
with open(out_file, "r", encoding="utf-8-sig") as f:
log_content = f.read()
if log_content:
print("--- Log ---")
print(log_content)
print("--- End ---")
except Exception:
pass
if log_content:
print("--- Log ---")
print(log_content)
print("--- End ---")
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,
)
for f in silent_failures:
print(f" {f}", file=sys.stderr)
if args.StrictLog and exit_code == 0:
exit_code = 1
sys.exit(exit_code)
+3 -3
View File
@@ -520,7 +520,7 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) {
try {
execSkill(opts.runtime, 'db-load-xml/scripts/db-load-xml',
['-V8Path', opts.v8ctx.v8path, '-InfoBasePath', dbDir, '-ConfigDir', baseConfigDir], 180_000);
['-V8Path', opts.v8ctx.v8path, '-InfoBasePath', dbDir, '-ConfigDir', baseConfigDir, '-StrictLog'], 180_000);
log('db-load-xml (config)', true);
} catch (e) {
const detail = (e.stderr || e.stdout || e.message).trim();
@@ -551,7 +551,7 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) {
if (existsSync(extDir)) {
try {
execSkill(opts.runtime, 'db-load-xml/scripts/db-load-xml',
['-V8Path', opts.v8ctx.v8path, '-InfoBasePath', dbDir, '-ConfigDir', extDir, '-Extension', extName], 180_000);
['-V8Path', opts.v8ctx.v8path, '-InfoBasePath', dbDir, '-ConfigDir', extDir, '-Extension', extName, '-StrictLog'], 180_000);
log('db-load-xml (ext)', true);
} catch (e) {
const detail = (e.stderr || e.stdout || e.message).trim();
@@ -624,7 +624,7 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) {
try {
execSkill(opts.runtime, 'db-load-xml/scripts/db-load-xml',
['-V8Path', opts.v8ctx.v8path, '-InfoBasePath', dbDir, '-ConfigDir', configDir], 180_000);
['-V8Path', opts.v8ctx.v8path, '-InfoBasePath', dbDir, '-ConfigDir', configDir, '-StrictLog'], 180_000);
log('db-load-xml', true);
} catch (e) {
const detail = (e.stderr || e.stdout || e.message).trim();