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.
- package/README.md +1 -1
- package/bin/lib/commands/install.js +119 -242
- package/package.json +3 -4
- package/lib/agent-cli/bin/agent.js +0 -187
- package/lib/agent-cli/dashboard/dashboard_server.js +0 -312
- package/lib/agent-cli/lib/ab-testing.js +0 -364
- package/lib/agent-cli/lib/audit.js +0 -154
- package/lib/agent-cli/lib/audit.test.js +0 -100
- package/lib/agent-cli/lib/auto-learn.js +0 -319
- package/lib/agent-cli/lib/backup.js +0 -138
- package/lib/agent-cli/lib/backup.test.js +0 -78
- package/lib/agent-cli/lib/causality-engine.js +0 -331
- package/lib/agent-cli/lib/cognitive-lesson.js +0 -476
- package/lib/agent-cli/lib/completion.js +0 -149
- package/lib/agent-cli/lib/config.js +0 -35
- package/lib/agent-cli/lib/dashboard-data.js +0 -380
- package/lib/agent-cli/lib/eslint-fix.js +0 -238
- package/lib/agent-cli/lib/evolution-signal.js +0 -215
- package/lib/agent-cli/lib/export.js +0 -86
- package/lib/agent-cli/lib/export.test.js +0 -65
- package/lib/agent-cli/lib/fix.js +0 -337
- package/lib/agent-cli/lib/fix.test.js +0 -80
- package/lib/agent-cli/lib/gemini-export.js +0 -83
- package/lib/agent-cli/lib/generate-registry.js +0 -42
- package/lib/agent-cli/lib/hooks/install-hooks.js +0 -152
- package/lib/agent-cli/lib/hooks/lint-learn.js +0 -172
- package/lib/agent-cli/lib/icons.js +0 -93
- package/lib/agent-cli/lib/ignore.js +0 -116
- package/lib/agent-cli/lib/ignore.test.js +0 -58
- package/lib/agent-cli/lib/init.js +0 -124
- package/lib/agent-cli/lib/knowledge-index.js +0 -326
- package/lib/agent-cli/lib/knowledge-metrics.js +0 -335
- package/lib/agent-cli/lib/knowledge-retention.js +0 -398
- package/lib/agent-cli/lib/knowledge-validator.js +0 -312
- package/lib/agent-cli/lib/learn.js +0 -255
- package/lib/agent-cli/lib/learn.test.js +0 -70
- package/lib/agent-cli/lib/metrics-collector.js +0 -410
- package/lib/agent-cli/lib/proposals.js +0 -199
- package/lib/agent-cli/lib/proposals.test.js +0 -56
- package/lib/agent-cli/lib/recall.js +0 -835
- package/lib/agent-cli/lib/recall.test.js +0 -107
- package/lib/agent-cli/lib/reinforcement.js +0 -299
- package/lib/agent-cli/lib/selfevolution-bridge.js +0 -167
- package/lib/agent-cli/lib/settings.js +0 -203
- package/lib/agent-cli/lib/skill-generator.js +0 -379
- package/lib/agent-cli/lib/skill-learn.js +0 -296
- package/lib/agent-cli/lib/stats.js +0 -132
- package/lib/agent-cli/lib/stats.test.js +0 -94
- package/lib/agent-cli/lib/types.js +0 -33
- package/lib/agent-cli/lib/ui/audit-ui.js +0 -146
- package/lib/agent-cli/lib/ui/backup-ui.js +0 -107
- package/lib/agent-cli/lib/ui/clack-helpers.js +0 -317
- package/lib/agent-cli/lib/ui/common.js +0 -83
- package/lib/agent-cli/lib/ui/completion-ui.js +0 -126
- package/lib/agent-cli/lib/ui/custom-select.js +0 -69
- package/lib/agent-cli/lib/ui/dashboard-ui.js +0 -222
- package/lib/agent-cli/lib/ui/evolution-signals-ui.js +0 -107
- package/lib/agent-cli/lib/ui/export-ui.js +0 -94
- package/lib/agent-cli/lib/ui/fix-all-ui.js +0 -191
- package/lib/agent-cli/lib/ui/help-ui.js +0 -49
- package/lib/agent-cli/lib/ui/index.js +0 -199
- package/lib/agent-cli/lib/ui/init-ui.js +0 -56
- package/lib/agent-cli/lib/ui/knowledge-ui.js +0 -55
- package/lib/agent-cli/lib/ui/learn-ui.js +0 -706
- package/lib/agent-cli/lib/ui/lessons-ui.js +0 -148
- package/lib/agent-cli/lib/ui/pretty.js +0 -145
- package/lib/agent-cli/lib/ui/proposals-ui.js +0 -99
- package/lib/agent-cli/lib/ui/recall-ui.js +0 -342
- package/lib/agent-cli/lib/ui/routing-demo.js +0 -79
- package/lib/agent-cli/lib/ui/routing-ui.js +0 -325
- package/lib/agent-cli/lib/ui/settings-ui.js +0 -381
- package/lib/agent-cli/lib/ui/stats-ui.js +0 -123
- package/lib/agent-cli/lib/ui/watch-ui.js +0 -236
- package/lib/agent-cli/lib/watcher.js +0 -181
- package/lib/agent-cli/lib/watcher.test.js +0 -85
- package/lib/agent-cli/src/MIGRATION.md +0 -418
- package/lib/agent-cli/src/README.md +0 -367
- package/lib/agent-cli/src/core/evolution/evolution-signal.js +0 -42
- package/lib/agent-cli/src/core/evolution/index.js +0 -17
- package/lib/agent-cli/src/core/evolution/review-gate.js +0 -40
- package/lib/agent-cli/src/core/evolution/signal-detector.js +0 -137
- package/lib/agent-cli/src/core/evolution/signal-queue.js +0 -79
- package/lib/agent-cli/src/core/evolution/threshold-checker.js +0 -79
- package/lib/agent-cli/src/core/index.js +0 -15
- package/lib/agent-cli/src/core/learning/cognitive-enhancer.js +0 -282
- package/lib/agent-cli/src/core/learning/index.js +0 -12
- package/lib/agent-cli/src/core/learning/lesson-synthesizer.js +0 -83
- package/lib/agent-cli/src/core/scanning/index.js +0 -14
- package/lib/agent-cli/src/data/index.js +0 -13
- package/lib/agent-cli/src/data/repositories/index.js +0 -8
- package/lib/agent-cli/src/data/repositories/lesson-repository.js +0 -130
- package/lib/agent-cli/src/data/repositories/signal-repository.js +0 -119
- package/lib/agent-cli/src/data/storage/index.js +0 -8
- package/lib/agent-cli/src/data/storage/json-storage.js +0 -64
- package/lib/agent-cli/src/data/storage/yaml-storage.js +0 -66
- package/lib/agent-cli/src/infrastructure/index.js +0 -13
- package/lib/agent-cli/src/presentation/formatters/skill-formatter.js +0 -232
- package/lib/agent-cli/src/services/export-service.js +0 -162
- package/lib/agent-cli/src/services/index.js +0 -13
- 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
|
-
};
|