913 lines
38 KiB
PowerShell
913 lines
38 KiB
PowerShell
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string[]]$BaseId,
|
|
[string]$AdapterUrl = "http://docker-gpu.cin.su:8011",
|
|
[string]$McpUrl = "http://docker.cin.su:8021",
|
|
[string]$ObjectRef,
|
|
[string]$ObjectKind,
|
|
[string]$ObjectName,
|
|
[string]$ObjectGuid,
|
|
[ValidateSet("ConfigSave", "ConfigCASSave")]
|
|
[string]$SavedStateTable = "ConfigSave",
|
|
[int]$TimeoutSec = 120,
|
|
[switch]$SkipRest,
|
|
[switch]$SkipMcp,
|
|
[switch]$SkipWritePlanSafetySmoke,
|
|
[switch]$SkipWriteRollbackSafetySmoke,
|
|
[switch]$SkipSavedStateDiffSmoke,
|
|
[switch]$SkipSavedStateWriteSmoke,
|
|
[switch]$SkipCodeWriteSavedStateSmoke,
|
|
[switch]$RequireSavedStateWriteSmoke,
|
|
[switch]$RequireCodeWriteSavedStateSmoke,
|
|
[switch]$RequireSelectorChainWritePlanComposition
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
$env:PYTHONIOENCODING = "utf-8"
|
|
|
|
function Invoke-CheckedCommand {
|
|
param(
|
|
[string]$Label,
|
|
[string[]]$Command
|
|
)
|
|
Write-Host "[run] $Label"
|
|
$exe = $Command[0]
|
|
$args = $Command[1..($Command.Length - 1)]
|
|
Write-Host ("[cmd] {0} {1}" -f $exe, ($args -join " "))
|
|
& $exe @args
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "$Label failed with code=$LASTEXITCODE"
|
|
}
|
|
}
|
|
|
|
function Write-HealthSummary {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Url
|
|
)
|
|
Write-Host "[health] $Label $Url"
|
|
$health = Invoke-RestMethod -Uri "$Url/health" -Method Get -TimeoutSec 15
|
|
$contractVersion = $health.contract_version
|
|
if (-not $contractVersion) {
|
|
$contractVersion = "<missing>"
|
|
}
|
|
Write-Host ("[health] {0}: status={1}; contract_version={2}" -f $Label, $health.status, $contractVersion)
|
|
}
|
|
|
|
function Add-ObjectSelectorArgs {
|
|
param(
|
|
[string[]]$Command
|
|
)
|
|
$result = @($Command)
|
|
if ($ObjectRef) {
|
|
$result += @("--ref", $ObjectRef)
|
|
}
|
|
if ($ObjectKind) {
|
|
$result += @("--kind", $ObjectKind)
|
|
}
|
|
if ($ObjectName) {
|
|
$result += @("--name", $ObjectName)
|
|
}
|
|
if ($ObjectGuid) {
|
|
$result += @("--guid", $ObjectGuid)
|
|
}
|
|
return $result
|
|
}
|
|
|
|
function ConvertTo-SafePathSegment {
|
|
param(
|
|
[string]$Value
|
|
)
|
|
$safe = $Value -replace '[^A-Za-z0-9_.-]', '_'
|
|
if (-not $safe) {
|
|
return "base"
|
|
}
|
|
return $safe
|
|
}
|
|
|
|
function Get-DuplicateValues {
|
|
param(
|
|
[string[]]$Values
|
|
)
|
|
$seen = @{}
|
|
$duplicates = New-Object System.Collections.Generic.HashSet[string]
|
|
foreach ($value in $Values) {
|
|
if ($seen.ContainsKey($value)) {
|
|
[void]$duplicates.Add($value)
|
|
} else {
|
|
$seen[$value] = $true
|
|
}
|
|
}
|
|
return @($duplicates | Sort-Object)
|
|
}
|
|
|
|
function Normalize-BaseIds {
|
|
param(
|
|
[string[]]$Values
|
|
)
|
|
$result = @()
|
|
foreach ($value in $Values) {
|
|
foreach ($part in ($value -split ",")) {
|
|
$trimmed = $part.Trim()
|
|
if ($trimmed) {
|
|
$result += $trimmed
|
|
}
|
|
}
|
|
}
|
|
return $result
|
|
}
|
|
|
|
function Read-JsonReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path
|
|
)
|
|
if (-not (Test-Path -LiteralPath $Path)) {
|
|
throw "$Label report was not written: $Path"
|
|
}
|
|
try {
|
|
return Get-Content -Raw -LiteralPath $Path | ConvertFrom-Json
|
|
} catch {
|
|
throw "$Label report is not valid JSON: $Path; $_"
|
|
}
|
|
}
|
|
|
|
function Assert-SelectorChainReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path,
|
|
[switch]$RequireComposition
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.passed -ne $true) {
|
|
throw "$Label report did not pass: $Path"
|
|
}
|
|
if (-not $report.coverage) {
|
|
throw "$Label report is missing coverage: $Path"
|
|
}
|
|
foreach ($section in @("resolve_overrides", "saved_state_resolution", "write_plan_composition", "skips")) {
|
|
if ($report.coverage.PSObject.Properties.Name -notcontains $section) {
|
|
throw "$Label report coverage is missing '$section': $Path"
|
|
}
|
|
}
|
|
if ($RequireComposition -and $report.coverage.write_plan_composition.composed -ne $true) {
|
|
throw "$Label report did not compose metadata.write.plan in strict mode: $Path"
|
|
}
|
|
foreach ($step in @($report.steps)) {
|
|
if ($step.name -in @("metadata.resolve_overrides", "code.search") -and $step.status -notlike "skipped*") {
|
|
if ($step.working_state -ne "working") {
|
|
throw "$Label step '$($step.name)' did not use working state: actual='$($step.working_state)'; path=$Path"
|
|
}
|
|
}
|
|
}
|
|
Write-Host ("[report] {0}: passed={1}; composition={2}; path={3}" -f $Label, $report.passed, $report.coverage.write_plan_composition.status, $Path)
|
|
}
|
|
|
|
function Assert-WritePlanSafetyReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.status -ne "ok") {
|
|
throw "$Label report status is not ok: $Path"
|
|
}
|
|
if ($report.failures -and $report.failures.Count -gt 0) {
|
|
throw "$Label report contains failures: $Path"
|
|
}
|
|
foreach ($check in @("blocked_effective_form_path", "replace_with_control_without_control_fragment", "replace_with_control_with_control_fragment", "replace_with_control_drift")) {
|
|
if ($report.checks.PSObject.Properties.Name -notcontains $check) {
|
|
throw "$Label report is missing check '$check': $Path"
|
|
}
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; checks={2}; path={3}" -f $Label, $report.status, $report.checks.PSObject.Properties.Name.Count, $Path)
|
|
}
|
|
|
|
function Assert-WritePreflightReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.schema -ne "onec_write_preflight_smoke.v1") {
|
|
throw "$Label report has unexpected schema '$($report.schema)': $Path"
|
|
}
|
|
if ($report.status -ne "ok") {
|
|
throw "$Label report status is not ok: $Path"
|
|
}
|
|
if ($report.failures -and $report.failures.Count -gt 0) {
|
|
throw "$Label report contains failures: $Path"
|
|
}
|
|
foreach ($check in @("method_exposed", "effective_path_preflight", "concrete_saved_state_preflight")) {
|
|
if ($report.checks.PSObject.Properties.Name -notcontains $check) {
|
|
throw "$Label report is missing check '$check': $Path"
|
|
}
|
|
}
|
|
if ($report.checks.method_exposed.status -ne "ok") {
|
|
throw "$Label did not expose metadata.write.preflight: $Path"
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; path={2}" -f $Label, $report.status, $Path)
|
|
}
|
|
|
|
function Assert-WriteRollbackSafetyReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.schema -ne "onec_write_rollback_safety_smoke.v1") {
|
|
throw "$Label report has unexpected schema '$($report.schema)': $Path"
|
|
}
|
|
if ($report.status -ne "ok") {
|
|
throw "$Label report status is not ok: $Path"
|
|
}
|
|
if ($report.failures -and $report.failures.Count -gt 0) {
|
|
throw "$Label report contains failures: $Path"
|
|
}
|
|
foreach ($check in @("method_exposed", "history_available", "rollback_without_gate_blocked")) {
|
|
if ($report.checks.PSObject.Properties.Name -notcontains $check) {
|
|
throw "$Label report is missing check '$check': $Path"
|
|
}
|
|
}
|
|
if ($report.checks.method_exposed.status -ne "ok") {
|
|
throw "$Label did not expose metadata.write.rollback: $Path"
|
|
}
|
|
if ($report.checks.rollback_without_gate_blocked.status -ne "invalid_argument") {
|
|
throw "$Label did not block rollback without explicit gate: $Path"
|
|
}
|
|
if ($report.checks.rollback_without_gate_blocked.argument -ne "allow_sql_saved_state_rollback") {
|
|
throw "$Label rollback gate error points to unexpected argument: $Path"
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; path={2}" -f $Label, $report.status, $Path)
|
|
}
|
|
|
|
function Assert-SavedStateDiffReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.schema -ne "onec_saved_state_diff_smoke.v1") {
|
|
throw "$Label report has unexpected schema '$($report.schema)': $Path"
|
|
}
|
|
if ($report.status -ne "ok") {
|
|
throw "$Label report status is not ok: $Path"
|
|
}
|
|
if ($report.failures -and $report.failures.Count -gt 0) {
|
|
throw "$Label report contains failures: $Path"
|
|
}
|
|
if ($report.checks.method_exposed.status -ne "ok") {
|
|
throw "$Label did not expose metadata.saved_state.diff: $Path"
|
|
}
|
|
$hasExisting = $report.checks.PSObject.Properties.Name -contains "diff_existing_saved_state"
|
|
$hasMissing = $report.checks.PSObject.Properties.Name -contains "diff_missing_saved_state"
|
|
if (-not $hasExisting -and -not $hasMissing) {
|
|
throw "$Label report has neither existing nor missing saved-state diff check: $Path"
|
|
}
|
|
if ($hasExisting -and $report.checks.diff_existing_saved_state.freshness -ne "live_sql_verified") {
|
|
throw "$Label existing diff is not live SQL verified: $Path"
|
|
}
|
|
if ($hasMissing -and $report.checks.diff_missing_saved_state.needs_prepare -ne $true) {
|
|
throw "$Label missing diff did not report needs_prepare=true: $Path"
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; path={2}" -f $Label, $report.status, $Path)
|
|
}
|
|
|
|
function Assert-SavedStateChangesReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.schema -ne "onec_saved_state_changes_smoke.v1") {
|
|
throw "$Label report has unexpected schema '$($report.schema)': $Path"
|
|
}
|
|
if ($report.status -ne "ok") {
|
|
throw "$Label report status is not ok: $Path"
|
|
}
|
|
if ($report.failures -and $report.failures.Count -gt 0) {
|
|
throw "$Label report contains failures: $Path"
|
|
}
|
|
foreach ($check in @("method_exposed", "changes_list", "changes_list_context")) {
|
|
if ($report.checks.PSObject.Properties.Name -notcontains $check) {
|
|
throw "$Label report is missing check '$check': $Path"
|
|
}
|
|
}
|
|
if ($report.checks.method_exposed.status -ne "ok") {
|
|
throw "$Label did not expose metadata.saved_state.changes.list: $Path"
|
|
}
|
|
if ($report.checks.changes_list.freshness -ne "live_sql_verified") {
|
|
throw "$Label changes list is not live SQL verified: $Path"
|
|
}
|
|
if ($report.checks.changes_list_context.include_context -ne $true) {
|
|
throw "$Label contextual changes list did not echo include_context=true: $Path"
|
|
}
|
|
if ($report.checks.changes_list_context.group_by_context -ne $true) {
|
|
throw "$Label contextual changes list did not echo group_by_context=true: $Path"
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; path={2}" -f $Label, $report.status, $Path)
|
|
}
|
|
|
|
function Assert-SavedStateFormWriteReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path,
|
|
[switch]$RequireWrite
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.passed -ne $true) {
|
|
throw "$Label report did not pass: $Path"
|
|
}
|
|
if ($RequireWrite -and $report.status -eq "skipped_no_saved_state") {
|
|
throw "$Label report skipped saved-state write in strict mode: $Path"
|
|
}
|
|
if ($report.status -ne "skipped_no_saved_state" -and (-not $report.routes -or $report.routes.Count -eq 0)) {
|
|
throw "$Label report has no verified routes: $Path"
|
|
}
|
|
Write-Host ("[report] {0}: passed={1}; status={2}; routes={3}; path={4}" -f $Label, $report.passed, $report.status, @($report.routes).Count, $Path)
|
|
}
|
|
|
|
function Assert-SavedStateModuleWriteReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path,
|
|
[switch]$RequireWrite
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($RequireWrite -and $report.status -eq "skipped_no_saved_state") {
|
|
throw "$Label report skipped saved-state module write in strict mode: $Path"
|
|
}
|
|
if ($report.status -notin @("skipped_no_saved_state", "verified_and_rolled_back")) {
|
|
throw "$Label report has unexpected status '$($report.status)': $Path"
|
|
}
|
|
if ($report.status -eq "verified_and_rolled_back" -and $report.write_plan.allowed -ne $true) {
|
|
throw "$Label report write plan was not allowed: $Path"
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; path={2}" -f $Label, $report.status, $Path)
|
|
}
|
|
|
|
function Assert-CodeWriteSavedStateReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path,
|
|
[switch]$RequireWrite
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.schema -ne "onec_code_write_saved_state_smoke.v1") {
|
|
throw "$Label report has unexpected schema '$($report.schema)': $Path"
|
|
}
|
|
if ($RequireWrite -and $report.status -in @("skipped_missing_target", "skipped_write_gate")) {
|
|
throw "$Label report skipped required write in strict mode: $Path"
|
|
}
|
|
if ($report.status -notin @("ok", "skipped_missing_target", "skipped_write_gate")) {
|
|
throw "$Label report has unexpected status '$($report.status)': $Path"
|
|
}
|
|
if ($report.status -eq "ok") {
|
|
$writeStep = @($report.steps | Where-Object { $_.name -eq "code.write apply" } | Select-Object -First 1)
|
|
if (-not $writeStep -or $writeStep.status -ne "applied" -or $writeStep.applied -ne $true) {
|
|
throw "$Label report did not apply code.write successfully: $Path"
|
|
}
|
|
if ($writeStep.write_mode.target -ne "saved_state" -or $writeStep.write_mode.activation_state -ne "not_activated") {
|
|
throw "$Label report write_mode is not saved_state/not_activated: $Path"
|
|
}
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; path={2}" -f $Label, $report.status, $Path)
|
|
}
|
|
|
|
function Assert-AgentWorkingViewReport {
|
|
param(
|
|
[string]$Label,
|
|
[string]$Path,
|
|
[switch]$RequireTarget
|
|
)
|
|
$report = Read-JsonReport -Label $Label -Path $Path
|
|
if ($report.schema -ne "onec_agent_working_view_report.v1") {
|
|
throw "$Label report has unexpected schema '$($report.schema)': $Path"
|
|
}
|
|
if ($RequireTarget -and $report.status -eq "skipped_missing_target") {
|
|
throw "$Label report skipped missing target in strict mode: $Path"
|
|
}
|
|
if ($report.status -notin @("ok", "skipped_missing_target")) {
|
|
throw "$Label report has unexpected status '$($report.status)': $Path"
|
|
}
|
|
if ($report.status -eq "ok") {
|
|
if (-not $report.save_forms_only_names -or $report.save_forms_only_names.Count -eq 0) {
|
|
throw "$Label report has no saved-state form names: $Path"
|
|
}
|
|
if ($report.code_read_working.current_state.source -ne "saved_state") {
|
|
throw "$Label report working code source is not saved_state: $Path"
|
|
}
|
|
if ($report.code_read_both.text_source -ne "saved_state") {
|
|
throw "$Label report both text_source is not saved_state: $Path"
|
|
}
|
|
}
|
|
Write-Host ("[report] {0}: status={1}; save_forms={2}; path={3}" -f $Label, $report.status, @($report.save_forms_only_names).Count, $Path)
|
|
}
|
|
|
|
try {
|
|
$baseIds = @(Normalize-BaseIds -Values $BaseId)
|
|
if (-not $baseIds) {
|
|
throw "At least one BaseId is required."
|
|
}
|
|
$duplicateBaseIds = @(Get-DuplicateValues -Values $baseIds)
|
|
if ($duplicateBaseIds) {
|
|
throw "Duplicate BaseId value(s): $($duplicateBaseIds -join ', ')"
|
|
}
|
|
|
|
if (-not $SkipRest) {
|
|
Write-HealthSummary -Label "REST adapter" -Url $AdapterUrl
|
|
foreach ($currentBaseId in $baseIds) {
|
|
$safeBaseId = ConvertTo-SafePathSegment -Value $currentBaseId
|
|
$reportDir = Join-Path "reports/1c-sql" $safeBaseId
|
|
$selectorChainReport = Join-Path $reportDir "selector-chain-rest-smoke.json"
|
|
$restCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_mcp_selector_chain.py",
|
|
"--live",
|
|
"--transport",
|
|
"rest",
|
|
"--adapter-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--json",
|
|
"--report",
|
|
$selectorChainReport
|
|
)
|
|
if ($RequireSelectorChainWritePlanComposition) {
|
|
$restCommand += "--require-write-plan-composition"
|
|
}
|
|
Invoke-CheckedCommand -Label "REST adapter selector-chain live smoke ($currentBaseId)" -Command (Add-ObjectSelectorArgs -Command $restCommand)
|
|
Assert-SelectorChainReport -Label "REST adapter selector-chain live smoke ($currentBaseId)" -Path $selectorChainReport -RequireComposition:$RequireSelectorChainWritePlanComposition
|
|
|
|
if (-not $SkipWritePlanSafetySmoke) {
|
|
$writePlanSafetyReport = Join-Path $reportDir "write-plan-safety-smoke.json"
|
|
$writePlanSafetyCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_write_plan_safety.py",
|
|
"--transport",
|
|
"rest",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$writePlanSafetyReport
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter write-plan safety smoke ($currentBaseId)" -Command $writePlanSafetyCommand
|
|
Assert-WritePlanSafetyReport -Label "REST adapter write-plan safety smoke ($currentBaseId)" -Path $writePlanSafetyReport
|
|
|
|
$writePreflightReport = Join-Path $reportDir "write-preflight-smoke.json"
|
|
$writePreflightCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_write_preflight.py",
|
|
"--transport",
|
|
"rest",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$writePreflightReport
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter write-preflight smoke ($currentBaseId)" -Command $writePreflightCommand
|
|
Assert-WritePreflightReport -Label "REST adapter write-preflight smoke ($currentBaseId)" -Path $writePreflightReport
|
|
}
|
|
|
|
if (-not $SkipWriteRollbackSafetySmoke) {
|
|
$writeRollbackSafetyReport = Join-Path $reportDir "write-rollback-safety-smoke.json"
|
|
$writeRollbackSafetyCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_write_rollback_safety.py",
|
|
"--transport",
|
|
"rest",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$writeRollbackSafetyReport
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter write-rollback safety smoke ($currentBaseId)" -Command $writeRollbackSafetyCommand
|
|
Assert-WriteRollbackSafetyReport -Label "REST adapter write-rollback safety smoke ($currentBaseId)" -Path $writeRollbackSafetyReport
|
|
}
|
|
|
|
if (-not $SkipSavedStateDiffSmoke) {
|
|
$savedStateDiffReport = Join-Path $reportDir "saved-state-diff-smoke.json"
|
|
$savedStateDiffCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_saved_state_diff.py",
|
|
"--transport",
|
|
"rest",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--saved-state-table",
|
|
$SavedStateTable,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$savedStateDiffReport
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state diff smoke ($currentBaseId)" -Command $savedStateDiffCommand
|
|
Assert-SavedStateDiffReport -Label "REST adapter saved-state diff smoke ($currentBaseId)" -Path $savedStateDiffReport
|
|
|
|
$savedStateChangesReport = Join-Path $reportDir "saved-state-changes-smoke.json"
|
|
$savedStateChangesCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_saved_state_changes.py",
|
|
"--transport",
|
|
"rest",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$savedStateChangesReport
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state changes smoke ($currentBaseId)" -Command $savedStateChangesCommand
|
|
Assert-SavedStateChangesReport -Label "REST adapter saved-state changes smoke ($currentBaseId)" -Path $savedStateChangesReport
|
|
}
|
|
|
|
if (-not $SkipSavedStateWriteSmoke) {
|
|
$readinessReport = Join-Path $reportDir "saved-state-strict-readiness.json"
|
|
$readinessCommand = @(
|
|
"python",
|
|
"scripts/check_1c_saved_state_strict_readiness.py",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--saved-state-table",
|
|
$SavedStateTable,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$readinessReport,
|
|
"--json"
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state strict readiness ($currentBaseId)" -Command $readinessCommand
|
|
|
|
$readiness = Get-Content -Raw -LiteralPath $readinessReport | ConvertFrom-Json
|
|
if (-not $readiness.ready) {
|
|
$copyPlanReport = Join-Path $reportDir "saved-state-copy-plan.json"
|
|
$copyPlanCommand = @(
|
|
"python",
|
|
"scripts/plan_1c_saved_state_copy.py",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--target-table",
|
|
$SavedStateTable,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$copyPlanReport,
|
|
"--json"
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state copy plan ($currentBaseId)" -Command (Add-ObjectSelectorArgs -Command $copyPlanCommand)
|
|
|
|
$prepareSqlPath = Join-Path $reportDir "prepare-saved-state-copy.sql"
|
|
$prepareSqlReport = Join-Path $reportDir "prepare-saved-state-copy-sql.json"
|
|
$prepareSqlCommand = @(
|
|
"python",
|
|
"scripts/prepare_1c_saved_state_copy_sql.py",
|
|
"--plan",
|
|
$copyPlanReport,
|
|
"--expected-base-id",
|
|
$currentBaseId,
|
|
"--expected-target-table",
|
|
$SavedStateTable,
|
|
"--sql-out",
|
|
$prepareSqlPath,
|
|
"--report",
|
|
$prepareSqlReport,
|
|
"--json"
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state prepare SQL artifact ($currentBaseId)" -Command $prepareSqlCommand
|
|
|
|
$cleanupSqlPath = Join-Path $reportDir "cleanup-saved-state-copy.sql"
|
|
$cleanupSqlReport = Join-Path $reportDir "cleanup-saved-state-copy-sql.json"
|
|
$cleanupSqlCommand = @(
|
|
"python",
|
|
"scripts/prepare_1c_saved_state_cleanup_sql.py",
|
|
"--plan",
|
|
$copyPlanReport,
|
|
"--expected-base-id",
|
|
$currentBaseId,
|
|
"--expected-target-table",
|
|
$SavedStateTable,
|
|
"--sql-out",
|
|
$cleanupSqlPath,
|
|
"--report",
|
|
$cleanupSqlReport,
|
|
"--json"
|
|
)
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state cleanup SQL artifact ($currentBaseId)" -Command $cleanupSqlCommand
|
|
} else {
|
|
Write-Host "[skip] Saved-state copy artifacts: $SavedStateTable is already ready for $currentBaseId"
|
|
}
|
|
|
|
$formReport = Join-Path $reportDir "saved-state-write-routes-smoke.json"
|
|
$moduleReport = Join-Path $reportDir "module-stream-write-smoke-script.json"
|
|
$allowEmptyArgs = @()
|
|
if (-not $RequireSavedStateWriteSmoke) {
|
|
$allowEmptyArgs += "--allow-empty-saved-state"
|
|
}
|
|
$formWriteCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_saved_state_write_routes.py",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--table",
|
|
$SavedStateTable,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$formReport
|
|
) + $allowEmptyArgs
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state form write smoke ($currentBaseId)" -Command $formWriteCommand
|
|
Assert-SavedStateFormWriteReport -Label "REST adapter saved-state form write smoke ($currentBaseId)" -Path $formReport -RequireWrite:$RequireSavedStateWriteSmoke
|
|
|
|
$moduleWriteCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_saved_state_module_write.py",
|
|
"--base-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--table",
|
|
$SavedStateTable,
|
|
"--file-name",
|
|
"placeholder.0",
|
|
"--stream-index",
|
|
"0",
|
|
"--report",
|
|
$moduleReport,
|
|
"--timeout-seconds",
|
|
$TimeoutSec.ToString()
|
|
) + $allowEmptyArgs
|
|
Invoke-CheckedCommand -Label "REST adapter saved-state module write smoke ($currentBaseId)" -Command $moduleWriteCommand
|
|
Assert-SavedStateModuleWriteReport -Label "REST adapter saved-state module write smoke ($currentBaseId)" -Path $moduleReport -RequireWrite:$RequireSavedStateWriteSmoke
|
|
}
|
|
|
|
if (-not $SkipCodeWriteSavedStateSmoke) {
|
|
$codeWriteReport = Join-Path $reportDir "code-write-saved-state-rest-smoke.json"
|
|
$codeWriteCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_code_write_saved_state.py",
|
|
"--transport",
|
|
"rest",
|
|
"--adapter-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--report",
|
|
$codeWriteReport,
|
|
"--json"
|
|
)
|
|
if (-not $RequireCodeWriteSavedStateSmoke) {
|
|
$codeWriteCommand += @("--allow-missing-target", "--allow-blocked-write-gate")
|
|
}
|
|
Invoke-CheckedCommand -Label "REST adapter code.write saved-state smoke ($currentBaseId)" -Command $codeWriteCommand
|
|
Assert-CodeWriteSavedStateReport -Label "REST adapter code.write saved-state smoke ($currentBaseId)" -Path $codeWriteReport -RequireWrite:$RequireCodeWriteSavedStateSmoke
|
|
|
|
$agentViewReport = Join-Path $reportDir "agent-working-view.json"
|
|
$agentViewCommand = @(
|
|
"python",
|
|
"scripts/report_1c_agent_working_view.py",
|
|
"--adapter-url",
|
|
$AdapterUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$agentViewReport,
|
|
"--json"
|
|
)
|
|
if (-not $RequireCodeWriteSavedStateSmoke) {
|
|
$agentViewCommand += "--allow-missing-target"
|
|
}
|
|
Invoke-CheckedCommand -Label "REST adapter agent working view report ($currentBaseId)" -Command $agentViewCommand
|
|
Assert-AgentWorkingViewReport -Label "REST adapter agent working view report ($currentBaseId)" -Path $agentViewReport -RequireTarget:$RequireCodeWriteSavedStateSmoke
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $SkipMcp) {
|
|
Write-HealthSummary -Label "MCP proxy" -Url $McpUrl
|
|
foreach ($currentBaseId in $baseIds) {
|
|
$safeBaseId = ConvertTo-SafePathSegment -Value $currentBaseId
|
|
$reportDir = Join-Path "reports/1c-sql" $safeBaseId
|
|
$selectorChainReport = Join-Path $reportDir "selector-chain-mcp-smoke.json"
|
|
$mcpCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_mcp_selector_chain.py",
|
|
"--live",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--json",
|
|
"--report",
|
|
$selectorChainReport
|
|
)
|
|
if ($RequireSelectorChainWritePlanComposition) {
|
|
$mcpCommand += "--require-write-plan-composition"
|
|
}
|
|
Invoke-CheckedCommand -Label "MCP proxy selector-chain live smoke ($currentBaseId)" -Command (Add-ObjectSelectorArgs -Command $mcpCommand)
|
|
Assert-SelectorChainReport -Label "MCP proxy selector-chain live smoke ($currentBaseId)" -Path $selectorChainReport -RequireComposition:$RequireSelectorChainWritePlanComposition
|
|
|
|
if (-not $SkipWritePlanSafetySmoke) {
|
|
$mcpWritePlanSafetyReport = Join-Path $reportDir "write-plan-safety-mcp-smoke.json"
|
|
$mcpWritePlanSafetyCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_write_plan_safety.py",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$mcpWritePlanSafetyReport
|
|
)
|
|
Invoke-CheckedCommand -Label "MCP proxy write-plan safety smoke ($currentBaseId)" -Command $mcpWritePlanSafetyCommand
|
|
Assert-WritePlanSafetyReport -Label "MCP proxy write-plan safety smoke ($currentBaseId)" -Path $mcpWritePlanSafetyReport
|
|
|
|
$mcpWritePreflightReport = Join-Path $reportDir "write-preflight-mcp-smoke.json"
|
|
$mcpWritePreflightCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_write_preflight.py",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$mcpWritePreflightReport
|
|
)
|
|
Invoke-CheckedCommand -Label "MCP proxy write-preflight smoke ($currentBaseId)" -Command $mcpWritePreflightCommand
|
|
Assert-WritePreflightReport -Label "MCP proxy write-preflight smoke ($currentBaseId)" -Path $mcpWritePreflightReport
|
|
}
|
|
|
|
if (-not $SkipWriteRollbackSafetySmoke) {
|
|
$mcpWriteRollbackSafetyReport = Join-Path $reportDir "write-rollback-safety-mcp-smoke.json"
|
|
$mcpWriteRollbackSafetyCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_write_rollback_safety.py",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$mcpWriteRollbackSafetyReport
|
|
)
|
|
Invoke-CheckedCommand -Label "MCP proxy write-rollback safety smoke ($currentBaseId)" -Command $mcpWriteRollbackSafetyCommand
|
|
Assert-WriteRollbackSafetyReport -Label "MCP proxy write-rollback safety smoke ($currentBaseId)" -Path $mcpWriteRollbackSafetyReport
|
|
}
|
|
|
|
if (-not $SkipSavedStateDiffSmoke) {
|
|
$mcpSavedStateDiffReport = Join-Path $reportDir "saved-state-diff-mcp-smoke.json"
|
|
$mcpSavedStateDiffCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_saved_state_diff.py",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--saved-state-table",
|
|
$SavedStateTable,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$mcpSavedStateDiffReport
|
|
)
|
|
Invoke-CheckedCommand -Label "MCP proxy saved-state diff smoke ($currentBaseId)" -Command $mcpSavedStateDiffCommand
|
|
Assert-SavedStateDiffReport -Label "MCP proxy saved-state diff smoke ($currentBaseId)" -Path $mcpSavedStateDiffReport
|
|
|
|
$mcpSavedStateChangesReport = Join-Path $reportDir "saved-state-changes-mcp-smoke.json"
|
|
$mcpSavedStateChangesCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_saved_state_changes.py",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$mcpSavedStateChangesReport
|
|
)
|
|
Invoke-CheckedCommand -Label "MCP proxy saved-state changes smoke ($currentBaseId)" -Command $mcpSavedStateChangesCommand
|
|
Assert-SavedStateChangesReport -Label "MCP proxy saved-state changes smoke ($currentBaseId)" -Path $mcpSavedStateChangesReport
|
|
}
|
|
|
|
if (-not $SkipCodeWriteSavedStateSmoke) {
|
|
$mcpCodeWriteReport = Join-Path $reportDir "code-write-saved-state-mcp-smoke.json"
|
|
$mcpCodeWriteCommand = @(
|
|
"python",
|
|
"scripts/smoke_1c_code_write_saved_state.py",
|
|
"--transport",
|
|
"mcp",
|
|
"--mcp-url",
|
|
$McpUrl,
|
|
"--base-id",
|
|
$currentBaseId,
|
|
"--timeout",
|
|
$TimeoutSec.ToString(),
|
|
"--report",
|
|
$mcpCodeWriteReport,
|
|
"--json"
|
|
)
|
|
if (-not $RequireCodeWriteSavedStateSmoke) {
|
|
$mcpCodeWriteCommand += @("--allow-missing-target", "--allow-blocked-write-gate")
|
|
}
|
|
Invoke-CheckedCommand -Label "MCP proxy code.write saved-state smoke ($currentBaseId)" -Command $mcpCodeWriteCommand
|
|
Assert-CodeWriteSavedStateReport -Label "MCP proxy code.write saved-state smoke ($currentBaseId)" -Path $mcpCodeWriteReport -RequireWrite:$RequireCodeWriteSavedStateSmoke
|
|
}
|
|
}
|
|
}
|
|
|
|
$reportsCheckCommand = @(
|
|
"python",
|
|
"scripts/check_1c_verify_reports.py",
|
|
"--base-id"
|
|
)
|
|
$reportsCheckCommand += $baseIds
|
|
$reportsCheckCommand += @("--rest-adapter-url", $AdapterUrl)
|
|
$reportsCheckCommand += @("--mcp-url", $McpUrl)
|
|
$reportsCheckCommand += @("--saved-state-table", $SavedStateTable)
|
|
if ($SkipRest) {
|
|
$reportsCheckCommand += "--skip-rest"
|
|
}
|
|
if ($SkipMcp) {
|
|
$reportsCheckCommand += "--skip-mcp"
|
|
}
|
|
if ($SkipWritePlanSafetySmoke) {
|
|
$reportsCheckCommand += "--skip-write-plan-safety-smoke"
|
|
}
|
|
if ($SkipWriteRollbackSafetySmoke) {
|
|
$reportsCheckCommand += "--skip-write-rollback-safety-smoke"
|
|
}
|
|
if ($SkipSavedStateDiffSmoke) {
|
|
$reportsCheckCommand += "--skip-saved-state-diff-smoke"
|
|
}
|
|
if ($SkipSavedStateWriteSmoke) {
|
|
$reportsCheckCommand += "--skip-saved-state-write-smoke"
|
|
}
|
|
if ($SkipCodeWriteSavedStateSmoke) {
|
|
$reportsCheckCommand += "--skip-code-write-saved-state-smoke"
|
|
}
|
|
if ($RequireSavedStateWriteSmoke) {
|
|
$reportsCheckCommand += "--require-saved-state-write-smoke"
|
|
}
|
|
if ($RequireCodeWriteSavedStateSmoke) {
|
|
$reportsCheckCommand += "--require-code-write-saved-state-smoke"
|
|
}
|
|
if ($RequireSelectorChainWritePlanComposition) {
|
|
$reportsCheckCommand += "--require-selector-chain-write-plan-composition"
|
|
}
|
|
Invoke-CheckedCommand -Label "Persisted 1C verify report check" -Command $reportsCheckCommand
|
|
|
|
Write-Host "[done] 1C adapter deployment verification passed"
|
|
exit 0
|
|
} catch {
|
|
Write-Error $_
|
|
exit 1
|
|
}
|