$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $list = Get-Content -LiteralPath (Join-Path $root 'pages/notification/n01-message-center.vue') -Raw -Encoding UTF8 $detail = Get-Content -LiteralPath (Join-Path $root 'pages/notification/n02-message-detail.vue') -Raw -Encoding UTF8 foreach ($token in @('listNotificationFixtures', 'unreadCount', 'openNotice', ':action="unreadCount > 0')) { if (-not $list.Contains($token)) { throw "N01-N02 flow missing: $token" } } if ($list -notmatch '(?s)openPage\(\s*"N02",\s*\{ id: String\(item\.id\) \},\s*"N01",?\s*\)') { throw 'N01 must open N02 through the registered gateway with only lexical id and N01 source' } foreach ($token in @('findNotificationFixture', 'noticeDetail.unread', 'markAsRead', 'getGenealogyFixtureAccess', 'openNoticeTarget as navigateNoticeTarget', 'noticeDetail.value.targetType', 'noticeDetail.value.targetParams')) { if (-not $detail.Contains($token)) { throw "N02 business detail missing: $token" } } if ($detail -notmatch '(?s)const selectedNotice = findNotificationFixture\(noticeId\.value\);.*?if \(.*?!selectedNotice.*?\) \{.*?noticeState\.value = "expired";.*?return;') { throw 'N02 unknown notice identity must fail closed' } if ($detail.Contains('noticeDetail.read') -or -not $detail.Contains('noticeDetail.value.unread = false;')) { throw 'N02 must consume and update the notification owner unread field' } if (-not $detail.Contains('const backToMessages = () => returnTo("N01", {});')) { throw 'N02 must return to N01 through the registered return gateway' } if (-not $detail.Contains('onBackPress((event) => handleBackPress(event, backToMessages));')) { throw 'N02 Android back must reuse the guarded N01 return' } foreach ($source in @($list, $detail)) { foreach ($forbidden in @('detailId', 'const noticeDetails', 'target: "/pages/', 'targetUrl', 'returnUrl', 'uni.navigateTo', 'uni.navigateBack', 'uni.redirectTo', 'uni.reLaunch', '/pages/')) { if ($source.Contains($forbidden)) { throw "N01-N02 retains a duplicate owner or navigation bypass: $forbidden" } } } if ($detail -match 'noticeDetail\.value\.target(?![A-Za-z0-9_$])') { throw 'N02 must not consume an executable notification target field' } Write-Output 'N01-N02-MESSAGE-FLOW-CONTRACT PASS'