fix: expose summaryStored in session status to detect silent summary loss (#1633)

Stop hook polled queueLength===0 as a proxy for summary success, but the queue
empties regardless of whether the LLM produced valid <summary> tags. Added
lastSummaryStored tracking on ActiveSession, surfaced via the /api/sessions/status
endpoint, and emit a logger.warn in the Stop hook when summaryStored===false.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ousama Ben Younes
2026-04-10 15:06:18 +00:00
parent cde4faae2f
commit 2f19eab9c2
5 changed files with 66 additions and 2 deletions
+13 -2
View File
@@ -87,6 +87,7 @@ export const summarizeHandler: EventHandler = {
// This keeps the Stop hook alive (120s timeout) so the SDK agent
// can finish processing the summary before SessionEnd kills the session.
const waitStart = Date.now();
let summaryStored: boolean | null = null;
while ((Date.now() - waitStart) < MAX_WAIT_FOR_SUMMARY_MS) {
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS));
try {
@@ -94,11 +95,21 @@ export const summarizeHandler: EventHandler = {
timeoutMs: 5000
});
if (statusResponse.ok) {
const status = await statusResponse.json() as { queueLength?: number };
const status = await statusResponse.json() as { queueLength?: number; summaryStored?: boolean | null };
if ((status.queueLength ?? 0) === 0) {
summaryStored = status.summaryStored ?? null;
logger.info('HOOK', 'Summary processing complete', {
waitedMs: Date.now() - waitStart
waitedMs: Date.now() - waitStart,
summaryStored
});
// Warn when the agent processed a summarize request but produced no storable summary.
// This is the silent-failure path described in #1633: queue empties but no summary record exists.
if (summaryStored === false) {
logger.warn('HOOK', 'Summary was not stored: LLM response likely lacked valid <summary> tags (#1633)', {
sessionId,
waitedMs: Date.now() - waitStart
});
}
break;
}
}