@@ -1254,10 +1254,16 @@ export async function runCodexAppServerAttempt(
12541254 turnAssistantCompletionIdleWatchArmed &&
12551255 notification . method === "item/completed" &&
12561256 activeTurnItemIds . size === 0 ;
1257- const shouldKeepCompletionIdleWatchArmed =
1257+ const trackedDynamicToolCompletion = isTrackedOpenClawDynamicToolCompletionNotification (
1258+ notification ,
1259+ activeOpenClawDynamicToolCallIds ,
1260+ ) ;
1261+ const shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem =
12581262 isCurrentTurnNotification &&
12591263 notification . method === "item/completed" &&
1260- activeTurnItemIds . size === 0 ;
1264+ activeTurnItemIds . size === 0 &&
1265+ ! trackedDynamicToolCompletion &&
1266+ ! isCompletedAssistantNotification ( notification ) ;
12611267 if ( isCurrentTurnNotification && notification . method === "error" ) {
12621268 if ( isRetryableErrorNotification ( notification . params ) ) {
12631269 disarmTurnCompletionIdleWatch ( ) ;
@@ -1271,14 +1277,10 @@ export async function runCodexAppServerAttempt(
12711277 armTurnAssistantCompletionIdleWatch ( describeNotificationActivity ( notification ) ) ;
12721278 } else if ( unblockedAssistantCompletionRelease ) {
12731279 armTurnAssistantCompletionIdleWatch ( describeNotificationActivity ( notification ) ) ;
1274- } else if (
1275- isCurrentTurnNotification &&
1276- notification . method === "item/completed" &&
1277- activeTurnItemIds . size === 0
1278- ) {
1279- // If the bridge goes silent immediately after the last current-turn item
1280- // completes, do not wait for the long terminal watchdog. Re-arm the short
1281- // completion-idle guard so we fail promptly instead of wedging the session.
1280+ } else if ( shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem ) {
1281+ // If a non-assistant current-turn item is the last active item and the
1282+ // bridge then goes quiet, reset the short completion-idle guard from that
1283+ // final completion so the remaining silent-turn gap fails fast.
12821284 armTurnCompletionIdleWatch ( ) ;
12831285 } else if (
12841286 isCurrentTurnNotification &&
@@ -1291,11 +1293,8 @@ export async function runCodexAppServerAttempt(
12911293 ! turnCompletionIdleWatchPinnedByTerminalError &&
12921294 notification . method !== "turn/completed" &&
12931295 isCurrentTurnNotification &&
1294- ! isTrackedOpenClawDynamicToolCompletionNotification (
1295- notification ,
1296- activeOpenClawDynamicToolCallIds ,
1297- ) &&
1298- ! shouldKeepCompletionIdleWatchArmed
1296+ ! trackedDynamicToolCompletion &&
1297+ ! shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem
12991298 ) {
13001299 // The short completion-idle watchdog guards blind gaps after Codex
13011300 // accepts a turn or after OpenClaw hands a turn-scoped request result
0 commit comments