pikakit 3.0.5 → 3.7.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.
Files changed (100) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/commands/install.js +119 -242
  3. package/package.json +3 -4
  4. package/lib/agent-cli/bin/agent.js +0 -187
  5. package/lib/agent-cli/dashboard/dashboard_server.js +0 -312
  6. package/lib/agent-cli/lib/ab-testing.js +0 -364
  7. package/lib/agent-cli/lib/audit.js +0 -154
  8. package/lib/agent-cli/lib/audit.test.js +0 -100
  9. package/lib/agent-cli/lib/auto-learn.js +0 -319
  10. package/lib/agent-cli/lib/backup.js +0 -138
  11. package/lib/agent-cli/lib/backup.test.js +0 -78
  12. package/lib/agent-cli/lib/causality-engine.js +0 -331
  13. package/lib/agent-cli/lib/cognitive-lesson.js +0 -476
  14. package/lib/agent-cli/lib/completion.js +0 -149
  15. package/lib/agent-cli/lib/config.js +0 -35
  16. package/lib/agent-cli/lib/dashboard-data.js +0 -380
  17. package/lib/agent-cli/lib/eslint-fix.js +0 -238
  18. package/lib/agent-cli/lib/evolution-signal.js +0 -215
  19. package/lib/agent-cli/lib/export.js +0 -86
  20. package/lib/agent-cli/lib/export.test.js +0 -65
  21. package/lib/agent-cli/lib/fix.js +0 -337
  22. package/lib/agent-cli/lib/fix.test.js +0 -80
  23. package/lib/agent-cli/lib/gemini-export.js +0 -83
  24. package/lib/agent-cli/lib/generate-registry.js +0 -42
  25. package/lib/agent-cli/lib/hooks/install-hooks.js +0 -152
  26. package/lib/agent-cli/lib/hooks/lint-learn.js +0 -172
  27. package/lib/agent-cli/lib/icons.js +0 -93
  28. package/lib/agent-cli/lib/ignore.js +0 -116
  29. package/lib/agent-cli/lib/ignore.test.js +0 -58
  30. package/lib/agent-cli/lib/init.js +0 -124
  31. package/lib/agent-cli/lib/knowledge-index.js +0 -326
  32. package/lib/agent-cli/lib/knowledge-metrics.js +0 -335
  33. package/lib/agent-cli/lib/knowledge-retention.js +0 -398
  34. package/lib/agent-cli/lib/knowledge-validator.js +0 -312
  35. package/lib/agent-cli/lib/learn.js +0 -255
  36. package/lib/agent-cli/lib/learn.test.js +0 -70
  37. package/lib/agent-cli/lib/metrics-collector.js +0 -410
  38. package/lib/agent-cli/lib/proposals.js +0 -199
  39. package/lib/agent-cli/lib/proposals.test.js +0 -56
  40. package/lib/agent-cli/lib/recall.js +0 -835
  41. package/lib/agent-cli/lib/recall.test.js +0 -107
  42. package/lib/agent-cli/lib/reinforcement.js +0 -299
  43. package/lib/agent-cli/lib/selfevolution-bridge.js +0 -167
  44. package/lib/agent-cli/lib/settings.js +0 -203
  45. package/lib/agent-cli/lib/skill-generator.js +0 -379
  46. package/lib/agent-cli/lib/skill-learn.js +0 -296
  47. package/lib/agent-cli/lib/stats.js +0 -132
  48. package/lib/agent-cli/lib/stats.test.js +0 -94
  49. package/lib/agent-cli/lib/types.js +0 -33
  50. package/lib/agent-cli/lib/ui/audit-ui.js +0 -146
  51. package/lib/agent-cli/lib/ui/backup-ui.js +0 -107
  52. package/lib/agent-cli/lib/ui/clack-helpers.js +0 -317
  53. package/lib/agent-cli/lib/ui/common.js +0 -83
  54. package/lib/agent-cli/lib/ui/completion-ui.js +0 -126
  55. package/lib/agent-cli/lib/ui/custom-select.js +0 -69
  56. package/lib/agent-cli/lib/ui/dashboard-ui.js +0 -222
  57. package/lib/agent-cli/lib/ui/evolution-signals-ui.js +0 -107
  58. package/lib/agent-cli/lib/ui/export-ui.js +0 -94
  59. package/lib/agent-cli/lib/ui/fix-all-ui.js +0 -191
  60. package/lib/agent-cli/lib/ui/help-ui.js +0 -49
  61. package/lib/agent-cli/lib/ui/index.js +0 -199
  62. package/lib/agent-cli/lib/ui/init-ui.js +0 -56
  63. package/lib/agent-cli/lib/ui/knowledge-ui.js +0 -55
  64. package/lib/agent-cli/lib/ui/learn-ui.js +0 -706
  65. package/lib/agent-cli/lib/ui/lessons-ui.js +0 -148
  66. package/lib/agent-cli/lib/ui/pretty.js +0 -145
  67. package/lib/agent-cli/lib/ui/proposals-ui.js +0 -99
  68. package/lib/agent-cli/lib/ui/recall-ui.js +0 -342
  69. package/lib/agent-cli/lib/ui/routing-demo.js +0 -79
  70. package/lib/agent-cli/lib/ui/routing-ui.js +0 -325
  71. package/lib/agent-cli/lib/ui/settings-ui.js +0 -381
  72. package/lib/agent-cli/lib/ui/stats-ui.js +0 -123
  73. package/lib/agent-cli/lib/ui/watch-ui.js +0 -236
  74. package/lib/agent-cli/lib/watcher.js +0 -181
  75. package/lib/agent-cli/lib/watcher.test.js +0 -85
  76. package/lib/agent-cli/src/MIGRATION.md +0 -418
  77. package/lib/agent-cli/src/README.md +0 -367
  78. package/lib/agent-cli/src/core/evolution/evolution-signal.js +0 -42
  79. package/lib/agent-cli/src/core/evolution/index.js +0 -17
  80. package/lib/agent-cli/src/core/evolution/review-gate.js +0 -40
  81. package/lib/agent-cli/src/core/evolution/signal-detector.js +0 -137
  82. package/lib/agent-cli/src/core/evolution/signal-queue.js +0 -79
  83. package/lib/agent-cli/src/core/evolution/threshold-checker.js +0 -79
  84. package/lib/agent-cli/src/core/index.js +0 -15
  85. package/lib/agent-cli/src/core/learning/cognitive-enhancer.js +0 -282
  86. package/lib/agent-cli/src/core/learning/index.js +0 -12
  87. package/lib/agent-cli/src/core/learning/lesson-synthesizer.js +0 -83
  88. package/lib/agent-cli/src/core/scanning/index.js +0 -14
  89. package/lib/agent-cli/src/data/index.js +0 -13
  90. package/lib/agent-cli/src/data/repositories/index.js +0 -8
  91. package/lib/agent-cli/src/data/repositories/lesson-repository.js +0 -130
  92. package/lib/agent-cli/src/data/repositories/signal-repository.js +0 -119
  93. package/lib/agent-cli/src/data/storage/index.js +0 -8
  94. package/lib/agent-cli/src/data/storage/json-storage.js +0 -64
  95. package/lib/agent-cli/src/data/storage/yaml-storage.js +0 -66
  96. package/lib/agent-cli/src/infrastructure/index.js +0 -13
  97. package/lib/agent-cli/src/presentation/formatters/skill-formatter.js +0 -232
  98. package/lib/agent-cli/src/services/export-service.js +0 -162
  99. package/lib/agent-cli/src/services/index.js +0 -13
  100. package/lib/agent-cli/src/services/learning-service.js +0 -99
@@ -1,398 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Knowledge Retention Runner
4
- *
5
- * Executes retention policies defined in retention.yaml.
6
- * Archives or soft-deletes stale lessons based on policy rules.
7
- *
8
- * Usage:
9
- * agent retention --dry-run # Preview what would be cleaned
10
- * agent retention --apply # Execute cleanup (with confirmation)
11
- * agent retention --status # Show retention policy status
12
- */
13
-
14
- import fs from 'fs';
15
- import path from 'path';
16
- import yaml from 'js-yaml';
17
- import { KNOWLEDGE_DIR } from './config.js';
18
-
19
- const RETENTION_PATH = path.join(KNOWLEDGE_DIR, 'retention.yaml');
20
- const BACKUP_DIR = path.join(KNOWLEDGE_DIR, 'backups');
21
-
22
- /**
23
- * Load retention policy
24
- * @returns {Object|null}
25
- */
26
- function loadPolicy() {
27
- if (!fs.existsSync(RETENTION_PATH)) {
28
- return null;
29
- }
30
-
31
- try {
32
- return yaml.load(fs.readFileSync(RETENTION_PATH, 'utf8'));
33
- } catch (e) {
34
- console.error(`āŒ Failed to load retention.yaml: ${e.message}`);
35
- return null;
36
- }
37
- }
38
-
39
- /**
40
- * Load all lessons from knowledge files
41
- * @returns {{ mistakes: Array, improvements: Array }}
42
- */
43
- function loadAllLessons() {
44
- const mistakes = [];
45
- const improvements = [];
46
-
47
- const mistakesPath = path.join(KNOWLEDGE_DIR, 'mistakes.yaml');
48
- if (fs.existsSync(mistakesPath)) {
49
- const data = yaml.load(fs.readFileSync(mistakesPath, 'utf8'));
50
- if (data?.mistakes) mistakes.push(...data.mistakes.map(m => ({ ...m, _source: 'mistakes' })));
51
- }
52
-
53
- const improvementsPath = path.join(KNOWLEDGE_DIR, 'improvements.yaml');
54
- if (fs.existsSync(improvementsPath)) {
55
- const data = yaml.load(fs.readFileSync(improvementsPath, 'utf8'));
56
- if (data?.improvements) improvements.push(...data.improvements.map(i => ({ ...i, _source: 'improvements' })));
57
- }
58
-
59
- return { mistakes, improvements };
60
- }
61
-
62
- /**
63
- * Evaluate a single condition against a lesson
64
- * @param {Object} lesson
65
- * @param {Object} condition - { field, operator, value }
66
- * @returns {boolean}
67
- */
68
- function evaluateCondition(lesson, condition) {
69
- const { field, operator, value } = condition;
70
-
71
- // Get nested field value (e.g., 'cognitive.confidence')
72
- const fieldValue = field.split('.').reduce((obj, key) => obj?.[key], lesson);
73
-
74
- switch (operator) {
75
- case 'equals':
76
- return fieldValue === value;
77
- case 'notEquals':
78
- return fieldValue !== value;
79
- case 'greaterThan':
80
- return (fieldValue || 0) > value;
81
- case 'lessThan':
82
- return (fieldValue || 0) < value;
83
- case 'isNull':
84
- return fieldValue === null || fieldValue === undefined;
85
- case 'contains':
86
- return Array.isArray(fieldValue) && fieldValue.includes(value);
87
- case 'olderThan': {
88
- if (!lesson.addedAt) return false;
89
- const addedTime = new Date(lesson.addedAt).getTime();
90
- const thresholdTime = Date.now() - (value * 24 * 60 * 60 * 1000);
91
- return addedTime < thresholdTime;
92
- }
93
- case 'newerThan': {
94
- if (!lesson.addedAt) return false;
95
- const addedTime = new Date(lesson.addedAt).getTime();
96
- const thresholdTime = Date.now() - (value * 24 * 60 * 60 * 1000);
97
- return addedTime > thresholdTime;
98
- }
99
- default:
100
- return false;
101
- }
102
- }
103
-
104
- /**
105
- * Evaluate policy conditions (all/any)
106
- * @param {Object} lesson
107
- * @param {Object} conditionGroup - { all?: [], any?: [] }
108
- * @returns {boolean}
109
- */
110
- function matchesConditions(lesson, conditionGroup) {
111
- if (conditionGroup.all) {
112
- return conditionGroup.all.every(cond => evaluateCondition(lesson, cond));
113
- }
114
- if (conditionGroup.any) {
115
- return conditionGroup.any.some(cond => evaluateCondition(lesson, cond));
116
- }
117
- return false;
118
- }
119
-
120
- /**
121
- * Check if lesson is protected by high-priority policy
122
- * @param {Object} lesson
123
- * @param {Array} policies
124
- * @returns {boolean}
125
- */
126
- function isProtected(lesson, policies) {
127
- const protectPolicy = policies.find(p => p.action?.type === 'protect' && p.enabled);
128
- if (!protectPolicy) return false;
129
- return matchesConditions(lesson, protectPolicy.condition);
130
- }
131
-
132
- /**
133
- * Run retention analysis (dry-run)
134
- * @returns {{ toArchive: Array, toDelete: Array, toFlag: Array, protected: Array }}
135
- */
136
- export function analyzeRetention() {
137
- const policy = loadPolicy();
138
-
139
- if (!policy || !policy.settings?.enabled) {
140
- return {
141
- toArchive: [],
142
- toDelete: [],
143
- toFlag: [],
144
- protected: [],
145
- disabled: true
146
- };
147
- }
148
-
149
- const { mistakes, improvements } = loadAllLessons();
150
- const allLessons = [...mistakes, ...improvements];
151
- const policies = policy.policies?.filter(p => p.enabled) || [];
152
-
153
- const result = {
154
- toArchive: [],
155
- toDelete: [],
156
- toFlag: [],
157
- protected: []
158
- };
159
-
160
- for (const lesson of allLessons) {
161
- // Check protection first
162
- if (isProtected(lesson, policies)) {
163
- result.protected.push({ id: lesson.id, reason: 'high_value_protection' });
164
- continue;
165
- }
166
-
167
- // Check other policies (sorted by priority)
168
- const sortedPolicies = policies
169
- .filter(p => p.action?.type !== 'protect')
170
- .sort((a, b) => (a.priority || 0) - (b.priority || 0));
171
-
172
- for (const pol of sortedPolicies) {
173
- if (pol.condition?.custom === 'detectDuplicatePatterns') {
174
- // Skip custom functions for now
175
- continue;
176
- }
177
-
178
- // Check exceptions
179
- const hasException = (pol.exceptions || []).some(exc =>
180
- evaluateCondition(lesson, exc)
181
- );
182
-
183
- if (hasException) continue;
184
-
185
- if (matchesConditions(lesson, pol.condition)) {
186
- const entry = {
187
- id: lesson.id,
188
- pattern: lesson.pattern,
189
- source: lesson._source,
190
- policy: pol.name,
191
- reason: pol.description
192
- };
193
-
194
- switch (pol.action?.type) {
195
- case 'archive':
196
- result.toArchive.push(entry);
197
- break;
198
- case 'soft_delete':
199
- result.toDelete.push(entry);
200
- break;
201
- case 'flag':
202
- result.toFlag.push(entry);
203
- break;
204
- }
205
- break; // Stop at first matching policy
206
- }
207
- }
208
- }
209
-
210
- return result;
211
- }
212
-
213
- /**
214
- * Execute retention cleanup
215
- * @param {{ toArchive: Array, toDelete: Array }} analysis
216
- * @returns {{ archived: number, deleted: number }}
217
- */
218
- export function executeRetention(analysis) {
219
- const policy = loadPolicy();
220
-
221
- // Safety check
222
- if (!policy?.settings?.enabled) {
223
- console.log('āŒ Retention is disabled. Enable in settings.yaml first.');
224
- return { archived: 0, deleted: 0 };
225
- }
226
-
227
- const limits = policy.limits || {};
228
- let archived = 0;
229
- let deleted = 0;
230
-
231
- // Ensure backup dir exists
232
- if (!fs.existsSync(BACKUP_DIR)) {
233
- fs.mkdirSync(BACKUP_DIR, { recursive: true });
234
- }
235
-
236
- // Archive lessons
237
- const archiveItems = analysis.toArchive.slice(0, limits.maxArchivePerRun || 50);
238
- if (archiveItems.length > 0) {
239
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
240
- const archivePath = path.join(BACKUP_DIR, `retention_archive_${timestamp}.yaml`);
241
-
242
- fs.writeFileSync(archivePath, yaml.dump({
243
- archivedAt: new Date().toISOString(),
244
- items: archiveItems
245
- }), 'utf8');
246
-
247
- archived = archiveItems.length;
248
- console.log(`šŸ“¦ Archived ${archived} lessons to ${path.basename(archivePath)}`);
249
- }
250
-
251
- // Note: Actual removal from source files requires more careful handling
252
- // For now, we just log what would be removed
253
-
254
- return { archived, deleted };
255
- }
256
-
257
- /**
258
- * Display status
259
- */
260
- function displayStatus() {
261
- const policy = loadPolicy();
262
-
263
- console.log(`
264
- šŸ“‹ Retention Policy Status
265
- ${'─'.repeat(50)}
266
-
267
- Settings:
268
- Enabled: ${policy?.settings?.enabled ? 'āœ… Yes' : 'āŒ No'}
269
- Dry-run default: ${policy?.settings?.dryRunDefault ? 'Yes' : 'No'}
270
- Backup before cleanup: ${policy?.settings?.backupBeforeCleanup ? 'Yes' : 'No'}
271
- Confirmation required: ${policy?.settings?.confirmationRequired ? 'Yes' : 'No'}
272
-
273
- Policies:`);
274
-
275
- const policies = policy?.policies || [];
276
- for (const pol of policies) {
277
- const status = pol.enabled ? 'āœ…' : 'āøļø';
278
- console.log(` ${status} ${pol.name} (priority ${pol.priority || 0})`);
279
- console.log(` Action: ${pol.action?.type || 'unknown'}`);
280
- }
281
-
282
- console.log(`
283
- Limits:
284
- Max delete/run: ${policy?.limits?.maxDeletePerRun || 10}
285
- Max archive/run: ${policy?.limits?.maxArchivePerRun || 50}
286
- Approval threshold: ${policy?.limits?.requireApprovalAbove || 5}
287
- `);
288
- }
289
-
290
- /**
291
- * Display dry-run results
292
- * @param {Object} analysis
293
- */
294
- function displayDryRun(analysis) {
295
- if (analysis.disabled) {
296
- console.log(`
297
- āš ļø Retention is DISABLED
298
-
299
- To enable, set in .agent/knowledge/settings.yaml:
300
- retention:
301
- enabled: true
302
- `);
303
- return;
304
- }
305
-
306
- console.log(`
307
- šŸ” Retention Dry-Run Analysis
308
- ${'─'.repeat(50)}
309
-
310
- šŸ“¦ To Archive (${analysis.toArchive.length}):`);
311
-
312
- for (const item of analysis.toArchive) {
313
- console.log(` • ${item.id}: ${item.reason}`);
314
- }
315
-
316
- console.log(`
317
- šŸ—‘ļø To Delete (${analysis.toDelete.length}):`);
318
-
319
- for (const item of analysis.toDelete) {
320
- console.log(` • ${item.id}: ${item.reason}`);
321
- }
322
-
323
- console.log(`
324
- 🚩 To Flag for Review (${analysis.toFlag.length}):`);
325
-
326
- for (const item of analysis.toFlag) {
327
- console.log(` • ${item.id}: ${item.reason}`);
328
- }
329
-
330
- console.log(`
331
- šŸ›”ļø Protected (${analysis.protected.length}):`);
332
-
333
- for (const item of analysis.protected) {
334
- console.log(` • ${item.id}: ${item.reason}`);
335
- }
336
-
337
- const total = analysis.toArchive.length + analysis.toDelete.length;
338
- console.log(`
339
- ${'─'.repeat(50)}
340
- šŸ“Š Total actions: ${total}
341
- ${total > 0 ? 'šŸ’” Run with --apply to execute (requires confirmation)\n' : '✨ No cleanup needed!\n'}
342
- `);
343
- }
344
-
345
- /**
346
- * CLI entry point
347
- */
348
- async function main() {
349
- const args = process.argv.slice(2);
350
-
351
- if (args.includes('--status') || args.length === 0) {
352
- displayStatus();
353
- return;
354
- }
355
-
356
- if (args.includes('--dry-run')) {
357
- const analysis = analyzeRetention();
358
- displayDryRun(analysis);
359
- return;
360
- }
361
-
362
- if (args.includes('--apply')) {
363
- const policy = loadPolicy();
364
-
365
- if (!policy?.settings?.enabled) {
366
- console.log('āŒ Retention is disabled. Enable in settings.yaml first.');
367
- process.exit(1);
368
- }
369
-
370
- console.log('šŸ”„ Running retention analysis...');
371
- const analysis = analyzeRetention();
372
- displayDryRun(analysis);
373
-
374
- const total = analysis.toArchive.length + analysis.toDelete.length;
375
- if (total === 0) {
376
- console.log('✨ No actions needed. Exiting.');
377
- return;
378
- }
379
-
380
- // In a real scenario, prompt for confirmation
381
- console.log('āš ļø Confirmation required. This is a dry-run preview.');
382
- console.log(' To actually execute, implement interactive confirmation.\n');
383
-
384
- return;
385
- }
386
-
387
- displayStatus();
388
- }
389
-
390
- // Run if called directly
391
- if (process.argv[1]?.includes('knowledge-retention')) {
392
- main();
393
- }
394
-
395
- export default {
396
- analyzeRetention,
397
- executeRetention
398
- };
@@ -1,312 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Knowledge Schema Validator
4
- *
5
- * Validates knowledge files against JSON schemas before save/load.
6
- * Ensures data integrity and prevents corruption.
7
- *
8
- * Usage:
9
- * agent validate # Validate all knowledge files
10
- * agent validate --fix # Auto-fix minor issues
11
- * agent validate --json # JSON output for CI
12
- */
13
-
14
- import fs from 'fs';
15
- import path from 'path';
16
- import yaml from 'js-yaml';
17
- import Ajv from 'ajv';
18
- import addFormats from 'ajv-formats';
19
- import { KNOWLEDGE_DIR } from './config.js';
20
-
21
- const SCHEMA_DIR = path.join(KNOWLEDGE_DIR, 'schema');
22
-
23
- // Initialize AJV with formats (date-time, etc.)
24
- const ajv = new Ajv({ allErrors: true, strict: false });
25
- addFormats(ajv);
26
-
27
- // Cache compiled validators
28
- const validators = {};
29
-
30
- /**
31
- * Load and compile schema
32
- * @param {string} schemaName - Schema filename without extension
33
- * @returns {Function} Compiled validator
34
- */
35
- function getValidator(schemaName) {
36
- if (validators[schemaName]) {
37
- return validators[schemaName];
38
- }
39
-
40
- const schemaPath = path.join(SCHEMA_DIR, `${schemaName}.schema.json`);
41
- if (!fs.existsSync(schemaPath)) {
42
- return null;
43
- }
44
-
45
- const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
46
- validators[schemaName] = ajv.compile(schema);
47
- return validators[schemaName];
48
- }
49
-
50
- /**
51
- * Validate a knowledge file against its schema
52
- * @param {string} filename - File to validate (e.g., 'mistakes.yaml')
53
- * @returns {{ valid: boolean, errors: Array, file: string }}
54
- */
55
- export function validateFile(filename) {
56
- const filePath = path.join(KNOWLEDGE_DIR, filename);
57
-
58
- if (!fs.existsSync(filePath)) {
59
- return { valid: true, errors: [], file: filename, skipped: true };
60
- }
61
-
62
- // Determine schema name from filename
63
- const baseName = path.basename(filename, path.extname(filename));
64
- const schemaName = baseName.replace(/-/g, ''); // mistakes, improvements, etc.
65
-
66
- // Map to correct schema names
67
- const schemaMap = {
68
- 'mistakes': 'mistakes',
69
- 'improvements': 'improvements',
70
- 'evolutionsignals': 'evolution-signals',
71
- 'settings': 'settings'
72
- };
73
-
74
- const mappedSchema = schemaMap[schemaName] || schemaName;
75
- const validator = getValidator(mappedSchema);
76
-
77
- if (!validator) {
78
- return { valid: true, errors: [], file: filename, noSchema: true };
79
- }
80
-
81
- try {
82
- let data;
83
- const ext = path.extname(filename).toLowerCase();
84
- const content = fs.readFileSync(filePath, 'utf8');
85
-
86
- if (ext === '.yaml' || ext === '.yml') {
87
- data = yaml.load(content);
88
- } else if (ext === '.json') {
89
- data = JSON.parse(content);
90
- } else {
91
- return { valid: true, errors: [], file: filename, unsupportedFormat: true };
92
- }
93
-
94
- const valid = validator(data);
95
-
96
- if (!valid) {
97
- return {
98
- valid: false,
99
- errors: validator.errors.map(err => ({
100
- path: err.instancePath || '/',
101
- message: err.message,
102
- keyword: err.keyword,
103
- params: err.params
104
- })),
105
- file: filename
106
- };
107
- }
108
-
109
- return { valid: true, errors: [], file: filename };
110
-
111
- } catch (e) {
112
- return {
113
- valid: false,
114
- errors: [{ path: '/', message: `Parse error: ${e.message}`, keyword: 'parse' }],
115
- file: filename
116
- };
117
- }
118
- }
119
-
120
- /**
121
- * Validate all knowledge files
122
- * @returns {{ results: Array, summary: { total: number, valid: number, invalid: number } }}
123
- */
124
- export function validateAll() {
125
- const files = [
126
- 'mistakes.yaml',
127
- 'improvements.yaml',
128
- 'evolution-signals.json',
129
- 'settings.yaml'
130
- ];
131
-
132
- const results = [];
133
-
134
- for (const file of files) {
135
- const result = validateFile(file);
136
- results.push(result);
137
- }
138
-
139
- const valid = results.filter(r => r.valid).length;
140
- const invalid = results.filter(r => !r.valid).length;
141
-
142
- return {
143
- results,
144
- summary: {
145
- total: results.length,
146
- valid,
147
- invalid
148
- }
149
- };
150
- }
151
-
152
- /**
153
- * Auto-fix common issues
154
- * @param {string} filename - File to fix
155
- * @returns {{ fixed: boolean, changes: string[] }}
156
- */
157
- export function autoFix(filename) {
158
- const filePath = path.join(KNOWLEDGE_DIR, filename);
159
- const changes = [];
160
-
161
- if (!fs.existsSync(filePath)) {
162
- return { fixed: false, changes: [] };
163
- }
164
-
165
- try {
166
- const ext = path.extname(filename).toLowerCase();
167
- const content = fs.readFileSync(filePath, 'utf8');
168
- let data;
169
-
170
- if (ext === '.yaml' || ext === '.yml') {
171
- data = yaml.load(content);
172
- } else if (ext === '.json') {
173
- data = JSON.parse(content);
174
- } else {
175
- return { fixed: false, changes: [] };
176
- }
177
-
178
- // Auto-fix: Ensure version field
179
- if (data && typeof data.version === 'undefined') {
180
- data.version = 1;
181
- changes.push('Added missing version field');
182
- }
183
-
184
- // Auto-fix: Ensure arrays exist
185
- if (filename === 'mistakes.yaml' && !Array.isArray(data.mistakes)) {
186
- data.mistakes = [];
187
- changes.push('Initialized empty mistakes array');
188
- }
189
- if (filename === 'improvements.yaml' && !Array.isArray(data.improvements)) {
190
- data.improvements = [];
191
- changes.push('Initialized empty improvements array');
192
- }
193
- if (filename === 'evolution-signals.json' && !Array.isArray(data.signals)) {
194
- data.signals = [];
195
- changes.push('Initialized empty signals array');
196
- }
197
-
198
- // Auto-fix: Default cognitive values
199
- const items = data.mistakes || data.improvements || [];
200
- for (const item of items) {
201
- if (!item.cognitive) {
202
- item.cognitive = { maturity: 'learning', confidence: 0.3 };
203
- changes.push(`Added default cognitive for ${item.id}`);
204
- }
205
- if (typeof item.hitCount === 'undefined') {
206
- item.hitCount = 0;
207
- changes.push(`Added default hitCount for ${item.id}`);
208
- }
209
- }
210
-
211
- if (changes.length > 0) {
212
- // Save fixed file
213
- if (ext === '.yaml' || ext === '.yml') {
214
- fs.writeFileSync(filePath, yaml.dump(data, { lineWidth: -1 }), 'utf8');
215
- } else {
216
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
217
- }
218
- }
219
-
220
- return { fixed: changes.length > 0, changes };
221
-
222
- } catch (e) {
223
- return { fixed: false, changes: [], error: e.message };
224
- }
225
- }
226
-
227
- /**
228
- * Display validation results
229
- * @param {{ results: Array, summary: Object }} validation
230
- */
231
- function displayResults(validation) {
232
- console.log(`
233
- šŸ“‹ Knowledge Schema Validation
234
- ${'─'.repeat(50)}
235
- `);
236
-
237
- for (const result of validation.results) {
238
- if (result.skipped) {
239
- console.log(`ā­ļø ${result.file} - Skipped (not found)`);
240
- } else if (result.noSchema) {
241
- console.log(`šŸ“„ ${result.file} - No schema (skipped)`);
242
- } else if (result.valid) {
243
- console.log(`āœ… ${result.file} - Valid`);
244
- } else {
245
- console.log(`āŒ ${result.file} - Invalid`);
246
- for (const err of result.errors) {
247
- console.log(` └─ ${err.path}: ${err.message}`);
248
- }
249
- }
250
- }
251
-
252
- console.log(`
253
- ${'─'.repeat(50)}
254
- šŸ“Š Summary: ${validation.summary.valid}/${validation.summary.total} valid
255
- `);
256
-
257
- if (validation.summary.invalid > 0) {
258
- console.log('šŸ’” Tip: Run with --fix to auto-fix common issues\n');
259
- }
260
- }
261
-
262
- /**
263
- * CLI entry point
264
- */
265
- async function main() {
266
- const args = process.argv.slice(2);
267
- const jsonMode = args.includes('--json');
268
- const fixMode = args.includes('--fix');
269
-
270
- if (fixMode) {
271
- console.log('šŸ”§ Auto-fixing knowledge files...\n');
272
-
273
- const files = ['mistakes.yaml', 'improvements.yaml', 'evolution-signals.json', 'settings.yaml'];
274
- let totalChanges = 0;
275
-
276
- for (const file of files) {
277
- const result = autoFix(file);
278
- if (result.fixed) {
279
- console.log(`āœ… Fixed ${file}:`);
280
- result.changes.forEach(c => console.log(` └─ ${c}`));
281
- totalChanges += result.changes.length;
282
- }
283
- }
284
-
285
- if (totalChanges === 0) {
286
- console.log('✨ No issues to fix!\n');
287
- } else {
288
- console.log(`\nšŸ”§ Made ${totalChanges} fixes. Re-validating...\n`);
289
- }
290
- }
291
-
292
- const validation = validateAll();
293
-
294
- if (jsonMode) {
295
- console.log(JSON.stringify(validation, null, 2));
296
- process.exit(validation.summary.invalid > 0 ? 1 : 0);
297
- }
298
-
299
- displayResults(validation);
300
- process.exit(validation.summary.invalid > 0 ? 1 : 0);
301
- }
302
-
303
- // Run if called directly
304
- if (process.argv[1]?.includes('knowledge-validator')) {
305
- main();
306
- }
307
-
308
- export default {
309
- validateFile,
310
- validateAll,
311
- autoFix
312
- };