From ff88dd1f8f62ed6e20e5d5fd112012b3ee617059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 13 Aug 2026 07:11:32 +0200 Subject: [PATCH] coach: keep cancelled-turn markers out of the plan fold too The facts fold already skips the empty assistant row a cancelled turn leaves behind; the plan fold read it as a blank turn and spent one of its recent-turn slots on nothing. Same skip, same reason. Also state the accepted one-slot slack a late rate-limit refund can leave in a freshly opened window. Refs #781. --- src/lib/ai/coach/plans.ts | 3 +++ src/lib/rate-limit.ts | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/lib/ai/coach/plans.ts b/src/lib/ai/coach/plans.ts index 070335bfe..cade32d18 100644 --- a/src/lib/ai/coach/plans.ts +++ b/src/lib/ai/coach/plans.ts @@ -276,6 +276,9 @@ async function loadRecentTurns( for (const m of [...row.messages].reverse()) { const content = decryptOrNull(m.encryptedContent); if (content === null) continue; + // #781 — skip empty bodies: a cancelled-turn marker (an empty assistant + // row closing an aborted turn) carries nothing to extract from. + if (!content.trim()) continue; turns.push({ role: m.role, content }); } return turns; diff --git a/src/lib/rate-limit.ts b/src/lib/rate-limit.ts index cad590f3b..b8dccc0a5 100644 --- a/src/lib/rate-limit.ts +++ b/src/lib/rate-limit.ts @@ -61,6 +61,12 @@ export async function checkRateLimit( * once `reset_at` has passed the counter is stale and a decrement would bleed * into the NEXT window's budget, so an expired row is left untouched. Never * drops below zero (concurrent refunds after a window flip are a no-op). + * + * Known slack: if the charge's window expires and a new request opens the + * NEXT window before a late refund lands, the refund decrements that fresh + * window instead — at most one extra slot there, only on failure paths that + * never reached the metered work. Accepted; carrying the charge's `reset_at` + * through every failure path is not worth one slot of slack. */ export async function refundRateLimit(key: string): Promise { await prisma.$executeRaw`