@kage-core/kage-graph-mcp 1.0.0 → 1.1.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/README.md +294 -0
- package/dist/cli.js +726 -0
- package/dist/daemon.js +230 -0
- package/dist/index.js +659 -21
- package/dist/kernel.js +4177 -0
- package/dist/registry/index.js +373 -0
- package/package.json +17 -8
- package/viewer/app.js +1000 -0
- package/viewer/index.html +136 -0
- package/viewer/styles.css +530 -0
- package/index.ts +0 -254
- package/tsconfig.json +0 -14
package/dist/cli.js
ADDED
|
@@ -0,0 +1,726 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const promises_1 = require("node:readline/promises");
|
|
5
|
+
const node_process_1 = require("node:process");
|
|
6
|
+
const daemon_js_1 = require("./daemon.js");
|
|
7
|
+
const kernel_js_1 = require("./kernel.js");
|
|
8
|
+
function usage() {
|
|
9
|
+
console.log(`Kage Repo-Recall MVP
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
kage index --project <dir>
|
|
13
|
+
kage init --project <dir>
|
|
14
|
+
kage policy --project <dir>
|
|
15
|
+
kage doctor --project <dir>
|
|
16
|
+
kage setup list
|
|
17
|
+
kage setup <agent> --project <dir> [--write] [--json]
|
|
18
|
+
kage setup doctor --project <dir> [--json]
|
|
19
|
+
kage daemon start --project <dir> [--port 3111]
|
|
20
|
+
kage daemon stop --project <dir>
|
|
21
|
+
kage daemon status --project <dir> [--json]
|
|
22
|
+
kage daemon doctor --project <dir> [--json]
|
|
23
|
+
kage viewer --project <dir> [--port 3113]
|
|
24
|
+
kage branch --project <dir> [--json]
|
|
25
|
+
kage metrics --project <dir> [--json]
|
|
26
|
+
kage quality --project <dir> [--json]
|
|
27
|
+
kage benchmark --project <dir> [--json]
|
|
28
|
+
kage code-graph --project <dir> [--json]
|
|
29
|
+
kage code-graph "<query>" --project <dir> [--json]
|
|
30
|
+
kage graph --project <dir> [--json]
|
|
31
|
+
kage graph --project <dir> --mermaid
|
|
32
|
+
kage graph "<query>" --project <dir> [--json]
|
|
33
|
+
kage recall "<query>" --project <dir> [--json] [--explain]
|
|
34
|
+
kage observe --project <dir> --event <json>
|
|
35
|
+
kage distill --project <dir> --session <id>
|
|
36
|
+
kage learn --project <dir> --learning <text> [--title <title>] [--type <type>] [--evidence <text>] [--verified-by <text>] [--tags a,b] [--paths a,b]
|
|
37
|
+
kage feedback --project <dir> --packet <packet-id> --kind helpful|wrong|stale
|
|
38
|
+
kage capture --project <dir> --title <title> --body <body> [--type <type>] [--summary <summary>] [--tags a,b] [--paths a,b] [--stack a,b]
|
|
39
|
+
kage propose --project <dir> --from-diff
|
|
40
|
+
kage review-artifact --project <dir>
|
|
41
|
+
kage promote --project <dir> --public <packet-id>
|
|
42
|
+
kage export-public --project <dir>
|
|
43
|
+
kage registry --project <dir> [--json]
|
|
44
|
+
kage marketplace --project <dir> [--json]
|
|
45
|
+
kage org status --project <dir> --org <org> [--json]
|
|
46
|
+
kage org upload --project <dir> --org <org> --packet <approved-packet-id>
|
|
47
|
+
kage org review --project <dir> --org <org> --packet <org-packet-id> --approve|--reject
|
|
48
|
+
kage org recall "<query>" --project <dir> --org <org> [--json]
|
|
49
|
+
kage org export --project <dir> --org <org> [--json]
|
|
50
|
+
kage layered-recall "<query>" --project <dir> [--org <org>] [--global] [--json]
|
|
51
|
+
kage global build --project <dir> [--org <org>] [--json]
|
|
52
|
+
kage review --project <dir>
|
|
53
|
+
kage validate --project <dir>
|
|
54
|
+
|
|
55
|
+
Types:
|
|
56
|
+
${kernel_js_1.MEMORY_TYPES.join(", ")}
|
|
57
|
+
`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
function takeArg(args, name) {
|
|
61
|
+
const index = args.indexOf(name);
|
|
62
|
+
if (index === -1)
|
|
63
|
+
return undefined;
|
|
64
|
+
return args[index + 1];
|
|
65
|
+
}
|
|
66
|
+
function listArg(value) {
|
|
67
|
+
return value ? value.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
68
|
+
}
|
|
69
|
+
function projectArg(args) {
|
|
70
|
+
return takeArg(args, "--project") ?? process.cwd();
|
|
71
|
+
}
|
|
72
|
+
function numberArg(args, name, fallback) {
|
|
73
|
+
const value = takeArg(args, name);
|
|
74
|
+
return value ? Number(value) : fallback;
|
|
75
|
+
}
|
|
76
|
+
function firstPositional(args) {
|
|
77
|
+
return args.find((arg, index) => index > 0 && !arg.startsWith("--") && !args[index - 1]?.startsWith("--"));
|
|
78
|
+
}
|
|
79
|
+
async function review(projectDir) {
|
|
80
|
+
const pending = (0, kernel_js_1.loadPendingPackets)(projectDir);
|
|
81
|
+
if (pending.length === 0) {
|
|
82
|
+
console.log("No pending packets to review.");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
86
|
+
try {
|
|
87
|
+
for (const packet of pending) {
|
|
88
|
+
console.log("\n─────────────────────────────────────────");
|
|
89
|
+
console.log(`Title: ${packet.title}`);
|
|
90
|
+
console.log(`Type: ${packet.type}`);
|
|
91
|
+
console.log(`ID: ${packet.id}`);
|
|
92
|
+
console.log(`Tags: ${packet.tags.join(", ") || "(none)"}`);
|
|
93
|
+
console.log(`Paths: ${packet.paths.join(", ") || "(none)"}`);
|
|
94
|
+
console.log("\n" + packet.body);
|
|
95
|
+
const answer = (await rl.question("\n(a) approve (r) reject (s) skip (q) quit: ")).trim().toLowerCase();
|
|
96
|
+
if (answer === "q")
|
|
97
|
+
break;
|
|
98
|
+
if (answer === "a") {
|
|
99
|
+
const path = (0, kernel_js_1.approvePending)(projectDir, packet.id);
|
|
100
|
+
console.log(`Approved: ${path}`);
|
|
101
|
+
}
|
|
102
|
+
else if (answer === "r") {
|
|
103
|
+
const path = (0, kernel_js_1.rejectPending)(projectDir, packet.id);
|
|
104
|
+
console.log(`Rejected: ${path}`);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log("Skipped.");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
rl.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function main() {
|
|
116
|
+
const args = process.argv.slice(2);
|
|
117
|
+
const command = args[0];
|
|
118
|
+
if (!command)
|
|
119
|
+
usage();
|
|
120
|
+
if (command === "index") {
|
|
121
|
+
const result = (0, kernel_js_1.indexProject)(projectArg(args));
|
|
122
|
+
console.log(`Indexed ${result.projectDir}`);
|
|
123
|
+
console.log(`Packets: ${result.packets}`);
|
|
124
|
+
console.log(`Migrated legacy nodes: ${result.migrated}`);
|
|
125
|
+
if (result.policyPath)
|
|
126
|
+
console.log(`Agent policy: ${result.policyPath}`);
|
|
127
|
+
console.log(`Indexes:\n${result.indexes.map((path) => ` - ${path}`).join("\n")}`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (command === "init") {
|
|
131
|
+
const result = (0, kernel_js_1.initProject)(projectArg(args));
|
|
132
|
+
console.log(`Initialized Kage memory for ${result.index.projectDir}`);
|
|
133
|
+
console.log(`Packets: ${result.index.packets}`);
|
|
134
|
+
console.log(`Migrated legacy nodes: ${result.index.migrated}`);
|
|
135
|
+
if (result.index.policyPath)
|
|
136
|
+
console.log(`Agent policy: ${result.index.policyPath}`);
|
|
137
|
+
console.log(result.validation.ok ? "Validation passed." : "Validation failed.");
|
|
138
|
+
if (result.validation.errors.length)
|
|
139
|
+
console.log(`Errors:\n${result.validation.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
140
|
+
if (result.validation.warnings.length)
|
|
141
|
+
console.log(`Warnings:\n${result.validation.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
142
|
+
console.log("\nFirst recall preview:\n");
|
|
143
|
+
console.log(result.sampleRecall.context_block);
|
|
144
|
+
if (!result.validation.ok)
|
|
145
|
+
process.exit(2);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (command === "policy") {
|
|
149
|
+
const result = (0, kernel_js_1.installAgentPolicy)(projectArg(args));
|
|
150
|
+
console.log(`${result.created ? "Created" : result.updated ? "Updated" : "Already current"} agent policy: ${result.path}`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (command === "doctor") {
|
|
154
|
+
const result = (0, kernel_js_1.doctorProject)(projectArg(args));
|
|
155
|
+
if (args.includes("--json")) {
|
|
156
|
+
console.log(JSON.stringify(result, null, 2));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
console.log(`Kage Doctor: ${result.projectDir}`);
|
|
160
|
+
console.log(`Memory root: ${result.memoryRoot}`);
|
|
161
|
+
console.log(`Git branch: ${result.gitBranch ?? "(not a git repo)"}`);
|
|
162
|
+
console.log(`Packets: ${result.packets}`);
|
|
163
|
+
console.log(`Pending: ${result.pending}`);
|
|
164
|
+
console.log(`Public candidates: ${result.publicCandidates}`);
|
|
165
|
+
console.log(`Graph entities: ${result.graphEntities}`);
|
|
166
|
+
console.log(`Graph edges: ${result.graphEdges}`);
|
|
167
|
+
console.log(`Registry recommendations: ${result.registryRecommendations.length}`);
|
|
168
|
+
console.log(`Indexes present: ${result.indexesPresent.join(", ") || "(none)"}`);
|
|
169
|
+
console.log(`Indexes missing: ${result.indexesMissing.join(", ") || "(none)"}`);
|
|
170
|
+
console.log(result.validation.ok ? "Validation: passed" : "Validation: failed");
|
|
171
|
+
if (result.validation.errors.length)
|
|
172
|
+
console.log(`Errors:\n${result.validation.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
173
|
+
if (result.validation.warnings.length)
|
|
174
|
+
console.log(`Warnings:\n${result.validation.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
175
|
+
console.log("\nRecall smoke test:\n");
|
|
176
|
+
console.log(result.sampleRecall);
|
|
177
|
+
if (!result.validation.ok)
|
|
178
|
+
process.exit(2);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (command === "setup") {
|
|
182
|
+
const action = args[1];
|
|
183
|
+
if (action === "list") {
|
|
184
|
+
console.log(kernel_js_1.SETUP_AGENTS.join("\n"));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (action === "doctor") {
|
|
188
|
+
const result = (0, kernel_js_1.setupDoctor)(projectArg(args));
|
|
189
|
+
if (args.includes("--json")) {
|
|
190
|
+
console.log(JSON.stringify(result, null, 2));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
console.log("Kage setup doctor");
|
|
194
|
+
for (const item of result) {
|
|
195
|
+
console.log(`- ${item.agent}: ${item.configured ? "configured" : "not detected"}${item.config_path ? ` (${item.config_path})` : ""}`);
|
|
196
|
+
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (!action || !kernel_js_1.SETUP_AGENTS.includes(action))
|
|
200
|
+
usage();
|
|
201
|
+
const result = (0, kernel_js_1.setupAgent)(action, projectArg(args), { write: args.includes("--write") });
|
|
202
|
+
if (args.includes("--json")) {
|
|
203
|
+
console.log(JSON.stringify(result, null, 2));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
console.log(`Kage setup for ${result.agent}`);
|
|
207
|
+
if (result.config_path)
|
|
208
|
+
console.log(`Config path: ${result.config_path}`);
|
|
209
|
+
console.log(result.write_supported ? `Write support: ${result.wrote ? "wrote config" : "available with --write"}` : "Write support: print-only");
|
|
210
|
+
console.log("\nConfig:\n");
|
|
211
|
+
console.log(result.config);
|
|
212
|
+
if (result.instructions.length) {
|
|
213
|
+
console.log("\nInstructions:");
|
|
214
|
+
for (const instruction of result.instructions)
|
|
215
|
+
console.log(`- ${instruction}`);
|
|
216
|
+
}
|
|
217
|
+
if (result.warnings.length) {
|
|
218
|
+
console.log("\nWarnings:");
|
|
219
|
+
for (const warning of result.warnings)
|
|
220
|
+
console.log(`- ${warning}`);
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (command === "daemon") {
|
|
225
|
+
const action = args[1];
|
|
226
|
+
const projectDir = projectArg(args);
|
|
227
|
+
if (action === "start") {
|
|
228
|
+
await (0, daemon_js_1.startDaemon)(projectDir, { restPort: numberArg(args, "--port", 3111) });
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (action === "stop") {
|
|
232
|
+
const result = (0, daemon_js_1.stopDaemon)(projectDir);
|
|
233
|
+
if (args.includes("--json"))
|
|
234
|
+
console.log(JSON.stringify(result, null, 2));
|
|
235
|
+
else
|
|
236
|
+
console.log(result.message);
|
|
237
|
+
if (!result.ok)
|
|
238
|
+
process.exit(2);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (action === "status") {
|
|
242
|
+
const result = (0, daemon_js_1.readDaemonStatus)(projectDir);
|
|
243
|
+
if (args.includes("--json"))
|
|
244
|
+
console.log(JSON.stringify(result ?? { ok: false }, null, 2));
|
|
245
|
+
else if (result)
|
|
246
|
+
console.log(`Kage daemon pid ${result.pid} at http://${result.host}:${result.rest_port}`);
|
|
247
|
+
else
|
|
248
|
+
console.log("No Kage daemon status found.");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (action === "doctor") {
|
|
252
|
+
const result = (0, daemon_js_1.daemonDoctor)(projectDir);
|
|
253
|
+
if (args.includes("--json")) {
|
|
254
|
+
console.log(JSON.stringify(result, null, 2));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
console.log(`Daemon configured: ${result.configured ? "yes" : "no"}`);
|
|
258
|
+
console.log(`Daemon running: ${result.running ? "yes" : "no"}`);
|
|
259
|
+
console.log("Endpoints:");
|
|
260
|
+
for (const endpoint of result.endpoints)
|
|
261
|
+
console.log(`- ${endpoint}`);
|
|
262
|
+
if (result.warnings.length)
|
|
263
|
+
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
usage();
|
|
267
|
+
}
|
|
268
|
+
if (command === "viewer") {
|
|
269
|
+
await (0, daemon_js_1.startViewer)(projectArg(args), { port: numberArg(args, "--port", 3113) });
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (command === "graph") {
|
|
273
|
+
const query = firstPositional(args);
|
|
274
|
+
if (query) {
|
|
275
|
+
const result = (0, kernel_js_1.queryGraph)(projectArg(args), query);
|
|
276
|
+
if (args.includes("--json"))
|
|
277
|
+
console.log(JSON.stringify(result, null, 2));
|
|
278
|
+
else
|
|
279
|
+
console.log(result.context_block);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (args.includes("--mermaid")) {
|
|
283
|
+
const result = (0, kernel_js_1.graphMermaid)(projectArg(args));
|
|
284
|
+
console.log("```mermaid");
|
|
285
|
+
console.log(result.mermaid);
|
|
286
|
+
console.log("```");
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const graph = (0, kernel_js_1.buildKnowledgeGraph)(projectArg(args));
|
|
290
|
+
if (args.includes("--json")) {
|
|
291
|
+
console.log(JSON.stringify(graph, null, 2));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
console.log(`Kage Graph: ${graph.project_dir}`);
|
|
295
|
+
console.log(`Entities: ${graph.entities.length}`);
|
|
296
|
+
console.log(`Edges: ${graph.edges.length}`);
|
|
297
|
+
console.log(`Episodes: ${graph.episodes.length}`);
|
|
298
|
+
console.log(`Branch: ${graph.repo_state.branch ?? "(none)"}`);
|
|
299
|
+
console.log("\nTop facts:");
|
|
300
|
+
for (const edge of graph.edges.slice(0, 10))
|
|
301
|
+
console.log(`- ${edge.fact}`);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (command === "code-graph") {
|
|
305
|
+
const query = firstPositional(args);
|
|
306
|
+
if (query) {
|
|
307
|
+
const result = (0, kernel_js_1.queryCodeGraph)(projectArg(args), query);
|
|
308
|
+
if (args.includes("--json"))
|
|
309
|
+
console.log(JSON.stringify(result, null, 2));
|
|
310
|
+
else
|
|
311
|
+
console.log(result.context_block);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const graph = (0, kernel_js_1.buildCodeGraph)(projectArg(args));
|
|
315
|
+
if (args.includes("--json")) {
|
|
316
|
+
console.log(JSON.stringify(graph, null, 2));
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
console.log(`Kage Code Graph: ${graph.project_dir}`);
|
|
320
|
+
console.log(`Files: ${graph.files.length}`);
|
|
321
|
+
console.log(`Symbols: ${graph.symbols.length}`);
|
|
322
|
+
console.log(`Imports: ${graph.imports.length}`);
|
|
323
|
+
console.log(`Calls: ${graph.calls.length}`);
|
|
324
|
+
console.log(`Routes: ${graph.routes.length}`);
|
|
325
|
+
console.log(`Tests: ${graph.tests.length}`);
|
|
326
|
+
console.log(`Packages/scripts: ${graph.packages.length}`);
|
|
327
|
+
console.log(`Branch: ${graph.repo_state.branch ?? "(none)"}`);
|
|
328
|
+
console.log("\nTop symbols:");
|
|
329
|
+
for (const symbol of graph.symbols.slice(0, 10))
|
|
330
|
+
console.log(`- ${symbol.kind} ${symbol.name} (${symbol.path}:${symbol.line})`);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (command === "branch") {
|
|
334
|
+
const result = (0, kernel_js_1.buildBranchOverlay)(projectArg(args));
|
|
335
|
+
if (args.includes("--json"))
|
|
336
|
+
console.log(JSON.stringify(result, null, 2));
|
|
337
|
+
else {
|
|
338
|
+
console.log(`Branch: ${result.branch ?? "(detached)"}`);
|
|
339
|
+
console.log(`Head: ${result.head ?? "(none)"}`);
|
|
340
|
+
console.log(`Merge base: ${result.merge_base ?? "(none)"}`);
|
|
341
|
+
console.log(`Changed files: ${result.changed_files.join(", ") || "(none)"}`);
|
|
342
|
+
console.log(`Pending packets: ${result.pending_packet_ids.length}`);
|
|
343
|
+
}
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
if (command === "metrics") {
|
|
347
|
+
const result = (0, kernel_js_1.kageMetrics)(projectArg(args));
|
|
348
|
+
if (args.includes("--json")) {
|
|
349
|
+
console.log(JSON.stringify(result, null, 2));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
console.log(`Kage Metrics: ${result.project_dir}`);
|
|
353
|
+
console.log(`Readiness score: ${result.harness.readiness_score}/100`);
|
|
354
|
+
console.log(`Validation: ${result.harness.validation_ok ? "passed" : "failed"} (${result.harness.errors} errors, ${result.harness.warnings} warnings)`);
|
|
355
|
+
console.log(`Policy installed: ${result.harness.policy_installed ? "yes" : "no"}`);
|
|
356
|
+
console.log("\nCode graph:");
|
|
357
|
+
console.log(` Files: ${result.code_graph.files}`);
|
|
358
|
+
console.log(` Symbols: ${result.code_graph.symbols}`);
|
|
359
|
+
console.log(` Imports: ${result.code_graph.imports}`);
|
|
360
|
+
console.log(` Calls: ${result.code_graph.calls}`);
|
|
361
|
+
console.log(` Routes: ${result.code_graph.routes}`);
|
|
362
|
+
console.log(` Tests: ${result.code_graph.tests}`);
|
|
363
|
+
console.log(` Indexer coverage: ${result.code_graph.indexer_coverage_percent}%`);
|
|
364
|
+
console.log(` Languages: ${Object.entries(result.code_graph.languages).map(([name, count]) => `${name}=${count}`).join(", ") || "(none)"}`);
|
|
365
|
+
console.log(` Parsers: ${Object.entries(result.code_graph.parsers).map(([name, count]) => `${name}=${count}`).join(", ") || "(none)"}`);
|
|
366
|
+
console.log("\nMemory graph:");
|
|
367
|
+
console.log(` Approved packets: ${result.memory_graph.approved_packets}`);
|
|
368
|
+
console.log(` Pending packets: ${result.memory_graph.pending_packets}`);
|
|
369
|
+
console.log(` Episodes: ${result.memory_graph.episodes}`);
|
|
370
|
+
console.log(` Entities: ${result.memory_graph.entities}`);
|
|
371
|
+
console.log(` Edges: ${result.memory_graph.edges}`);
|
|
372
|
+
console.log(` Evidence coverage: ${result.memory_graph.evidence_coverage_percent}%`);
|
|
373
|
+
console.log(` Average quality: ${result.memory_graph.average_quality_score}/100`);
|
|
374
|
+
console.log(` Duplicate candidates: ${result.memory_graph.duplicate_candidate_pairs}`);
|
|
375
|
+
console.log("\nToken savings:");
|
|
376
|
+
console.log(` Indexed source tokens: ${result.savings.estimated_indexed_source_tokens}`);
|
|
377
|
+
console.log(` Memory tokens: ${result.savings.estimated_memory_tokens}`);
|
|
378
|
+
console.log(` Recall context tokens: ${result.savings.estimated_recall_context_tokens}`);
|
|
379
|
+
console.log(` Estimated tokens saved per recall: ${result.savings.estimated_tokens_saved_per_recall}`);
|
|
380
|
+
if (result.quality) {
|
|
381
|
+
console.log("\nQuality:");
|
|
382
|
+
console.log(` Useful memory ratio: ${result.quality.useful_memory_ratio_percent}%`);
|
|
383
|
+
console.log(` Duplicate burden: ${result.quality.duplicate_burden}%`);
|
|
384
|
+
console.log(` Evidence coverage: ${result.quality.evidence_coverage_percent}%`);
|
|
385
|
+
console.log(` Review queue size: ${result.quality.totals.pending}`);
|
|
386
|
+
}
|
|
387
|
+
if (result.pain) {
|
|
388
|
+
console.log("\nPain avoided:");
|
|
389
|
+
console.log(` Recall hit rate: ${result.pain.recall_hit_rate_percent}%`);
|
|
390
|
+
console.log(` Estimated rediscovery avoided: ${result.pain.estimated_rediscovery_avoided}`);
|
|
391
|
+
console.log(` Estimated tokens saved: ${result.pain.estimated_tokens_saved}`);
|
|
392
|
+
console.log(` Time to first use: ${result.pain.time_to_first_use_seconds}s`);
|
|
393
|
+
}
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (command === "quality") {
|
|
397
|
+
const result = (0, kernel_js_1.qualityReport)(projectArg(args));
|
|
398
|
+
if (args.includes("--json")) {
|
|
399
|
+
console.log(JSON.stringify(result, null, 2));
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
console.log(`Kage Quality: ${result.project_dir}`);
|
|
403
|
+
console.log(`Useful memory ratio: ${result.useful_memory_ratio_percent}%`);
|
|
404
|
+
console.log(`Duplicate burden: ${result.duplicate_burden}%`);
|
|
405
|
+
console.log(`Evidence coverage: ${result.evidence_coverage_percent}%`);
|
|
406
|
+
console.log(`Path grounding coverage: ${result.path_grounding_coverage_percent}%`);
|
|
407
|
+
console.log(`Review queue size: ${result.totals.pending}`);
|
|
408
|
+
console.log(`Approved vs pending ratio: ${result.approved_to_pending_ratio}`);
|
|
409
|
+
console.log(`Type coverage: ${Object.entries(result.memory_type_coverage).map(([type, count]) => `${type}=${count}`).join(", ") || "(none)"}`);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (command === "benchmark") {
|
|
413
|
+
const result = (0, kernel_js_1.benchmarkProject)(projectArg(args));
|
|
414
|
+
if (args.includes("--json")) {
|
|
415
|
+
console.log(JSON.stringify(result, null, 2));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
console.log(`Kage Benchmark: ${result.project_dir}`);
|
|
419
|
+
for (const [name, value] of Object.entries(result.pain_metrics))
|
|
420
|
+
console.log(`${name}: ${value}`);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (command === "learn") {
|
|
424
|
+
const learning = takeArg(args, "--learning");
|
|
425
|
+
if (!learning)
|
|
426
|
+
usage();
|
|
427
|
+
const result = (0, kernel_js_1.learn)({
|
|
428
|
+
projectDir: projectArg(args),
|
|
429
|
+
learning,
|
|
430
|
+
title: takeArg(args, "--title"),
|
|
431
|
+
type: takeArg(args, "--type"),
|
|
432
|
+
evidence: takeArg(args, "--evidence"),
|
|
433
|
+
verifiedBy: takeArg(args, "--verified-by"),
|
|
434
|
+
tags: listArg(takeArg(args, "--tags")),
|
|
435
|
+
paths: listArg(takeArg(args, "--paths")),
|
|
436
|
+
stack: listArg(takeArg(args, "--stack")),
|
|
437
|
+
});
|
|
438
|
+
if (!result.ok) {
|
|
439
|
+
console.error(`Learning capture blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
440
|
+
process.exit(2);
|
|
441
|
+
}
|
|
442
|
+
console.log(`Captured session learning: ${result.path}`);
|
|
443
|
+
console.log(`Review with: kage review --project ${projectArg(args)}`);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (command === "propose") {
|
|
447
|
+
if (!args.includes("--from-diff"))
|
|
448
|
+
usage();
|
|
449
|
+
const result = (0, kernel_js_1.proposeFromDiff)(projectArg(args));
|
|
450
|
+
if (!result.ok) {
|
|
451
|
+
console.error(`Proposal blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
452
|
+
process.exit(2);
|
|
453
|
+
}
|
|
454
|
+
console.log(`Wrote branch review summary: ${result.path}`);
|
|
455
|
+
if (result.packetPath)
|
|
456
|
+
console.log(`Captured pending change memory: ${result.packetPath}`);
|
|
457
|
+
console.log(`Changed files: ${result.changedFiles.join(", ")}`);
|
|
458
|
+
console.log(`Review memory: kage review --project ${projectArg(args)}`);
|
|
459
|
+
console.log(`Review artifact: kage review-artifact --project ${projectArg(args)}`);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
if (command === "review-artifact") {
|
|
463
|
+
const result = (0, kernel_js_1.createReviewArtifact)(projectArg(args));
|
|
464
|
+
console.log(`Wrote review artifact: ${result.path}`);
|
|
465
|
+
console.log(`Pending packets: ${result.pending}`);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (command === "promote") {
|
|
469
|
+
const id = takeArg(args, "--public");
|
|
470
|
+
if (!id)
|
|
471
|
+
usage();
|
|
472
|
+
const result = (0, kernel_js_1.createPublicCandidate)(projectArg(args), id);
|
|
473
|
+
if (!result.ok) {
|
|
474
|
+
console.error(`Promotion blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
475
|
+
process.exit(2);
|
|
476
|
+
}
|
|
477
|
+
console.log(`Created public review candidate: ${result.path}`);
|
|
478
|
+
console.log("This file is local only until a human publishes it.");
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
if (command === "export-public") {
|
|
482
|
+
const result = (0, kernel_js_1.exportPublicBundle)(projectArg(args));
|
|
483
|
+
if (!result.ok) {
|
|
484
|
+
console.error(`Public bundle blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
485
|
+
process.exit(2);
|
|
486
|
+
}
|
|
487
|
+
console.log(`Exported public bundle: ${result.path}`);
|
|
488
|
+
console.log(`Packets: ${result.packetCount}`);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (command === "registry") {
|
|
492
|
+
const result = (0, kernel_js_1.registryRecommendations)(projectArg(args));
|
|
493
|
+
if (args.includes("--json")) {
|
|
494
|
+
console.log(JSON.stringify(result, null, 2));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (result.length === 0) {
|
|
498
|
+
console.log("No registry recommendations found for this repo.");
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
for (const item of result) {
|
|
502
|
+
console.log(`${item.id} [${item.kind}] ${item.title}`);
|
|
503
|
+
console.log(` ${item.summary}`);
|
|
504
|
+
console.log(` matched: ${item.matched.join(", ") || "(repo metadata)"}`);
|
|
505
|
+
console.log(` trust: ${item.trust}; install: ${item.install}`);
|
|
506
|
+
}
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
if (command === "marketplace") {
|
|
510
|
+
const result = (0, kernel_js_1.buildMarketplace)(projectArg(args));
|
|
511
|
+
if (args.includes("--json")) {
|
|
512
|
+
console.log(JSON.stringify(result, null, 2));
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
console.log(`Marketplace manifest: ${result.path}`);
|
|
516
|
+
console.log(`Packs: ${result.packs.length}`);
|
|
517
|
+
for (const pack of result.packs) {
|
|
518
|
+
console.log(`- ${pack.id} [${pack.kind}] ${pack.title} (${pack.install})`);
|
|
519
|
+
}
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
if (command === "org") {
|
|
523
|
+
const action = args[1];
|
|
524
|
+
const org = takeArg(args, "--org") ?? "local";
|
|
525
|
+
const projectDir = projectArg(args);
|
|
526
|
+
if (action === "status") {
|
|
527
|
+
const result = (0, kernel_js_1.orgStatus)(projectDir, org);
|
|
528
|
+
if (args.includes("--json"))
|
|
529
|
+
console.log(JSON.stringify(result, null, 2));
|
|
530
|
+
else {
|
|
531
|
+
console.log(`Org memory: ${result.org}`);
|
|
532
|
+
console.log(`Path: ${result.path}`);
|
|
533
|
+
console.log(`Inbox: ${result.inbox}`);
|
|
534
|
+
console.log(`Approved: ${result.approved}`);
|
|
535
|
+
console.log(`Rejected: ${result.rejected}`);
|
|
536
|
+
console.log(`Audit events: ${result.audit_events}`);
|
|
537
|
+
if (result.registry_path)
|
|
538
|
+
console.log(`Registry: ${result.registry_path}`);
|
|
539
|
+
}
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
if (action === "upload") {
|
|
543
|
+
const id = takeArg(args, "--packet");
|
|
544
|
+
if (!id)
|
|
545
|
+
usage();
|
|
546
|
+
const result = (0, kernel_js_1.orgUploadPacket)(projectDir, org, id);
|
|
547
|
+
if (!result.ok) {
|
|
548
|
+
console.error(`Org upload blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
549
|
+
process.exit(2);
|
|
550
|
+
}
|
|
551
|
+
console.log(`Created org review candidate: ${result.path}`);
|
|
552
|
+
console.log("Approve explicitly with: kage org review --approve");
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (action === "review") {
|
|
556
|
+
const id = takeArg(args, "--packet");
|
|
557
|
+
if (!id || (!args.includes("--approve") && !args.includes("--reject")))
|
|
558
|
+
usage();
|
|
559
|
+
const result = (0, kernel_js_1.orgReviewPacket)(projectDir, org, id, args.includes("--approve") ? "approve" : "reject");
|
|
560
|
+
if (!result.ok) {
|
|
561
|
+
console.error(`Org review failed:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
562
|
+
process.exit(2);
|
|
563
|
+
}
|
|
564
|
+
console.log(`Org review wrote: ${result.path}`);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (action === "recall") {
|
|
568
|
+
const query = firstPositional(args.slice(1));
|
|
569
|
+
if (!query)
|
|
570
|
+
usage();
|
|
571
|
+
const result = (0, kernel_js_1.orgRecall)(projectDir, org, query);
|
|
572
|
+
if (args.includes("--json"))
|
|
573
|
+
console.log(JSON.stringify(result, null, 2));
|
|
574
|
+
else
|
|
575
|
+
console.log(result.context_block);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
if (action === "export") {
|
|
579
|
+
const result = (0, kernel_js_1.exportOrgRegistry)(projectDir, org);
|
|
580
|
+
if (args.includes("--json"))
|
|
581
|
+
console.log(JSON.stringify(result, null, 2));
|
|
582
|
+
else
|
|
583
|
+
console.log(`Exported org registry: ${result.registry_path}`);
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
usage();
|
|
587
|
+
}
|
|
588
|
+
if (command === "layered-recall") {
|
|
589
|
+
const query = firstPositional(args);
|
|
590
|
+
if (!query)
|
|
591
|
+
usage();
|
|
592
|
+
const result = (0, kernel_js_1.layeredRecall)(projectArg(args), query, {
|
|
593
|
+
org: takeArg(args, "--org"),
|
|
594
|
+
includeGlobal: args.includes("--global"),
|
|
595
|
+
});
|
|
596
|
+
if (args.includes("--json"))
|
|
597
|
+
console.log(JSON.stringify(result, null, 2));
|
|
598
|
+
else
|
|
599
|
+
console.log(result.context_block);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
if (command === "global") {
|
|
603
|
+
const action = args[1];
|
|
604
|
+
if (action !== "build")
|
|
605
|
+
usage();
|
|
606
|
+
const result = (0, kernel_js_1.buildGlobalCdnBundle)(projectArg(args), takeArg(args, "--org") ?? "local");
|
|
607
|
+
if (args.includes("--json")) {
|
|
608
|
+
console.log(JSON.stringify(result, null, 2));
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (!result.ok) {
|
|
612
|
+
console.error(`Global bundle failed:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
613
|
+
process.exit(2);
|
|
614
|
+
}
|
|
615
|
+
console.log(`Global registry: ${result.manifest_path}`);
|
|
616
|
+
console.log(`Latest alias: ${result.alias_path}`);
|
|
617
|
+
console.log(`Marketplace: ${result.marketplace_path}`);
|
|
618
|
+
console.log(`Public packets: ${result.packet_count}`);
|
|
619
|
+
console.log(`Marketplace packs: ${result.marketplace_packs}`);
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (command === "recall") {
|
|
623
|
+
const query = firstPositional(args);
|
|
624
|
+
if (!query)
|
|
625
|
+
usage();
|
|
626
|
+
const result = (0, kernel_js_1.recall)(projectArg(args), query, 5, args.includes("--explain"));
|
|
627
|
+
if (args.includes("--json"))
|
|
628
|
+
console.log(JSON.stringify(result, null, 2));
|
|
629
|
+
else
|
|
630
|
+
console.log(result.context_block);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (command === "observe") {
|
|
634
|
+
const event = takeArg(args, "--event");
|
|
635
|
+
if (!event)
|
|
636
|
+
usage();
|
|
637
|
+
const result = (0, kernel_js_1.observe)(projectArg(args), JSON.parse(event));
|
|
638
|
+
if (args.includes("--json"))
|
|
639
|
+
console.log(JSON.stringify(result, null, 2));
|
|
640
|
+
else if (result.ok && result.duplicate)
|
|
641
|
+
console.log(`Observation already stored: ${result.path}`);
|
|
642
|
+
else if (result.ok)
|
|
643
|
+
console.log(`Stored observation: ${result.path}`);
|
|
644
|
+
else {
|
|
645
|
+
console.error(`Observation blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
646
|
+
process.exit(2);
|
|
647
|
+
}
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (command === "distill") {
|
|
651
|
+
const sessionId = takeArg(args, "--session");
|
|
652
|
+
if (!sessionId)
|
|
653
|
+
usage();
|
|
654
|
+
const result = (0, kernel_js_1.distillSession)(projectArg(args), sessionId);
|
|
655
|
+
if (args.includes("--json"))
|
|
656
|
+
console.log(JSON.stringify(result, null, 2));
|
|
657
|
+
else {
|
|
658
|
+
console.log(`Distilled session: ${sessionId}`);
|
|
659
|
+
console.log(`Observations: ${result.observations}`);
|
|
660
|
+
console.log(`Candidates: ${result.candidates.filter((candidate) => candidate.ok).length}`);
|
|
661
|
+
if (result.errors.length)
|
|
662
|
+
console.log(`Errors:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
663
|
+
}
|
|
664
|
+
if (!result.ok)
|
|
665
|
+
process.exit(2);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (command === "feedback") {
|
|
669
|
+
const id = takeArg(args, "--packet");
|
|
670
|
+
const kind = takeArg(args, "--kind");
|
|
671
|
+
if (!id || !kind)
|
|
672
|
+
usage();
|
|
673
|
+
const result = (0, kernel_js_1.recordFeedback)(projectArg(args), id, kind);
|
|
674
|
+
if (!result.ok) {
|
|
675
|
+
console.error(`Feedback failed:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
676
|
+
process.exit(2);
|
|
677
|
+
}
|
|
678
|
+
console.log(`Recorded ${kind} feedback for ${id}`);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
if (command === "capture") {
|
|
682
|
+
const title = takeArg(args, "--title");
|
|
683
|
+
const body = takeArg(args, "--body");
|
|
684
|
+
if (!title || !body)
|
|
685
|
+
usage();
|
|
686
|
+
const type = takeArg(args, "--type");
|
|
687
|
+
const input = {
|
|
688
|
+
projectDir: projectArg(args),
|
|
689
|
+
title,
|
|
690
|
+
body,
|
|
691
|
+
type,
|
|
692
|
+
summary: takeArg(args, "--summary"),
|
|
693
|
+
tags: listArg(takeArg(args, "--tags")),
|
|
694
|
+
paths: listArg(takeArg(args, "--paths")),
|
|
695
|
+
stack: listArg(takeArg(args, "--stack")),
|
|
696
|
+
};
|
|
697
|
+
const result = (0, kernel_js_1.capture)(input);
|
|
698
|
+
if (!result.ok) {
|
|
699
|
+
console.error(`Capture blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
700
|
+
process.exit(2);
|
|
701
|
+
}
|
|
702
|
+
console.log(`Captured pending packet: ${result.path}`);
|
|
703
|
+
console.log(`Review with: kage review --project ${input.projectDir}`);
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (command === "review") {
|
|
707
|
+
await review(projectArg(args));
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
if (command === "validate") {
|
|
711
|
+
const result = (0, kernel_js_1.validateProject)(projectArg(args));
|
|
712
|
+
if (result.errors.length)
|
|
713
|
+
console.log(`Errors:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
714
|
+
if (result.warnings.length)
|
|
715
|
+
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
716
|
+
console.log(result.ok ? "Validation passed." : "Validation failed.");
|
|
717
|
+
if (!result.ok)
|
|
718
|
+
process.exit(2);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
usage();
|
|
722
|
+
}
|
|
723
|
+
main().catch((error) => {
|
|
724
|
+
console.error(error);
|
|
725
|
+
process.exit(1);
|
|
726
|
+
});
|