Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
320
admin-ui/js/core/debug-inspector.js
Normal file
320
admin-ui/js/core/debug-inspector.js
Normal file
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
* DSS Debug Inspector
|
||||
*
|
||||
* Exposes DSS internal debugging tools to browser console.
|
||||
* Allows self-inspection and troubleshooting without external tools.
|
||||
*
|
||||
* Usage in browser console:
|
||||
* - window.__DSS_DEBUG.auditLogger.getLogs()
|
||||
* - window.__DSS_DEBUG.workflowPersistence.getSnapshots()
|
||||
* - window.__DSS_DEBUG.errorRecovery.getCrashReport()
|
||||
*
|
||||
* Access keyboard shortcut (when implemented):
|
||||
* - Ctrl+Alt+D to open Debug Inspector UI
|
||||
*/
|
||||
|
||||
class DebugInspector {
|
||||
constructor() {
|
||||
this.auditLogger = null;
|
||||
this.workflowPersistence = null;
|
||||
this.errorRecovery = null;
|
||||
this.routeGuards = null;
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize debug inspector with system modules
|
||||
* Call this after all modules are loaded
|
||||
*/
|
||||
initialize(auditLogger, workflowPersistence, errorRecovery, routeGuards) {
|
||||
this.auditLogger = auditLogger;
|
||||
this.workflowPersistence = workflowPersistence;
|
||||
this.errorRecovery = errorRecovery;
|
||||
this.routeGuards = routeGuards;
|
||||
this.initialized = true;
|
||||
|
||||
console.log(
|
||||
'%c[DSS Debug Inspector] Initialized',
|
||||
'color: #0066FF; font-weight: bold;'
|
||||
);
|
||||
console.log(
|
||||
'%cAccess debugging tools: window.__DSS_DEBUG',
|
||||
'color: #666; font-style: italic;'
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick diagnostic report
|
||||
*/
|
||||
quickDiagnosis() {
|
||||
if (!this.initialized) {
|
||||
return { error: 'Debug inspector not initialized' };
|
||||
}
|
||||
|
||||
const recentLogs = this.auditLogger.getLogs().slice(-20);
|
||||
const snapshots = this.workflowPersistence.getSnapshots();
|
||||
const crashReport = this.errorRecovery.getCrashReport();
|
||||
const stats = this.auditLogger.getStats();
|
||||
|
||||
return {
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href,
|
||||
|
||||
// Current state
|
||||
currentSnapshot: snapshots.length > 0 ? snapshots[snapshots.length - 1] : null,
|
||||
|
||||
// Recent activity
|
||||
recentActions: recentLogs.slice(-10).map(log => ({
|
||||
action: log.action,
|
||||
level: log.level,
|
||||
category: log.category,
|
||||
timestamp: new Date(log.timestamp).toLocaleTimeString()
|
||||
})),
|
||||
|
||||
// Error status
|
||||
hasCrash: crashReport.crashDetected,
|
||||
lastError: crashReport.crashDetected ? {
|
||||
category: crashReport.errorCategory,
|
||||
message: crashReport.error?.message
|
||||
} : null,
|
||||
|
||||
// Stats
|
||||
totalLogsRecorded: stats.total,
|
||||
logsByCategory: stats.byCategory,
|
||||
logsByLevel: stats.byLevel,
|
||||
|
||||
// Recovery
|
||||
availableRecoveryPoints: crashReport.recoveryPoints?.length || 0,
|
||||
savedSnapshots: snapshots.length
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted console output
|
||||
*/
|
||||
printDiagnosis() {
|
||||
const diagnosis = this.quickDiagnosis();
|
||||
|
||||
if (diagnosis.error) {
|
||||
console.error(`%c❌ ${diagnosis.error}`, 'color: #FF0000; font-weight: bold;');
|
||||
return;
|
||||
}
|
||||
|
||||
console.group('%c📊 DSS Diagnostic Report', 'color: #0066FF; font-weight: bold; font-size: 14px;');
|
||||
|
||||
// Current state
|
||||
console.group('%cCurrent State', 'color: #FF6B00; font-weight: bold;');
|
||||
console.log('User:', diagnosis.currentSnapshot?.state?.user);
|
||||
console.log('Team:', diagnosis.currentSnapshot?.state?.team);
|
||||
console.log('Current Page:', diagnosis.currentSnapshot?.state?.currentPage);
|
||||
console.log('Figma Connected:', diagnosis.currentSnapshot?.state?.figmaConnected);
|
||||
console.groupEnd();
|
||||
|
||||
// Recent activity
|
||||
console.group('%cRecent Activity (Last 10)', 'color: #00B600; font-weight: bold;');
|
||||
console.table(diagnosis.recentActions);
|
||||
console.groupEnd();
|
||||
|
||||
// Error status
|
||||
if (diagnosis.hasCrash) {
|
||||
console.group('%c⚠️ Crash Detected', 'color: #FF0000; font-weight: bold;');
|
||||
console.log('Category:', diagnosis.lastError.category);
|
||||
console.log('Message:', diagnosis.lastError.message);
|
||||
console.log('Recovery Points Available:', diagnosis.availableRecoveryPoints);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.log('%c✅ No crashes detected', 'color: #00B600;');
|
||||
}
|
||||
|
||||
// Stats
|
||||
console.group('%cStatistics', 'color: #666; font-weight: bold;');
|
||||
console.log('Total Logs:', diagnosis.totalLogsRecorded);
|
||||
console.table(diagnosis.logsByCategory);
|
||||
console.groupEnd();
|
||||
|
||||
console.groupEnd();
|
||||
|
||||
return diagnosis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search audit logs with flexible filtering
|
||||
*/
|
||||
findLogs(pattern) {
|
||||
if (!this.auditLogger) {
|
||||
console.error('Audit logger not initialized');
|
||||
return [];
|
||||
}
|
||||
|
||||
const allLogs = this.auditLogger.getLogs();
|
||||
|
||||
if (typeof pattern === 'string') {
|
||||
// Search by action or message content
|
||||
return allLogs.filter(log =>
|
||||
log.action.includes(pattern) ||
|
||||
JSON.stringify(log.details).toLowerCase().includes(pattern.toLowerCase())
|
||||
);
|
||||
} else if (typeof pattern === 'object') {
|
||||
// Filter by object criteria
|
||||
return allLogs.filter(log => {
|
||||
for (const [key, value] of Object.entries(pattern)) {
|
||||
if (key === 'timeRange') {
|
||||
if (log.timestamp < value.start || log.timestamp > value.end) {
|
||||
return false;
|
||||
}
|
||||
} else if (log[key] !== value && log.details[key] !== value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get performance metrics from audit logs
|
||||
*/
|
||||
getPerformanceMetrics() {
|
||||
if (!this.auditLogger) {
|
||||
return { error: 'Audit logger not initialized' };
|
||||
}
|
||||
|
||||
const apiCalls = this.auditLogger.getLogs({
|
||||
action: 'api_call'
|
||||
});
|
||||
|
||||
const slowCalls = apiCalls.filter(log => log.details.duration > 1000);
|
||||
const failedCalls = apiCalls.filter(log => log.details.status >= 400);
|
||||
|
||||
return {
|
||||
totalApiCalls: apiCalls.length,
|
||||
averageResponseTime: apiCalls.reduce((sum, log) => sum + (log.details.duration || 0), 0) / apiCalls.length || 0,
|
||||
slowCalls: slowCalls.length,
|
||||
failedCalls: failedCalls.length,
|
||||
slowCallDetails: slowCalls.map(log => ({
|
||||
endpoint: log.details.endpoint,
|
||||
method: log.details.method,
|
||||
duration: log.details.duration,
|
||||
status: log.details.status
|
||||
})),
|
||||
failedCallDetails: failedCalls.map(log => ({
|
||||
endpoint: log.details.endpoint,
|
||||
method: log.details.method,
|
||||
status: log.details.status,
|
||||
error: log.details.error
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all debugging data
|
||||
*/
|
||||
exportDebugData() {
|
||||
if (!this.initialized) {
|
||||
console.error('Debug inspector not initialized');
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = {
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href,
|
||||
browser: navigator.userAgent,
|
||||
|
||||
auditLogs: this.auditLogger.getLogs(),
|
||||
auditStats: this.auditLogger.getStats(),
|
||||
|
||||
snapshots: this.workflowPersistence.getSnapshots(),
|
||||
|
||||
crashReport: this.errorRecovery.getCrashReport(),
|
||||
|
||||
performance: this.getPerformanceMetrics(),
|
||||
|
||||
diagnosis: this.quickDiagnosis()
|
||||
};
|
||||
|
||||
// Copy to clipboard
|
||||
const json = JSON.stringify(data, null, 2);
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(json).then(() => {
|
||||
console.log('%c✅ Debug data copied to clipboard', 'color: #00B600; font-weight: bold;');
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print helpful guide
|
||||
*/
|
||||
help() {
|
||||
console.log(`
|
||||
%c╔════════════════════════════════════════════╗
|
||||
║ DSS Debug Inspector - Quick Reference ║
|
||||
╚════════════════════════════════════════════╝
|
||||
|
||||
%c📊 DIAGNOSTICS
|
||||
%c __DSS_DEBUG.printDiagnosis()
|
||||
%c Shows quick overview of system state, recent activity, errors
|
||||
|
||||
%c🔍 SEARCH & FILTER
|
||||
%c __DSS_DEBUG.findLogs('action-name')
|
||||
%c __DSS_DEBUG.findLogs({ action: 'api_call', level: 'error' })
|
||||
%c Find logs by string pattern or filter object
|
||||
|
||||
%c💾 SNAPSHOTS
|
||||
%c __DSS_DEBUG.workflowPersistence.getSnapshots()
|
||||
%c __DSS_DEBUG.workflowPersistence.restoreSnapshot('id')
|
||||
%c View and restore application state
|
||||
|
||||
%c⚠️ ERRORS & RECOVERY
|
||||
%c __DSS_DEBUG.errorRecovery.getCrashReport()
|
||||
%c __DSS_DEBUG.errorRecovery.recover('recovery-point-id')
|
||||
%c Analyze crashes and recover to known good state
|
||||
|
||||
%c⚡ PERFORMANCE
|
||||
%c __DSS_DEBUG.getPerformanceMetrics()
|
||||
%c Get API response times, slow calls, failures
|
||||
|
||||
%c📥 EXPORT
|
||||
%c __DSS_DEBUG.exportDebugData()
|
||||
%c Export everything for offline analysis (copies to clipboard)
|
||||
|
||||
%cFor detailed documentation, see:
|
||||
%c .dss/DSS_SELF_DEBUG_METHODOLOGY.md
|
||||
`,
|
||||
'color: #0066FF; font-weight: bold; font-size: 12px;',
|
||||
'color: #FF6B00; font-weight: bold;',
|
||||
'color: #666;',
|
||||
'color: #0066FF; font-weight: bold;',
|
||||
'color: #FF6B00; font-weight: bold;',
|
||||
'color: #666;',
|
||||
'color: #0066FF; font-weight: bold;',
|
||||
'color: #FF6B00; font-weight: bold;',
|
||||
'color: #666;',
|
||||
'color: #0066FF; font-weight: bold;',
|
||||
'color: #FF6B00; font-weight: bold;',
|
||||
'color: #666;',
|
||||
'color: #0066FF; font-weight: bold;',
|
||||
'color: #FF6B00; font-weight: bold;',
|
||||
'color: #666;',
|
||||
'color: #0066FF; font-weight: bold;',
|
||||
'color: #FF6B00; font-weight: bold;',
|
||||
'color: #666;',
|
||||
'color: #666; font-style: italic;'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
export const debugInspector = new DebugInspector();
|
||||
|
||||
// Make available globally
|
||||
if (typeof window !== 'undefined') {
|
||||
window.__DSS_DEBUG = debugInspector;
|
||||
}
|
||||
|
||||
export default debugInspector;
|
||||
Reference in New Issue
Block a user