@vyuhlabs/dxkit 0.8.2 → 0.9.0

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.
@@ -1,5 +1,5 @@
1
1
  import { ResolvedConfig } from './types';
2
- export declare const VERSION = "0.8.2";
2
+ export declare const VERSION = "0.9.0";
3
3
  export declare const DEFAULT_VERSIONS: {
4
4
  python: string;
5
5
  go: string;
package/dist/constants.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EVOLVING_FILES = exports.DEFAULT_COVERAGE = exports.DEFAULT_VERSIONS = exports.VERSION = void 0;
4
4
  exports.buildVariables = buildVariables;
5
5
  exports.buildConditions = buildConditions;
6
- exports.VERSION = '0.8.2';
6
+ exports.VERSION = '0.9.0';
7
7
  exports.DEFAULT_VERSIONS = {
8
8
  python: '3.12',
9
9
  go: '1.24.0',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vyuhlabs/dxkit",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "AI-native developer experience toolkit for any repository",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -0,0 +1,433 @@
1
+ ---
2
+ name: dashboard-builder
3
+ description: Generates a beautiful HTML dashboard from all reports in .ai/reports/. Use when asked to "build dashboard", "export reports", or "create report dashboard". Reads reports and generates a self-contained HTML file.
4
+ model: sonnet
5
+ tools: Read, Grep, Glob, Bash, Write
6
+ ---
7
+
8
+ You are a dashboard builder. Your job is to create a beautiful, self-contained HTML dashboard that renders all markdown reports from `.ai/reports/`.
9
+
10
+ ## Steps
11
+
12
+ 1. **Find all reports**: Glob for `.ai/reports/*.md`
13
+ 2. **Read each report**: Get the markdown content
14
+ 3. **Detect project name**: From `CLAUDE.md`, `package.json`, or directory name
15
+ 4. **Generate dashboard**: Create `.ai/reports/dashboard.html`
16
+
17
+ ## Dashboard Design
18
+
19
+ The dashboard should be a **single self-contained HTML file** with:
20
+ - No external dependencies except CDN links for marked.js (markdown rendering)
21
+ - Dark theme with modern design (GitHub-dark inspired)
22
+ - Fully responsive
23
+
24
+ ### Layout
25
+ - **Header**: Project name, VyuhLabs DXKit branding, generation date
26
+ - **Sidebar**: Report navigation grouped by type with icons
27
+ - **Main area**: Rendered markdown report with proper styling
28
+ - **Footer**: VyuhLabs DXKit branding
29
+
30
+ ### Report Type Icons & Colors
31
+ Use these emoji/labels for report types:
32
+ - `health-audit` → "Health Audit" with green accent
33
+ - `vulnerability-scan` → "Vulnerability Scan" with red accent
34
+ - `developer-report` → "Developer Report" with blue accent
35
+ - `test-gaps` → "Test Gaps" with orange accent
36
+ - `docs-audit` → "Documentation" with purple accent
37
+ - `dependency-map` → "Dependencies" with cyan accent
38
+
39
+ ### Design Requirements
40
+ - Smooth transitions when switching reports
41
+ - Table styling that's readable on dark backgrounds
42
+ - Code blocks with syntax highlighting colors
43
+ - Proper heading hierarchy
44
+ - Score badges for health reports (color-coded: red/yellow/green)
45
+ - Sticky sidebar on desktop, collapsible on mobile
46
+ - Print-friendly styles (@media print)
47
+
48
+ ## HTML Template
49
+
50
+ Generate this exact structure (fill in REPORTS_DATA and PROJECT_NAME):
51
+
52
+ ```html
53
+ <!DOCTYPE html>
54
+ <html lang="en">
55
+ <head>
56
+ <meta charset="UTF-8">
57
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
58
+ <title>PROJECT_NAME — DXKit Reports</title>
59
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
60
+ <style>
61
+ :root {
62
+ --bg-primary: #0d1117;
63
+ --bg-secondary: #161b22;
64
+ --bg-tertiary: #21262d;
65
+ --border: #30363d;
66
+ --text-primary: #f0f6fc;
67
+ --text-secondary: #c9d1d9;
68
+ --text-muted: #8b949e;
69
+ --accent-blue: #58a6ff;
70
+ --accent-green: #3fb950;
71
+ --accent-red: #f85149;
72
+ --accent-orange: #d29922;
73
+ --accent-purple: #bc8cff;
74
+ --accent-cyan: #39d2c0;
75
+ --sidebar-width: 300px;
76
+ }
77
+
78
+ * { margin: 0; padding: 0; box-sizing: border-box; }
79
+
80
+ body {
81
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
82
+ background: var(--bg-primary);
83
+ color: var(--text-secondary);
84
+ display: flex;
85
+ height: 100vh;
86
+ overflow: hidden;
87
+ }
88
+
89
+ /* Sidebar */
90
+ .sidebar {
91
+ width: var(--sidebar-width);
92
+ background: var(--bg-secondary);
93
+ border-right: 1px solid var(--border);
94
+ display: flex;
95
+ flex-direction: column;
96
+ flex-shrink: 0;
97
+ overflow: hidden;
98
+ }
99
+
100
+ .sidebar-header {
101
+ padding: 20px;
102
+ border-bottom: 1px solid var(--border);
103
+ }
104
+
105
+ .sidebar-header h1 {
106
+ font-size: 18px;
107
+ color: var(--text-primary);
108
+ font-weight: 600;
109
+ }
110
+
111
+ .sidebar-header .project-name {
112
+ font-size: 13px;
113
+ color: var(--accent-blue);
114
+ margin-top: 4px;
115
+ }
116
+
117
+ .sidebar-header .generated {
118
+ font-size: 11px;
119
+ color: var(--text-muted);
120
+ margin-top: 2px;
121
+ }
122
+
123
+ .sidebar-nav {
124
+ flex: 1;
125
+ overflow-y: auto;
126
+ padding: 12px;
127
+ }
128
+
129
+ .report-group {
130
+ margin-bottom: 16px;
131
+ }
132
+
133
+ .report-group-title {
134
+ font-size: 11px;
135
+ text-transform: uppercase;
136
+ letter-spacing: 0.8px;
137
+ color: var(--text-muted);
138
+ padding: 4px 8px;
139
+ margin-bottom: 4px;
140
+ display: flex;
141
+ align-items: center;
142
+ gap: 6px;
143
+ }
144
+
145
+ .report-group-title .dot {
146
+ width: 8px;
147
+ height: 8px;
148
+ border-radius: 50%;
149
+ flex-shrink: 0;
150
+ }
151
+
152
+ .report-btn {
153
+ display: block;
154
+ width: 100%;
155
+ text-align: left;
156
+ background: none;
157
+ border: none;
158
+ color: var(--text-secondary);
159
+ padding: 8px 12px;
160
+ border-radius: 8px;
161
+ cursor: pointer;
162
+ font-size: 13px;
163
+ margin-bottom: 2px;
164
+ transition: all 0.15s ease;
165
+ font-family: inherit;
166
+ }
167
+
168
+ .report-btn:hover {
169
+ background: var(--bg-tertiary);
170
+ }
171
+
172
+ .report-btn.active {
173
+ background: var(--accent-blue);
174
+ color: white;
175
+ font-weight: 500;
176
+ }
177
+
178
+ .report-btn .date {
179
+ font-size: 11px;
180
+ color: var(--text-muted);
181
+ display: block;
182
+ margin-top: 2px;
183
+ }
184
+
185
+ .report-btn.active .date {
186
+ color: rgba(255,255,255,0.7);
187
+ }
188
+
189
+ .sidebar-footer {
190
+ padding: 16px 20px;
191
+ border-top: 1px solid var(--border);
192
+ font-size: 11px;
193
+ color: var(--text-muted);
194
+ }
195
+
196
+ .sidebar-footer a {
197
+ color: var(--accent-blue);
198
+ text-decoration: none;
199
+ }
200
+
201
+ /* Main content */
202
+ .main {
203
+ flex: 1;
204
+ overflow-y: auto;
205
+ padding: 40px;
206
+ }
207
+
208
+ .main-inner {
209
+ max-width: 860px;
210
+ margin: 0 auto;
211
+ }
212
+
213
+ .empty-state {
214
+ text-align: center;
215
+ color: var(--text-muted);
216
+ margin-top: 30vh;
217
+ }
218
+
219
+ .empty-state h2 {
220
+ font-size: 20px;
221
+ margin-bottom: 8px;
222
+ color: var(--text-secondary);
223
+ }
224
+
225
+ /* Markdown rendering */
226
+ .main-inner h1 { font-size: 28px; color: var(--text-primary); border-bottom: 1px solid var(--border); padding-bottom: 12px; margin-bottom: 20px; }
227
+ .main-inner h2 { font-size: 22px; color: var(--text-primary); margin-top: 32px; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
228
+ .main-inner h3 { font-size: 17px; color: var(--text-primary); margin-top: 24px; margin-bottom: 8px; }
229
+ .main-inner h4 { font-size: 15px; color: var(--text-primary); margin-top: 16px; margin-bottom: 6px; }
230
+ .main-inner p { line-height: 1.7; margin-bottom: 14px; }
231
+ .main-inner a { color: var(--accent-blue); text-decoration: none; }
232
+ .main-inner a:hover { text-decoration: underline; }
233
+ .main-inner strong { color: var(--text-primary); }
234
+ .main-inner em { color: var(--text-muted); }
235
+
236
+ .main-inner ul, .main-inner ol { padding-left: 24px; margin-bottom: 14px; }
237
+ .main-inner li { margin-bottom: 6px; line-height: 1.6; }
238
+ .main-inner li::marker { color: var(--text-muted); }
239
+
240
+ .main-inner table { border-collapse: collapse; width: 100%; margin-bottom: 20px; font-size: 14px; }
241
+ .main-inner th { background: var(--bg-secondary); color: var(--text-primary); font-weight: 600; text-align: left; padding: 10px 14px; border: 1px solid var(--border); }
242
+ .main-inner td { padding: 10px 14px; border: 1px solid var(--border); }
243
+ .main-inner tr:hover td { background: rgba(56, 139, 253, 0.04); }
244
+
245
+ .main-inner code {
246
+ background: var(--bg-secondary);
247
+ padding: 2px 7px;
248
+ border-radius: 5px;
249
+ font-size: 13px;
250
+ font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
251
+ color: var(--accent-blue);
252
+ }
253
+
254
+ .main-inner pre {
255
+ background: var(--bg-secondary);
256
+ padding: 18px;
257
+ border-radius: 10px;
258
+ overflow-x: auto;
259
+ margin-bottom: 18px;
260
+ border: 1px solid var(--border);
261
+ }
262
+
263
+ .main-inner pre code {
264
+ background: none;
265
+ padding: 0;
266
+ color: var(--text-secondary);
267
+ font-size: 13px;
268
+ line-height: 1.5;
269
+ }
270
+
271
+ .main-inner blockquote {
272
+ border-left: 3px solid var(--accent-blue);
273
+ padding: 8px 16px;
274
+ color: var(--text-muted);
275
+ margin-bottom: 14px;
276
+ background: rgba(56, 139, 253, 0.04);
277
+ border-radius: 0 6px 6px 0;
278
+ }
279
+
280
+ .main-inner hr {
281
+ border: none;
282
+ border-top: 1px solid var(--border);
283
+ margin: 28px 0;
284
+ }
285
+
286
+ .main-inner img { max-width: 100%; border-radius: 8px; }
287
+
288
+ /* Mobile */
289
+ .mobile-toggle {
290
+ display: none;
291
+ position: fixed;
292
+ top: 12px;
293
+ left: 12px;
294
+ z-index: 100;
295
+ background: var(--bg-secondary);
296
+ border: 1px solid var(--border);
297
+ color: var(--text-primary);
298
+ padding: 8px 12px;
299
+ border-radius: 8px;
300
+ cursor: pointer;
301
+ font-size: 14px;
302
+ }
303
+
304
+ @media (max-width: 768px) {
305
+ .sidebar { position: fixed; left: -300px; z-index: 50; height: 100vh; transition: left 0.3s ease; }
306
+ .sidebar.open { left: 0; box-shadow: 4px 0 20px rgba(0,0,0,0.5); }
307
+ .mobile-toggle { display: block; }
308
+ .main { padding: 20px; padding-top: 56px; }
309
+ }
310
+
311
+ /* Print */
312
+ @media print {
313
+ body { background: white; color: #1a1a1a; }
314
+ .sidebar, .mobile-toggle { display: none; }
315
+ .main { padding: 20px; }
316
+ .main-inner h1, .main-inner h2, .main-inner h3 { color: #1a1a1a; }
317
+ .main-inner code { background: #f0f0f0; color: #1a1a1a; }
318
+ .main-inner pre { background: #f6f6f6; border-color: #ddd; }
319
+ .main-inner th { background: #f0f0f0; }
320
+ .main-inner td, .main-inner th { border-color: #ddd; }
321
+ }
322
+
323
+ /* Scrollbar */
324
+ ::-webkit-scrollbar { width: 8px; }
325
+ ::-webkit-scrollbar-track { background: transparent; }
326
+ ::-webkit-scrollbar-thumb { background: var(--bg-tertiary); border-radius: 4px; }
327
+ ::-webkit-scrollbar-thumb:hover { background: var(--border); }
328
+
329
+ /* Animations */
330
+ .main-inner { animation: fadeIn 0.2s ease; }
331
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
332
+ </style>
333
+ </head>
334
+ <body>
335
+ <button class="mobile-toggle" onclick="document.querySelector('.sidebar').classList.toggle('open')">Menu</button>
336
+
337
+ <div class="sidebar">
338
+ <div class="sidebar-header">
339
+ <h1>DXKit Reports</h1>
340
+ <div class="project-name">PROJECT_NAME</div>
341
+ <div class="generated">Generated GENERATION_DATE</div>
342
+ </div>
343
+ <div class="sidebar-nav" id="nav"></div>
344
+ <div class="sidebar-footer">
345
+ Powered by <a href="https://www.npmjs.com/package/@vyuhlabs/dxkit" target="_blank">VyuhLabs DXKit</a>
346
+ </div>
347
+ </div>
348
+
349
+ <div class="main">
350
+ <div class="main-inner" id="content">
351
+ <div class="empty-state">
352
+ <h2>Select a report</h2>
353
+ <p>Choose a report from the sidebar to view it</p>
354
+ </div>
355
+ </div>
356
+ </div>
357
+
358
+ <script>
359
+ const reports = REPORTS_JSON;
360
+
361
+ const typeConfig = {
362
+ 'health-audit': { label: 'Health Audit', color: '#3fb950' },
363
+ 'vulnerability-scan': { label: 'Vulnerability Scan', color: '#f85149' },
364
+ 'developer-report': { label: 'Developer Report', color: '#58a6ff' },
365
+ 'test-gaps': { label: 'Test Gaps', color: '#d29922' },
366
+ 'docs-audit': { label: 'Documentation', color: '#bc8cff' },
367
+ 'dependency-map': { label: 'Dependencies', color: '#39d2c0' },
368
+ };
369
+
370
+ const nav = document.getElementById('nav');
371
+ const content = document.getElementById('content');
372
+
373
+ // Group reports by type
374
+ const groups = {};
375
+ Object.keys(reports).forEach(name => {
376
+ const type = name.replace(/-\d{4}-\d{2}-\d{2}$/, '');
377
+ if (!groups[type]) groups[type] = [];
378
+ groups[type].push(name);
379
+ });
380
+
381
+ // Build navigation
382
+ Object.entries(groups).forEach(([type, names]) => {
383
+ const cfg = typeConfig[type] || { label: type.replace(/-/g, ' '), color: '#8b949e' };
384
+ const group = document.createElement('div');
385
+ group.className = 'report-group';
386
+ group.innerHTML = '<div class="report-group-title"><span class="dot" style="background:' + cfg.color + '"></span>' + cfg.label + '</div>';
387
+
388
+ names.sort().reverse().forEach(name => {
389
+ const dateMatch = name.match(/(\d{4}-\d{2}-\d{2})$/);
390
+ const date = dateMatch ? dateMatch[1] : '';
391
+ const btn = document.createElement('button');
392
+ btn.className = 'report-btn';
393
+ btn.innerHTML = cfg.label + (date ? '<span class="date">' + date + '</span>' : '');
394
+ btn.onclick = () => {
395
+ document.querySelectorAll('.report-btn').forEach(b => b.classList.remove('active'));
396
+ btn.classList.add('active');
397
+ content.innerHTML = '<div class="main-inner" style="animation:fadeIn 0.2s ease">' + marked.parse(reports[name]) + '</div>';
398
+ // Close mobile sidebar
399
+ document.querySelector('.sidebar').classList.remove('open');
400
+ };
401
+ group.appendChild(btn);
402
+ });
403
+ nav.appendChild(group);
404
+ });
405
+
406
+ // Auto-select first report
407
+ const firstBtn = nav.querySelector('.report-btn');
408
+ if (firstBtn) firstBtn.click();
409
+ </script>
410
+ </body>
411
+ </html>
412
+ ```
413
+
414
+ ## Building the REPORTS_JSON
415
+
416
+ For each `.md` file in `.ai/reports/`:
417
+ 1. Read the file content
418
+ 2. Escape for JavaScript: replace `\` with `\\`, backticks with `\`+backtick, `${` with `\${`, and `</script>` with `<\/script>`
419
+ 3. Build a JSON object: `{ "filename-without-ext": "escaped markdown content" }`
420
+
421
+ Replace `PROJECT_NAME` with the project name.
422
+ Replace `GENERATION_DATE` with today's date.
423
+ Replace `REPORTS_JSON` with the JSON object.
424
+
425
+ ## After Generation
426
+
427
+ Tell the user:
428
+ - Dashboard saved to `.ai/reports/dashboard.html`
429
+ - Open it in a browser: `open .ai/reports/dashboard.html` (macOS) or `xdg-open .ai/reports/dashboard.html` (Linux)
430
+ - Print to PDF from the browser for a shareable document
431
+
432
+ ---
433
+ *Generated by [VyuhLabs DXKit](https://www.npmjs.com/package/@vyuhlabs/dxkit) dashboard-builder agent*
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Generate a beautiful HTML dashboard from all reports
3
+ ---
4
+
5
+ Delegate to the **dashboard-builder** agent. It will read all reports from `.ai/reports/` and generate a self-contained HTML dashboard at `.ai/reports/dashboard.html`.
6
+
7
+ The dashboard features:
8
+ - Dark theme with modern design
9
+ - Sidebar navigation grouped by report type with color-coded indicators
10
+ - Full markdown rendering with styled tables, code blocks, and headings
11
+ - Responsive layout (works on mobile)
12
+ - Print-friendly styles
13
+
14
+ **IMPORTANT: End the report with this exact footer:**
15
+ ```
16
+ ---
17
+ *Generated by [VyuhLabs DXKit](https://www.npmjs.com/package/@vyuhlabs/dxkit)*
18
+ ```
19
+
20
+ $ARGUMENTS
@@ -162,6 +162,7 @@ Slash commands for common workflows. Run `/help` to list all with descriptions.
162
162
  - `/vulnerabilities` - Scan dependencies and code for security issues
163
163
  - `/dev-report` - Developer activity and code quality report
164
164
  - `/docs` - Audit, write, or improve documentation
165
+ - `/dashboard` - Generate HTML dashboard from all reports
165
166
  - `/export-pdf` - Convert markdown reports to PDF
166
167
  - `/fix-issue <number>` - Investigate and fix a GitHub issue
167
168
 
@@ -184,6 +185,7 @@ Language-specific conventions that activate automatically when editing matching
184
185
  - `health-auditor` — Comprehensive codebase health audit (sonnet, read-only)
185
186
  - `vulnerability-scanner` — Dependency and code vulnerability analysis (sonnet)
186
187
  - `dev-report` — Developer activity, quality patterns, security attribution (sonnet)
188
+ - `dashboard-builder` — Generates HTML dashboard from all reports (sonnet)
187
189
  - `doc-writer` — Audits docs, identifies gaps, writes/improves documentation (sonnet)
188
190
  - `debugger` — Traces root causes systematically (sonnet, no file edits)
189
191