$ErrorActionPreference = 'Stop' function Read-Utf8([string]$Path) { [System.IO.File]::ReadAllText( (Join-Path (Join-Path $PSScriptRoot '..') $Path), [System.Text.Encoding]::UTF8 ) } function Assert-Contains { param([string]$Content, [string]$Expected, [string]$Message) if (-not $Content.Contains($Expected)) { throw $Message } } $page = Read-Utf8 'pages/family/f09-media-upload.vue' $catalog = Read-Utf8 'data/page-catalog.js' foreach ($expected in @( 'class="media-upload-page"', 'media-upload-state--${uploadState}', 'class="media-album-card"', 'class="media-photo-grid"', 'class="media-add-tile"', 'class="media-batch-field"', 'class="media-photo-field"', 'class="media-photo-editor"', 'class="media-photo-editor__thumb"', 'class="media-photo-editor__position"', 'const MAX_PHOTOS = 9;', 'const selectMockPhotos = () =>', 'const selectPhoto = (index) =>', 'const removePhoto = (index) =>', 'const addMockPhoto = () =>', 'const updateActiveNote = (event) =>', 'const startUpload = () =>', 'const retryFailed = () =>', 'const returnToAlbum = () =>', '["permission", "selected", "uploading", "error", "success"].includes(query.state)', 'class="media-permission-action"', 'class="media-photo-status media-photo-status--error"', 'class="media-success-title"', 'class="media-progress-copy"', 'class="media-primary-action"', 'class="media-retry-action"', 'f08-reunion-hero.png', 'f08-family-portrait.png', 'f08-reunion-table.png', 'f08-ancestral-home.png', 'f08-ancestral-portrait.png', 'ModulePageBackground', 'PageHeader', 'AppButton' )) { Assert-Contains $page $expected "F09 contract missing: $expected" } foreach ($forbidden in @( '