$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $tree = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t01-tree-overview.vue') -Raw -Encoding UTF8 $pedigree = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t02-pedigree-overview.vue') -Raw -Encoding UTF8 $routes = Get-Content -LiteralPath (Join-Path $root 'utils/navigation-routes.js') -Raw -Encoding UTF8 foreach ($required in @( 'class="member-node__surface"', 'const memberActionPanelVisible = ref(false)', 'const memberActions = Object.freeze([', 'const openMemberAction = (action) =>', '', 'const openMemberDetail = async (member) =>', 'appApi.getPerson(genealogyId.value, member.id', 'detailVisible', 'class="member-node__name"', 'class="member-node__copy"' )) { if (-not $pedigree.Contains($required)) { throw "T02 pedigree member interaction missing: $required" } } foreach ($required in @( 'optionalParams: ["personId", "mode", "relationType"]', 'allowedSources: ["T01", "T02", "T03"]', 'optionalParams: ["mode"]' )) { if (-not $routes.Contains($required)) { throw "Tree route contract missing: $required" } } Write-Output 'T01-PERSON-ACTION-PANEL-CONTRACT PASS'