Files
NODEDC_MISSION_CORE/experiments/perception/worker/Invoke-M48NNativeCandidateBuild.ps1

350 lines
13 KiB
PowerShell

[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$ReleaseRoot,
[Parameter(Mandatory = $true)]
[ValidatePattern("^[A-Za-z0-9._-]{1,96}$")]
[string]$RunId,
[string]$OutputRoot = "D:\NDC_MISSIONCORE\runtime\experiments\m48n-native-candidate"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode([string]$Operation) {
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
}
function Get-Sha256([string]$Path) {
return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
}
function Resolve-DDirectory([string]$Path, [string]$Label, [bool]$Create) {
if ($Create -and -not (Test-Path -LiteralPath $Path)) {
$null = New-Item -ItemType Directory -Path $Path
}
$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 Assert-RegularFile([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
if ($item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
throw "$Label must be a regular file"
}
return $item.FullName
}
function Convert-ToDockerPath([string]$Path) { return $Path.Replace("\", "/") }
function Get-Container([string]$Name) {
$rows = @((& docker inspect $Name) | ConvertFrom-Json)
Assert-LastExitCode "Docker inspection for $Name"
if ($rows.Count -ne 1) { throw "Container identity for $Name is not unique" }
return $rows[0]
}
if ($env:COMPUTERNAME -cne "DESKTOP-OPJ8J04") {
throw "M48N native candidate build is pinned to DESKTOP-OPJ8J04"
}
$release = Resolve-DDirectory $ReleaseRoot "M48N release root" $false
$output = Resolve-DDirectory $OutputRoot "M48N output root" $true
$runOutput = Join-Path $output $RunId
if (Test-Path -LiteralPath $runOutput) { throw "M48N run output already exists" }
$null = New-Item -ItemType Directory -Path $runOutput
$runOutput = Resolve-DDirectory $runOutput "M48N run output" $false
$exporter = Assert-RegularFile (
Join-Path $release "export_m48n_rf_detr_native_worker.py"
) "native exporter"
$converter = Assert-RegularFile (
Join-Path $release "convert_m48n_rf_detr_native_onnx_fp16.py"
) "native FP16 converter"
$wrapper = Assert-RegularFile (
Join-Path $release "wrap_m48n_rf_detr_native_uint8_onnx.py"
) "native UINT8 wrapper"
$checkpoint = Assert-RegularFile (
"D:\NDC_MISSIONCORE\runtime\experiments\m48t-fixed-detector-20260825T095425Z" +
"\weights\rf-detr-large-2026.pth"
) "RF-DETR checkpoint"
$checkpointSha256 = Get-Sha256 $checkpoint
if ($checkpointSha256 -cne "0f4e20e19a99c0f8a62b5685f57f6c8b5c371c59081feda6752a0561a79ccf38") {
throw "RF-DETR checkpoint SHA-256 changed"
}
$mask = Assert-RegularFile (
"D:\NDC_MISSIONCORE\runtime\inputs\e2" +
"\valid-fov-mask-b4dd8ddf2b87c1d520ee8a0868c4fea062d7c14d1bae73ccabd3abe1f3acbac2" +
"\mask.png"
) "valid-FOV mask"
$maskSha256 = Get-Sha256 $mask
if ($maskSha256 -cne "a40cee06b7c6f69b6a09a11563dcfd237f3de833b1ccd31459e66692e528ba63") {
throw "valid-FOV mask SHA-256 changed"
}
$historical = Get-Container "ndc-mission-core-triton"
if (-not $historical.State.Running -or $historical.State.Health.Status -cne "healthy") {
throw "Historical Triton must remain healthy"
}
$historicalId = [string]$historical.Id
$baseImage = (
"nvcr.io/nvidia/tritonserver:26.06-py3@" +
"sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
)
& docker image inspect $baseImage *> $null
Assert-LastExitCode "pinned base image inspection"
$baseImageId = (& docker image inspect $baseImage --format "{{.Id}}").Trim()
Assert-LastExitCode "pinned base image identity"
$runtimeVolume = "ndc-mission-core-m48t-upstream-parity-env"
if (-not (& docker volume ls --quiet --filter "name=^$runtimeVolume$")) {
throw "pinned RF-DETR dependency volume is unavailable"
}
$buildDepsVolume = "ndc-mission-core-m48n-native-build-deps"
if (-not (& docker volume ls --quiet --filter "name=^$buildDepsVolume$")) {
& docker volume create `
--label "com.nodedc.product=mission-core" `
--label "com.nodedc.stack=ndc-mission-core-compute" `
--label "com.nodedc.role=bounded-rf-detr-native-build-dependencies" `
--label "com.nodedc.managed-by=codex-bounded-experiment" `
$buildDepsVolume *> $null
Assert-LastExitCode "M48N build dependency volume creation"
}
$buildDepsReady = $false
$strictErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "Continue"
& docker run --rm `
--read-only `
--security-opt "no-new-privileges:true" `
--cap-drop ALL `
--tmpfs "/tmp:rw,noexec,nosuid,size=512m" `
-e "PYTHONPATH=/opt/build-deps:/opt/parity" `
-v ($buildDepsVolume + ":/opt/build-deps:ro") `
-v ($runtimeVolume + ":/opt/parity:ro") `
--entrypoint python3 `
$baseImage `
-c (
"import importlib.metadata as m, onnx, onnxconverter_common; " +
"assert m.version('onnx') == '1.22.0'; " +
"assert m.version('onnxconverter-common') == '1.16.0'; " +
"assert m.version('protobuf') == '6.33.6'"
) *> $null
if ($LASTEXITCODE -eq 0) { $buildDepsReady = $true }
$ErrorActionPreference = $strictErrorActionPreference
if (-not $buildDepsReady) {
& docker run --rm `
--name "ndc-mission-core-m48n-native-build-deps-init" `
--read-only `
--security-opt "no-new-privileges:true" `
--cap-drop ALL `
--pids-limit 256 `
--tmpfs "/tmp:rw,noexec,nosuid,size=2g" `
-e "PIP_DISABLE_PIP_VERSION_CHECK=1" `
-v ($buildDepsVolume + ":/opt/build-deps:rw") `
--entrypoint python3 `
$baseImage `
-m pip install --no-cache-dir --no-deps --upgrade --target /opt/build-deps `
"onnx==1.22.0" "onnxconverter-common==1.16.0" "protobuf==6.33.6"
Assert-LastExitCode "M48N build dependency initialization"
}
& docker run --rm `
--read-only `
--security-opt "no-new-privileges:true" `
--cap-drop ALL `
--tmpfs "/tmp:rw,noexec,nosuid,size=512m" `
-e "PYTHONPATH=/opt/build-deps:/opt/parity" `
-v ($buildDepsVolume + ":/opt/build-deps:ro") `
-v ($runtimeVolume + ":/opt/parity:ro") `
--entrypoint python3 `
$baseImage `
-c (
"import importlib.metadata as m, onnx, onnxconverter_common; " +
"assert m.version('onnx') == '1.22.0'; " +
"assert m.version('onnxconverter-common') == '1.16.0'; " +
"assert m.version('protobuf') == '6.33.6'"
)
Assert-LastExitCode "M48N build dependency verification"
$releaseMount = (Convert-ToDockerPath $release) + ":/release:ro"
$outputMount = (Convert-ToDockerPath $runOutput) + ":/output:rw"
$checkpointMount = (Convert-ToDockerPath $checkpoint) + ":/model/rf-detr-large-2026.pth:ro"
$maskMount = (Convert-ToDockerPath $mask) + ":/input/mask.png:ro"
$common = @(
"run", "--rm",
"--read-only",
"--security-opt", "no-new-privileges:true",
"--cap-drop", "ALL",
"--pids-limit", "512",
"--gpus", "all",
"--shm-size", "2g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=8g",
"-e", "PYTHONDONTWRITEBYTECODE=1",
"-e", "PYTHONPATH=/opt/build-deps:/opt/parity",
"-v", ($buildDepsVolume + ":/opt/build-deps:ro"),
"-v", ($runtimeVolume + ":/opt/parity:ro"),
"-v", $releaseMount,
"-v", $outputMount,
"-v", $checkpointMount,
"-v", $maskMount
)
try {
& docker @common `
--name "ndc-mission-core-m48n-native-export" `
--entrypoint python3 `
$baseImage `
/release/export_m48n_rf_detr_native_worker.py `
--checkpoint /model/rf-detr-large-2026.pth `
--expected-checkpoint-sha256 $checkpointSha256 `
--output-root /output/core-export `
--manifest /output/export-manifest.json `
--upstream-revision 9b009fa928d6218320439803d1da01869a85c072
Assert-LastExitCode "M48N native core export"
$exportManifest = Get-Content -LiteralPath (
Join-Path $runOutput "export-manifest.json"
) -Raw | ConvertFrom-Json
$corePath = [string]$exportManifest.onnx.path
$coreLeaf = Split-Path -Leaf $corePath
$coreHostPath = Assert-RegularFile (
Join-Path (Join-Path $runOutput "core-export") $coreLeaf
) "native core ONNX"
if ((Get-Sha256 $coreHostPath) -cne [string]$exportManifest.onnx.sha256) {
throw "native core ONNX hash does not match its manifest"
}
& docker @common `
--name "ndc-mission-core-m48n-native-fp16" `
--entrypoint python3 `
$baseImage `
/release/convert_m48n_rf_detr_native_onnx_fp16.py `
--input ("/output/core-export/" + $coreLeaf) `
--expected-input-sha256 ([string]$exportManifest.onnx.sha256) `
--output /output/rf-detr-native-core-fp16.onnx `
--manifest /output/fp16-manifest.json
Assert-LastExitCode "M48N native FP16 conversion"
$fp16Manifest = Get-Content -LiteralPath (
Join-Path $runOutput "fp16-manifest.json"
) -Raw | ConvertFrom-Json
$fp16Path = Assert-RegularFile (
Join-Path $runOutput "rf-detr-native-core-fp16.onnx"
) "native FP16 ONNX"
if ((Get-Sha256 $fp16Path) -cne [string]$fp16Manifest.output_onnx_sha256) {
throw "native FP16 ONNX hash does not match its manifest"
}
& docker @common `
--name "ndc-mission-core-m48n-native-wrapper" `
--entrypoint python3 `
$baseImage `
/release/wrap_m48n_rf_detr_native_uint8_onnx.py `
--input /output/rf-detr-native-core-fp16.onnx `
--expected-input-sha256 ([string]$fp16Manifest.output_onnx_sha256) `
--mask /input/mask.png `
--expected-mask-sha256 $maskSha256 `
--output /output/rf-detr-native-uint8.onnx `
--manifest /output/wrapper-manifest.json
Assert-LastExitCode "M48N native UINT8 wrapper"
$wrapperManifest = Get-Content -LiteralPath (
Join-Path $runOutput "wrapper-manifest.json"
) -Raw | ConvertFrom-Json
$wrappedPath = Assert-RegularFile (
Join-Path $runOutput "rf-detr-native-uint8.onnx"
) "native UINT8 ONNX"
if ((Get-Sha256 $wrappedPath) -cne [string]$wrapperManifest.output_onnx_sha256) {
throw "native UINT8 ONNX hash does not match its manifest"
}
& docker @common `
--name "ndc-mission-core-m48n-native-trt-build" `
--entrypoint /usr/src/tensorrt/bin/trtexec `
$baseImage `
--onnx=/output/rf-detr-native-uint8.onnx `
--saveEngine=/output/rf-detr-native-uint8.plan `
--stronglyTyped `
--builderOptimizationLevel=5 `
--memPoolSize=workspace:8192 `
--skipInference
Assert-LastExitCode "M48N native TensorRT engine build"
$enginePath = Assert-RegularFile (
Join-Path $runOutput "rf-detr-native-uint8.plan"
) "native TensorRT engine"
$receipt = [ordered]@{
schema_version = "missioncore.m48n-native-candidate-build/v0"
run_id = $RunId
completed = $true
worker = [ordered]@{
id = "worker-006"
node = $env:COMPUTERNAME
base_image = $baseImage
base_image_id = $baseImageId
dependency_volume = $runtimeVolume
build_dependency_volume = $buildDepsVolume
}
artifacts = [ordered]@{
export_manifest_sha256 = Get-Sha256 (
Join-Path $runOutput "export-manifest.json"
)
core_onnx_sha256 = Get-Sha256 $coreHostPath
fp16_manifest_sha256 = Get-Sha256 (
Join-Path $runOutput "fp16-manifest.json"
)
fp16_onnx_sha256 = Get-Sha256 $fp16Path
wrapper_manifest_sha256 = Get-Sha256 (
Join-Path $runOutput "wrapper-manifest.json"
)
wrapped_onnx_sha256 = Get-Sha256 $wrappedPath
engine_sha256 = Get-Sha256 $enginePath
engine_size_bytes = (Get-Item -LiteralPath $enginePath).Length
}
historical_triton = [ordered]@{
container_id = $historicalId
action = "none"
}
authority = [ordered]@{
ground_truth = $false
candidate_accepted = $false
commands_enabled = $false
actuation_allowed = $false
navigation_or_safety_accepted = $false
}
}
$receipt | ConvertTo-Json -Depth 8 -Compress | Set-Content -LiteralPath (
Join-Path $runOutput "build-receipt.json"
) -Encoding UTF8
} finally {
foreach ($name in @(
"ndc-mission-core-m48n-native-export",
"ndc-mission-core-m48n-native-fp16",
"ndc-mission-core-m48n-native-wrapper",
"ndc-mission-core-m48n-native-trt-build"
)) {
if (& docker ps -a --format "{{.Names}}" --filter "name=^/$name$") {
& docker rm -f $name *> $null
}
}
$historicalAfter = Get-Container "ndc-mission-core-triton"
if (
$historicalAfter.Id -cne $historicalId -or
-not $historicalAfter.State.Running -or
$historicalAfter.State.Health.Status -cne "healthy"
) {
throw "Historical Triton changed during M48N candidate build"
}
}
Write-Output ("M48N_NATIVE_BUILD_RECEIPT={0}" -f (
Join-Path $runOutput "build-receipt.json"
))
Write-Output "HISTORICAL_TRITON_ACTION=none"
Write-Output "SEMANTIC_AUTHORITY_CHANGED=false"