@kage-core/kage-graph-mcp 1.1.35 → 1.1.37
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 +157 -135
- package/dist/cli.js +429 -3
- package/dist/daemon.js +314 -7
- package/dist/index.js +329 -3
- package/dist/kernel.js +3255 -64
- package/package.json +1 -1
- package/viewer/app.js +2421 -316
- package/viewer/data.html +296 -0
- package/viewer/graph.html +296 -0
- package/viewer/index.html +170 -165
- package/viewer/intel.html +296 -0
- package/viewer/memory.html +367 -0
- package/viewer/owners.html +296 -0
- package/viewer/review.html +307 -0
- package/viewer/styles.css +1581 -371
package/dist/daemon.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.viewerStaticHeaders = viewerStaticHeaders;
|
|
4
|
+
exports.viewerRedirectLocation = viewerRedirectLocation;
|
|
5
|
+
exports.viewerBenchmarkReport = viewerBenchmarkReport;
|
|
6
|
+
exports.daemonContextReport = daemonContextReport;
|
|
3
7
|
exports.readDaemonStatus = readDaemonStatus;
|
|
4
8
|
exports.daemonDoctor = daemonDoctor;
|
|
5
9
|
exports.stopDaemon = stopDaemon;
|
|
@@ -34,6 +38,107 @@ function contentType(filePath) {
|
|
|
34
38
|
return "text/markdown; charset=utf-8";
|
|
35
39
|
return "application/octet-stream";
|
|
36
40
|
}
|
|
41
|
+
function viewerStaticHeaders(filePath) {
|
|
42
|
+
return {
|
|
43
|
+
"content-type": contentType(filePath),
|
|
44
|
+
"x-content-type-options": "nosniff",
|
|
45
|
+
"referrer-policy": "no-referrer",
|
|
46
|
+
"cross-origin-opener-policy": "same-origin",
|
|
47
|
+
"content-security-policy": [
|
|
48
|
+
"default-src 'self'",
|
|
49
|
+
"script-src 'self'",
|
|
50
|
+
"script-src-attr 'none'",
|
|
51
|
+
"style-src 'self' 'unsafe-inline'",
|
|
52
|
+
"img-src 'self' data:",
|
|
53
|
+
"connect-src 'self'",
|
|
54
|
+
"font-src 'none'",
|
|
55
|
+
"object-src 'none'",
|
|
56
|
+
"base-uri 'none'",
|
|
57
|
+
"frame-ancestors 'none'",
|
|
58
|
+
].join("; "),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function viewerRedirectLocation(pathname, search, fallbackSearch) {
|
|
62
|
+
if (pathname !== "/" && pathname !== "/viewer" && pathname !== "/viewer/")
|
|
63
|
+
return null;
|
|
64
|
+
return `/viewer/index.html${search || fallbackSearch}`;
|
|
65
|
+
}
|
|
66
|
+
function viewerBenchmarkReport(projectDir) {
|
|
67
|
+
const gates = (0, kernel_js_1.benchmarkProject)(projectDir);
|
|
68
|
+
const memoryQuality = (0, kernel_js_1.benchmarkCodingMemoryQuality)();
|
|
69
|
+
const memoryScale = (0, kernel_js_1.benchmarkMemoryScale)({ sizes: [240], topK: 10 });
|
|
70
|
+
const requiredGates = gates.gates.filter((gate) => gate.required);
|
|
71
|
+
const requiredGatePasses = requiredGates.filter((gate) => gate.pass).length;
|
|
72
|
+
const requiredGatePercent = requiredGates.length ? Math.round((requiredGatePasses / requiredGates.length) * 100) : (gates.ok ? 100 : 0);
|
|
73
|
+
const recallAt10 = Number(memoryQuality.summary.recall_at_10_percent ?? memoryQuality.summary.recall_at_k_percent ?? 0);
|
|
74
|
+
const sourceDiversity = memoryQuality.source_diversity;
|
|
75
|
+
const scaleHitRate = Number(memoryScale.summary.largest_hit_rate_percent ?? 0);
|
|
76
|
+
const scaleContextCut = Number(memoryScale.summary.largest_context_reduction_percent ?? 0);
|
|
77
|
+
return {
|
|
78
|
+
...gates,
|
|
79
|
+
summary: memoryQuality.summary,
|
|
80
|
+
memory_quality: {
|
|
81
|
+
dataset: memoryQuality.dataset,
|
|
82
|
+
summary: memoryQuality.summary,
|
|
83
|
+
source_diversity: memoryQuality.source_diversity,
|
|
84
|
+
by_category: memoryQuality.by_category,
|
|
85
|
+
baselines: memoryQuality.baselines,
|
|
86
|
+
caveats: memoryQuality.caveats,
|
|
87
|
+
},
|
|
88
|
+
memory_scale: {
|
|
89
|
+
sizes: memoryScale.sizes,
|
|
90
|
+
summary: memoryScale.summary,
|
|
91
|
+
results: memoryScale.results,
|
|
92
|
+
caveats: memoryScale.caveats,
|
|
93
|
+
},
|
|
94
|
+
proof_ledger: [
|
|
95
|
+
{
|
|
96
|
+
id: "memory-quality",
|
|
97
|
+
label: "Coding-memory retrieval",
|
|
98
|
+
metric: `${recallAt10.toFixed(2)}% R@10, ${memoryQuality.summary.ndcg_at_10.toFixed(4)} NDCG@10`,
|
|
99
|
+
target: ">=95% R@10 and >=0.85 NDCG@10",
|
|
100
|
+
actual: recallAt10,
|
|
101
|
+
unit: "percent",
|
|
102
|
+
pass: recallAt10 >= 95 && memoryQuality.summary.ndcg_at_10 >= 0.85,
|
|
103
|
+
command: "kage benchmark --memory-quality --json",
|
|
104
|
+
next_action: "Use this as the fast coding-memory retrieval proof before publishing benchmark claims.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "source-diversity",
|
|
108
|
+
label: "Source diversity",
|
|
109
|
+
metric: `${sourceDiversity.unique_sources} sources in top ${sourceDiversity.top_k}; max ${sourceDiversity.max_results_from_one_source} from one source`,
|
|
110
|
+
target: ">=2 sources and <=3 results from one observed session",
|
|
111
|
+
actual: sourceDiversity.unique_sources,
|
|
112
|
+
unit: "score",
|
|
113
|
+
pass: sourceDiversity.pass,
|
|
114
|
+
command: "kage benchmark --memory-quality --json",
|
|
115
|
+
next_action: sourceDiversity.pass ? "Use this to prove noisy sessions cannot crowd out independent repo memory." : "Inspect recall source diversity before publishing memory-quality claims.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "memory-scale",
|
|
119
|
+
label: "Memory scale sanity",
|
|
120
|
+
metric: `${memoryScale.summary.largest_packets} packets, ${scaleHitRate.toFixed(2)}% hit rate, ${scaleContextCut.toFixed(2)}% context cut`,
|
|
121
|
+
target: ">=95% hit rate and >=80% context reduction",
|
|
122
|
+
actual: scaleHitRate,
|
|
123
|
+
unit: "percent",
|
|
124
|
+
pass: scaleHitRate >= 95 && scaleContextCut >= 80,
|
|
125
|
+
command: "kage benchmark --scale --sizes 240 --json",
|
|
126
|
+
next_action: "Run kage benchmark --scale --sizes 240,1000,5000 --json for a larger release proof.",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "local-gates",
|
|
130
|
+
label: "Repo trust gates",
|
|
131
|
+
metric: `${requiredGatePasses}/${requiredGates.length || gates.gates.length} required gates passing`,
|
|
132
|
+
target: "100% required gates passing",
|
|
133
|
+
actual: requiredGatePercent,
|
|
134
|
+
unit: "percent",
|
|
135
|
+
pass: gates.ok,
|
|
136
|
+
command: "kage benchmark --project . --json",
|
|
137
|
+
next_action: gates.ok ? "Keep this green before handoff, README updates, or release." : "Fix failing repo benchmark gates before sharing this memory state.",
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
};
|
|
141
|
+
}
|
|
37
142
|
function statusPath(projectDir) {
|
|
38
143
|
return (0, node_path_1.join)(daemonDir(projectDir), "status.json");
|
|
39
144
|
}
|
|
@@ -64,6 +169,68 @@ function readBody(req) {
|
|
|
64
169
|
req.on("error", reject);
|
|
65
170
|
});
|
|
66
171
|
}
|
|
172
|
+
function stringArray(value) {
|
|
173
|
+
if (Array.isArray(value))
|
|
174
|
+
return value.map(String).filter(Boolean);
|
|
175
|
+
if (typeof value === "string")
|
|
176
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
function filePathHints(query) {
|
|
180
|
+
const matches = query.match(/[A-Za-z0-9_./@-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|kts|rb|php|cs|c|h|cc|cpp|hpp|swift|json|md)\b/g) ?? [];
|
|
181
|
+
return [...new Set(matches.map((match) => match.replace(/^\.\//, "")).filter((match) => !/^https?:\/\//.test(match)))];
|
|
182
|
+
}
|
|
183
|
+
function wantsDependencyPath(query) {
|
|
184
|
+
return /\b(connect|connected|dependency|depend|depends|path|impact|flow|trace)\b/i.test(query);
|
|
185
|
+
}
|
|
186
|
+
function riskContextBlock(result) {
|
|
187
|
+
const targets = Object.values(result.targets);
|
|
188
|
+
if (!targets.length)
|
|
189
|
+
return "";
|
|
190
|
+
const lines = targets.slice(0, 5).map((item) => {
|
|
191
|
+
const coChange = item.git.co_change_partners.length
|
|
192
|
+
? ` Co-change: ${item.git.co_change_partners.slice(0, 3).map((partner) => `${partner.file_path} (${partner.count})`).join(", ")}.`
|
|
193
|
+
: "";
|
|
194
|
+
return `- ${item.risk_summary}${coChange}`;
|
|
195
|
+
});
|
|
196
|
+
return `\n## Risk Signals\n${lines.join("\n")}`;
|
|
197
|
+
}
|
|
198
|
+
function daemonContextReport(projectDir, body) {
|
|
199
|
+
const query = String(body.query ?? "");
|
|
200
|
+
const limit = Number(body.limit ?? 5);
|
|
201
|
+
const validation = (0, kernel_js_1.validateProject)(projectDir);
|
|
202
|
+
const recallResult = (0, kernel_js_1.recall)(projectDir, query, limit, Boolean(body.explain));
|
|
203
|
+
const graphResult = (0, kernel_js_1.queryGraph)(projectDir, query, 5);
|
|
204
|
+
const explicitTargets = [...stringArray(body.targets), ...filePathHints(query)];
|
|
205
|
+
const changedFiles = stringArray(body.changed_files);
|
|
206
|
+
const riskResult = explicitTargets.length || changedFiles.length ? (0, kernel_js_1.kageRisk)(projectDir, explicitTargets, changedFiles) : null;
|
|
207
|
+
const pathHints = filePathHints(query);
|
|
208
|
+
const dependencyResult = wantsDependencyPath(query) && pathHints.length >= 2
|
|
209
|
+
? (0, kernel_js_1.kageDependencyPath)(projectDir, pathHints[0], pathHints[1])
|
|
210
|
+
: null;
|
|
211
|
+
const reconciliation = (0, kernel_js_1.kageMemoryReconciliation)(projectDir, {
|
|
212
|
+
sessionId: typeof body.session_id === "string" ? body.session_id : undefined,
|
|
213
|
+
limit: 5,
|
|
214
|
+
});
|
|
215
|
+
const validationText = validation.ok ? "Memory healthy." : `Warnings: ${validation.warnings.join("; ")}`;
|
|
216
|
+
const contextBlock = [
|
|
217
|
+
recallResult.context_block,
|
|
218
|
+
graphResult.context_block ? `\n## Graph Facts\n${graphResult.context_block}` : "",
|
|
219
|
+
riskResult ? riskContextBlock(riskResult) : "",
|
|
220
|
+
dependencyResult ? `\n## Dependency Path\n${dependencyResult.summary}${dependencyResult.path.length ? `\nPath: ${dependencyResult.path.join(" -> ")}` : ""}` : "",
|
|
221
|
+
reconciliation.unresolved_count ? `\n## Memory Reconciliation\n${reconciliation.agent_instruction}` : "",
|
|
222
|
+
`\n_${validationText}_`,
|
|
223
|
+
].filter(Boolean).join("");
|
|
224
|
+
return {
|
|
225
|
+
context_block: contextBlock,
|
|
226
|
+
recall: recallResult,
|
|
227
|
+
graph: graphResult,
|
|
228
|
+
risk: riskResult,
|
|
229
|
+
dependency_path: dependencyResult,
|
|
230
|
+
validation,
|
|
231
|
+
memory_reconciliation: reconciliation,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
67
234
|
function readDaemonStatus(projectDir) {
|
|
68
235
|
const path = statusPath(projectDir);
|
|
69
236
|
if (!(0, node_fs_1.existsSync)(path))
|
|
@@ -93,9 +260,20 @@ function daemonDoctor(projectDir) {
|
|
|
93
260
|
status,
|
|
94
261
|
endpoints: [
|
|
95
262
|
`GET http://${DEFAULT_HOST}:${restPort}/health`,
|
|
263
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/context`,
|
|
96
264
|
`POST http://${DEFAULT_HOST}:${restPort}/kage/recall`,
|
|
265
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/capture`,
|
|
266
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/learn`,
|
|
267
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/feedback`,
|
|
97
268
|
`POST http://${DEFAULT_HOST}:${restPort}/kage/observe`,
|
|
98
269
|
`POST http://${DEFAULT_HOST}:${restPort}/kage/distill`,
|
|
270
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/replay`,
|
|
271
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/setup-doctor`,
|
|
272
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/profile`,
|
|
273
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/capabilities`,
|
|
274
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/context-slots`,
|
|
275
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/context-slots`,
|
|
276
|
+
`DELETE http://${DEFAULT_HOST}:${restPort}/kage/context-slots/:label`,
|
|
99
277
|
`GET http://${DEFAULT_HOST}:${restPort}/kage/metrics`,
|
|
100
278
|
`GET http://${DEFAULT_HOST}:${restPort}/kage/quality`,
|
|
101
279
|
`GET http://${DEFAULT_HOST}:${restPort}/kage/inbox`,
|
|
@@ -187,12 +365,60 @@ async function startDaemon(projectDir, options = {}) {
|
|
|
187
365
|
json(res, 200, (0, kernel_js_1.qualityReport)(projectDir));
|
|
188
366
|
return;
|
|
189
367
|
}
|
|
368
|
+
if (req.method === "GET" && url.pathname === "/kage/profile") {
|
|
369
|
+
json(res, 200, (0, kernel_js_1.kageProjectProfile)(projectDir));
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (req.method === "GET" && url.pathname === "/kage/capabilities") {
|
|
373
|
+
json(res, 200, (0, kernel_js_1.kageCapabilityAudit)(projectDir));
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (req.method === "GET" && url.pathname === "/kage/replay") {
|
|
377
|
+
json(res, 200, (0, kernel_js_1.kageSessionReplay)(projectDir, {
|
|
378
|
+
sessionId: url.searchParams.get("session") ?? undefined,
|
|
379
|
+
limit: Number(url.searchParams.get("limit") ?? 200),
|
|
380
|
+
}));
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (req.method === "GET" && url.pathname === "/kage/context-slots") {
|
|
384
|
+
json(res, 200, (0, kernel_js_1.kageContextSlots)(projectDir));
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (req.method === "GET" && url.pathname === "/kage/lifecycle") {
|
|
388
|
+
json(res, 200, (0, kernel_js_1.kageMemoryLifecycle)(projectDir));
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (req.method === "GET" && url.pathname === "/kage/memory-audit") {
|
|
392
|
+
json(res, 200, (0, kernel_js_1.kageMemoryAudit)(projectDir, Number(url.searchParams.get("limit") ?? 100)));
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (req.method === "GET" && url.pathname === "/kage/handoff") {
|
|
396
|
+
json(res, 200, (0, kernel_js_1.kageMemoryHandoff)(projectDir));
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (req.method === "GET" && url.pathname === "/kage/timeline") {
|
|
400
|
+
json(res, 200, (0, kernel_js_1.kageMemoryTimeline)(projectDir, Number(url.searchParams.get("days") ?? 14)));
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (req.method === "GET" && url.pathname === "/kage/lineage") {
|
|
404
|
+
json(res, 200, (0, kernel_js_1.kageMemoryLineage)(projectDir));
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
190
407
|
if (req.method === "GET" && url.pathname === "/kage/inbox") {
|
|
191
408
|
json(res, 200, (0, kernel_js_1.memoryInbox)(projectDir));
|
|
192
409
|
return;
|
|
193
410
|
}
|
|
194
411
|
if (req.method === "GET" && url.pathname === "/kage/benchmark") {
|
|
195
|
-
json(res, 200, (0, kernel_js_1.benchmarkProject)(projectDir));
|
|
412
|
+
json(res, 200, url.searchParams.get("mode") === "memory_quality" ? (0, kernel_js_1.benchmarkCodingMemoryQuality)() : (0, kernel_js_1.benchmarkProject)(projectDir));
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (req.method === "GET" && url.pathname === "/kage/setup-doctor") {
|
|
416
|
+
json(res, 200, (0, kernel_js_1.setupDoctor)(projectDir));
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (req.method === "POST" && url.pathname === "/kage/context") {
|
|
420
|
+
const body = await readBody(req);
|
|
421
|
+
json(res, 200, daemonContextReport(projectDir, body));
|
|
196
422
|
return;
|
|
197
423
|
}
|
|
198
424
|
if (req.method === "POST" && url.pathname === "/kage/recall") {
|
|
@@ -200,6 +426,63 @@ async function startDaemon(projectDir, options = {}) {
|
|
|
200
426
|
json(res, 200, (0, kernel_js_1.recall)(projectDir, String(body.query ?? ""), Number(body.limit ?? 5), Boolean(body.explain)));
|
|
201
427
|
return;
|
|
202
428
|
}
|
|
429
|
+
if (req.method === "POST" && url.pathname === "/kage/capture") {
|
|
430
|
+
const body = await readBody(req);
|
|
431
|
+
const result = (0, kernel_js_1.capture)({
|
|
432
|
+
projectDir,
|
|
433
|
+
title: String(body.title ?? ""),
|
|
434
|
+
summary: body.summary == null ? undefined : String(body.summary),
|
|
435
|
+
body: String(body.body ?? body.learning ?? ""),
|
|
436
|
+
type: body.type == null ? undefined : String(body.type),
|
|
437
|
+
tags: stringArray(body.tags),
|
|
438
|
+
paths: stringArray(body.paths),
|
|
439
|
+
stack: stringArray(body.stack),
|
|
440
|
+
});
|
|
441
|
+
json(res, result.ok ? 200 : 400, result);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (req.method === "POST" && url.pathname === "/kage/learn") {
|
|
445
|
+
const body = await readBody(req);
|
|
446
|
+
const result = (0, kernel_js_1.learn)({
|
|
447
|
+
projectDir,
|
|
448
|
+
learning: String(body.learning ?? body.body ?? ""),
|
|
449
|
+
title: body.title == null ? undefined : String(body.title),
|
|
450
|
+
type: body.type == null ? undefined : String(body.type),
|
|
451
|
+
evidence: body.evidence == null ? undefined : String(body.evidence),
|
|
452
|
+
verifiedBy: body.verified_by == null ? body.verifiedBy == null ? undefined : String(body.verifiedBy) : String(body.verified_by),
|
|
453
|
+
tags: stringArray(body.tags),
|
|
454
|
+
paths: stringArray(body.paths),
|
|
455
|
+
stack: stringArray(body.stack),
|
|
456
|
+
});
|
|
457
|
+
json(res, result.ok ? 200 : 400, result);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
if (req.method === "POST" && url.pathname === "/kage/feedback") {
|
|
461
|
+
const body = await readBody(req);
|
|
462
|
+
const result = (0, kernel_js_1.recordFeedback)(projectDir, String(body.packet_id ?? body.packet ?? ""), String(body.kind ?? ""));
|
|
463
|
+
json(res, result.ok ? 200 : 400, result);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (req.method === "POST" && url.pathname === "/kage/context-slots") {
|
|
467
|
+
const body = await readBody(req);
|
|
468
|
+
const result = (0, kernel_js_1.setContextSlot)(projectDir, {
|
|
469
|
+
label: String(body.label ?? ""),
|
|
470
|
+
content: String(body.content ?? ""),
|
|
471
|
+
description: body.description == null ? undefined : String(body.description),
|
|
472
|
+
pinned: body.pinned == null ? undefined : Boolean(body.pinned),
|
|
473
|
+
size_limit: body.size_limit == null ? undefined : Number(body.size_limit),
|
|
474
|
+
paths: stringArray(body.paths),
|
|
475
|
+
tags: stringArray(body.tags),
|
|
476
|
+
});
|
|
477
|
+
json(res, result.ok ? 200 : 400, result);
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
if (req.method === "DELETE" && url.pathname.startsWith("/kage/context-slots/")) {
|
|
481
|
+
const label = decodeURIComponent(url.pathname.slice("/kage/context-slots/".length));
|
|
482
|
+
const result = (0, kernel_js_1.deleteContextSlot)(projectDir, label);
|
|
483
|
+
json(res, result.ok ? 200 : 404, result);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
203
486
|
if (req.method === "POST" && url.pathname === "/kage/observe") {
|
|
204
487
|
const body = await readBody(req);
|
|
205
488
|
json(res, 200, (0, kernel_js_1.observe)(projectDir, body));
|
|
@@ -244,11 +527,23 @@ async function startViewer(projectDir, options = {}) {
|
|
|
244
527
|
const qualityPath = (0, node_path_1.join)(reportsDir, "quality.json");
|
|
245
528
|
const benchmarkPath = (0, node_path_1.join)(reportsDir, "benchmark.json");
|
|
246
529
|
const contributorsPath = (0, node_path_1.join)(reportsDir, "contributors.json");
|
|
530
|
+
const profilePath = (0, node_path_1.join)(reportsDir, "profile.json");
|
|
531
|
+
const capabilitiesPath = (0, node_path_1.join)(reportsDir, "capabilities.json");
|
|
532
|
+
const slotsPath = (0, node_path_1.join)(reportsDir, "context-slots.json");
|
|
247
533
|
const decisionsPath = (0, node_path_1.join)(reportsDir, "decisions.json");
|
|
248
534
|
const riskPath = (0, node_path_1.join)(reportsDir, "risk.json");
|
|
249
535
|
const moduleHealthPath = (0, node_path_1.join)(reportsDir, "module-health.json");
|
|
250
536
|
const graphInsightsPath = (0, node_path_1.join)(reportsDir, "graph-insights.json");
|
|
251
537
|
const workspacePath = (0, node_path_1.join)(reportsDir, "workspace.json");
|
|
538
|
+
const sessionsPath = (0, node_path_1.join)(reportsDir, "sessions.json");
|
|
539
|
+
const replayPath = (0, node_path_1.join)(reportsDir, "replay.json");
|
|
540
|
+
const memoryAccessPath = (0, node_path_1.join)(reportsDir, "memory-access.json");
|
|
541
|
+
const memoryAuditPath = (0, node_path_1.join)(reportsDir, "memory-audit.json");
|
|
542
|
+
const handoffPath = (0, node_path_1.join)(reportsDir, "handoff.json");
|
|
543
|
+
const lifecyclePath = (0, node_path_1.join)(reportsDir, "lifecycle.json");
|
|
544
|
+
const timelinePath = (0, node_path_1.join)(reportsDir, "timeline.json");
|
|
545
|
+
const lineagePath = (0, node_path_1.join)(reportsDir, "lineage.json");
|
|
546
|
+
const setupPath = (0, node_path_1.join)(reportsDir, "setup.json");
|
|
252
547
|
// Pre-generate lightweight JSON reports so the viewer can load them directly.
|
|
253
548
|
try {
|
|
254
549
|
(0, node_fs_1.mkdirSync)(reportsDir, { recursive: true });
|
|
@@ -257,24 +552,36 @@ async function startViewer(projectDir, options = {}) {
|
|
|
257
552
|
const inbox = (0, kernel_js_1.memoryInbox)(projectDir);
|
|
258
553
|
(0, node_fs_1.writeFileSync)(inboxPath, JSON.stringify(inbox, null, 2));
|
|
259
554
|
(0, node_fs_1.writeFileSync)(qualityPath, JSON.stringify((0, kernel_js_1.qualityReport)(projectDir), null, 2));
|
|
260
|
-
(0, node_fs_1.writeFileSync)(benchmarkPath, JSON.stringify((
|
|
555
|
+
(0, node_fs_1.writeFileSync)(benchmarkPath, JSON.stringify(viewerBenchmarkReport(projectDir), null, 2));
|
|
261
556
|
(0, node_fs_1.writeFileSync)(contributorsPath, JSON.stringify((0, kernel_js_1.kageContributors)(projectDir), null, 2));
|
|
557
|
+
(0, node_fs_1.writeFileSync)(profilePath, JSON.stringify((0, kernel_js_1.kageProjectProfile)(projectDir), null, 2));
|
|
558
|
+
(0, node_fs_1.writeFileSync)(capabilitiesPath, JSON.stringify((0, kernel_js_1.kageCapabilityAudit)(projectDir), null, 2));
|
|
559
|
+
(0, node_fs_1.writeFileSync)(slotsPath, JSON.stringify((0, kernel_js_1.kageContextSlots)(projectDir), null, 2));
|
|
262
560
|
(0, node_fs_1.writeFileSync)(decisionsPath, JSON.stringify((0, kernel_js_1.kageDecisionIntelligence)(projectDir), null, 2));
|
|
263
561
|
(0, node_fs_1.writeFileSync)(riskPath, JSON.stringify((0, kernel_js_1.kageRisk)(projectDir), null, 2));
|
|
264
562
|
(0, node_fs_1.writeFileSync)(moduleHealthPath, JSON.stringify((0, kernel_js_1.kageModuleHealth)(projectDir), null, 2));
|
|
265
563
|
(0, node_fs_1.writeFileSync)(graphInsightsPath, JSON.stringify((0, kernel_js_1.kageGraphInsights)(projectDir), null, 2));
|
|
266
564
|
(0, node_fs_1.writeFileSync)(workspacePath, JSON.stringify((0, kernel_js_1.kageWorkspace)(projectDir), null, 2));
|
|
565
|
+
(0, node_fs_1.writeFileSync)(sessionsPath, JSON.stringify((0, kernel_js_1.kageSessionCaptureReport)(projectDir), null, 2));
|
|
566
|
+
(0, node_fs_1.writeFileSync)(replayPath, JSON.stringify((0, kernel_js_1.kageSessionReplay)(projectDir), null, 2));
|
|
567
|
+
(0, node_fs_1.writeFileSync)(memoryAccessPath, JSON.stringify((0, kernel_js_1.kageMemoryAccess)(projectDir), null, 2));
|
|
568
|
+
(0, node_fs_1.writeFileSync)(memoryAuditPath, JSON.stringify((0, kernel_js_1.kageMemoryAudit)(projectDir), null, 2));
|
|
569
|
+
(0, node_fs_1.writeFileSync)(handoffPath, JSON.stringify((0, kernel_js_1.kageMemoryHandoff)(projectDir), null, 2));
|
|
570
|
+
(0, node_fs_1.writeFileSync)(lifecyclePath, JSON.stringify((0, kernel_js_1.kageMemoryLifecycle)(projectDir), null, 2));
|
|
571
|
+
(0, node_fs_1.writeFileSync)(timelinePath, JSON.stringify((0, kernel_js_1.kageMemoryTimeline)(projectDir), null, 2));
|
|
572
|
+
(0, node_fs_1.writeFileSync)(lineagePath, JSON.stringify((0, kernel_js_1.kageMemoryLineage)(projectDir), null, 2));
|
|
573
|
+
(0, node_fs_1.writeFileSync)(setupPath, JSON.stringify((0, kernel_js_1.setupDoctor)(projectDir), null, 2));
|
|
267
574
|
}
|
|
268
575
|
catch {
|
|
269
576
|
// non-fatal: viewer will show 404 for reports if generation fails
|
|
270
577
|
}
|
|
271
|
-
const url = `http://${host}:${port}/viewer/index.html?graph=${encodeURIComponent(graphPath)}&code=${encodeURIComponent(codePath)}&metrics=${encodeURIComponent(metricsPath)}&inbox=${encodeURIComponent(inboxPath)}&review=${encodeURIComponent(reviewPath)}&pending=${encodeURIComponent(pendingDir)}&quality=${encodeURIComponent(qualityPath)}&benchmark=${encodeURIComponent(benchmarkPath)}&contributors=${encodeURIComponent(contributorsPath)}&decisions=${encodeURIComponent(decisionsPath)}&risk=${encodeURIComponent(riskPath)}&moduleHealth=${encodeURIComponent(moduleHealthPath)}&graphInsights=${encodeURIComponent(graphInsightsPath)}&workspace=${encodeURIComponent(workspacePath)}&view=code`;
|
|
578
|
+
const url = `http://${host}:${port}/viewer/index.html?graph=${encodeURIComponent(graphPath)}&code=${encodeURIComponent(codePath)}&metrics=${encodeURIComponent(metricsPath)}&inbox=${encodeURIComponent(inboxPath)}&review=${encodeURIComponent(reviewPath)}&pending=${encodeURIComponent(pendingDir)}&quality=${encodeURIComponent(qualityPath)}&benchmark=${encodeURIComponent(benchmarkPath)}&contributors=${encodeURIComponent(contributorsPath)}&profile=${encodeURIComponent(profilePath)}&capabilities=${encodeURIComponent(capabilitiesPath)}&slots=${encodeURIComponent(slotsPath)}&decisions=${encodeURIComponent(decisionsPath)}&risk=${encodeURIComponent(riskPath)}&moduleHealth=${encodeURIComponent(moduleHealthPath)}&graphInsights=${encodeURIComponent(graphInsightsPath)}&workspace=${encodeURIComponent(workspacePath)}&sessions=${encodeURIComponent(sessionsPath)}&replay=${encodeURIComponent(replayPath)}&memoryAccess=${encodeURIComponent(memoryAccessPath)}&memoryAudit=${encodeURIComponent(memoryAuditPath)}&handoff=${encodeURIComponent(handoffPath)}&lifecycle=${encodeURIComponent(lifecyclePath)}&timeline=${encodeURIComponent(timelinePath)}&lineage=${encodeURIComponent(lineagePath)}&setup=${encodeURIComponent(setupPath)}&view=code`;
|
|
272
579
|
const server = (0, node_http_1.createServer)((req, res) => {
|
|
273
580
|
const requestUrl = new URL(req.url ?? "/", `http://${host}:${port}`);
|
|
274
581
|
let filePath = null;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
res.writeHead(302, { location:
|
|
582
|
+
const redirectLocation = viewerRedirectLocation(requestUrl.pathname, requestUrl.search, new URL(url).search);
|
|
583
|
+
if (redirectLocation) {
|
|
584
|
+
res.writeHead(302, { location: redirectLocation });
|
|
278
585
|
res.end();
|
|
279
586
|
return;
|
|
280
587
|
}
|
|
@@ -303,7 +610,7 @@ async function startViewer(projectDir, options = {}) {
|
|
|
303
610
|
json(res, 200, { ok: true, files });
|
|
304
611
|
return;
|
|
305
612
|
}
|
|
306
|
-
res.writeHead(200,
|
|
613
|
+
res.writeHead(200, viewerStaticHeaders(filePath));
|
|
307
614
|
res.end((0, node_fs_1.readFileSync)(filePath));
|
|
308
615
|
});
|
|
309
616
|
await new Promise((resolveListen) => server.listen(port, host, resolveListen));
|