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,215 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Evolution Signal Layer - Backward Compatibility Adapter
|
|
3
|
-
*
|
|
4
|
-
* This file maintains the old API while delegating to the new architecture.
|
|
5
|
-
* Allows gradual migration without breaking existing code.
|
|
6
|
-
*
|
|
7
|
-
* OLD LOCATION: lib/evolution-signal.js
|
|
8
|
-
* NEW LOCATION: src/core/evolution/* + src/data/repositories/*
|
|
9
|
-
*
|
|
10
|
-
* @deprecated Use new architecture: import from 'src/core/evolution'
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// Import new architecture components
|
|
14
|
-
import { EvolutionSignal } from '../src/core/evolution/evolution-signal.js';
|
|
15
|
-
import { ThresholdChecker } from '../src/core/evolution/threshold-checker.js';
|
|
16
|
-
import { ReviewGate } from '../src/core/evolution/review-gate.js';
|
|
17
|
-
import { SignalRepository } from '../src/data/repositories/signal-repository.js';
|
|
18
|
-
import { JsonStorage } from '../src/data/storage/json-storage.js';
|
|
19
|
-
import { SignalDetector as SignalService } from '../src/core/evolution/signal-detector.js';
|
|
20
|
-
import { KNOWLEDGE_DIR } from './config.js';
|
|
21
|
-
|
|
22
|
-
// ============================================================================
|
|
23
|
-
// BACKWARD COMPATIBLE EXPORTS
|
|
24
|
-
// ============================================================================
|
|
25
|
-
|
|
26
|
-
// Re-export EvolutionSignal class
|
|
27
|
-
export { EvolutionSignal };
|
|
28
|
-
|
|
29
|
-
// Lazy-initialized singleton instances
|
|
30
|
-
let _storage = null;
|
|
31
|
-
let _repository = null;
|
|
32
|
-
let _detector = null;
|
|
33
|
-
|
|
34
|
-
function getDetector() {
|
|
35
|
-
if (!_detector) {
|
|
36
|
-
_storage = new JsonStorage(KNOWLEDGE_DIR);
|
|
37
|
-
_repository = new SignalRepository(_storage);
|
|
38
|
-
_detector = new SignalService(_repository);
|
|
39
|
-
}
|
|
40
|
-
return _detector;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ============================================================================
|
|
44
|
-
// THRESHOLD CHECKER (Backward Compatible)
|
|
45
|
-
// ============================================================================
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @deprecated Use ThresholdChecker.check() from src/core/evolution
|
|
49
|
-
*/
|
|
50
|
-
export function checkEvolutionThreshold(lesson, threshold = 10) {
|
|
51
|
-
return ThresholdChecker.check(lesson, threshold);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @deprecated Use ThresholdChecker.calculateStability() from src/core/evolution
|
|
56
|
-
*/
|
|
57
|
-
export function calculatePatternStability(violationHistory = []) {
|
|
58
|
-
return ThresholdChecker.calculateStability(violationHistory);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ============================================================================
|
|
62
|
-
// SIGNAL QUEUE (Backward Compatible)
|
|
63
|
-
// ============================================================================
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* SignalQueue - Backward compatible class
|
|
67
|
-
* @deprecated Use SignalRepository + SignalDetector from new architecture
|
|
68
|
-
*/
|
|
69
|
-
class SignalQueueCompat {
|
|
70
|
-
get signals() {
|
|
71
|
-
// Return cached signals (sync access)
|
|
72
|
-
if (!this._cachedSignals) {
|
|
73
|
-
// Synchronous fallback - load on first access
|
|
74
|
-
this._cachedSignals = [];
|
|
75
|
-
this.load().then(signals => {
|
|
76
|
-
this._cachedSignals = signals;
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
return this._cachedSignals;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async load() {
|
|
83
|
-
const detector = getDetector();
|
|
84
|
-
const all = await detector.signalRepository.findAll();
|
|
85
|
-
this._cachedSignals = all;
|
|
86
|
-
return all;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async save() {
|
|
90
|
-
// Auto-save through repository (no-op for compatibility)
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async add(signal) {
|
|
95
|
-
const detector = getDetector();
|
|
96
|
-
const result = await detector.queue(
|
|
97
|
-
signal.lessonId,
|
|
98
|
-
{ ready: true, reason: signal.reason, confidence: signal.confidence },
|
|
99
|
-
signal.metadata
|
|
100
|
-
);
|
|
101
|
-
await this.load(); // Refresh cache
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
getPending() {
|
|
106
|
-
return this.signals.filter(s => s.status === 'pending');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
getByLesson(lessonId) {
|
|
110
|
-
return this.signals.filter(s => s.lessonId === lessonId);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async approve(signalId) {
|
|
114
|
-
const detector = getDetector();
|
|
115
|
-
const result = await detector.approve(signalId);
|
|
116
|
-
await this.load(); // Refresh cache
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async reject(signalId) {
|
|
121
|
-
const detector = getDetector();
|
|
122
|
-
const result = await detector.reject(signalId);
|
|
123
|
-
await this.load(); // Refresh cache
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async execute(signalId) {
|
|
128
|
-
const detector = getDetector();
|
|
129
|
-
const result = await detector.execute(signalId);
|
|
130
|
-
await this.load(); // Refresh cache
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async cleanup() {
|
|
135
|
-
const detector = getDetector();
|
|
136
|
-
await detector.signalRepository.cleanup();
|
|
137
|
-
await this.load(); // Refresh cache
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Singleton instance for backward compatibility
|
|
142
|
-
const signalQueueInstance = new SignalQueueCompat();
|
|
143
|
-
|
|
144
|
-
// Initialize on module load
|
|
145
|
-
signalQueueInstance.load().catch(err => {
|
|
146
|
-
console.error('Failed to initialize signal queue:', err);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
export { signalQueueInstance as signalQueue };
|
|
150
|
-
|
|
151
|
-
// ============================================================================
|
|
152
|
-
// REVIEW GATE (Backward Compatible)
|
|
153
|
-
// ============================================================================
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* @deprecated Use ReviewGate.evaluate() from src/core/evolution
|
|
157
|
-
*/
|
|
158
|
-
export function reviewGate(signal, settings = {}) {
|
|
159
|
-
return ReviewGate.evaluate(signal, settings);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ============================================================================
|
|
163
|
-
// HELPER FUNCTIONS (Backward Compatible)
|
|
164
|
-
// ============================================================================
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @deprecated Use SignalDetector.queue() from new architecture
|
|
168
|
-
*/
|
|
169
|
-
export async function queueEvolutionSignal(lessonId, checkResult, metadata = {}) {
|
|
170
|
-
if (!checkResult.ready) return null;
|
|
171
|
-
|
|
172
|
-
const signal = new EvolutionSignal(
|
|
173
|
-
lessonId,
|
|
174
|
-
checkResult.reason,
|
|
175
|
-
checkResult.confidence,
|
|
176
|
-
metadata
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
return signalQueueInstance.add(signal);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* @deprecated Use SignalDetector.getStats() from new architecture
|
|
184
|
-
*/
|
|
185
|
-
export async function getEvolutionStats() {
|
|
186
|
-
const detector = getDetector();
|
|
187
|
-
return detector.getStats();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// ============================================================================
|
|
191
|
-
// MIGRATION GUIDE
|
|
192
|
-
// ============================================================================
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* HOW TO MIGRATE TO NEW ARCHITECTURE:
|
|
196
|
-
*
|
|
197
|
-
* OLD CODE:
|
|
198
|
-
* ```
|
|
199
|
-
* import { signalQueue, checkEvolutionThreshold } from './evolution-signal.js';
|
|
200
|
-
*
|
|
201
|
-
* const check = checkEvolutionThreshold(lesson, 10);
|
|
202
|
-
* await signalQueue.add(signal);
|
|
203
|
-
* ```
|
|
204
|
-
*
|
|
205
|
-
* NEW CODE:
|
|
206
|
-
* ```
|
|
207
|
-
* import { ThresholdChecker } from '../src/core/evolution/threshold-checker.js';
|
|
208
|
-
* import { SignalRepository } from '../src/data/repositories/signal-repository.js';
|
|
209
|
-
* import { SignalDetector } from '../src/core/evolution/signal-detector.js';
|
|
210
|
-
*
|
|
211
|
-
* const check = ThresholdChecker.check(lesson, 10);
|
|
212
|
-
* const detector = new SignalDetector(repository);
|
|
213
|
-
* await detector.queue(lessonId, check, metadata);
|
|
214
|
-
* ```
|
|
215
|
-
*/
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Export and Import for PikaKit
|
|
3
|
-
* Share settings between projects
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import yaml from "js-yaml";
|
|
9
|
-
import { LESSONS_PATH } from "./config.js";
|
|
10
|
-
import { SETTINGS_PATH, loadSettings } from "./settings.js";
|
|
11
|
-
import { loadKnowledge, saveKnowledge } from "./recall.js";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Export lessons and settings to JSON file
|
|
15
|
-
* @param {string} outputPath - Output file path
|
|
16
|
-
* @returns {boolean}
|
|
17
|
-
*/
|
|
18
|
-
export function exportData(outputPath) {
|
|
19
|
-
try {
|
|
20
|
-
const data = {
|
|
21
|
-
version: 1,
|
|
22
|
-
exportedAt: new Date().toISOString(),
|
|
23
|
-
lessons: loadKnowledge().lessons || [],
|
|
24
|
-
settings: loadSettings()
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2), "utf8");
|
|
28
|
-
return true;
|
|
29
|
-
} catch (e) {
|
|
30
|
-
console.error("Failed to export:", e.message);
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Import data from JSON file
|
|
37
|
-
* @param {string} inputPath - Input file path
|
|
38
|
-
* @param {"merge" | "replace"} mode - Import mode
|
|
39
|
-
* @returns {{ success: boolean, lessonsCount: number, hasSettings: boolean }}
|
|
40
|
-
*/
|
|
41
|
-
export function importData(inputPath, mode = "merge") {
|
|
42
|
-
try {
|
|
43
|
-
if (!fs.existsSync(inputPath)) {
|
|
44
|
-
return { success: false, lessonsCount: 0, hasSettings: false };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const content = fs.readFileSync(inputPath, "utf8");
|
|
48
|
-
const data = JSON.parse(content);
|
|
49
|
-
|
|
50
|
-
// Import lessons
|
|
51
|
-
const currentDb = loadKnowledge();
|
|
52
|
-
|
|
53
|
-
if (mode === "replace") {
|
|
54
|
-
currentDb.lessons = data.lessons || [];
|
|
55
|
-
} else {
|
|
56
|
-
// Merge - add new lessons, skip duplicates by pattern
|
|
57
|
-
const existingPatterns = new Set(currentDb.lessons.map(l => l.pattern));
|
|
58
|
-
for (const lesson of (data.lessons || [])) {
|
|
59
|
-
if (!existingPatterns.has(lesson.pattern)) {
|
|
60
|
-
currentDb.lessons.push(lesson);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
saveKnowledge(currentDb);
|
|
66
|
-
|
|
67
|
-
// Import settings if present
|
|
68
|
-
let hasSettings = false;
|
|
69
|
-
if (data.settings) {
|
|
70
|
-
const settingsPath = SETTINGS_PATH;
|
|
71
|
-
fs.writeFileSync(settingsPath, yaml.dump(data.settings), "utf8");
|
|
72
|
-
hasSettings = true;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
success: true,
|
|
77
|
-
lessonsCount: data.lessons?.length || 0,
|
|
78
|
-
hasSettings
|
|
79
|
-
};
|
|
80
|
-
} catch (e) {
|
|
81
|
-
console.error("Failed to import:", e.message);
|
|
82
|
-
return { success: false, lessonsCount: 0, hasSettings: false };
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export default { exportData, importData };
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Tests for export module
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import os from "os";
|
|
9
|
-
|
|
10
|
-
describe("export", () => {
|
|
11
|
-
const testDir = path.join(os.tmpdir(), "test-export-" + Date.now());
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
fs.mkdirSync(testDir, { recursive: true });
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
afterEach(() => {
|
|
18
|
-
if (fs.existsSync(testDir)) {
|
|
19
|
-
fs.rmSync(testDir, { recursive: true, force: true });
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
describe("export format", () => {
|
|
24
|
-
it("creates valid JSON structure", () => {
|
|
25
|
-
const data = {
|
|
26
|
-
version: 1,
|
|
27
|
-
exportedAt: new Date().toISOString(),
|
|
28
|
-
lessons: [{ id: "TEST", pattern: "x" }]
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const outputPath = path.join(testDir, "export.json");
|
|
32
|
-
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2));
|
|
33
|
-
|
|
34
|
-
const loaded = JSON.parse(fs.readFileSync(outputPath, "utf8"));
|
|
35
|
-
expect(loaded.version).toBe(1);
|
|
36
|
-
expect(loaded.lessons).toHaveLength(1);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("supports lesson array format", () => {
|
|
40
|
-
const lessons = [
|
|
41
|
-
{ id: "L1", pattern: "a", message: "msg" },
|
|
42
|
-
{ id: "L2", pattern: "b", message: "msg2" }
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
const data = { version: 1, lessons };
|
|
46
|
-
const json = JSON.stringify(data);
|
|
47
|
-
const parsed = JSON.parse(json);
|
|
48
|
-
|
|
49
|
-
expect(parsed.lessons).toHaveLength(2);
|
|
50
|
-
expect(parsed.lessons[0].id).toBe("L1");
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("import validation", () => {
|
|
55
|
-
it("validates version field", () => {
|
|
56
|
-
const valid = { version: 1, lessons: [] };
|
|
57
|
-
expect(valid.version).toBe(1);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("validates lessons array", () => {
|
|
61
|
-
const valid = { version: 1, lessons: [{ id: "X", pattern: "y" }] };
|
|
62
|
-
expect(Array.isArray(valid.lessons)).toBe(true);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
});
|
package/lib/agent-cli/lib/fix.js
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Smart Fix - Auto-fix Detected Violations
|
|
4
|
-
*
|
|
5
|
-
* Automatically fixes code violations based on learned patterns.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Comment out violations (safe mode)
|
|
9
|
-
* - Remove violations (aggressive mode)
|
|
10
|
-
* - Replace patterns (custom fix rules)
|
|
11
|
-
*
|
|
12
|
-
* Usage: agent fix <file|directory> [--mode safe|aggressive]
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import fs from "fs";
|
|
16
|
-
import path from "path";
|
|
17
|
-
import { loadKnowledge, saveKnowledge, scanFile, scanDirectory } from "./recall.js";
|
|
18
|
-
import { VERSION } from "./config.js";
|
|
19
|
-
|
|
20
|
-
// ============================================================================
|
|
21
|
-
// FIX RULES
|
|
22
|
-
// ============================================================================
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Built-in fix rules for common patterns
|
|
26
|
-
*/
|
|
27
|
-
const FIX_RULES = {
|
|
28
|
-
// Console statements ā comment out
|
|
29
|
-
"console.log": {
|
|
30
|
-
type: "comment",
|
|
31
|
-
replacement: (line) => `// REMOVED: ${line.trim()}`
|
|
32
|
-
},
|
|
33
|
-
"console.warn": {
|
|
34
|
-
type: "comment",
|
|
35
|
-
replacement: (line) => `// REMOVED: ${line.trim()}`
|
|
36
|
-
},
|
|
37
|
-
"console.error": {
|
|
38
|
-
type: "comment",
|
|
39
|
-
replacement: (line) => `// REMOVED: ${line.trim()}`
|
|
40
|
-
},
|
|
41
|
-
"console.debug": {
|
|
42
|
-
type: "comment",
|
|
43
|
-
replacement: (line) => `// REMOVED: ${line.trim()}`
|
|
44
|
-
},
|
|
45
|
-
"console.info": {
|
|
46
|
-
type: "comment",
|
|
47
|
-
replacement: (line) => `// REMOVED: ${line.trim()}`
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
// var ā const
|
|
51
|
-
"\\bvar\\s+": {
|
|
52
|
-
type: "replace",
|
|
53
|
-
replacement: (line) => line.replace(/\bvar\s+/, "const ")
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
// == ā === (loose equality)
|
|
57
|
-
"[^!=]==[^=]": {
|
|
58
|
-
type: "replace",
|
|
59
|
-
replacement: (line) => line.replace(/([^!=])==([^=])/g, "$1===$2")
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
// != ā !== (loose inequality)
|
|
63
|
-
"[^!]=!=[^=]": {
|
|
64
|
-
type: "replace",
|
|
65
|
-
replacement: (line) => line.replace(/([^!])!=([^=])/g, "$1!==$2")
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
// debugger ā remove
|
|
69
|
-
"\\bdebugger\\b": {
|
|
70
|
-
type: "remove",
|
|
71
|
-
replacement: () => ""
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
// alert ā comment out
|
|
75
|
-
"\\balert\\(": {
|
|
76
|
-
type: "comment",
|
|
77
|
-
replacement: (line) => `// REMOVED: ${line.trim()}`
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
// TODO/FIXME in production ā warn only
|
|
81
|
-
"TODO|FIXME": {
|
|
82
|
-
type: "comment",
|
|
83
|
-
replacement: (line) => line // Leave as is, just flag
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
// Empty catch blocks ā add comment
|
|
87
|
-
"catch\\s*\\([^)]*\\)\\s*\\{\\s*\\}": {
|
|
88
|
-
type: "replace",
|
|
89
|
-
replacement: (line) => line.replace(/\{\s*\}/, "{ /* Intentionally empty */ }")
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
// Promise without catch ā add comment
|
|
93
|
-
"\\.then\\([^)]*\\)(?!.*\\.catch)": {
|
|
94
|
-
type: "comment",
|
|
95
|
-
replacement: (line) => `${line} // TODO: Add .catch()`
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
// Hardcoded localhost ā flag
|
|
99
|
-
"localhost:\\d+": {
|
|
100
|
-
type: "comment",
|
|
101
|
-
replacement: (line) => `// REVIEW: ${line.trim()} // Hardcoded URL`
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
// @ts-ignore ā flag for review
|
|
105
|
-
"@ts-ignore": {
|
|
106
|
-
type: "comment",
|
|
107
|
-
replacement: (line) => `${line} // TODO: Fix instead of ignoring`
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
// any type in TypeScript ā flag
|
|
111
|
-
": any": {
|
|
112
|
-
type: "comment",
|
|
113
|
-
replacement: (line) => `${line} // TODO: Replace 'any' with proper type`
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
// ============================================================================
|
|
118
|
-
// FIX ENGINE
|
|
119
|
-
// ============================================================================
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Fix a single file
|
|
123
|
-
* @param {string} filePath
|
|
124
|
-
* @param {object} db - Knowledge base
|
|
125
|
-
* @param {string} mode - 'safe' or 'aggressive'
|
|
126
|
-
* @returns {{ file: string, fixes: number, backup: string }}
|
|
127
|
-
*/
|
|
128
|
-
function fixFile(filePath, db, mode = "safe") {
|
|
129
|
-
if (!fs.existsSync(filePath)) {
|
|
130
|
-
return { file: filePath, fixes: 0, error: "File not found" };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const content = fs.readFileSync(filePath, "utf8");
|
|
134
|
-
const lines = content.split("\n");
|
|
135
|
-
let fixCount = 0;
|
|
136
|
-
let modified = false;
|
|
137
|
-
|
|
138
|
-
// Scan for violations
|
|
139
|
-
const result = scanFile(filePath, db, false);
|
|
140
|
-
|
|
141
|
-
if (result.violations.length === 0) {
|
|
142
|
-
return { file: filePath, fixes: 0 };
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Create backup
|
|
146
|
-
const backupPath = filePath + ".backup";
|
|
147
|
-
fs.writeFileSync(backupPath, content, "utf8");
|
|
148
|
-
|
|
149
|
-
// Apply fixes
|
|
150
|
-
result.violations.forEach(({ lesson, matches }) => {
|
|
151
|
-
const rule = FIX_RULES[lesson.pattern] || {
|
|
152
|
-
type: mode === "aggressive" ? "remove" : "comment",
|
|
153
|
-
replacement: (line) => mode === "aggressive" ? "" : `// FLAGGED: ${line.trim()}`
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
matches.forEach(match => {
|
|
157
|
-
const lineIdx = match.line - 1;
|
|
158
|
-
if (lineIdx >= 0 && lineIdx < lines.length) {
|
|
159
|
-
const originalLine = lines[lineIdx];
|
|
160
|
-
|
|
161
|
-
if (rule.type === "remove") {
|
|
162
|
-
lines[lineIdx] = "";
|
|
163
|
-
fixCount++;
|
|
164
|
-
modified = true;
|
|
165
|
-
} else if (rule.type === "comment") {
|
|
166
|
-
if (!originalLine.trim().startsWith("//")) {
|
|
167
|
-
lines[lineIdx] = rule.replacement(originalLine);
|
|
168
|
-
fixCount++;
|
|
169
|
-
modified = true;
|
|
170
|
-
}
|
|
171
|
-
} else if (rule.type === "replace") {
|
|
172
|
-
const newLine = rule.replacement(originalLine);
|
|
173
|
-
if (newLine !== originalLine) {
|
|
174
|
-
lines[lineIdx] = newLine;
|
|
175
|
-
fixCount++;
|
|
176
|
-
modified = true;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// Write fixed content
|
|
184
|
-
if (modified) {
|
|
185
|
-
const newContent = lines.filter(l => l !== "" || mode !== "aggressive").join("\n");
|
|
186
|
-
fs.writeFileSync(filePath, newContent, "utf8");
|
|
187
|
-
} else {
|
|
188
|
-
// Remove backup if no changes
|
|
189
|
-
fs.unlinkSync(backupPath);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
file: filePath,
|
|
194
|
-
fixes: fixCount,
|
|
195
|
-
backup: modified ? backupPath : null
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Fix all files in directory
|
|
201
|
-
*/
|
|
202
|
-
function fixDirectory(dirPath, db, mode = "safe") {
|
|
203
|
-
const results = [];
|
|
204
|
-
const extensions = [".js", ".ts", ".tsx", ".jsx", ".mjs"];
|
|
205
|
-
|
|
206
|
-
function walk(dir) {
|
|
207
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
208
|
-
|
|
209
|
-
for (const entry of entries) {
|
|
210
|
-
const fullPath = path.join(dir, entry.name);
|
|
211
|
-
|
|
212
|
-
if (entry.isDirectory()) {
|
|
213
|
-
if (!["node_modules", ".git", "dist", "build"].includes(entry.name)) {
|
|
214
|
-
walk(fullPath);
|
|
215
|
-
}
|
|
216
|
-
} else if (entry.isFile()) {
|
|
217
|
-
const ext = path.extname(entry.name);
|
|
218
|
-
if (extensions.includes(ext)) {
|
|
219
|
-
const result = fixFile(fullPath, db, mode);
|
|
220
|
-
if (result.fixes > 0) {
|
|
221
|
-
results.push(result);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (fs.statSync(dirPath).isDirectory()) {
|
|
229
|
-
walk(dirPath);
|
|
230
|
-
} else {
|
|
231
|
-
const result = fixFile(dirPath, db, mode);
|
|
232
|
-
if (result.fixes > 0) {
|
|
233
|
-
results.push(result);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return results;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// ============================================================================
|
|
241
|
-
// CLI
|
|
242
|
-
// ============================================================================
|
|
243
|
-
|
|
244
|
-
async function main() {
|
|
245
|
-
const args = process.argv.slice(2);
|
|
246
|
-
|
|
247
|
-
if (args.length === 0 || args.includes("--help")) {
|
|
248
|
-
console.log(`
|
|
249
|
-
š§ Smart Fix v${VERSION} - Auto-fix Violations
|
|
250
|
-
|
|
251
|
-
Usage:
|
|
252
|
-
agent fix <file|directory> [options]
|
|
253
|
-
|
|
254
|
-
Options:
|
|
255
|
-
--mode safe Comment out violations (default)
|
|
256
|
-
--mode aggressive Remove violations entirely
|
|
257
|
-
--eslint Also run ESLint --fix
|
|
258
|
-
--dry-run Show what would be fixed without changing files
|
|
259
|
-
--help Show this help
|
|
260
|
-
|
|
261
|
-
Examples:
|
|
262
|
-
agent fix src/
|
|
263
|
-
agent fix app.js --mode aggressive
|
|
264
|
-
agent fix src/ --eslint
|
|
265
|
-
`);
|
|
266
|
-
process.exit(0);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const target = args[0];
|
|
270
|
-
const mode = args.includes("--mode")
|
|
271
|
-
? args[args.indexOf("--mode") + 1]
|
|
272
|
-
: "safe";
|
|
273
|
-
const dryRun = args.includes("--dry-run");
|
|
274
|
-
const useEslint = args.includes("--eslint");
|
|
275
|
-
|
|
276
|
-
const db = loadKnowledge();
|
|
277
|
-
|
|
278
|
-
if (!db.lessons || db.lessons.length === 0) {
|
|
279
|
-
console.log("ā¹ļø No lessons learned yet. Nothing to fix.");
|
|
280
|
-
process.exit(0);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
console.log(`\nš§ Smart Fix v${VERSION}`);
|
|
284
|
-
console.log(`š Target: ${target}`);
|
|
285
|
-
console.log(`šÆ Mode: ${mode}`);
|
|
286
|
-
if (useEslint) console.log(`š§ ESLint: enabled`);
|
|
287
|
-
console.log(`${"ā".repeat(50)}\n`);
|
|
288
|
-
|
|
289
|
-
// Run ESLint fix first if enabled
|
|
290
|
-
if (useEslint && !dryRun) {
|
|
291
|
-
try {
|
|
292
|
-
const { runEslintFix } = await import("./eslint-fix.js");
|
|
293
|
-
runEslintFix(target);
|
|
294
|
-
} catch (e) {
|
|
295
|
-
console.log(`ā ļø ESLint fix skipped: ${e.message}`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (dryRun) {
|
|
300
|
-
console.log("š DRY RUN - showing what would be fixed:\n");
|
|
301
|
-
const scanResults = scanDirectory(target, db);
|
|
302
|
-
scanResults.forEach(r => {
|
|
303
|
-
console.log(`š ${path.relative(process.cwd(), r.file)}`);
|
|
304
|
-
r.violations.forEach(v => {
|
|
305
|
-
console.log(` Would fix ${v.matches.length} violation(s) of [${v.lesson.id}]`);
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
process.exit(0);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const results = fixDirectory(target, db, mode);
|
|
312
|
-
|
|
313
|
-
if (results.length === 0) {
|
|
314
|
-
console.log("ā
No pattern violations to fix.");
|
|
315
|
-
process.exit(0);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
let totalFixes = 0;
|
|
319
|
-
results.forEach(r => {
|
|
320
|
-
totalFixes += r.fixes;
|
|
321
|
-
console.log(`ā
${path.relative(process.cwd(), r.file)}: ${r.fixes} fix(es)`);
|
|
322
|
-
if (r.backup) {
|
|
323
|
-
console.log(` š¦ Backup: ${path.basename(r.backup)}`);
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
console.log(`\n${"ā".repeat(50)}`);
|
|
328
|
-
console.log(`š Fixed ${totalFixes} violation(s) in ${results.length} file(s)`);
|
|
329
|
-
console.log(`š” Backups created with .backup extension`);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Run if executed directly (as async)
|
|
333
|
-
if (process.argv[1].includes("fix")) {
|
|
334
|
-
main().catch(console.error);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export { fixFile, fixDirectory, FIX_RULES };
|