$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $page = Get-Content -LiteralPath (Join-Path $root 'pages/tree/t07-member-directory.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 } } Assert-Match 'class="directory-context"' 'T07 must show the current genealogy context.' Assert-Match '\u5f53\u524d\u5bb6\u8c31' 'T07 must not render a stale mock genealogy name.' Assert-Match '''directory-state--loading'': directoryState === ''loading''' 'T07 loading state must have an explicit root class.' Assert-Match 'v-if="directoryState === ''list'' \|\| directoryState === ''empty''"' 'T07 search must remain available for list and empty states only.' Assert-Match 'class="directory-search__action"[^>]*role="button"[^>]*aria-label="\u67e5\u627e\u6210\u5458"' 'T07 search action must expose button semantics and an accessible label.' Assert-Match ']+type="secondary"[^>]+:label="hasValidContext \? ''\u91cd\u65b0\u67e5\u770b'' : ''\u8fd4\u56de\u4e0a\u4e00\u9875''"[^>]+@click="retryDirectory"' 'T07 error state must provide context-safe recovery.' Assert-Match '(?s)const retryDirectory = \(\) => \{\s*if \(!hasValidContext\.value\) return goBack\(\);\s*pageNum\.value = 1;\s*return loadMembers\(\);\s*\}' 'T07 retry action must reload a valid directory context.' Assert-Match '(?s)\.directory-page\s*\{[^}]*overflow-y:\s*auto;' 'T07 must allow natural vertical scrolling.' if ($page -match '(?s)\.directory-page\s*\{[^}]*overflow-x:\s*hidden;') { throw 'T07 must not hide horizontal layout failures at the page root.' } Assert-Match '(?s)\.directory-search\s*\{[^}]*min-height:\s*44px;' 'T07 search field must preserve a 44 CSS px minimum touch height at every viewport.' Assert-Match '(?s)\.directory-search__action\s*\{[^}]*min-width:\s*88rpx;[^}]*min-height:\s*44px;' 'T07 search action must preserve a 44 CSS px touch target.' Assert-Match '@include adaptive\.adaptive-tree-field;' 'T07 search must consume the shared adaptive tree field profile.' Assert-Match '@include adaptive\.adaptive-genealogy-list-card;' 'T07 member cards must consume the shared adaptive genealogy list profile.' foreach ($asset in @('modules/tree/transparent/t07-search-input-frame.png', 'modules/genealogy/transparent/list-slip-frame.png')) { if ($profiles -notmatch [regex]::Escape($asset)) { throw "Adaptive profiles must own the T07 surface: $asset" } } if ($page -match 'g06-search-input-wide\.png|application-status-card\.png') { throw 'T07 must not reuse opaque search or application-status skins.' } if ($page -match 'row-seal-frame\.png|directory-card__seal') { throw 'T07 member cards must not repeat generation information in decorative seals.' } Assert-Match 'class="directory-card__status"' 'T07 member identity or profile state must use a dedicated status label.' foreach ($state in @('loading', 'list', 'empty', 'error')) { Assert-Match $state "T07 must preserve the $state state." } Write-Output 'T07-MODULE-BASELINE-CONTRACT PASS'