$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $page = Get-Content -LiteralPath (Join-Path $root 'pages/genealogy/g01-my-genealogies.vue') -Raw -Encoding UTF8 $mock = Get-Content -LiteralPath (Join-Path $root 'data/mock.js') -Raw -Encoding UTF8 $api = Get-Content -LiteralPath (Join-Path $root 'utils/api.js') -Raw -Encoding UTF8 $context = Get-Content -LiteralPath (Join-Path $root 'utils/genealogy-context.js') -Raw -Encoding UTF8 foreach ($token in @('genealogyContext', 'setCurrentGenealogyId', 'reconcileCurrentGenealogyId', 'invalidateCurrentGenealogyId', 'isCurrentGenealogyInvalidated', 'reconcilePageGenealogyContext', 'item.accessRole === "owner"', 'item.accessRole === "member"', 'String(query?.genealogyId || "")', 'contextInvalidated', 'state-panel--context', ') || null,', ' \{\s*loadGenealogies\(\)') { throw 'G01 retry must rerun the remote list owner instead of exposing a dead button' } if ($page -match '@/data/mock\.js|getGenealogyFixtureAccess|listNotificationFixtures') { throw 'G01 remote page must not retain fixture data owners' } foreach ($membership in @("membership: 'created'", "membership: 'joined'")) { if (-not $mock.Contains($membership)) { throw "Genealogy mock ownership missing: $membership" } } if (-not $api.Contains('id: String(Date.now())')) { throw 'Mock genealogy creation must produce a lexical string ID' } Write-Output 'G01-GENEALOGY-CONTEXT-CONTRACT PASS'