From 75ce583d0b9bd1f2159a8d447b25b27e61359709 Mon Sep 17 00:00:00 2001 From: nrslib <38722970+nrslib@users.noreply.github.com> Date: Fri, 20 Feb 2026 23:42:38 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E3=82=A4=E3=83=86=E3=83=AC=E3=83=BC?= =?UTF-8?q?=E3=82=B7=E3=83=A7=E3=83=B3=E5=85=A5=E5=8A=9B=E5=BE=85=E3=81=A1?= =?UTF-8?q?=E4=B8=AD=E3=81=AEpoll=5Ftick=E3=83=AD=E3=82=B0=E9=80=A3?= =?UTF-8?q?=E7=B6=9A=E5=87=BA=E5=8A=9B=E3=82=92=E6=8A=91=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 入力待ちフラグ(enterInputWait/leaveInputWait)を導入し、 selectOption待ち中はワーカープールのポーリングログをスキップする。 入力完了で自動復活。 --- src/features/tasks/execute/inputWait.ts | 24 ++++++++++ .../tasks/execute/parallelExecution.ts | 3 +- src/features/tasks/execute/pieceExecution.ts | 48 +++++++++++-------- 3 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 src/features/tasks/execute/inputWait.ts 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(); } };