| … | … | @@ -243,7 +243,7 @@ ${liveSession && liveSession.turns > 0 ? ` |
| 243 | 243 | <div style="display: flex; gap: 32px; align-items: baseline;"> |
| 244 | 244 | <div><span class="big-number ${liveColor}">${liveScore}</span><span class="dim"> score</span></div> |
| 245 | 245 | <div><span class="green" style="font-size:20px">${liveSession.approvals} approved</span> <span class="red" style="font-size:20px">${liveSession.corrections} corrected</span><span class="dim"> in ${liveSession.turns} turns</span></div> |
| 246 | | <div><span class="dim">${liveSession.toolCalls} tools</span></div> |
| 246 | <div><span class="dim">${liveSession.toolCalls} tool calls</span></div> |
| 247 | 247 | <div><span class="${liveTrajColor}">${liveTraj}</span></div> |
| 248 | 248 | ${liveLearningRate !== null ? `<div><span class="${liveLearningColor}" style="font-size:18px">${liveLearningStr}</span></div>` : ''} |
| 249 | 249 | </div> |
| … | … | @@ -255,17 +255,17 @@ ${liveSession && liveSession.turns > 0 ? ` |
| 255 | 255 | <div class="card"> |
| 256 | 256 | <div class="card-title">Novel Corrections (target: >90%)</div> |
| 257 | 257 | <div class="big-number ${novelColor}">${novelRate}%${novelArrow}</div> |
| 258 | | <div class="dim">old mistakes eliminated — higher is better</div> |
| 258 | <div class="dim">% of corrections that are new mistakes, not repeats. Higher = old mistakes stay fixed.</div> |
| 259 | 259 | </div> |
| 260 | 260 | <div class="card"> |
| 261 | 261 | <div class="card-title">Correction Density (target: <15%)</div> |
| 262 | 262 | <div class="big-number ${densityColor}">${densityPct}%${densityArrow}</div> |
| 263 | | <div class="dim">corrections per turn — lower is better</div> |
| 263 | <div class="dim">How often the user has to correct Claude per turn. 20% = 1 in 5 turns. Lower = fewer mistakes.</div> |
| 264 | 264 | </div> |
| 265 | 265 | <div class="card"> |
| 266 | 266 | <div class="card-title">Loop Resolution (target: <6 turns)</div> |
| 267 | 267 | <div class="big-number ${resColor}">${resolution}${resArrow}</div> |
| 268 | | <div class="dim">turns to fix a loop — lower is better</div> |
| 268 | <div class="dim">When Claude gets stuck in a correction loop, how many turns to escape. Lower = learns faster.</div> |
| 269 | 269 | </div> |
| 270 | 270 | <div class="card"> |
| 271 | 271 | <div class="card-title">Learned Rules</div> |
| … | … | @@ -276,19 +276,19 @@ ${liveSession && liveSession.turns > 0 ? ` |
| 276 | 276 | |
| 277 | 277 | <!-- Weekly Fused Score Trend --> |
| 278 | 278 | <div class="chart-container"> |
| 279 | | <div class="card-title">Weekly Fused Score Trend</div> |
| 279 | <div class="card-title">Weekly Fused Score (higher = better)</div> |
| 280 | 280 | ${renderLineChart(weeklyData.map(w => w.score), weeklyData.map(w => w.week), { height: 140, color: '#58a6ff', label: 'Fused Score', format: 'auto' })} |
| 281 | 281 | </div> |
| 282 | 282 | |
| 283 | 283 | <!-- Weekly Correction Density --> |
| 284 | 284 | <div class="chart-container"> |
| 285 | | <div class="card-title">Weekly Corrections vs Approvals</div> |
| 285 | <div class="card-title">Weekly Corrections vs Approvals (green overtaking red = improving)</div> |
| 286 | 286 | ${renderBarChart(weeklyData, { height: 120 })} |
| 287 | 287 | </div> |
| 288 | 288 | |
| 289 | 289 | <!-- Loops Over Time --> |
| 290 | 290 | <div class="chart-container"> |
| 291 | | <div class="card-title">Loops Per Week</div> |
| 291 | <div class="card-title">Loops Per Week (lower = better)</div> |
| 292 | 292 | ${renderLineChart( |
| 293 | 293 | Object.entries(loopsWeekly).sort().map(([, v]) => v.total), |
| 294 | 294 | Object.entries(loopsWeekly).sort().map(([k]) => k), |
| … | … | @@ -298,12 +298,13 @@ ${liveSession && liveSession.turns > 0 ? ` |
| 298 | 298 | |
| 299 | 299 | <!-- Session Scatter --> |
| 300 | 300 | <div class="chart-container"> |
| 301 | | <div class="card-title">Session Scores (each dot = one session, size = turns)</div> |
| 301 | <div class="card-title">Session Scores — green dots = clean sessions, red = heavy corrections, size = session length. Higher = better.</div> |
| 302 | 302 | ${renderScatter(sessionData, { height: 150 })} |
| 303 | 303 | </div> |
| 304 | 304 | |
| 305 | 305 | <!-- Loops by Project --> |
| 306 | 306 | <h3>Loops by Project</h3> |
| 307 | <p class="dim" style="margin-bottom:8px">A loop is a correction spiral — Claude gets corrected, tries to fix it, gets corrected again. More loops = more frustration. Higher resolved % = problems eventually get fixed.</p> |
| 307 | 308 | <table> |
| 308 | 309 | <tr><th>Project</th><th>Loops</th><th>Resolved</th><th>Avg Duration</th><th></th></tr> |
| 309 | 310 | ${Object.entries(loopsByProject).sort((a, b) => b[1].total - a[1].total).map(([proj, data]) => { |
| … | … | @@ -320,6 +321,7 @@ ${liveSession && liveSession.turns > 0 ? ` |
| 320 | 321 | |
| 321 | 322 | <!-- Subsystem Danger Map --> |
| 322 | 323 | <h3>Subsystem Danger Map</h3> |
| 324 | <p class="dim" style="margin-bottom:8px">Auto-discovered from code. Red = high loop count (Claude struggles here). Yellow = moderate. Green = stable. L=loops, F=files in subsystem.</p> |
| 323 | 325 | ${Object.entries(dangerMap).map(([proj, subs]) => { |
| 324 | 326 | if (subs.length === 0) return '' |
| 325 | 327 | return `<div style="margin-bottom:12px"> |
| … | … | @@ -331,7 +333,8 @@ ${Object.entries(dangerMap).map(([proj, subs]) => { |
| 331 | 333 | }).join('\n')} |
| 332 | 334 | |
| 333 | 335 | <!-- Sensor Weights --> |
| 334 | | <h3>Sensor Weight Evolution</h3> |
| 336 | <h3>Sensor Weights</h3> |
| 337 | <p class="dim" style="margin-bottom:8px">The system uses 16 sensors to score each turn. Weights auto-adjust based on which sensors best predict corrections. Higher weight = more influence on the fused score.</p> |
| 335 | 338 | <table> |
| 336 | 339 | <tr><th>Sensor</th><th>Weight</th><th>Bar</th></tr> |
| 337 | 340 | ${fused?.sensorWeights ? Object.entries(fused.sensorWeights).sort((a, b) => b[1] - a[1]).map(([name, weight]) => { |
| … | … | @@ -346,7 +349,8 @@ ${Object.entries(dangerMap).map(([proj, subs]) => { |
| 346 | 349 | |
| 347 | 350 | <!-- Ratchet Intelligence Trends --> |
| 348 | 351 | <h3>Intelligence Ratchet Trends</h3> |
| 349 | | ${benchmarkHistory.length >= 2 ? ` |
| 352 | <p class="dim" style="margin-bottom:8px">These lines should trend in the right direction over time. If they don't, the ratchet isn't working.</p> |
| 353 | ${benchmarkHistory.length >= 1 ? ` |
| 350 | 354 | <div class="grid"> |
| 351 | 355 | <div class="card"> |
| 352 | 356 | <div class="card-title">Novel Correction Rate (higher = better)</div> |
| … | … | @@ -383,7 +387,7 @@ ${benchmarkHistory.length >= 2 ? ` |
| 383 | 387 | </div> |
| 384 | 388 | |
| 385 | 389 | <div class="card" style="margin-top:16px"> |
| 386 | | <div class="card-title">Ratchet Scorecard — Is it working?</div> |
| 390 | <div class="card-title">Ratchet Scorecard — Green = target met, Yellow = working on it, Red = failing</div> |
| 387 | 391 | <table> |
| 388 | 392 | <tr><th>Metric</th><th>Current</th><th>Target</th><th>Status</th></tr> |
| 389 | 393 | <tr> |