@kage-core/kage-graph-mcp 1.1.8 → 1.1.10
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/package.json +1 -1
- package/viewer/app.js +134 -20
- package/viewer/demo/graph.json +267 -0
- package/viewer/demo/metrics.json +87 -0
package/package.json
CHANGED
package/viewer/app.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
edges: [],
|
|
8
8
|
episodesById: new Map(),
|
|
9
9
|
entityById: new Map(),
|
|
10
|
+
edgeById: new Map(),
|
|
11
|
+
degreeById: new Map(),
|
|
10
12
|
positions: new Map(),
|
|
11
13
|
visibleEntityIds: new Set(),
|
|
12
14
|
visibleEdgeIds: new Set(),
|
|
@@ -27,8 +29,12 @@
|
|
|
27
29
|
panning: null,
|
|
28
30
|
hoverNode: null,
|
|
29
31
|
raf: null,
|
|
32
|
+
drawRaf: null,
|
|
30
33
|
running: false,
|
|
31
|
-
lastSignature: ""
|
|
34
|
+
lastSignature: "",
|
|
35
|
+
tick: 0,
|
|
36
|
+
idleFrames: 0,
|
|
37
|
+
adjacency: new Map()
|
|
32
38
|
},
|
|
33
39
|
pan: null
|
|
34
40
|
};
|
|
@@ -104,7 +110,7 @@
|
|
|
104
110
|
};
|
|
105
111
|
|
|
106
112
|
els.graphFile.addEventListener("change", handleFile);
|
|
107
|
-
els.searchInput.addEventListener("input",
|
|
113
|
+
els.searchInput.addEventListener("input", scheduleRender);
|
|
108
114
|
els.viewMode.addEventListener("change", render);
|
|
109
115
|
els.typeFilter.addEventListener("change", render);
|
|
110
116
|
els.relationFilter.addEventListener("change", render);
|
|
@@ -183,6 +189,10 @@
|
|
|
183
189
|
state.entityById = new Map(entities.map(function (entity) {
|
|
184
190
|
return [entity.id, entity];
|
|
185
191
|
}));
|
|
192
|
+
state.edgeById = new Map(edges.map(function (edge) {
|
|
193
|
+
return [edge.id, edge];
|
|
194
|
+
}));
|
|
195
|
+
state.degreeById = buildDegreeMap(edges);
|
|
186
196
|
state.episodesById = new Map(episodes.map(function (episode) {
|
|
187
197
|
return [episode.id, episode];
|
|
188
198
|
}));
|
|
@@ -195,6 +205,15 @@
|
|
|
195
205
|
render();
|
|
196
206
|
}
|
|
197
207
|
|
|
208
|
+
function buildDegreeMap(edges) {
|
|
209
|
+
var degrees = new Map();
|
|
210
|
+
edges.forEach(function (edge) {
|
|
211
|
+
degrees.set(edge.from, (degrees.get(edge.from) || 0) + 1);
|
|
212
|
+
degrees.set(edge.to, (degrees.get(edge.to) || 0) + 1);
|
|
213
|
+
});
|
|
214
|
+
return degrees;
|
|
215
|
+
}
|
|
216
|
+
|
|
198
217
|
function loadFromUrlParams() {
|
|
199
218
|
var params = new URLSearchParams(window.location.search);
|
|
200
219
|
var graphPaths = []
|
|
@@ -214,7 +233,7 @@
|
|
|
214
233
|
if (reviewPath) jobs.push(fetchText(reviewPath).then(function (text) { state.reviewText = text; }).catch(function () { state.reviewText = ""; }));
|
|
215
234
|
if (pendingPath) jobs.push(loadPending(pendingPath).then(function (packets) { state.pendingPackets = packets; }));
|
|
216
235
|
if (!graphPaths.length && !jobs.length) {
|
|
217
|
-
|
|
236
|
+
loadHostedDemo();
|
|
218
237
|
return;
|
|
219
238
|
}
|
|
220
239
|
setAutoLoad("loading project graph", false);
|
|
@@ -239,6 +258,21 @@
|
|
|
239
258
|
});
|
|
240
259
|
}
|
|
241
260
|
|
|
261
|
+
function loadHostedDemo() {
|
|
262
|
+
setAutoLoad("loading hosted demo graph", false);
|
|
263
|
+
Promise.all([
|
|
264
|
+
fetchJson("./demo/graph.json"),
|
|
265
|
+
fetchJson("./demo/metrics.json").catch(function () { return null; })
|
|
266
|
+
]).then(function (items) {
|
|
267
|
+
var graph = items[0];
|
|
268
|
+
state.metrics = items[1];
|
|
269
|
+
loadNormalizedGraph(normalizeGraph(graph), "hosted demo graph");
|
|
270
|
+
setAutoLoad("hosted demo graph loaded", true);
|
|
271
|
+
}).catch(function () {
|
|
272
|
+
setAutoLoad("manual mode", false);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
242
276
|
function inferMemoryRoot(path) {
|
|
243
277
|
var marker = "/.agent_memory/";
|
|
244
278
|
var index = path.indexOf(marker);
|
|
@@ -471,6 +505,7 @@
|
|
|
471
505
|
if (!state.graph) return;
|
|
472
506
|
|
|
473
507
|
var query = parseSearchQuery(els.searchInput.value);
|
|
508
|
+
state.renderQuery = query;
|
|
474
509
|
var mode = els.viewMode.value;
|
|
475
510
|
var type = els.typeFilter.value;
|
|
476
511
|
var relation = els.relationFilter.value;
|
|
@@ -509,6 +544,7 @@
|
|
|
509
544
|
type: type,
|
|
510
545
|
relation: relation,
|
|
511
546
|
scope: els.scopeFilter.value,
|
|
547
|
+
mode: mode,
|
|
512
548
|
maxNodes: Number(els.maxNodes.value || 90),
|
|
513
549
|
showDependencies: els.showDependencies.checked
|
|
514
550
|
});
|
|
@@ -528,6 +564,14 @@
|
|
|
528
564
|
renderProof();
|
|
529
565
|
}
|
|
530
566
|
|
|
567
|
+
function scheduleRender() {
|
|
568
|
+
if (state.renderRaf) return;
|
|
569
|
+
state.renderRaf = window.requestAnimationFrame(function () {
|
|
570
|
+
state.renderRaf = null;
|
|
571
|
+
render();
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
531
575
|
function refineVisibleGraph(entityIds, edgeIds, options) {
|
|
532
576
|
var entities = new Set(entityIds);
|
|
533
577
|
var edges = new Set(edgeIds);
|
|
@@ -552,7 +596,9 @@
|
|
|
552
596
|
return entityImportance(state.entityById.get(b)) - entityImportance(state.entityById.get(a)) ||
|
|
553
597
|
displayName(state.entityById.get(a)).localeCompare(displayName(state.entityById.get(b)));
|
|
554
598
|
});
|
|
555
|
-
entities =
|
|
599
|
+
entities = options.mode === "combined"
|
|
600
|
+
? balancedSignalEntities(ranked, options.maxNodes)
|
|
601
|
+
: new Set(ranked.slice(0, options.maxNodes));
|
|
556
602
|
if (state.selected && state.selected.kind === "entity") entities.add(state.selected.id);
|
|
557
603
|
edges = edgesWithVisibleEndpoints(edges, entities);
|
|
558
604
|
}
|
|
@@ -568,6 +614,33 @@
|
|
|
568
614
|
return { entities: entities, edges: edgesWithVisibleEndpoints(edges, entities) };
|
|
569
615
|
}
|
|
570
616
|
|
|
617
|
+
function balancedSignalEntities(rankedIds, maxNodes) {
|
|
618
|
+
var result = new Set();
|
|
619
|
+
var memoryIds = rankedIds.filter(function (id) {
|
|
620
|
+
var entity = state.entityById.get(id);
|
|
621
|
+
return entity && entity.graph_kind === "memory" && ["memory", "repo", "memory_type", "command"].indexOf(entity.type) !== -1;
|
|
622
|
+
});
|
|
623
|
+
var codeIds = rankedIds.filter(function (id) {
|
|
624
|
+
var entity = state.entityById.get(id);
|
|
625
|
+
return entity && entity.graph_kind === "code";
|
|
626
|
+
});
|
|
627
|
+
var otherMemoryIds = rankedIds.filter(function (id) {
|
|
628
|
+
var entity = state.entityById.get(id);
|
|
629
|
+
return entity && entity.graph_kind === "memory" && !memoryIds.includes(id);
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
var memoryBudget = clamp(Math.round(maxNodes * 0.34), 18, Math.min(44, maxNodes));
|
|
633
|
+
memoryIds.slice(0, memoryBudget).forEach(function (id) { result.add(id); });
|
|
634
|
+
otherMemoryIds.slice(0, Math.max(0, Math.round(memoryBudget * 0.35))).forEach(function (id) { result.add(id); });
|
|
635
|
+
codeIds.forEach(function (id) {
|
|
636
|
+
if (result.size < maxNodes) result.add(id);
|
|
637
|
+
});
|
|
638
|
+
rankedIds.forEach(function (id) {
|
|
639
|
+
if (result.size < maxNodes) result.add(id);
|
|
640
|
+
});
|
|
641
|
+
return result;
|
|
642
|
+
}
|
|
643
|
+
|
|
571
644
|
function focusSelection(entityIds, edgeIds, selection) {
|
|
572
645
|
var entities = new Set();
|
|
573
646
|
var edges = new Set();
|
|
@@ -599,7 +672,7 @@
|
|
|
599
672
|
|
|
600
673
|
function edgesWithVisibleEndpoints(edgeIds, entityIds) {
|
|
601
674
|
return new Set(Array.from(edgeIds).filter(function (id) {
|
|
602
|
-
var edge = state.
|
|
675
|
+
var edge = state.edgeById.get(id);
|
|
603
676
|
return edge && entityIds.has(edge.from) && entityIds.has(edge.to);
|
|
604
677
|
}));
|
|
605
678
|
}
|
|
@@ -656,6 +729,22 @@
|
|
|
656
729
|
state.sim.edges = state.edges.filter(function (edge) {
|
|
657
730
|
return state.visibleEdgeIds.has(edge.id) && state.sim.nodeById.has(edge.from) && state.sim.nodeById.has(edge.to);
|
|
658
731
|
});
|
|
732
|
+
state.sim.adjacency = buildAdjacency(state.sim.edges);
|
|
733
|
+
if (forceReset) {
|
|
734
|
+
state.sim.tick = 0;
|
|
735
|
+
state.sim.idleFrames = 0;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function buildAdjacency(edges) {
|
|
740
|
+
var adjacency = new Map();
|
|
741
|
+
edges.forEach(function (edge) {
|
|
742
|
+
if (!adjacency.has(edge.from)) adjacency.set(edge.from, new Set());
|
|
743
|
+
if (!adjacency.has(edge.to)) adjacency.set(edge.to, new Set());
|
|
744
|
+
adjacency.get(edge.from).add(edge.to);
|
|
745
|
+
adjacency.get(edge.to).add(edge.from);
|
|
746
|
+
});
|
|
747
|
+
return adjacency;
|
|
659
748
|
}
|
|
660
749
|
|
|
661
750
|
function seededPosition(index, total) {
|
|
@@ -673,16 +762,28 @@
|
|
|
673
762
|
state.sim.raf = window.requestAnimationFrame(simulationTick);
|
|
674
763
|
}
|
|
675
764
|
|
|
765
|
+
function stopSimulation() {
|
|
766
|
+
state.sim.running = false;
|
|
767
|
+
if (state.sim.raf) window.cancelAnimationFrame(state.sim.raf);
|
|
768
|
+
state.sim.raf = null;
|
|
769
|
+
}
|
|
770
|
+
|
|
676
771
|
function simulationTick() {
|
|
677
772
|
if (!state.sim.running) return;
|
|
678
|
-
stepSimulation();
|
|
773
|
+
var maxVelocity = stepSimulation();
|
|
679
774
|
drawCanvasGraph();
|
|
775
|
+
state.sim.tick += 1;
|
|
776
|
+
state.sim.idleFrames = maxVelocity < 0.035 ? state.sim.idleFrames + 1 : 0;
|
|
777
|
+
if (!state.sim.dragNode && (state.sim.idleFrames > 24 || state.sim.tick > 220)) {
|
|
778
|
+
stopSimulation();
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
680
781
|
state.sim.raf = window.requestAnimationFrame(simulationTick);
|
|
681
782
|
}
|
|
682
783
|
|
|
683
784
|
function stepSimulation() {
|
|
684
785
|
var nodes = state.sim.nodes;
|
|
685
|
-
if (!nodes.length) return;
|
|
786
|
+
if (!nodes.length) return 0;
|
|
686
787
|
var nodeMap = state.sim.nodeById;
|
|
687
788
|
var count = nodes.length;
|
|
688
789
|
var repulsion = count > 120 ? 3600 : count > 70 ? 2500 : 1700;
|
|
@@ -736,11 +837,16 @@
|
|
|
736
837
|
}
|
|
737
838
|
});
|
|
738
839
|
|
|
840
|
+
var maxVelocity = 0;
|
|
739
841
|
nodes.forEach(function (node) {
|
|
740
842
|
if (state.sim.dragNode === node) return;
|
|
741
|
-
|
|
742
|
-
|
|
843
|
+
var vx = clamp(node.vx, -8, 8);
|
|
844
|
+
var vy = clamp(node.vy, -8, 8);
|
|
845
|
+
node.x += vx;
|
|
846
|
+
node.y += vy;
|
|
847
|
+
maxVelocity = Math.max(maxVelocity, Math.abs(vx), Math.abs(vy));
|
|
743
848
|
});
|
|
849
|
+
return maxVelocity;
|
|
744
850
|
}
|
|
745
851
|
|
|
746
852
|
function drawCanvasGraph() {
|
|
@@ -803,7 +909,7 @@
|
|
|
803
909
|
function drawCanvasEdges(ctx) {
|
|
804
910
|
var nodeMap = state.sim.nodeById;
|
|
805
911
|
var focusId = focusedCanvasNodeId();
|
|
806
|
-
var query = parseSearchQuery(els.searchInput.value);
|
|
912
|
+
var query = state.renderQuery || parseSearchQuery(els.searchInput.value);
|
|
807
913
|
var dense = state.sim.nodes.length > 55;
|
|
808
914
|
state.sim.edges.forEach(function (edge) {
|
|
809
915
|
var from = nodeMap.get(edge.from);
|
|
@@ -832,15 +938,14 @@
|
|
|
832
938
|
|
|
833
939
|
function drawCanvasNodes(ctx) {
|
|
834
940
|
var focusId = focusedCanvasNodeId();
|
|
835
|
-
var query = parseSearchQuery(els.searchInput.value);
|
|
941
|
+
var query = state.renderQuery || parseSearchQuery(els.searchInput.value);
|
|
836
942
|
var dense = state.sim.nodes.length > 55;
|
|
943
|
+
var focusNeighbors = focusId ? state.sim.adjacency.get(focusId) : null;
|
|
837
944
|
state.sim.nodes.forEach(function (node) {
|
|
838
945
|
var entity = node.entity;
|
|
839
946
|
var selected = state.selected && state.selected.kind === "entity" && state.selected.id === node.id;
|
|
840
947
|
var hovered = state.sim.hoverNode && state.sim.hoverNode.id === node.id;
|
|
841
|
-
var connected = focusId && (node.id === focusId ||
|
|
842
|
-
return (edge.from === focusId && edge.to === node.id) || (edge.to === focusId && edge.from === node.id);
|
|
843
|
-
}));
|
|
948
|
+
var connected = focusId && (node.id === focusId || (focusNeighbors && focusNeighbors.has(node.id)));
|
|
844
949
|
var matches = matchesSearchQuery(entity, query);
|
|
845
950
|
var alpha = !matches ? 0.12 : focusId && !connected ? 0.20 : 1;
|
|
846
951
|
var color = nodeThemeColor(entity);
|
|
@@ -1376,9 +1481,7 @@
|
|
|
1376
1481
|
}
|
|
1377
1482
|
|
|
1378
1483
|
function degreeOf(id) {
|
|
1379
|
-
return state.
|
|
1380
|
-
return sum + (edge.from === id || edge.to === id ? 1 : 0);
|
|
1381
|
-
}, 0);
|
|
1484
|
+
return state.degreeById.get(id) || 0;
|
|
1382
1485
|
}
|
|
1383
1486
|
|
|
1384
1487
|
function entityImportance(entity) {
|
|
@@ -1442,6 +1545,9 @@
|
|
|
1442
1545
|
state.sim.dragNode.y = world.y;
|
|
1443
1546
|
state.sim.dragNode.vx = 0;
|
|
1444
1547
|
state.sim.dragNode.vy = 0;
|
|
1548
|
+
state.sim.tick = 0;
|
|
1549
|
+
state.sim.idleFrames = 0;
|
|
1550
|
+
startSimulation();
|
|
1445
1551
|
} else if (state.sim.panning) {
|
|
1446
1552
|
var dx = event.clientX - state.sim.panning.x;
|
|
1447
1553
|
var dy = event.clientY - state.sim.panning.y;
|
|
@@ -1451,7 +1557,7 @@
|
|
|
1451
1557
|
}
|
|
1452
1558
|
state.sim.hoverNode = findCanvasNode(world.x, world.y);
|
|
1453
1559
|
updateCanvasTooltip(event);
|
|
1454
|
-
|
|
1560
|
+
scheduleCanvasDraw();
|
|
1455
1561
|
}
|
|
1456
1562
|
|
|
1457
1563
|
function endCanvasPointer() {
|
|
@@ -1471,7 +1577,7 @@
|
|
|
1471
1577
|
state.sim.dragNode = null;
|
|
1472
1578
|
state.sim.panning = null;
|
|
1473
1579
|
if (els.tooltip) els.tooltip.classList.remove("visible");
|
|
1474
|
-
|
|
1580
|
+
scheduleCanvasDraw();
|
|
1475
1581
|
}
|
|
1476
1582
|
|
|
1477
1583
|
function handleCanvasWheel(event) {
|
|
@@ -1482,7 +1588,15 @@
|
|
|
1482
1588
|
state.sim.zoom = clamp(state.sim.zoom * factor, 0.14, 4.5);
|
|
1483
1589
|
state.sim.panX = event.clientX - rect.left - before.x * state.sim.zoom;
|
|
1484
1590
|
state.sim.panY = event.clientY - rect.top - before.y * state.sim.zoom;
|
|
1485
|
-
|
|
1591
|
+
scheduleCanvasDraw();
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
function scheduleCanvasDraw() {
|
|
1595
|
+
if (state.sim.drawRaf) return;
|
|
1596
|
+
state.sim.drawRaf = window.requestAnimationFrame(function () {
|
|
1597
|
+
state.sim.drawRaf = null;
|
|
1598
|
+
drawCanvasGraph();
|
|
1599
|
+
});
|
|
1486
1600
|
}
|
|
1487
1601
|
|
|
1488
1602
|
function handleCanvasDoubleClick(event) {
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
{
|
|
2
|
+
"entities": [
|
|
3
|
+
{
|
|
4
|
+
"id": "repo:kage",
|
|
5
|
+
"type": "repo",
|
|
6
|
+
"name": "Kage",
|
|
7
|
+
"summary": "Repo memory and source graph for coding agents.",
|
|
8
|
+
"aliases": ["kage-core/Kage"],
|
|
9
|
+
"evidence": ["episode:demo-launch"]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "memory:viewer-balance",
|
|
13
|
+
"type": "memory",
|
|
14
|
+
"name": "Viewer balances memory and code",
|
|
15
|
+
"summary": "Combined mode reserves visible space for memory packets before filling the rest with code graph nodes.",
|
|
16
|
+
"aliases": ["viewer", "memory graph", "code graph"],
|
|
17
|
+
"evidence": ["episode:demo-viewer"]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "memory:kage-context",
|
|
21
|
+
"type": "memory",
|
|
22
|
+
"name": "kage_context starts agent sessions",
|
|
23
|
+
"summary": "Agents should call kage_context at session start to receive repo memory, code graph, metrics, and policy hints.",
|
|
24
|
+
"aliases": ["codex", "claude code", "mcp"],
|
|
25
|
+
"evidence": ["episode:demo-context"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "memory:repo-local",
|
|
29
|
+
"type": "memory",
|
|
30
|
+
"name": "Repo-local memory is git-native",
|
|
31
|
+
"summary": "Approved repo memory is written as JSON packets under .agent_memory/packets and travels with the repo.",
|
|
32
|
+
"aliases": ["git", "packets"],
|
|
33
|
+
"evidence": ["episode:demo-repo-memory"]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "memory:review-boundary",
|
|
37
|
+
"type": "memory",
|
|
38
|
+
"name": "Org/global promotion is reviewed",
|
|
39
|
+
"summary": "Agents can write repo-local memory, but org/global/public promotion requires explicit human review.",
|
|
40
|
+
"aliases": ["trust", "review"],
|
|
41
|
+
"evidence": ["episode:demo-trust"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "type:decision",
|
|
45
|
+
"type": "memory_type",
|
|
46
|
+
"name": "decision",
|
|
47
|
+
"summary": "Durable architectural or product choice.",
|
|
48
|
+
"aliases": [],
|
|
49
|
+
"evidence": ["episode:demo-viewer"]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "type:runbook",
|
|
53
|
+
"type": "memory_type",
|
|
54
|
+
"name": "runbook",
|
|
55
|
+
"summary": "How to run, test, debug, or operate the repo.",
|
|
56
|
+
"aliases": [],
|
|
57
|
+
"evidence": ["episode:demo-context"]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "command:kage-viewer",
|
|
61
|
+
"type": "command",
|
|
62
|
+
"name": "kage viewer --project .",
|
|
63
|
+
"summary": "Launches the local auto-loaded Memory Terminal for a repo.",
|
|
64
|
+
"aliases": ["viewer"],
|
|
65
|
+
"evidence": ["episode:demo-viewer"]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "command:kage-refresh",
|
|
69
|
+
"type": "command",
|
|
70
|
+
"name": "kage refresh --project .",
|
|
71
|
+
"summary": "Rebuilds indexes, code graph, memory graph, metrics, and stale memory metadata.",
|
|
72
|
+
"aliases": ["refresh"],
|
|
73
|
+
"evidence": ["episode:demo-context"]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "path:mcp-viewer-app",
|
|
77
|
+
"type": "path",
|
|
78
|
+
"name": "mcp/viewer/app.js",
|
|
79
|
+
"summary": "Static Memory Terminal canvas graph and inspector.",
|
|
80
|
+
"aliases": ["viewer app"],
|
|
81
|
+
"evidence": ["episode:demo-viewer"]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "path:mcp-kernel",
|
|
85
|
+
"type": "path",
|
|
86
|
+
"name": "mcp/kernel.ts",
|
|
87
|
+
"summary": "Memory kernel, validation, indexing, graph, recall, setup, metrics, and PR checks.",
|
|
88
|
+
"aliases": ["kernel"],
|
|
89
|
+
"evidence": ["episode:demo-context"]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "tag:viewer",
|
|
93
|
+
"type": "tag",
|
|
94
|
+
"name": "viewer",
|
|
95
|
+
"summary": "Graph and memory terminal experience.",
|
|
96
|
+
"aliases": [],
|
|
97
|
+
"evidence": ["episode:demo-viewer"]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "tag:repo-memory",
|
|
101
|
+
"type": "tag",
|
|
102
|
+
"name": "repo-memory",
|
|
103
|
+
"summary": "Git-native memory packets shared across agents.",
|
|
104
|
+
"aliases": [],
|
|
105
|
+
"evidence": ["episode:demo-repo-memory"]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"id": "tag:mcp",
|
|
109
|
+
"type": "tag",
|
|
110
|
+
"name": "mcp",
|
|
111
|
+
"summary": "Model Context Protocol integration for coding agents.",
|
|
112
|
+
"aliases": [],
|
|
113
|
+
"evidence": ["episode:demo-context"]
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"edges": [
|
|
117
|
+
{
|
|
118
|
+
"id": "edge:repo:viewer",
|
|
119
|
+
"from": "repo:kage",
|
|
120
|
+
"to": "memory:viewer-balance",
|
|
121
|
+
"relation": "contains_memory",
|
|
122
|
+
"fact": "Kage contains a viewer memory about balancing memory and code graph nodes.",
|
|
123
|
+
"confidence": 0.95,
|
|
124
|
+
"evidence": ["episode:demo-viewer"]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "edge:repo:context",
|
|
128
|
+
"from": "repo:kage",
|
|
129
|
+
"to": "memory:kage-context",
|
|
130
|
+
"relation": "contains_memory",
|
|
131
|
+
"fact": "Kage contains a session-start memory about kage_context.",
|
|
132
|
+
"confidence": 0.95,
|
|
133
|
+
"evidence": ["episode:demo-context"]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"id": "edge:repo:local",
|
|
137
|
+
"from": "repo:kage",
|
|
138
|
+
"to": "memory:repo-local",
|
|
139
|
+
"relation": "contains_memory",
|
|
140
|
+
"fact": "Kage contains a memory about git-native repo-local packets.",
|
|
141
|
+
"confidence": 0.95,
|
|
142
|
+
"evidence": ["episode:demo-repo-memory"]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "edge:repo:review",
|
|
146
|
+
"from": "repo:kage",
|
|
147
|
+
"to": "memory:review-boundary",
|
|
148
|
+
"relation": "contains_memory",
|
|
149
|
+
"fact": "Kage contains a trust-boundary memory for org/global promotion.",
|
|
150
|
+
"confidence": 0.95,
|
|
151
|
+
"evidence": ["episode:demo-trust"]
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"id": "edge:viewer:type",
|
|
155
|
+
"from": "memory:viewer-balance",
|
|
156
|
+
"to": "type:decision",
|
|
157
|
+
"relation": "has_type",
|
|
158
|
+
"fact": "Viewer balance is a product decision.",
|
|
159
|
+
"confidence": 0.9,
|
|
160
|
+
"evidence": ["episode:demo-viewer"]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"id": "edge:context:type",
|
|
164
|
+
"from": "memory:kage-context",
|
|
165
|
+
"to": "type:runbook",
|
|
166
|
+
"relation": "has_type",
|
|
167
|
+
"fact": "kage_context is operational runbook memory.",
|
|
168
|
+
"confidence": 0.9,
|
|
169
|
+
"evidence": ["episode:demo-context"]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"id": "edge:viewer:path",
|
|
173
|
+
"from": "memory:viewer-balance",
|
|
174
|
+
"to": "path:mcp-viewer-app",
|
|
175
|
+
"relation": "affects_path",
|
|
176
|
+
"fact": "Viewer balance applies to the static viewer app.",
|
|
177
|
+
"confidence": 0.92,
|
|
178
|
+
"evidence": ["episode:demo-viewer"]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"id": "edge:context:path",
|
|
182
|
+
"from": "memory:kage-context",
|
|
183
|
+
"to": "path:mcp-kernel",
|
|
184
|
+
"relation": "affects_path",
|
|
185
|
+
"fact": "kage_context is implemented through the memory kernel and MCP server.",
|
|
186
|
+
"confidence": 0.88,
|
|
187
|
+
"evidence": ["episode:demo-context"]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "edge:viewer:command",
|
|
191
|
+
"from": "memory:viewer-balance",
|
|
192
|
+
"to": "command:kage-viewer",
|
|
193
|
+
"relation": "documents_command",
|
|
194
|
+
"fact": "The viewer memory documents the kage viewer command.",
|
|
195
|
+
"confidence": 0.9,
|
|
196
|
+
"evidence": ["episode:demo-viewer"]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "edge:context:refresh",
|
|
200
|
+
"from": "memory:kage-context",
|
|
201
|
+
"to": "command:kage-refresh",
|
|
202
|
+
"relation": "documents_command",
|
|
203
|
+
"fact": "Agent context should be refreshed after meaningful changes.",
|
|
204
|
+
"confidence": 0.86,
|
|
205
|
+
"evidence": ["episode:demo-context"]
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"id": "edge:viewer:tag",
|
|
209
|
+
"from": "memory:viewer-balance",
|
|
210
|
+
"to": "tag:viewer",
|
|
211
|
+
"relation": "mentions_tag",
|
|
212
|
+
"fact": "Viewer balance is tagged viewer.",
|
|
213
|
+
"confidence": 0.9,
|
|
214
|
+
"evidence": ["episode:demo-viewer"]
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "edge:local:tag",
|
|
218
|
+
"from": "memory:repo-local",
|
|
219
|
+
"to": "tag:repo-memory",
|
|
220
|
+
"relation": "mentions_tag",
|
|
221
|
+
"fact": "Repo-local memory is tagged repo-memory.",
|
|
222
|
+
"confidence": 0.9,
|
|
223
|
+
"evidence": ["episode:demo-repo-memory"]
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "edge:context:tag",
|
|
227
|
+
"from": "memory:kage-context",
|
|
228
|
+
"to": "tag:mcp",
|
|
229
|
+
"relation": "mentions_tag",
|
|
230
|
+
"fact": "kage_context is exposed through MCP.",
|
|
231
|
+
"confidence": 0.9,
|
|
232
|
+
"evidence": ["episode:demo-context"]
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
"episodes": [
|
|
236
|
+
{
|
|
237
|
+
"id": "episode:demo-launch",
|
|
238
|
+
"summary": "Kage demo graph for the hosted Memory Terminal.",
|
|
239
|
+
"source": "hosted_demo",
|
|
240
|
+
"created_at": "2026-05-03T00:00:00.000Z"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"id": "episode:demo-viewer",
|
|
244
|
+
"summary": "The viewer should show memory and code graph together, not an empty shell.",
|
|
245
|
+
"source": "hosted_demo",
|
|
246
|
+
"created_at": "2026-05-03T00:00:00.000Z"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"id": "episode:demo-context",
|
|
250
|
+
"summary": "Agents use kage_context and refresh to avoid rediscovery.",
|
|
251
|
+
"source": "hosted_demo",
|
|
252
|
+
"created_at": "2026-05-03T00:00:00.000Z"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "episode:demo-repo-memory",
|
|
256
|
+
"summary": "Repo-local packets are git-native durable memory.",
|
|
257
|
+
"source": "hosted_demo",
|
|
258
|
+
"created_at": "2026-05-03T00:00:00.000Z"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"id": "episode:demo-trust",
|
|
262
|
+
"summary": "Org/global sharing is review-gated.",
|
|
263
|
+
"source": "hosted_demo",
|
|
264
|
+
"created_at": "2026-05-03T00:00:00.000Z"
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"project_dir": "hosted-demo",
|
|
4
|
+
"repo_key": "kage-core-kage",
|
|
5
|
+
"generated_at": "2026-05-03T00:00:00.000Z",
|
|
6
|
+
"code_graph": {
|
|
7
|
+
"files": 12,
|
|
8
|
+
"symbols": 1894,
|
|
9
|
+
"imports": 37,
|
|
10
|
+
"calls": 2317,
|
|
11
|
+
"routes": 3,
|
|
12
|
+
"tests": 64,
|
|
13
|
+
"packages_and_scripts": 9,
|
|
14
|
+
"languages": {
|
|
15
|
+
"typescript": 6,
|
|
16
|
+
"javascript": 3,
|
|
17
|
+
"markdown": 3
|
|
18
|
+
},
|
|
19
|
+
"parsers": {
|
|
20
|
+
"typescript": 6,
|
|
21
|
+
"javascript": 3,
|
|
22
|
+
"metadata": 3
|
|
23
|
+
},
|
|
24
|
+
"source_symbols_by_parser": {
|
|
25
|
+
"typescript": 1620,
|
|
26
|
+
"javascript": 274
|
|
27
|
+
},
|
|
28
|
+
"indexer_coverage_percent": 100
|
|
29
|
+
},
|
|
30
|
+
"memory_graph": {
|
|
31
|
+
"approved_packets": 22,
|
|
32
|
+
"pending_packets": 0,
|
|
33
|
+
"episodes": 5,
|
|
34
|
+
"entities": 14,
|
|
35
|
+
"edges": 13,
|
|
36
|
+
"evidence_backed_edges": 13,
|
|
37
|
+
"evidence_coverage_percent": 100,
|
|
38
|
+
"average_quality_score": 97,
|
|
39
|
+
"duplicate_candidate_pairs": 0
|
|
40
|
+
},
|
|
41
|
+
"savings": {
|
|
42
|
+
"estimated_indexed_source_tokens": 113882,
|
|
43
|
+
"estimated_memory_tokens": 1800,
|
|
44
|
+
"estimated_recall_context_tokens": 1800,
|
|
45
|
+
"estimated_tokens_saved_per_recall": 112082
|
|
46
|
+
},
|
|
47
|
+
"harness": {
|
|
48
|
+
"policy_installed": true,
|
|
49
|
+
"validation_ok": true,
|
|
50
|
+
"warnings": 0,
|
|
51
|
+
"errors": 0,
|
|
52
|
+
"readiness_score": 100
|
|
53
|
+
},
|
|
54
|
+
"pain": {
|
|
55
|
+
"setup_runbook_coverage_percent": 100,
|
|
56
|
+
"bug_fix_coverage_percent": 80,
|
|
57
|
+
"decision_coverage_percent": 100,
|
|
58
|
+
"code_flow_coverage_percent": 100,
|
|
59
|
+
"recall_hit_rate_percent": 100,
|
|
60
|
+
"estimated_rediscovery_avoided": 9,
|
|
61
|
+
"estimated_tokens_saved": 112082,
|
|
62
|
+
"time_to_first_use_seconds": 60
|
|
63
|
+
},
|
|
64
|
+
"quality": {
|
|
65
|
+
"totals": {
|
|
66
|
+
"approved": 22,
|
|
67
|
+
"pending": 0,
|
|
68
|
+
"high_signal": 21,
|
|
69
|
+
"needs_review": 1,
|
|
70
|
+
"duplicate": 0,
|
|
71
|
+
"stale": 0,
|
|
72
|
+
"too_generic": 0
|
|
73
|
+
},
|
|
74
|
+
"memory_type_coverage": {
|
|
75
|
+
"decision": 10,
|
|
76
|
+
"runbook": 5,
|
|
77
|
+
"gotcha": 3,
|
|
78
|
+
"reference": 4
|
|
79
|
+
},
|
|
80
|
+
"useful_memory_ratio_percent": 97,
|
|
81
|
+
"duplicate_burden": 0,
|
|
82
|
+
"stale_wrong_feedback_rate_percent": 0,
|
|
83
|
+
"evidence_coverage_percent": 100,
|
|
84
|
+
"path_grounding_coverage_percent": 100,
|
|
85
|
+
"approved_to_pending_ratio": 22
|
|
86
|
+
}
|
|
87
|
+
}
|