feat(observatory): install local M49 worker path

This commit is contained in:
DCCONSTRUCTIONS
2026-08-31 16:51:10 +03:00
parent 2f6e45bc96
commit 9c69d81296
19 changed files with 2252 additions and 212 deletions
@@ -0,0 +1,401 @@
[CmdletBinding()]
param()
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
# This is one exact, additive Worker 006 transition. It never recompiles the
# runner, retags an image, starts a container, or changes the candidate files.
$WorkerId = "worker-006"
$ExpectedComputer = "DESKTOP-OPJ8J04"
$CandidateId = "beef090b79ab0e019cff976033d0446c45d4746ee921e02e8076a5a67f21817e"
$CandidateArchiveSha256 = "70cd95e611381e0f1d362f2e201b7615bb9530d69e26aafbf949b19aa523c630"
$CandidateReleaseSha256 = "a4fa00bf02c44e584667d4d48c6ec6a55832c704e7b47786dea638b59945c5db"
$CandidateBuildSealSha256 = "4b29155896db9f48461ea4af6b4c02a2c2b0224dd65748e827e5ca1125b8648d"
$CandidateReceiptSha256 = "a6b32fde8c09faa5419fb9c75a8207d4016a1d044ede3d6d6148da00b3092b8c"
$SourceRevision = "2f6e45bc96f2c9f65b8830dc536784e9aa85fd87"
$ReleaseId = "m49-tgs-portable-executor-v1"
$ReleaseParent = "D:\NDC_MISSIONCORE\runtime\releases\observatory-portable"
$CandidateRootName = "m49-tgs-portable-candidate-$CandidateId"
$RuntimeReleaseRoot = "/release"
$BaseImageSha256 = "7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f"
$ExecutorImageSha256 = "f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3"
$ExecutorImageSizeBytes = 1030212146
$ExecutorImageTag = "ndc/mission-core-m49-tgs-portable-executor:beef090b79ab0e01-candidate"
$RunnerSha256 = "7be449392ef161fb8713b4c984705d2373bc3cd05645332d92b88a8bff0c7db3"
$RunnerBytes = 274168
$ProfileSha256 = "6128d6af7e6137f9a9473db045e3b155e2105319159f17c32f344b4aedf823a9"
$ProfileBytes = 1683
$RuntimeBuildSealSha256 = "e3bb2e91c70712eff74e8e69718075a407e042fb494616d65984500da42b21a9"
$RuntimeBuildSealBytes = 1014
$InstalledReleaseSha256 = "c5b0670d943fe0452ef4bbfbc144ab2439a1a674f9ef164798ad9f8b1ecc29fa"
$InstalledReleaseBytes = 1693
$ReadyReceiptSha256 = "b560ff9e02746cbb760502f2a3b4b7bd564f95ab52d1149d189927a326b1645a"
$ReadyReceiptBytes = 2672
$ResultContractSha256 = "9dd80c8e2504559d2156fca933de6eb27901e35305e6853aeb84707e1cb13892"
$RunnerSourceSha256 = "52813392aabd02efc5c2b8f7c22ed88e3ef4cc8ad3aafeba2792efe503e29fe9"
$RunnerWrapperSha256 = "2d6c32560682647f868e4ce4c2605749f17c60482a609f8c03ff951411f48ffb"
$FixtureSmokeSha256 = "b8bc1cf9f21f69904bb64c6384db6fe301faf10f8041cc405a77b011602eaf04"
$ProtectedRuntime = @(
[ordered]@{ name = "ndc-mission-core-triton"; container_id = "4232fb040062a8384809e73612baa92b343ddcb60f00c23e7091eb4909959223" },
[ordered]@{ name = "ndc-mission-core-perception-worker"; container_id = "db2024d05098a6beb6b73bbf43f02c88ede586a4664b2c91182f436a42b3e3ff" },
[ordered]@{ name = "ndc-gaussian-pipeline-gaussian-gateway-1"; container_id = "67c6b7bdf37a3745a67126e5acc5929230b4f51e9e353dac4828df90c5f9df9f" },
[ordered]@{ name = "ndc-gaussian-pipeline-gaussian-pipeline-1"; container_id = "ae855b3b3414ae94dcd9bdc2c8223fe278109484ce828cd82fe5ef0adecf17c9" },
[ordered]@{ name = "ndc-gaussian-pipeline-gaussian-terrain-executor-1"; container_id = "4624a9fbcad8cda9d0ff0bc0a5b9bb09eb2340ec93f694033c5b3d2cd1806265" }
)
$RuntimeBuildSealPayload = @'
{"authority":{"actuation_allowed":false,"commands_enabled":false,"navigation_or_safety_accepted":false,"production_accepted":false},"binary":{"byte_length":274168,"file_name":"run_m49_tgs_portable","format":"elf","sha256":"7be449392ef161fb8713b4c984705d2373bc3cd05645332d92b88a8bff0c7db3"},"build_image_sha256":"7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f","compiler_contract":{"compiler":"g++","eigen_include":"/usr/include/eigen3","flags":["-O3","-DNDEBUG","-pthread"],"language_standard":"c++17","travel_include":"/opt/travel/src/TRAVEL/cpp/travel/core"},"profile_sha256":"6128d6af7e6137f9a9473db045e3b155e2105319159f17c32f344b4aedf823a9","runner_source_sha256":"52813392aabd02efc5c2b8f7c22ed88e3ef4cc8ad3aafeba2792efe503e29fe9","runner_wrapper_sha256":"2d6c32560682647f868e4ce4c2605749f17c60482a609f8c03ff951411f48ffb","schema_version":"missioncore.m49-tgs-portable-compiled-runner-build/v1","source_revision":"2f6e45bc96f2c9f65b8830dc536784e9aa85fd87","source_state":"committed-snapshot"}
'@.Trim()
$InstalledReleasePayload = @'
{"authority":{"actuation_allowed":false,"commands_enabled":false,"navigation_or_safety_accepted":false,"production_accepted":false},"base_image_sha256":"7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f","blockers":[],"candidate":{"candidate_sha256":"beef090b79ab0e019cff976033d0446c45d4746ee921e02e8076a5a67f21817e","release_sha256":"a4fa00bf02c44e584667d4d48c6ec6a55832c704e7b47786dea638b59945c5db","worker_installation_receipt_sha256":"a6b32fde8c09faa5419fb9c75a8207d4016a1d044ede3d6d6148da00b3092b8c"},"compiled_runner":{"byte_length":274168,"relative_path":"run_m49_tgs_portable","sha256":"7be449392ef161fb8713b4c984705d2373bc3cd05645332d92b88a8bff0c7db3"},"compiled_runner_build_seal":{"byte_length":1014,"relative_path":"compiled-runner-build.json","sha256":"e3bb2e91c70712eff74e8e69718075a407e042fb494616d65984500da42b21a9"},"executor_image":{"sha256":"f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3","size_bytes":1030212146},"fixture_smoke":{"classified_points_per_frame":124637,"frame_count":2,"input_points_per_frame":124668,"network":"none","result":"passed","source":"pinned TRAVEL KITTI fixture"},"profile":{"byte_length":1683,"relative_path":"m49-tgs-portable-v2.json","sha256":"6128d6af7e6137f9a9473db045e3b155e2105319159f17c32f344b4aedf823a9"},"release_id":"m49-tgs-portable-executor-v1","result_contract_sha256":"9dd80c8e2504559d2156fca933de6eb27901e35305e6853aeb84707e1cb13892","schema_version":"missioncore.m49-tgs-portable-executor-installed/v1","source_archive_sha256":"70cd95e611381e0f1d362f2e201b7615bb9530d69e26aafbf949b19aa523c630","source_revision":"2f6e45bc96f2c9f65b8830dc536784e9aa85fd87","state":"ready","worker_id":"worker-006"}
'@.Trim()
$ReadyReceiptPayload = @'
{"authority":{"actuation_allowed":false,"commands_enabled":false,"navigation_or_safety_accepted":false,"production_accepted":false},"base_image_sha256":"7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f","blockers":[],"candidate_release_sha256":"a4fa00bf02c44e584667d4d48c6ec6a55832c704e7b47786dea638b59945c5db","candidate_sha256":"beef090b79ab0e019cff976033d0446c45d4746ee921e02e8076a5a67f21817e","candidate_worker_installation_receipt_sha256":"a6b32fde8c09faa5419fb9c75a8207d4016a1d044ede3d6d6148da00b3092b8c","computer_name":"DESKTOP-OPJ8J04","executor_image_sha256":"f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3","files":[{"asset_id":"m49-portable-compiled-runner","byte_length":274168,"relative_path":"run_m49_tgs_portable","sha256":"7be449392ef161fb8713b4c984705d2373bc3cd05645332d92b88a8bff0c7db3"},{"asset_id":"m49-portable-compiled-runner-build-seal","byte_length":1014,"relative_path":"compiled-runner-build.json","sha256":"e3bb2e91c70712eff74e8e69718075a407e042fb494616d65984500da42b21a9"},{"asset_id":"m49-portable-executor-release","byte_length":1693,"relative_path":"executor-release.json","sha256":"c5b0670d943fe0452ef4bbfbc144ab2439a1a674f9ef164798ad9f8b1ecc29fa"},{"asset_id":"m49-portable-profile","byte_length":1683,"relative_path":"m49-tgs-portable-v2.json","sha256":"6128d6af7e6137f9a9473db045e3b155e2105319159f17c32f344b4aedf823a9"}],"fixture_smoke":"passed","legacy_m49_task_state":"Ready","protected_runtime":[{"container_id":"4232fb040062a8384809e73612baa92b343ddcb60f00c23e7091eb4909959223","name":"ndc-mission-core-triton"},{"container_id":"db2024d05098a6beb6b73bbf43f02c88ede586a4664b2c91182f436a42b3e3ff","name":"ndc-mission-core-perception-worker"},{"container_id":"67c6b7bdf37a3745a67126e5acc5929230b4f51e9e353dac4828df90c5f9df9f","name":"ndc-gaussian-pipeline-gaussian-gateway-1"},{"container_id":"ae855b3b3414ae94dcd9bdc2c8223fe278109484ce828cd82fe5ef0adecf17c9","name":"ndc-gaussian-pipeline-gaussian-pipeline-1"},{"container_id":"4624a9fbcad8cda9d0ff0bc0a5b9bb09eb2340ec93f694033c5b3d2cd1806265","name":"ndc-gaussian-pipeline-gaussian-terrain-executor-1"}],"receipt_state":"installed-ready","release_id":"m49-tgs-portable-executor-v1","release_root":"D:\\NDC_MISSIONCORE\\runtime\\releases\\observatory-portable\\m49-tgs-portable-candidate-beef090b79ab0e019cff976033d0446c45d4746ee921e02e8076a5a67f21817e\\ready","release_sha256":"c5b0670d943fe0452ef4bbfbc144ab2439a1a674f9ef164798ad9f8b1ecc29fa","runtime_release_root":"/release","schema_version":"missioncore.m49-tgs-portable-worker-installation-ready-receipt/v1","source_revision":"2f6e45bc96f2c9f65b8830dc536784e9aa85fd87","worker_id":"worker-006"}
'@.Trim()
function Assert-LastExitCode([string]$Operation) {
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Resolve-DDirectory([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
if (
-not $item.PSIsContainer -or
($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or
[IO.Path]::GetPathRoot($item.FullName).TrimEnd("\") -ine "D:"
) {
throw "$Label must be a real D: directory"
}
return $item.FullName
}
function Resolve-DFile([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
if (
$item.PSIsContainer -or
($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or
[IO.Path]::GetPathRoot($item.FullName).TrimEnd("\") -ine "D:"
) {
throw "$Label must be a real D: file"
}
return $item.FullName
}
function Get-Sha256([string]$Path) {
return (Get-FileHash -Algorithm SHA256 -LiteralPath $Path).Hash.ToLowerInvariant()
}
function Get-PayloadSha256([string]$Value) {
$encoding = New-Object System.Text.UTF8Encoding($false)
$bytes = $encoding.GetBytes($Value)
$algorithm = [Security.Cryptography.SHA256]::Create()
try {
return ([BitConverter]::ToString($algorithm.ComputeHash($bytes))).Replace("-", "").ToLowerInvariant()
} finally {
$algorithm.Dispose()
}
}
function Get-PayloadBytes([string]$Value) {
$encoding = New-Object System.Text.UTF8Encoding($false)
return $encoding.GetByteCount($Value)
}
function Write-Utf8NoBom([string]$Path, [string]$Value) {
$encoding = New-Object System.Text.UTF8Encoding($false)
[IO.File]::WriteAllText($Path, $Value, $encoding)
}
function Assert-ExactFile(
[string]$Path,
[string]$Sha256,
[long]$ByteLength,
[string]$Label
) {
$resolved = Resolve-DFile $Path $Label
$item = Get-Item -LiteralPath $resolved -Force
if ($item.Length -ne $ByteLength -or (Get-Sha256 $resolved) -cne $Sha256) {
throw "$Label identity changed"
}
return $resolved
}
function Assert-ExactDigest([string]$Path, [string]$Sha256, [string]$Label) {
$resolved = Resolve-DFile $Path $Label
if ((Get-Sha256 $resolved) -cne $Sha256) {
throw "$Label identity changed"
}
return $resolved
}
function Read-ExactJson(
[string]$Path,
[string]$Sha256,
[string]$Label
) {
$resolved = Resolve-DFile $Path $Label
if ((Get-Sha256 $resolved) -cne $Sha256) {
throw "$Label digest changed"
}
try {
return Get-Content -LiteralPath $resolved -Raw | ConvertFrom-Json
} catch {
throw "$Label is not valid JSON"
}
}
function Get-ProtectedRuntime() {
$names = @($ProtectedRuntime | ForEach-Object { [string]$_.name })
$rows = @(((& docker inspect $names) | ConvertFrom-Json))
Assert-LastExitCode "protected runtime inspection"
if ($rows.Count -ne $ProtectedRuntime.Count) {
throw "protected runtime inventory is incomplete"
}
return $rows
}
function Assert-ProtectedRuntime([object[]]$Rows) {
foreach ($expected in $ProtectedRuntime) {
$dockerName = "/$([string]$expected.name)"
$matched = @($Rows | Where-Object { [string]$_.Name -ceq $dockerName })
if (
$matched.Count -ne 1 -or
[string]$matched[0].Id -cne [string]$expected.container_id -or
-not $matched[0].State.Running
) {
throw "protected runtime identity changed: $dockerName"
}
if (
[string]$expected.name -cne "ndc-mission-core-perception-worker" -and
[string]$matched[0].State.Health.Status -cne "healthy"
) {
throw "protected runtime health changed: $dockerName"
}
}
}
function Assert-LegacyTaskReady() {
$task = Get-ScheduledTask -TaskName "MissionCore-M49TgsFullShadow" -ErrorAction SilentlyContinue
if ($null -eq $task -or [string]$task.State -cne "Ready") {
throw "legacy M49 scheduled task is not Ready"
}
}
function Assert-ReadyRoot([string]$Path) {
$ready = Resolve-DDirectory $Path "portable M4.9 ready release"
$expectedNames = @(
"compiled-runner-build.json",
"executor-release.json",
"m49-tgs-portable-v2.json",
"run_m49_tgs_portable",
"worker-installation-receipt.json"
)
$children = @(Get-ChildItem -LiteralPath $ready -Force)
$names = @($children | ForEach-Object { $_.Name } | Sort-Object)
if (
$children.Count -ne $expectedNames.Count -or
(Compare-Object -ReferenceObject $expectedNames -DifferenceObject $names)
) {
throw "portable M4.9 ready release contains unexpected files"
}
$null = Assert-ExactFile (Join-Path $ready "run_m49_tgs_portable") $RunnerSha256 $RunnerBytes "portable M4.9 ready runner"
$null = Assert-ExactFile (Join-Path $ready "compiled-runner-build.json") $RuntimeBuildSealSha256 $RuntimeBuildSealBytes "portable M4.9 runtime build seal"
$null = Assert-ExactFile (Join-Path $ready "m49-tgs-portable-v2.json") $ProfileSha256 $ProfileBytes "portable M4.9 ready profile"
$null = Assert-ExactFile (Join-Path $ready "executor-release.json") $InstalledReleaseSha256 $InstalledReleaseBytes "portable M4.9 installed release"
$null = Assert-ExactFile (Join-Path $ready "worker-installation-receipt.json") $ReadyReceiptSha256 $ReadyReceiptBytes "portable M4.9 ready receipt"
return $ready
}
if ($env:COMPUTERNAME -cne $ExpectedComputer) {
throw "portable M4.9 promotion is pinned to Worker 006"
}
if (
(Get-PayloadSha256 $RuntimeBuildSealPayload) -cne $RuntimeBuildSealSha256 -or
(Get-PayloadBytes $RuntimeBuildSealPayload) -ne $RuntimeBuildSealBytes -or
(Get-PayloadSha256 $InstalledReleasePayload) -cne $InstalledReleaseSha256 -or
(Get-PayloadBytes $InstalledReleasePayload) -ne $InstalledReleaseBytes -or
(Get-PayloadSha256 $ReadyReceiptPayload) -cne $ReadyReceiptSha256 -or
(Get-PayloadBytes $ReadyReceiptPayload) -ne $ReadyReceiptBytes
) {
throw "portable M4.9 promotion payload identity changed"
}
$releaseParent = Resolve-DDirectory $ReleaseParent "portable Observatory release parent"
$candidateRoot = Resolve-DDirectory (Join-Path $releaseParent $CandidateRootName) "portable M4.9 candidate root"
if ((Split-Path -Parent $candidateRoot) -ine $releaseParent) {
throw "portable M4.9 candidate escaped its release parent"
}
$null = Assert-ExactDigest (Join-Path $candidateRoot "candidate.tgz") $CandidateArchiveSha256 "portable M4.9 candidate archive"
$installedCandidate = Resolve-DDirectory (Join-Path $candidateRoot "installed") "portable M4.9 installed candidate"
$candidateRelease = Read-ExactJson (Join-Path $installedCandidate "executor-release-candidate.json") $CandidateReleaseSha256 "portable M4.9 candidate release"
$candidateBuildSeal = Read-ExactJson (Join-Path $installedCandidate "compiled-runner-build-candidate.json") $CandidateBuildSealSha256 "portable M4.9 candidate build seal"
$candidateReceipt = Read-ExactJson (Join-Path $installedCandidate "worker-installation-receipt.json") $CandidateReceiptSha256 "portable M4.9 candidate receipt"
$candidateRunner = Assert-ExactFile (Join-Path $installedCandidate "run_m49_tgs_portable") $RunnerSha256 $RunnerBytes "portable M4.9 candidate runner"
$candidateProfile = Assert-ExactFile (Join-Path $installedCandidate "m49-tgs-portable-v2.json") $ProfileSha256 $ProfileBytes "portable M4.9 candidate profile"
if (
[string]$candidateRelease.schema_version -cne "missioncore.m49-tgs-portable-executor-installed-candidate/v1" -or
[string]$candidateRelease.state -cne "installed-candidate-blocked" -or
[string]$candidateRelease.worker_id -cne $WorkerId -or
[string]$candidateRelease.candidate_sha256 -cne $CandidateId -or
[string]$candidateRelease.source_revision -cne $SourceRevision -or
[string]$candidateRelease.source_state -cne "committed-snapshot" -or
[string]$candidateRelease.source_archive_sha256 -cne $CandidateArchiveSha256 -or
[string]$candidateRelease.base_image_sha256 -cne $BaseImageSha256 -or
[string]$candidateRelease.executor_image.sha256 -cne $ExecutorImageSha256 -or
[long]$candidateRelease.executor_image.size_bytes -ne $ExecutorImageSizeBytes -or
[string]$candidateRelease.compiled_runner.sha256 -cne $RunnerSha256 -or
[long]$candidateRelease.compiled_runner.byte_length -ne $RunnerBytes -or
[string]$candidateRelease.compiled_runner_build_seal.sha256 -cne $CandidateBuildSealSha256 -or
[string]$candidateRelease.profile.sha256 -cne $ProfileSha256 -or
[string]$candidateRelease.result_contract_sha256 -cne $ResultContractSha256 -or
[string]$candidateRelease.fixture_smoke.result -cne "passed" -or
@($candidateRelease.blockers).Count -ne 1 -or
[string]$candidateRelease.blockers[0] -cne "runtime-registry-promotion-pending"
) {
throw "portable M4.9 candidate release is not promotable"
}
if (
[string]$candidateBuildSeal.schema_version -cne "missioncore.m49-tgs-portable-compiled-runner-build-candidate/v1" -or
[string]$candidateBuildSeal.source_revision -cne $SourceRevision -or
[string]$candidateBuildSeal.source_state -cne "committed-snapshot" -or
[string]$candidateBuildSeal.candidate_sha256 -cne $CandidateId -or
[string]$candidateBuildSeal.build_image_sha256 -cne $BaseImageSha256 -or
[string]$candidateBuildSeal.profile_sha256 -cne $ProfileSha256 -or
[string]$candidateBuildSeal.runner_source_sha256 -cne $RunnerSourceSha256 -or
[string]$candidateBuildSeal.runner_wrapper_sha256 -cne $RunnerWrapperSha256 -or
[string]$candidateBuildSeal.binary.sha256 -cne $RunnerSha256 -or
[long]$candidateBuildSeal.binary.byte_length -ne $RunnerBytes
) {
throw "portable M4.9 candidate build seal is not promotable"
}
if (
[string]$candidateReceipt.schema_version -cne "missioncore.m49-tgs-portable-worker-installation-receipt/v1" -or
[string]$candidateReceipt.receipt_state -cne "installed-candidate-blocked" -or
[string]$candidateReceipt.worker_id -cne $WorkerId -or
[string]$candidateReceipt.computer_name -cne $ExpectedComputer -or
[string]$candidateReceipt.release_id -cne $ReleaseId -or
[string]$candidateReceipt.release_sha256 -cne $CandidateReleaseSha256 -or
[string]$candidateReceipt.executor_image_sha256 -cne $ExecutorImageSha256 -or
[string]$candidateReceipt.compiled_runner_sha256 -cne $RunnerSha256 -or
[string]$candidateReceipt.compiled_runner_build_seal_sha256 -cne $CandidateBuildSealSha256 -or
[string]$candidateReceipt.fixture_smoke -cne "passed" -or
@($candidateReceipt.blockers).Count -ne 1 -or
[string]$candidateReceipt.blockers[0] -cne "runtime-registry-promotion-pending"
) {
throw "portable M4.9 candidate receipt is not promotable"
}
if (@($candidateReceipt.protected_runtime).Count -ne $ProtectedRuntime.Count) {
throw "portable M4.9 candidate receipt protected runtime is incomplete"
}
foreach ($expected in $ProtectedRuntime) {
$matched = @(
$candidateReceipt.protected_runtime |
Where-Object {
[string]$_.name -ceq [string]$expected.name -and
[string]$_.container_id -ceq [string]$expected.container_id
}
)
if ($matched.Count -ne 1) {
throw "portable M4.9 candidate receipt protected runtime changed"
}
}
$baseImage = @(((& docker image inspect "sha256:$BaseImageSha256") | ConvertFrom-Json))
Assert-LastExitCode "portable M4.9 base image inspection"
if ($baseImage.Count -ne 1 -or [string]$baseImage[0].Id -cne "sha256:$BaseImageSha256") {
throw "portable M4.9 base image identity changed"
}
$executorImage = @(((& docker image inspect $ExecutorImageTag) | ConvertFrom-Json))
Assert-LastExitCode "portable M4.9 executor image inspection"
if (
$executorImage.Count -ne 1 -or
[string]$executorImage[0].Id -cne "sha256:$ExecutorImageSha256" -or
[long]$executorImage[0].Size -ne $ExecutorImageSizeBytes -or
[string]$executorImage[0].Config.Labels.'com.nodedc.authority' -cne "observation-only" -or
[string]$executorImage[0].Config.Labels.'com.nodedc.product' -cne "mission-core" -or
[string]$executorImage[0].Config.Labels.'com.nodedc.stack' -cne "ndc-mission-core-observatory" -or
[string]$executorImage[0].Config.Labels.'com.nodedc.role' -cne "m49-tgs-portable-executor" -or
[string]$executorImage[0].Config.Labels.'com.nodedc.managed-by' -cne "mission-core-worker-release" -or
[string]$executorImage[0].Config.Labels.'com.nodedc.worker-contour' -cne $WorkerId -or
[string]$executorImage[0].Config.Labels.'com.nodedc.base-image.sha256' -cne $BaseImageSha256 -or
[string]$executorImage[0].Config.Labels.'com.nodedc.runner-source.sha256' -cne $RunnerSourceSha256 -or
[string]$executorImage[0].Config.Labels.'com.nodedc.fixture-smoke.sha256' -cne $FixtureSmokeSha256 -or
[string]$executorImage[0].Config.Labels.'com.nodedc.profile.sha256' -cne $ProfileSha256
) {
throw "portable M4.9 executor image identity changed"
}
$protectedBefore = @(Get-ProtectedRuntime)
Assert-ProtectedRuntime $protectedBefore
Assert-LegacyTaskReady
$readyRoot = Join-Path $candidateRoot "ready"
if (Test-Path -LiteralPath $readyRoot) {
$readyRoot = Assert-ReadyRoot $readyRoot
[pscustomobject]@{
ok = $true
already_promoted = $true
worker_id = $WorkerId
release_id = $ReleaseId
release_sha256 = $InstalledReleaseSha256
executor_image_sha256 = $ExecutorImageSha256
compiled_runner_sha256 = $RunnerSha256
compiled_runner_build_seal_sha256 = $RuntimeBuildSealSha256
worker_installation_receipt_sha256 = $ReadyReceiptSha256
release_root = $readyRoot
runtime_release_root = $RuntimeReleaseRoot
} | ConvertTo-Json -Compress
exit 0
}
$imageUsers = @(& docker ps -aq --filter "ancestor=sha256:$ExecutorImageSha256")
Assert-LastExitCode "portable M4.9 executor image use inspection"
if ($imageUsers.Count -ne 0) {
throw "portable M4.9 executor image is already used by a container"
}
$stagingRoot = Join-Path $candidateRoot ".ready-stage"
if (Test-Path -LiteralPath $stagingRoot) {
throw "portable M4.9 promotion staging requires reconciliation"
}
$null = New-Item -ItemType Directory -Path $stagingRoot
try {
$stagingRoot = Resolve-DDirectory $stagingRoot "portable M4.9 promotion staging"
Copy-Item -LiteralPath $candidateRunner -Destination (Join-Path $stagingRoot "run_m49_tgs_portable")
Copy-Item -LiteralPath $candidateProfile -Destination (Join-Path $stagingRoot "m49-tgs-portable-v2.json")
Write-Utf8NoBom (Join-Path $stagingRoot "compiled-runner-build.json") $RuntimeBuildSealPayload
Write-Utf8NoBom (Join-Path $stagingRoot "executor-release.json") $InstalledReleasePayload
Write-Utf8NoBom (Join-Path $stagingRoot "worker-installation-receipt.json") $ReadyReceiptPayload
$null = Assert-ReadyRoot $stagingRoot
$protectedAfter = @(Get-ProtectedRuntime)
Assert-ProtectedRuntime $protectedAfter
Assert-LegacyTaskReady
if (Test-Path -LiteralPath $readyRoot) {
throw "portable M4.9 ready release collided during promotion"
}
Move-Item -LiteralPath $stagingRoot -Destination $readyRoot
$readyRoot = Assert-ReadyRoot $readyRoot
} finally {
if (Test-Path -LiteralPath $stagingRoot) {
Remove-Item -LiteralPath $stagingRoot -Recurse -Force
}
}
[pscustomobject]@{
ok = $true
already_promoted = $false
worker_id = $WorkerId
release_id = $ReleaseId
release_sha256 = $InstalledReleaseSha256
executor_image_sha256 = $ExecutorImageSha256
compiled_runner_sha256 = $RunnerSha256
compiled_runner_build_seal_sha256 = $RuntimeBuildSealSha256
worker_installation_receipt_sha256 = $ReadyReceiptSha256
release_root = $readyRoot
runtime_release_root = $RuntimeReleaseRoot
} | ConvertTo-Json -Compress