From 4df4d7eb6fc514ce4c0cc4beb621a354938bc2d3 Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 19 Oct 2025 12:40:54 -0500 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=A4=96=20Fix=20race=20condition=20in?= =?UTF-8?q?=20auto-compact-continue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue: checkAutoCompact() can run concurrently (effect + store subscription), and both runs could pass the initial guard check before either sets the guard. Flow: - User runs /compact -c "continue..." - Backend completes compaction, sends events - Store updates → triggers subscription callback - Effect also triggers - Both call checkAutoCompact() nearly simultaneously Race condition: 1. Run #1: checks guard (not set) → proceeds 2. Run #2: checks guard (not set yet) → proceeds 3. Run #1: sets guard → sends message 4. Run #2: sets guard (redundant) → sends message (DUPLICATE!) Fix: Double-check guard immediately before setting it. Since JS is single-threaded, whichever run reaches the guard check first will set it, and the other will see it set and skip. Added logging to track when continue messages are sent for debugging. --- src/hooks/useAutoCompactContinue.ts | 30 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/hooks/useAutoCompactContinue.ts b/src/hooks/useAutoCompactContinue.ts index 2b98fe190..05223d8c1 100644 --- a/src/hooks/useAutoCompactContinue.ts +++ b/src/hooks/useAutoCompactContinue.ts @@ -60,21 +60,25 @@ export function useAutoCompactContinue() { // The summary message has compaction-result metadata with the continueMessage const summaryMessage = state.cmuxMessages[0]; // Single compacted message const cmuxMeta = summaryMessage?.metadata?.cmuxMetadata; + const continueMessage = cmuxMeta?.type === "compaction-result" ? cmuxMeta.continueMessage : undefined; - if (cmuxMeta?.type === "compaction-result" && cmuxMeta.continueMessage) { - // Mark as fired immediately to avoid re-entry on rapid renders - firedForWorkspace.current.add(workspaceId); + if (!continueMessage) continue; - // Build options and send message directly - const options = buildSendMessageOptions(workspaceId); - window.api.workspace - .sendMessage(workspaceId, cmuxMeta.continueMessage, options) - .catch((error) => { - console.error("Failed to send continue message:", error); - // If sending failed, allow another attempt on next render by clearing the guard - firedForWorkspace.current.delete(workspaceId); - }); - } + // Mark as fired BEFORE any async operations to prevent race conditions + // This MUST come immediately after checking continueMessage to ensure + // only one of multiple concurrent checkAutoCompact() runs can proceed + if (firedForWorkspace.current.has(workspaceId)) continue; // Double-check + firedForWorkspace.current.add(workspaceId); + + console.log(`[useAutoCompactContinue] Sending continue message for ${workspaceId}:`, continueMessage); + + // Build options and send message directly + const options = buildSendMessageOptions(workspaceId); + window.api.workspace.sendMessage(workspaceId, continueMessage, options).catch((error) => { + console.error("Failed to send continue message:", error); + // If sending failed, allow another attempt on next render by clearing the guard + firedForWorkspace.current.delete(workspaceId); + }); } }; From ff32d84140ad063b63fdffe7dfa1ebce2186444a Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 19 Oct 2025 12:43:21 -0500 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=A4=96=20Fix=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useAutoCompactContinue.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hooks/useAutoCompactContinue.ts b/src/hooks/useAutoCompactContinue.ts index 05223d8c1..f93581536 100644 --- a/src/hooks/useAutoCompactContinue.ts +++ b/src/hooks/useAutoCompactContinue.ts @@ -60,7 +60,8 @@ export function useAutoCompactContinue() { // The summary message has compaction-result metadata with the continueMessage const summaryMessage = state.cmuxMessages[0]; // Single compacted message const cmuxMeta = summaryMessage?.metadata?.cmuxMetadata; - const continueMessage = cmuxMeta?.type === "compaction-result" ? cmuxMeta.continueMessage : undefined; + const continueMessage = + cmuxMeta?.type === "compaction-result" ? cmuxMeta.continueMessage : undefined; if (!continueMessage) continue; @@ -70,7 +71,10 @@ export function useAutoCompactContinue() { if (firedForWorkspace.current.has(workspaceId)) continue; // Double-check firedForWorkspace.current.add(workspaceId); - console.log(`[useAutoCompactContinue] Sending continue message for ${workspaceId}:`, continueMessage); + console.log( + `[useAutoCompactContinue] Sending continue message for ${workspaceId}:`, + continueMessage + ); // Build options and send message directly const options = buildSendMessageOptions(workspaceId); From 9e5bc148eed2e84a5ac927a5cf86bd15c255d46d Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 19 Oct 2025 12:45:02 -0500 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=A4=96=20Trigger=20CI=20rerun?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit