From 3e68fcc3e080e7765ed89e526040f25c1de9729d Mon Sep 17 00:00:00 2001 From: Darryl Doonie Date: Thu, 2 Jul 2026 14:11:04 -0400 Subject: [PATCH] fix(learning-readback): surface CONTEXT.md summaries instead of mangled dir slugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadFailurePatterns() read each failure's CONTEXT.md into memory and then discarded it, injecting the de-slugified directory name instead — hard-cut at 70 chars with no word boundary. Session starts received garbled, low-signal lines while the clean human-readable Summary line written by FailureCapture sat unused in the file it had just read. - Prefer CONTEXT.md's **Summary:** line; fall back to the first line of '## What Happened'; fall back to the de-slugged dir name. - Truncate at a word boundary (~110 chars) with ellipsis. - Dedupe captures whose summaries are identical (double-fires produce two dirs for one event). Co-Authored-By: Claude Fable 5 --- .../.claude/hooks/lib/learning-readback.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Releases/v5.0.0/.claude/hooks/lib/learning-readback.ts b/Releases/v5.0.0/.claude/hooks/lib/learning-readback.ts index 4535e18449..a721c3cf99 100755 --- a/Releases/v5.0.0/.claude/hooks/lib/learning-readback.ts +++ b/Releases/v5.0.0/.claude/hooks/lib/learning-readback.ts @@ -172,12 +172,23 @@ export function loadFailurePatterns(paiDir: string): string | null { try { const content = readFileSync(contextPath, 'utf-8'); - // Extract slug as human-readable failure description - const slug = dir.replace(/^\d{4}-\d{2}-\d{2}-\d{6}_/, '').replace(/-/g, ' '); // Get date from dir name const dateMatch = dir.match(/^(\d{4}-\d{2}-\d{2})/); const date = dateMatch ? dateMatch[1] : ''; - patterns.push(`[${date}] ${slug.substring(0, 70)}`); + // Prefer CONTEXT.md's own one-liner over the mangled dir slug + // (previously the file was read but its content discarded) + let desc = content.match(/\*\*Summary:\*\*\s*(.+)/)?.[1]?.trim() + || content.match(/## What Happened\s*\n+([^\n]+)/)?.[1]?.trim() + || dir.replace(/^\d{4}-\d{2}-\d{2}-\d{6}_/, '').replace(/-/g, ' '); + // Truncate at a word boundary instead of a hard mid-word cut + if (desc.length > 110) { + const cut = desc.lastIndexOf(' ', 110); + desc = desc.slice(0, cut > 60 ? cut : 110) + '…'; + } + // Skip duplicate captures of the same event (a double-fire can + // produce two dirs with different slugs but identical summaries) + if (patterns.some(p => p.endsWith(desc))) continue; + patterns.push(`[${date}] ${desc}`); } catch { /* skip unreadable */ } } } catch { /* skip unreadable months */ }