guanghu-ice-heart/development/GHB-DEV-CHAIN-20260812-002.md

8.2 KiB
Executable file
Raw Blame History

光湖桥聊天工具 · 双壳集成开发链 · DEV-20260812-002

  • 登记号GHB-DEV-CHAIN-20260812-002
  • 日期2026-08-12
  • 执行人:铸渊 ICE-P-ZY001QoderCN 实例)
  • 指令源:冰朔——"光湖桥,就是给人类在光湖世界里做一个聊天工具。你就在我本地开发,开发好了装到这两个框架里都试试,看看是否真的成功运行了这个通讯工具。"
  • 上游基线GHB-DEV-20260812-001光湖桥 v1 独立参考实现bridge-node.mjsselftest 五项 PASS
  • 状态:Electron 壳全链路 PASS含打包 .appTauri 壳部分 PASS接入通、UI 发送被 ACL 拦,未闭合)

一、任务目标

把光湖桥从"协议参考实现"变成"人类可用的聊天工具",并分别装进两个桌面框架实测:

  1. Electron0.8.0 HoloLake Era 同族路线)
  2. Tauri0.4.6 源码线同族路线,冰朔偏好的轻量壳)

验收标准:两个壳各自能连上会合点、互发消息、收到送达回执,真实运行而非纸面设计。

二、架构决策链(为什么这样做)

目标:一套聊天前端,两个壳都能装
  └─ 决策1桥运行时统一走 stdio JSON 子进程模式
       原因Electron 主进程虽自带 Node但 Tauri 后端是 Rust 无 Node 运行时;
             取交集 = 两边都能 spawn 子进程 + 读写 stdio。
             给 bridge-node.mjs 增加 --stdio 模式NDJSON 命令进/事件出,日志走 stderr
             两壳集成方式完全同构,协议面只有一份。
  └─ 决策2聊天前端零构建纯 HTML/CSS/JS不用 Vite/Webpack
       原因:构建链越短,双壳复用越干净,也符合光湖"可手工审计"原则。
  └─ 决策3adapter.js 适配层统一事件面
       前端只认 window.GHB = { send(to,text), on(event,cb) }
       Electron 走 preload contextBridgeghbElectron
       Tauri 走 withGlobalTauri 的 __TAURI__.event/core
       裸浏览器降级为 mock 提示。壳的差异被隔离在 adapter 一层。
  └─ 决策4开发与构建全部落本地盘 /tmp成品归档 JZAO
       原因既有教训——ExFATJZAO上构建会因 AppleDouble 崩签名;
             且沙箱对工作区外 shell 写入有限制。
  └─ 决策5无人值守自检钩子
       GHB_AUTOSEND="对端|文本|延迟秒"(走 UI 发送路径,气泡真实渲染)
       + GHB_SHOT=路径(延迟截屏取证),让"是否真的运行"有图有日志。

三、实测结果

Electron 壳 PASS

  • 开发模式双实例ELECTRON-A ↔ ELECTRON-B双向消息送达、回执签名验证通过、UI 气泡完整渲染(截图取证 shot-a/shot-b
  • 打包 .appGuanghuBridgeChat.app手工组装 + ad-hoc 签名双实例复测PKG-A ↔ PKG-B 双向送达、验签通过(截图 shot-pkg-a/b
  • 证据relay 日志四条在线直投;signature_verified: true;截屏显示绿连接点、节点号、双向气泡、"✓ 已送达·已验签"。

Tauri 壳 ⚠️ 部分 PASS未闭合

  • cargo 编译通过Tauri v2 + Rust 1.96)。
  • 双实例接入会合点成功relay 日志TAURI-A / TAURI-B 接入)。
  • 未闭合点:后端 emit 的事件能到前端,但前端 invoke('bridge_send') 没有触发发送——应用命令的 ACL 权限未被 tauri-build 收录进 acl-manifests.jsonmanifest 只有 core 系列,allow-bridge-send 不存在,引用即编译报错)。见未决问题 U1。
  • 未打包 .appbundle.active=false验证未通过前不做

四、踩坑因果链(现象 → 原因 → 处置)

  1. parseArgs 吞开关--stdio 无值开关被旧配对逻辑吃掉后续 --id → 改为逐个扫描,值以 -- 开头则视为布尔开关。
  2. stdio 模式 stdin EOF 即退出:后台测试时 stdin=/dev/null节点刚连上就退出relay 侧表现为"刚接入就离线" → 结论stdio 子进程要求宿主保持 stdin 管道打开Electron/Tauri spawn 默认满足);测试用 (sleep N) | node ... 保持。
  3. connected 事件早于渲染进程就绪:截屏显示"接入中…红点"但回执事件已到 → 原因:子进程启动快于 webContents 加载,早到事件被丢 → 处置main 进程加事件缓冲队列did-finish-load 后补发。
  4. Electron 沙箱内 SIGSEGV:同代码上轮能跑本轮段错误,伴随 nice(5) failed → 沙箱策略变化所致 → --no-sandbox --disable-gpu 规避。
  5. npm 缓存权限:沙箱禁写 ~/.npm--cache /tmp/npm-cache
  6. Electron 二进制下载失败postinstall 从 GitHub 拉二进制被断 → 换 npmmirrorELECTRON_MIRROR+ ELECTRON_CACHE=/tmp/electron-cache
  7. electron-builder 打包在沙箱下解包丢二进制dist 里 Contents/MacOS 为空rename ENOENT → 放弃 builder手工组装 .app:拷官方 Electron.app → asar pack --unpack-dir bridge → 改 Info.plistCFBundleExecutable/Name/Identifier→ 改名主二进制 → codesign --force --deep -s -。此路线完全可控且可复现。
  8. 外部 node 读不了 asar 内文件:打包后 spawn 的系统 node 报 MODULE_NOT_FOUND → asar 透明读取只在 Electron 进程内生效 → bridge 脚本 unpack 到 app.asar.unpacked/main.cjs 加路径探测(打包态优先 unpacked开发态回退本地目录
  9. cargo 写 ~/.cargo 被沙箱拦CARGO_HOME=/tmp/cargo-home
  10. Tauri generate_context 要求 icons/icon.png → python 纯手写 PNG光湖青圆形128px
  11. Rust E0597Exit 事件里 if let Ok(guard) = state.0.lock() 的临时 MutexGuard 析构顺序晚于 state 绑定 → 块尾加分号提前落临时对象。
  12. zsh 杂项rm -rf x/*.png 无匹配报错、echo ==== 被解析、后台进程 nice 警告——全部改用落文件再查看的方式规避。

五、未决问题清单

  • U1Tauri ACL最高优先:应用命令 bridge_send 的 allow 权限未进 acl-manifests.json。疑点tauri-build 收集应用命令权限的机制与本工程 [lib] 双 crate 结构main.rs 调 app_lib::run的交互下次优先试 a) 把 run() 逻辑并回 main.rs 单 crate 重建看 manifest 是否收录b) 查 tauri 官方脚手架的 capabilities 生成差异。
  • U2Tauri 壳 UI 渲染取证缺(无截屏钩子),可在 lib.rs 加 webview.screenshot 或走系统 screencapture。
  • U3GHB_AUTOSEND / GHB_SHOT 是开发自检钩子,正式交付前决定保留(运维有用)或摘除。
  • U4:桥协议层未竟项(承 DEV-001TLS、多会合点、BS-TCS 准入门禁对接、群聊/人格体协作信封。
  • U5:待冰朔裁定——聊天工具源码是否推 REPO-014 走正典登记;真实跨机会合点落哪台节点。
  • U6:本仓库工作区存在 1027 个 0-insertion/0-deletion 的 ExFAT 元数据"假改动"stat 差异),未处理,不属本次交付范围,仅报告。

六、资产清单与复现

  • 源码归档:/Volumes/JZAO/HoloLake/development/guanghu-bridge-DEV-20260812-001/
    • bridge-node.mjs(新增 --stdio 模式与事件缓冲无关,纯运行时)
    • chat/chat.html/css/js + adapter.js 四件共用前端)
    • chat/electron/main.cjs + preload.cjs + package.json
    • chat/tauri/Cargo.toml + build.rs + tauri.conf.json + src/ + capabilities/
  • 构建配方(本地盘):
    • Electronnpm i electron --cache /tmp/npm-cacheELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/;打包走手工组装七步(见踩坑 7
    • TauriCARGO_HOME=/tmp/cargo-home cargo build
  • 运行:先起 node bridge-node.mjs relay --port <P>,壳通过环境变量 GHB_NODE_ID / GHB_RELAY 接入。
  • 实测证据件:截图 shot-a/bElectron 开发态、shot-pkg-a/b.app 打包态)存 /Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/图片/shot-a/b与本次会话日志。

七、状态推进

  • 光湖桥人类产品形态DESIGN_PROVEN → ELECTRON_SHELL_PROVEN_LOCAL / TAURI_SHELL_PARTIALACL 未闭合)
  • 认知基线 025 的 realtime_transport_state 维持 REFERENCE_IMPLEMENTATION_PROVEN_LOCAL,待 Tauri 闭合后可加注双壳验证。