← back to Ticket System
chore: harden DM thread-walk against cyclic re-chains (cycle guard in threadRootMid + server rootOf); session-close review pass
fda28cb2ca139275c13e60d15d809c25c031c6ce · 2026-07-26 20:53:02 -0700 · Steve Abrams
Files touched
Diff
commit fda28cb2ca139275c13e60d15d809c25c031c6ce
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 26 20:53:02 2026 -0700
chore: harden DM thread-walk against cyclic re-chains (cycle guard in threadRootMid + server rootOf); session-close review pass
---
lib.js | 5 +++--
server.js | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/lib.js b/lib.js
index da46fe3..d6ce20e 100644
--- a/lib.js
+++ b/lib.js
@@ -75,8 +75,9 @@ function messages() {
return map;
}
-// Walk re-links up to the conversation root mid.
-function threadRootMid(mid, mm) { let id = mid, c = mm.get(mid); while (c && c.re && mm.get(c.re)) { id = c.re; c = mm.get(id); } return id; }
+// Walk re-links up to the conversation root mid. Visited set prevents infinite
+// loop if a corrupt/cyclical re-chain ever appears in the event log.
+function threadRootMid(mid, mm) { let id = mid, c = mm.get(mid); const seen = new Set([id]); while (c && c.re && mm.get(c.re)) { if (seen.has(c.re)) break; seen.add(c.re); id = c.re; c = mm.get(id); } return id; }
// Every agent that has sent or been addressed in a message's conversation.
function threadParticipants(mid, mm) {
diff --git a/server.js b/server.js
index fa9705a..2e1083f 100644
--- a/server.js
+++ b/server.js
@@ -22,7 +22,7 @@ function page() {
${!t.comments.length && !t.actions.length ? '<div class="c none">no comments yet</div>' : ''}</div></div>`;
// ── Direct-message conversations, grouped into threads ──
const mm = messages();
- const rootOf = mid => { let id = mid, c = mm.get(mid); while (c && c.re && mm.get(c.re)) { id = c.re; c = mm.get(id); } return id; };
+ const rootOf = mid => { let id = mid, c = mm.get(mid); const seen = new Set([id]); while (c && c.re && mm.get(c.re)) { if (seen.has(c.re)) break; seen.add(c.re); id = c.re; c = mm.get(id); } return id; };
const threads = new Map();
for (const m of mm.values()) { const r = rootOf(m.mid); (threads.get(r) || threads.set(r, []).get(r)).push(m); }
const convos = [...threads.values()].map(ms => ms.sort((a, b) => a.ts < b.ts ? -1 : 1))
← fb0737f harden @mention routing: only DM known agents (or broadcast)
·
back to Ticket System
·
auto-save: 2026-07-26T21:15:59 (2 files) — server.js office. f49cf45 →