$ErrorActionPreference = 'Stop' $base = 'http://192.168.110.96:8301/api/cockpit/v1' function Read-Cockpit([string]$path) { $response = Invoke-WebRequest "$base/$path" -UseBasicParsing -TimeoutSec 25 $body = $response.Content | ConvertFrom-Json if ([int]$response.StatusCode -ne 200 -or $body.code -ne 200) { throw "Unsuccessful response: $path" } return $body.data } $map = Read-Cockpit 'map-snapshot?pageSize=1000' $overview = Read-Cockpit 'monitoring/overview' $distribution = Read-Cockpit 'monitoring/distribution?pageSize=1000' $empty = Read-Cockpit 'monitoring/distribution?pointStatus=EMPTY&pageSize=1000' $unassigned = Read-Cockpit 'monitoring/distribution?district=UNASSIGNED&pageSize=1000' $gas = Read-Cockpit 'monitoring/distribution?industry=GAS&pageSize=1000' $expectedCodes = @('GS001', 'GS002', 'PS001', 'PS002', 'RQ001', 'RQ002') -join ',' $checks = @() function Check([string]$name, [bool]$passed, $actual, $expected) { $script:checks += [pscustomobject]@{ name=$name; passed=$passed; actual=$actual; expected=$expected } } $mapCodes = @($map.monitoringPoints.pointCode | Sort-Object) -join ',' $distributionCodes = @($distribution.monitoringPoints.pointCode | Sort-Object) -join ',' $overviewCodes = @($overview.mapFilter.pointCodes | Sort-Object) -join ',' Check 'map-six-baseline' ($mapCodes -eq $expectedCodes) $mapCodes $expectedCodes Check 'overview-count' ($overview.counts.monitoringPointCount -eq 6) $overview.counts.monitoringPointCount 6 Check 'overview-point-codes' ($overviewCodes -eq $expectedCodes) $overviewCodes $expectedCodes Check 'distribution-point-codes' ($distributionCodes -eq $expectedCodes) $distributionCodes $expectedCodes $emptyCount = ($distribution.pointStatusDistribution | Where-Object status -eq 'EMPTY').count Check 'distribution-empty-bucket' ($emptyCount -eq 6) $emptyCount 6 $candidates = @($map.monitoringPoints).Count + @($map.unassociatedEquipment).Count $excluded = $distribution.excluded.unknownTypeCount + $distribution.excluded.typeKindMismatchCount + $distribution.excluded.nonFormalIndustryCount + $distribution.excluded.invalidCoordinateCount Check 'whole-source-object-reconciliation' ($candidates -eq ($distribution.pagination.total + $excluded)) ($distribution.pagination.total + $excluded) $candidates $statesTotal = ($distribution.pointStatusDistribution | Measure-Object -Property count -Sum).Sum Check 'status-sum-matches-pagination' ($statesTotal -eq $distribution.pagination.total) $statesTotal $distribution.pagination.total Check 'distribution-no-false-empty-freshness' ($distribution.freshness.status -eq 'CURRENT' -and $distribution.freshness.reason -eq 'READY') "$($distribution.freshness.status)/$($distribution.freshness.reason)" 'CURRENT/READY' $notRenderable = @($distribution.monitoringPoints | Where-Object { $_.coordinateValidation.renderable -eq $false }).Count Check 'unrenderable-points-still-counted' ($notRenderable -eq 6) $notRenderable 6 Check 'empty-status-filter' ($empty.pagination.total -eq 6 -and @($empty.monitoringPoints).Count -eq 6 -and @($empty.unassociatedEquipment).Count -eq 0) $empty.pagination.total 6 $unassignedCodes = @($unassigned.monitoringPoints.pointCode | Sort-Object) -join ',' Check 'unassigned-retains-empty-points' ($unassignedCodes -eq $expectedCodes) $unassignedCodes $expectedCodes $gasPoints = @($gas.monitoringPoints).Count Check 'formal-industry-does-not-invent-empty-point-industry' ($gasPoints -eq 0) $gasPoints 0 $result = [pscustomobject]@{ observedAt=(Get-Date -Format o); baseUrl=$base; method='GET only'; candidateObjects=$candidates; includedObjects=$distribution.pagination.total; excludedObjects=$excluded; allPassed=(@($checks | Where-Object { -not $_.passed }).Count -eq 0); checks=$checks } $artifact = Join-Path $PSScriptRoot 'artifacts/t28/acceptance-checks.json' New-Item -ItemType Directory -Force -Path (Split-Path $artifact) | Out-Null $result | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $artifact -Encoding utf8 $result | ConvertTo-Json -Depth 10 if (-not $result.allPassed) { exit 1 }