@hawon/nexus 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +44 -71
- package/dist/index.js +15 -24
- package/dist/mcp/server.js +7 -6
- package/package.json +1 -1
- package/scripts/benchmark.ts +13 -35
- package/src/cli/index.ts +45 -84
- package/src/index.ts +17 -27
- package/src/mcp/server.ts +8 -7
- package/src/memory-engine/index.ts +4 -6
- package/src/memory-engine/semantic.ts +38 -11
- package/src/promptguard/advanced-rules.ts +122 -5
- package/src/promptguard/entropy.ts +21 -2
- package/src/promptguard/rules.ts +87 -2
- package/src/promptguard/scanner.test.ts +1 -4
- package/src/promptguard/scanner.ts +1 -1
- package/src/promptguard/semantic.ts +19 -4
- package/src/promptguard/token-analysis.ts +17 -5
- package/src/review/analyzer.ts +106 -23
- package/src/skills/index.ts +11 -27
- package/src/testing/health-check.ts +19 -2
- package/src/memory-engine/compressor.ts +0 -97
- package/src/memory-engine/context-window.ts +0 -113
- package/src/memory-engine/store.ts +0 -371
- package/src/memory-engine/types.ts +0 -32
- package/src/skills/context-engine.ts +0 -863
- package/src/skills/extractor.ts +0 -224
- package/src/skills/global-context.ts +0 -731
- package/src/skills/library.ts +0 -189
- package/src/skills/pattern-engine.ts +0 -715
- package/src/skills/render-evolved.ts +0 -160
- package/src/skills/skill-reconciler.ts +0 -699
- package/src/skills/smart-extractor.ts +0 -849
- package/src/skills/types.ts +0 -18
- package/src/skills/wisdom-extractor.ts +0 -737
- package/src/superdev-evolution/index.ts +0 -3
- package/src/superdev-evolution/skill-manager.ts +0 -266
- package/src/superdev-evolution/types.ts +0 -20
package/dist/cli/index.js
CHANGED
|
@@ -6,16 +6,14 @@ import { discoverSessions } from "../parser/discover.js";
|
|
|
6
6
|
import { discoverAllSessions } from "../parser/unified.js";
|
|
7
7
|
import { parseSession } from "../parser/parse.js";
|
|
8
8
|
import { exportSession } from "../obsidian/exporter.js";
|
|
9
|
-
import { extractSkills } from "../skills/extractor.js";
|
|
10
9
|
import { reviewCode } from "../review/analyzer.js";
|
|
11
10
|
import { mapCodebase } from "../codebase/mapper.js";
|
|
12
11
|
import { generateOnboardingGuide } from "../codebase/onboard.js";
|
|
13
12
|
import { checkTestHealth } from "../testing/health-check.js";
|
|
14
13
|
import { suggestFixes } from "../testing/test-fixer.js";
|
|
15
14
|
import { validateConfig } from "../config/validator.js";
|
|
16
|
-
import {
|
|
15
|
+
import { createNexusMemory } from "../memory-engine/nexus-memory.js";
|
|
17
16
|
import { scan as scanPrompt } from "../promptguard/scanner.js";
|
|
18
|
-
import { addSkills, exportToObsidian, loadSkillLibrary, saveSkillLibrary, searchSkills, } from "../skills/library.js";
|
|
19
17
|
import { extractMemorySkills, renderKnowledgeBase } from "../skills/memory-skill-engine.js";
|
|
20
18
|
import { readdirSync, rmSync } from "node:fs";
|
|
21
19
|
// ── ANSI Colors ──────────────────────────────────────────────────
|
|
@@ -54,7 +52,7 @@ function resolveConfig(flags) {
|
|
|
54
52
|
const vaultPath = flags["--vault"] ??
|
|
55
53
|
process.env["NEXUS_VAULT_PATH"] ??
|
|
56
54
|
join(homedir(), "ObsidianVault", "Claude");
|
|
57
|
-
const dataDir = join(
|
|
55
|
+
const dataDir = process.env["NEXUS_DATA"] ?? join(homedir(), ".nexus");
|
|
58
56
|
return { vaultPath, dataDir };
|
|
59
57
|
}
|
|
60
58
|
function loadStatus(dataDir) {
|
|
@@ -189,30 +187,20 @@ function cmdSync(flags) {
|
|
|
189
187
|
}
|
|
190
188
|
const parsedSessions = [];
|
|
191
189
|
const exportedFiles = [];
|
|
192
|
-
let skillsExtracted = 0;
|
|
193
|
-
const library = loadSkillLibrary(config.dataDir);
|
|
194
190
|
for (let i = 0; i < allSessionPaths.length; i++) {
|
|
195
191
|
const { path: sessionPath } = allSessionPaths[i];
|
|
196
192
|
logProgress(i + 1, allSessionPaths.length, `Syncing session ${i + 1}/${allSessionPaths.length}...`);
|
|
197
193
|
try {
|
|
198
194
|
const session = parseSession(sessionPath);
|
|
199
195
|
parsedSessions.push(session);
|
|
200
|
-
// 3. Export to Obsidian
|
|
201
196
|
const filePath = exportSessionToObsidian(session, config.vaultPath);
|
|
202
197
|
exportedFiles.push(filePath);
|
|
203
|
-
// 4. Extract skills
|
|
204
|
-
const skills = extractSkills(session);
|
|
205
|
-
const added = addSkills(library, skills);
|
|
206
|
-
skillsExtracted += added;
|
|
207
198
|
}
|
|
208
199
|
catch (err) {
|
|
209
200
|
const msg = err instanceof Error ? err.message : String(err);
|
|
210
201
|
log(`\n${c.yellow}Warning:${c.reset} Failed to parse ${sessionPath}: ${msg}`);
|
|
211
202
|
}
|
|
212
203
|
}
|
|
213
|
-
// 5. Save skill library & export to Obsidian
|
|
214
|
-
saveSkillLibrary(library, config.dataDir);
|
|
215
|
-
const skillFiles = exportToObsidian(library, config.vaultPath);
|
|
216
204
|
// 6. Update MOC and daily notes
|
|
217
205
|
logInfo("Updating MOC and daily notes...");
|
|
218
206
|
updateMOC(parsedSessions, config.vaultPath);
|
|
@@ -221,18 +209,15 @@ function cmdSync(flags) {
|
|
|
221
209
|
const status = {
|
|
222
210
|
lastSync: new Date().toISOString(),
|
|
223
211
|
totalSessions: parsedSessions.length,
|
|
224
|
-
totalSkills:
|
|
212
|
+
totalSkills: 0,
|
|
225
213
|
sessionsExported: parsedSessions.map((s) => s.sessionId),
|
|
226
214
|
};
|
|
227
215
|
saveStatus(status, config.dataDir);
|
|
228
|
-
// Summary
|
|
229
216
|
log("");
|
|
230
217
|
log(`${c.bold}${c.green}Sync complete!${c.reset}`);
|
|
231
218
|
log(` ${c.cyan}Sessions exported:${c.reset} ${exportedFiles.length}`);
|
|
232
|
-
log(` ${c.cyan}New skills found:${c.reset} ${skillsExtracted}`);
|
|
233
|
-
log(` ${c.cyan}Total skills:${c.reset} ${library.skills.length}`);
|
|
234
|
-
log(` ${c.cyan}Skill files:${c.reset} ${skillFiles.length}`);
|
|
235
219
|
log(` ${c.cyan}Vault path:${c.reset} ${config.vaultPath}`);
|
|
220
|
+
log(` ${c.dim}Run \`nexus reorganize\` to extract knowledge.${c.reset}`);
|
|
236
221
|
}
|
|
237
222
|
function cmdSessions() {
|
|
238
223
|
const discovery = discoverSessions();
|
|
@@ -289,30 +274,36 @@ function cmdExport(sessionId, flags) {
|
|
|
289
274
|
const session = parseSession(matchedPath);
|
|
290
275
|
const filePath = exportSessionToObsidian(session, config.vaultPath);
|
|
291
276
|
logSuccess(`Exported to ${filePath}`);
|
|
292
|
-
// Extract skills too
|
|
293
|
-
const library = loadSkillLibrary(config.dataDir);
|
|
294
|
-
const skills = extractSkills(session);
|
|
295
|
-
const added = addSkills(library, skills);
|
|
296
|
-
if (added > 0) {
|
|
297
|
-
saveSkillLibrary(library, config.dataDir);
|
|
298
|
-
logSuccess(`Extracted ${added} new skill(s)`);
|
|
299
|
-
}
|
|
300
277
|
}
|
|
301
278
|
function cmdSkills(flags) {
|
|
302
279
|
const config = resolveConfig(flags);
|
|
303
|
-
const
|
|
304
|
-
if (
|
|
305
|
-
logInfo("No
|
|
280
|
+
const kbPath = join(config.dataDir, "knowledge.json");
|
|
281
|
+
if (!existsSync(kbPath)) {
|
|
282
|
+
logInfo("No knowledge extracted yet. Run `nexus reorganize` first.");
|
|
306
283
|
return;
|
|
307
284
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
285
|
+
const kb = JSON.parse(readFileSync(kbPath, "utf-8"));
|
|
286
|
+
const skills = kb.skills ?? [];
|
|
287
|
+
const tips = kb.tips ?? [];
|
|
288
|
+
const facts = kb.facts ?? [];
|
|
289
|
+
log(`\n${c.bold}Knowledge Base${c.reset} (${skills.length} skills | ${tips.length} tips | ${facts.length} facts)\n`);
|
|
290
|
+
if (skills.length > 0) {
|
|
291
|
+
log(`${c.bold}Skills:${c.reset}`);
|
|
292
|
+
for (const s of skills) {
|
|
293
|
+
log(` ${c.cyan}${s.name.slice(0, 50)}${c.reset} — ${(s.confidence * 100).toFixed(0)}% | ${s.evidenceCount} evidence`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (tips.length > 0) {
|
|
297
|
+
log(`\n${c.bold}Tips:${c.reset}`);
|
|
298
|
+
for (const t of tips) {
|
|
299
|
+
log(` 💡 ${t.advice?.slice(0, 60) ?? t.name}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (facts.length > 0) {
|
|
303
|
+
log(`\n${c.bold}Facts:${c.reset}`);
|
|
304
|
+
for (const f of facts) {
|
|
305
|
+
log(` 📌 ${f.statement?.slice(0, 60) ?? f.name}`);
|
|
306
|
+
}
|
|
316
307
|
}
|
|
317
308
|
log("");
|
|
318
309
|
}
|
|
@@ -321,32 +312,16 @@ function cmdSkillsSearch(query, flags) {
|
|
|
321
312
|
logError("Usage: nexus skills search <query>");
|
|
322
313
|
process.exit(1);
|
|
323
314
|
}
|
|
324
|
-
|
|
325
|
-
const library = loadSkillLibrary(config.dataDir);
|
|
326
|
-
const results = searchSkills(library, query);
|
|
327
|
-
if (results.length === 0) {
|
|
328
|
-
logInfo(`No skills matching "${query}".`);
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
log(`\n${c.bold}Skills matching "${query}"${c.reset} (${results.length} results)\n`);
|
|
332
|
-
for (const skill of results) {
|
|
333
|
-
log(`${c.cyan}${c.bold}${skill.name}${c.reset} ${c.dim}(${(skill.confidence * 100).toFixed(0)}% confidence)${c.reset}`);
|
|
334
|
-
log(` ${c.dim}Trigger:${c.reset} ${skill.trigger}`);
|
|
335
|
-
log(` ${c.dim}Tools:${c.reset} ${skill.toolsUsed.join(", ")}`);
|
|
336
|
-
log(` ${c.dim}Steps:${c.reset} ${skill.steps.length}`);
|
|
337
|
-
log("");
|
|
338
|
-
}
|
|
315
|
+
logInfo(`Search not available yet. Use \`nexus skills\` to view all knowledge.`);
|
|
339
316
|
}
|
|
340
317
|
function cmdStatus(flags) {
|
|
341
318
|
const config = resolveConfig(flags);
|
|
342
319
|
const status = loadStatus(config.dataDir);
|
|
343
|
-
|
|
344
|
-
log(`\n${c.bold}Claude Vault Status${c.reset}\n`);
|
|
320
|
+
log(`\n${c.bold}Nexus Status${c.reset}\n`);
|
|
345
321
|
log(` ${c.cyan}Vault path:${c.reset} ${config.vaultPath}`);
|
|
346
322
|
log(` ${c.cyan}Last sync:${c.reset} ${status.lastSync || "never"}`);
|
|
347
|
-
log(` ${c.cyan}
|
|
348
|
-
log(` ${c.cyan}
|
|
349
|
-
log(` ${c.cyan}Library ver:${c.reset} ${library.version}`);
|
|
323
|
+
log(` ${c.cyan}Sessions:${c.reset} ${status.sessionsExported ?? 0}`);
|
|
324
|
+
log(` ${c.cyan}Knowledge:${c.reset} ${status.totalKnowledge ?? "run reorganize"}`);
|
|
350
325
|
log("");
|
|
351
326
|
}
|
|
352
327
|
function cmdReorganize(flags) {
|
|
@@ -604,13 +579,13 @@ async function cmdConfig(dir, flags) {
|
|
|
604
579
|
}
|
|
605
580
|
function cmdMemory(subcommand, query, flags) {
|
|
606
581
|
const config = resolveConfig(flags);
|
|
607
|
-
const store =
|
|
582
|
+
const store = createNexusMemory(config.dataDir);
|
|
608
583
|
if (subcommand === "search") {
|
|
609
584
|
if (!query) {
|
|
610
585
|
logError("Usage: nexus memory search <query>");
|
|
611
586
|
process.exit(1);
|
|
612
587
|
}
|
|
613
|
-
const results = store.search(
|
|
588
|
+
const results = store.search(query);
|
|
614
589
|
if ("--json" in flags) {
|
|
615
590
|
log(JSON.stringify(results, null, 2));
|
|
616
591
|
return;
|
|
@@ -620,10 +595,9 @@ function cmdMemory(subcommand, query, flags) {
|
|
|
620
595
|
return;
|
|
621
596
|
}
|
|
622
597
|
log(`\n${c.bold}Memory Search: "${query}"${c.reset} (${results.length} results)\n`);
|
|
623
|
-
for (const
|
|
624
|
-
log(` ${c.cyan}${
|
|
625
|
-
log(` ${
|
|
626
|
-
log(` ${entry.content.slice(0, 120)}${entry.content.length > 120 ? "..." : ""}`);
|
|
598
|
+
for (const r of results) {
|
|
599
|
+
log(` ${c.cyan}[${r.retrievalLevel}]${c.reset} score=${r.score.toFixed(2)}`);
|
|
600
|
+
log(` ${r.observation.content.slice(0, 120)}`);
|
|
627
601
|
log("");
|
|
628
602
|
}
|
|
629
603
|
}
|
|
@@ -634,13 +608,12 @@ function cmdMemory(subcommand, query, flags) {
|
|
|
634
608
|
return;
|
|
635
609
|
}
|
|
636
610
|
log(`\n${c.bold}Memory Stats${c.reset}\n`);
|
|
637
|
-
log(` ${c.cyan}
|
|
638
|
-
log(` ${c.cyan}
|
|
639
|
-
log(` ${c.cyan}
|
|
640
|
-
log(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
611
|
+
log(` ${c.cyan}Observations:${c.reset} ${stats.totalObservations}`);
|
|
612
|
+
log(` ${c.cyan}Valid:${c.reset} ${stats.validObservations}`);
|
|
613
|
+
log(` ${c.cyan}Graph nodes:${c.reset} ${stats.graphNodes}`);
|
|
614
|
+
log(` ${c.cyan}Graph edges:${c.reset} ${stats.graphEdges}`);
|
|
615
|
+
log(` ${c.cyan}Tunnels:${c.reset} ${stats.tunnels}`);
|
|
616
|
+
log(` ${c.cyan}Domains:${c.reset} ${stats.domains.join(", ")}`);
|
|
644
617
|
log("");
|
|
645
618
|
}
|
|
646
619
|
else {
|
package/dist/index.js
CHANGED
|
@@ -7,34 +7,25 @@ export { discoverOpenClawSessions, parseOpenClawSession } from "./parser/opencla
|
|
|
7
7
|
export { exportSession } from "./obsidian/exporter.js";
|
|
8
8
|
export { updateMOC } from "./obsidian/moc.js";
|
|
9
9
|
export { appendToDailyNote } from "./obsidian/daily-note.js";
|
|
10
|
-
// Skills —
|
|
11
|
-
export {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
17
|
-
export {
|
|
18
|
-
//
|
|
10
|
+
// Skills — Memory-based Knowledge Extraction
|
|
11
|
+
export { extractMemorySkills, renderKnowledgeBase } from "./skills/memory-skill-engine.js";
|
|
12
|
+
// Prompt Injection Detection
|
|
13
|
+
export { scan, isInjected, guard, scanBatch, PromptInjectionError } from "./promptguard/scanner.js";
|
|
14
|
+
export { BUILTIN_RULES } from "./promptguard/rules.js";
|
|
15
|
+
export { ADVANCED_RULES } from "./promptguard/advanced-rules.js";
|
|
16
|
+
export { MULTILINGUAL_RULES } from "./promptguard/multilingual-rules.js";
|
|
17
|
+
export { normalizeText } from "./promptguard/normalize.js";
|
|
18
|
+
// Memory Engine
|
|
19
|
+
export { createNexusMemory } from "./memory-engine/nexus-memory.js";
|
|
20
|
+
export { semanticSimilarity, expandQuery, getSynonyms } from "./memory-engine/semantic.js";
|
|
21
|
+
// Code Review
|
|
19
22
|
export { reviewCode } from "./review/analyzer.js";
|
|
20
23
|
export { reviewDiff } from "./review/diff-reviewer.js";
|
|
21
|
-
// Codebase Mapping
|
|
24
|
+
// Codebase Mapping
|
|
22
25
|
export { mapCodebase } from "./codebase/mapper.js";
|
|
23
26
|
export { generateOnboardingGuide } from "./codebase/onboard.js";
|
|
24
|
-
// Test Health
|
|
27
|
+
// Test Health
|
|
25
28
|
export { checkTestHealth } from "./testing/health-check.js";
|
|
26
29
|
export { suggestFixes } from "./testing/test-fixer.js";
|
|
27
|
-
// Config Validator
|
|
30
|
+
// Config Validator
|
|
28
31
|
export { validateConfig } from "./config/validator.js";
|
|
29
|
-
// Infinite Memory (from superdev)
|
|
30
|
-
export { createMemoryStore } from "./memory-engine/store.js";
|
|
31
|
-
export { createContextWindow } from "./memory-engine/context-window.js";
|
|
32
|
-
// Prompt Injection Detection (from promptguard)
|
|
33
|
-
export { scan, isInjected, guard, scanBatch, PromptInjectionError } from "./promptguard/scanner.js";
|
|
34
|
-
export { BUILTIN_RULES } from "./promptguard/rules.js";
|
|
35
|
-
export { ADVANCED_RULES } from "./promptguard/advanced-rules.js";
|
|
36
|
-
export { MULTILINGUAL_RULES } from "./promptguard/multilingual-rules.js";
|
|
37
|
-
export { normalizeText } from "./promptguard/normalize.js";
|
|
38
|
-
export { analyzeEntropy } from "./promptguard/entropy.js";
|
|
39
|
-
export { classifyIntent } from "./promptguard/semantic.js";
|
|
40
|
-
export { analyzeTokens } from "./promptguard/token-analysis.js";
|
package/dist/mcp/server.js
CHANGED
|
@@ -46,17 +46,17 @@ import { suggestFixes } from "../testing/test-fixer.js";
|
|
|
46
46
|
// Config
|
|
47
47
|
import { validateConfig } from "../config/validator.js";
|
|
48
48
|
// Memory
|
|
49
|
-
import {
|
|
49
|
+
import { createNexusMemory } from "../memory-engine/nexus-memory.js";
|
|
50
50
|
// Prompt injection
|
|
51
51
|
import { scan, isInjected } from "../promptguard/scanner.js";
|
|
52
52
|
// Knowledge — uses cached data from last `nexus reorganize`
|
|
53
53
|
const server = new McpServer({ name: "nexus", version: "0.1.0" });
|
|
54
|
-
const dataDir = resolve(process.env.NEXUS_DATA ?? ".nexus");
|
|
54
|
+
const dataDir = resolve(process.env.NEXUS_DATA ?? join(process.env.HOME ?? "/home", ".nexus"));
|
|
55
55
|
// Singleton memory store (avoid re-reading from disk on every MCP call)
|
|
56
56
|
let _memoryStore = null;
|
|
57
57
|
function getMemoryStore() {
|
|
58
58
|
if (!_memoryStore)
|
|
59
|
-
_memoryStore =
|
|
59
|
+
_memoryStore = createNexusMemory(dataDir);
|
|
60
60
|
return _memoryStore;
|
|
61
61
|
}
|
|
62
62
|
// ─── Session Intelligence ────────────────────────────────────────
|
|
@@ -149,7 +149,7 @@ server.tool("nexus_memory_search", "Search persistent memory for relevant past i
|
|
|
149
149
|
limit: z.number().optional().describe("Max results (default: 10)"),
|
|
150
150
|
}, async ({ query, limit }) => {
|
|
151
151
|
const store = getMemoryStore();
|
|
152
|
-
const results = store.search(
|
|
152
|
+
const results = store.search(query, limit ?? 10);
|
|
153
153
|
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
|
|
154
154
|
});
|
|
155
155
|
server.tool("nexus_memory_save", "Save information to persistent memory for future reference.", {
|
|
@@ -157,8 +157,9 @@ server.tool("nexus_memory_save", "Save information to persistent memory for futu
|
|
|
157
157
|
tags: z.array(z.string()).optional().describe("Tags for categorization"),
|
|
158
158
|
}, async ({ content, tags }) => {
|
|
159
159
|
const store = getMemoryStore();
|
|
160
|
-
const
|
|
161
|
-
|
|
160
|
+
const count = store.ingest(content, "manual");
|
|
161
|
+
store.save();
|
|
162
|
+
return { content: [{ type: "text", text: JSON.stringify({ saved: true, observations: count }) }] };
|
|
162
163
|
});
|
|
163
164
|
// ─── Knowledge (Skills + Tips + Facts) ───────────────────────────
|
|
164
165
|
server.tool("nexus_skills", "List all knowledge: skills (complex patterns), tips (quick advice), and facts (reference info).", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hawon/nexus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The all-in-one AI developer framework — session intelligence, code review, prompt injection defense, infinite memory, self-evolving skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/scripts/benchmark.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Tests all 5 performance areas:
|
|
5
5
|
* 1. Prompt Injection Detection — accuracy, false positive rate
|
|
6
6
|
* 2. Memory Search — BM25+semantic vs TF-IDF precision
|
|
7
|
-
* 3.
|
|
7
|
+
* 3. Session Parser — parse rate and coverage
|
|
8
8
|
* 4. Code Review — detection accuracy
|
|
9
9
|
* 5. Speed — throughput across all modules
|
|
10
10
|
*/
|
|
@@ -15,8 +15,6 @@ import { semanticSimilarity } from "../src/memory-engine/semantic.js";
|
|
|
15
15
|
import { reviewCode } from "../src/review/analyzer.js";
|
|
16
16
|
import { discoverSessions } from "../src/parser/discover.js";
|
|
17
17
|
import { parseSession } from "../src/parser/parse.js";
|
|
18
|
-
import { extractWisdom } from "../src/skills/wisdom-extractor.js";
|
|
19
|
-
import { reconcileWisdom } from "../src/skills/skill-reconciler.js";
|
|
20
18
|
|
|
21
19
|
const BOLD = "\x1b[1m";
|
|
22
20
|
const GREEN = "\x1b[32m";
|
|
@@ -234,17 +232,15 @@ function benchmarkMemory(): void {
|
|
|
234
232
|
// 3. SKILL EXTRACTION BENCHMARK
|
|
235
233
|
// ═══════════════════════════════════════════════════════════════════
|
|
236
234
|
|
|
237
|
-
function
|
|
238
|
-
header("3.
|
|
235
|
+
function benchmarkSessionParser(): void {
|
|
236
|
+
header("3. Session Parser");
|
|
239
237
|
|
|
240
238
|
const discovery = discoverSessions();
|
|
241
239
|
let totalSessions = 0;
|
|
242
240
|
let parsedSessions = 0;
|
|
243
|
-
let totalWisdoms = 0;
|
|
244
241
|
let totalMessages = 0;
|
|
245
|
-
|
|
242
|
+
let failedSessions = 0;
|
|
246
243
|
|
|
247
|
-
// Parse all sessions
|
|
248
244
|
for (const proj of discovery.projects) {
|
|
249
245
|
for (const sp of proj.sessions) {
|
|
250
246
|
totalSessions++;
|
|
@@ -252,38 +248,20 @@ function benchmarkSkills(): void {
|
|
|
252
248
|
const session = parseSession(sp);
|
|
253
249
|
parsedSessions++;
|
|
254
250
|
totalMessages += session.messages.length;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
} catch { /* skip */ }
|
|
251
|
+
} catch {
|
|
252
|
+
failedSessions++;
|
|
253
|
+
}
|
|
259
254
|
}
|
|
260
255
|
}
|
|
261
256
|
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
const result = reconcileWisdom(allWisdoms, library);
|
|
257
|
+
const parseRate = totalSessions > 0 ? (parsedSessions / totalSessions * 100).toFixed(0) : "0";
|
|
258
|
+
const avgMessages = parsedSessions > 0 ? (totalMessages / parsedSessions).toFixed(1) : "0";
|
|
265
259
|
|
|
266
260
|
metric("Sessions discovered", String(totalSessions));
|
|
267
|
-
metric("Sessions parsed", `${parsedSessions} (${
|
|
261
|
+
metric("Sessions parsed", `${parsedSessions}/${totalSessions} (${parseRate}%)`);
|
|
262
|
+
metric("Parse failures", String(failedSessions));
|
|
268
263
|
metric("Total messages", String(totalMessages));
|
|
269
|
-
metric("
|
|
270
|
-
metric("Quality gate rejected", `${result.rejected.length} (${(result.rejected.length / totalWisdoms * 100).toFixed(0)}%)`);
|
|
271
|
-
metric("Refined skills created", String(result.created.length));
|
|
272
|
-
metric("Skills updated", String(result.updated.length));
|
|
273
|
-
metric("Preferences learned", String(result.preferencesLearned.length));
|
|
274
|
-
metric("Extraction rate", `${(totalWisdoms / parsedSessions).toFixed(1)} wisdoms/session`);
|
|
275
|
-
metric("Quality rate", `${((result.created.length + result.updated.length) / Math.max(totalWisdoms, 1) * 100).toFixed(1)}% pass quality gate`);
|
|
276
|
-
|
|
277
|
-
// Rejection breakdown
|
|
278
|
-
const reasons: Record<string, number> = {};
|
|
279
|
-
for (const r of result.rejected) {
|
|
280
|
-
reasons[r.reason] = (reasons[r.reason] ?? 0) + 1;
|
|
281
|
-
}
|
|
282
|
-
log("");
|
|
283
|
-
log(" Quality Gate Rejection Breakdown:");
|
|
284
|
-
for (const [reason, count] of Object.entries(reasons).sort(([, a], [, b]) => b - a)) {
|
|
285
|
-
log(` ${count}x — ${reason.slice(0, 60)}`);
|
|
286
|
-
}
|
|
264
|
+
metric("Avg messages/session", avgMessages);
|
|
287
265
|
}
|
|
288
266
|
|
|
289
267
|
// ═══════════════════════════════════════════════════════════════════
|
|
@@ -459,7 +437,7 @@ log(`${BOLD}╚═════════════════════
|
|
|
459
437
|
|
|
460
438
|
benchmarkInjection();
|
|
461
439
|
benchmarkMemory();
|
|
462
|
-
|
|
440
|
+
benchmarkSessionParser();
|
|
463
441
|
benchmarkReview();
|
|
464
442
|
benchmarkSpeed();
|
|
465
443
|
|