pikakit 1.0.8 → 1.0.9

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,365 @@
1
+ /**
2
+ * AutoLearn v6.0 - Dashboard Data Provider
3
+ *
4
+ * Aggregates data from all engines for Dashboard display.
5
+ * Provides real-time metrics, trends, and alerts.
6
+ *
7
+ * @version 6.0.0
8
+ * @author PikaKit
9
+ */
10
+
11
+ import { getDashboardData, getMetricHistory, getSummary } from './metrics-collector.js';
12
+ import { getReinforcementStats } from './reinforcement.js';
13
+ import { getABTestStats, getActiveTests } from './ab-testing.js';
14
+ import { getSkillStats, loadAutoSkills } from './precision-skill-generator.js';
15
+ import { loadCausalPatterns } from './causality-engine.js';
16
+
17
+ // ============================================================================
18
+ // DASHBOARD DATA AGGREGATION
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Get complete dashboard data
23
+ * @returns {Object} - Full dashboard data
24
+ */
25
+ export function getFullDashboardData() {
26
+ const data = {
27
+ timestamp: new Date().toISOString(),
28
+ version: '6.0.0',
29
+
30
+ // Core KPIs
31
+ kpis: getDashboardData(),
32
+
33
+ // Summary
34
+ summary: getSummary(),
35
+
36
+ // Module Stats
37
+ modules: {
38
+ reinforcement: getReinforcementStats(),
39
+ abTesting: getABTestStats(),
40
+ skills: getSkillStats(),
41
+ patterns: getPatternStats()
42
+ },
43
+
44
+ // Active items
45
+ active: {
46
+ abTests: getActiveTests().map(t => ({
47
+ id: t.id,
48
+ status: t.status,
49
+ patternA: t.patternA.name || t.patternA.id,
50
+ patternB: t.patternB.name || t.patternB.id,
51
+ samplesA: t.metrics.patternA.applied,
52
+ samplesB: t.metrics.patternB.applied
53
+ })),
54
+ skills: loadAutoSkills().slice(0, 10) // Last 10
55
+ },
56
+
57
+ // Alerts
58
+ alerts: generateAlerts()
59
+ };
60
+
61
+ return data;
62
+ }
63
+
64
+ /**
65
+ * Get pattern statistics
66
+ */
67
+ function getPatternStats() {
68
+ const patterns = loadCausalPatterns();
69
+
70
+ if (patterns.length === 0) {
71
+ return { total: 0, avgConfidence: 0, categories: [] };
72
+ }
73
+
74
+ return {
75
+ total: patterns.length,
76
+ avgConfidence: patterns.reduce((sum, p) => sum + p.confidence, 0) / patterns.length,
77
+ categories: [...new Set(patterns.map(p => p.category || 'unknown'))]
78
+ };
79
+ }
80
+
81
+ // ============================================================================
82
+ // TREND DATA
83
+ // ============================================================================
84
+
85
+ /**
86
+ * Get trend data for a specific metric
87
+ * @param {string} metricId - Metric ID
88
+ * @param {string} period - 'day' | 'week' | 'month'
89
+ * @returns {Object} - Trend data
90
+ */
91
+ export function getMetricTrend(metricId, period = 'week') {
92
+ const limits = { day: 24, week: 168, month: 720 };
93
+ const limit = limits[period] || 168;
94
+
95
+ const history = getMetricHistory(metricId, limit);
96
+
97
+ if (history.length < 2) {
98
+ return { trend: 'stable', change: 0, data: history };
99
+ }
100
+
101
+ // Calculate trend
102
+ const firstValue = parseFloat(history[0].value) || 0;
103
+ const lastValue = parseFloat(history[history.length - 1].value) || 0;
104
+ const change = firstValue > 0 ? ((lastValue - firstValue) / firstValue * 100) : 0;
105
+
106
+ let trend = 'stable';
107
+ if (change > 5) trend = 'up';
108
+ if (change < -5) trend = 'down';
109
+
110
+ return {
111
+ metricId,
112
+ period,
113
+ trend,
114
+ change: change.toFixed(2),
115
+ firstValue,
116
+ lastValue,
117
+ dataPoints: history.length,
118
+ data: history
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Get all key trends
124
+ * @returns {Object} - Key trends
125
+ */
126
+ export function getKeyTrends() {
127
+ const keyMetrics = [
128
+ 'task_success_rate',
129
+ 'error_repeat_rate',
130
+ 'skill_effectiveness',
131
+ 'pattern_precision'
132
+ ];
133
+
134
+ const trends = {};
135
+ for (const metricId of keyMetrics) {
136
+ trends[metricId] = getMetricTrend(metricId, 'week');
137
+ }
138
+
139
+ return trends;
140
+ }
141
+
142
+ // ============================================================================
143
+ // ALERTS
144
+ // ============================================================================
145
+
146
+ const ALERT_RULES = [
147
+ {
148
+ id: 'low_success_rate',
149
+ check: (kpis) => parseFloat(kpis.task_success_rate?.value) < 80,
150
+ severity: 'warning',
151
+ message: 'Task success rate below 80%'
152
+ },
153
+ {
154
+ id: 'high_error_repeat',
155
+ check: (kpis) => parseFloat(kpis.error_repeat_rate?.value) > 10,
156
+ severity: 'warning',
157
+ message: 'Error repeat rate above 10%'
158
+ },
159
+ {
160
+ id: 'low_skill_effectiveness',
161
+ check: (kpis) => parseFloat(kpis.skill_effectiveness?.value) < 50,
162
+ severity: 'info',
163
+ message: 'Skill effectiveness below 50%'
164
+ },
165
+ {
166
+ id: 'high_false_positive',
167
+ check: (kpis) => parseFloat(kpis.false_positive_rate?.value) > 15,
168
+ severity: 'warning',
169
+ message: 'False positive rate above 15%'
170
+ },
171
+ {
172
+ id: 'pattern_confidence_low',
173
+ check: (kpis) => parseFloat(kpis.pattern_confidence_avg?.value) < 0.5,
174
+ severity: 'info',
175
+ message: 'Average pattern confidence below 50%'
176
+ }
177
+ ];
178
+
179
+ /**
180
+ * Generate alerts based on current KPIs
181
+ * @returns {Array} - Active alerts
182
+ */
183
+ export function generateAlerts() {
184
+ const dashboard = getDashboardData();
185
+ const kpis = dashboard.kpis;
186
+ const alerts = [];
187
+
188
+ for (const rule of ALERT_RULES) {
189
+ try {
190
+ if (rule.check(kpis)) {
191
+ alerts.push({
192
+ id: rule.id,
193
+ severity: rule.severity,
194
+ message: rule.message,
195
+ timestamp: new Date().toISOString()
196
+ });
197
+ }
198
+ } catch {
199
+ // Skip rules that fail
200
+ }
201
+ }
202
+
203
+ // Check for skills needing attention
204
+ const skills = loadAutoSkills();
205
+ const underperforming = skills.filter(s => s.state === 'underperforming');
206
+ if (underperforming.length > 0) {
207
+ alerts.push({
208
+ id: 'underperforming_skills',
209
+ severity: 'info',
210
+ message: `${underperforming.length} skills underperforming`,
211
+ timestamp: new Date().toISOString()
212
+ });
213
+ }
214
+
215
+ // Check for pending A/B tests
216
+ const abStats = getABTestStats();
217
+ if (abStats.running > 3) {
218
+ alerts.push({
219
+ id: 'too_many_ab_tests',
220
+ severity: 'info',
221
+ message: `${abStats.running} A/B tests running simultaneously`,
222
+ timestamp: new Date().toISOString()
223
+ });
224
+ }
225
+
226
+ return alerts;
227
+ }
228
+
229
+ // ============================================================================
230
+ // DASHBOARD WIDGETS DATA
231
+ // ============================================================================
232
+
233
+ /**
234
+ * Get data for gauge widgets
235
+ * @returns {Array} - Gauge data
236
+ */
237
+ export function getGaugeWidgets() {
238
+ const dashboard = getDashboardData();
239
+ const kpis = dashboard.kpis;
240
+
241
+ const gauges = [
242
+ { id: 'task_success_rate', label: 'Success Rate', ...kpis.task_success_rate },
243
+ { id: 'error_repeat_rate', label: 'Error Repeat', ...kpis.error_repeat_rate },
244
+ { id: 'first_time_success', label: 'First-Time', ...kpis.first_time_success },
245
+ { id: 'skill_effectiveness', label: 'Skill Effect', ...kpis.skill_effectiveness }
246
+ ];
247
+
248
+ return gauges;
249
+ }
250
+
251
+ /**
252
+ * Get data for counter widgets
253
+ * @returns {Array} - Counter data
254
+ */
255
+ export function getCounterWidgets() {
256
+ const dashboard = getDashboardData();
257
+ const kpis = dashboard.kpis;
258
+ const summary = getSummary();
259
+
260
+ return [
261
+ { id: 'total_tasks', label: 'Total Tasks', value: summary.totalTasks },
262
+ { id: 'skills_generated', label: 'Skills Generated', value: kpis.skills_auto_generated?.value || 0 },
263
+ { id: 'patterns_learned', label: 'Patterns', value: summary.patternsLearned },
264
+ { id: 'skills_pruned', label: 'Skills Pruned', value: kpis.skills_pruned?.value || 0 }
265
+ ];
266
+ }
267
+
268
+ /**
269
+ * Get learning velocity chart data
270
+ * @returns {Object} - Chart data
271
+ */
272
+ export function getLearningVelocityChart() {
273
+ const history = getMetricHistory('learning_velocity', 8);
274
+
275
+ return {
276
+ title: 'Learning Velocity (Patterns/Week)',
277
+ labels: history.map((_, i) => `W${i + 1}`),
278
+ data: history.map(h => parseFloat(h.value) || 0)
279
+ };
280
+ }
281
+
282
+ /**
283
+ * Get skill effectiveness breakdown
284
+ * @returns {Object} - Breakdown data
285
+ */
286
+ export function getSkillEffectivenessBreakdown() {
287
+ const skills = loadAutoSkills();
288
+
289
+ const breakdown = {
290
+ high: skills.filter(s => s.confidence >= 0.8).length,
291
+ medium: skills.filter(s => s.confidence >= 0.5 && s.confidence < 0.8).length,
292
+ low: skills.filter(s => s.confidence < 0.5).length
293
+ };
294
+
295
+ return {
296
+ title: 'Skill Distribution',
297
+ data: breakdown
298
+ };
299
+ }
300
+
301
+ // ============================================================================
302
+ // FORMATTED OUTPUT FOR CLI
303
+ // ============================================================================
304
+
305
+ /**
306
+ * Format dashboard for CLI display
307
+ * @returns {string} - Formatted string
308
+ */
309
+ export function formatDashboardForCLI() {
310
+ const data = getFullDashboardData();
311
+ const kpis = data.kpis.kpis;
312
+
313
+ const lines = [
314
+ '',
315
+ '┌─────────────────────────────────────────────────────────────────┐',
316
+ '│ 🧠 AutoLearn v6.0 Dashboard │',
317
+ '├─────────────────────────────────────────────────────────────────┤',
318
+ '│ │',
319
+ `│ Task Success: ${formatValue(kpis.task_success_rate)} Error Repeat: ${formatValue(kpis.error_repeat_rate)} │`,
320
+ `│ First-Time: ${formatValue(kpis.first_time_success)} Skill Effect: ${formatValue(kpis.skill_effectiveness)} │`,
321
+ '│ │',
322
+ '├─────────────────────────────────────────────────────────────────┤',
323
+ `│ 📊 Patterns: ${data.modules.patterns.total} Skills: ${data.modules.skills.total} A/B Tests: ${data.modules.abTesting.running} │`,
324
+ '│ │'
325
+ ];
326
+
327
+ // Add alerts
328
+ if (data.alerts.length > 0) {
329
+ lines.push('│ ⚠️ Alerts: │');
330
+ for (const alert of data.alerts.slice(0, 3)) {
331
+ lines.push(`│ • ${alert.message.padEnd(55)}│`);
332
+ }
333
+ } else {
334
+ lines.push('│ ✅ No alerts │');
335
+ }
336
+
337
+ lines.push('│ │');
338
+ lines.push('└─────────────────────────────────────────────────────────────────┘');
339
+ lines.push('');
340
+
341
+ return lines.join('\n');
342
+ }
343
+
344
+ function formatValue(kpi) {
345
+ if (!kpi) return ' --.-%';
346
+ const val = parseFloat(kpi.value).toFixed(1);
347
+ const status = kpi.status === 'good' ? '✓' : kpi.status === 'critical' ? '✗' : '~';
348
+ return `${status} ${val.padStart(5)}%`;
349
+ }
350
+
351
+ // ============================================================================
352
+ // EXPORTS
353
+ // ============================================================================
354
+
355
+ export default {
356
+ getFullDashboardData,
357
+ getMetricTrend,
358
+ getKeyTrends,
359
+ generateAlerts,
360
+ getGaugeWidgets,
361
+ getCounterWidgets,
362
+ getLearningVelocityChart,
363
+ getSkillEffectivenessBreakdown,
364
+ formatDashboardForCLI
365
+ };
@@ -330,7 +330,7 @@ Examples:
330
330
  }
331
331
 
332
332
  // Run if executed directly (as async)
333
- if (process.argv[1].includes("fix")) {
333
+ if (process.argv[1]?.includes("fix")) {
334
334
  main().catch(console.error);
335
335
  }
336
336