From d1fde9ddd3b2194f3b51651e7bc787b822d82ec6 Mon Sep 17 00:00:00 2001 From: "SYM.BOT" Date: Thu, 30 Apr 2026 05:50:35 +0100 Subject: [PATCH] 0.5.6: align _createPeer stale threshold with inbound handler (1s) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v0.5.5 lowered the stale-prior threshold to 1s in the inbound-connection handler but left the _createPeer path on the old _heartbeatInterval (10s). When both sides dialled each other in rapid succession, the two paths could pick opposite winners — Mac-side and Node-side kept different connections, each killing the other's choice. Field testing showed a continuous ~6s join → disconnect cycle persisting after v0.5.5. Aligned both stale-detection sites on 1s. --- CHANGELOG.md | 15 +++++++++++++++ lib/node.js | 9 ++++++++- package.json | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa5723a..0481948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ > **Note:** Versions 0.3.26 – 0.3.55 were released as git tags without changelog entries. Changelog resumes at 0.3.56 below. +## 0.5.6 + +### Fixed + +- **Apply 1s stale-prior threshold to `_createPeer` path.** v0.5.5 + lowered the threshold to 1s in the inbound-connection handler but + left the `_createPeer` path on the old `_heartbeatInterval` (10s). + When both sides of a peer pair dialled each other in rapid + succession, the inbound handler accepted with the 1s rule but the + merged `_createPeer` re-evaluated with 10s and could pick the + opposite winner. Mac-side and Node-side then kept different + connections, each killing the other's choice — visible in field + testing as a continuous ~6s join → disconnect cycle even after + v0.5.5. Aligned both sites on 1s. + ## 0.5.5 ### Fixed diff --git a/lib/node.js b/lib/node.js index 997b22f..2c54926 100644 --- a/lib/node.js +++ b/lib/node.js @@ -1208,8 +1208,15 @@ class SymNode extends EventEmitter { // nodeId acts as client and keeps outbound; higher keeps inbound const existingTransport = existingPeer.transports.get(source); const staleByFlag = !existingTransport || existingTransport._closed; + // Match the inbound-connection handler (v0.5.5): a 1s threshold catches + // peer process restarts (kill + quick re-dial) without rejecting + // genuine dual-dial collisions, which fire <100ms apart. The previous + // _heartbeatInterval (10s) caused dedup-decisions to diverge across + // SDKs — Node-side rejected as stale while sym-swift kept the prior, + // so the surviving connection on one side was already dead on the + // other and the peer flapped continuously. const staleByLastSeen = existingPeer.lastSeen - && (Date.now() - existingPeer.lastSeen) > this._heartbeatInterval; + && (Date.now() - existingPeer.lastSeen) > 1000; const stalePrior = staleByFlag || staleByLastSeen; if (existingTransport && !stalePrior) { const prevIsOutbound = !!existingPeer.isOutbound; diff --git a/package.json b/package.json index 038b09f..a31d0da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sym-bot/sym", - "version": "0.5.5", + "version": "0.5.6", "description": "Infrastructure and protocol for multi-agent collective intelligence", "main": "lib/node.js", "bin": {