From b3d0e0cb458265fa234176cddc8af136733a4d15 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 16 Feb 2026 23:31:26 +0000 Subject: [PATCH] fix(cron): preserve overrides and harden next-run calculation --- src/cron/isolated-agent/session.test.ts | 6 +----- src/cron/isolated-agent/session.ts | 5 ++--- src/cron/schedule.ts | 5 ++--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/cron/isolated-agent/session.test.ts b/src/cron/isolated-agent/session.test.ts index 519b2744c..270628e81 100644 --- a/src/cron/isolated-agent/session.test.ts +++ b/src/cron/isolated-agent/session.test.ts @@ -150,12 +150,8 @@ describe("resolveCronSession", () => { "webhook:stable-key": { updatedAt: Date.now() - 1000, modelOverride: "some-model", - } as unknown as { - sessionId: string; - updatedAt: number; - modelOverride?: string; }, - }); + } as ReturnType); vi.mocked(evaluateSessionFreshness).mockReturnValue({ fresh: true }); const result = resolveCronSession({ diff --git a/src/cron/isolated-agent/session.ts b/src/cron/isolated-agent/session.ts index fcc2579cb..0f23c836c 100644 --- a/src/cron/isolated-agent/session.ts +++ b/src/cron/isolated-agent/session.ts @@ -59,9 +59,8 @@ export function resolveCronSession(params: { } const sessionEntry: SessionEntry = { - // Spread existing entry to preserve conversation context when reusing - // (the spread already copies all fields when !isNewSession, no need to re-assign) - ...(isNewSession ? undefined : entry), + // Preserve existing per-session overrides even when rolling to a new sessionId. + ...entry, // Always update these core fields sessionId, updatedAt: params.nowMs, diff --git a/src/cron/schedule.ts b/src/cron/schedule.ts index a459bc5be..669aae32b 100644 --- a/src/cron/schedule.ts +++ b/src/cron/schedule.ts @@ -62,13 +62,12 @@ export function computeNextRunAtMs(schedule: CronSchedule, nowMs: number): numbe } // Guard against same-second rescheduling loops: if croner returns - // "now" (or an earlier instant) when the job completed mid-second, - // retry from the next whole second. + // "now" (or an earlier instant), retry from the next whole second. const nextSecondMs = Math.floor(nowMs / 1000) * 1000 + 1000; const retry = cron.nextRun(new Date(nextSecondMs)); if (!retry) { return undefined; } const retryMs = retry.getTime(); - return Number.isFinite(retryMs) ? retryMs : undefined; + return Number.isFinite(retryMs) && retryMs > nowMs ? retryMs : undefined; }