$ErrorActionPreference = 'Stop' $projectRoot = [IO.Path]::GetFullPath('C:\wechat_rpa') $artifactRoot = [IO.Path]::GetFullPath('C:\kefu\deploy\protocol-file-identity-20260917') $installer = Join-Path $projectRoot 'dist\installer\甄AI客服-安装包-v1.4.17.exe' $exe = Join-Path $projectRoot 'dist\ZhenAI-WeCom-Assistant-v1.4.17\ZhenAI-WeCom-Assistant-v1.4.17.exe' $releases = Join-Path $projectRoot 'releases' $releaseInstaller = [IO.Path]::GetFullPath((Join-Path $releases '甄AI客服-安装包-v1.4.17.exe')) if (-not $releaseInstaller.StartsWith($releases + '\', [StringComparison]::OrdinalIgnoreCase)) { throw 'Release path is outside workspace release folder' } if (Test-Path -LiteralPath $releaseInstaller) { throw 'Release artifact already exists; refusing to overwrite' } $sevenZip = Join-Path $projectRoot 'tmp\7zip-offline\7z.exe' & $sevenZip t $installer *> (Join-Path $artifactRoot 'installer-integrity.log') if ($LASTEXITCODE -ne 0) { throw 'Installer archive integrity check failed' } New-Item -ItemType Directory -Path $releases -Force | Out-Null Copy-Item -LiteralPath $installer -Destination $releaseInstaller $hash = (Get-FileHash -LiteralPath $installer -Algorithm SHA256).Hash.ToLowerInvariant() $copiedHash = (Get-FileHash -LiteralPath $releaseInstaller -Algorithm SHA256).Hash.ToLowerInvariant() if ($hash -ne $copiedHash) { throw 'Release copy hash mismatch' } $exeHash = (Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant() $appLog = Get-Content -Raw -LiteralPath (Join-Path $artifactRoot 'app-build.log') if (-not $appLog.Contains('Packaged Qt WebEngine self-check passed')) { throw 'Production self-check marker missing' } if (-not $appLog.Contains('C:\wechat_rpa\.build-venv\Scripts\python.exe')) { throw 'Expected build runtime marker missing' } $report = [ordered]@{ version = '1.4.17' buildRuntime = 'CPython 3.12.14 x64' buildPython = 'C:\wechat_rpa\.build-venv\Scripts\python.exe' pyinstaller = '6.22.2' pyside6 = '6.10.3' productionSelfCheck = 'passed' frozenFileIdentityRegression = 'passed' installerIntegrity = 'passed: 7-Zip t' installer = [ordered]@{ path = $releaseInstaller; buildPath = $installer; bytes = (Get-Item -LiteralPath $releaseInstaller).Length; sha256 = $hash; signature = [string](Get-AuthenticodeSignature -LiteralPath $releaseInstaller).Status } executable = [ordered]@{ path = $exe; bytes = (Get-Item -LiteralPath $exe).Length; sha256 = $exeHash; productVersion = (Get-Item -LiteralPath $exe).VersionInfo.ProductVersion } installed = $false published = $false currentUserApplicationStopped = $false realMessagesSent = 0 finishedAt = (Get-Date).ToString('o') } [IO.File]::WriteAllText((Join-Path $artifactRoot 'release-v1.4.17.json'), ($report | ConvertTo-Json -Depth 6), [Text.UTF8Encoding]::new($false)) [IO.File]::WriteAllText(($releaseInstaller + '.sha256'), ($hash + ' ' + [IO.Path]::GetFileName($releaseInstaller) + "`n"), [Text.UTF8Encoding]::new($false)) $report | ConvertTo-Json -Depth 6