feat(perception): add vegetation mission policy lab
This commit is contained in:
@@ -0,0 +1,492 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet("Start", "Run", "Status", "Manifest", "VerifyModels", "Verify")]
|
||||
[string]$Mode = "Status",
|
||||
|
||||
[string]$Root = "D:\NDC_MISSIONCORE\datasets\vegetation-v1\observed-2026-08-27",
|
||||
|
||||
[int]$DownloadLimitMiB = 30
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$canonicalPrefix = "D:\NDC_MISSIONCORE\datasets\"
|
||||
if (-not $Root.StartsWith($canonicalPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw "LAB V1 assets must stay under $canonicalPrefix"
|
||||
}
|
||||
if ($DownloadLimitMiB -lt 1 -or $DownloadLimitMiB -gt 100) {
|
||||
throw "DownloadLimitMiB must be between 1 and 100"
|
||||
}
|
||||
|
||||
$stateRoot = "D:\NDC_MISSIONCORE\datasets\state\lab-v1-vegetation"
|
||||
$toolRoot = "D:\NDC_MISSIONCORE\datasets\tooling\aria2-1.37.0"
|
||||
$ariaArchive = Join-Path $toolRoot "aria2-1.37.0-win-64bit-build1.zip"
|
||||
$ariaExecutable = Join-Path $toolRoot "aria2-1.37.0-win-64bit-build1\aria2c.exe"
|
||||
$ariaUrl = "https://github.com/aria2/aria2/releases/download/release-1.37.0/aria2-1.37.0-win-64bit-build1.zip"
|
||||
$taskName = "MissionCore-LabV1-VegetationAssets"
|
||||
$stagePath = Join-Path $stateRoot "download-stage.json"
|
||||
$assetManifestPath = Join-Path $stateRoot "asset-manifest.json"
|
||||
$verificationPath = Join-Path $stateRoot "verification.jsonl"
|
||||
$bulkVerificationPath = Join-Path $stateRoot "bulk-verification.json"
|
||||
$gooseInputPath = Join-Path $stateRoot "goose-and-models.input.txt"
|
||||
$wildScenesInputPath = Join-Path $stateRoot "wildscenes-61541v003.input.txt"
|
||||
$orfdTorrentPath = Join-Path $stateRoot "orfd-ec5ccf4b8e49271ee3b63660383facf43063f2f2.torrent"
|
||||
$wildScenesDataFileCount = 76525
|
||||
$wildScenesMetadataFileCount = 4
|
||||
$wildScenesInputEntryCount = $wildScenesDataFileCount + $wildScenesMetadataFileCount
|
||||
$orfdTorrentExpectedBytes = 4918171
|
||||
$orfdTorrentSha256 = "b886dc76d169c924d619ff07baf8a0cd2364ca6f9c4b36d8777f2971fd78bc92"
|
||||
$orfdPublishedFileCount = 70983
|
||||
$orfdPublishedSizeBytes = 45941056780
|
||||
$wildScenesPublishedSizeBytes = 196358841020
|
||||
|
||||
$assets = @(
|
||||
[pscustomobject]@{ group = "models"; id = "goose-ppliteseg-category-512"; url = "https://goose-dataset.de/models/ppliteseg_category_512.pth"; relative_path = "models\goose\ppliteseg_category_512.pth"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "models"; id = "goose-ppliteseg-class-512"; url = "https://goose-dataset.de/models/ppliteseg_class_512.pth"; relative_path = "models\goose\ppliteseg_class_512.pth"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "models"; id = "goose-ddrnet-category-512"; url = "https://goose-dataset.de/models/ddrnet_category_512.pth"; relative_path = "models\goose\ddrnet_category_512.pth"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "models"; id = "goose-ddrnet-class-512"; url = "https://goose-dataset.de/models/ddrnet_class_512.pth"; relative_path = "models\goose\ddrnet_class_512.pth"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "models"; id = "rellis-hrnet-ocr"; url = "https://drive.usercontent.google.com/download?id=137Lfw6HcDmdEReu_R7Q_I-zmRvvqFys3&export=download&confirm=t"; relative_path = "models\rellis-3d\hrnet_best.zip"; expected_bytes = 788183119 },
|
||||
[pscustomobject]@{ group = "models"; id = "rellis-gscnn"; url = "https://drive.usercontent.google.com/download?id=1Z8OlstkdzDrY9k-yxMQmVB192ac8j4MD&export=download&confirm=t"; relative_path = "models\rellis-3d\gscnn_best.pth"; expected_bytes = 1098515419 },
|
||||
[pscustomobject]@{ group = "models"; id = "rellis-salsanext"; url = "https://drive.usercontent.google.com/download?id=1DxuzlnFKnU8EpSuODRywJUrJlieUUheg&export=download&confirm=t"; relative_path = "models\rellis-3d\salsanext_best.zip"; expected_bytes = 164312336 },
|
||||
[pscustomobject]@{ group = "models"; id = "rellis-kpconv"; url = "https://drive.usercontent.google.com/download?id=1Exrt4yWDhgucx_vr08hAuXTcaLUcpXXm&export=download&confirm=t"; relative_path = "models\rellis-3d\kpconv_best.zip"; expected_bytes = 1522250650 },
|
||||
[pscustomobject]@{ group = "models"; id = "wildscenes-models"; url = "https://www.dropbox.com/scl/fo/1za8yjfj0dl8fsddbl9ns/AAZ4xc2PkwcPc14sjY_GhVA?rlkey=3yqq5lpiicjtqqau4cljl66y5&st=fwhd1l86&dl=1"; relative_path = "models\wildscenes\WildScenes-Models.zip"; expected_bytes = 8637507567 },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-2d-train"; url = "https://goose-dataset.de/storage/goose_2d_train.zip"; relative_path = "goose-2d\archives\goose_2d_train.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-2d-val"; url = "https://goose-dataset.de/storage/goose_2d_val.zip"; relative_path = "goose-2d\archives\goose_2d_val.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-2d-test"; url = "https://goose-dataset.de/storage/goose_2d_test.zip"; relative_path = "goose-2d\archives\goose_2d_test.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-3d-train"; url = "https://goose-dataset.de/storage/goose_3d_train.zip"; relative_path = "goose-3d\archives\goose_3d_train.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-3d-test"; url = "https://goose-dataset.de/storage/goose_3d_test.zip"; relative_path = "goose-3d\archives\goose_3d_test.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-ex-2d-train"; url = "https://goose-dataset.de/storage/gooseEx_2d_train.zip"; relative_path = "goose-ex-2d\archives\gooseEx_2d_train.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-ex-2d-val"; url = "https://goose-dataset.de/storage/gooseEx_2d_val.zip"; relative_path = "goose-ex-2d\archives\gooseEx_2d_val.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-ex-2d-test"; url = "https://goose-dataset.de/storage/gooseEx_2d_test.zip"; relative_path = "goose-ex-2d\archives\gooseEx_2d_test.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-ex-3d-train"; url = "https://goose-dataset.de/storage/gooseEx_3d_train.zip"; relative_path = "goose-ex-3d\archives\gooseEx_3d_train.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-ex-3d-val"; url = "https://goose-dataset.de/storage/gooseEx_3d_val.zip"; relative_path = "goose-ex-3d\archives\gooseEx_3d_val.zip"; expected_bytes = $null },
|
||||
[pscustomobject]@{ group = "goose"; id = "goose-ex-3d-test"; url = "https://goose-dataset.de/storage/gooseEx_3d_test.zip"; relative_path = "goose-ex-3d\archives\gooseEx_3d_test.zip"; expected_bytes = $null }
|
||||
)
|
||||
|
||||
function Write-JsonFile {
|
||||
param([string]$Path, [object]$Value)
|
||||
$parent = Split-Path -Parent $Path
|
||||
New-Item -ItemType Directory -Force -Path $parent | Out-Null
|
||||
$json = $Value | ConvertTo-Json -Depth 12
|
||||
[System.IO.File]::WriteAllText($Path, $json + [Environment]::NewLine, [System.Text.UTF8Encoding]::new($false))
|
||||
}
|
||||
|
||||
function Set-Stage {
|
||||
param([string]$Stage, [string]$Status, [string]$Detail)
|
||||
Write-JsonFile -Path $stagePath -Value ([ordered]@{
|
||||
schema_version = "missioncore.lab-v1-asset-download-stage/v1"
|
||||
observed_at_utc = [DateTime]::UtcNow.ToString("o")
|
||||
worker_id = "worker-006"
|
||||
stage = $Stage
|
||||
status = $Status
|
||||
detail = $Detail
|
||||
})
|
||||
}
|
||||
|
||||
function Invoke-CurlDownload {
|
||||
param([string]$Url, [string]$Destination)
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $Destination) | Out-Null
|
||||
& curl.exe --location --fail --retry 8 --retry-all-errors --continue-at - --output $Destination $Url
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "curl failed for $Url with exit code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-AriaInputList {
|
||||
param([string]$Path, [int]$ExpectedEntries)
|
||||
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
||||
return $false
|
||||
}
|
||||
|
||||
$urlCount = 0
|
||||
$dirCount = 0
|
||||
foreach ($line in [System.IO.File]::ReadLines($Path)) {
|
||||
if ($line.StartsWith("https://", [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
$urlCount++
|
||||
}
|
||||
elseif ($line.StartsWith(" dir=", [System.StringComparison]::Ordinal)) {
|
||||
$dirCount++
|
||||
}
|
||||
}
|
||||
return $urlCount -eq $ExpectedEntries -and $dirCount -eq $ExpectedEntries
|
||||
}
|
||||
|
||||
function Test-FileIntegrity {
|
||||
param([string]$Path, [long]$ExpectedBytes, [string]$ExpectedSha256)
|
||||
$file = Get-Item -LiteralPath $Path -ErrorAction SilentlyContinue
|
||||
if ($null -eq $file -or $file.Length -ne $ExpectedBytes) {
|
||||
return $false
|
||||
}
|
||||
$actualSha256 = (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
return $actualSha256 -eq $ExpectedSha256
|
||||
}
|
||||
|
||||
function Initialize-Aria2 {
|
||||
New-Item -ItemType Directory -Force -Path $toolRoot | Out-Null
|
||||
if (-not (Test-Path -LiteralPath $ariaExecutable -PathType Leaf)) {
|
||||
Invoke-CurlDownload -Url $ariaUrl -Destination $ariaArchive
|
||||
Expand-Archive -LiteralPath $ariaArchive -DestinationPath $toolRoot -Force
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $ariaExecutable -PathType Leaf)) {
|
||||
throw "aria2 executable was not installed at $ariaExecutable"
|
||||
}
|
||||
}
|
||||
|
||||
function Write-DirectInput {
|
||||
$lines = [System.Collections.Generic.List[string]]::new()
|
||||
foreach ($asset in $assets) {
|
||||
$destination = Join-Path $Root $asset.relative_path
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $destination) | Out-Null
|
||||
$lines.Add([string]$asset.url)
|
||||
$lines.Add(" dir=" + (Split-Path -Parent $destination))
|
||||
$lines.Add(" out=" + (Split-Path -Leaf $destination))
|
||||
}
|
||||
[System.IO.File]::WriteAllLines($gooseInputPath, $lines, [System.Text.UTF8Encoding]::new($false))
|
||||
}
|
||||
|
||||
function Invoke-AriaInput {
|
||||
param([string]$InputPath, [int]$ConcurrentDownloads, [int]$ConnectionsPerServer)
|
||||
$downloadLimit = "{0}M" -f $DownloadLimitMiB
|
||||
& $ariaExecutable `
|
||||
--input-file=$InputPath `
|
||||
--continue=true `
|
||||
--max-concurrent-downloads=$ConcurrentDownloads `
|
||||
--max-connection-per-server=$ConnectionsPerServer `
|
||||
--split=$ConnectionsPerServer `
|
||||
--min-split-size=16M `
|
||||
"--max-overall-download-limit=$downloadLimit" `
|
||||
--file-allocation=none `
|
||||
--disk-cache=64M `
|
||||
--auto-file-renaming=false `
|
||||
--allow-overwrite=false `
|
||||
--retry-wait=5 `
|
||||
--max-tries=0 `
|
||||
--summary-interval=60 `
|
||||
--console-log-level=notice
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "aria2 input run failed for $InputPath with exit code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-DownloadTask {
|
||||
return Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
function Get-AssetSnapshot {
|
||||
$rows = foreach ($asset in $assets) {
|
||||
$path = Join-Path $Root $asset.relative_path
|
||||
$file = Get-Item -LiteralPath $path -ErrorAction SilentlyContinue
|
||||
$partial = Get-Item -LiteralPath ($path + ".aria2") -ErrorAction SilentlyContinue
|
||||
[ordered]@{
|
||||
id = $asset.id
|
||||
group = $asset.group
|
||||
relative_path = $asset.relative_path
|
||||
status = if ($null -ne $file -and $null -eq $partial) { "downloaded" } elseif ($null -ne $file) { "partial" } else { "pending" }
|
||||
size_bytes = if ($null -ne $file) { $file.Length } else { 0 }
|
||||
expected_bytes = $asset.expected_bytes
|
||||
}
|
||||
}
|
||||
return @($rows)
|
||||
}
|
||||
|
||||
function Invoke-Verify {
|
||||
param([ValidateSet("All", "Models")][string]$Scope = "All")
|
||||
New-Item -ItemType Directory -Force -Path $stateRoot | Out-Null
|
||||
$writer = [System.IO.StreamWriter]::new($verificationPath, $false, [System.Text.UTF8Encoding]::new($false))
|
||||
try {
|
||||
foreach ($asset in $assets) {
|
||||
if ($Scope -eq "Models" -and $asset.group -ne "models") {
|
||||
continue
|
||||
}
|
||||
$path = Join-Path $Root $asset.relative_path
|
||||
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
||||
continue
|
||||
}
|
||||
if (Test-Path -LiteralPath ($path + ".aria2") -PathType Leaf) {
|
||||
throw "Cannot verify partial asset $($asset.id)"
|
||||
}
|
||||
$file = Get-Item -LiteralPath $path
|
||||
$hash = Get-FileHash -LiteralPath $path -Algorithm SHA256
|
||||
$sizeMatches = $null
|
||||
if ($null -ne $asset.expected_bytes) {
|
||||
$sizeMatches = $file.Length -eq [long]$asset.expected_bytes
|
||||
if (-not $sizeMatches) {
|
||||
throw "Size mismatch for $($asset.id): expected $($asset.expected_bytes), got $($file.Length)"
|
||||
}
|
||||
}
|
||||
$row = [ordered]@{
|
||||
schema_version = "missioncore.lab-v1-asset-verification/v1"
|
||||
observed_at_utc = [DateTime]::UtcNow.ToString("o")
|
||||
id = $asset.id
|
||||
relative_path = $asset.relative_path
|
||||
size_bytes = $file.Length
|
||||
expected_bytes = $asset.expected_bytes
|
||||
size_matches = $sizeMatches
|
||||
sha256 = $hash.Hash.ToLowerInvariant()
|
||||
source_url = $asset.url
|
||||
}
|
||||
$writer.WriteLine(($row | ConvertTo-Json -Compress -Depth 8))
|
||||
$writer.Flush()
|
||||
}
|
||||
$offnetRoot = Join-Path $Root "models\orfd-offnet"
|
||||
if (Test-Path -LiteralPath $offnetRoot -PathType Container) {
|
||||
Get-ChildItem -LiteralPath $offnetRoot -File -Recurse | Sort-Object FullName | ForEach-Object {
|
||||
$row = [ordered]@{
|
||||
schema_version = "missioncore.lab-v1-asset-verification/v1"
|
||||
observed_at_utc = [DateTime]::UtcNow.ToString("o")
|
||||
id = "orfd-offnet/" + $_.FullName.Substring($offnetRoot.Length + 1).Replace("\", "/")
|
||||
relative_path = $_.FullName.Substring($Root.Length + 1)
|
||||
size_bytes = $_.Length
|
||||
expected_bytes = $null
|
||||
size_matches = $null
|
||||
sha256 = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
source_url = "https://drive.google.com/drive/folders/1lnm2M1HEkVs9W3-FSEX3ddE9GYz4rqCU"
|
||||
}
|
||||
$writer.WriteLine(($row | ConvertTo-Json -Compress -Depth 8))
|
||||
$writer.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$writer.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function Measure-PayloadTree {
|
||||
param([string]$Path)
|
||||
[long]$bytes = 0
|
||||
[long]$fileCount = 0
|
||||
[long]$partialCount = 0
|
||||
Get-ChildItem -LiteralPath $Path -File -Recurse | ForEach-Object {
|
||||
if ($_.Name.EndsWith(".aria2", [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
$partialCount++
|
||||
}
|
||||
else {
|
||||
$fileCount++
|
||||
$bytes += $_.Length
|
||||
}
|
||||
}
|
||||
return [ordered]@{ file_count = $fileCount; size_bytes = $bytes; partial_count = $partialCount }
|
||||
}
|
||||
|
||||
function Invoke-BulkVerify {
|
||||
$wildScenesRoot = Join-Path $Root "wildscenes"
|
||||
$orfdRoot = Join-Path $Root "orfd"
|
||||
$wildScenes = Measure-PayloadTree -Path $wildScenesRoot
|
||||
$orfd = Measure-PayloadTree -Path $orfdRoot
|
||||
if (
|
||||
$wildScenes.file_count -ne $wildScenesInputEntryCount -or
|
||||
$wildScenes.size_bytes -ne $wildScenesPublishedSizeBytes -or
|
||||
$wildScenes.partial_count -ne 0
|
||||
) {
|
||||
throw "WildScenes tree failed count/size/partial verification"
|
||||
}
|
||||
if (
|
||||
$orfd.file_count -ne $orfdPublishedFileCount -or
|
||||
$orfd.size_bytes -ne $orfdPublishedSizeBytes -or
|
||||
$orfd.partial_count -ne 0
|
||||
) {
|
||||
throw "ORFD tree failed count/size/partial verification"
|
||||
}
|
||||
Write-JsonFile -Path $bulkVerificationPath -Value ([ordered]@{
|
||||
schema_version = "missioncore.lab-v1-bulk-verification/v1"
|
||||
observed_at_utc = [DateTime]::UtcNow.ToString("o")
|
||||
worker_id = "worker-006"
|
||||
wildscenes = $wildScenes
|
||||
orfd = $orfd
|
||||
canonical_triton_action = "none"
|
||||
})
|
||||
}
|
||||
|
||||
function Write-AssetManifest {
|
||||
if (-not (Test-AriaInputList -Path $wildScenesInputPath -ExpectedEntries $wildScenesInputEntryCount)) {
|
||||
throw "WildScenes input list is not admitted"
|
||||
}
|
||||
if (-not (Test-FileIntegrity -Path $orfdTorrentPath -ExpectedBytes $orfdTorrentExpectedBytes -ExpectedSha256 $orfdTorrentSha256)) {
|
||||
throw "ORFD torrent source is not admitted"
|
||||
}
|
||||
Write-JsonFile -Path $assetManifestPath -Value ([ordered]@{
|
||||
schema_version = "missioncore.lab-v1-asset-manifest/v1"
|
||||
observed_at_utc = [DateTime]::UtcNow.ToString("o")
|
||||
worker_id = "worker-006"
|
||||
storage_policy = "worker-d-only"
|
||||
root = $Root
|
||||
runtime_models_mutated = $false
|
||||
canonical_triton_action = "none"
|
||||
existing_admitted_assets = @(
|
||||
[ordered]@{ id = "goose-3d-val"; path = "D:\NDC_MISSIONCORE\datasets\goose-3d\v2025-08-22\archives\goose_3d_val.zip"; sha256 = "0be9e0f8459bafcbc92ff7c3cc366e9b4e2f6e1e9bdf50e6439e1557e864c26f" },
|
||||
[ordered]@{ id = "rellis-3d-v1.1"; path = "D:\NDC_MISSIONCORE\datasets\rellis-3d\v1.1"; admission_identity = "a3f3f161a5a7edccdf66cea75ecf9004b8f6a895282faabe661c075c15a82774" }
|
||||
)
|
||||
direct_assets = $assets
|
||||
wildscenes = [ordered]@{ collection_id = 63154; version = 3; published_size_bytes = $wildScenesPublishedSizeBytes; data_file_count = $wildScenesDataFileCount; metadata_file_count = $wildScenesMetadataFileCount; input_entry_count = $wildScenesInputEntryCount; url_list = $wildScenesInputPath; url_list_sha256 = (Get-FileHash -LiteralPath $wildScenesInputPath -Algorithm SHA256).Hash.ToLowerInvariant() }
|
||||
orfd = [ordered]@{ info_hash = "ec5ccf4b8e49271ee3b63660383facf43063f2f2"; published_size_bytes = $orfdPublishedSizeBytes; published_file_count = $orfdPublishedFileCount; torrent = $orfdTorrentPath; torrent_size_bytes = $orfdTorrentExpectedBytes; torrent_sha256 = $orfdTorrentSha256 }
|
||||
offnet_weights = [ordered]@{ source_folder = "https://drive.google.com/drive/folders/1lnm2M1HEkVs9W3-FSEX3ddE9GYz4rqCU"; relative_path = "models\orfd-offnet"; downloader = "gdown==5.2.0"; isolated_image = "nvcr.io/nvidia/tritonserver@sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"; runtime_models_mutated = $false }
|
||||
})
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $Root, $stateRoot | Out-Null
|
||||
|
||||
switch ($Mode) {
|
||||
"Start" {
|
||||
$existingTask = Get-DownloadTask
|
||||
if ($null -ne $existingTask -and $existingTask.State -eq "Running") {
|
||||
throw "LAB V1 downloader task is already running"
|
||||
}
|
||||
|
||||
$drive = Get-PSDrive -Name D
|
||||
$currentUsage = Measure-PayloadTree -Path $Root
|
||||
[long]$remainingPayloadBytes = 360GB - [long]$currentUsage.size_bytes
|
||||
if ($remainingPayloadBytes -lt 0) {
|
||||
$remainingPayloadBytes = 0
|
||||
}
|
||||
[long]$requiredFreeBytes = 10GB + $remainingPayloadBytes
|
||||
if ($drive.Free -lt $requiredFreeBytes) {
|
||||
throw "Worker D: has only $([math]::Round($drive.Free / 1GB, 2)) GiB free; $([math]::Round($requiredFreeBytes / 1GB, 2)) GiB is required for remaining payload plus reserve"
|
||||
}
|
||||
|
||||
Set-Stage -Stage "preflight" -Status "running" -Detail "Installing bounded downloader and generating immutable source lists"
|
||||
Initialize-Aria2
|
||||
Write-DirectInput
|
||||
|
||||
if (-not (Test-AriaInputList -Path $wildScenesInputPath -ExpectedEntries $wildScenesInputEntryCount)) {
|
||||
Invoke-CurlDownload -Url "https://data.csiro.au/dap/ws/v2/collections/63154/files/list" -Destination $wildScenesInputPath
|
||||
}
|
||||
if (-not (Test-AriaInputList -Path $wildScenesInputPath -ExpectedEntries $wildScenesInputEntryCount)) {
|
||||
throw "WildScenes input list is incomplete: expected $wildScenesInputEntryCount URL/dir entries"
|
||||
}
|
||||
if (-not (Test-FileIntegrity -Path $orfdTorrentPath -ExpectedBytes $orfdTorrentExpectedBytes -ExpectedSha256 $orfdTorrentSha256)) {
|
||||
Remove-Item -LiteralPath $orfdTorrentPath -Force -ErrorAction SilentlyContinue
|
||||
Invoke-CurlDownload -Url "https://academictorrents.com/download/ec5ccf4b8e49271ee3b63660383facf43063f2f2.torrent" -Destination $orfdTorrentPath
|
||||
}
|
||||
if (-not (Test-FileIntegrity -Path $orfdTorrentPath -ExpectedBytes $orfdTorrentExpectedBytes -ExpectedSha256 $orfdTorrentSha256)) {
|
||||
throw "ORFD torrent source failed size/SHA-256 verification"
|
||||
}
|
||||
|
||||
Write-AssetManifest
|
||||
|
||||
$powershell = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe"
|
||||
$arguments = @(
|
||||
"-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass",
|
||||
"-File", "`"$PSCommandPath`"",
|
||||
"-Mode", "Run",
|
||||
"-Root", "`"$Root`"",
|
||||
"-DownloadLimitMiB", $DownloadLimitMiB
|
||||
) -join " "
|
||||
$action = New-ScheduledTaskAction -Execute $powershell -Argument $arguments -WorkingDirectory (Split-Path -Parent $PSCommandPath)
|
||||
$principal = New-ScheduledTaskPrincipal -UserId ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) -LogonType Interactive -RunLevel Limited
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At ((Get-Date).AddMinutes(30))
|
||||
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit ([TimeSpan]::FromHours(72))
|
||||
Register-ScheduledTask -TaskName $taskName -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Mission Core LAB V1 isolated vegetation dataset and model admission." -Force | Out-Null
|
||||
Start-ScheduledTask -TaskName $taskName
|
||||
Set-Stage -Stage "queued" -Status "running" -Detail "Bounded downloader started as scheduled task $taskName"
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
mode = $Mode
|
||||
task_name = $taskName
|
||||
task_state = (Get-ScheduledTask -TaskName $taskName).State.ToString()
|
||||
root = $Root
|
||||
d_free_gib_before = [math]::Round($drive.Free / 1GB, 2)
|
||||
download_limit_mib = $DownloadLimitMiB
|
||||
canonical_triton_action = "none"
|
||||
} | ConvertTo-Json -Depth 6
|
||||
}
|
||||
"Run" {
|
||||
try {
|
||||
Initialize-Aria2
|
||||
Set-Stage -Stage "models-and-goose" -Status "running" -Detail "Downloading official pretrained weights and prepared GOOSE/GOOSE-Ex splits"
|
||||
Invoke-AriaInput -InputPath $gooseInputPath -ConcurrentDownloads 2 -ConnectionsPerServer 4
|
||||
|
||||
Set-Stage -Stage "orfd" -Status "running" -Detail "Downloading the 45.94 GB Academic Torrents ORFD release"
|
||||
$orfdRoot = Join-Path $Root "orfd"
|
||||
$downloadLimit = "{0}M" -f $DownloadLimitMiB
|
||||
New-Item -ItemType Directory -Force -Path $orfdRoot | Out-Null
|
||||
& $ariaExecutable `
|
||||
--dir=$orfdRoot `
|
||||
--continue=true `
|
||||
--seed-time=0 `
|
||||
"--max-overall-download-limit=$downloadLimit" `
|
||||
--file-allocation=none `
|
||||
--disk-cache=64M `
|
||||
--summary-interval=60 `
|
||||
--console-log-level=notice `
|
||||
$orfdTorrentPath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "ORFD torrent run failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Set-Stage -Stage "wildscenes" -Status "running" -Detail "Downloading the complete public WildScenes v3 file list"
|
||||
$wildScenesRoot = Join-Path $Root "wildscenes"
|
||||
New-Item -ItemType Directory -Force -Path $wildScenesRoot | Out-Null
|
||||
Push-Location $wildScenesRoot
|
||||
try {
|
||||
Invoke-AriaInput -InputPath $wildScenesInputPath -ConcurrentDownloads 8 -ConnectionsPerServer 2
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Set-Stage -Stage "verification" -Status "running" -Detail "Computing SHA-256 for direct archive and model assets"
|
||||
Invoke-Verify
|
||||
Invoke-BulkVerify
|
||||
Set-Stage -Stage "complete" -Status "complete" -Detail "All scheduled assets downloaded and verified by direct hashes or published tree totals"
|
||||
}
|
||||
catch {
|
||||
Set-Stage -Stage "failed" -Status "failed" -Detail $_.Exception.Message
|
||||
throw
|
||||
}
|
||||
}
|
||||
"Status" {
|
||||
$task = Get-DownloadTask
|
||||
$stage = if (Test-Path -LiteralPath $stagePath -PathType Leaf) { Get-Content -LiteralPath $stagePath -Raw | ConvertFrom-Json } else { $null }
|
||||
$snapshot = Get-AssetSnapshot
|
||||
$drive = Get-PSDrive -Name D
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
mode = $Mode
|
||||
running = $null -ne $task -and $task.State -eq "Running"
|
||||
task_name = $taskName
|
||||
task_state = if ($null -ne $task) { $task.State.ToString() } else { $null }
|
||||
stage = $stage
|
||||
direct_assets = $snapshot
|
||||
downloaded_direct_asset_count = @($snapshot | Where-Object { $_.status -eq "downloaded" }).Count
|
||||
partial_direct_asset_count = @($snapshot | Where-Object { $_.status -eq "partial" }).Count
|
||||
d_free_gib = [math]::Round($drive.Free / 1GB, 2)
|
||||
canonical_triton_action = "none"
|
||||
} | ConvertTo-Json -Depth 10
|
||||
}
|
||||
"Manifest" {
|
||||
Write-AssetManifest
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
mode = $Mode
|
||||
manifest_path = $assetManifestPath
|
||||
manifest_sha256 = (Get-FileHash -LiteralPath $assetManifestPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
canonical_triton_action = "none"
|
||||
} | ConvertTo-Json -Depth 6
|
||||
}
|
||||
"VerifyModels" {
|
||||
Invoke-Verify -Scope "Models"
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
mode = $Mode
|
||||
verification_path = $verificationPath
|
||||
verification_sha256 = (Get-FileHash -LiteralPath $verificationPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
verified_asset_count = (Get-Content -LiteralPath $verificationPath).Count
|
||||
canonical_triton_action = "none"
|
||||
} | ConvertTo-Json -Depth 6
|
||||
}
|
||||
"Verify" {
|
||||
Set-Stage -Stage "verification" -Status "running" -Detail "Manual direct-asset and published-tree verification requested"
|
||||
Invoke-Verify
|
||||
Invoke-BulkVerify
|
||||
Set-Stage -Stage "verification" -Status "complete" -Detail "Direct assets hashed and bulk trees match published totals"
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
mode = $Mode
|
||||
verification_path = $verificationPath
|
||||
bulk_verification_path = $bulkVerificationPath
|
||||
verified_asset_count = (Get-Content -LiteralPath $verificationPath).Count
|
||||
} | ConvertTo-Json -Depth 6
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user