From b2bd10517d092cbf5bfadb08cc25b5809ee2e5e1 Mon Sep 17 00:00:00 2001 From: Dotta Date: Sun, 25 Oct 2026 05:36:16 -0500 Subject: [PATCH] test(server): wait for Discord recovery settlement before quiet checks Co-Authored-By: Paperclip --- ...0-25-discord-command-registration-sleep-audit.md | 13 +++++++++++++ .../chat-discord-command-registration-store.test.ts | 8 +++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/doc/plans/2026-10-25-discord-command-registration-sleep-audit.md b/doc/plans/2026-10-25-discord-command-registration-sleep-audit.md index 7da51f397f5..baca522b7d8 100644 --- a/doc/plans/2026-10-25-discord-command-registration-sleep-audit.md +++ b/doc/plans/2026-10-25-discord-command-registration-sleep-audit.md @@ -185,3 +185,16 @@ always restores spies. Verification: 87 worker/coordinator/health, eight produce and affected Slack, 57 existing lifecycle/startup tests; server types/build pass. The health security parent is inherited through company cleanup. See the owning Discord document for failure evidence and exact scope. Fresh remote gates remain. + +## Idle assertion settlement repair + +A descendant CI run (#17583, run 40184498387, server shard 11/12) observed one +scoped candidate SELECT during the rollback test's quiet interval. The test only +waited for nextWakeAt to become null. The coordinator consumes a timer before +its asynchronous transaction reconciliation and scoped load run, so null alone +can mean work is running, not settled. The test now waits for zero tracked active +work as well as no deadline before measuring the same 60-second zero-SQL interval. +No production timeout, dispatch, or quiet predicate was relaxed. All 41 real +PostgreSQL command ownership cases pass with the repair. Log: +`/tmp/sleep19-settlement-tests.log`. Propagate this owner-level change through the +stack; remote checks must verify the new heads. diff --git a/server/src/services/chat-discord-command-registration-store.test.ts b/server/src/services/chat-discord-command-registration-store.test.ts index 5dd2afdb64b..71660aaeae6 100644 --- a/server/src/services/chat-discord-command-registration-store.test.ts +++ b/server/src/services/chat-discord-command-registration-store.test.ts @@ -1,4 +1,5 @@ import { reconcileDatabaseWork } from "@paperclipai/db"; +import { idleWorkSnapshot } from "./task-admission.js"; import { DELIVERY_QUEUES, notifyDeliveryWork } from "./delivery-work-notifications.js"; import { discordCommandSchedule } from "./chat-channels/discord/command-schedule.js"; import { registerDiscordCommandWork } from "./chat-channels/discord/command-work.js"; @@ -755,7 +756,12 @@ suite("Discord command ownership store (real PostgreSQL, no network)", () => { throw new Error("abort"); })).rejects.toThrow("abort"); await vi.advanceTimersByTimeAsync(60_000); - await vi.waitFor(() => expect(coordinator!.nextWakeAt()).toBeNull()); + // A running sweep has already consumed its timer. Wait for its SQL and + // transaction reconciliation to settle before measuring idle traffic. + await vi.waitFor(() => { + expect(idleWorkSnapshot().active).toBe(0); + expect(coordinator!.nextWakeAt()).toBeNull(); + }); await sqlQuiet(60_000); draining = true; await db.transaction(async tx => activate(tx as unknown as typeof db));