feat(db-*): после загрузки расширения проверяется его применимость

Платформа отчитывается успехом и о расширении, которое не применит: отказ
всплывает лениво, при первом вызове метода, записью в журнал регистрации.
Теперь db-load-xml, db-load-git, db-load-cf и db-update после успешной операции
с расширением спрашивают платформу явно и печатают предупреждение; код возврата
операции не меняется — применение неприменимого расширения не разрушительно,
платформа просто работает по оригиналу. Поднять код возврата может -StrictLog,
он для регрессов и в инструкциях не значится.

Проверка обязана быть ОТДЕЛЬНЫМ запуском платформы: в одной командной строке
DESIGNER выполняет только последнюю пакетную команду, и дописанная проверка
отменила бы саму загрузку (замер: /LoadConfigFromFiles + /CheckCanApply… → код 0,
пустой лог, расширение в базе не изменилось). Об этом сказано в теле функции,
чтобы «оптимизация» не вернула команды в одну строку.

Выключатель: ключ -NoApplyCheck и настройка проекта extensionApplyCheck (ключ
команды сильнее). В ветке ibcmd проверка идёт соседним 1cv8; если его рядом нет —
одна строка [note], а не тишина.

Общий блок (Invoke-ApplyCheck / Invoke-ApplyCheckReport / Get-ApplyCheckEnabled и
их py-двойники) объявлен семьёй в check-inline-drift.mjs: разъехавшиеся копии
означали бы, что один навык предупреждает, а соседний по той же операции молчит.
db-load-cf получил недостающие копии Find-V8Project и ключ -StrictLog.

Раннер: у фейковой платформы появился отдельный ответ на проверку (spec.check),
выбираемый по составу аргументов, — иначе сценарий «загрузка прошла, проверка
провалилась» невыразим.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QoAJmoNbgWKobA7JGgN5S3
This commit is contained in:
Nick Shirokov
2026-09-05 14:06:59 +03:00
co-authored by Claude Opus 5
parent 5943828216
commit a3ea0b7be6
28 changed files with 1137 additions and 53 deletions
@@ -116,6 +116,10 @@ param(
# но в логе есть отбраковка.
[switch]$StrictLog,
# Пропустить проверку применимости расширения после загрузки.
[Parameter(Mandatory=$false)]
[switch]$NoApplyCheck,
[Parameter(Mandatory=$false)]
[string]$RepositoryPath,
@@ -573,7 +577,74 @@ function Find-SilentRejections {
}
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
# Постусловие применимости расширения: платформа отчитывается успехом и о расширении, которое
# не применит — отказ всплывает лениво, при первом вызове метода, записью в журнал регистрации.
#
# Запуск ОБЯЗАТЕЛЬНО отдельный. Дописать эту команду в строку операции нельзя: в одной командной
# строке DESIGNER выполняет только ПОСЛЕДНЮЮ пакетную команду, остальные молча отбрасывает —
# проверено на 8.3.24, /LoadConfigFromFiles вместе с /CheckCanApplyConfigurationExtensions
# завершились кодом 0 с пустым логом, и загрузка не состоялась.
#
# Проверку умеет только 1cv8; если навык работал через ibcmd, берём соседний исполняемый файл.
function Invoke-ApplyCheck {
param([string]$Exe, [string[]]$ConnArgs, [string]$Extension, [string[]]$ExtraArgs)
$exeDir = Split-Path $Exe -Parent
$exeLeaf = Split-Path $Exe -Leaf
$v8 = if ($exeLeaf -match '^ibcmd') { Join-Path $exeDir ("1cv8" + [System.IO.Path]::GetExtension($Exe)) } else { $Exe }
if (-not (Test-Path $v8)) { return @{ Skipped = $true; Reason = "1cv8 not found at $v8"; ExitCode = 0; Lines = @() } }
$dir = Join-Path $env:TEMP "apply_check_$(Get-Random)"
New-Item -ItemType Directory -Path $dir -Force | Out-Null
try {
$a = @("DESIGNER") + $ConnArgs + @("/CheckCanApplyConfigurationExtensions")
if ($Extension) { $a += "-Extension", "`"$Extension`"" }
$outFile = Join-Path $dir "check_log.txt"
$a += "/Out", "`"$outFile`"", "/DisableStartupDialogs"
$a += $ExtraArgs
$res = Invoke-PlatformProcess $v8 $a -PreQuoted
$lines = @()
if (Test-Path $outFile) {
$raw = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
if ($raw) { $lines = @($raw -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }) }
}
return @{ Skipped = $false; Reason = ''; ExitCode = $res.ExitCode; Lines = $lines }
} finally {
if (Test-Path $dir) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue }
}
}
# Проверить и напечатать. $true, если платформа расширение не применит — вызывающий решает,
# поднимать ли код возврата (строгий режим).
function Invoke-ApplyCheckReport {
param([string]$Exe, [string[]]$ConnArgs, [string]$Extension, [string[]]$ExtraArgs)
$ac = Invoke-ApplyCheck $Exe $ConnArgs $Extension $ExtraArgs
if ($ac.Skipped) {
Write-Host "[note] applicability check skipped: $($ac.Reason)" -ForegroundColor Yellow
return $false
}
if ($ac.ExitCode -ne 0 -or $ac.Lines.Count -gt 0) {
Write-Host "[warning] the extension is loaded, but the platform will not apply it:" -ForegroundColor Yellow
foreach ($l in $ac.Lines) { Write-Host " $l" -ForegroundColor Yellow }
return $true
}
return $false
}
# Проверять ли применимость: -NoApplyCheck сильнее настройки проекта.
function Get-ApplyCheckEnabled {
param([switch]$Disabled)
if ($Disabled) { return $false }
$pf = Find-V8Project (Get-Location).Path
if ($pf) {
try {
$proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
if ($null -ne $proj.extensionApplyCheck) { return [bool]$proj.extensionApplyCheck }
} catch {}
}
return $true
}
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
if ($engine -eq "ibcmd") {
if (-not $InfoBasePath) {
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
@@ -782,6 +853,13 @@ try {
} else {
Write-Host "Error updating database configuration (code: $exitCode)$(Get-ExitAnnotation $exitCode)" -ForegroundColor Red
}
# Проверку применимости умеет только 1cv8 — соединение для неё собираем в его форме.
if ($exitCode -eq 0 -and ($Extension -or $AllExtensions) -and (Get-ApplyCheckEnabled -Disabled:$NoApplyCheck)) {
$acConn = @("/F", "`"$InfoBasePath`"")
if ($UserName) { $acConn += "/N`"$UserName`"" }
if ($Password) { $acConn += "/P`"$Password`"" }
if ((Invoke-ApplyCheckReport $V8Path $acConn $Extension @()) -and $StrictLog) { $exitCode = 1 }
}
Write-PlatformOutput $applyOut
}
exit $exitCode
@@ -794,21 +872,24 @@ try {
[System.IO.File]::WriteAllLines($listFile, $configFiles, $utf8Bom)
# --- Build arguments ---
$arguments = @("DESIGNER")
# Аргументы соединения собираем отдельно: тем же набором пойдёт запуск проверки применимости.
$connArgs = @()
if ($InfoBaseServer -and $InfoBaseRef) {
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
$connArgs += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
} else {
$arguments += "/F", "`"$InfoBasePath`""
$connArgs += "/F", "`"$InfoBasePath`""
}
if ($UserName) { $arguments += "/N`"$UserName`"" }
if ($Password) { $arguments += "/P`"$Password`"" }
if ($UserName) { $connArgs += "/N`"$UserName`"" }
if ($Password) { $connArgs += "/P`"$Password`"" }
# База под хранилищем не примет НИ ОДНОЙ операции конфигуратора без этих реквизитов, а для
# базы вне хранилища они безвредны — поэтому подставляем всегда, когда они известны.
$__repo = Resolve-RepositorySettings
$arguments += Get-RepositoryArgs $__repo
$connArgs += Get-RepositoryArgs $__repo
$arguments = @("DESIGNER") + $connArgs
$arguments += "/LoadConfigFromFiles", "`"$ConfigDir`""
$arguments += "-listFile", "`"$listFile`""
@@ -872,6 +953,11 @@ try {
if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 }
}
# Расширение могло загрузиться «успешно» и остаться неприменимым — спрашиваем платформу.
if ($exitCode -eq 0 -and ($Extension -or $AllExtensions) -and (Get-ApplyCheckEnabled -Disabled:$NoApplyCheck)) {
if ((Invoke-ApplyCheckReport $V8Path $connArgs $Extension $extraArgs) -and $StrictLog) { $exitCode = 1 }
}
exit $exitCode
} finally {