OverviewFilesCommitsIssuesDocsReleasesPeers

knowledge-ratchet commits / 994c85e

Fix false resolution detection — loops near session end marked unresolved
A loop is only resolved if: 1. Explicit approval follows, OR 2. Clean turns with decent scores AND not near session end Previously: 3 clean turns = resolved, even if user rage-quit. Now: loops ending within 5 turns of session end with no approval = unresolved. Result: 255→232 resolved, 38→61 unresolved (honest accounting). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
994c85eef68e772ffa614d81099d9d5bd61f476d
by plankatron <fleeky@gmail.com> · 2026-04-07T21:29:20.000Z

Changed files (1) +17 -1

loop-detector.js +17 -1
……@@ -127,6 +127,22 @@ function finalizeLoop (raw, session) {
127127 const project = classifyProject(session.cwd || '', allFiles)
128128 const loopType = classifyType(raw.corrections)
129129
130 // A loop is only truly resolved if:
131 // 1. There's an explicit approval after the corrections, OR
132 // 2. The clean turns after the loop have decent scores AND
133 // the loop doesn't end near the session end (user didn't just give up)
134 const totalTurns = raw.allTurns[raw.allTurns.length - 1]?.turn || 0
135 const sessionEnd = (session.turns?.length || totalTurns) - 1
136 const loopEndsTurn = raw.allTurns[raw.allTurns.length - 1]?.turn || 0
137 const nearSessionEnd = sessionEnd - loopEndsTurn < 5
138 const avgScoreAfter = resolutionTurns.length > 0
139 ? resolutionTurns.reduce((s, t) => s + t.score, 0) / resolutionTurns.length
140 : 0
141
142 const isResolved = resolutionApproval
143 ? true
144 : (!nearSessionEnd && avgScoreAfter > 0.6 && resolutionTurns.length >= CLEAN_STREAK)
145
130146 return {
131147 sessionId: session.sessionId,
132148 date: session.date,
……@@ -139,7 +155,7 @@ function finalizeLoop (raw, session) {
139155 duration: (raw.allTurns[raw.allTurns.length - 1]?.turn || raw.endTurn) - raw.startTurn + 1,
140156 correctionCount: raw.corrections.length,
141157 totalToolCalls: raw.totalToolCalls,
142 resolved: resolutionApproval ? true : resolutionTurns.length >= CLEAN_STREAK,
158 resolved: isResolved,
143159
144160 // The problem: what corrections said
145161 corrections: raw.corrections.map(c => c.text.slice(0, 200)),