$ErrorActionPreference = 'Stop' $taskProjectRoot = [IO.Path]::GetFullPath('C:\wechat_rpa') $taskArtifactRoot = [IO.Path]::GetFullPath('C:\kefu\deploy\review-picker-20260918') $taskInstaller = Join-Path $taskProjectRoot 'dist\installer\甄AI客服-安装包-v1.4.24.exe' $taskRelease = Join-Path $taskProjectRoot 'releases\甄AI客服-安装包-v1.4.24.exe' $taskFrozen = Get-Content -Raw -LiteralPath (Join-Path $taskArtifactRoot 'frozen-continuity-tests.json') | ConvertFrom-Json $taskIntegrity = Get-Content -Raw -LiteralPath (Join-Path $taskArtifactRoot 'nsis-payload-integrity.json') | ConvertFrom-Json $taskQA = Get-Content -Raw -LiteralPath (Join-Path $taskArtifactRoot 'frozen-release-qa.json') | ConvertFrom-Json $taskBuildLog = Get-Content -Raw -LiteralPath (Join-Path $taskArtifactRoot 'app-build.log') $taskPanel = Get-Content -Raw -LiteralPath (Join-Path $taskArtifactRoot 'panel-dom-results-frozen.json') | ConvertFrom-Json if ($taskPanel.status -ne 'passed' -or $taskPanel.checks -lt 64) { throw 'Frozen panel regression incomplete' } if ($taskFrozen.failures -ne 0 -or $taskFrozen.errors -ne 0 -or $taskFrozen.blocked_external_actions.Count -ne 0) { throw 'Frozen regression checks failed' } if (-not $taskQA.sourceManifestMatches -or -not $taskQA.privateFilesExcluded -or -not $taskQA.uiAssetsMatchSource) { throw 'Frozen release checks failed' } if (-not $taskBuildLog.Contains('Packaged Qt WebEngine self-check passed')) { throw 'Packaged self-check did not pass' } $taskHash = (Get-FileHash -LiteralPath $taskInstaller -Algorithm SHA256).Hash.ToLowerInvariant() if (-not $taskIntegrity.crcPassed -or -not $taskIntegrity.completeDeflateStream -or $taskIntegrity.missingFiles.Count -ne 0 -or $taskIntegrity.installerSha256 -ne $taskHash) { throw 'Installer integrity verification failed' } if (Test-Path -LiteralPath $taskRelease) { throw 'Release already exists; refusing to overwrite' } New-Item -ItemType Directory -Path (Split-Path -Parent $taskRelease) -Force | Out-Null Copy-Item -LiteralPath $taskInstaller -Destination $taskRelease if ((Get-FileHash -LiteralPath $taskRelease -Algorithm SHA256).Hash.ToLowerInvariant() -ne $taskHash) { throw 'Release copy differs' } $taskReport = [ordered]@{ version = '1.4.24' installer = $taskRelease bytes = (Get-Item -LiteralPath $taskRelease).Length sha256 = $taskHash frozenRegressionTests = $taskFrozen.tests_run frozenPanelAssertions = $taskPanel.checks frozenPanelScreenshots = $taskPanel.screenshots packagedSelfCheck = 'passed' privateFilesExcluded = $true installerIntegrity = 'NSIS CRC32, complete deflate stream, all application file SHA256 hashes' contactPickerFix = 'readable contact order, visible selection and saved recipient display' enabledByDefault = $false realMessagesSent = 0 installed = $false published = $false liveClientRestarted = $false finishedAt = (Get-Date).ToString('o') } [IO.File]::WriteAllText((Join-Path $taskArtifactRoot 'release-v1.4.24.json'), ($taskReport | ConvertTo-Json -Depth 4), [Text.UTF8Encoding]::new($false)) [IO.File]::WriteAllText(($taskRelease + '.sha256'), ($taskHash + ' ' + [IO.Path]::GetFileName($taskRelease) + "`n"), [Text.UTF8Encoding]::new($false)) $taskReport | ConvertTo-Json -Depth 4