thinkpool-pair 0.7.116 → 0.7.117

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bridge.mjs +17 -1
  2. package/package.json +1 -1
package/bridge.mjs CHANGED
@@ -2409,7 +2409,19 @@ flowChannel
2409
2409
  cleanupFlowLanes(payload.flowId, 600)
2410
2410
  process.stderr.write(`\n ${A.yel}◆ flow cancelled — closing its lanes (${String(payload.flowId).replace(/-/g, '').slice(0, 8)}).${A.rst}\n`)
2411
2411
  })
2412
- .subscribe()
2412
+ .subscribe(status => {
2413
+ // BRG-2 (audit 2026-07-02): tpflow had a bare subscribe with no status handler, so a
2414
+ // channel-specific CHANNEL_ERROR (socket still healthy → the main tpcode watchdog
2415
+ // never trips) dropped flow dispatch/plan/done silently until the next bridge
2416
+ // restart. Surface it. supabase-js auto-rejoins every channel on a socket reconnect,
2417
+ // so a transient drop self-heals; an active per-channel re-subscribe is deliberately
2418
+ // NOT added here — re-subscribing a live supabase channel is a known lifecycle
2419
+ // footgun (the 2026-06-30 channel-collision family) and can't be two-device verified
2420
+ // from a single host.
2421
+ if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT' || status === 'CLOSED') {
2422
+ process.stderr.write(`\n ⚠ flow realtime ${status} (tpflow:${room}).\n`)
2423
+ }
2424
+ })
2413
2425
 
2414
2426
  // Watchdog — if the realtime channel is stuck (never connected, or dropped and
2415
2427
  // not recovered) for >60s, exit non-zero so a supervisor/launchd restarts a
@@ -2565,6 +2577,10 @@ async function shutdown(code = 0, farewell = true) {
2565
2577
  // socket is alive; on a wedge it won't flush and the hard backstop above wins).
2566
2578
  try { await channel.untrack() } catch { /* noop */ }
2567
2579
  try { await supabase.removeChannel(channel) } catch { /* noop */ }
2580
+ // BRG-2 (audit 2026-07-02): shutdown removed only the room channel, leaking the flow
2581
+ // topic (no presence to untrack, but the subscription + socket join outlived the
2582
+ // process teardown). Close it too so shutdown is symmetric.
2583
+ try { await supabase.removeChannel(flowChannel) } catch { /* noop */ }
2568
2584
  setTimeout(() => process.exit(code), 250) // grace for the leave/close frames to flush
2569
2585
  }
2570
2586
  process.on('SIGINT', () => shutdown(0))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.116",
3
+ "version": "0.7.117",
4
4
  "description": "Share a local coding-agent CLI (Claude Code, Codex, Gemini, Aider, …) into a ThinkPool Code room, live.",
5
5
  "type": "module",
6
6
  "bin": {