test: restore 100% per-file coverage for agent-loop and the acp bridge

agent-loop: behavior tests for retry-while-busy, cancelled recovery
windows, no-facts stream failures, idle-listener preemption, rejected
driver promises under whenIdle, finish-chunk failures after step close,
presentationMeta persistence, pre-aborted and torn-down create/resume
signals, and configured-start failures over existing artifacts or after
teardown. The remaining guards that no public path can reach carry
justified v8 ignore annotations naming the invariant that starves them.

acp bridge: cover the retry-adoption path (a retry turn resolves the
prompt the failed turn deferred), the no-retry quiescence rejection, and
the admission-blocked cancelled settlement; the synchronous send-throw
catch is annotated as a future-proofing guard since the machine's send()
contains listener failures.
This commit is contained in:
_Kerman
2026-07-26 14:57:24 +08:00
parent fc8d339bf0
commit 6a068ec28d
6 changed files with 216 additions and 3 deletions

View File

@@ -295,6 +295,9 @@ export class ReactLoopAgent implements Agent {
if (outcome.continueTurn || this.outbox.some(item => 'id' in item)) continue
break
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 })
@@ -315,6 +318,9 @@ export class ReactLoopAgent implements Agent {
`agent "${this.id}": request recovery failed at turn ${turn}, step ${step}: ${errorChain(recoveryError)}`,
)
} 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
}
retry = recoveryCompleted
@@ -342,6 +348,10 @@ export class ReactLoopAgent implements Agent {
({ reason, idle } = this.settle(turn, step, caught, signal))
} finally {
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 })
@@ -357,6 +367,9 @@ export class ReactLoopAgent implements Agent {
emitAgentEvent(this.loopCtx, this, 'agent/error', turn, step, error)
}
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
signal.removeEventListener('abort', cancelRetry)
}