From 87cd712498f9712621bd7ef65bc04bacd89aaba0 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 23 Sep 2026 17:34:35 +0545 Subject: [PATCH] fix: give reopen checks the original report, log every verdict A reopen only classified the delta since the last check, so a genuine bug could keep reading as routine follow-up (e.g. "here's the fix zip") run after run with no context on what it was even about. Now pairs the delta with the conversation's opening messages. Also logs the classifier's verdict on every reopen/stale-auto check, not just escalations, so a skip is visible in the run log instead of silent. Co-Authored-By: Claude Sonnet 5 --- scripts/crisp-classify.mjs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/crisp-classify.mjs b/scripts/crisp-classify.mjs index 140708a..499c982 100644 --- a/scripts/crisp-classify.mjs +++ b/scripts/crisp-classify.mjs @@ -150,7 +150,16 @@ async function main() { const relevantMessages = isReopen && !hasNewManualNote ? messages.filter((m) => (m.timestamp ?? 0) > previousResolveAt) : messages; - const transcript = transcriptFrom(relevantMessages); + let transcript = transcriptFrom(relevantMessages); + // Pair a reopen's delta with the opening messages, or it reads as + // routine follow-up with no idea what bug it's about. Capped to a few + // messages, not the full history, to keep this cheap. + if (isReopen && !hasNewManualNote && transcript.trim()) { + const opening = transcriptFrom(messages.slice(0, 6)); + if (opening.trim()) { + transcript = `[Original report]\n${opening}\n\n[New activity since last checked]\n${transcript}`; + } + } if (!transcript.trim()) continue; if (hasNewManualNote) { @@ -171,6 +180,9 @@ async function main() { investigated.add(conversation.session_id); reopenEscalations++; console.log(`[${accountKey}] ${conversation.session_id}: reopened after resolve, classifier agrees -> escalated to ${result.repo}`); + } else { + // Log the verdict even on a skip, so a silently-missed real bug is visible in the run log. + console.log(`[${accountKey}] ${conversation.session_id}: reopened after resolve, classifier says not actionable (kind=${result.kind ?? "n/a"}${result.repo ? "" : ", unmapped"}) -- not escalated`); } // Advance the marker so an unresolved reopen doesn't get re-classified next run. const newestMs = messages.reduce((max, m) => Math.max(max, m.timestamp ?? 0), previousResolveAt); @@ -183,6 +195,8 @@ async function main() { investigated.add(conversation.session_id); autoEscalations++; console.log(`[${accountKey}] ${conversation.session_id}: stale ${staleHours.toFixed(1)}h, classifier agrees -> escalated to ${result.repo}`); + } else { + console.log(`[${accountKey}] ${conversation.session_id}: stale ${staleHours.toFixed(1)}h, classifier says not actionable (kind=${result.kind ?? "n/a"}${result.repo ? "" : ", unmapped"}) -- not escalated`); } }