@@ -1395,6 +1395,7 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
13951395
13961396 const displayName = workflowNames [ workflowName ] || workflowName ;
13971397 const timestamp = new Date ( ) . toLocaleString ( ) ;
1398+ const workspaceFolder = vscode . workspace . workspaceFolders ?. [ 0 ] ?. uri . fsPath || '' ;
13981399
13991400 // Format the report as markdown
14001401 let content = `# ${ displayName } Report\n\n` ;
@@ -1404,8 +1405,12 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
14041405 }
14051406 content += `\n---\n\n` ;
14061407
1408+ // Special formatting for sync-claude output
1409+ if ( workflowName === 'sync-claude' ) {
1410+ content = this . _formatSyncClaudeReport ( output , timestamp , workspaceFolder ) ;
1411+ }
14071412 // Try to parse as JSON for structured formatting, otherwise use raw output
1408- try {
1413+ else try {
14091414 const parsed = JSON . parse ( output ) ;
14101415 content += this . _formatJsonReport ( parsed ) ;
14111416 } catch {
@@ -1504,6 +1509,81 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
15041509 return content ;
15051510 }
15061511
1512+ /**
1513+ * Format sync-claude output with enhanced display:
1514+ * - Clickable file links
1515+ * - Pattern counts by category
1516+ * - Sample patterns preview
1517+ */
1518+ private _formatSyncClaudeReport ( output : string , timestamp : string , workspaceFolder : string ) : string {
1519+ let content = `# 🔄 Sync to Claude Code\n\n` ;
1520+ content += `**Generated:** ${ timestamp } \n\n` ;
1521+
1522+ // Parse categories from output (format: "✓ category: N patterns → path")
1523+ const categoryRegex = / ✓ \s + ( \w + ) : \s + ( \d + ) \s + p a t t e r n s \s + → \s + ( .+ \. m d ) / g;
1524+ const categories : Array < { name : string ; count : number ; file : string } > = [ ] ;
1525+ let match ;
1526+ while ( ( match = categoryRegex . exec ( output ) ) !== null ) {
1527+ categories . push ( { name : match [ 1 ] , count : parseInt ( match [ 2 ] ) , file : match [ 3 ] } ) ;
1528+ }
1529+
1530+ // Extract total from output
1531+ const totalMatch = output . match ( / T o t a l : \s + ( \d + ) \s + p a t t e r n s / ) ;
1532+ const totalPatterns = totalMatch ? parseInt ( totalMatch [ 1 ] ) : categories . reduce ( ( sum , c ) => sum + c . count , 0 ) ;
1533+
1534+ // Summary section
1535+ content += `## ✅ Summary\n\n` ;
1536+ content += `**${ totalPatterns } patterns** synced to Claude Code rules.\n\n` ;
1537+
1538+ // Categories table with clickable links
1539+ if ( categories . length > 0 ) {
1540+ content += `## 📁 Pattern Categories\n\n` ;
1541+ content += `| Category | Patterns | File |\n` ;
1542+ content += `|----------|----------|------|\n` ;
1543+ for ( const cat of categories ) {
1544+ const fileName = cat . file . split ( '/' ) . pop ( ) || cat . file ;
1545+ content += `| ${ cat . name } | ${ cat . count } | [${ fileName } ](${ cat . file } ) |\n` ;
1546+ }
1547+ content += `\n` ;
1548+ }
1549+
1550+ // Load and show sample patterns
1551+ content += `## 🔍 Sample Patterns\n\n` ;
1552+ try {
1553+ const debuggingPath = path . join ( workspaceFolder , '.claude' , 'rules' , 'empathy' , 'debugging.md' ) ;
1554+ if ( fs . existsSync ( debuggingPath ) ) {
1555+ const debugContent = fs . readFileSync ( debuggingPath , 'utf-8' ) ;
1556+ // Extract first 3 patterns (look for "### " headers after "## Bug Fix Patterns")
1557+ const patternRegex = / # # # \s + ( \w + ) \n - \s + \* \* R o o t c a u s e \* \* : \s + ( .+ ) \n / g;
1558+ const patterns : string [ ] = [ ] ;
1559+ let patMatch ;
1560+ while ( ( patMatch = patternRegex . exec ( debugContent ) ) !== null && patterns . length < 3 ) {
1561+ patterns . push ( `- **${ patMatch [ 1 ] } **: ${ patMatch [ 2 ] } ` ) ;
1562+ }
1563+ if ( patterns . length > 0 ) {
1564+ content += `Recent debugging patterns:\n\n${ patterns . join ( '\n' ) } \n\n` ;
1565+ } else {
1566+ content += `_No sample patterns available._\n\n` ;
1567+ }
1568+ } else {
1569+ content += `_Pattern files will be available after sync._\n\n` ;
1570+ }
1571+ } catch {
1572+ content += `_Could not load sample patterns._\n\n` ;
1573+ }
1574+
1575+ // Quick actions section
1576+ content += `## ⚡ Quick Actions\n\n` ;
1577+ content += `- 📂 [Open Rules Folder](.claude/rules/empathy/)\n` ;
1578+ content += `- 🔄 Run \`empathy sync-claude\` to re-sync\n` ;
1579+ content += `- 📖 Patterns are now available to Claude Code\n\n` ;
1580+
1581+ // Raw output (collapsed)
1582+ content += `<details>\n<summary>📋 Raw Output</summary>\n\n\`\`\`\n${ output } \n\`\`\`\n</details>\n` ;
1583+
1584+ return content ;
1585+ }
1586+
15071587 /**
15081588 * Save security audit findings to file and trigger diagnostics refresh
15091589 */
0 commit comments