From 29256329e4edf3386c9c5885f825d23482bbcfca Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 21:04:40 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E5=AE=9A=E6=A1=8C=E9=9D=A2=E5=A3=B3?= =?UTF-8?q?=E4=BA=A7=E7=89=A9=E9=AA=8C=E6=94=B6=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 桌面壳配置检查反查根级 release 二进制产物验收 同步原生壳方案文档和共享决策记录 --- apps/desktop-shell/scripts/check-config.mjs | 38 +++++++++++++++++++ .../shared-memory/decision-log.md | 6 +-- ...ExpoReactNative与Tauri宿主壳方案-2026-06-17.md | 2 +- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/apps/desktop-shell/scripts/check-config.mjs b/apps/desktop-shell/scripts/check-config.mjs index 5da20a638..889d34bd2 100644 --- a/apps/desktop-shell/scripts/check-config.mjs +++ b/apps/desktop-shell/scripts/check-config.mjs @@ -8,6 +8,11 @@ const rootPackagePath = new URL('../../../package.json', import.meta.url); const rootPackageConfig = JSON.parse(fs.readFileSync(rootPackagePath, 'utf8')); const rootPackageLockPath = new URL('../../../package-lock.json', import.meta.url); const rootPackageLock = JSON.parse(fs.readFileSync(rootPackageLockPath, 'utf8')); +const nativeShellCheckPath = new URL( + '../../../scripts/check-native-shells.mjs', + import.meta.url, +); +const nativeShellCheckSource = fs.readFileSync(nativeShellCheckPath, 'utf8'); const capabilityPath = new URL( '../src-tauri/capabilities/main.json', import.meta.url, @@ -636,6 +641,39 @@ assertNoBlockedCargoLockPackages(); assertNoBlockedDesktopSdkSnippets(); assertDesktopSourceLayout(); +for (const snippet of [ + 'label: \'desktop-shell-release-build-smoke\'', + "args: ['run', 'desktop-shell:build', '--', '--no-bundle']", + 'function assertDesktopReleaseBinaryArtifact()', + "'apps'", + "'desktop-shell'", + "'src-tauri'", + "'target'", + "'release'", + 'genarrative-desktop-shell.exe', + 'genarrative-desktop-shell', + 'desktop release binary is missing', + 'desktop release binary must be a real non-empty executable file', + 'desktop Linux release binary must be an executable ELF file', + 'desktop macOS release binary must be an executable Mach-O file', + 'desktop Windows release binary must be a PE executable', + 'header[0] === 0x7f', + 'header[1] === 0x45', + 'header[2] === 0x4c', + 'header[3] === 0x46', + '(stat.mode & 0o111) === 0', + 'header.readUInt32BE(0)', + 'machMagic === 0xfeedfacf', + 'header[0] !== 0x4d', + 'header[1] !== 0x5a', + "console.log('[check:native-shells] desktop-release-binary-artifact')", + 'assertDesktopReleaseBinaryArtifact();', +]) { + if (!nativeShellCheckSource.includes(snippet)) { + throw new Error(`root native shell gate must keep desktop release artifact check ${snippet}`); + } +} + for (const [scriptName, expected] of Object.entries({ dev: 'WEB_PORT=3000 tauri dev', build: 'tauri build', diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 252310c12..186d17e17 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -2988,9 +2988,9 @@ ## 2026-06-20 桌面壳 release 二进制产物验收 - 背景:桌面壳统一验收已经执行 `tauri build --no-bundle`,但如果只看命令退出码,后续产物路径、二进制名称或平台输出发生漂移时,可能无法证明本机确实产出了可执行桌面壳。 -- 决策:`npm run check:native-shells` 在桌面 release build smoke 后必须检查 `apps/desktop-shell/src-tauri/target/release/genarrative-desktop-shell` 存在、体积非空,并按当前平台校验 Linux ELF / macOS Mach-O / Windows PE 文件头和可执行位。该检查不启动 GUI,也不生成平台安装包。 -- 影响范围:`scripts/check-native-shells.mjs`、原生壳方案文档。 -- 验证方式:`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。 +- 决策:`npm run check:native-shells` 在桌面 release build smoke 后必须检查 `apps/desktop-shell/src-tauri/target/release/genarrative-desktop-shell` 存在、体积非空,并按当前平台校验 Linux ELF / macOS Mach-O / Windows PE 文件头和可执行位。`apps/desktop-shell/scripts/check-config.mjs` 必须反查根级门禁仍保留 release build smoke 和二进制产物检查。该检查不启动 GUI,也不生成平台安装包。 +- 影响范围:`scripts/check-native-shells.mjs`、`apps/desktop-shell/scripts/check-config.mjs`、原生壳方案文档。 +- 验证方式:`npm run desktop-shell:typecheck`、`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。 ## 2026-06-20 移动壳 smoke 脚本进入生产扫描 diff --git a/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md b/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md index 5a491b84c..2c7027380 100644 --- a/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md +++ b/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md @@ -509,7 +509,7 @@ GameBridge 禁止: 2026-06-19 追加:桌面壳 macOS 媒体权限说明进入门禁。Tauri 桌面壳仍不新增摄像头或麦克风 HostBridge method,不把系统媒体能力暴露成桌面命令;同源 H5 页面可继续使用浏览器标准 `getUserMedia` 承接儿童动作热身 Demo 的实时摄像头输入和汪汪声浪正式 runtime 的实时麦克风输入。macOS 分发包必须通过 `bundle.macOS.infoPlist="Info.plist"` 合并受控用途说明:`NSCameraUsageDescription` 只描述同源 H5 实时动作输入,`NSMicrophoneUsageDescription` 只描述同源 H5 实时声音玩法。`apps/desktop-shell/scripts/check-config.mjs` 会校验 plist 路径和两条文案,并把 `Info.plist` 纳入生产壳替身词扫描,防止桌面包缺少系统授权说明、把媒体权限扩写成通用采集能力,或在 macOS 分发配置里留下临时替身文本。 -2026-06-18 追加:桌面壳 release 构建烟测进入统一验收。`npm run check:native-shells` 会在 H5 HostBridge、Expo 壳和 Tauri 单测通过后执行 `npm run desktop-shell:build -- --no-bundle`,确认根 `dist` H5 资产、Tauri release 入口、受控命令白名单、图标和 Rust release 编译可以共同产出桌面二进制;构建后还必须检查 `target/release/genarrative-desktop-shell` 存在、非空且符合当前平台可执行文件头。该烟测不生成平台安装包,避免把 Linux 本机缺少的系统打包器误判为 HostBridge 回归。 +2026-06-18 追加:桌面壳 release 构建烟测进入统一验收。`npm run check:native-shells` 会在 H5 HostBridge、Expo 壳和 Tauri 单测通过后执行 `npm run desktop-shell:build -- --no-bundle`,确认根 `dist` H5 资产、Tauri release 入口、受控命令白名单、图标和 Rust release 编译可以共同产出桌面二进制;构建后还必须检查 `target/release/genarrative-desktop-shell` 存在、非空且符合当前平台可执行文件头。`apps/desktop-shell/scripts/check-config.mjs` 会反查根级门禁仍保留 release build smoke、二进制路径、Linux ELF / macOS Mach-O / Windows PE 文件头和可执行位检查,避免桌面产物验收被改成只看命令退出码。该烟测不生成平台安装包,避免把 Linux 本机缺少的系统打包器误判为 HostBridge 回归。 2026-06-18 追加:移动壳 Expo managed config 烟测进入统一验收。`npm run check:native-shells` 会执行 `npm run mobile-shell:config`,在 `apps/mobile-shell` 目录内调用 `expo config --type public --json`,校验 Expo CLI 实际解析结果中的包名、scheme、深链、ATS / cleartext / backup / 相机与麦克风权限、启动页、adaptive icon、插件配置和 HostBridge 版本没有漂移。