From a9a2004d4af707dad8c69f99b0167ae0bdf4c1ed Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sat, 6 Dec 2025 21:04:50 +0800 Subject: [PATCH] feat(dashboard): add context sections for assets, dependencies, test context, and conflict detection --- ccw/src/templates/dashboard.css | 51 ++++- ccw/src/templates/dashboard.js | 379 +++++++++++++++++++++++++++++++- 2 files changed, 426 insertions(+), 4 deletions(-) diff --git a/ccw/src/templates/dashboard.css b/ccw/src/templates/dashboard.css index 87a91d9c..2dcb5b24 100644 --- a/ccw/src/templates/dashboard.css +++ b/ccw/src/templates/dashboard.css @@ -1328,10 +1328,40 @@ code { gap: 1rem; } +.context-section { + padding: 1rem; + background: hsl(var(--muted) / 0.3); + border: 1px solid hsl(var(--border)); + border-radius: 0.5rem; +} + +.context-section-title { + font-size: 1rem; + font-weight: 600; + color: hsl(var(--foreground)); + margin-bottom: 0.75rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid hsl(var(--border)); +} + .context-field { - padding: 0.75rem; - background: hsl(var(--muted)); - border-radius: 0.375rem; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.context-label { + font-size: 0.75rem; + font-weight: 600; + color: hsl(var(--muted-foreground)); + text-transform: uppercase; + letter-spacing: 0.025em; +} + +.context-value { + font-size: 0.875rem; + color: hsl(var(--foreground)); + line-height: 1.6; } .context-field label { @@ -1712,6 +1742,21 @@ code { line-height: 1.6; } +/* Summary Item Direct (No collapse) */ +.summary-item-direct { + border: 1px solid hsl(var(--border)); + border-radius: 0.5rem; + padding: 1rem; + background: hsl(var(--card)); +} + +.summary-item-direct .summary-content-pre { + margin-top: 0.5rem; + padding: 0.75rem; + background: hsl(var(--muted)); + border-radius: 0.375rem; +} + .markdown-content { background: hsl(var(--muted)); padding: 1rem; diff --git a/ccw/src/templates/dashboard.js b/ccw/src/templates/dashboard.js index 6a975fb8..fee91bd9 100644 --- a/ccw/src/templates/dashboard.js +++ b/ccw/src/templates/dashboard.js @@ -943,11 +943,15 @@ function renderContextContent(context) { const techStack = projectContext.tech_stack || metadata.tech_stack || {}; const codingConventions = projectContext.coding_conventions || {}; const architecturePatterns = projectContext.architecture_patterns || []; + const assets = context.assets || {}; + const dependencies = context.dependencies || {}; + const testContext = context.test_context || {}; + const conflictDetection = context.conflict_detection || {}; return `
-
+

Context Package

` : ''} + + + ${Object.keys(assets).length > 0 ? ` +
+

๐Ÿ“š Assets & Resources

+
+ ${renderAssetsSection(assets)} +
+
+ ` : ''} + + + ${(dependencies.internal && dependencies.internal.length > 0) || (dependencies.external && dependencies.external.length > 0) ? ` +
+

๐Ÿ”— Dependencies

+
+ ${renderDependenciesSection(dependencies)} +
+
+ ` : ''} + + + ${Object.keys(testContext).length > 0 ? ` +
+

๐Ÿงช Test Context

+
+ ${renderTestContextSection(testContext)} +
+
+ ` : ''} + + + ${Object.keys(conflictDetection).length > 0 ? ` +
+

โš ๏ธ Conflict Detection & Risk Analysis

+
+ ${renderConflictDetectionSection(conflictDetection)} +
+
+ ` : ''}
`; } @@ -1148,6 +1192,339 @@ function renderCodingConventions(conventions) { return sections.join(''); } +function renderAssetsSection(assets) { + const sections = []; + + // Documentation + if (assets.documentation && assets.documentation.length > 0) { + sections.push(` +
+
๐Ÿ“„ Documentation
+
+ ${assets.documentation.map(doc => ` +
+
+ ${escapeHtml(doc.path)} + ${(doc.relevance_score * 100).toFixed(0)}% +
+
+
${escapeHtml(doc.scope || '')}
+ ${doc.contains && doc.contains.length > 0 ? ` +
+ ${doc.contains.map(tag => `${escapeHtml(tag)}`).join('')} +
+ ` : ''} +
+
+ `).join('')} +
+
+ `); + } + + // Source Code + if (assets.source_code && assets.source_code.length > 0) { + sections.push(` +
+
๐Ÿ’ป Source Code
+
+ ${assets.source_code.map(src => ` +
+
+ ${escapeHtml(src.path)} + ${(src.relevance_score * 100).toFixed(0)}% +
+
+
${escapeHtml(src.role || '')}
+ ${src.exports && src.exports.length > 0 ? ` +
Exports: ${src.exports.map(e => `${escapeHtml(e)}`).join(', ')}
+ ` : ''} + ${src.features && src.features.length > 0 ? ` +
${src.features.map(f => `${escapeHtml(f)}`).join('')}
+ ` : ''} +
+
+ `).join('')} +
+
+ `); + } + + // Tests + if (assets.tests && assets.tests.length > 0) { + sections.push(` +
+
๐Ÿงช Tests
+
+ ${assets.tests.map(test => ` +
+
+ ${escapeHtml(test.path)} + ${test.test_count ? `${test.test_count} tests` : ''} +
+
+
${escapeHtml(test.type || '')}
+ ${test.test_classes ? `
Classes: ${escapeHtml(test.test_classes.join(', '))}
` : ''} + ${test.coverage ? `
Coverage: ${escapeHtml(test.coverage)}
` : ''} +
+
+ `).join('')} +
+
+ `); + } + + return sections.join(''); +} + +function renderDependenciesSection(dependencies) { + const sections = []; + + // Internal Dependencies + if (dependencies.internal && dependencies.internal.length > 0) { + sections.push(` +
+
๐Ÿ”„ Internal Dependencies
+
+ ${dependencies.internal.slice(0, 10).map(dep => ` +
+
${escapeHtml(dep.from)}
+
+ ${escapeHtml(dep.type)} + โ†’ +
+
${escapeHtml(dep.to)}
+
+ `).join('')} + ${dependencies.internal.length > 10 ? `
... and ${dependencies.internal.length - 10} more
` : ''} +
+
+ `); + } + + // External Dependencies + if (dependencies.external && dependencies.external.length > 0) { + sections.push(` +
+
๐Ÿ“ฆ External Dependencies
+
+ ${dependencies.external.map(dep => ` +
+
${escapeHtml(dep.package)}
+
${escapeHtml(dep.version || '')}
+
${escapeHtml(dep.usage || '')}
+
+ `).join('')} +
+
+ `); + } + + return sections.join(''); +} + +function renderTestContextSection(testContext) { + const sections = []; + + // Test Frameworks + if (testContext.frameworks) { + const frameworks = testContext.frameworks; + sections.push(` +
+
๐Ÿ› ๏ธ Test Frameworks
+
+ ${frameworks.backend ? ` +
+
+ Backend + ${escapeHtml(frameworks.backend.name || 'N/A')} +
+ ${frameworks.backend.plugins ? ` +
${frameworks.backend.plugins.map(p => `${escapeHtml(p)}`).join('')}
+ ` : ''} +
+ ` : ''} + ${frameworks.frontend ? ` +
+
+ Frontend + ${escapeHtml(frameworks.frontend.name || 'N/A')} +
+ ${frameworks.frontend.recommended ? `` : ''} + ${frameworks.frontend.gap ? `
โš ๏ธ ${escapeHtml(frameworks.frontend.gap)}
` : ''} +
+ ` : ''} +
+
+ `); + } + + // Existing Tests Statistics + if (testContext.existing_tests) { + const tests = testContext.existing_tests; + let totalTests = 0; + let totalClasses = 0; + + if (tests.backend) { + if (tests.backend.integration) { + totalTests += tests.backend.integration.tests || 0; + totalClasses += tests.backend.integration.classes || 0; + } + if (tests.backend.api_endpoints) { + totalTests += tests.backend.api_endpoints.tests || 0; + totalClasses += tests.backend.api_endpoints.classes || 0; + } + } + + sections.push(` +
+
๐Ÿ“Š Test Statistics
+
+
+
${totalTests}
+
Total Tests
+
+
+
${totalClasses}
+
Test Classes
+
+ ${testContext.coverage_config && testContext.coverage_config.target ? ` +
+
${escapeHtml(testContext.coverage_config.target)}
+
Coverage Target
+
+ ` : ''} +
+
+ `); + } + + // Test Markers + if (testContext.test_markers) { + sections.push(` +
+
๐Ÿท๏ธ Test Markers
+
+ ${Object.entries(testContext.test_markers).map(([marker, desc]) => ` +
+ @${escapeHtml(marker)} + ${escapeHtml(desc)} +
+ `).join('')} +
+
+ `); + } + + return sections.join(''); +} + +function renderConflictDetectionSection(conflictDetection) { + const sections = []; + + // Risk Level Indicator + if (conflictDetection.risk_level) { + const riskLevel = conflictDetection.risk_level; + const riskColor = riskLevel === 'high' ? '#ef4444' : riskLevel === 'medium' ? '#f59e0b' : '#10b981'; + sections.push(` +
+
+ ${escapeHtml(riskLevel.toUpperCase())} RISK +
+ ${conflictDetection.mitigation_strategy ? ` +
+ Mitigation Strategy: ${escapeHtml(conflictDetection.mitigation_strategy)} +
+ ` : ''} +
+ `); + } + + // Risk Factors + if (conflictDetection.risk_factors) { + const factors = conflictDetection.risk_factors; + sections.push(` +
+
โš ๏ธ Risk Factors
+
+ ${factors.test_gaps && factors.test_gaps.length > 0 ? ` +
+ Test Gaps: +
    + ${factors.test_gaps.map(gap => `
  • ${escapeHtml(gap)}
  • `).join('')} +
+
+ ` : ''} + ${factors.existing_implementations && factors.existing_implementations.length > 0 ? ` +
+ Existing Implementations: +
    + ${factors.existing_implementations.map(impl => `
  • ${escapeHtml(impl)}
  • `).join('')} +
+
+ ` : ''} +
+
+ `); + } + + // Affected Modules + if (conflictDetection.affected_modules && conflictDetection.affected_modules.length > 0) { + sections.push(` +
+
๐Ÿ“ฆ Affected Modules
+
+ ${conflictDetection.affected_modules.map(mod => ` + ${escapeHtml(mod)} + `).join('')} +
+
+ `); + } + + // Historical Conflicts + if (conflictDetection.historical_conflicts && conflictDetection.historical_conflicts.length > 0) { + sections.push(` +
+
๐Ÿ“œ Historical Lessons
+
+ ${conflictDetection.historical_conflicts.map(conflict => ` +
+
Source: ${escapeHtml(conflict.source || 'Unknown')}
+ ${conflict.lesson ? `
Lesson: ${escapeHtml(conflict.lesson)}
` : ''} + ${conflict.recommendation ? `
Recommendation: ${escapeHtml(conflict.recommendation)}
` : ''} + ${conflict.challenge ? `
Challenge: ${escapeHtml(conflict.challenge)}
` : ''} +
+ `).join('')} +
+
+ `); + } + + return sections.join(''); +} + +// Helper functions +function getRelevanceColor(score) { + if (score >= 0.95) return '#10b981'; + if (score >= 0.90) return '#3b82f6'; + if (score >= 0.80) return '#f59e0b'; + return '#6b7280'; +} + +function getRoleBadgeClass(role) { + const roleMap = { + 'core-hook': 'primary', + 'api-client': 'success', + 'api-router': 'info', + 'service-layer': 'warning', + 'pydantic-schemas': 'secondary', + 'orm-model': 'secondary', + 'typescript-types': 'info' + }; + return roleMap[role] || 'secondary'; +} + async function loadAndRenderSummaryTab(session, contentArea) { contentArea.innerHTML = '
Loading summaries...
';