| … | … | @@ -127,6 +127,22 @@ function finalizeLoop (raw, session) { |
| 127 | 127 | const project = classifyProject(session.cwd || '', allFiles) |
| 128 | 128 | const loopType = classifyType(raw.corrections) |
| 129 | 129 | |
| 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 | |
| 130 | 146 | return { |
| 131 | 147 | sessionId: session.sessionId, |
| 132 | 148 | date: session.date, |
| … | … | @@ -139,7 +155,7 @@ function finalizeLoop (raw, session) { |
| 139 | 155 | duration: (raw.allTurns[raw.allTurns.length - 1]?.turn || raw.endTurn) - raw.startTurn + 1, |
| 140 | 156 | correctionCount: raw.corrections.length, |
| 141 | 157 | totalToolCalls: raw.totalToolCalls, |
| 142 | | resolved: resolutionApproval ? true : resolutionTurns.length >= CLEAN_STREAK, |
| 158 | resolved: isResolved, |
| 143 | 159 | |
| 144 | 160 | // The problem: what corrections said |
| 145 | 161 | corrections: raw.corrections.map(c => c.text.slice(0, 200)), |