diff --git a/docs/schemas/loop-final-status-v1.schema.json b/docs/schemas/loop-final-status-v1.schema.json index c4fc3257d..5fc795cb0 100644 --- a/docs/schemas/loop-final-status-v1.schema.json +++ b/docs/schemas/loop-final-status-v1.schema.json @@ -37,6 +37,8 @@ "executionCellLeasePath": {"type": "string"}, "executionCellId": {"type": "string"}, "executionCellLeaseId": {"type": "string"}, + "harnessInstanceLeasePath": {"type": "string"}, + "harnessInstanceLeaseId": {"type": "string"}, "harnessInstanceId": {"type": "string"} }, "required": ["path", "output", "suiteClass", "runtimeSurface", "processModelClass", "windowsOnly", "requestedSimultaneous"], diff --git a/scripts/Run-AutonomousIntegrationLoop.ps1 b/scripts/Run-AutonomousIntegrationLoop.ps1 index 2dd5292d9..a18c1813a 100644 --- a/scripts/Run-AutonomousIntegrationLoop.ps1 +++ b/scripts/Run-AutonomousIntegrationLoop.ps1 @@ -153,6 +153,7 @@ param( , [string]$TestStandExecutionCellLeasePath = $env:LOOP_TESTSTAND_EXECUTION_CELL_LEASE_PATH , [string]$TestStandExecutionCellId = $env:LOOP_TESTSTAND_EXECUTION_CELL_ID , [string]$TestStandExecutionCellLeaseId = $env:LOOP_TESTSTAND_EXECUTION_CELL_LEASE_ID +, [string]$TestStandHarnessInstanceLeasePath = $env:LOOP_TESTSTAND_HARNESS_INSTANCE_LEASE_PATH , [string]$TestStandHarnessInstanceId = $env:LOOP_TESTSTAND_HARNESS_INSTANCE_ID , [switch]$TestStandReplaceFlags ) @@ -219,6 +220,29 @@ function Get-ExecutionCellLeaseMetadata { return [pscustomobject]$metadata } +function Get-HarnessInstanceLeaseMetadata { + param([string]$LeasePath) + + $metadata = [ordered]@{ + leaseId = $null + } + + if ([string]::IsNullOrWhiteSpace($LeasePath)) { + return [pscustomobject]$metadata + } + + try { + $resolvedLeasePath = (Resolve-Path -LiteralPath $LeasePath -ErrorAction Stop).Path + $payload = Get-Content -LiteralPath $resolvedLeasePath -Raw | ConvertFrom-Json -ErrorAction Stop + $grant = if ($payload -and $payload.PSObject.Properties.Name -contains 'grant') { $payload.grant } else { $null } + if ($grant -and $grant.PSObject.Properties.Name -contains 'leaseId' -and -not [string]::IsNullOrWhiteSpace($grant.leaseId)) { + $metadata.leaseId = [string]$grant.leaseId + } + } catch {} + + return [pscustomobject]$metadata +} + # Defaults / fallbacks if (-not $MaxIterations) { $MaxIterations = 1 } if ($null -eq $IntervalSeconds) { $IntervalSeconds = 0 } @@ -352,6 +376,8 @@ if ($UseTestStandHarness) { $executionCellLeaseMetadata = Get-ExecutionCellLeaseMetadata -LeasePath $executionCellLeasePath $agentId = $TestStandAgentId $agentClass = $TestStandAgentClass + $harnessInstanceLeasePath = $TestStandHarnessInstanceLeasePath + $harnessInstanceLeaseMetadata = Get-HarnessInstanceLeaseMetadata -LeasePath $harnessInstanceLeasePath $harnessInstanceId = $TestStandHarnessInstanceId $harnessIteration = [ref]0 @@ -381,6 +407,7 @@ if ($UseTestStandHarness) { if ($executionCellLeasePath) { $harnessParams.ExecutionCellLeasePath = $executionCellLeasePath } if ($executionCellId) { $harnessParams.ExecutionCellId = $executionCellId } if ($executionCellLeaseId) { $harnessParams.ExecutionCellLeaseId = $executionCellLeaseId } + if ($harnessInstanceLeasePath) { $harnessParams.HarnessInstanceLeasePath = $harnessInstanceLeasePath } if ($harnessInstanceId) { $harnessParams.HarnessInstanceId = $harnessInstanceId } if ($renderReport) { $harnessParams.RenderReport = $true } if ($closeLabVIEW) { $harnessParams.CloseLabVIEW = $true } @@ -448,6 +475,8 @@ if ($UseTestStandHarness) { executionCellLeasePath = $executionCellLeasePath executionCellId = $executionCellId executionCellLeaseId = $executionCellLeaseId + harnessInstanceLeasePath = $harnessInstanceLeasePath + harnessInstanceLeaseId = $harnessInstanceLeaseMetadata.leaseId harnessInstanceId = $harnessInstanceId } } @@ -688,6 +717,8 @@ if ($FinalStatusJsonPath) { executionCellLeasePath = $harnessPlan.executionCellLeasePath executionCellId = $harnessPlan.executionCellId executionCellLeaseId = $harnessPlan.executionCellLeaseId + harnessInstanceLeasePath = $harnessPlan.harnessInstanceLeasePath + harnessInstanceLeaseId = $harnessPlan.harnessInstanceLeaseId harnessInstanceId = $harnessPlan.harnessInstanceId } } diff --git a/tests/Run-AutonomousIntegrationLoop.Tests.ps1 b/tests/Run-AutonomousIntegrationLoop.Tests.ps1 index 0b576e71c..5444caca5 100644 --- a/tests/Run-AutonomousIntegrationLoop.Tests.ps1 +++ b/tests/Run-AutonomousIntegrationLoop.Tests.ps1 @@ -78,6 +78,7 @@ Describe 'Run-AutonomousIntegrationLoop TestStand harness mode' -Tag 'Unit' { $base = Join-Path $outDir 'BaseHarness.vi' $head = Join-Path $outDir 'HeadHarness.vi' $leasePath = Join-Path $outDir 'execution-cell.json' + $harnessLeasePath = Join-Path $outDir 'harness-instance.json' New-Item -ItemType File -Path $base -Force | Out-Null New-Item -ItemType File -Path $head -Force | Out-Null @' @@ -91,6 +92,19 @@ Describe 'Run-AutonomousIntegrationLoop TestStand harness mode' -Tag 'Unit' { } } '@ | Set-Content -LiteralPath $leasePath -Encoding UTF8 + @' +{ + "instanceId": "ts-loop-hooke-01", + "request": { + "role": "worker", + "runtimeSurface": "windows-native-teststand", + "processModelClass": "parallel-process-model" + }, + "grant": { + "leaseId": "harness-lease-hooke-loop-01" + } +} +'@ | Set-Content -LiteralPath $harnessLeasePath -Encoding UTF8 $harnessStub = Join-Path $outDir 'TestStand-CompareHarness.ps1' $logPath = Join-Path $outDir 'harness-log.ndjson' @@ -108,6 +122,7 @@ param( [string]`$ExecutionCellLeasePath, [string]`$ExecutionCellId, [string]`$ExecutionCellLeaseId, + [string]`$HarnessInstanceLeasePath, [string]`$HarnessInstanceId, [string]`$OutputRoot, [ValidateSet('detect','spawn','skip')][string]`$Warmup, @@ -138,6 +153,7 @@ if (`$logDir -and -not (Test-Path `$logDir)) { New-Item -ItemType Directory -Pat executionCellLeasePath = `$ExecutionCellLeasePath executionCellId = `$ExecutionCellId executionCellLeaseId = `$ExecutionCellLeaseId + harnessInstanceLeasePath = `$HarnessInstanceLeasePath harnessInstanceId = `$HarnessInstanceId flags = @(`$Flags) renderReport = `$RenderReport.IsPresent @@ -157,7 +173,7 @@ exit 0 try { $runner = Join-Path $outDir 'runner-harness.ps1' $runnerContent = @" -& '$scriptPath' -Base '$base' -Head '$head' -MaxIterations 2 -IntervalSeconds 0 -LogVerbosity Quiet -LvCompareArgs '-foo 1 -bar' -UseTestStandHarness -TestStandHarnessPath '$harnessStub' -TestStandOutputRoot '$outputRoot' -TestStandWarmup detect -TestStandSuiteClass dual-plane-parity -TestStandLabVIEW64Path 'C:\Program Files\National Instruments\LabVIEW 2026\LabVIEW.exe' -TestStandLabVIEW32Path 'C:\Program Files (x86)\National Instruments\LabVIEW 2026\LabVIEW.exe' -TestStandAgentId 'hooke' -TestStandAgentClass 'subagent' -TestStandExecutionCellLeasePath '$leasePath' -TestStandExecutionCellId 'exec-cell-hooke-loop-01' -TestStandExecutionCellLeaseId 'lease-hooke-loop-01' -TestStandHarnessInstanceId 'ts-loop-hooke-01' -TestStandRenderReport -TestStandCloseLabVIEW -TestStandCloseLVCompare -TestStandTimeoutSeconds 45 -TestStandReplaceFlags -FinalStatusJsonPath '$outDir/final.json' +& '$scriptPath' -Base '$base' -Head '$head' -MaxIterations 2 -IntervalSeconds 0 -LogVerbosity Quiet -LvCompareArgs '-foo 1 -bar' -UseTestStandHarness -TestStandHarnessPath '$harnessStub' -TestStandOutputRoot '$outputRoot' -TestStandWarmup detect -TestStandSuiteClass dual-plane-parity -TestStandLabVIEW64Path 'C:\Program Files\National Instruments\LabVIEW 2026\LabVIEW.exe' -TestStandLabVIEW32Path 'C:\Program Files (x86)\National Instruments\LabVIEW 2026\LabVIEW.exe' -TestStandAgentId 'hooke' -TestStandAgentClass 'subagent' -TestStandExecutionCellLeasePath '$leasePath' -TestStandExecutionCellId 'exec-cell-hooke-loop-01' -TestStandExecutionCellLeaseId 'lease-hooke-loop-01' -TestStandHarnessInstanceLeasePath '$harnessLeasePath' -TestStandHarnessInstanceId 'ts-loop-hooke-01' -TestStandRenderReport -TestStandCloseLabVIEW -TestStandCloseLVCompare -TestStandTimeoutSeconds 45 -TestStandReplaceFlags -FinalStatusJsonPath '$outDir/final.json' exit `$LASTEXITCODE "@ Set-Content -LiteralPath $runner -Encoding UTF8 -Value $runnerContent @@ -179,6 +195,7 @@ exit `$LASTEXITCODE $entries | ForEach-Object { $_.executionCellLeasePath } | Sort-Object -Unique | Should -Be @($leasePath) $entries | ForEach-Object { $_.executionCellId } | Sort-Object -Unique | Should -Be @('exec-cell-hooke-loop-01') $entries | ForEach-Object { $_.executionCellLeaseId } | Sort-Object -Unique | Should -Be @('lease-hooke-loop-01') + $entries | ForEach-Object { $_.harnessInstanceLeasePath } | Sort-Object -Unique | Should -Be @($harnessLeasePath) $entries | ForEach-Object { $_.harnessInstanceId } | Sort-Object -Unique | Should -Be @('ts-loop-hooke-01') $entries | ForEach-Object { $_.renderReport } | Sort-Object -Unique | Should -Be @($true) $entries | ForEach-Object { $_.closeLabVIEW } | Sort-Object -Unique | Should -Be @($true) @@ -201,6 +218,8 @@ exit `$LASTEXITCODE $finalStatus.harness.executionCellLeasePath | Should -Be $leasePath $finalStatus.harness.executionCellId | Should -Be 'exec-cell-hooke-loop-01' $finalStatus.harness.executionCellLeaseId | Should -Be 'lease-hooke-loop-01' + $finalStatus.harness.harnessInstanceLeasePath | Should -Be $harnessLeasePath + $finalStatus.harness.harnessInstanceLeaseId | Should -Be 'harness-lease-hooke-loop-01' $finalStatus.harness.harnessInstanceId | Should -Be 'ts-loop-hooke-01' } finally {