In v4.1.0+, users observed duplicate assistant streams rendering the same content in two languages simultaneously (e.g. Chinese + English), most often at the end of a turn. Root cause: ParentWakeNotifier.requeueWake() unconditionally requeued ANY wake that arrived during the background-agent-parent-wake post-dispatch hold window. When a duplicate completion edge fired during that hold, the same wake was replayed after the hold expired, triggering a second prompt dispatch and a parallel assistant stream. The fix compares the new wake against dispatchedParentWakes.get(sessionID) and drops identical wakes during the gate hold, while preserving the existing requeue behavior for genuinely-new wakes and failed-dispatch retries. Regression test added in given/when/then style covering the duplicate-during- hold scenario (TDD red-then-green). Fixes #4256 Fixes #4019
This commit is contained in:
@@ -84,6 +84,31 @@ function releaseParentWakeHold(sessionID: string): void {
|
||||
}
|
||||
|
||||
describe("ParentWakeNotifier — same-source reservation requeue (BUG-E)", () => {
|
||||
test("#given a duplicate parent wake is in post-dispatch hold #when the duplicate fires again #then it is dropped instead of requeued", async () => {
|
||||
// given
|
||||
const { notifier, promptAsyncCalls } = createNotifier()
|
||||
const sessionID = "parent-hold-duplicate-wake"
|
||||
notifier.queuePendingParentWake(sessionID, "wake A", { agent: "sisyphus" }, true)
|
||||
|
||||
try {
|
||||
await notifier.flushPendingParentWake(sessionID)
|
||||
expect(promptAsyncCalls).toHaveLength(1)
|
||||
|
||||
// when
|
||||
notifier.queuePendingParentWake(sessionID, "wake A", { agent: "sisyphus" }, true)
|
||||
await notifier.flushPendingParentWake(sessionID)
|
||||
releaseParentWakeHold(sessionID)
|
||||
await notifier.flushPendingParentWake(sessionID)
|
||||
|
||||
// then
|
||||
expect(promptAsyncCalls).toHaveLength(1)
|
||||
expect(notifier.getPendingParentWakes().has(sessionID)).toBe(false)
|
||||
} finally {
|
||||
notifier.shutdown()
|
||||
releaseAllPromptAsyncReservationsForTesting()
|
||||
}
|
||||
})
|
||||
|
||||
test("#given a parent wake is in post-dispatch hold #when a new pending wake fires within the hold window #then the new wake is re-enqueued and dispatched after the hold expires", async () => {
|
||||
// given
|
||||
const { notifier, promptAsyncCalls } = createNotifier()
|
||||
|
||||
Reference in New Issue
Block a user