现象(两层)
1. 隐性漂移 :hub 进程可以长期不在 launchd 管理下运行而用户无感知。我的实例从 6/3(#41 那次 bootout 修复后)一直由 hub-client/hub-channel.ts 的 auto-spawn 保活(hub-channel.ts ~L320 "Hub 未运行,尝试自动启动"),运行了 10 天。期间 launchctl print gui/$UID/com.forge-hub 返回 "Could not find service",但 hub 功能正常——所以没人发现。
2. env 不继承 :hub-channel spawn hub 时(spawn(BUN_BINARY, [hubPath], {detached, stdio: "ignore"}))不带 env 注入,spawn 出的 hub 只继承 hub-channel 自己的环境。结果是 plist EnvironmentVariables 里配的 FORGE_HUB_TTS_HOOK / FORGE_FFMPEG_PATH 等全部失效,hub_send_voice 持续 501/合成失败,但 forge-hub doctor 全绿(它检查 plist 文件存在,不检查 serving 进程是否 launchd 管理、env 是否生效)。
复现步骤
正常 launchd 部署 + CC session 运行中(hub-channel 已连接)
launchctl bootout gui/$(id -u)/com.forge-hub(模拟 install during active CC session triggers launchctl spawn-fail loop #41 的修复操作)
kill <hub PID> → ~12 秒内 hub-channel 检测断连并 respawn 一个 hub(孤儿,PPID=hub-channel)
此后任何 launchctl bootstrap 尝试都因 9900 被占而 fatal crash loop(KeepAlive 每 30s 重试一次、每次失败)——hub-channel 的事件驱动 respawn(秒级)永远快过 launchd 的 ThrottleInterval(30s),race 无法靠时序赢
在 plist 加任何新 env → 永远无法生效(serving 进程始终是 hub-channel 的无 env 后代)
日志片段
# hub-stderr.log —— launchd 实例的 crash loop
[2026-06-13 01:04:27] [hub] Forge Hub v0.2.0 · PID 23566 · 上次 PID 23552
[2026-06-13 01:04:27] [hub] ERROR: Fatal: Error: Failed to start server. Is port 9900 in use?
[2026-06-13 01:04:27] [hub] ERROR: 另一个 Hub 实例可能正在运行。launchd 不会自动重试。
(每 30s 重复,PID 23566 → 23699 → ...)
# hub.log —— serving 实例(hub-channel spawn 的)无 env
[2026-06-13 01:14:22] [hub] ERROR: TTS 未配置:设置 FORGE_HUB_TTS_HOOK env var 指向你的 TTS 脚本
(plist EnvironmentVariables 已含 FORGE_HUB_TTS_HOOK,launchctl setenv 也已设,均无效)
doctor 输出
✅ All checks passed(v0.2.0 · Bun installed / LaunchAgent plist ✓ / MCP ✓)——全绿恰好是问题的一部分:检查不到管理权漂移。
环境
macOS 14.6.1 (Apple Silicon) / Bun 1.3.13 / forge-hub v0.2.0
关联
与 #41 相关:#41 是 install 触发 spawn 风暴,本条是其修复操作(bootout)之后的长尾后果。修复方案留给维护者定夺。
现象(两层)
1. 隐性漂移:hub 进程可以长期不在 launchd 管理下运行而用户无感知。我的实例从 6/3(#41 那次 bootout 修复后)一直由
hub-client/hub-channel.ts的 auto-spawn 保活(hub-channel.ts~L320 "Hub 未运行,尝试自动启动"),运行了 10 天。期间launchctl print gui/$UID/com.forge-hub返回 "Could not find service",但 hub 功能正常——所以没人发现。2. env 不继承:hub-channel spawn hub 时(
spawn(BUN_BINARY, [hubPath], {detached, stdio: "ignore"}))不带 env 注入,spawn 出的 hub 只继承 hub-channel 自己的环境。结果是 plistEnvironmentVariables里配的FORGE_HUB_TTS_HOOK/FORGE_FFMPEG_PATH等全部失效,hub_send_voice持续 501/合成失败,但forge-hub doctor全绿(它检查 plist 文件存在,不检查 serving 进程是否 launchd 管理、env 是否生效)。复现步骤
launchctl bootout gui/$(id -u)/com.forge-hub(模拟 install during active CC session triggers launchctl spawn-fail loop #41 的修复操作)kill <hub PID>→ ~12 秒内 hub-channel 检测断连并 respawn 一个 hub(孤儿,PPID=hub-channel)launchctl bootstrap尝试都因 9900 被占而 fatal crash loop(KeepAlive 每 30s 重试一次、每次失败)——hub-channel 的事件驱动 respawn(秒级)永远快过 launchd 的 ThrottleInterval(30s),race 无法靠时序赢日志片段
doctor 输出
✅ All checks passed(v0.2.0 · Bun installed / LaunchAgent plist ✓ / MCP ✓)——全绿恰好是问题的一部分:检查不到管理权漂移。
环境
macOS 14.6.1 (Apple Silicon) / Bun 1.3.13 / forge-hub v0.2.0
关联
与 #41 相关:#41 是 install 触发 spawn 风暴,本条是其修复操作(bootout)之后的长尾后果。修复方案留给维护者定夺。