@exaudeus/workrail 0.8.0 → 0.8.2
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.
- package/dist/application/app.d.ts +0 -1
- package/dist/application/app.js +0 -6
- package/dist/application/services/workflow-service.js +56 -4
- package/dist/mcp-server.js +0 -35
- package/package.json +1 -1
- package/workflows/bug-investigation.agentic.json +112 -0
- package/workflows/document-creation-workflow.json +1 -1
- package/workflows/documentation-update-workflow.json +1 -1
- package/workflows/routines/plan-analysis.json +139 -0
- package/workflows/scoped-documentation-workflow.json +252 -0
- package/workflows/workflow-diagnose-environment.json +24 -0
- package/spec/mcp-compliance-summary.md +0 -211
- package/spec/mcp-protocol-handshake.md +0 -604
- package/web/DESIGN_SYSTEM_INTEGRATION.md +0 -305
- package/web/assets/images/favicon-amber-16.png +0 -0
- package/web/assets/images/favicon-amber-32.png +0 -0
- package/web/assets/images/favicon-white-16-clean.png +0 -0
- package/web/assets/images/favicon-white-32-clean.png +0 -0
- package/web/assets/images/icon-amber-192.png +0 -0
- package/web/assets/images/icon-amber-512.png +0 -0
- package/web/assets/images/icon-amber.svg +0 -27
- package/web/assets/images/icon-white-192-clean.png +0 -0
- package/web/assets/images/icon-white-512-clean.png +0 -0
- package/web/assets/images/icon-white.svg +0 -27
- package/web/examples/BEFORE_AFTER.md +0 -691
- package/workflows/IMPROVEMENTS-simplified.md +0 -122
- package/workflows/systematic-bug-investigation-simplified.backup-20251106-155300.json +0 -117
- package/workflows/systematic-bug-investigation-with-loops.backup-20251106-162241.json +0 -731
|
@@ -1,691 +0,0 @@
|
|
|
1
|
-
# Before & After: The Component System Transformation
|
|
2
|
-
|
|
3
|
-
## 🔴 **BEFORE: Current Approach (Bug-Prone)**
|
|
4
|
-
|
|
5
|
-
### Creating a Dashboard Page (200+ lines)
|
|
6
|
-
|
|
7
|
-
```html
|
|
8
|
-
<!-- dashboard.html -->
|
|
9
|
-
<!DOCTYPE html>
|
|
10
|
-
<html lang="en">
|
|
11
|
-
<head>
|
|
12
|
-
<link rel="stylesheet" href="/assets/design-system.css">
|
|
13
|
-
<link rel="stylesheet" href="/assets/components.css">
|
|
14
|
-
<link rel="stylesheet" href="/assets/animations.css">
|
|
15
|
-
<link rel="stylesheet" href="/assets/styles.css">
|
|
16
|
-
<link rel="stylesheet" href="/assets/background-effects.css">
|
|
17
|
-
<link rel="stylesheet" href="/assets/theme-toggle.css">
|
|
18
|
-
<!-- ... 10+ more style imports -->
|
|
19
|
-
|
|
20
|
-
<style>
|
|
21
|
-
/* Custom styles - potential for conflicts */
|
|
22
|
-
body {
|
|
23
|
-
padding: var(--space-8) 0; /* Might break header */
|
|
24
|
-
}
|
|
25
|
-
.dashboard-main {
|
|
26
|
-
max-width: 1200px;
|
|
27
|
-
margin: 0 auto;
|
|
28
|
-
padding: 0 var(--space-6); /* Might need responsive fixes */
|
|
29
|
-
}
|
|
30
|
-
/* ... 100+ more lines of custom CSS */
|
|
31
|
-
</style>
|
|
32
|
-
</head>
|
|
33
|
-
<body>
|
|
34
|
-
<!-- Manual header positioning -->
|
|
35
|
-
<header class="dashboard-header">
|
|
36
|
-
<div class="header-content">
|
|
37
|
-
<button class="btn-back">← All Sessions</button>
|
|
38
|
-
<h1>🔍 Bug Investigation Dashboard</h1>
|
|
39
|
-
<div class="header-meta">
|
|
40
|
-
<span class="session-id">DASH-001</span>
|
|
41
|
-
<span class="updated">Updated: <span id="timestamp"></span></span>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
</header>
|
|
45
|
-
|
|
46
|
-
<!-- Manual layout -->
|
|
47
|
-
<main class="dashboard-main">
|
|
48
|
-
<!-- Hero section - manual HTML -->
|
|
49
|
-
<div class="hero-section">
|
|
50
|
-
<div class="hero-stats">
|
|
51
|
-
<div class="stat-item">
|
|
52
|
-
<span class="stat-label">PROGRESS</span>
|
|
53
|
-
<span class="stat-value" id="progress">0%</span>
|
|
54
|
-
</div>
|
|
55
|
-
<!-- ... more manual stat items -->
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<!-- Root cause card - manual HTML -->
|
|
60
|
-
<div class="card root-cause-card" id="rootCauseCard">
|
|
61
|
-
<div class="card-header">
|
|
62
|
-
<h2>🎯 Root Cause</h2>
|
|
63
|
-
<span class="status-badge" id="rcStatus">Pending</span>
|
|
64
|
-
</div>
|
|
65
|
-
<div class="card-body">
|
|
66
|
-
<div class="detail-row">
|
|
67
|
-
<span class="label">Location:</span>
|
|
68
|
-
<code id="rcLocation">-</code>
|
|
69
|
-
</div>
|
|
70
|
-
<!-- ... more manual rows -->
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
<!-- Hypotheses - manual rendering -->
|
|
75
|
-
<div id="hypothesesList"></div>
|
|
76
|
-
|
|
77
|
-
<!-- Timeline - manual rendering -->
|
|
78
|
-
<div id="timeline"></div>
|
|
79
|
-
</main>
|
|
80
|
-
|
|
81
|
-
<script>
|
|
82
|
-
// Manual data fetching
|
|
83
|
-
let sessionData = null;
|
|
84
|
-
let updateInterval = null;
|
|
85
|
-
|
|
86
|
-
async function loadData() {
|
|
87
|
-
const response = await fetch('/api/sessions/bug-investigation/DASH-001');
|
|
88
|
-
sessionData = await response.json();
|
|
89
|
-
renderDashboard();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Manual rendering - error-prone
|
|
93
|
-
function renderDashboard() {
|
|
94
|
-
// Update progress
|
|
95
|
-
const progressEl = document.getElementById('progress');
|
|
96
|
-
if (progressEl && sessionData?.dashboard?.progress) {
|
|
97
|
-
progressEl.textContent = sessionData.dashboard.progress + '%';
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Update root cause
|
|
101
|
-
const rcLocation = document.getElementById('rcLocation');
|
|
102
|
-
if (rcLocation && sessionData?.rootCause?.location) {
|
|
103
|
-
rcLocation.textContent = sessionData.rootCause.location;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Render hypotheses - manual DOM manipulation
|
|
107
|
-
const hypothesesList = document.getElementById('hypothesesList');
|
|
108
|
-
if (hypothesesList && sessionData?.hypotheses) {
|
|
109
|
-
hypothesesList.innerHTML = ''; // Clear
|
|
110
|
-
sessionData.hypotheses.forEach((h, i) => {
|
|
111
|
-
const card = document.createElement('div');
|
|
112
|
-
card.className = 'card hypothesis-card';
|
|
113
|
-
card.innerHTML = `
|
|
114
|
-
<div class="hypothesis-header">
|
|
115
|
-
<span class="hypothesis-id">H${i + 1}</span>
|
|
116
|
-
<h3>${h.title || 'Untitled'}</h3>
|
|
117
|
-
<span class="status-badge status-${h.status}">${h.status}</span>
|
|
118
|
-
</div>
|
|
119
|
-
<div class="hypothesis-body">
|
|
120
|
-
<p>${h.description || ''}</p>
|
|
121
|
-
<div class="confidence">
|
|
122
|
-
Confidence: <strong>${h.confidence || 0}/10</strong>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
`;
|
|
126
|
-
hypothesesList.appendChild(card);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Render timeline - manual DOM manipulation
|
|
131
|
-
const timelineEl = document.getElementById('timeline');
|
|
132
|
-
if (timelineEl && sessionData?.timeline) {
|
|
133
|
-
timelineEl.innerHTML = '';
|
|
134
|
-
sessionData.timeline.forEach(event => {
|
|
135
|
-
const item = document.createElement('div');
|
|
136
|
-
item.className = `timeline-item timeline-${event.type}`;
|
|
137
|
-
item.innerHTML = `
|
|
138
|
-
<div class="timeline-marker"></div>
|
|
139
|
-
<div class="timeline-content">
|
|
140
|
-
<span class="timeline-time">${formatTime(event.timestamp)}</span>
|
|
141
|
-
<span class="timeline-title">${event.title}</span>
|
|
142
|
-
</div>
|
|
143
|
-
`;
|
|
144
|
-
timelineEl.appendChild(item);
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Manual polling
|
|
150
|
-
function startPolling() {
|
|
151
|
-
updateInterval = setInterval(loadData, 2000);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Manual initialization
|
|
155
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
156
|
-
loadData();
|
|
157
|
-
startPolling();
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Manual cleanup
|
|
161
|
-
window.addEventListener('beforeunload', () => {
|
|
162
|
-
if (updateInterval) clearInterval(updateInterval);
|
|
163
|
-
});
|
|
164
|
-
</script>
|
|
165
|
-
</body>
|
|
166
|
-
</html>
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Problems with This Approach
|
|
170
|
-
|
|
171
|
-
1. **Layout bugs** - Body padding breaks fixed header
|
|
172
|
-
2. **CSS conflicts** - Multiple stylesheets, potential conflicts
|
|
173
|
-
3. **Manual DOM manipulation** - Error-prone, verbose
|
|
174
|
-
4. **No prop validation** - Runtime errors if data is missing
|
|
175
|
-
5. **No reusability** - Copy-paste code for each dashboard
|
|
176
|
-
6. **Hard to maintain** - Changes require touching multiple files
|
|
177
|
-
7. **No testing** - Can't test components in isolation
|
|
178
|
-
8. **Accessibility issues** - Easy to forget ARIA attributes
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## 🟢 **AFTER: Component System (Bulletproof)**
|
|
183
|
-
|
|
184
|
-
### Creating the Same Dashboard (30 lines)
|
|
185
|
-
|
|
186
|
-
```html
|
|
187
|
-
<!DOCTYPE html>
|
|
188
|
-
<html lang="en">
|
|
189
|
-
<head>
|
|
190
|
-
<meta charset="UTF-8">
|
|
191
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
192
|
-
<title>Bug Investigation Dashboard</title>
|
|
193
|
-
|
|
194
|
-
<!-- Single import -->
|
|
195
|
-
<link rel="stylesheet" href="/assets/workrail-ui.css">
|
|
196
|
-
<script src="/assets/workrail-ui.js"></script>
|
|
197
|
-
</head>
|
|
198
|
-
<body>
|
|
199
|
-
<div id="root"></div>
|
|
200
|
-
|
|
201
|
-
<script type="module">
|
|
202
|
-
import { createDashboard } from '/assets/workrail-ui.js';
|
|
203
|
-
|
|
204
|
-
// That's it. Everything else is handled.
|
|
205
|
-
const dashboard = createDashboard({
|
|
206
|
-
workflow: 'bug-investigation',
|
|
207
|
-
sessionId: 'DASH-001',
|
|
208
|
-
|
|
209
|
-
// Automatic data fetching, polling, error handling
|
|
210
|
-
dataSource: '/api/sessions/bug-investigation/DASH-001',
|
|
211
|
-
updateInterval: 2000,
|
|
212
|
-
|
|
213
|
-
// Automatic layout, responsive, dark mode, animations
|
|
214
|
-
sections: [
|
|
215
|
-
{ type: 'hero' },
|
|
216
|
-
{ type: 'stats', fields: ['progress', 'confidence', 'phase'] },
|
|
217
|
-
{ type: 'rootCause' },
|
|
218
|
-
{ type: 'hypotheses' },
|
|
219
|
-
{ type: 'timeline' }
|
|
220
|
-
]
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
document.getElementById('root').appendChild(dashboard);
|
|
224
|
-
</script>
|
|
225
|
-
</body>
|
|
226
|
-
</html>
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Benefits of This Approach
|
|
230
|
-
|
|
231
|
-
1. **Zero layout bugs** - Layout handled by system
|
|
232
|
-
2. **No CSS conflicts** - Single source of truth
|
|
233
|
-
3. **Automatic rendering** - Components handle DOM updates
|
|
234
|
-
4. **Built-in validation** - Type checking, helpful errors
|
|
235
|
-
5. **100% reusable** - Same code for all dashboards
|
|
236
|
-
6. **Easy maintenance** - Update once, applies everywhere
|
|
237
|
-
7. **Fully tested** - All components have tests
|
|
238
|
-
8. **Accessible by default** - ARIA attributes automatic
|
|
239
|
-
|
|
240
|
-
---
|
|
241
|
-
|
|
242
|
-
## 🎨 **Custom Dashboards Are Still Easy**
|
|
243
|
-
|
|
244
|
-
### Need something custom? Use composition:
|
|
245
|
-
|
|
246
|
-
```javascript
|
|
247
|
-
import {
|
|
248
|
-
DashboardLayout,
|
|
249
|
-
Hero,
|
|
250
|
-
Grid,
|
|
251
|
-
Card,
|
|
252
|
-
Timeline,
|
|
253
|
-
Badge,
|
|
254
|
-
Button
|
|
255
|
-
} from '/assets/workrail-ui.js';
|
|
256
|
-
|
|
257
|
-
// Compose your own layout
|
|
258
|
-
const dashboard = DashboardLayout({
|
|
259
|
-
header: {
|
|
260
|
-
title: 'Custom Dashboard',
|
|
261
|
-
backButton: true,
|
|
262
|
-
actions: [
|
|
263
|
-
Button({ text: 'Export', icon: 'download' })
|
|
264
|
-
]
|
|
265
|
-
},
|
|
266
|
-
|
|
267
|
-
main: Grid({
|
|
268
|
-
columns: 2,
|
|
269
|
-
gap: 'lg',
|
|
270
|
-
children: [
|
|
271
|
-
// Custom hero
|
|
272
|
-
Hero({
|
|
273
|
-
title: 'My Investigation',
|
|
274
|
-
badge: Badge({ text: 'Active', variant: 'success' }),
|
|
275
|
-
stats: [
|
|
276
|
-
{ label: 'Progress', value: '75%' },
|
|
277
|
-
{ label: 'Time', value: '2.5h' }
|
|
278
|
-
]
|
|
279
|
-
}),
|
|
280
|
-
|
|
281
|
-
// Custom card
|
|
282
|
-
Card({
|
|
283
|
-
title: 'Custom Section',
|
|
284
|
-
icon: 'zap',
|
|
285
|
-
children: [
|
|
286
|
-
document.createTextNode('Any custom content here!')
|
|
287
|
-
]
|
|
288
|
-
}),
|
|
289
|
-
|
|
290
|
-
// Timeline
|
|
291
|
-
Timeline({
|
|
292
|
-
events: [
|
|
293
|
-
{ time: '10:30', title: 'Started', type: 'start' },
|
|
294
|
-
{ time: '11:45', title: 'Found issue', type: 'success' }
|
|
295
|
-
]
|
|
296
|
-
})
|
|
297
|
-
]
|
|
298
|
-
})
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
document.getElementById('root').appendChild(dashboard);
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
---
|
|
305
|
-
|
|
306
|
-
## 📊 **Comparison Table**
|
|
307
|
-
|
|
308
|
-
| Feature | Before (Manual) | After (Component System) |
|
|
309
|
-
|---------|----------------|--------------------------|
|
|
310
|
-
| **Lines of code** | 200+ per dashboard | 30 per dashboard |
|
|
311
|
-
| **CSS files** | 10+ imports | 1 import |
|
|
312
|
-
| **Layout bugs** | Common | Impossible |
|
|
313
|
-
| **Dark mode** | Manual implementation | Automatic |
|
|
314
|
-
| **Responsive** | Manual breakpoints | Automatic |
|
|
315
|
-
| **Animations** | Manual CSS | Automatic |
|
|
316
|
-
| **Error handling** | Manual checks | Automatic validation |
|
|
317
|
-
| **Testing** | None | Built-in |
|
|
318
|
-
| **Accessibility** | Manual ARIA | Automatic |
|
|
319
|
-
| **Time to create** | 2-3 hours | 10 minutes |
|
|
320
|
-
| **Maintenance** | High effort | Low effort |
|
|
321
|
-
| **Bug potential** | High | Near zero |
|
|
322
|
-
|
|
323
|
-
---
|
|
324
|
-
|
|
325
|
-
## 🚀 **The Best Part**
|
|
326
|
-
|
|
327
|
-
### Existing dashboards keep working!
|
|
328
|
-
|
|
329
|
-
The component system is **additive**, not replacement:
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
// Option 1: Use full scaffold (new dashboards)
|
|
333
|
-
createDashboard({ ... })
|
|
334
|
-
|
|
335
|
-
// Option 2: Use individual components (gradual migration)
|
|
336
|
-
const card = Card({ title: 'Test' });
|
|
337
|
-
document.body.appendChild(card);
|
|
338
|
-
|
|
339
|
-
// Option 3: Keep manual HTML (legacy dashboards)
|
|
340
|
-
// Your old code still works!
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
**No breaking changes. Progressive enhancement.** ✨
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
## 🔴 **BEFORE: Current Approach (Bug-Prone)**
|
|
349
|
-
|
|
350
|
-
### Creating a Dashboard Page (200+ lines)
|
|
351
|
-
|
|
352
|
-
```html
|
|
353
|
-
<!-- dashboard.html -->
|
|
354
|
-
<!DOCTYPE html>
|
|
355
|
-
<html lang="en">
|
|
356
|
-
<head>
|
|
357
|
-
<link rel="stylesheet" href="/assets/design-system.css">
|
|
358
|
-
<link rel="stylesheet" href="/assets/components.css">
|
|
359
|
-
<link rel="stylesheet" href="/assets/animations.css">
|
|
360
|
-
<link rel="stylesheet" href="/assets/styles.css">
|
|
361
|
-
<link rel="stylesheet" href="/assets/background-effects.css">
|
|
362
|
-
<link rel="stylesheet" href="/assets/theme-toggle.css">
|
|
363
|
-
<!-- ... 10+ more style imports -->
|
|
364
|
-
|
|
365
|
-
<style>
|
|
366
|
-
/* Custom styles - potential for conflicts */
|
|
367
|
-
body {
|
|
368
|
-
padding: var(--space-8) 0; /* Might break header */
|
|
369
|
-
}
|
|
370
|
-
.dashboard-main {
|
|
371
|
-
max-width: 1200px;
|
|
372
|
-
margin: 0 auto;
|
|
373
|
-
padding: 0 var(--space-6); /* Might need responsive fixes */
|
|
374
|
-
}
|
|
375
|
-
/* ... 100+ more lines of custom CSS */
|
|
376
|
-
</style>
|
|
377
|
-
</head>
|
|
378
|
-
<body>
|
|
379
|
-
<!-- Manual header positioning -->
|
|
380
|
-
<header class="dashboard-header">
|
|
381
|
-
<div class="header-content">
|
|
382
|
-
<button class="btn-back">← All Sessions</button>
|
|
383
|
-
<h1>🔍 Bug Investigation Dashboard</h1>
|
|
384
|
-
<div class="header-meta">
|
|
385
|
-
<span class="session-id">DASH-001</span>
|
|
386
|
-
<span class="updated">Updated: <span id="timestamp"></span></span>
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
389
|
-
</header>
|
|
390
|
-
|
|
391
|
-
<!-- Manual layout -->
|
|
392
|
-
<main class="dashboard-main">
|
|
393
|
-
<!-- Hero section - manual HTML -->
|
|
394
|
-
<div class="hero-section">
|
|
395
|
-
<div class="hero-stats">
|
|
396
|
-
<div class="stat-item">
|
|
397
|
-
<span class="stat-label">PROGRESS</span>
|
|
398
|
-
<span class="stat-value" id="progress">0%</span>
|
|
399
|
-
</div>
|
|
400
|
-
<!-- ... more manual stat items -->
|
|
401
|
-
</div>
|
|
402
|
-
</div>
|
|
403
|
-
|
|
404
|
-
<!-- Root cause card - manual HTML -->
|
|
405
|
-
<div class="card root-cause-card" id="rootCauseCard">
|
|
406
|
-
<div class="card-header">
|
|
407
|
-
<h2>🎯 Root Cause</h2>
|
|
408
|
-
<span class="status-badge" id="rcStatus">Pending</span>
|
|
409
|
-
</div>
|
|
410
|
-
<div class="card-body">
|
|
411
|
-
<div class="detail-row">
|
|
412
|
-
<span class="label">Location:</span>
|
|
413
|
-
<code id="rcLocation">-</code>
|
|
414
|
-
</div>
|
|
415
|
-
<!-- ... more manual rows -->
|
|
416
|
-
</div>
|
|
417
|
-
</div>
|
|
418
|
-
|
|
419
|
-
<!-- Hypotheses - manual rendering -->
|
|
420
|
-
<div id="hypothesesList"></div>
|
|
421
|
-
|
|
422
|
-
<!-- Timeline - manual rendering -->
|
|
423
|
-
<div id="timeline"></div>
|
|
424
|
-
</main>
|
|
425
|
-
|
|
426
|
-
<script>
|
|
427
|
-
// Manual data fetching
|
|
428
|
-
let sessionData = null;
|
|
429
|
-
let updateInterval = null;
|
|
430
|
-
|
|
431
|
-
async function loadData() {
|
|
432
|
-
const response = await fetch('/api/sessions/bug-investigation/DASH-001');
|
|
433
|
-
sessionData = await response.json();
|
|
434
|
-
renderDashboard();
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// Manual rendering - error-prone
|
|
438
|
-
function renderDashboard() {
|
|
439
|
-
// Update progress
|
|
440
|
-
const progressEl = document.getElementById('progress');
|
|
441
|
-
if (progressEl && sessionData?.dashboard?.progress) {
|
|
442
|
-
progressEl.textContent = sessionData.dashboard.progress + '%';
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Update root cause
|
|
446
|
-
const rcLocation = document.getElementById('rcLocation');
|
|
447
|
-
if (rcLocation && sessionData?.rootCause?.location) {
|
|
448
|
-
rcLocation.textContent = sessionData.rootCause.location;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Render hypotheses - manual DOM manipulation
|
|
452
|
-
const hypothesesList = document.getElementById('hypothesesList');
|
|
453
|
-
if (hypothesesList && sessionData?.hypotheses) {
|
|
454
|
-
hypothesesList.innerHTML = ''; // Clear
|
|
455
|
-
sessionData.hypotheses.forEach((h, i) => {
|
|
456
|
-
const card = document.createElement('div');
|
|
457
|
-
card.className = 'card hypothesis-card';
|
|
458
|
-
card.innerHTML = `
|
|
459
|
-
<div class="hypothesis-header">
|
|
460
|
-
<span class="hypothesis-id">H${i + 1}</span>
|
|
461
|
-
<h3>${h.title || 'Untitled'}</h3>
|
|
462
|
-
<span class="status-badge status-${h.status}">${h.status}</span>
|
|
463
|
-
</div>
|
|
464
|
-
<div class="hypothesis-body">
|
|
465
|
-
<p>${h.description || ''}</p>
|
|
466
|
-
<div class="confidence">
|
|
467
|
-
Confidence: <strong>${h.confidence || 0}/10</strong>
|
|
468
|
-
</div>
|
|
469
|
-
</div>
|
|
470
|
-
`;
|
|
471
|
-
hypothesesList.appendChild(card);
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// Render timeline - manual DOM manipulation
|
|
476
|
-
const timelineEl = document.getElementById('timeline');
|
|
477
|
-
if (timelineEl && sessionData?.timeline) {
|
|
478
|
-
timelineEl.innerHTML = '';
|
|
479
|
-
sessionData.timeline.forEach(event => {
|
|
480
|
-
const item = document.createElement('div');
|
|
481
|
-
item.className = `timeline-item timeline-${event.type}`;
|
|
482
|
-
item.innerHTML = `
|
|
483
|
-
<div class="timeline-marker"></div>
|
|
484
|
-
<div class="timeline-content">
|
|
485
|
-
<span class="timeline-time">${formatTime(event.timestamp)}</span>
|
|
486
|
-
<span class="timeline-title">${event.title}</span>
|
|
487
|
-
</div>
|
|
488
|
-
`;
|
|
489
|
-
timelineEl.appendChild(item);
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// Manual polling
|
|
495
|
-
function startPolling() {
|
|
496
|
-
updateInterval = setInterval(loadData, 2000);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Manual initialization
|
|
500
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
501
|
-
loadData();
|
|
502
|
-
startPolling();
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
// Manual cleanup
|
|
506
|
-
window.addEventListener('beforeunload', () => {
|
|
507
|
-
if (updateInterval) clearInterval(updateInterval);
|
|
508
|
-
});
|
|
509
|
-
</script>
|
|
510
|
-
</body>
|
|
511
|
-
</html>
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
### Problems with This Approach
|
|
515
|
-
|
|
516
|
-
1. **Layout bugs** - Body padding breaks fixed header
|
|
517
|
-
2. **CSS conflicts** - Multiple stylesheets, potential conflicts
|
|
518
|
-
3. **Manual DOM manipulation** - Error-prone, verbose
|
|
519
|
-
4. **No prop validation** - Runtime errors if data is missing
|
|
520
|
-
5. **No reusability** - Copy-paste code for each dashboard
|
|
521
|
-
6. **Hard to maintain** - Changes require touching multiple files
|
|
522
|
-
7. **No testing** - Can't test components in isolation
|
|
523
|
-
8. **Accessibility issues** - Easy to forget ARIA attributes
|
|
524
|
-
|
|
525
|
-
---
|
|
526
|
-
|
|
527
|
-
## 🟢 **AFTER: Component System (Bulletproof)**
|
|
528
|
-
|
|
529
|
-
### Creating the Same Dashboard (30 lines)
|
|
530
|
-
|
|
531
|
-
```html
|
|
532
|
-
<!DOCTYPE html>
|
|
533
|
-
<html lang="en">
|
|
534
|
-
<head>
|
|
535
|
-
<meta charset="UTF-8">
|
|
536
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
537
|
-
<title>Bug Investigation Dashboard</title>
|
|
538
|
-
|
|
539
|
-
<!-- Single import -->
|
|
540
|
-
<link rel="stylesheet" href="/assets/workrail-ui.css">
|
|
541
|
-
<script src="/assets/workrail-ui.js"></script>
|
|
542
|
-
</head>
|
|
543
|
-
<body>
|
|
544
|
-
<div id="root"></div>
|
|
545
|
-
|
|
546
|
-
<script type="module">
|
|
547
|
-
import { createDashboard } from '/assets/workrail-ui.js';
|
|
548
|
-
|
|
549
|
-
// That's it. Everything else is handled.
|
|
550
|
-
const dashboard = createDashboard({
|
|
551
|
-
workflow: 'bug-investigation',
|
|
552
|
-
sessionId: 'DASH-001',
|
|
553
|
-
|
|
554
|
-
// Automatic data fetching, polling, error handling
|
|
555
|
-
dataSource: '/api/sessions/bug-investigation/DASH-001',
|
|
556
|
-
updateInterval: 2000,
|
|
557
|
-
|
|
558
|
-
// Automatic layout, responsive, dark mode, animations
|
|
559
|
-
sections: [
|
|
560
|
-
{ type: 'hero' },
|
|
561
|
-
{ type: 'stats', fields: ['progress', 'confidence', 'phase'] },
|
|
562
|
-
{ type: 'rootCause' },
|
|
563
|
-
{ type: 'hypotheses' },
|
|
564
|
-
{ type: 'timeline' }
|
|
565
|
-
]
|
|
566
|
-
});
|
|
567
|
-
|
|
568
|
-
document.getElementById('root').appendChild(dashboard);
|
|
569
|
-
</script>
|
|
570
|
-
</body>
|
|
571
|
-
</html>
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
### Benefits of This Approach
|
|
575
|
-
|
|
576
|
-
1. **Zero layout bugs** - Layout handled by system
|
|
577
|
-
2. **No CSS conflicts** - Single source of truth
|
|
578
|
-
3. **Automatic rendering** - Components handle DOM updates
|
|
579
|
-
4. **Built-in validation** - Type checking, helpful errors
|
|
580
|
-
5. **100% reusable** - Same code for all dashboards
|
|
581
|
-
6. **Easy maintenance** - Update once, applies everywhere
|
|
582
|
-
7. **Fully tested** - All components have tests
|
|
583
|
-
8. **Accessible by default** - ARIA attributes automatic
|
|
584
|
-
|
|
585
|
-
---
|
|
586
|
-
|
|
587
|
-
## 🎨 **Custom Dashboards Are Still Easy**
|
|
588
|
-
|
|
589
|
-
### Need something custom? Use composition:
|
|
590
|
-
|
|
591
|
-
```javascript
|
|
592
|
-
import {
|
|
593
|
-
DashboardLayout,
|
|
594
|
-
Hero,
|
|
595
|
-
Grid,
|
|
596
|
-
Card,
|
|
597
|
-
Timeline,
|
|
598
|
-
Badge,
|
|
599
|
-
Button
|
|
600
|
-
} from '/assets/workrail-ui.js';
|
|
601
|
-
|
|
602
|
-
// Compose your own layout
|
|
603
|
-
const dashboard = DashboardLayout({
|
|
604
|
-
header: {
|
|
605
|
-
title: 'Custom Dashboard',
|
|
606
|
-
backButton: true,
|
|
607
|
-
actions: [
|
|
608
|
-
Button({ text: 'Export', icon: 'download' })
|
|
609
|
-
]
|
|
610
|
-
},
|
|
611
|
-
|
|
612
|
-
main: Grid({
|
|
613
|
-
columns: 2,
|
|
614
|
-
gap: 'lg',
|
|
615
|
-
children: [
|
|
616
|
-
// Custom hero
|
|
617
|
-
Hero({
|
|
618
|
-
title: 'My Investigation',
|
|
619
|
-
badge: Badge({ text: 'Active', variant: 'success' }),
|
|
620
|
-
stats: [
|
|
621
|
-
{ label: 'Progress', value: '75%' },
|
|
622
|
-
{ label: 'Time', value: '2.5h' }
|
|
623
|
-
]
|
|
624
|
-
}),
|
|
625
|
-
|
|
626
|
-
// Custom card
|
|
627
|
-
Card({
|
|
628
|
-
title: 'Custom Section',
|
|
629
|
-
icon: 'zap',
|
|
630
|
-
children: [
|
|
631
|
-
document.createTextNode('Any custom content here!')
|
|
632
|
-
]
|
|
633
|
-
}),
|
|
634
|
-
|
|
635
|
-
// Timeline
|
|
636
|
-
Timeline({
|
|
637
|
-
events: [
|
|
638
|
-
{ time: '10:30', title: 'Started', type: 'start' },
|
|
639
|
-
{ time: '11:45', title: 'Found issue', type: 'success' }
|
|
640
|
-
]
|
|
641
|
-
})
|
|
642
|
-
]
|
|
643
|
-
})
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
document.getElementById('root').appendChild(dashboard);
|
|
647
|
-
```
|
|
648
|
-
|
|
649
|
-
---
|
|
650
|
-
|
|
651
|
-
## 📊 **Comparison Table**
|
|
652
|
-
|
|
653
|
-
| Feature | Before (Manual) | After (Component System) |
|
|
654
|
-
|---------|----------------|--------------------------|
|
|
655
|
-
| **Lines of code** | 200+ per dashboard | 30 per dashboard |
|
|
656
|
-
| **CSS files** | 10+ imports | 1 import |
|
|
657
|
-
| **Layout bugs** | Common | Impossible |
|
|
658
|
-
| **Dark mode** | Manual implementation | Automatic |
|
|
659
|
-
| **Responsive** | Manual breakpoints | Automatic |
|
|
660
|
-
| **Animations** | Manual CSS | Automatic |
|
|
661
|
-
| **Error handling** | Manual checks | Automatic validation |
|
|
662
|
-
| **Testing** | None | Built-in |
|
|
663
|
-
| **Accessibility** | Manual ARIA | Automatic |
|
|
664
|
-
| **Time to create** | 2-3 hours | 10 minutes |
|
|
665
|
-
| **Maintenance** | High effort | Low effort |
|
|
666
|
-
| **Bug potential** | High | Near zero |
|
|
667
|
-
|
|
668
|
-
---
|
|
669
|
-
|
|
670
|
-
## 🚀 **The Best Part**
|
|
671
|
-
|
|
672
|
-
### Existing dashboards keep working!
|
|
673
|
-
|
|
674
|
-
The component system is **additive**, not replacement:
|
|
675
|
-
|
|
676
|
-
```javascript
|
|
677
|
-
// Option 1: Use full scaffold (new dashboards)
|
|
678
|
-
createDashboard({ ... })
|
|
679
|
-
|
|
680
|
-
// Option 2: Use individual components (gradual migration)
|
|
681
|
-
const card = Card({ title: 'Test' });
|
|
682
|
-
document.body.appendChild(card);
|
|
683
|
-
|
|
684
|
-
// Option 3: Keep manual HTML (legacy dashboards)
|
|
685
|
-
// Your old code still works!
|
|
686
|
-
```
|
|
687
|
-
|
|
688
|
-
**No breaking changes. Progressive enhancement.** ✨
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|