Files
ARCADIA-Studio/harness/experiments/analysis-baseline-20260911/build-fixtures.ps1
T

217 lines
11 KiB
PowerShell

# Fixture construction only. This does not parse/evaluate the proposed language.
$ErrorActionPreference = 'Stop'
$taskDir = $PSScriptRoot
$ids = @{
project = '4210b9f2-7046-47f0-aa3b-153f626a579d'
duration = '188b911c-5f8b-431c-9eea-2d41f3953767'
second = '534f4672-1ba5-4157-8b0a-b9cf41d0a3ce'
millisecond = '39053f37-fec9-4708-9f0a-3959d223f891'
combine = 'fd7ce7ab-f789-40bc-b699-0c37f1b6902f'
input_a = '28ff40b0-1b8f-4735-8536-5a6ab21b56cb'
input_b = '7a47cc1e-8ae5-4551-b2d8-8a68108e0976'
respond = 'cabec6a1-7d5d-48f3-8d2d-a7fc8cf78f59'
receive = '4ab9a8a7-7552-488d-9862-e14b89e7b353'
dispatch = '6df991ba-4c5e-4535-99e2-524ae274ee8b'
receive_time = '63a931c2-675a-4fce-89e5-04361cb99450'
dispatch_time = 'c33fc772-2a60-4044-9af9-73c61c563ace'
total_time = 'bd5b68e8-65fc-4e35-9071-a73061316a4b'
limit = '437bedbb-2cf4-44ee-a139-6563cc5086ec'
degraded = '38036c65-16d4-449c-837b-91eb141c1d93'
unmeasured = '99d3e09a-0ec3-4194-9dd4-9f3de6625cde'
budget = 'bac0de99-9d2f-4e53-9158-d424ecac61bf'
}
function Exact([string]$n, [string]$d = '1') {
return @{ numerator = $n; denominator = $d }
}
function Local([string]$name) { return @{ Local = $ids[$name] } }
function ReadProperty([string]$name) { return @{ Property = $ids[$name] } }
function Literal([string]$n, [string]$unit) {
return @{ Quantity = @{ magnitude = (Exact $n); unit = (Local $unit) } }
}
function Bound($expr) { return @{ Expression = $expr } }
function Record([string]$key, [string]$name, $body) {
return @{
id = $ids[$key]; alias = $key; name = $name; description = ''; body = $body
}
}
function Element([string]$key, [string]$name, $body, $parent = $null) {
$r = Record $key $name $body
$r.parent = $parent
return $r
}
function Property([string]$key, [string]$name, [string]$subject, [string]$unit, $binding) {
return Element $key $name @{ Oa = @{ Shared = @{ EngineeringProperty = @{
subject = @{ Element = $ids[$subject] }
value_type = $quantityType
display_unit = (Local $unit)
base = $binding
} } } }
}
function OrderedCopy($value) {
if ($null -eq $value) { return $null }
if ($value -is [Collections.IDictionary]) {
$copy = [ordered]@{}
[string[]]$keys = @($value.Keys)
[Array]::Sort($keys, [StringComparer]::Ordinal)
foreach ($key in $keys) { $copy[$key] = OrderedCopy $value[$key] }
return $copy
}
if ($value -is [Collections.IEnumerable] -and $value -isnot [string]) {
$copy = @()
foreach ($item in $value) { $copy += ,(OrderedCopy $item) }
return ,$copy
}
return $value
}
function JsonBytes($value) {
$json = (OrderedCopy $value) | ConvertTo-Json -Depth 100
$json = $json.Replace([string][char]13 + [string][char]10, [string][char]10)
return [Text.UTF8Encoding]::new($false).GetBytes($json + [string][char]10)
}
function SaveBytes([string]$name, [byte[]]$bytes) {
[IO.File]::WriteAllBytes((Join-Path $taskDir $name), $bytes)
}
$quantityType = @{ Scalar = @{ Quantity = (Local 'duration') } }
$definitions = @{}
$definitions[$ids.duration] = Record 'duration' 'Duration' @{ QuantityKind = @{
dimension = @(0, 0, 1, 0, 0, 0, 0); algebra = 'Linear'
} }
$definitions[$ids.second] = Record 'second' 'Second' @{ Unit = @{
kind = (Local 'duration'); scale = (Exact '1'); offset = (Exact '0'); symbol = 's'
} }
$definitions[$ids.millisecond] = Record 'millisecond' 'Millisecond' @{ Unit = @{
kind = (Local 'duration'); scale = (Exact '1' '1000'); offset = (Exact '0'); symbol = 'ms'
} }
$definitions[$ids.combine] = Record 'combine' 'Combine durations' @{ Calculation = @{
parameters = @(
@{ id = $ids.input_a; name = 'a'; value_type = $quantityType },
@{ id = $ids.input_b; name = 'b'; value_type = $quantityType }
)
result = $quantityType
body = (Bound @{ Binary = @{
op = 'Add'; left = @{ Parameter = $ids.input_a }; right = @{ Parameter = $ids.input_b }
} })
} }
$receiveBase = Bound (Literal '750' 'millisecond')
$dispatchBase = Bound (Literal '1' 'second')
$totalBase = Bound @{ Call = @{
definition = (Local 'combine')
arguments = @{
$ids.input_a = (ReadProperty 'receive_time')
$ids.input_b = (ReadProperty 'dispatch_time')
}
} }
$limitBase = Bound (Literal '2' 'second')
$degradedBinding = Bound (Literal '1250' 'millisecond')
$predicate = Bound @{ Binary = @{
op = 'LessOrEqual'; left = (ReadProperty 'total_time'); right = (ReadProperty 'limit')
} }
$elements = @{}
$elements[$ids.respond] = Element 'respond' 'Respond' @{ Oa = 'Activity' }
$elements[$ids.receive] = Element 'receive' 'Receive' @{ Oa = 'Activity' } $ids.respond
$elements[$ids.dispatch] = Element 'dispatch' 'Dispatch' @{ Oa = 'Activity' } $ids.respond
$elements[$ids.receive_time] = Property 'receive_time' 'Receive time' 'receive' 'millisecond' $receiveBase
$elements[$ids.dispatch_time] = Property 'dispatch_time' 'Dispatch time' 'dispatch' 'second' $dispatchBase
$elements[$ids.total_time] = Property 'total_time' 'Total time' 'respond' 'second' $totalBase
$elements[$ids.limit] = Property 'limit' 'Allowed duration' 'respond' 'second' $limitBase
$elements[$ids.budget] = Element 'budget' 'Response budget' @{ Oa = @{ Shared = @{ AnalysisCheck = @{
subject = $null; documented_constraint = $null; predicate = $predicate
} } } }
$elements[$ids.degraded] = Element 'degraded' 'Degraded radio' @{ Oa = @{ Shared = @{ AnalysisCase = @{
subject = $null; base = 'ModelBaseline'; overrides = @{ $ids.receive_time = $degradedBinding }
} } } }
$elements[$ids.unmeasured] = Element 'unmeasured' 'Unmeasured radio' @{ Oa = @{ Shared = @{ AnalysisCase = @{
subject = $null; base = 'ModelBaseline'; overrides = @{ $ids.receive_time = 'Unbound' }
} } } }
$sourceBytes = [IO.File]::ReadAllBytes((Join-Path $taskDir 'active.arcadia.proposed'))
$source = [Text.UTF8Encoding]::new($false, $true).GetString($sourceBytes)
$project = @{
schema_version = 8; id = $ids.project; alias = 'response_budget'; name = 'Response budget'
description = 'A complete proposed analysis model. Schema 8 and the new declarations are not implemented source7 syntax.'
elements = $elements; relations = @{}; diagrams = @{}; artifact_links = @{}; traces = @{}
definitions = $definitions; imports = @{}; definition_mounts = @{}; library_instances = @{}
}
$document = @{
model = $project
source = @{ entry = 'active.arcadia'; files = @{ 'active.arcadia' = $source } }
packages = @{}
}
[byte[]]$documentBytes = JsonBytes $document
SaveBytes 'portable-document.json.proposed' $documentBytes
$documentDigest = [Convert]::ToHexString([Security.Cryptography.SHA256]::HashData($documentBytes)).ToLowerInvariant()
$manifest = @(
@{ property = $ids.receive_time; binding = $degradedBinding; origin = @{ CaseOverride = $ids.degraded } },
@{ property = $ids.dispatch_time; binding = $dispatchBase; origin = 'ModelBaseline' },
@{ property = $ids.total_time; binding = $totalBase; origin = 'ModelBaseline' },
@{ property = $ids.limit; binding = $limitBase; origin = 'ModelBaseline' }
) | Sort-Object { $_.property }
$freeze = @{
format = 'arcadia-analysis-freeze-1-proposal'
captured_document = @{
media_type = 'application/vnd.arcadia.portable-document+json'
sha256 = $documentDigest
bytes_base64 = [Convert]::ToBase64String($documentBytes)
}
origin = @{ Local = @{
document_instance = 'd911a3c0-8adb-4203-850c-b16e9b4e4d0a'; accepted_revision = 1
} }
model_id = $ids.project
context = @{ Case = $ids.degraded }
targets = @{ properties = @($ids.total_time); checks = @($ids.budget) }
numeric_profile = 'Q1-exact-1'
effective_bindings = @($manifest)
check_predicates = @(@{ check = $ids.budget; predicate = $predicate })
definition_capture = @{
document_sha256 = $documentDigest
local_definitions = @($ids.duration, $ids.second, $ids.millisecond, $ids.combine | Sort-Object)
imports = @()
}
}
SaveBytes 'freeze-degraded.json.proposed' (JsonBytes $freeze)
$expected = @{
status = 'Hand-derived expectations, not evaluator output'
baseline = @{ total_canonical_seconds = (Exact '7' '4'); check = 'Satisfied' }
degraded = @{ total_canonical_seconds = (Exact '9' '4'); check = 'Violated' }
unmeasured = @{ total = 'Missing'; input = $ids.receive_time; check = 'Unresolved' }
after_clear_unmeasured_override = @{ total_canonical_seconds = (Exact '7' '4'); check = 'Satisfied' }
after_baseline_dispatch_changes_to_two_seconds = @{
active_degraded_total = (Exact '13' '4'); frozen_degraded_total = (Exact '9' '4')
}
}
SaveBytes 'expected-observations.json' (JsonBytes $expected)
$largeInteger = [Numerics.BigInteger]::Pow([Numerics.BigInteger]10, 300).ToString()
$smallDenominator = [Numerics.BigInteger]::Pow([Numerics.BigInteger]2, 4095).ToString()
$boundInteger = ([Numerics.BigInteger]::Pow([Numerics.BigInteger]2, 4096) - 1).ToString()
$literalFixtures = @(
@{ name = 'ten_to_300'; expression = @{ Number = (Exact $largeInteger) }; canonical_source = $largeInteger },
@{ name = 'one_over_two_to_4095'; expression = @{ Number = (Exact '1' $smallDenominator) }; canonical_source = ('ratio(1, ' + $smallDenominator + ')') },
@{ name = 'negative_4096_bit_bound'; expression = @{ Number = (Exact ('-' + $boundInteger)) }; canonical_source = ('ratio(-' + $boundInteger + ', 1)') }
)
SaveBytes 'r7-literal-boundaries.json' (JsonBytes $literalFixtures)
# Verify only JSON transport, UUID completeness, raw source retention and hashes.
$parsed = Get-Content -LiteralPath (Join-Path $taskDir 'freeze-degraded.json.proposed') -Raw | ConvertFrom-Json
$decoded = [Convert]::FromBase64String($parsed.captured_document.bytes_base64)
if ([Convert]::ToBase64String($decoded) -cne [Convert]::ToBase64String($documentBytes)) { throw 'Document capsule differs' }
$parsedDoc = [Text.Encoding]::UTF8.GetString($decoded) | ConvertFrom-Json
if ($parsedDoc.source.files.'active.arcadia' -cne $source) { throw 'Source changed' }
if ($ids.Count -ne (@($ids.Values | Sort-Object -Unique)).Count) { throw 'Duplicate fixture UUID' }
foreach ($value in $ids.Values) {
[void][guid]::ParseExact($value, 'D')
if (-not $source.Contains('id "' + $value + '"')) { throw "Missing source identity $value" }
}
$stats = @{
source_lines = ($source -split [string][char]10).Count - 1
source_utf8_bytes = $sourceBytes.Length
explicit_source_uuids = $ids.Count
project_elements = $elements.Count
local_definitions = $definitions.Count
scoped_parameters = 2
base_bindings = 4
override_bindings = 2
shared_checks = 1
portable_document_sha256 = $documentDigest
verified = 'JSON transport, 17 syntactically valid distinct UUIDs, exact source bytes, capsule equality. No proposed parser/evaluator execution.'
}
SaveBytes 'fixture-integrity.json' (JsonBytes $stats)
$stats | ConvertTo-Json