$ErrorActionPreference = 'Stop' function Assert-Contains { param([string]$Content, [string]$Expected, [string]$Message) if (-not $Content.Contains($Expected)) { throw $Message } } $root = Split-Path -Parent $PSScriptRoot $pages = @{ T01 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t01-tree-overview.vue') -Raw -Encoding UTF8 T03 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t03-member-profile.vue') -Raw -Encoding UTF8 T04 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t04-add-relative.vue') -Raw -Encoding UTF8 T05 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t05-edit-member.vue') -Raw -Encoding UTF8 T06 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t06-edit-relationship.vue') -Raw -Encoding UTF8 T07 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t07-member-directory.vue') -Raw -Encoding UTF8 T08 = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t08-member-states.vue') -Raw -Encoding UTF8 } foreach ($entry in $pages.GetEnumerator()) { if ($entry.Value -match '\buni\.(?:navigateTo|navigateBack|redirectTo|reLaunch|switchTab)\b') { throw "$($entry.Key) must use the navigation gateway exclusively" } if ($entry.Value.Contains('/pages/')) { throw "$($entry.Key) must not own route literals" } } foreach ($required in @( 'appApi.getTree', 'const memberActions = Object.freeze([', 'const openMemberAction = (action) =>', 'openPage("T03"', 'routeKey: "T04"', 'routeKey: "T05"', 'routeKey: "T06"', 'return openPage(action.routeKey, params, "T01")' )) { Assert-Contains $pages.T01 $required "T01 missing member flow contract: $required" } foreach ($required in @( 'appApi.getPerson(', 'const memberTrail = reactive([]);', 'const trailIndex = ref(-1);', 'const openRelative = async (nextPersonId) =>', 'onUnload(() =>', 'memberRequestController.abort()' )) { Assert-Contains $pages.T03 $required "T03 missing remote member trail contract: $required" } foreach ($key in @('T04', 'T05', 'T06')) { $content = $pages[$key] foreach ($required in @('appApi.getPerson(', 'createRequestController', 'isRequestCancelled', 'onUnload(() =>')) { Assert-Contains $content $required "$key missing remote closed-flow contract: $required" } foreach ($forbidden in @('@/data/mock.js', 'setTimeout(')) { if ($content.Contains($forbidden)) { throw "$key retains local preview owner: $forbidden" } } } Assert-Contains $pages.T04 'relationType.value' 'T04 must accept the validated relation intent from T01' $routes = Get-Content -LiteralPath (Join-Path $root 'utils/navigation-routes.js') -Raw -Encoding UTF8 Assert-Contains $routes 'allowedSources: ["T01", "T03"]' 'T05 route source contract drifted' Assert-Contains $pages.T06 'query.mode !== "rank"' 'T06 must reject non-rank entry modes' Write-Output 'T03-T08-MEMBER-FLOW-CONTRACT PASS REMOTE-WRITE'