claude-code-workflow 6.0.5 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.claude/agents/action-planning-agent.md +1 -1
  2. package/.claude/agents/cli-execution-agent.md +269 -269
  3. package/.claude/agents/cli-explore-agent.md +182 -182
  4. package/.claude/agents/context-search-agent.md +582 -582
  5. package/.claude/agents/memory-bridge.md +93 -93
  6. package/.claude/commands/cli/cli-init.md +1 -1
  7. package/.claude/commands/memory/docs-full-cli.md +471 -471
  8. package/.claude/commands/memory/docs-related-cli.md +386 -386
  9. package/.claude/commands/memory/docs.md +615 -615
  10. package/.claude/commands/memory/load.md +1 -1
  11. package/.claude/commands/memory/update-full.md +332 -332
  12. package/.claude/commands/memory/update-related.md +5 -5
  13. package/.claude/commands/workflow/init.md +1 -1
  14. package/.claude/commands/workflow/lite-fix.md +621 -621
  15. package/.claude/commands/workflow/lite-plan.md +592 -592
  16. package/.claude/commands/workflow/tools/context-gather.md +434 -434
  17. package/.claude/commands/workflow/ui-design/generate.md +504 -504
  18. package/.claude/commands/workflow/ui-design/import-from-code.md +537 -537
  19. package/.claude/scripts/classify-folders.sh +4 -0
  20. package/.claude/scripts/convert_tokens_to_css.sh +4 -0
  21. package/.claude/scripts/detect_changed_modules.sh +5 -1
  22. package/.claude/scripts/discover-design-files.sh +87 -83
  23. package/.claude/scripts/generate_module_docs.sh +717 -713
  24. package/.claude/scripts/get_modules_by_depth.sh +5 -1
  25. package/.claude/scripts/ui-generate-preview.sh +4 -0
  26. package/.claude/scripts/ui-instantiate-prototypes.sh +4 -0
  27. package/.claude/scripts/update_module_claude.sh +4 -0
  28. package/.claude/skills/command-guide/index/all-commands.json +1 -12
  29. package/.claude/skills/command-guide/index/by-category.json +1 -12
  30. package/.claude/skills/command-guide/index/by-use-case.json +1 -12
  31. package/.claude/skills/command-guide/index/essential-commands.json +1 -12
  32. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +127 -71
  33. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +269 -269
  34. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +182 -182
  35. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +18 -38
  36. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +582 -577
  37. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
  38. package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +1 -1
  39. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
  40. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
  41. package/.claude/skills/command-guide/reference/commands/memory/docs.md +615 -610
  42. package/.claude/skills/command-guide/reference/commands/memory/load.md +1 -1
  43. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
  44. package/.claude/skills/command-guide/reference/commands/memory/update-related.md +5 -5
  45. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +299 -451
  46. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +14 -37
  47. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +252 -350
  48. package/.claude/skills/command-guide/reference/commands/workflow/init.md +2 -2
  49. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +52 -0
  50. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +621 -602
  51. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +46 -36
  52. package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +18 -58
  53. package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +22 -52
  54. package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +19 -48
  55. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +25 -5
  56. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +1 -1
  57. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +7 -7
  58. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
  59. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +151 -11
  60. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +4 -4
  61. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +1 -1
  62. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +504 -504
  63. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +537 -537
  64. package/.claude/workflows/context-search-strategy.md +77 -77
  65. package/.claude/workflows/tool-strategy.md +90 -71
  66. package/.claude/workflows/workflow-architecture.md +1 -1
  67. package/README.md +285 -285
  68. package/ccw/src/cli.js +7 -0
  69. package/ccw/src/commands/tool.js +217 -0
  70. package/ccw/src/core/dashboard-generator.js +18 -3
  71. package/ccw/src/core/lite-scanner.js +35 -11
  72. package/ccw/src/core/server.js +531 -46
  73. package/ccw/src/templates/dashboard-css/01-base.css +161 -0
  74. package/ccw/src/templates/dashboard-css/02-session.css +726 -0
  75. package/ccw/src/templates/dashboard-css/03-tasks.css +512 -0
  76. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +843 -0
  77. package/ccw/src/templates/dashboard-css/05-context.css +2206 -0
  78. package/ccw/src/templates/dashboard-css/06-cards.css +1570 -0
  79. package/ccw/src/templates/dashboard-css/07-managers.css +936 -0
  80. package/ccw/src/templates/dashboard-css/08-review.css +1266 -0
  81. package/ccw/src/templates/dashboard-css/09-explorer.css +1397 -0
  82. package/ccw/src/templates/dashboard-js/components/global-notifications.js +219 -0
  83. package/ccw/src/templates/dashboard-js/components/hook-manager.js +10 -0
  84. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +11 -1
  85. package/ccw/src/templates/dashboard-js/components/navigation.js +11 -5
  86. package/ccw/src/templates/dashboard-js/components/tabs-context.js +20 -20
  87. package/ccw/src/templates/dashboard-js/components/tabs-other.js +11 -11
  88. package/ccw/src/templates/dashboard-js/components/theme.js +29 -1
  89. package/ccw/src/templates/dashboard-js/main.js +4 -0
  90. package/ccw/src/templates/dashboard-js/state.js +5 -0
  91. package/ccw/src/templates/dashboard-js/views/explorer.js +852 -0
  92. package/ccw/src/templates/dashboard-js/views/home.js +13 -9
  93. package/ccw/src/templates/dashboard-js/views/hook-manager.js +8 -5
  94. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +21 -16
  95. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +90 -19
  96. package/ccw/src/templates/dashboard-js/views/project-overview.js +15 -11
  97. package/ccw/src/templates/dashboard-js/views/review-session.js +3 -3
  98. package/ccw/src/templates/dashboard-js/views/session-detail.js +38 -28
  99. package/ccw/src/templates/dashboard.html +129 -28
  100. package/ccw/src/tools/classify-folders.js +204 -0
  101. package/ccw/src/tools/convert-tokens-to-css.js +250 -0
  102. package/ccw/src/tools/detect-changed-modules.js +288 -0
  103. package/ccw/src/tools/discover-design-files.js +134 -0
  104. package/ccw/src/tools/edit-file.js +266 -0
  105. package/ccw/src/tools/generate-module-docs.js +416 -0
  106. package/ccw/src/tools/get-modules-by-depth.js +308 -0
  107. package/ccw/src/tools/index.js +176 -0
  108. package/ccw/src/tools/ui-generate-preview.js +327 -0
  109. package/ccw/src/tools/ui-instantiate-prototypes.js +301 -0
  110. package/ccw/src/tools/update-module-claude.js +380 -0
  111. package/package.json +1 -1
  112. package/.claude/skills/command-guide/reference/commands/workflow/status.md +0 -352
  113. package/ccw/src/core/server.js.bak +0 -385
  114. package/ccw/src/core/server_original.bak +0 -385
  115. package/ccw/src/templates/dashboard.css +0 -8187
  116. package/ccw/src/templates/dashboard_tailwind.html +0 -42
  117. package/ccw/src/templates/dashboard_test.html +0 -37
  118. package/ccw/src/templates/tailwind-base.css +0 -212
@@ -0,0 +1,219 @@
1
+ // ==========================================
2
+ // GLOBAL NOTIFICATION SYSTEM
3
+ // ==========================================
4
+ // Floating notification panel accessible from any view
5
+
6
+ /**
7
+ * Initialize global notification panel
8
+ */
9
+ function initGlobalNotifications() {
10
+ // Create FAB and panel if not exists
11
+ if (!document.getElementById('globalNotificationFab')) {
12
+ const fabHtml = `
13
+ <div class="global-notif-fab" id="globalNotificationFab" onclick="toggleGlobalNotifications()" title="Notifications">
14
+ <span class="fab-icon">🔔</span>
15
+ <span class="fab-badge" id="globalNotifBadge">0</span>
16
+ </div>
17
+
18
+ <div class="global-notif-panel" id="globalNotificationPanel">
19
+ <div class="global-notif-header">
20
+ <span class="global-notif-title">🔔 Notifications</span>
21
+ <button class="global-notif-close" onclick="toggleGlobalNotifications()">×</button>
22
+ </div>
23
+ <div class="global-notif-actions">
24
+ <button class="notif-action-btn" onclick="clearGlobalNotifications()">
25
+ <span>🗑️</span> Clear All
26
+ </button>
27
+ </div>
28
+ <div class="global-notif-list" id="globalNotificationList">
29
+ <div class="global-notif-empty">
30
+ <span>No notifications</span>
31
+ <p>System events and task updates will appear here</p>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ `;
36
+
37
+ const container = document.createElement('div');
38
+ container.id = 'globalNotificationContainer';
39
+ container.innerHTML = fabHtml;
40
+ document.body.appendChild(container);
41
+ }
42
+
43
+ renderGlobalNotifications();
44
+ }
45
+
46
+ /**
47
+ * Toggle notification panel visibility
48
+ */
49
+ function toggleGlobalNotifications() {
50
+ isNotificationPanelVisible = !isNotificationPanelVisible;
51
+ const panel = document.getElementById('globalNotificationPanel');
52
+ const fab = document.getElementById('globalNotificationFab');
53
+
54
+ if (panel && fab) {
55
+ if (isNotificationPanelVisible) {
56
+ panel.classList.add('show');
57
+ fab.classList.add('active');
58
+ } else {
59
+ panel.classList.remove('show');
60
+ fab.classList.remove('active');
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Add a global notification
67
+ * @param {string} type - 'info', 'success', 'warning', 'error'
68
+ * @param {string} message - Main notification message
69
+ * @param {string} details - Optional details
70
+ * @param {string} source - Optional source identifier (e.g., 'explorer', 'mcp')
71
+ */
72
+ function addGlobalNotification(type, message, details = null, source = null) {
73
+ const notification = {
74
+ id: Date.now(),
75
+ type,
76
+ message,
77
+ details,
78
+ source,
79
+ timestamp: new Date().toISOString(),
80
+ read: false
81
+ };
82
+
83
+ globalNotificationQueue.unshift(notification);
84
+
85
+ // Keep only last 100 notifications
86
+ if (globalNotificationQueue.length > 100) {
87
+ globalNotificationQueue = globalNotificationQueue.slice(0, 100);
88
+ }
89
+
90
+ renderGlobalNotifications();
91
+ updateGlobalNotifBadge();
92
+
93
+ // Show toast for important notifications
94
+ if (type === 'error' || type === 'success') {
95
+ showNotificationToast(notification);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Show a brief toast notification
101
+ */
102
+ function showNotificationToast(notification) {
103
+ const typeIcon = {
104
+ 'info': 'ℹ️',
105
+ 'success': '✅',
106
+ 'warning': '⚠️',
107
+ 'error': '❌'
108
+ }[notification.type] || 'ℹ️';
109
+
110
+ // Remove existing toast
111
+ const existing = document.querySelector('.notif-toast');
112
+ if (existing) existing.remove();
113
+
114
+ const toast = document.createElement('div');
115
+ toast.className = `notif-toast type-${notification.type}`;
116
+ toast.innerHTML = `
117
+ <span class="toast-icon">${typeIcon}</span>
118
+ <span class="toast-message">${escapeHtml(notification.message)}</span>
119
+ `;
120
+ document.body.appendChild(toast);
121
+
122
+ // Animate in
123
+ requestAnimationFrame(() => toast.classList.add('show'));
124
+
125
+ // Auto-remove
126
+ setTimeout(() => {
127
+ toast.classList.remove('show');
128
+ setTimeout(() => toast.remove(), 300);
129
+ }, 3000);
130
+ }
131
+
132
+ /**
133
+ * Render notification list
134
+ */
135
+ function renderGlobalNotifications() {
136
+ const listEl = document.getElementById('globalNotificationList');
137
+ if (!listEl) return;
138
+
139
+ if (globalNotificationQueue.length === 0) {
140
+ listEl.innerHTML = `
141
+ <div class="global-notif-empty">
142
+ <span>No notifications</span>
143
+ <p>System events and task updates will appear here</p>
144
+ </div>
145
+ `;
146
+ return;
147
+ }
148
+
149
+ listEl.innerHTML = globalNotificationQueue.map(notif => {
150
+ const typeIcon = {
151
+ 'info': 'ℹ️',
152
+ 'success': '✅',
153
+ 'warning': '⚠️',
154
+ 'error': '❌'
155
+ }[notif.type] || 'ℹ️';
156
+
157
+ const time = formatNotifTime(notif.timestamp);
158
+ const sourceLabel = notif.source ? `<span class="notif-source">${notif.source}</span>` : '';
159
+
160
+ return `
161
+ <div class="global-notif-item type-${notif.type} ${notif.read ? 'read' : ''}" data-id="${notif.id}">
162
+ <div class="notif-item-header">
163
+ <span class="notif-icon">${typeIcon}</span>
164
+ <span class="notif-message">${escapeHtml(notif.message)}</span>
165
+ ${sourceLabel}
166
+ </div>
167
+ ${notif.details ? `<div class="notif-details">${escapeHtml(notif.details)}</div>` : ''}
168
+ <div class="notif-meta">
169
+ <span class="notif-time">${time}</span>
170
+ </div>
171
+ </div>
172
+ `;
173
+ }).join('');
174
+ }
175
+
176
+ /**
177
+ * Format notification time
178
+ */
179
+ function formatNotifTime(timestamp) {
180
+ const date = new Date(timestamp);
181
+ const now = new Date();
182
+ const diff = now - date;
183
+
184
+ if (diff < 60000) return 'Just now';
185
+ if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
186
+ if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
187
+ return date.toLocaleDateString();
188
+ }
189
+
190
+ /**
191
+ * Update notification badge
192
+ */
193
+ function updateGlobalNotifBadge() {
194
+ const badge = document.getElementById('globalNotifBadge');
195
+ if (badge) {
196
+ const unreadCount = globalNotificationQueue.filter(n => !n.read).length;
197
+ badge.textContent = unreadCount;
198
+ badge.style.display = unreadCount > 0 ? 'flex' : 'none';
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Clear all notifications
204
+ */
205
+ function clearGlobalNotifications() {
206
+ globalNotificationQueue = [];
207
+ renderGlobalNotifications();
208
+ updateGlobalNotifBadge();
209
+ }
210
+
211
+ /**
212
+ * Mark all as read
213
+ */
214
+ function markAllNotificationsRead() {
215
+ globalNotificationQueue.forEach(n => n.read = true);
216
+ renderGlobalNotifications();
217
+ updateGlobalNotifBadge();
218
+ }
219
+
@@ -271,3 +271,13 @@ function getHookEventIcon(event) {
271
271
  };
272
272
  return icons[event] || '🪝';
273
273
  }
274
+
275
+ function getHookEventIconLucide(event) {
276
+ const icons = {
277
+ 'PreToolUse': '<i data-lucide="clock" class="w-5 h-5"></i>',
278
+ 'PostToolUse': '<i data-lucide="check-circle" class="w-5 h-5"></i>',
279
+ 'Notification': '<i data-lucide="bell" class="w-5 h-5"></i>',
280
+ 'Stop': '<i data-lucide="octagon-x" class="w-5 h-5"></i>'
281
+ };
282
+ return icons[event] || '<i data-lucide="webhook" class="w-5 h-5"></i>';
283
+ }
@@ -1,11 +1,18 @@
1
1
  // MCP Manager Component
2
- // Manages MCP server configuration from .claude.json
2
+ // Manages MCP server configuration from multiple sources:
3
+ // - Enterprise: managed-mcp.json (highest priority)
4
+ // - User: ~/.claude.json mcpServers
5
+ // - Project: .mcp.json in project root
6
+ // - Local: ~/.claude.json projects[path].mcpServers
3
7
 
4
8
  // ========== MCP State ==========
5
9
  let mcpConfig = null;
6
10
  let mcpAllProjects = {};
7
11
  let mcpGlobalServers = {};
12
+ let mcpUserServers = {};
13
+ let mcpEnterpriseServers = {};
8
14
  let mcpCurrentProjectServers = {};
15
+ let mcpConfigSources = [];
9
16
  let mcpCreateMode = 'form'; // 'form' or 'json'
10
17
 
11
18
  // ========== Initialization ==========
@@ -33,6 +40,9 @@ async function loadMcpConfig() {
33
40
  mcpConfig = data;
34
41
  mcpAllProjects = data.projects || {};
35
42
  mcpGlobalServers = data.globalServers || {};
43
+ mcpUserServers = data.userServers || {};
44
+ mcpEnterpriseServers = data.enterpriseServers || {};
45
+ mcpConfigSources = data.configSources || [];
36
46
 
37
47
  // Get current project servers
38
48
  const currentPath = projectPath.replace(/\//g, '\\');
@@ -96,6 +96,8 @@ function initNavigation() {
96
96
  renderMcpManager();
97
97
  } else if (currentView === 'project-overview') {
98
98
  renderProjectOverview();
99
+ } else if (currentView === 'explorer') {
100
+ renderExplorer();
99
101
  }
100
102
  });
101
103
  });
@@ -112,6 +114,8 @@ function updateContentTitle() {
112
114
  titleEl.textContent = 'Project Overview';
113
115
  } else if (currentView === 'mcp-manager') {
114
116
  titleEl.textContent = 'MCP Server Management';
117
+ } else if (currentView === 'explorer') {
118
+ titleEl.textContent = 'File Explorer';
115
119
  } else if (currentView === 'liteTasks') {
116
120
  const names = { 'lite-plan': 'Lite Plan Sessions', 'lite-fix': 'Lite Fix Sessions' };
117
121
  titleEl.textContent = names[currentLiteType] || 'Lite Tasks';
@@ -157,17 +161,19 @@ async function refreshWorkspace() {
157
161
  // Reload data from server
158
162
  const data = await loadDashboardData(projectPath);
159
163
  if (data) {
160
- // Update stores
161
- sessionDataStore = {};
162
- liteTaskDataStore = {};
164
+ // Clear and repopulate stores
165
+ Object.keys(sessionDataStore).forEach(k => delete sessionDataStore[k]);
166
+ Object.keys(liteTaskDataStore).forEach(k => delete liteTaskDataStore[k]);
163
167
 
164
168
  // Populate stores
165
169
  [...(data.activeSessions || []), ...(data.archivedSessions || [])].forEach(s => {
166
- sessionDataStore[s.session_id] = s;
170
+ const sessionKey = `session-${s.session_id}`.replace(/[^a-zA-Z0-9-]/g, '-');
171
+ sessionDataStore[sessionKey] = s;
167
172
  });
168
173
 
169
174
  [...(data.liteTasks?.litePlan || []), ...(data.liteTasks?.liteFix || [])].forEach(s => {
170
- liteTaskDataStore[s.session_id] = s;
175
+ const sessionKey = `lite-${s.session_id}`.replace(/[^a-zA-Z0-9-]/g, '-');
176
+ liteTaskDataStore[sessionKey] = s;
171
177
  });
172
178
 
173
179
  // Update global data
@@ -12,7 +12,7 @@ function renderContextContent(context) {
12
12
  if (!context) {
13
13
  return `
14
14
  <div class="tab-empty-state">
15
- <div class="empty-icon">📦</div>
15
+ <div class="empty-icon"><i data-lucide="package" class="w-12 h-12"></i></div>
16
16
  <div class="empty-title">No Context Data</div>
17
17
  <div class="empty-text">No context-package.json found for this session.</div>
18
18
  </div>
@@ -39,9 +39,9 @@ function renderContextContent(context) {
39
39
  <!-- Header Card -->
40
40
  <div class="ctx-header-card">
41
41
  <div class="ctx-header-content">
42
- <h3 class="ctx-main-title">📦 Context Package</h3>
42
+ <h3 class="ctx-main-title"><i data-lucide="package" class="w-5 h-5 inline mr-2"></i>Context Package</h3>
43
43
  <button class="btn-view-modal" onclick="openMarkdownModal('context-package.json', window._currentContextJson, 'json')">
44
- 👁️ View JSON
44
+ <i data-lucide="eye" class="w-4 h-4 inline mr-1"></i>View JSON
45
45
  </button>
46
46
  </div>
47
47
  </div>
@@ -50,7 +50,7 @@ function renderContextContent(context) {
50
50
  ${metadata.task_description || metadata.session_id ? `
51
51
  <div class="ctx-card">
52
52
  <div class="ctx-card-header">
53
- <span class="ctx-card-icon">📋</span>
53
+ <span class="ctx-card-icon"><i data-lucide="clipboard-list" class="w-5 h-5"></i></span>
54
54
  <h4 class="ctx-card-title">Task Metadata</h4>
55
55
  </div>
56
56
  <div class="ctx-card-body">
@@ -90,7 +90,7 @@ function renderContextContent(context) {
90
90
  ${architecturePatterns.length > 0 ? `
91
91
  <div class="ctx-card">
92
92
  <div class="ctx-card-header">
93
- <span class="ctx-card-icon">🏛️</span>
93
+ <span class="ctx-card-icon"><i data-lucide="building-2" class="w-5 h-5"></i></span>
94
94
  <h4 class="ctx-card-title">Architecture Patterns</h4>
95
95
  <span class="ctx-count-badge">${architecturePatterns.length}</span>
96
96
  </div>
@@ -106,7 +106,7 @@ function renderContextContent(context) {
106
106
  ${Object.keys(techStack).length > 0 ? `
107
107
  <div class="ctx-card">
108
108
  <div class="ctx-card-header">
109
- <span class="ctx-card-icon">💻</span>
109
+ <span class="ctx-card-icon"><i data-lucide="code-2" class="w-5 h-5"></i></span>
110
110
  <h4 class="ctx-card-title">Technology Stack</h4>
111
111
  </div>
112
112
  <div class="ctx-card-body">
@@ -119,7 +119,7 @@ function renderContextContent(context) {
119
119
  ${Object.keys(codingConventions).length > 0 ? `
120
120
  <div class="ctx-card">
121
121
  <div class="ctx-card-header">
122
- <span class="ctx-card-icon">📝</span>
122
+ <span class="ctx-card-icon"><i data-lucide="file-code" class="w-5 h-5"></i></span>
123
123
  <h4 class="ctx-card-title">Coding Conventions</h4>
124
124
  </div>
125
125
  <div class="ctx-card-body">
@@ -145,7 +145,7 @@ function renderContextContent(context) {
145
145
  ${(dependencies.internal && dependencies.internal.length > 0) || (dependencies.external && dependencies.external.length > 0) ? `
146
146
  <div class="ctx-card">
147
147
  <div class="ctx-card-header">
148
- <span class="ctx-card-icon">🔗</span>
148
+ <span class="ctx-card-icon"><i data-lucide="link" class="w-5 h-5"></i></span>
149
149
  <h4 class="ctx-card-title">Dependencies</h4>
150
150
  </div>
151
151
  <div class="ctx-card-body">
@@ -158,7 +158,7 @@ function renderContextContent(context) {
158
158
  ${Object.keys(testContext).length > 0 ? `
159
159
  <div class="ctx-card">
160
160
  <div class="ctx-card-header">
161
- <span class="ctx-card-icon">🧪</span>
161
+ <span class="ctx-card-icon"><i data-lucide="flask-conical" class="w-5 h-5"></i></span>
162
162
  <h4 class="ctx-card-title">Test Context</h4>
163
163
  </div>
164
164
  <div class="ctx-card-body">
@@ -314,7 +314,7 @@ function renderAssetsCards(assets) {
314
314
  sections.push(`
315
315
  <div class="ctx-assets-category">
316
316
  <div class="ctx-assets-cat-header">
317
- <span class="ctx-assets-cat-icon">📄</span>
317
+ <span class="ctx-assets-cat-icon"><i data-lucide="file-text" class="w-4 h-4"></i></span>
318
318
  <span class="ctx-assets-cat-title">Documentation</span>
319
319
  <span class="ctx-assets-cat-count">${assets.documentation.length}</span>
320
320
  </div>
@@ -335,7 +335,7 @@ function renderAssetsCards(assets) {
335
335
  sections.push(`
336
336
  <div class="ctx-assets-category">
337
337
  <div class="ctx-assets-cat-header">
338
- <span class="ctx-assets-cat-icon">💻</span>
338
+ <span class="ctx-assets-cat-icon"><i data-lucide="code-2" class="w-4 h-4"></i></span>
339
339
  <span class="ctx-assets-cat-title">Source Code</span>
340
340
  <span class="ctx-assets-cat-count">${assets.source_code.length}</span>
341
341
  </div>
@@ -356,7 +356,7 @@ function renderAssetsCards(assets) {
356
356
  sections.push(`
357
357
  <div class="ctx-assets-category">
358
358
  <div class="ctx-assets-cat-header">
359
- <span class="ctx-assets-cat-icon">🧪</span>
359
+ <span class="ctx-assets-cat-icon"><i data-lucide="flask-conical" class="w-4 h-4"></i></span>
360
360
  <span class="ctx-assets-cat-title">Tests</span>
361
361
  <span class="ctx-assets-cat-count">${assets.tests.length}</span>
362
362
  </div>
@@ -657,7 +657,7 @@ function renderAssetsSection(assets) {
657
657
  if (assets.documentation && assets.documentation.length > 0) {
658
658
  sections.push(`
659
659
  <div class="asset-category">
660
- <h5 class="asset-category-title">📄 Documentation</h5>
660
+ <h5 class="asset-category-title"><i data-lucide="file-text" class="w-4 h-4 inline mr-1"></i>Documentation</h5>
661
661
  <div class="asset-grid">
662
662
  ${assets.documentation.map(doc => `
663
663
  <div class="asset-card">
@@ -684,7 +684,7 @@ function renderAssetsSection(assets) {
684
684
  if (assets.source_code && assets.source_code.length > 0) {
685
685
  sections.push(`
686
686
  <div class="asset-category">
687
- <h5 class="asset-category-title">💻 Source Code</h5>
687
+ <h5 class="asset-category-title"><i data-lucide="code-2" class="w-4 h-4 inline mr-1"></i>Source Code</h5>
688
688
  <div class="asset-grid">
689
689
  ${assets.source_code.map(src => `
690
690
  <div class="asset-card">
@@ -712,7 +712,7 @@ function renderAssetsSection(assets) {
712
712
  if (assets.tests && assets.tests.length > 0) {
713
713
  sections.push(`
714
714
  <div class="asset-category">
715
- <h5 class="asset-category-title">🧪 Tests</h5>
715
+ <h5 class="asset-category-title"><i data-lucide="flask-conical" class="w-4 h-4 inline mr-1"></i>Tests</h5>
716
716
  <div class="asset-grid">
717
717
  ${assets.tests.map(test => `
718
718
  <div class="asset-card">
@@ -764,7 +764,7 @@ function renderDependenciesSection(dependencies) {
764
764
  if (dependencies.external && dependencies.external.length > 0) {
765
765
  sections.push(`
766
766
  <div class="dep-category">
767
- <h5 class="dep-category-title">📦 External Dependencies</h5>
767
+ <h5 class="dep-category-title"><i data-lucide="package" class="w-4 h-4 inline mr-1"></i>External Dependencies</h5>
768
768
  <div class="dep-grid">
769
769
  ${dependencies.external.map(dep => `
770
770
  <div class="dep-external-card">
@@ -836,7 +836,7 @@ function renderTestContextSection(testContext) {
836
836
 
837
837
  sections.push(`
838
838
  <div class="test-category">
839
- <h5 class="test-category-title">📊 Test Statistics</h5>
839
+ <h5 class="test-category-title"><i data-lucide="bar-chart-3" class="w-4 h-4 inline mr-1"></i>Test Statistics</h5>
840
840
  <div class="test-stats-grid">
841
841
  <div class="stat-card">
842
842
  <div class="stat-value">${totalTests}</div>
@@ -930,7 +930,7 @@ function renderConflictDetectionSection(conflictDetection) {
930
930
  if (conflictDetection.affected_modules && conflictDetection.affected_modules.length > 0) {
931
931
  sections.push(`
932
932
  <div class="conflict-category">
933
- <h5 class="conflict-category-title">📦 Affected Modules</h5>
933
+ <h5 class="conflict-category-title"><i data-lucide="package-open" class="w-4 h-4 inline mr-1"></i>Affected Modules</h5>
934
934
  <div class="affected-modules-grid">
935
935
  ${conflictDetection.affected_modules.map(mod => `
936
936
  <span class="affected-module-tag">${escapeHtml(mod)}</span>
@@ -996,7 +996,7 @@ function renderSessionContextContent(context, explorations, conflictResolution)
996
996
 
997
997
  return `
998
998
  <div class="tab-empty-state">
999
- <div class="empty-icon">📦</div>
999
+ <div class="empty-icon"><i data-lucide="package" class="w-12 h-12"></i></div>
1000
1000
  <div class="empty-title">No Context Data</div>
1001
1001
  <div class="empty-text">No context-package.json or exploration files found for this session.</div>
1002
1002
  </div>
@@ -1033,7 +1033,7 @@ function renderConflictResolutionContext(conflictResolution) {
1033
1033
  <div class="conflict-decisions-section collapsible-section">
1034
1034
  <div class="collapsible-header">
1035
1035
  <span class="collapse-icon">▶</span>
1036
- <span class="section-label">🎯 User Decisions (${decisions.length})</span>
1036
+ <span class="section-label"><i data-lucide="target" class="w-4 h-4 inline mr-1"></i>User Decisions (${decisions.length})</span>
1037
1037
  </div>
1038
1038
  <div class="collapsible-content collapsed">
1039
1039
  <div class="decisions-list">
@@ -11,7 +11,7 @@ function renderSummaryContent(summaries) {
11
11
  if (!summaries || summaries.length === 0) {
12
12
  return `
13
13
  <div class="tab-empty-state">
14
- <div class="empty-icon">📝</div>
14
+ <div class="empty-icon"><i data-lucide="file-text" class="w-12 h-12"></i></div>
15
15
  <div class="empty-title">No Summaries</div>
16
16
  <div class="empty-text">No summaries found in .summaries/</div>
17
17
  </div>
@@ -31,9 +31,9 @@ function renderSummaryContent(summaries) {
31
31
  return `
32
32
  <div class="summary-item-card">
33
33
  <div class="summary-item-header">
34
- <h4 class="summary-item-title">📄 ${escapeHtml(s.name || 'Summary')}</h4>
34
+ <h4 class="summary-item-title"><i data-lucide="file-text" class="w-4 h-4 inline mr-1"></i>${escapeHtml(s.name || 'Summary')}</h4>
35
35
  <button class="btn-view-modal" onclick="openMarkdownModal('${escapeHtml(s.name || 'Summary')}', window._currentSummaries[${idx}].content, 'markdown');">
36
- 👁️ View
36
+ <i data-lucide="eye" class="w-4 h-4 inline mr-1"></i>View
37
37
  </button>
38
38
  </div>
39
39
  <div class="summary-item-preview">
@@ -54,7 +54,7 @@ function renderImplPlanContent(implPlan) {
54
54
  if (!implPlan) {
55
55
  return `
56
56
  <div class="tab-empty-state">
57
- <div class="empty-icon">📐</div>
57
+ <div class="empty-icon"><i data-lucide="ruler" class="w-12 h-12"></i></div>
58
58
  <div class="empty-title">No IMPL Plan</div>
59
59
  <div class="empty-text">No IMPL_PLAN.md found for this session.</div>
60
60
  </div>
@@ -73,9 +73,9 @@ function renderImplPlanContent(implPlan) {
73
73
  <div class="impl-plan-tab-content">
74
74
  <div class="impl-plan-card">
75
75
  <div class="impl-plan-header">
76
- <h3 class="impl-plan-title">📐 Implementation Plan</h3>
76
+ <h3 class="impl-plan-title"><i data-lucide="ruler" class="w-5 h-5 inline mr-2"></i>Implementation Plan</h3>
77
77
  <button class="btn-view-modal" onclick="openMarkdownModal('IMPL_PLAN.md', window._currentImplPlan, 'markdown')">
78
- 👁️ View
78
+ <i data-lucide="eye" class="w-4 h-4 inline mr-1"></i>View
79
79
  </button>
80
80
  </div>
81
81
  <div class="impl-plan-preview">
@@ -151,7 +151,7 @@ function renderLiteContextContent(context, explorations, session) {
151
151
 
152
152
  return `
153
153
  <div class="tab-empty-state">
154
- <div class="empty-icon">📦</div>
154
+ <div class="empty-icon"><i data-lucide="package" class="w-12 h-12"></i></div>
155
155
  <div class="empty-title">No Context Data</div>
156
156
  <div class="empty-text">No context-package.json or exploration files found for this session.</div>
157
157
  </div>
@@ -187,10 +187,10 @@ function renderExplorationContext(explorations) {
187
187
  // Render each exploration angle as collapsible section
188
188
  const explorationOrder = ['architecture', 'dependencies', 'patterns', 'integration-points'];
189
189
  const explorationTitles = {
190
- 'architecture': '🏗️ Architecture',
191
- 'dependencies': '📦 Dependencies',
192
- 'patterns': '🔄 Patterns',
193
- 'integration-points': '🔌 Integration Points'
190
+ 'architecture': '<i data-lucide="blocks" class="w-4 h-4 inline mr-1"></i>Architecture',
191
+ 'dependencies': '<i data-lucide="package" class="w-4 h-4 inline mr-1"></i>Dependencies',
192
+ 'patterns': '<i data-lucide="git-branch" class="w-4 h-4 inline mr-1"></i>Patterns',
193
+ 'integration-points': '<i data-lucide="plug" class="w-4 h-4 inline mr-1"></i>Integration Points'
194
194
  };
195
195
 
196
196
  for (const angle of explorationOrder) {
@@ -6,6 +6,7 @@ function initTheme() {
6
6
  const saved = localStorage.getItem('theme') || 'light';
7
7
  document.documentElement.setAttribute('data-theme', saved);
8
8
  updateThemeIcon(saved);
9
+ updateHljsTheme(saved);
9
10
 
10
11
  document.getElementById('themeToggle').addEventListener('click', () => {
11
12
  const current = document.documentElement.getAttribute('data-theme');
@@ -13,9 +14,36 @@ function initTheme() {
13
14
  document.documentElement.setAttribute('data-theme', next);
14
15
  localStorage.setItem('theme', next);
15
16
  updateThemeIcon(next);
17
+ updateHljsTheme(next);
16
18
  });
17
19
  }
18
20
 
19
21
  function updateThemeIcon(theme) {
20
- document.getElementById('themeToggle').textContent = theme === 'light' ? '🌙' : '☀️';
22
+ const darkIcon = document.querySelector('.theme-icon-dark');
23
+ const lightIcon = document.querySelector('.theme-icon-light');
24
+ if (darkIcon && lightIcon) {
25
+ if (theme === 'light') {
26
+ darkIcon.classList.remove('hidden');
27
+ lightIcon.classList.add('hidden');
28
+ } else {
29
+ darkIcon.classList.add('hidden');
30
+ lightIcon.classList.remove('hidden');
31
+ }
32
+ }
33
+ }
34
+
35
+ function updateHljsTheme(theme) {
36
+ // Toggle highlight.js theme stylesheets
37
+ const darkTheme = document.getElementById('hljs-theme-dark');
38
+ const lightTheme = document.getElementById('hljs-theme-light');
39
+
40
+ if (darkTheme && lightTheme) {
41
+ if (theme === 'dark') {
42
+ darkTheme.disabled = false;
43
+ lightTheme.disabled = true;
44
+ } else {
45
+ darkTheme.disabled = true;
46
+ lightTheme.disabled = false;
47
+ }
48
+ }
21
49
  }
@@ -2,6 +2,9 @@
2
2
  // Initializes all components and sets up global event handlers
3
3
 
4
4
  document.addEventListener('DOMContentLoaded', async () => {
5
+ // Initialize Lucide icons (must be first to render SVG icons)
6
+ try { lucide.createIcons(); } catch (e) { console.error('Lucide icons init failed:', e); }
7
+
5
8
  // Initialize components with error handling to prevent cascading failures
6
9
  try { initTheme(); } catch (e) { console.error('Theme init failed:', e); }
7
10
  try { initSidebar(); } catch (e) { console.error('Sidebar init failed:', e); }
@@ -12,6 +15,7 @@ document.addEventListener('DOMContentLoaded', async () => {
12
15
  try { initCarousel(); } catch (e) { console.error('Carousel init failed:', e); }
13
16
  try { initMcpManager(); } catch (e) { console.error('MCP Manager init failed:', e); }
14
17
  try { initHookManager(); } catch (e) { console.error('Hook Manager init failed:', e); }
18
+ try { initGlobalNotifications(); } catch (e) { console.error('Global notifications init failed:', e); }
15
19
 
16
20
  // Initialize real-time features (WebSocket + auto-refresh)
17
21
  try { initWebSocket(); } catch (e) { console.log('WebSocket not available:', e.message); }
@@ -35,3 +35,8 @@ const liteTaskDataStore = {};
35
35
  // Store task JSON data in a global map instead of inline script tags
36
36
  // Key: unique task ID, Value: raw task JSON data
37
37
  const taskJsonStore = {};
38
+
39
+ // ========== Global Notification Queue ==========
40
+ // Notification queue visible from any view
41
+ let globalNotificationQueue = [];
42
+ let isNotificationPanelVisible = false;