diff --git a/src/features/tasks/execute/inputWait.ts b/src/features/tasks/execute/inputWait.ts new file mode 100644 index 0000000..5c7ea52 --- /dev/null +++ b/src/features/tasks/execute/inputWait.ts @@ -0,0 +1,24 @@ +/** + * Shared input-wait state for worker pool log suppression. + * + * When a task is waiting for user input (e.g. iteration limit prompt), + * the worker pool should suppress poll_tick debug logs to avoid + * flooding the log file with identical entries. + */ + +let waitCount = 0; + +/** Call when entering an input-wait state (e.g. selectOption). */ +export function enterInputWait(): void { + waitCount++; +} + +/** Call when leaving an input-wait state. */ +export function leaveInputWait(): void { + if (waitCount > 0) waitCount--; +} + +/** Returns true if any task is currently waiting for user input. */ +export function isInputWaiting(): boolean { + return waitCount > 0; +} diff --git a/src/features/tasks/execute/parallelExecution.ts b/src/features/tasks/execute/parallelExecution.ts index 93b9dc6..da47da4 100644 --- a/src/features/tasks/execute/parallelExecution.ts +++ b/src/features/tasks/execute/parallelExecution.ts @@ -18,6 +18,7 @@ import { EXIT_SIGINT } from '../../../shared/exitCodes.js'; import { createLogger } from '../../../shared/utils/index.js'; import { executeAndCompleteTask } from './taskExecution.js'; import { ShutdownManager } from './shutdownManager.js'; +import { isInputWaiting } from './inputWait.js'; import type { TaskExecutionOptions } from './types.js'; const log = createLogger('worker-pool'); @@ -169,7 +170,7 @@ export async function runWithWorkerPool( } } - if (!abortController.signal.aborted) { + if (!abortController.signal.aborted && !isInputWaiting()) { const freeSlots = concurrency - active.size; if (freeSlots > 0) { const newTasks = taskRunner.claimNextTasks(freeSlots); diff --git a/src/features/tasks/execute/pieceExecution.ts b/src/features/tasks/execute/pieceExecution.ts index 1fdce46..6ae36d5 100644 --- a/src/features/tasks/execute/pieceExecution.ts +++ b/src/features/tasks/execute/pieceExecution.ts @@ -10,6 +10,7 @@ import type { PieceExecutionResult, PieceExecutionOptions } from './types.js'; import { detectRuleIndex } from '../../../shared/utils/ruleIndex.js'; import { interruptAllQueries } from '../../../infra/claude/query-manager.js'; import { callAiJudge } from '../../../agents/ai-judge.js'; +import { enterInputWait, leaveInputWait } from './inputWait.js'; export type { PieceExecutionResult, PieceExecutionOptions }; @@ -398,32 +399,37 @@ export async function executePiece( playWarningSound(); } - const action = await selectOption(getLabel('piece.iterationLimit.continueQuestion'), [ - { - label: getLabel('piece.iterationLimit.continueLabel'), - value: 'continue', - description: getLabel('piece.iterationLimit.continueDescription'), - }, - { label: getLabel('piece.iterationLimit.stopLabel'), value: 'stop' }, - ]); + enterInputWait(); + try { + const action = await selectOption(getLabel('piece.iterationLimit.continueQuestion'), [ + { + label: getLabel('piece.iterationLimit.continueLabel'), + value: 'continue', + description: getLabel('piece.iterationLimit.continueDescription'), + }, + { label: getLabel('piece.iterationLimit.stopLabel'), value: 'stop' }, + ]); - if (action !== 'continue') { - return null; - } - - while (true) { - const input = await promptInput(getLabel('piece.iterationLimit.inputPrompt')); - if (!input) { + if (action !== 'continue') { return null; } - const additionalIterations = Number.parseInt(input, 10); - if (Number.isInteger(additionalIterations) && additionalIterations > 0) { - pieceConfig.maxMovements = request.maxMovements + additionalIterations; - return additionalIterations; - } + while (true) { + const input = await promptInput(getLabel('piece.iterationLimit.inputPrompt')); + if (!input) { + return null; + } - out.warn(getLabel('piece.iterationLimit.invalidInput')); + const additionalIterations = Number.parseInt(input, 10); + if (Number.isInteger(additionalIterations) && additionalIterations > 0) { + pieceConfig.maxMovements = request.maxMovements + additionalIterations; + return additionalIterations; + } + + out.warn(getLabel('piece.iterationLimit.invalidInput')); + } + } finally { + leaveInputWait(); } };