$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $page = Get-Content -LiteralPath (Join-Path $root 'pages/records/r01-people-list.vue') -Raw -Encoding utf8 $profiles = Get-Content -LiteralPath (Join-Path $root 'styles/adaptive-frame-profiles.scss') -Raw -Encoding utf8 function Assert-Match([string]$Pattern, [string]$Message) { if ($page -notmatch $Pattern) { throw $Message } } if ($page -match "import\s+ModulePage\s+from|)") { throw 'R01 must own its page instead of delegating to ModulePage.' } if ($page -match 'application-status-card\.png') { throw 'R01 must not reuse the application status card.' } if ($page -match 'people-intro|brand-seal\.png') { throw 'R01 must not repeat a numbered intro block below the page header.' } Assert-Match '@include\s+adaptive\.adaptive-records-person\s*;' 'R01 must consume its dedicated adaptive person-card profile.' Assert-Match '@include\s+adaptive\.adaptive-records-field\s*;' 'R01 must consume the shared adaptive records field profile.' if ($profiles -notmatch '(?s)@mixin\s+adaptive-records-person\s*\{.*?modules/records/transparent/r01-person-name-card\.png') { throw 'The adaptive profile owner must retain R01 dedicated person-card artwork.' } Assert-Match 'class="people-search"' 'R01 must expose its search region.' Assert-Match 'people-state--empty' 'R01 must expose an empty review state.' Assert-Match 'people-state--error' 'R01 must expose an error review state.' Assert-Match 'AppButton' 'R01 must use the project button component.' Assert-Match 'AppToast' 'R01 must use the project Toast component.' Assert-Match '/pages/records/r02-person-detail' 'R01 person cards must navigate to R02.' Assert-Match '(?s)\.people-search__action\s*\{[^}]*min-height:\s*44px;' 'R01 search action must preserve a 44 CSS px touch height.' if ($page -match 'position\s*:') { throw 'R01 must keep ordinary content in document flow.' } Write-Output 'R01-MODULE-BASELINE-CONTRACT PASS'