diff --git a/packages/core/agent-loop/src/agent.ts b/packages/core/agent-loop/src/agent.ts index 50d01024e0..7176fdeb0d 100644 --- a/packages/core/agent-loop/src/agent.ts +++ b/packages/core/agent-loop/src/agent.ts @@ -196,10 +196,10 @@ export class ReactLoopAgent implements Agent { /** Claim and admit the next queued prompt, then start its turn. */ private kick(): void { if (this.abort !== undefined || !this.queued.some(item => item.wakeup)) return - const item = this.queued.shift() - /* v8 ignore next -- unreachable: the some() guard above proves the queue is non-empty */ - if (item === undefined) return - const { message } = item + // The some() guard above proves the queue is non-empty; the non-null + // assertion expresses that invariant. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const { message } = this.queued.shift()! emitAgentEvent(this.loopCtx, this, 'agent/inbox/dequeue', message) const admission = new AbortController() @@ -232,9 +232,8 @@ export class ReactLoopAgent implements Agent { // cancel() aborts but never clears the slot, and kick()/run()/retry() // all refuse to install a new owner while one exists, so the admission - // still owns the slot here. - /* v8 ignore next -- unreachable false arm: no writer replaces the abort owner mid-admission */ - if (this.abort === admission) this.abort = undefined + // still owns the slot here and releasing it unconditionally is exact. + this.abort = undefined if (admitted === undefined) { this.continueOrIdle() return @@ -297,11 +296,8 @@ export class ReactLoopAgent implements Agent { case 'request-failed': { // step() reports request failures only after step/start commits // and before its own step/end, so the step is always open here. - /* v8 ignore next -- unreachable false arm, see above */ - if (this.stepOpen) { - this.stepOpen = false - this.session.append('step/end', { turn, step }) - } + this.stepOpen = false + this.session.append('step/end', { turn, step }) if (agentInterruptReasonOf(signal) === undefined) { const retryWindow = { requested: false } this.retryWindow = retryWindow @@ -319,9 +315,9 @@ export class ReactLoopAgent implements Agent { ) } finally { // Nothing else writes the window while the waterfall runs: - // cancel() only flips `requested` and a second run cannot start. - /* v8 ignore next -- unreachable false arm, see above */ - if (this.retryWindow === retryWindow) this.retryWindow = undefined + // cancel() only flips `requested` and a second run cannot + // start, so unconditional retirement is exact. + this.retryWindow = undefined } retry = recoveryCompleted && agentInterruptReasonOf(signal) === undefined @@ -347,15 +343,10 @@ export class ReactLoopAgent implements Agent { } ({ reason, idle } = this.settle(turn, step, caught, signal)) } finally { + // Every step-close happens before this point on both success and + // failure paths (step(), the request-failed branch, the catch), so the + // finally owes only the turn boundary. try { - // Every step-close before this point clears the flag on both success - // and failure paths (step(), the request-failed branch, the catch), - // so the finally never finds a step still open. - /* v8 ignore next 4 -- unreachable last-resort step close, see above */ - if (this.stepOpen) { - this.stepOpen = false - this.session.append('step/end', { turn, step }) - } if (this.turnOpen) { // Re-entrant turn/end listeners must route new input to a later turn. this.turnOpen = false @@ -368,9 +359,9 @@ export class ReactLoopAgent implements Agent { } this.retryWindow = undefined // cancel() aborts but never clears the slot, and no second run can - // install a controller while this one is still unwinding. - /* v8 ignore next -- unreachable false arm, see above */ - if (this.abort === controller) this.abort = undefined + // install a controller while this one is still unwinding, so the slot + // is still this run's controller here. + this.abort = undefined signal.removeEventListener('abort', cancelRetry) }