diff --git a/doc/plans/2026-10-25-voice-drain-repair.md b/doc/plans/2026-10-25-voice-drain-repair.md index da0ae09914d..dbe0754408e 100644 --- a/doc/plans/2026-10-25-voice-drain-repair.md +++ b/doc/plans/2026-10-25-voice-drain-repair.md @@ -60,3 +60,13 @@ owner test now advances the actual retained nextWakeAt, waits for row removal, and checks disarm. Before resume it also proves a stable idle snapshot through a minute of quiet. All 11 retention cases pass in /tmp/sleep24-drain-tests.log. No production scheduling deadline or dispatch behavior changed for this repair. + +## Report resume assertion + +The report test had the same active-counter-only flush assumption. It now checks +idle snapshot stability while paused, advances the retained nextWakeAt on resume, +and verifies one fetch and the available durable report before testing rollback. +All 14 report cases pass in /tmp/sleep25-drain-tests.log. An intermediate new +assertion incorrectly expected state=completed; the schema uses status=available. +That test-authoring failure is retained in /tmp/sleep25-drain-invalid-assertion.log. +The scheduler repair and business deadlines were not changed to satisfy tests. diff --git a/server/src/__tests__/voice-call-reports.test.ts b/server/src/__tests__/voice-call-reports.test.ts index 1094e0fa815..ffbf960fdc0 100644 --- a/server/src/__tests__/voice-call-reports.test.ts +++ b/server/src/__tests__/voice-call-reports.test.ts @@ -141,8 +141,13 @@ const support = external ? { supported: true } : await getEmbeddedPostgresTestSu }); it("retains committed work during drain and ignores rolled-back nested writes", async () => { await start(); await flush(); enabled = false; - const call = await session(); await quiet(60_000); expect(await report(call.id)).toBeUndefined(); - enabled = true; await flush(); expect(fetchReport).toHaveBeenCalledOnce(); + const call = await session(); await flush(); + const drained = idleWorkSnapshot(); + await quiet(60_000); expect(idleWorkSnapshot()).toEqual(drained); expect(await report(call.id)).toBeUndefined(); + const resumeAt = coordinator!.nextWakeAt(); expect(resumeAt).not.toBeNull(); + enabled = true; await vi.advanceTimersByTimeAsync(Math.max(0, resumeAt! - Date.now())); + await vi.waitFor(async () => { await flush(); expect(fetchReport).toHaveBeenCalledOnce(); }); + expect(await report(call.id)).toMatchObject({ status: "available" }); await expect(db.transaction(async tx => { await session({}, tx as unknown as typeof db); throw new Error("rollback"); })).rejects.toThrow("rollback"); await flush(); expect(fetchReport).toHaveBeenCalledOnce(); await quiet(); });