From 19bfcd797cf5e2b0fd9be8dc8019711080c0447a Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Thu, 12 Mar 2026 09:03:00 -0600 Subject: [PATCH] fix: address review nits from #113 merge - Fix misleading "atomically" comment on persistCompletedKey - Consolidate duplicate "(attempt N)" strings in recovery notifications - Add setImmediate yield in idempotency skip to prevent tight recursion Co-Authored-By: Claude Opus 4.6 --- src/resources/extensions/gsd/auto.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/resources/extensions/gsd/auto.ts b/src/resources/extensions/gsd/auto.ts index bbc061bea..ccf17e743 100644 --- a/src/resources/extensions/gsd/auto.ts +++ b/src/resources/extensions/gsd/auto.ts @@ -78,7 +78,7 @@ function completedKeysPath(base: string): string { return join(base, ".gsd", "completed-units.json"); } -/** Write a completed unit key to disk atomically (append to set). */ +/** Write a completed unit key to disk (read-modify-write append to set). */ function persistCompletedKey(base: string, key: string): void { const file = completedKeysPath(base); let keys: string[] = []; @@ -1194,8 +1194,9 @@ async function dispatchNextUnit( `Skipping ${unitType} ${unitId} — already completed in a prior session. Advancing.`, "info", ); - // Don't increment dispatch count — just advance by calling dispatchNextUnit again. - // First, force state re-derive so the scheduler sees the completed artifact. + // Yield to the event loop before re-dispatching to avoid tight recursion + // when many units are already completed (e.g., after crash recovery). + await new Promise(r => setImmediate(r)); await dispatchNextUnit(ctx, pi); return; } @@ -2348,7 +2349,7 @@ async function recoverTimedOutUnit( { triggerTurn: true, deliverAs: "steer" }, ); ctx.ui.notify( - `${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to finish durable output (attempt ${recoveryAttempts + 1}/${maxRecoveryAttempts}) (attempt ${attemptNumber}).`, + `${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to finish durable output (attempt ${attemptNumber}, session ${recoveryAttempts + 1}/${maxRecoveryAttempts}).`, "warning", ); return "recovered"; @@ -2452,7 +2453,7 @@ async function recoverTimedOutUnit( { triggerTurn: true, deliverAs: "steer" }, ); ctx.ui.notify( - `${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to produce ${expected} (attempt ${recoveryAttempts + 1}/${maxRecoveryAttempts}) (attempt ${attemptNumber}).`, + `${reason === "idle" ? "Idle" : "Timeout"} recovery: steering ${unitType} ${unitId} to produce ${expected} (attempt ${attemptNumber}, session ${recoveryAttempts + 1}/${maxRecoveryAttempts}).`, "warning", ); return "recovered";