cc-haha/docs/desktop/09-electron-migration-validation-checklist.md
程序员阿江(Relakkes) 81845fbc49 fix: finalize Electron migration boundaries
Complete the Electron replacement boundary before merging by removing the renderer-side Tauri host fallback, tightening H5/browser access so only desktop navigation is tokenless, and moving desktop release publication to a tag-driven GitHub Actions matrix with a single final publish job.

Constraint: H5/browser capability access must not gain tokenless access through localhost or retired Tauri origins

Constraint: Desktop release artifacts must be built by GitHub Actions from version tags, not treated as local build outputs

Rejected: Keep localhost browser origins trusted for convenience | local browser contexts can access loopback services and must use the H5 token path

Rejected: Publish from each matrix job | partial releases can be created before all platforms finish

Confidence: high

Scope-risk: broad

Directive: Do not reintroduce Tauri origins or localhost browser origins into the trusted desktop origin set without a reviewed security design

Tested: bun test src/server/__tests__/h5-access-policy.test.ts src/server/__tests__/h5-access-auth.test.ts src/server/__tests__/diagnostics-service.test.ts src/server/middleware/cors.test.ts

Tested: bun test scripts/pr/release-workflow.test.ts scripts/release-update-metadata.test.ts

Tested: bun run check:desktop

Tested: bun run check:native

Tested: git diff --check

Not-tested: bun run check:server is blocked by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-02 22:42:53 +08:00

173 lines
41 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Electron 迁移验证清单
> 用于迁移收口,不替代 `docs/desktop/08-electron-migration-tasks.md`。`package-smoke` 只验证包结构和关键资源,不声明 GUI 启动或交互成功。
交互式执行版见 [`electron-migration-qa-checklist.html`](/desktop/electron-migration-qa-checklist.html),可在本地浏览器直接打开并用 `localStorage` 保存勾选进度与问题记录。
## 已有自动化证据
- [x] `bun run check:native`sidecar build、Electron TypeScript、83 个 Electron IPC/service 测试、main/preload/preview-preload bundle、Electron `--dir` 打包和当前平台 package-smoke 均通过。
- [x] `bun run check:desktop`desktop lint、151 个 Vitest 文件、1199 个测试、renderer production build 均通过。
- [x] `bun test scripts/quality-gate/package-smoke/index.test.ts scripts/pr/release-workflow.test.ts`package-smoke harness 与 release workflow 静态回归通过。
- [x] `bun test scripts/quality-gate/package-smoke/index.test.ts scripts/pr/release-workflow.test.ts scripts/quality-gate/runner.test.ts`25 tests passed覆盖 release lane、显式 GitHub publish 配置和 `latest-mac.yml` 引用真实 artifact 的 package-smoke 回归。
- [x] `bun test scripts/quality-gate/package-smoke/index.test.ts scripts/pr/release-workflow.test.ts scripts/release-update-metadata.test.ts`26 tests passed覆盖 Windows canonical output、Linux x64/arm64 `latest-linux*.yml` update metadata、release workflow Gatekeeper/signing preflight 和 post-matrix metadata republish。
- [x] `cd desktop && CSC_IDENTITY_AUTO_DISCOVERY=false bun run electron:package:dir`macOS unpacked `.app` 可打包。
- [x] `bun run test:package-smoke --platform macos`macOS `.app` 结构、`app.asar`、unpacked sidecar、unpacked `node-pty` native module 和 `spawn-helper` 通过静态检查。
- [x] macOS `.zip/latest-mac.yml` 发布产物复验:`MAC_TARGETS=zip SKIP_INSTALL=1 SIGN_BUILD=0 desktop/scripts/build-macos-arm64.sh` 通过canonical 输出包含 `.app``.zip``.zip.blockmap``latest-mac.yml`,脚本末尾自动运行 canonical package-smoke 并 PASS。
- [x] macOS directory-only native/package 当前态:`bun run check:native` 通过,覆盖 sidecar 构建/ad-hoc signing、Electron 83 tests、production build、`electron-builder --dir``package-smoke --package-kind dir --artifacts-dir desktop/build-artifacts/electron`。该项只证明 unpacked bundle 结构和关键资源,不证明 `.dmg`、Gatekeeper 或 signed release launch。
- [x] macOS `.dmg/.zip/latest-mac.yml` 当前态复验:`SKIP_INSTALL=1 SIGN_BUILD=0 desktop/scripts/build-macos-arm64.sh` 已通过默认 `dmg zip` targetcanonical `desktop/build-artifacts/macos-arm64` 包含 `.app``.dmg``.dmg.blockmap``.zip``.zip.blockmap``latest-mac.yml`,脚本末尾 release package-smoke PASS。
- [x] macOS canonical packaged launch smoke使用隔离 `CLAUDE_CONFIG_DIR`、隔离 `--user-data-dir``CC_HAHA_ELECTRON_DISABLE_SINGLE_INSTANCE_LOCK=1` 启动 `desktop/build-artifacts/macos-arm64/Claude Code Haha.app`server sidecar 启动于临时端口Computer Use `get_app_state` 成功读取 `Claude Code Companion` 主窗口和 packaged `file://.../app.asar/dist/index.html` renderer。
- [x] macOS canonical packaged system interaction smoke同一 canonical `.app` 隔离实例中Computer Use 确认项目选择器显示系统目录选择结果 `/private/tmp/cc-haha-electron-real-fixed-sRFUeO/project`;打开终端后执行 `printf 'canonical-terminal-ok\n'; pwd`,画面可见 `canonical-terminal-ok` 与实际工作目录输出,且未出现 Safe Storage 钥匙串弹窗。
- [x] 本地 `main` 同步后 targeted checks 通过:`cd desktop && bun run test -- src/components/workspace/WorkspaceFileOpenWith.test.tsx src/lib/previewEvents.test.ts electron/services/updater.test.ts``cd desktop && bun run check:electron``bun test src/server/middleware/cors.test.ts src/server/__tests__/h5-access-policy.test.ts`
## Review 已收口
- [x] Packaged app 不再信任 `ELECTRON_RENDERER_URL`;只有 dev 模式允许 local HTTP renderer。
- [x] Preview external page bridge 增加消息大小上限、事件类型 allowlist、字段 schema 和 data URL 校验。
- [x] Packaged macOS `node-pty` runtime cache 会从 bundle manifest 校验,发现 tamper 后重建cache 权限收紧。
- [x] macOS 通知设置入口改走 native command + allowlisted system settings URL。
- [x] Electron `preview.message()` 不再 silent no-op会转发到 injected preview bridge。
- [x] Dev/release desktop workflows 在 Electron builder 后运行 `test:package-smoke`,阻止缺失关键 runtime 资源的产物上传/发布。
- [x] Packaged Electron `file://` renderer origin 已纳入 server CORS/H5 token local-origin policy避免真实打包 app 的 chat WebSocket 在 H5 token mode 下被拒绝。
- [x] Electron Builder publish 配置不再依赖 git remote autodetection`artifactName` 改为无空格稳定文件名package-smoke 会检查 `latest*.yml` 引用的本地 artifact 是否存在。
## 必跑本地门禁
- [x] `bun run check:native`
- [x] `bun run check:desktop`
- [x] `bun run check:docs`
- [x] `bun run verify`:最新为 `artifacts/quality-runs/2026-05-31T21-42-57-279Z/report.md``passed=9 failed=0 skipped=1`
- [x] `bun run check:coverage`:最新为 `artifacts/coverage/2026-05-31T21-46-15-873Z/coverage-report.md``passed=5 failed=0`
- [x] 同步本地 `main``file://` CORS/H5 修复和 Electron 迁移当前态后复跑 `bun run check:server`88 files / 969 tests passed。
- [x] 同步本地 `main` 与 updater no-op 修复后复跑 `cd desktop && bun run check:electron`16 files / 76 tests passed。
- [x] `bun run test:package-smoke --platform macos`
- [x] `cd desktop && bun run test -- --run scripts/dev-launcher.test.ts && bun run check:electron`:新增 Electron dev launcher 代理绕过回归,最新 Electron checks 为 17 files / 79 tests passed。
- [x] `bun run test:package-smoke --platform macos`:结构检查仍通过,并明确提示该命令不做 Gatekeeper launch approval。
- [x] `cd desktop && bun run test -- src/lib/desktopRuntime.test.ts src/components/shared/UpdateChecker.test.tsx src/lib/composerAttachments.test.ts src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx src/components/layout/AppShell.test.tsx src/components/controls/PermissionModeSelector.test.tsx src/components/shared/RepositoryLaunchControls.test.tsx`8 files / 75 tests passed覆盖 Electron desktop runtime 判断、更新提示、native attachment picker 和移动布局分支。
- [x] `cd desktop && bun run check:electron`16 files / 77 tests passed覆盖 Electron updater proxy contract、IPC payload validation、main/preload/preview-preload bundle。
- [x] `bun test scripts/quality-gate/package-smoke/index.test.ts`7 tests passed发布型 macOS 包缺失 resources/app-update.yml 会失败,纯 `--dir` 开发包不强制该文件。
- [x] `bun test scripts/quality-gate/package-smoke/index.test.ts scripts/pr/quality-contract.test.ts`12 tests passed覆盖 host platform 到 package-smoke platform 的映射,并锁定 `check:native` 必须包含 `electron:package:dir``test:package-smoke:current`
- [x] `bun run check:native`:最新复跑完成 sidecar build、Electron 77 tests、Electron `--dir` package并执行 `bun run test:package-smoke:current` -> macOS `.app` 结构检查 PASSnotes 明确当前纯 `--dir` artifact set 不强制 `app-update.yml`,也不做 GUI/Gatekeeper launch approval。
- [x] Linux `electron-builder --dir` package-smoke 回归Linux 纯 `linux-unpacked` 开发目录包会检查 `app.asar`、unpacked sidecar 和 `node-pty` 后通过,不要求 AppImage/deb发布型 AppImage/deb artifact set 仍要求 update metadata 和 `app-update.yml`
- [x] PR native workflow Electron 化:`desktop-native-checks` 不再安装 WebKitGTK/Rust/Rust cache`build-sidecars` 不再用 `rustc -vV` 推导 host triple`check:native` 只依赖 Bun/Electron sidecar/package-smoke 链路。
- [x] package-smoke 显式包类型:`check:native` 通过 `--package-kind dir --artifacts-dir desktop/build-artifacts/electron` 验开发目录包dev/release workflows 和平台构建脚本通过 `--package-kind release --artifacts-dir <精确输出目录>` 验发布包,避免旧 artifact 混入。
- [x] release gate 验包收窄:`quality:gate --mode release` 现在包含 PR checks并使用当前平台 canonical release dir 运行 `test:package-smoke --package-kind release --artifacts-dir desktop/build-artifacts/<platform-arch>`,不再把 `desktop/build-artifacts/electron` 的开发目录包当 release 证据macOS release lane 还会追加 `--require-macos-gatekeeper`,与 release workflow 上传前 Gatekeeper 检查保持一致。
- [x] 当前平台 canonical release package-smoke 复验:`bun run test:package-smoke --platform macos --package-kind release --artifacts-dir desktop/build-artifacts/macos-arm64` 通过,确认 canonical zip/update metadata/app-update.yml/sidecar/node-pty 结构仍完整;该命令仍不声明 GUI/Gatekeeper launch success。
- [x] release workflow preflightGitHub tag/workflow_dispatch 打包矩阵前先运行 `bun run verify`,避免 tag release 绕过 PR-quality 基线。
- [x] signing/notarization secrets preflight独立非 matrix `signing-preflight` job 在打包矩阵前检查 Developer ID、notarization 和 Windows signing secrets缺失时 GitHub Actions 直接报错并阻止所有平台 artifact 上传,不再等到 Electron Builder/Gatekeeper 阶段或发布 partial release 后才失败。
- [x] 多架构 update metadata 上传冲突规避release workflow 上传前将 `latest*.yml` 重命名为带 matrix label 的唯一 asset避免 GitHub Release 中 `latest-mac.yml/latest-linux.yml` 同名覆盖或上传失败。
- [x] 多架构标准 updater metadata 合并:`scripts/release-update-metadata.ts` 会在 matrix build 全部通过后重新发布标准 channel metadatamacOS 合并 x64/arm64 entries 到 `latest-mac.yml`Linux 恢复 `latest-linux.yml` / `latest-linux-arm64.yml`Windows 恢复 `latest.yml`。完整自动更新 release 仍需在 signed/notarized artifact 上复验。
- [x] `MAC_TARGETS=zip SKIP_INSTALL=1 SIGN_BUILD=0 desktop/scripts/build-macos-arm64.sh`canonical macOS zip/update artifact set 通过;脚本自动执行 `bun run test:package-smoke --platform macos --package-kind release --artifacts-dir desktop/build-artifacts/macos-arm64`,确认 `latest-mac.yml` 引用真实 zip安装后 resources 包含 `app-update.yml`
- [x] `bun run quality:gate --mode baseline --allow-live --only 'provider-smoke:*' --provider-model sub2api-chatgpt:main:sub2api-chatgpt-main``artifacts/quality-runs/2026-05-31T21-28-07-154Z/report.md``passed=1 failed=0 skipped=0`,直接复用本机 cc-haha provider selector。
- [x] 当前 release provider smoke 复验:`bun run quality:gate --mode release --allow-live --only 'provider-smoke:*' --provider-model sub2api-chatgpt:main:sub2api-chatgpt-main` 通过,报告为 `artifacts/quality-runs/2026-06-01T12-18-47-144Z/report.md``passed=1 failed=0 skipped=0`
- [x] `cd desktop && bun test electron/services/updater.test.ts`10 tests passed覆盖 unpacked `app-update.yml` 缺失、packaged update config 缺失时不调用 updater、GitHub release 缺少 `latest-mac.yml` 时降级为无更新、关闭 electron-updater 内置 logger以及非 metadata updater 错误继续抛出。
- [x] `cd desktop && bun run check:electron`:最新 97 tests passed覆盖通知 smoke `close/failed` lifecycle JSONL、synthetic action + renderer ack JSONL、updater missing channel metadata 修复、Keychain guard、single-instance validation bypass、update smoke stub、window smoke 诊断和 Electron main/preload/preview-preload bundle。
- [ ] `bun run test:package-smoke --platform macos --package-kind release --artifacts-dir desktop/build-artifacts/macos-arm64 --require-macos-gatekeeper`:当前失败;非 Gatekeeper 结构检查 PASS包含 `latest-mac.yml` 引用 zip、安装后 `app-update.yml`、sidecar 和 `node-pty`。追加 Gatekeeper 后 `codesign` verify/details 通过,但 `spctl` 返回 `bundle format unrecognized, invalid, or unsuitable``stapler` 返回 `does not have a ticket stapled to it`。package-smoke 现已在 `spctl``Too many open files` 时用 raised file descriptor limit 自动重试,避免该临时诊断掩盖真实 Gatekeeper 结果。release-ready 需要 Developer ID signing/notarization 或在真实签名产物上复验。
- [x] Gatekeeper 失败诊断:`--require-macos-gatekeeper` 现在在 `spctl` 失败时记录 `codesign --verify --deep --strict --verbose=2``codesign -dv --verbose=4``xcrun stapler validate` 摘要,便于 signed/notarized artifact 在 CI/release runner 上定位签名链、bundle 格式或 notarization ticket 问题。
- [x] Gatekeeper 诊断复验:`bun run test:package-smoke --platform macos --package-kind release --artifacts-dir desktop/build-artifacts/macos-arm64 --require-macos-gatekeeper` 预期失败;输出中包含 `spctl Gatekeeper assessment exited with status 1``codesign verification exited with status 0`、bundle identifier/signature detail 摘要,以及 `notarization ticket validation exited with status 65` / `does not have a ticket stapled to it`
- [x] release workflow macOS 上传前强制运行 `bun run test:package-smoke --platform macos --package-kind release --artifacts-dir desktop/build-artifacts/electron --require-macos-gatekeeper`;开发构建仍只跑结构验包,因为 dev workflow 明确禁用签名自动发现。
- [x] Security/Runtime Review 修复Electron renderer 不再有 `previewEval` 任意 JS 注入 IPC预览截图/元素选择走结构化 `preview.message``shell.openPath` 拒绝 app bundle、脚本/安装器/Windows 可执行扩展和 POSIX executable 文件Electron `windowControls=false`Windows 暂不显示自定义 window chrome。
- [x] 历史 `bun run quality:gate --mode release --allow-live --provider-model sub2api-chatgpt:main:sub2api-chatgpt-main``artifacts/quality-runs/2026-05-31T20-29-45-758Z/report.md``passed=15 failed=0 skipped=0`。SubAgent Review 后 release gate 已收窄为 canonical release artifact 验包;该历史报告不能再作为当前 release-ready 证据。
- [ ] 重新运行当前 `bun run quality:gate --mode release --allow-live --provider-model sub2api-chatgpt:main:sub2api-chatgpt-main`:需要 signed/notarized artifact、canonical release metadata 和可用 Computer Use 桌面会话。
- [x] `bun run quality:gate --mode release --dry-run --only 'desktop-package-smoke:*'`:报告 `artifacts/quality-runs/2026-06-01T12-15-48-692Z/report.md`,确认 macOS release package-smoke 命令包含 `--require-macos-gatekeeper`
- [x] `bun run quality:gate --mode release --only 'desktop-package-smoke:*'`:报告 `artifacts/quality-runs/2026-06-01T12-16-06-442Z/report.md`,按预期失败于 Gatekeeper结构检查均通过`spctl` 返回 `bundle format unrecognized, invalid, or unsuitable``stapler` 返回 `does not have a ticket stapled to it`
- [x] `bun run check:policy`77 tests passed并执行 `check:quarantine`;覆盖 release workflow、quality gate runner、provider/desktop smoke、change policy、quality contract 和 quarantine governance。
- [x] 本地 `main` 同步后 focused regression已应用 `main` 最近 10 个提交的非重叠改动,并手动合并 `ChatInput.tsx` / `previewEvents.ts` / `previewEvents.test.ts` 冲突面。验证desktop ChatInput/previewEvents 24 tests passedserver/CLI/image/powershell/provider 124 tests passedFeishu streaming card 36 tests passed`cd desktop && bun run check:electron` 94 tests passed。
- [x] 本地 `main` 同步后重新打包:`CSC_IDENTITY_AUTO_DISCOVERY=false bun run electron:package:dir` 完成当前源码 packaged dir`bun run test:package-smoke --platform macos --package-kind dir --artifacts-dir desktop/build-artifacts/electron` PASS。
- [x] release update blockmap 验证补强:`bun test scripts/quality-gate/package-smoke/index.test.ts` 通过 17 tests`bun run test:package-smoke --platform macos --package-kind release --artifacts-dir desktop/build-artifacts/macos-arm64` PASS并确认当前 macOS release artifact set 包含 `.dmg.blockmap``.zip.blockmap`。Windows `.exe.blockmap` 与 Linux `.AppImage.blockmap` 已由 fixture 回归覆盖,仍需实机 release artifact smoke。
- [x] 通知点击 renderer ack 证据补强Electron renderer 处理通知 action 并打开目标 session 后,会通过 `desktop:notification:action-ack` 回写 `renderer_ack``CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_LOG`,用于后续可点击 OS 通知环境证明 main action 已进入 UI 导航链路。验证focused notification/desktopHost tests 42 passed`cd desktop && bun run check:electron` 97 tests passed。
- [x] `git diff --check`
## macOS Computer Use Smoke
- 2026-06-01 复测阻塞:早期 Computer Use 工具层对 `list_apps``get_app_state(Finder)` 返回 `NSOSStatusErrorDomain Code=-600 procNotFound`;后续 `list_apps` 恢复,但 `get_app_state(Electron)` 仍超时,`get_app_state(Finder)``cgWindowNotFound`,同时系统 `screencapture` 返回 `could not create image from display`。当前阻塞已定位为本机会话显示/截图能力不可用,不能把它解释为 Electron app 单点故障。
- 2026-06-01 continuation 复测Computer Use `list_apps` 可列出运行中应用,但 `get_app_state(Finder)` 仍为 `cgWindowNotFound`;系统 `screencapture` 仍返回 `could not create image from display`。当前仍无法进行点击、输入、选择文件等 Computer Use GUI 操作。
- 2026-06-01 Electron dev smoke本机代理环境会让 `electron:dev` 的 renderer 等待请求命中 502已把默认 renderer URL 改为 `http://localhost:1420`并对当前进程、Vite 子进程和 Electron 子进程补齐 `NO_PROXY/no_proxy=localhost,127.0.0.1,::1`。重启后 Electron dev 壳可启动 sidecar 和 renderer。
- 2026-06-01 窗口可见性修正Electron main 在创建主窗口后立即 `show/focus`renderer load 完成后再补一次,避免隐藏窗口等待 renderer load 时被 Computer Use/系统自动化看成无窗口。
- 2026-06-01 packaged launch policy`open -n desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app` 被 macOS `AppleSystemPolicy` 直接终止ad-hoc 和本机 Apple Development 重新签名的临时副本均未通过 `spctl`。因此当前 unpacked `.app` 只能证明结构完整,不能声明 release launchable。
- 2026-06-01 DMG builder policy清理所有旧 `Claude Code Haha` disk image 挂载后zip-only Electron Builder 可成功产出 update metadataDMG target 仍在本机 `hdiutil create` 超时,且失败后的临时读写 disk image 无法正常 detach。该项保持 macOS runner/DiskImages blocker。
- 2026-06-01 final-definition 复测Computer Use `list_apps` 仍可列出运行中应用,`get_app_state(Finder)` 仍返回 `cgWindowNotFound`;系统 `screencapture -x` 仍返回 `could not create image from display`。当前机器仍不能作为 Computer Use GUI 验收环境。
- 2026-06-01 cross-platform-script 复测Computer Use `list_apps` 可列出应用且包含 `/Applications/Claude Code Haha.app`,但 `get_app_state(Finder)` 仍返回 `cgWindowNotFound``get_app_state(Claude Code Haha)` 返回 `remoteConnection`,系统 `screencapture -x /tmp/cc-haha-computer-use-check.png` 仍失败为 `could not create image from display`。当前机器继续不能完成真实 GUI 操作验收。
- 2026-06-01 package-kind 复测Computer Use `list_apps` 可列出运行中的 `/Applications/Claude Code Haha.app`,但 `get_app_state(Claude Code Haha)``get_app_state(Finder)` 均返回 `cgWindowNotFound`;系统 `screencapture -x /tmp/cc-haha-computer-use-check-2.png` 仍失败为 `could not create image from display`。当前机器继续不能完成点击、输入、系统文件选择器、托盘/通知等 GUI 验收。
- 2026-06-01 Gatekeeper 诊断后复测Computer Use `list_apps` 可列出运行中的 `/Applications/Claude Code Haha.app`,但 `get_app_state(Claude Code Haha)``get_app_state(Finder)` 均返回 `cgWindowNotFound`;系统 `screencapture -x /tmp/cc-haha-computer-use-check-3.png` 仍失败为 `could not create image from display`。当前机器仍不是可用的 Computer Use GUI 验收环境。
- 2026-06-01 release metadata 合并后复测Computer Use `list_apps` 仍可列出运行中的 `/Applications/Claude Code Haha.app`,但 `get_app_state(Claude Code Haha)``get_app_state(Finder)` 仍返回 `cgWindowNotFound`;系统 `screencapture -x /tmp/cc-haha-computer-use-check-4.png` 仍失败为 `could not create image from display`。当前机器仍不能执行真实 GUI 操作验收。
- 2026-06-01 mock update feed UI 补强后复测Computer Use `list_apps` 仍可列出运行中的 `/Applications/Claude Code Haha.app`,但 `get_app_state(Claude Code Haha)``get_app_state(Finder)` 仍返回 `cgWindowNotFound`;系统 `screencapture -x /tmp/cc-haha-computer-use-check-5.png` 仍失败为 `could not create image from display`。当前机器仍不能执行真实 GUI 操作验收。
- 2026-06-01 Keychain prompt mitigationElectron main 在 macOS 启动早期启用 Chromium `use-mock-keychain`,避免 `claude-code-desktop Safe Storage` 反复弹登录钥匙串授权;`ModelSelector` 不再挂载即请求 Claude/OpenAI 官方 OAuth status而是 runtime 下拉打开时按需请求一次。验证focused ModelSelector/keychain tests 12 passed`check:electron` 80 passed。
- 2026-06-01 Keychain prompt Computer Use 复测:当前 Electron dev 壳启动后 `get_app_state(Electron)` 成功返回 `localhost:1420/` 主界面Computer Use 截图和 AX 树没有出现 Safe Storage 钥匙串授权弹窗。
- 2026-06-01 Keychain prompt 当前态复验focused ModelSelector/keychain tests 12 passed`check:electron` 83 passedComputer Use `get_app_state(Electron)` 返回 `Claude Code Companion` 主窗口和 `localhost:1420/` renderer未出现 Safe Storage 钥匙串授权弹窗。
- 2026-06-01 附件选择 Computer Use 复测:当前 Electron dev 壳中点击 composer `添加文件或图片`macOS 原生 `打开` 面板可用;选择 `/Users/nanmi/cc-haha-cua-attachment-smoke.txt` 后回到 composer并显示 `cc-haha-cua-attachment-smoke.txt` 附件 chip未出现 Safe Storage 钥匙串弹窗。
- 2026-06-01 Python 路径选择 Computer Use 复测:当前 Electron dev 壳中点击 Computer Use 设置里的 `选择`macOS 原生 `选择 Python 解释器` 面板可用;选择 `/Users/nanmi/cc-haha-cua-python3-smoke` 后设置页保存并解析到 `/opt/homebrew/Cellar/python@3.14/3.14.5/Frameworks/Python.framework/Versions/3.14/bin/python3.14`;随后恢复自动检测,`/api/computer-use/authorized-apps` 返回 `pythonPath: null`
- 2026-06-01 外链 Computer Use 复测:当前 Electron dev 壳中点击关于页 GitHub 项目卡片后,系统浏览器 Google Chrome 被拉到前台,地址栏为 `github.com/NanmiCoder/cc-haha`Electron renderer 仍停留在 `localhost:1420/`,未在应用内导航外链。
- 2026-06-01 窗口关闭/恢复 Computer Use 复测:当前 Electron dev 壳中点击 macOS 关闭按钮后Electron 进程仍在 Computer Use `list_apps` 中保持 running 且主窗口消失;通过 macOS app activation 路径重新激活同一 Electron app 后Computer Use 再次看到 `Claude Code Companion` 主窗口和 `localhost:1420/` renderer。Computer Use 当前不能稳定枚举 Dock因此本轮验证的是与 Dock 点击等价的 app activation/show 主窗口路径。
- 2026-06-01 通知点击 smoke hook新增显式环境变量 `CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_SESSION_ID=<session-id>`,用于让 Electron main process 发送带 session target 的真实 Electron 通知focused tests 覆盖默认不发送、target payload 透传和窗口恢复链路。真实 OS 点击复测时Computer Use 对 Notification Center/SystemUIServer 均超时,且 `get_app_state(Electron)` 本身会激活 app因此不能作为点击通知证据该项仍保持未勾选。
- 2026-06-01 通知点击二次复测:用 `CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_DELAY_MS=30000` 启动 Electron dev 壳Computer Use 先确认 `localhost:1420/` 主窗口可见,再点击 macOS close buttonElectron 随后无主窗口符合隐藏到后台预期。等待通知触发后Computer Use 对 `SystemUIServer``/System/Library/CoreServices/NotificationCenter.app` 仍返回 `timeoutReached`,前台 Chrome 截图/AX 树也未出现可点击通知横幅,因此仍不能证明真实 OS 通知点击回跳。
- 2026-06-01 packaged 通知 JSONL smoke新增 `CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_LOG=<path>` 后重新打包 packaged app隔离配置启动后 Computer Use 确认 packaged `file://.../app.asar/dist/index.html` 主窗口可见JSONL 记录 `scheduled``sent:true`。Computer Use 对 `SystemUIServer` 和 Notification Center 仍 `timeoutReached`JSONL 未出现 `action`,因此仍不能勾选“点击通知后回到目标 session”。
- 2026-06-01 packaged 通知点击当前态复测canonical packaged app 使用 `CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_SESSION_ID=notification-click-smoke-session``CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_DELAY_MS=8000` 和 JSONL log 启动Computer Use 关闭主窗口后 app 留在后台JSONL 记录 `scheduled``sent:true`。Computer Use 对 `UserNotificationCenter.app` 返回安全策略拒绝,对 `NotificationCenter.app``timeoutReached`,因此真实 OS 点击仍未完成。通知 smoke 现已记录 `lifecycle: close|failed`,后续可在可操作通知横幅的 macOS/Windows runner 上区分 close、failed 和 action。
- 2026-06-01 packaged 通知点击 launchctl 复测:直接执行 app binary 时 smoke env 没有进入最终 Electron app 进程;改用 `launchctl setenv` + `open -n` 启动隔离 packaged app 后JSONL 正常记录 `scheduled``sent:true`。Computer Use 对 Notification Center 与 SystemUIServer 仍 `timeoutReached`Finder 状态读取返回 ScreenCaptureKit stream errorJSONL 未出现 `action`,所以真实点击回跳仍不能勾选。
- 2026-06-01 通知点击再次复测worktree packaged app 通过 `launchctl setenv` 启动后,通知 JSONL 正常记录 `scheduled``sent:true`Computer Use 对 worktree app 连续返回 ScreenCaptureKit stream error`list_apps` 仍能看到该 app running。复制当前 packaged app 为唯一 bundle id smoke app 并 ad-hoc 重签名后LaunchServices 能注册 `Claude Code Haha Smoke`,但 app 立即退出,系统日志显示 appDeath本轮仍没有真实 OS 点击 `action` 证据。
- 2026-06-01 renderer ack 补强后 packaged 复测:重新打包 `desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app` 并通过 package-smoke dir PASS首次以 notification smoke env 启动时 Computer Use 读取 worktree packaged app 返回 `timeoutReached`,直接执行也曾退出 137。随后用隔离 `CLAUDE_CONFIG_DIR` / `--user-data-dir` 重新直接运行同一 `.app` 后保持运行Computer Use 成功读取 `Claude Code Companion` 主窗口renderer URL 为 `file:///Users/nanmi/.codex/worktrees/2392/claude-code-haha/desktop/build-artifacts/electron/mac-arm64/Claude%20Code%20Haha.app/Contents/Resources/app.asar/dist/index.html`;点击设置入口后进入 packaged 设置页。`spctl` 仍返回 `bundle format unrecognized, invalid, or unsuitable``codesign --verify --deep --strict` 通过,因此 signed/notarized Gatekeeper 与真实 OS 通知点击仍未完成。
- 2026-06-01 packaged synthetic notification action 复测:新增 `CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_TRIGGER_ACTION=1`,仅在显式 smoke 环境中由 main process 触发同一条 notification action -> renderer navigation -> `desktop:notification:action-ack` 诊断链路。用 `launchctl setenv` + `open -n desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app --args --user-data-dir=<tmp>` 启动当前 worktree packaged app 后Computer Use 成功读取 packaged `file://.../app.asar/dist/index.html` 主窗口JSONL 记录 `scheduled``sent:true``synthetic_action``renderer_ack`。该 synthetic action 不代表真实 OS 通知点击,真实点击回跳仍未勾选。
- 2026-06-01 DiskImages 复核:`hdiutil info` 仍显示 Electron Builder 失败遗留的 `.temp...Claude-Code-Haha-0.3.2-arm64.dmg` 挂载在 `/dev/disk4`,但无 `hdiutil` / `diskutil` / `electron-builder` 残留进程;此前 `hdiutil detach``diskutil` 对该设备会阻塞,继续强制处理会污染当前验证。
- 2026-06-01 macOS build script hardening默认 `SKIP_INSTALL=1 SIGN_BUILD=0 desktop/scripts/build-macos-arm64.sh` 现在在 stale `.temp...Claude-Code-Haha-0.3.2-arm64.dmg` 挂载存在时 fail fast并提示改用 `MAC_TARGETS=zip` 验证 update zip`MAC_TARGETS=zip` 路径通过且自动 package-smoke PASS。
- 2026-06-01 macOS canonical release 复测:默认 `SKIP_INSTALL=1 SIGN_BUILD=0 desktop/scripts/build-macos-arm64.sh` 已完成 `.dmg + .zip + latest-mac.yml`package-smoke release PASS。启动 canonical `.app` 后 Computer Use 成功读取 `Claude Code Companion` 主窗口electron-updater 内置 logger 已关闭,缺失 GitHub `latest-mac.yml` 不再向启动日志输出 404 stack。
- 2026-06-01 canonical packaged system interaction 复测:启动 `desktop/build-artifacts/macos-arm64/Claude Code Haha.app` 的隔离实例后Computer Use 读取到 packaged `file://.../app.asar/dist/index.html` 主界面,项目选择器显示 `/private/tmp/cc-haha-electron-real-fixed-sRFUeO/project`;点击 `打开终端` 后终端面板运行 `/bin/zsh`,输入 `printf 'canonical-terminal-ok\n'; pwd` 后显示 `canonical-terminal-ok``/tmp/cc-haha-canonical-cua-flow.xTxSmt/claude-config`。该轮未出现 `claude-code-desktop Safe Storage` 钥匙串授权弹窗。
- 2026-06-01 canonical packaged Computer Use 设置流程复测:启动 `desktop/build-artifacts/macos-arm64/Claude Code Haha.app` 的隔离实例后,用 Computer Use 进入 `设置 > Computer Use`。首次状态请求曾 30s timeout点击 `重试` 后状态页正常;通过 `安装环境` 按钮完成 venv 创建与依赖安装。UI 显示 Python 3.14.5、虚拟环境已就绪、依赖包已安装、辅助功能权限已授权、屏幕录制权限未授权;`GET /api/computer-use/status` 返回 `venv.created=true``dependencies.installed=true``permissions.accessibility=true``permissions.screenRecording=false`。点击 `打开屏幕录制设置`Computer Use 读取到 macOS 系统设置窗口 `录屏与系统录音`,列表中包含 `Claude Code Haha` 权限项。
- 2026-06-01 canonical packaged Computer Use 授权应用复测:同一 packaged app 隔离实例中Computer Use 在 `已授权应用` 搜索框输入 `Terminal`,列表返回 `Terminal / com.apple.Terminal`;点击后 UI 显示 check 状态,隔离 `cc-haha/computer-use-config.json``GET /api/computer-use/authorized-apps` 均返回 `authorizedApps[0].bundleId=com.apple.Terminal`grant flags 为 `clipboardRead=true``clipboardWrite=true``systemKeyCombos=true`。该项覆盖真实 UI 输入、点击、滚动、应用枚举和授权配置持久化。
- 2026-06-01 packaged menu/window lifecycle 复测:在隔离 `desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app`Computer Use 点击 macOS app menu `Settings...` 后打开设置页;点击窗口关闭按钮后主窗口消失且同一 PID 继续运行System Events 显示 `count=0`;随后 app activation 恢复窗口Computer Use 再次读取到 packaged `file://.../app.asar/dist/index.html` 设置页。继续通过 app menu `Quit` 退出后,隔离配置写入 `window-state.json`;用同一 `CLAUDE_CONFIG_DIR``--user-data-dir` 重启Computer Use 成功读取新 PID 的 packaged 主窗口System Events 显示 `count=1 names=Claude Code Companion`。该项覆盖菜单打开设置、关闭隐藏、恢复窗口和重启后窗口仍可见;真实 tray 图标点击仍未单独完成。
- 2026-06-01 Gatekeeper 诊断补强后 packaged launch 复测:用隔离 `CLAUDE_CONFIG_DIR``--user-data-dir` 启动 `desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app`Computer Use 成功读取 `Claude Code Companion` 主窗口和 packaged `file://.../app.asar/dist/index.html` renderer未出现 Safe Storage 钥匙串弹窗。
- 2026-06-01 release provider smoke 后 packaged launch 复测:真实 provider smoke 通过后,再次用隔离 `CLAUDE_CONFIG_DIR``--user-data-dir` 启动 `desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app`Computer Use 成功读取 packaged `file://.../app.asar/dist/index.html` 主窗口。
- 2026-06-01 policy gate 后 packaged launch 复测:`check:policy` 通过后,再次用隔离 `CLAUDE_CONFIG_DIR``--user-data-dir` 启动 packaged appComputer Use 首次读取遇到 ScreenCaptureKit stream errorSystem Events 同时显示同一 PID 有 `Claude Code Companion` 窗口,重试后 Computer Use 成功读取 packaged renderer。
- 2026-06-01 本地 `main` 同步后 packaged launch 复测:重新打包 `desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app`,使用隔离 `CLAUDE_CONFIG_DIR=/tmp/cc-haha-main-sync-cua-1780317323/config` 和隔离 `--user-data-dir` 启动Computer Use 成功读取 `Claude Code Companion` 主窗口和当前 packaged renderer未出现 Safe Storage 钥匙串弹窗。
- [x] 启动真实 packaged app`desktop/build-artifacts/electron-smoke/mac-arm64/Claude Code Haha Smoke.app`。该 smoke bundle 使用同一构建产物重新打包,仅更换临时 appId/productName 以避开本机已运行的正式 app 单实例锁。
- [x] 本地 `main` 同步后启动真实 packaged app`desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app`,使用隔离 `--user-data-dir=/tmp/cc-haha-electron-real-fixed-sRFUeO/user-data` 和隔离 `CLAUDE_CONFIG_DIR`
- [x] 确认主界面从 packaged renderer 加载local server sidecar 自动启动,无需手动 `SERVER_PORT`
- [x] 打开终端,执行 `printf electron-terminal-ok`,确认输出可见。
- [x] 关闭终端后通过进程列表确认没有残留 `/tmp/cc-haha-electron-smoke-config` PTY shell。
- [x] 选择工作目录,确认系统目录对话框可打开。
- [x] 复制本机 cc-haha provider/model 配置到隔离临时配置目录,真实模型选择器显示 `gpt-5.5 Sub2API-ChatGPT`
- [x] 真实模型 chat smoke会话 `e0d7abc2-27db-4ff1-9954-7923f6c3385e` 通过 WebSocket 启动 CLI subprocess读取 `package.json``src/greeting.ts`,经 UI 权限审批执行 `bun test`JSONL 记录 `1 pass / 0 fail`Computer Use 看到最终回复“测试通过。”。
- [x] 选择附件文件,确认文件可加入 composer。
- [x] 打开 Python 路径选择,确认系统文件选择器可用。
- [x] 点击外链或 OAuth 帮助链接,确认走系统浏览器。
- [x] 关闭主窗口,确认 Dock/app activation 可恢复窗口;真实 tray 图标点击仍需可枚举 tray 环境复验。
- [ ] 触发通知,点击通知后回到目标 session。
- [x] 触发通知发送 smokepackaged app 通过 `CC_HAHA_ELECTRON_NOTIFICATION_SMOKE_LOG` 记录 `scheduled``sent:true`;真实 OS 点击仍因 Computer Use 无法操作 Notification Center/SystemUIServer 而未完成。
- [x] 打开 preview/workbench browser panel导航 `https://example.com/`,确认 WebContentsView 加载成功。
- [x] 点击 preview 截图,确认 `screenshot-full.png` 回填到 composer。
- [x] packaged Computer Use 设置流程:隔离配置下完成环境安装,确认 venv/依赖状态、辅助功能/屏幕录制权限状态,并从应用打开 macOS `录屏与系统录音` 设置页。
- [x] packaged Computer Use 授权应用流程:搜索并授权 `Terminal / com.apple.Terminal`,确认剪贴板和系统快捷键 grant flags 持久化。
- [x] unpacked dir package 缺少 `app-update.yml` 时 update check 视为无更新,不阻塞 UI非 metadata updater 错误仍会抛出。
- [x] 更新代理 contractElectron updater 会接收 renderer 传入的 manual proxy并在切回 system proxy 时清理手动代理IPC validator 只允许 `{ proxy: string }` 形状,拒绝空 proxy 或额外字段。
- [x] 关闭 electron-updater 内置 logger避免缺失远端 `latest-mac.yml` 时把 404 stack 打到 packaged app 启动日志;业务层仍把 metadata 缺失分类为“无更新”。
- [x] 发布型包 updater metadata如果 artifact set 中存在 release archive/update metadata`package-smoke` 会强制检查安装后 resources/app-update.yml防止“有 latest*.yml 但安装后永远无法检查更新”的包进入 releasemacOS zip-only canonical artifact set 已通过该检查。
- [x] packaged app updater 缺失 channel metadata smoke重新打包 `desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app` 后,用隔离配置目录直接运行 app executableComputer Use 确认 packaged renderer 从 `file://.../app.asar/dist/index.html` 加载local server sidecar 自动启动,未出现 Safe Storage 钥匙串弹窗,日志未再出现 `ERR_UPDATER_CHANNEL_FILE_NOT_FOUND` IPC handler 崩错。纯 `--dir` 包缺少 `app-update.yml` 的提示仍按无更新处理。
- [x] 触发 mock feed确认 check/download/install/relaunch 状态流不阻塞 UI`UpdateChecker` 集成测试通过 Electron `desktopHost` mock update feed 驱动真实 `updateStore`,覆盖下载完成弹窗、点击 install、prepare/install/relaunch 调用和 prompt 退出。signed/release update feed 仍需在真实 signed/notarized artifact 上复验。
- [x] packaged main/preload update smoke`CC_HAHA_ELECTRON_UPDATE_SMOKE_VERSION=9.9.9-smoke` 启动唯一 bundle id 的 packaged dir apppackaged renderer 通过 preload 调用 `desktopHost.updates.check/download/prepareInstall/install/relaunch`JSONL 记录 `check``download-start``download-finish``quit-and-install`。Computer Use `list_apps` 可见该 smoke app`get_app_state` 超时,真实桌面点击安装仍按未完成处理。
- [x] packaged window smoke 诊断:`CC_HAHA_ELECTRON_WINDOW_SMOKE_LOG` 记录 packaged app 在 `after-initial-show``after-final-show` 均为 `visible:true`bounds 为 `1280x820`renderer URL 为 packaged `file://.../app.asar/dist/index.html`;早前 System Events 曾返回 `windows count=0` 且 Computer Use `get_app_state` 超时。随后用完整 `.app` 路径复测Computer Use 成功读取 `Claude Code Companion` 主窗口和 packaged rendererSystem Events 返回 `front=true count=1 names=Claude Code Companion`。因此之前卡点是 macOS AX/窗口捕获状态波动,不是 renderer、server sidecar 或 update preload smoke 失败。
## Windows 待实机
- [ ] 构建 NSIS 安装器并安装。
- [x] Windows build script 已补 canonical package-smoke`desktop/scripts/build-windows-x64.ps1` 会复制 installer/update metadata/blockmap/`win-unpacked``desktop/build-artifacts/windows-x64`,并默认运行 `bun run test:package-smoke --platform windows --package-kind release --artifacts-dir desktop/build-artifacts/windows-x64`
- [ ] 在 Windows runner/实机运行 `bun run test:package-smoke --platform windows` 或 build script 内置 canonical package-smoke。
- [ ] 启动安装后的 app验证 sidecar 自动启动。
- [ ] 验证 sidecar 文件锁、更新前 stop process、通知、托盘、窗口隐藏/恢复、系统对话框。
- [ ] 完成一次 Computer Use 设置和操作 smoke。
## Linux 待实机
- [ ] 构建 AppImage/deb。
- [x] Linux build script 已补 canonical package-smoke`desktop/scripts/build-linux.sh` 支持 `LINUX_ARCH=x64|arm64`,会复制 AppImage/deb/update metadata/blockmap/`linux-unpacked``desktop/build-artifacts/linux-<arch>`,并默认运行 `bun run test:package-smoke --platform linux --package-kind release --artifacts-dir desktop/build-artifacts/linux-<arch>`
- [x] Linux arm64 update metadata preflight 已补:`desktop/scripts/build-linux.sh` 复制 `latest-linux*.yml``package-smoke` 识别 `latest-linux.yml``latest-linux-arm64.yml` 并校验 metadata 引用的 AppImage/deb artifact回归测试覆盖 canonical `linux-arm64` 输出。
- [ ] 在 Linux runner/实机运行 `bun run test:package-smoke --platform linux` 或 build script 内置 canonical package-smoke。
- [ ] 启动 AppImage/deb 安装后的 app验证 sidecar 自动启动。
- [ ] 验证 tray、通知、系统对话框、外链、更新策略如平台能力降级写入 release note。
## 完成判定
- [ ] macOS packaged app 完成 Computer Use smoke。历史上已完成启动、server、终端、目录选择、preview、真实模型 chat 与 unpacked updater no-opdev 壳另已补附件选择、Python 路径选择、外链打开和窗口关闭后 app activation 恢复证据。最终完成仍需要可启动的 signed/notarized artifact、可截图/可点击桌面会话、通知点击回跳和完整 update feed 复验。
- [ ] Windows packaged app 完成实机 smoke或明确记录 release blocker。
- [ ] Linux packaged app 完成实机 smoke或明确记录 release blocker。
- [x] `verify` 通过,并记录 quality report 与 coverage report 路径。最新 quality report`artifacts/quality-runs/2026-05-31T21-42-57-279Z/report.md`coverage report`artifacts/coverage/2026-05-31T21-46-15-873Z/coverage-report.md`
- [x] live release gate 通过,或明确记录 provider/live access blocker。最新 `release --allow-live` 已通过:`artifacts/quality-runs/2026-05-31T20-29-45-758Z/report.md``passed=15 failed=0 skipped=0`