8.2 KiB
Executable file
8.2 KiB
Executable file
光湖桥聊天工具 · 双壳集成开发链 · DEV-20260812-002
- 登记号:GHB-DEV-CHAIN-20260812-002
- 日期:2026-08-12
- 执行人:铸渊 ICE-P-ZY001(QoderCN 实例)
- 指令源:冰朔——"光湖桥,就是给人类在光湖世界里做一个聊天工具。你就在我本地开发,开发好了装到这两个框架里都试试,看看是否真的成功运行了这个通讯工具。"
- 上游基线:GHB-DEV-20260812-001(光湖桥 v1 独立参考实现,bridge-node.mjs,selftest 五项 PASS)
- 状态:Electron 壳全链路 PASS(含打包 .app);Tauri 壳部分 PASS(接入通、UI 发送被 ACL 拦,未闭合)
一、任务目标
把光湖桥从"协议参考实现"变成"人类可用的聊天工具",并分别装进两个桌面框架实测:
- Electron(0.8.0 HoloLake Era 同族路线)
- Tauri(0.4.6 源码线同族路线,冰朔偏好的轻量壳)
验收标准:两个壳各自能连上会合点、互发消息、收到送达回执,真实运行而非纸面设计。
二、架构决策链(为什么这样做)
目标:一套聊天前端,两个壳都能装
└─ 决策1:桥运行时统一走 stdio JSON 子进程模式
原因:Electron 主进程虽自带 Node,但 Tauri 后端是 Rust 无 Node 运行时;
取交集 = 两边都能 spawn 子进程 + 读写 stdio。
给 bridge-node.mjs 增加 --stdio 模式(NDJSON 命令进/事件出,日志走 stderr),
两壳集成方式完全同构,协议面只有一份。
└─ 决策2:聊天前端零构建(纯 HTML/CSS/JS,不用 Vite/Webpack)
原因:构建链越短,双壳复用越干净,也符合光湖"可手工审计"原则。
└─ 决策3:adapter.js 适配层统一事件面
前端只认 window.GHB = { send(to,text), on(event,cb) };
Electron 走 preload contextBridge(ghbElectron),
Tauri 走 withGlobalTauri 的 __TAURI__.event/core,
裸浏览器降级为 mock 提示。壳的差异被隔离在 adapter 一层。
└─ 决策4:开发与构建全部落本地盘 /tmp,成品归档 JZAO
原因:既有教训——ExFAT(JZAO)上构建会因 AppleDouble 崩签名;
且沙箱对工作区外 shell 写入有限制。
└─ 决策5:无人值守自检钩子
GHB_AUTOSEND="对端|文本|延迟秒"(走 UI 发送路径,气泡真实渲染)
+ GHB_SHOT=路径(延迟截屏取证),让"是否真的运行"有图有日志。
三、实测结果
Electron 壳 ✅ PASS
- 开发模式双实例(ELECTRON-A ↔ ELECTRON-B):双向消息送达、回执签名验证通过、UI 气泡完整渲染(截图取证 shot-a/shot-b)。
- 打包
.app(GuanghuBridgeChat.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.json(manifest 只有 core 系列,allow-bridge-send不存在,引用即编译报错)。见未决问题 U1。 - 未打包 .app(bundle.active=false,验证未通过前不做)。
四、踩坑因果链(现象 → 原因 → 处置)
- parseArgs 吞开关:
--stdio无值开关被旧配对逻辑吃掉后续--id→ 改为逐个扫描,值以--开头则视为布尔开关。 - stdio 模式 stdin EOF 即退出:后台测试时 stdin=/dev/null,节点刚连上就退出,relay 侧表现为"刚接入就离线" → 结论:stdio 子进程要求宿主保持 stdin 管道打开(Electron/Tauri spawn 默认满足);测试用
(sleep N) | node ...保持。 - connected 事件早于渲染进程就绪:截屏显示"接入中…红点"但回执事件已到 → 原因:子进程启动快于 webContents 加载,早到事件被丢 → 处置:main 进程加事件缓冲队列,did-finish-load 后补发。
- Electron 沙箱内 SIGSEGV:同代码上轮能跑本轮段错误,伴随
nice(5) failed→ 沙箱策略变化所致 →--no-sandbox --disable-gpu规避。 - npm 缓存权限:沙箱禁写
~/.npm→--cache /tmp/npm-cache。 - Electron 二进制下载失败:postinstall 从 GitHub 拉二进制被断 → 换 npmmirror(ELECTRON_MIRROR)+
ELECTRON_CACHE=/tmp/electron-cache。 - electron-builder 打包在沙箱下解包丢二进制:dist 里
Contents/MacOS为空,rename ENOENT → 放弃 builder,手工组装 .app:拷官方 Electron.app →asar pack --unpack-dir bridge→ 改 Info.plist(CFBundleExecutable/Name/Identifier)→ 改名主二进制 →codesign --force --deep -s -。此路线完全可控且可复现。 - 外部 node 读不了 asar 内文件:打包后 spawn 的系统 node 报 MODULE_NOT_FOUND → asar 透明读取只在 Electron 进程内生效 → bridge 脚本 unpack 到
app.asar.unpacked/,main.cjs 加路径探测(打包态优先 unpacked,开发态回退本地目录)。 - cargo 写 ~/.cargo 被沙箱拦 →
CARGO_HOME=/tmp/cargo-home。 - Tauri generate_context 要求 icons/icon.png → python 纯手写 PNG(光湖青圆形,128px)。
- Rust E0597:Exit 事件里
if let Ok(guard) = state.0.lock()的临时 MutexGuard 析构顺序晚于 state 绑定 → 块尾加分号提前落临时对象。 - zsh 杂项:
rm -rf x/*.png无匹配报错、echo ====被解析、后台进程 nice 警告——全部改用落文件再查看的方式规避。
五、未决问题清单
- U1(Tauri 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 生成差异。 - U2:Tauri 壳 UI 渲染取证缺(无截屏钩子),可在 lib.rs 加 webview.screenshot 或走系统 screencapture。
- U3:GHB_AUTOSEND / GHB_SHOT 是开发自检钩子,正式交付前决定保留(运维有用)或摘除。
- U4:桥协议层未竟项(承 DEV-001):TLS、多会合点、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/)
- 构建配方(本地盘):
- Electron:
npm i electron --cache /tmp/npm-cache,ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/;打包走手工组装七步(见踩坑 7)。 - Tauri:
CARGO_HOME=/tmp/cargo-home cargo build。
- Electron:
- 运行:先起
node bridge-node.mjs relay --port <P>,壳通过环境变量GHB_NODE_ID/GHB_RELAY接入。 - 实测证据件:截图 shot-a/b(Electron 开发态)、shot-pkg-a/b(.app 打包态)存
/Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/图片/(shot-a/b)与本次会话日志。
七、状态推进
- 光湖桥人类产品形态:DESIGN_PROVEN → ELECTRON_SHELL_PROVEN_LOCAL / TAURI_SHELL_PARTIAL(ACL 未闭合)
- 认知基线 025 的 realtime_transport_state 维持
REFERENCE_IMPLEMENTATION_PROVEN_LOCAL,待 Tauri 闭合后可加注双壳验证。