@iservu-inc/adf-cli 0.9.1 → 0.11.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.
@@ -0,0 +1,1383 @@
1
+ # Learning Analytics Dashboard - Design Specification
2
+
3
+ **Version:** 1.0
4
+ **Date:** 2025-10-27
5
+ **Phase:** Phase 6 - Advanced Learning Features
6
+ **Status:** Design Complete
7
+
8
+ ---
9
+
10
+ ## Table of Contents
11
+
12
+ 1. [Overview](#overview)
13
+ 2. [Goals](#goals)
14
+ 3. [Data Sources](#data-sources)
15
+ 4. [Analytics Metrics](#analytics-metrics)
16
+ 5. [Dashboard Interface](#dashboard-interface)
17
+ 6. [Calculations & Algorithms](#calculations--algorithms)
18
+ 7. [Export Formats](#export-formats)
19
+ 8. [Implementation Plan](#implementation-plan)
20
+ 9. [Testing Strategy](#testing-strategy)
21
+
22
+ ---
23
+
24
+ ## Overview
25
+
26
+ The Learning Analytics Dashboard provides comprehensive insights into the ADF CLI learning system's behavior, effectiveness, and user patterns. It enables users to understand how the learning system is performing and make data-driven decisions about their learned preferences.
27
+
28
+ **Key Features:**
29
+ - 10+ meaningful analytics metrics
30
+ - Time-series trend visualization (ASCII charts)
31
+ - Pattern confidence distribution analysis
32
+ - Learning effectiveness calculations
33
+ - Export to JSON/CSV for external analysis
34
+ - Performance optimized for large datasets
35
+
36
+ ---
37
+
38
+ ## Goals
39
+
40
+ ### Primary Goals
41
+ 1. **Transparency** - Show users what the learning system has learned
42
+ 2. **Insights** - Provide actionable insights about skip behavior and patterns
43
+ 3. **Effectiveness** - Measure time savings and filtering accuracy
44
+ 4. **Confidence** - Display pattern confidence distribution and decay status
45
+ 5. **Export** - Enable data export for team sharing and external tools
46
+
47
+ ### Success Criteria
48
+ - Dashboard shows 10+ meaningful insights
49
+ - Performance acceptable with 100+ sessions (< 2 seconds load time)
50
+ - Export works in both JSON and CSV formats
51
+ - All metrics have clear explanations
52
+ - Visual charts render correctly in CLI
53
+
54
+ ---
55
+
56
+ ## Data Sources
57
+
58
+ ### 1. Skip History (`skip-history.json`)
59
+ ```json
60
+ {
61
+ "version": "1.0",
62
+ "sessions": [
63
+ {
64
+ "sessionId": "uuid",
65
+ "timestamp": "2025-10-27T...",
66
+ "projectType": "cli-tool",
67
+ "frameworks": ["commander"],
68
+ "languages": ["javascript"],
69
+ "skips": [
70
+ {
71
+ "questionId": "q_deployment_strategy",
72
+ "text": "What deployment strategy?",
73
+ "category": "deployment",
74
+ "phase": "planning",
75
+ "action": "skipped",
76
+ "reason": "manual", // or "filtered"
77
+ "timeViewed": 2.5,
78
+ "relevanceScore": 30,
79
+ "skipReason": "Not relevant for CLI"
80
+ }
81
+ ],
82
+ "answers": []
83
+ }
84
+ ]
85
+ }
86
+ ```
87
+
88
+ ### 2. Answer History (`answer-history.json`)
89
+ ```json
90
+ {
91
+ "version": "1.0",
92
+ "sessions": [
93
+ {
94
+ "sessionId": "uuid",
95
+ "timestamp": "2025-10-27T...",
96
+ "projectType": "cli-tool",
97
+ "frameworks": ["commander"],
98
+ "answers": [
99
+ {
100
+ "questionId": "q_core_purpose",
101
+ "text": "What is the core purpose?",
102
+ "category": "overview",
103
+ "phase": "discovery",
104
+ "action": "answered",
105
+ "answerLength": 250,
106
+ "wordCount": 45,
107
+ "timeSpent": 45.2,
108
+ "qualityScore": 85,
109
+ "richness": 0.72,
110
+ "relevanceScore": 100
111
+ }
112
+ ]
113
+ }
114
+ ]
115
+ }
116
+ ```
117
+
118
+ ### 3. Patterns (`patterns.json`)
119
+ ```json
120
+ {
121
+ "version": "1.0",
122
+ "lastUpdated": "2025-10-27T...",
123
+ "lastDecayCheck": "2025-10-27T...",
124
+ "patterns": [
125
+ {
126
+ "id": "pattern_skip_q_deployment_strategy",
127
+ "type": "consistent_skip",
128
+ "questionId": "q_deployment_strategy",
129
+ "questionText": "What deployment strategy?",
130
+ "category": "deployment",
131
+ "confidence": 100,
132
+ "sessionsAnalyzed": 5,
133
+ "skipCount": 5,
134
+ "recommendation": "Auto-filter this question",
135
+ "status": "active",
136
+ "userApproved": true,
137
+ "createdAt": "2025-10-15T...",
138
+ "lastSeen": "2025-10-27T...",
139
+ "timesRenewed": 2,
140
+ "lastDecayCalculation": "2025-10-27T..."
141
+ }
142
+ ]
143
+ }
144
+ ```
145
+
146
+ ### 4. Learned Rules (`learned-rules.json`)
147
+ ```json
148
+ {
149
+ "version": "1.0",
150
+ "rules": [
151
+ {
152
+ "id": "rule_skip_q_deployment_strategy",
153
+ "patternId": "pattern_skip_q_deployment_strategy",
154
+ "type": "question_filter",
155
+ "enabled": true,
156
+ "createdAt": "2025-10-15T...",
157
+ "appliedCount": 12,
158
+ "lastApplied": "2025-10-27T..."
159
+ }
160
+ ]
161
+ }
162
+ ```
163
+
164
+ ### 5. Statistics (`stats.json`)
165
+ ```json
166
+ {
167
+ "version": "1.0",
168
+ "totalSessions": 15,
169
+ "totalSkips": 45,
170
+ "totalAnswers": 120,
171
+ "patternsDetected": 8,
172
+ "rulesApplied": 3,
173
+ "lastUpdated": "2025-10-27T..."
174
+ }
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Analytics Metrics
180
+
181
+ ### 1. Overview Statistics
182
+ **Purpose:** High-level summary of learning system activity
183
+
184
+ **Metrics:**
185
+ - Total sessions conducted
186
+ - Total questions skipped (manual + filtered)
187
+ - Total questions answered
188
+ - Active patterns count
189
+ - Active learned rules count
190
+ - Learning system age (days since first session)
191
+ - Data size (MB)
192
+
193
+ **Calculation:**
194
+ ```javascript
195
+ {
196
+ totalSessions: stats.totalSessions,
197
+ totalSkips: stats.totalSkips,
198
+ totalAnswers: stats.totalAnswers,
199
+ activePatterns: patterns.patterns.filter(p => p.status === 'active').length,
200
+ activeRules: rules.rules.filter(r => r.enabled).length,
201
+ learningAge: daysSince(firstSession.timestamp),
202
+ dataSize: await storage.getLearningDataSize() / 1024 / 1024 // MB
203
+ }
204
+ ```
205
+
206
+ ---
207
+
208
+ ### 2. Skip Trends Over Time
209
+ **Purpose:** Visualize skip behavior evolution
210
+
211
+ **Metrics:**
212
+ - Skip count by week (last 12 weeks)
213
+ - Manual skips vs filtered skips over time
214
+ - Skip rate trend (% of questions skipped)
215
+
216
+ **Calculation:**
217
+ ```javascript
218
+ function calculateSkipTrends(skipHistory) {
219
+ const weeks = getLast12Weeks();
220
+ const trendData = weeks.map(week => {
221
+ const weekSessions = filterSessionsByWeek(skipHistory.sessions, week);
222
+ const manualSkips = countSkipsByReason(weekSessions, 'manual');
223
+ const filteredSkips = countSkipsByReason(weekSessions, 'filtered');
224
+ const totalQuestions = manualSkips + filteredSkips + countAnswers(weekSessions);
225
+
226
+ return {
227
+ week: week.label,
228
+ manualSkips,
229
+ filteredSkips,
230
+ totalSkips: manualSkips + filteredSkips,
231
+ skipRate: Math.round((manualSkips + filteredSkips) / totalQuestions * 100)
232
+ };
233
+ });
234
+
235
+ return trendData;
236
+ }
237
+ ```
238
+
239
+ **Visualization:** ASCII bar chart
240
+ ```
241
+ Skip Trends (Last 12 Weeks)
242
+ Week 40: ████████░░ 15 skips (8 manual, 7 filtered)
243
+ Week 41: ██████████ 20 skips (12 manual, 8 filtered)
244
+ Week 42: ████░░░░░░ 8 skips (5 manual, 3 filtered)
245
+ ...
246
+ ```
247
+
248
+ ---
249
+
250
+ ### 3. Category Preference Heatmap
251
+ **Purpose:** Show skip rates by question category
252
+
253
+ **Metrics:**
254
+ - Skip rate per category (%)
255
+ - Most skipped categories (top 5)
256
+ - Least skipped categories (bottom 5)
257
+ - Category skip trend (increasing/decreasing)
258
+
259
+ **Calculation:**
260
+ ```javascript
261
+ function calculateCategoryPreferences(skipHistory, answerHistory) {
262
+ const categories = {};
263
+
264
+ // Count skips and answers by category
265
+ for (const session of skipHistory.sessions) {
266
+ for (const skip of session.skips) {
267
+ if (!skip.category) continue;
268
+ if (!categories[skip.category]) {
269
+ categories[skip.category] = { skips: 0, answers: 0 };
270
+ }
271
+ categories[skip.category].skips++;
272
+ }
273
+ }
274
+
275
+ for (const session of answerHistory.sessions) {
276
+ for (const answer of session.answers) {
277
+ if (!answer.category) continue;
278
+ if (!categories[answer.category]) {
279
+ categories[answer.category] = { skips: 0, answers: 0 };
280
+ }
281
+ categories[answer.category].answers++;
282
+ }
283
+ }
284
+
285
+ // Calculate skip rates
286
+ return Object.entries(categories).map(([category, data]) => {
287
+ const total = data.skips + data.answers;
288
+ const skipRate = Math.round((data.skips / total) * 100);
289
+
290
+ return {
291
+ category,
292
+ skips: data.skips,
293
+ answers: data.answers,
294
+ total,
295
+ skipRate,
296
+ level: getSkipLevel(skipRate) // "low", "medium", "high"
297
+ };
298
+ }).sort((a, b) => b.skipRate - a.skipRate);
299
+ }
300
+
301
+ function getSkipLevel(skipRate) {
302
+ if (skipRate >= 70) return 'high';
303
+ if (skipRate >= 40) return 'medium';
304
+ return 'low';
305
+ }
306
+ ```
307
+
308
+ **Visualization:** ASCII heatmap
309
+ ```
310
+ Category Preferences (Skip Rate)
311
+ deployment ████████████████████ 95% (19/20) HIGH
312
+ UI/UX ██████████████░░░░░░ 70% (14/20) HIGH
313
+ documentation ████████░░░░░░░░░░░░ 40% (8/20) MEDIUM
314
+ architecture ███░░░░░░░░░░░░░░░░░ 15% (3/20) LOW
315
+ core-features ██░░░░░░░░░░░░░░░░░░ 10% (2/20) LOW
316
+ ```
317
+
318
+ ---
319
+
320
+ ### 4. Pattern Confidence Distribution
321
+ **Purpose:** Show distribution of pattern confidence scores
322
+
323
+ **Metrics:**
324
+ - Patterns by confidence level (high/medium/low)
325
+ - Average pattern confidence
326
+ - Pattern confidence trend (improving/declining)
327
+ - Patterns approaching removal threshold
328
+
329
+ **Calculation:**
330
+ ```javascript
331
+ function calculatePatternDistribution(patterns) {
332
+ const distribution = {
333
+ high: patterns.filter(p => p.confidence >= 90).length, // 90%+
334
+ medium: patterns.filter(p => p.confidence >= 75 && p.confidence < 90).length, // 75-89%
335
+ low: patterns.filter(p => p.confidence < 75 && p.confidence >= 50).length, // 50-74%
336
+ veryLow: patterns.filter(p => p.confidence < 50).length // <50%
337
+ };
338
+
339
+ const avgConfidence = patterns.reduce((sum, p) => sum + p.confidence, 0) / patterns.length;
340
+
341
+ const atRisk = patterns.filter(p => p.confidence < 50 || isInactive(p, 5)); // <50 or 5+ months inactive
342
+
343
+ return {
344
+ distribution,
345
+ avgConfidence: Math.round(avgConfidence),
346
+ totalPatterns: patterns.length,
347
+ atRiskCount: atRisk.length,
348
+ atRiskPatterns: atRisk
349
+ };
350
+ }
351
+ ```
352
+
353
+ **Visualization:** ASCII pie chart representation
354
+ ```
355
+ Pattern Confidence Distribution
356
+ High (90%+): ████████░░ 8 patterns (53%)
357
+ Medium (75-89%): ████░░░░░░ 4 patterns (27%)
358
+ Low (50-74%): ██░░░░░░░░ 2 patterns (13%)
359
+ Very Low (<50%): █░░░░░░░░░ 1 pattern (7%)
360
+
361
+ Average Confidence: 78%
362
+ At Risk (decay): 1 pattern
363
+ ```
364
+
365
+ ---
366
+
367
+ ### 5. Learning Effectiveness
368
+ **Purpose:** Measure learning system's impact and accuracy
369
+
370
+ **Metrics:**
371
+ - Time saved (estimated minutes)
372
+ - Questions auto-filtered successfully
373
+ - False positive rate (filtered but should answer)
374
+ - Pattern accuracy (approved patterns / total patterns)
375
+ - Rule application rate (how often rules are triggered)
376
+
377
+ **Calculation:**
378
+ ```javascript
379
+ function calculateEffectiveness(skipHistory, patterns, rules) {
380
+ // Time saved: filtered questions × avg time per question
381
+ const avgTimePerQuestion = 2.5; // minutes (from answer data)
382
+ const questionsFiltered = countFilteredQuestions(skipHistory);
383
+ const timeSavedMinutes = Math.round(questionsFiltered * avgTimePerQuestion);
384
+
385
+ // False positives: filtered questions that user later answered manually
386
+ // (This would require tracking if a filtered question was later answered)
387
+ const falsePositives = 0; // TODO: Implement tracking in Phase 6.1
388
+
389
+ // Pattern accuracy: user-approved patterns / total patterns
390
+ const approvedPatterns = patterns.filter(p => p.userApproved).length;
391
+ const patternAccuracy = Math.round((approvedPatterns / patterns.length) * 100);
392
+
393
+ // Rule application rate: how often rules actually filter questions
394
+ const totalRuleApplications = rules.reduce((sum, r) => sum + (r.appliedCount || 0), 0);
395
+ const avgApplicationsPerRule = Math.round(totalRuleApplications / rules.length);
396
+
397
+ return {
398
+ timeSavedMinutes,
399
+ questionsFiltered,
400
+ falsePositives,
401
+ falsePositiveRate: 0, // TODO
402
+ patternAccuracy,
403
+ totalRuleApplications,
404
+ avgApplicationsPerRule,
405
+ effectiveness: calculateOverallEffectiveness(patternAccuracy, falsePositives)
406
+ };
407
+ }
408
+
409
+ function calculateOverallEffectiveness(accuracy, falsePositives) {
410
+ // Simple formula: accuracy - (falsePositives * 5)
411
+ // Each false positive reduces effectiveness by 5%
412
+ const effectiveness = accuracy - (falsePositives * 5);
413
+ return Math.max(0, Math.min(100, effectiveness));
414
+ }
415
+ ```
416
+
417
+ **Visualization:**
418
+ ```
419
+ Learning Effectiveness
420
+
421
+ Time Saved: 145 minutes (2.4 hours)
422
+ Questions Filtered: 58 questions
423
+ Pattern Accuracy: 87% (13/15 patterns approved)
424
+ Rule Applications: 42 total (3.5 avg per rule)
425
+
426
+ Overall Effectiveness: 87%
427
+ Status: EXCELLENT ✓
428
+ ```
429
+
430
+ ---
431
+
432
+ ### 6. Pattern Decay Status
433
+ **Purpose:** Show pattern health and decay trends
434
+
435
+ **Metrics:**
436
+ - Patterns by decay status (healthy/warning/critical)
437
+ - Patterns renewed in last 30 days
438
+ - Patterns approaching removal threshold
439
+ - Average pattern age (days)
440
+ - Decay rate distribution
441
+
442
+ **Calculation:**
443
+ ```javascript
444
+ function calculateDecayStatus(patterns, decayConfig) {
445
+ const now = new Date();
446
+ const decayStatus = {
447
+ healthy: [],
448
+ warning: [],
449
+ critical: []
450
+ };
451
+
452
+ for (const pattern of patterns) {
453
+ const daysSinceLastSeen = daysBetween(new Date(pattern.lastSeen), now);
454
+ const monthsInactive = daysSinceLastSeen / 30;
455
+
456
+ // Categorize by confidence and inactivity
457
+ if (pattern.confidence >= 75 && monthsInactive < 3) {
458
+ decayStatus.healthy.push(pattern);
459
+ } else if (pattern.confidence >= 50 && monthsInactive < 5) {
460
+ decayStatus.warning.push(pattern);
461
+ } else {
462
+ decayStatus.critical.push(pattern);
463
+ }
464
+ }
465
+
466
+ const recentlyRenewed = patterns.filter(p => {
467
+ const renewalDate = new Date(pattern.lastSeen);
468
+ return daysBetween(renewalDate, now) <= 30;
469
+ });
470
+
471
+ const avgAge = patterns.reduce((sum, p) => {
472
+ return sum + daysBetween(new Date(p.createdAt), now);
473
+ }, 0) / patterns.length;
474
+
475
+ return {
476
+ healthy: decayStatus.healthy.length,
477
+ warning: decayStatus.warning.length,
478
+ critical: decayStatus.critical.length,
479
+ recentlyRenewed: recentlyRenewed.length,
480
+ avgAge: Math.round(avgAge),
481
+ needsAttention: decayStatus.critical
482
+ };
483
+ }
484
+ ```
485
+
486
+ **Visualization:**
487
+ ```
488
+ Pattern Decay Status
489
+
490
+ Healthy (75%+, <3mo): ████████░░ 8 patterns (53%)
491
+ Warning (50-74%, 3-5mo): ████░░░░░░ 4 patterns (27%)
492
+ Critical (<50%, >5mo): ██░░░░░░░░ 2 patterns (13%)
493
+ Recently Renewed: 1 pattern (last 30 days)
494
+
495
+ Average Pattern Age: 45 days
496
+ Patterns Needing Attention: 2 patterns
497
+
498
+ ⚠ Warning: 2 patterns approaching removal threshold
499
+ ```
500
+
501
+ ---
502
+
503
+ ### 7. Session Timeline
504
+ **Purpose:** Show session history and frequency
505
+
506
+ **Metrics:**
507
+ - Session frequency (sessions per week)
508
+ - Session count by project type
509
+ - Most active time period
510
+ - Sessions with most skips/answers
511
+
512
+ **Calculation:**
513
+ ```javascript
514
+ function calculateSessionTimeline(skipHistory, answerHistory) {
515
+ const sessions = skipHistory.sessions;
516
+ const timeline = [];
517
+
518
+ for (const session of sessions) {
519
+ const skipCount = session.skips.length;
520
+ const matchingAnswerSession = answerHistory.sessions.find(
521
+ s => s.sessionId === session.sessionId
522
+ );
523
+ const answerCount = matchingAnswerSession ? matchingAnswerSession.answers.length : 0;
524
+
525
+ timeline.push({
526
+ sessionId: session.sessionId,
527
+ timestamp: session.timestamp,
528
+ projectType: session.projectType,
529
+ frameworks: session.frameworks,
530
+ skipCount,
531
+ answerCount,
532
+ totalQuestions: skipCount + answerCount
533
+ });
534
+ }
535
+
536
+ // Calculate frequency
537
+ const firstSession = new Date(sessions[0].timestamp);
538
+ const lastSession = new Date(sessions[sessions.length - 1].timestamp);
539
+ const weeksBetween = Math.ceil(daysBetween(firstSession, lastSession) / 7);
540
+ const sessionsPerWeek = sessions.length / weeksBetween;
541
+
542
+ return {
543
+ timeline: timeline.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp)),
544
+ sessionsPerWeek: sessionsPerWeek.toFixed(1),
545
+ totalSessions: sessions.length,
546
+ firstSession: firstSession.toISOString().split('T')[0],
547
+ lastSession: lastSession.toISOString().split('T')[0]
548
+ };
549
+ }
550
+ ```
551
+
552
+ ---
553
+
554
+ ### 8. Most Impactful Patterns
555
+ **Purpose:** Highlight patterns with biggest impact
556
+
557
+ **Metrics:**
558
+ - Top 5 patterns by time saved
559
+ - Top 5 patterns by application count
560
+ - Newest high-confidence patterns
561
+ - Most consistent patterns (100% confidence)
562
+
563
+ **Calculation:**
564
+ ```javascript
565
+ function calculateImpactfulPatterns(patterns, rules, skipHistory) {
566
+ const impactData = [];
567
+
568
+ for (const pattern of patterns) {
569
+ const matchingRule = rules.find(r => r.patternId === pattern.id);
570
+ const appliedCount = matchingRule ? matchingRule.appliedCount : 0;
571
+ const timeSaved = appliedCount * 2.5; // 2.5 min per question
572
+
573
+ impactData.push({
574
+ pattern,
575
+ appliedCount,
576
+ timeSaved,
577
+ impact: calculateImpact(appliedCount, pattern.confidence)
578
+ });
579
+ }
580
+
581
+ return {
582
+ topByTimeSaved: impactData.sort((a, b) => b.timeSaved - a.timeSaved).slice(0, 5),
583
+ topByApplications: impactData.sort((a, b) => b.appliedCount - a.appliedCount).slice(0, 5),
584
+ perfectConfidence: patterns.filter(p => p.confidence === 100),
585
+ newestHighConfidence: patterns
586
+ .filter(p => p.confidence >= 90)
587
+ .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
588
+ .slice(0, 5)
589
+ };
590
+ }
591
+
592
+ function calculateImpact(applications, confidence) {
593
+ // Impact = applications × confidence × 0.01
594
+ return Math.round(applications * confidence * 0.01);
595
+ }
596
+ ```
597
+
598
+ ---
599
+
600
+ ### 9. Question Statistics
601
+ **Purpose:** Detailed question-level analytics
602
+
603
+ **Metrics:**
604
+ - Most answered questions (top 10)
605
+ - Most skipped questions (top 10)
606
+ - Questions with lowest skip rate
607
+ - Average time per question by category
608
+
609
+ **Calculation:**
610
+ ```javascript
611
+ function calculateQuestionStats(skipHistory, answerHistory) {
612
+ const questionData = {};
613
+
614
+ // Aggregate skip data
615
+ for (const session of skipHistory.sessions) {
616
+ for (const skip of session.skips) {
617
+ if (!questionData[skip.questionId]) {
618
+ questionData[skip.questionId] = {
619
+ questionId: skip.questionId,
620
+ text: skip.text,
621
+ category: skip.category,
622
+ skips: 0,
623
+ answers: 0,
624
+ totalTimeSpent: 0,
625
+ avgTimeSpent: 0
626
+ };
627
+ }
628
+ questionData[skip.questionId].skips++;
629
+ }
630
+ }
631
+
632
+ // Aggregate answer data
633
+ for (const session of answerHistory.sessions) {
634
+ for (const answer of session.answers) {
635
+ if (!questionData[answer.questionId]) {
636
+ questionData[answer.questionId] = {
637
+ questionId: answer.questionId,
638
+ text: answer.text,
639
+ category: answer.category,
640
+ skips: 0,
641
+ answers: 0,
642
+ totalTimeSpent: 0,
643
+ avgTimeSpent: 0
644
+ };
645
+ }
646
+ questionData[answer.questionId].answers++;
647
+ questionData[answer.questionId].totalTimeSpent += answer.timeSpent || 0;
648
+ }
649
+ }
650
+
651
+ // Calculate averages and rates
652
+ const stats = Object.values(questionData).map(q => {
653
+ const total = q.skips + q.answers;
654
+ q.skipRate = Math.round((q.skips / total) * 100);
655
+ q.avgTimeSpent = q.answers > 0 ? Math.round(q.totalTimeSpent / q.answers) : 0;
656
+ return q;
657
+ });
658
+
659
+ return {
660
+ mostAnswered: stats.sort((a, b) => b.answers - a.answers).slice(0, 10),
661
+ mostSkipped: stats.sort((a, b) => b.skips - a.skips).slice(0, 10),
662
+ lowestSkipRate: stats.sort((a, b) => a.skipRate - b.skipRate).slice(0, 10),
663
+ avgTimeByCategory: calculateAvgTimeByCategory(stats)
664
+ };
665
+ }
666
+ ```
667
+
668
+ ---
669
+
670
+ ### 10. Export Summary
671
+ **Purpose:** Provide metadata for exported analytics
672
+
673
+ **Metrics:**
674
+ - Export timestamp
675
+ - Data range (first session to last session)
676
+ - Export version
677
+ - Data completeness indicators
678
+
679
+ ---
680
+
681
+ ## Dashboard Interface
682
+
683
+ ### CLI Navigation Structure
684
+
685
+ ```
686
+ Learning System
687
+ ├── View Skip History
688
+ ├── Review Patterns
689
+ ├── Manage Rules
690
+ ├── Analytics Dashboard ← NEW
691
+ │ ├── Overview
692
+ │ ├── Skip Trends
693
+ │ ├── Category Preferences
694
+ │ ├── Pattern Health
695
+ │ ├── Effectiveness
696
+ │ ├── Question Stats
697
+ │ └── Export Analytics
698
+ ├── Settings
699
+ └── Clear Data
700
+ ```
701
+
702
+ ### Dashboard Layout
703
+
704
+ ```
705
+ ═══════════════════════════════════════════════════════════════
706
+ LEARNING ANALYTICS DASHBOARD
707
+ ═══════════════════════════════════════════════════════════════
708
+
709
+ 📊 OVERVIEW
710
+
711
+ Total Sessions: 15 sessions
712
+ Total Skips: 45 questions (30 manual, 15 filtered)
713
+ Total Answers: 120 questions
714
+ Active Patterns: 8 patterns
715
+ Active Rules: 3 rules
716
+ Learning System Age: 32 days
717
+ Data Size: 0.15 MB
718
+
719
+ ───────────────────────────────────────────────────────────────
720
+
721
+ 📈 SKIP TRENDS (Last 12 Weeks)
722
+
723
+ Week 40: ████████░░ 15 skips (10 manual, 5 filtered)
724
+ Week 41: ██████████ 20 skips (13 manual, 7 filtered)
725
+ Week 42: ████░░░░░░ 8 skips (5 manual, 3 filtered)
726
+ Week 43: ░░░░░░░░░░ 0 skips (no sessions)
727
+
728
+ Trend: Decreasing (↓ 40% from peak)
729
+
730
+ ───────────────────────────────────────────────────────────────
731
+
732
+ 🎯 CATEGORY PREFERENCES
733
+
734
+ deployment ████████████████████ 95% (19/20) HIGH
735
+ UI/UX ██████████████░░░░░░ 70% (14/20) HIGH
736
+ documentation ████████░░░░░░░░░░░░ 40% (8/20) MEDIUM
737
+ architecture ███░░░░░░░░░░░░░░░░░ 15% (3/20) LOW
738
+ core-features ██░░░░░░░░░░░░░░░░░░ 10% (2/20) LOW
739
+
740
+ ───────────────────────────────────────────────────────────────
741
+
742
+ 🧬 PATTERN HEALTH
743
+
744
+ Healthy (75%+): ████████░░ 8 patterns (53%)
745
+ Warning (50-74%): ████░░░░░░ 4 patterns (27%)
746
+ Critical (<50%): ██░░░░░░░░ 2 patterns (13%)
747
+
748
+ Average Confidence: 78%
749
+ Recently Renewed: 1 pattern (last 30 days)
750
+
751
+ ⚠ Warning: 2 patterns approaching removal threshold
752
+
753
+ ───────────────────────────────────────────────────────────────
754
+
755
+ ✨ EFFECTIVENESS
756
+
757
+ Time Saved: 145 minutes (2.4 hours)
758
+ Questions Filtered: 58 questions
759
+ Pattern Accuracy: 87% (13/15 patterns approved)
760
+ Rule Applications: 42 total (3.5 avg per rule)
761
+
762
+ Overall Effectiveness: 87% ✓ EXCELLENT
763
+
764
+ ───────────────────────────────────────────────────────────────
765
+
766
+ ? What would you like to do?
767
+
768
+ View Detailed Skip Trends
769
+ View Category Breakdown
770
+ View Pattern Details
771
+ View Question Statistics
772
+ ❯ Export Analytics (JSON/CSV)
773
+ Back to Learning System
774
+
775
+ ───────────────────────────────────────────────────────────────
776
+ ```
777
+
778
+ ### Interactive Features
779
+
780
+ 1. **Navigation**
781
+ - Arrow keys to navigate sections
782
+ - Enter to select/drill down
783
+ - 'q' or ESC to go back
784
+ - 'e' to export from any view
785
+
786
+ 2. **Drill-Down Views**
787
+ - Click on any metric to see detailed breakdown
788
+ - Example: Click "Category Preferences" → See detailed category analysis with all questions
789
+
790
+ 3. **Filtering**
791
+ - Filter by date range
792
+ - Filter by project type
793
+ - Filter by confidence level
794
+
795
+ 4. **Refresh**
796
+ - Auto-refresh option (every N seconds)
797
+ - Manual refresh with 'r' key
798
+
799
+ ---
800
+
801
+ ## Calculations & Algorithms
802
+
803
+ ### Helper Functions
804
+
805
+ ```javascript
806
+ // Date utilities
807
+ function daysBetween(date1, date2) {
808
+ return Math.floor((date2 - date1) / (1000 * 60 * 60 * 24));
809
+ }
810
+
811
+ function getLast12Weeks() {
812
+ const weeks = [];
813
+ const now = new Date();
814
+
815
+ for (let i = 11; i >= 0; i--) {
816
+ const weekStart = new Date(now);
817
+ weekStart.setDate(now.getDate() - (i * 7));
818
+ const weekEnd = new Date(weekStart);
819
+ weekEnd.setDate(weekStart.getDate() + 6);
820
+
821
+ weeks.push({
822
+ label: `Week ${getWeekNumber(weekStart)}`,
823
+ start: weekStart,
824
+ end: weekEnd
825
+ });
826
+ }
827
+
828
+ return weeks;
829
+ }
830
+
831
+ function getWeekNumber(date) {
832
+ const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
833
+ const pastDaysOfYear = (date - firstDayOfYear) / 86400000;
834
+ return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
835
+ }
836
+
837
+ // Session filtering
838
+ function filterSessionsByWeek(sessions, week) {
839
+ return sessions.filter(session => {
840
+ const sessionDate = new Date(session.timestamp);
841
+ return sessionDate >= week.start && sessionDate <= week.end;
842
+ });
843
+ }
844
+
845
+ function countSkipsByReason(sessions, reason) {
846
+ return sessions.reduce((count, session) => {
847
+ return count + session.skips.filter(s => s.reason === reason).length;
848
+ }, 0);
849
+ }
850
+
851
+ function countAnswers(sessions) {
852
+ return sessions.reduce((count, session) => {
853
+ return count + session.answers.length;
854
+ }, 0);
855
+ }
856
+
857
+ // Inactivity detection
858
+ function isInactive(pattern, months) {
859
+ const now = new Date();
860
+ const lastSeen = new Date(pattern.lastSeen);
861
+ const monthsInactive = (now - lastSeen) / (1000 * 60 * 60 * 24 * 30);
862
+ return monthsInactive >= months;
863
+ }
864
+
865
+ // ASCII chart generation
866
+ function generateBarChart(data, maxWidth = 20) {
867
+ const maxValue = Math.max(...data.map(d => d.value));
868
+
869
+ return data.map(item => {
870
+ const barWidth = Math.round((item.value / maxValue) * maxWidth);
871
+ const bar = '█'.repeat(barWidth) + '░'.repeat(maxWidth - barWidth);
872
+ return `${item.label.padEnd(15)} ${bar} ${item.value}`;
873
+ }).join('\n');
874
+ }
875
+
876
+ function generatePieChart(data, totalWidth = 10) {
877
+ const total = data.reduce((sum, d) => sum + d.value, 0);
878
+
879
+ return data.map(item => {
880
+ const percentage = Math.round((item.value / total) * 100);
881
+ const barWidth = Math.round((item.value / total) * totalWidth);
882
+ const bar = '█'.repeat(barWidth) + '░'.repeat(totalWidth - barWidth);
883
+ return `${item.label.padEnd(15)} ${bar} ${item.value} (${percentage}%)`;
884
+ }).join('\n');
885
+ }
886
+ ```
887
+
888
+ ---
889
+
890
+ ## Export Formats
891
+
892
+ ### JSON Export Format
893
+
894
+ ```json
895
+ {
896
+ "version": "1.0",
897
+ "exportedAt": "2025-10-27T12:34:56Z",
898
+ "exportType": "learning-analytics",
899
+ "dataRange": {
900
+ "firstSession": "2025-09-15T...",
901
+ "lastSession": "2025-10-27T...",
902
+ "totalSessions": 15,
903
+ "daysSpanned": 42
904
+ },
905
+ "overview": {
906
+ "totalSessions": 15,
907
+ "totalSkips": 45,
908
+ "totalAnswers": 120,
909
+ "activePatterns": 8,
910
+ "activeRules": 3,
911
+ "learningAge": 42,
912
+ "dataSizeMB": 0.15
913
+ },
914
+ "skipTrends": [
915
+ {
916
+ "week": "Week 40",
917
+ "manualSkips": 10,
918
+ "filteredSkips": 5,
919
+ "totalSkips": 15,
920
+ "skipRate": 30
921
+ }
922
+ ],
923
+ "categoryPreferences": [
924
+ {
925
+ "category": "deployment",
926
+ "skips": 19,
927
+ "answers": 1,
928
+ "total": 20,
929
+ "skipRate": 95,
930
+ "level": "high"
931
+ }
932
+ ],
933
+ "patternDistribution": {
934
+ "distribution": {
935
+ "high": 8,
936
+ "medium": 4,
937
+ "low": 2,
938
+ "veryLow": 1
939
+ },
940
+ "avgConfidence": 78,
941
+ "totalPatterns": 15,
942
+ "atRiskCount": 2
943
+ },
944
+ "effectiveness": {
945
+ "timeSavedMinutes": 145,
946
+ "questionsFiltered": 58,
947
+ "patternAccuracy": 87,
948
+ "totalRuleApplications": 42,
949
+ "avgApplicationsPerRule": 3.5,
950
+ "overallEffectiveness": 87
951
+ },
952
+ "decayStatus": {
953
+ "healthy": 8,
954
+ "warning": 4,
955
+ "critical": 2,
956
+ "recentlyRenewed": 1,
957
+ "avgAge": 45
958
+ },
959
+ "questionStats": {
960
+ "mostAnswered": [...],
961
+ "mostSkipped": [...],
962
+ "lowestSkipRate": [...]
963
+ }
964
+ }
965
+ ```
966
+
967
+ ### CSV Export Format
968
+
969
+ **File 1: `analytics-overview.csv`**
970
+ ```csv
971
+ Metric,Value,Unit
972
+ Total Sessions,15,sessions
973
+ Total Skips,45,questions
974
+ Total Answers,120,questions
975
+ Active Patterns,8,patterns
976
+ Active Rules,3,rules
977
+ Learning Age,42,days
978
+ Data Size,0.15,MB
979
+ Time Saved,145,minutes
980
+ Pattern Accuracy,87,%
981
+ Overall Effectiveness,87,%
982
+ ```
983
+
984
+ **File 2: `analytics-skip-trends.csv`**
985
+ ```csv
986
+ Week,Manual Skips,Filtered Skips,Total Skips,Skip Rate
987
+ Week 40,10,5,15,30
988
+ Week 41,13,7,20,35
989
+ Week 42,5,3,8,20
990
+ ```
991
+
992
+ **File 3: `analytics-category-preferences.csv`**
993
+ ```csv
994
+ Category,Skips,Answers,Total,Skip Rate,Level
995
+ deployment,19,1,20,95,high
996
+ UI/UX,14,6,20,70,high
997
+ documentation,8,12,20,40,medium
998
+ ```
999
+
1000
+ **File 4: `analytics-patterns.csv`**
1001
+ ```csv
1002
+ Pattern ID,Type,Confidence,Status,Created At,Last Seen,Times Renewed
1003
+ pattern_skip_q_deployment,consistent_skip,100,active,2025-10-15,2025-10-27,2
1004
+ ```
1005
+
1006
+ ---
1007
+
1008
+ ## Implementation Plan
1009
+
1010
+ ### Phase 1: Core Analytics Module
1011
+ **Files to create:**
1012
+ - `lib/learning/analytics.js` - Core analytics module with all calculation functions
1013
+
1014
+ **Features:**
1015
+ 1. Overview statistics calculation
1016
+ 2. Skip trends calculation
1017
+ 3. Category preferences calculation
1018
+ 4. Pattern distribution calculation
1019
+ 5. Effectiveness calculation
1020
+ 6. Decay status calculation
1021
+
1022
+ **Estimated effort:** 4-6 hours
1023
+
1024
+ ---
1025
+
1026
+ ### Phase 2: Dashboard UI
1027
+ **Files to create:**
1028
+ - `lib/learning/analytics-view.js` - CLI dashboard UI
1029
+
1030
+ **Features:**
1031
+ 1. Main dashboard view with all metrics
1032
+ 2. ASCII chart rendering
1033
+ 3. Interactive navigation
1034
+ 4. Drill-down views
1035
+ 5. Color-coded output
1036
+
1037
+ **Estimated effort:** 3-4 hours
1038
+
1039
+ ---
1040
+
1041
+ ### Phase 3: Export Functionality
1042
+ **Files to create:**
1043
+ - `lib/learning/analytics-exporter.js` - Export to JSON/CSV
1044
+
1045
+ **Features:**
1046
+ 1. JSON export with complete analytics data
1047
+ 2. CSV export with multiple files
1048
+ 3. Export configuration options
1049
+ 4. Export validation
1050
+
1051
+ **Estimated effort:** 2-3 hours
1052
+
1053
+ ---
1054
+
1055
+ ### Phase 4: Integration
1056
+ **Files to modify:**
1057
+ - `lib/commands/config.js` - Add "Analytics Dashboard" to learning menu
1058
+ - `lib/learning/learning-manager.js` - Integrate analytics module
1059
+
1060
+ **Features:**
1061
+ 1. Add "Analytics Dashboard" option to learning menu
1062
+ 2. Integrate analytics module into learning manager
1063
+ 3. Add export shortcuts
1064
+
1065
+ **Estimated effort:** 1-2 hours
1066
+
1067
+ ---
1068
+
1069
+ ### Phase 5: Testing
1070
+ **Files to create:**
1071
+ - `tests/analytics.test.js` - Analytics calculations tests
1072
+ - `tests/analytics-view.test.js` - Dashboard UI tests (snapshot tests)
1073
+ - `tests/analytics-exporter.test.js` - Export functionality tests
1074
+
1075
+ **Test Coverage:**
1076
+ - All metrics calculation functions
1077
+ - Edge cases (no data, single session, large datasets)
1078
+ - Export format validation
1079
+ - Performance tests (100+ sessions)
1080
+
1081
+ **Estimated effort:** 3-4 hours
1082
+
1083
+ ---
1084
+
1085
+ **Total Estimated Effort:** 13-19 hours (2-3 days)
1086
+
1087
+ ---
1088
+
1089
+ ## Testing Strategy
1090
+
1091
+ ### Unit Tests
1092
+
1093
+ ```javascript
1094
+ // tests/analytics.test.js
1095
+
1096
+ describe('Analytics Calculations', () => {
1097
+ describe('calculateOverviewStats', () => {
1098
+ it('should calculate correct overview statistics', () => {
1099
+ const stats = { totalSessions: 15, totalSkips: 45, totalAnswers: 120 };
1100
+ const patterns = { patterns: [{}, {}, {}] };
1101
+ const rules = { rules: [{}, {}] };
1102
+
1103
+ const result = calculateOverviewStats(stats, patterns, rules);
1104
+
1105
+ expect(result.totalSessions).toBe(15);
1106
+ expect(result.totalSkips).toBe(45);
1107
+ expect(result.activePatterns).toBe(3);
1108
+ });
1109
+
1110
+ it('should handle empty data', () => {
1111
+ const result = calculateOverviewStats({}, { patterns: [] }, { rules: [] });
1112
+ expect(result.totalSessions).toBe(0);
1113
+ expect(result.activePatterns).toBe(0);
1114
+ });
1115
+ });
1116
+
1117
+ describe('calculateSkipTrends', () => {
1118
+ it('should calculate skip trends for last 12 weeks', () => {
1119
+ const skipHistory = createMockSkipHistory(15);
1120
+ const trends = calculateSkipTrends(skipHistory);
1121
+
1122
+ expect(trends).toHaveLength(12);
1123
+ expect(trends[0]).toHaveProperty('week');
1124
+ expect(trends[0]).toHaveProperty('manualSkips');
1125
+ expect(trends[0]).toHaveProperty('skipRate');
1126
+ });
1127
+
1128
+ it('should handle weeks with no sessions', () => {
1129
+ const skipHistory = { sessions: [] };
1130
+ const trends = calculateSkipTrends(skipHistory);
1131
+
1132
+ expect(trends).toHaveLength(12);
1133
+ expect(trends[0].manualSkips).toBe(0);
1134
+ });
1135
+ });
1136
+
1137
+ describe('calculateCategoryPreferences', () => {
1138
+ it('should calculate skip rates by category', () => {
1139
+ const skipHistory = createMockSkipHistoryWithCategories();
1140
+ const answerHistory = createMockAnswerHistoryWithCategories();
1141
+
1142
+ const prefs = calculateCategoryPreferences(skipHistory, answerHistory);
1143
+
1144
+ expect(prefs[0]).toHaveProperty('category');
1145
+ expect(prefs[0]).toHaveProperty('skipRate');
1146
+ expect(prefs[0]).toHaveProperty('level');
1147
+ });
1148
+
1149
+ it('should sort categories by skip rate descending', () => {
1150
+ const prefs = calculateCategoryPreferences(mockSkipHistory, mockAnswerHistory);
1151
+
1152
+ for (let i = 0; i < prefs.length - 1; i++) {
1153
+ expect(prefs[i].skipRate).toBeGreaterThanOrEqual(prefs[i + 1].skipRate);
1154
+ }
1155
+ });
1156
+ });
1157
+
1158
+ describe('calculateEffectiveness', () => {
1159
+ it('should calculate time saved correctly', () => {
1160
+ const skipHistory = { sessions: [{ skips: [{ reason: 'filtered' }] }] };
1161
+ const result = calculateEffectiveness(skipHistory, [], []);
1162
+
1163
+ expect(result.timeSavedMinutes).toBeGreaterThan(0);
1164
+ expect(result.questionsFiltered).toBe(1);
1165
+ });
1166
+
1167
+ it('should calculate pattern accuracy', () => {
1168
+ const patterns = [
1169
+ { userApproved: true },
1170
+ { userApproved: true },
1171
+ { userApproved: false }
1172
+ ];
1173
+
1174
+ const result = calculateEffectiveness({}, patterns, []);
1175
+ expect(result.patternAccuracy).toBe(67); // 2/3 = 66.67%
1176
+ });
1177
+ });
1178
+ });
1179
+ ```
1180
+
1181
+ ### Integration Tests
1182
+
1183
+ ```javascript
1184
+ // tests/analytics-integration.test.js
1185
+
1186
+ describe('Analytics Integration', () => {
1187
+ it('should generate complete analytics from real data', async () => {
1188
+ const projectPath = createTestProject();
1189
+ await populateWithMockData(projectPath, 15);
1190
+
1191
+ const analytics = await generateAnalytics(projectPath);
1192
+
1193
+ expect(analytics).toHaveProperty('overview');
1194
+ expect(analytics).toHaveProperty('skipTrends');
1195
+ expect(analytics).toHaveProperty('categoryPreferences');
1196
+ expect(analytics).toHaveProperty('effectiveness');
1197
+ });
1198
+
1199
+ it('should export analytics to JSON', async () => {
1200
+ const projectPath = createTestProject();
1201
+ const analytics = await generateAnalytics(projectPath);
1202
+
1203
+ const exported = await exportAnalytics(analytics, 'json');
1204
+ const parsed = JSON.parse(exported);
1205
+
1206
+ expect(parsed.version).toBe('1.0');
1207
+ expect(parsed).toHaveProperty('overview');
1208
+ });
1209
+
1210
+ it('should export analytics to CSV', async () => {
1211
+ const projectPath = createTestProject();
1212
+ const analytics = await generateAnalytics(projectPath);
1213
+
1214
+ const files = await exportAnalytics(analytics, 'csv');
1215
+
1216
+ expect(files).toHaveProperty('overview.csv');
1217
+ expect(files).toHaveProperty('trends.csv');
1218
+ expect(files).toHaveProperty('categories.csv');
1219
+ });
1220
+ });
1221
+ ```
1222
+
1223
+ ### Performance Tests
1224
+
1225
+ ```javascript
1226
+ // tests/analytics-performance.test.js
1227
+
1228
+ describe('Analytics Performance', () => {
1229
+ it('should handle 100 sessions in < 2 seconds', async () => {
1230
+ const projectPath = createTestProject();
1231
+ await populateWithMockData(projectPath, 100);
1232
+
1233
+ const startTime = Date.now();
1234
+ await generateAnalytics(projectPath);
1235
+ const elapsed = Date.now() - startTime;
1236
+
1237
+ expect(elapsed).toBeLessThan(2000); // < 2 seconds
1238
+ });
1239
+
1240
+ it('should handle 500 patterns efficiently', () => {
1241
+ const patterns = createMockPatterns(500);
1242
+
1243
+ const startTime = Date.now();
1244
+ const distribution = calculatePatternDistribution(patterns);
1245
+ const elapsed = Date.now() - startTime;
1246
+
1247
+ expect(elapsed).toBeLessThan(500); // < 500ms
1248
+ });
1249
+ });
1250
+ ```
1251
+
1252
+ ---
1253
+
1254
+ ## Success Criteria
1255
+
1256
+ ✅ **Functional Requirements:**
1257
+ - Dashboard displays 10+ meaningful metrics
1258
+ - All calculations are accurate
1259
+ - Export works in both JSON and CSV
1260
+ - Performance < 2 seconds for 100 sessions
1261
+ - UI is clear and intuitive
1262
+
1263
+ ✅ **Code Quality:**
1264
+ - 80%+ test coverage for analytics module
1265
+ - All edge cases handled (no data, single session, etc.)
1266
+ - Code follows existing patterns in codebase
1267
+ - Comprehensive JSDoc documentation
1268
+
1269
+ ✅ **User Experience:**
1270
+ - Dashboard loads instantly
1271
+ - Navigation is intuitive
1272
+ - Charts render correctly in all terminals
1273
+ - Export files are well-formatted
1274
+
1275
+ ✅ **Integration:**
1276
+ - Seamlessly integrates into `adf config` → Learning System menu
1277
+ - No breaking changes to existing functionality
1278
+ - Compatible with all other Phase 6 features
1279
+
1280
+ ---
1281
+
1282
+ ## Future Enhancements (Post-v0.6.0)
1283
+
1284
+ 1. **Visual Enhancements**
1285
+ - Web-based dashboard (HTML export)
1286
+ - More chart types (line charts, scatter plots)
1287
+ - Color themes
1288
+
1289
+ 2. **Advanced Analytics**
1290
+ - Predictive analytics (which patterns likely to decay)
1291
+ - Anomaly detection (unusual skip behavior)
1292
+ - Session comparison
1293
+ - A/B testing for learned rules
1294
+
1295
+ 3. **Team Features**
1296
+ - Aggregate analytics across team members
1297
+ - Team benchmarking
1298
+ - Shared insights
1299
+
1300
+ 4. **Real-Time Analytics**
1301
+ - Live dashboard during interview
1302
+ - Real-time effectiveness monitoring
1303
+ - In-session recommendations
1304
+
1305
+ ---
1306
+
1307
+ ## Appendix
1308
+
1309
+ ### A. Mock Data for Testing
1310
+
1311
+ ```javascript
1312
+ function createMockSkipHistory(sessionCount) {
1313
+ const sessions = [];
1314
+
1315
+ for (let i = 0; i < sessionCount; i++) {
1316
+ const sessionDate = new Date();
1317
+ sessionDate.setDate(sessionDate.getDate() - (i * 2));
1318
+
1319
+ sessions.push({
1320
+ sessionId: `session_${i}`,
1321
+ timestamp: sessionDate.toISOString(),
1322
+ projectType: i % 2 === 0 ? 'cli-tool' : 'web-app',
1323
+ frameworks: i % 2 === 0 ? ['commander'] : ['react'],
1324
+ skips: generateRandomSkips(3, 8),
1325
+ answers: []
1326
+ });
1327
+ }
1328
+
1329
+ return { version: '1.0', sessions };
1330
+ }
1331
+
1332
+ function generateRandomSkips(min, max) {
1333
+ const count = Math.floor(Math.random() * (max - min + 1)) + min;
1334
+ const skips = [];
1335
+
1336
+ const categories = ['deployment', 'UI/UX', 'documentation', 'architecture', 'core-features'];
1337
+ const reasons = ['manual', 'filtered'];
1338
+
1339
+ for (let i = 0; i < count; i++) {
1340
+ skips.push({
1341
+ questionId: `q_${Math.floor(Math.random() * 50)}`,
1342
+ text: `Sample question ${i}`,
1343
+ category: categories[Math.floor(Math.random() * categories.length)],
1344
+ phase: 'planning',
1345
+ action: 'skipped',
1346
+ reason: reasons[Math.floor(Math.random() * reasons.length)],
1347
+ timeViewed: Math.random() * 5,
1348
+ relevanceScore: Math.floor(Math.random() * 100)
1349
+ });
1350
+ }
1351
+
1352
+ return skips;
1353
+ }
1354
+ ```
1355
+
1356
+ ### B. ASCII Chart Examples
1357
+
1358
+ ```
1359
+ Bar Chart Example:
1360
+ deployment ████████████████████ 95%
1361
+ UI/UX ██████████████░░░░░░ 70%
1362
+ documentation ████████░░░░░░░░░░░░ 40%
1363
+
1364
+ Pie Chart Example:
1365
+ High: ████████░░ 8 (53%)
1366
+ Medium: ████░░░░░░ 4 (27%)
1367
+ Low: ██░░░░░░░░ 2 (13%)
1368
+
1369
+ Line Chart Example (Trend):
1370
+ 20 | ╭──╮
1371
+ 15 | ╭─────────╯ ╰╮
1372
+ 10 | ╭─╯ ╰─╮
1373
+ 5 | ╭╯ ╰─
1374
+ 0 └──────────────────────
1375
+ W1 W4 W7 W10 W12
1376
+ ```
1377
+
1378
+ ---
1379
+
1380
+ **End of Design Specification**
1381
+
1382
+ **Status:** ✅ Design Complete - Ready for Implementation
1383
+ **Next Steps:** Review design → Create implementation task → Begin coding