@kage-core/kage-graph-mcp 1.1.36 → 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 +101 -2
- 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 +1250 -41
- package/viewer/data.html +2 -9
- package/viewer/graph.html +2 -9
- package/viewer/index.html +2 -9
- package/viewer/intel.html +2 -9
- package/viewer/memory.html +73 -9
- package/viewer/owners.html +2 -9
- package/viewer/review.html +13 -9
- package/viewer/styles.css +582 -103
package/README.md
CHANGED
|
@@ -34,6 +34,9 @@ Roo Code, Kilo Code, Claude Desktop, Aider, generic MCP (`kage setup list`).
|
|
|
34
34
|
|
|
35
35
|
- Repo-local memory for decisions, runbooks, bug fixes, gotchas, conventions,
|
|
36
36
|
and code explanations.
|
|
37
|
+
- Claude Code ambient hooks for prompt-time recall, tool-result observation,
|
|
38
|
+
failure capture, pre-compact/session-end distillation, and stop-time review
|
|
39
|
+
refresh.
|
|
37
40
|
- A code graph for files, symbols, imports, confidence-scored calls, routes
|
|
38
41
|
(FastAPI / Flask / Django / Rails / Laravel / Spring / Go / Rust / ASP.NET),
|
|
39
42
|
tests, and packages.
|
|
@@ -42,7 +45,37 @@ Roo Code, Kilo Code, Claude Desktop, Aider, generic MCP (`kage setup list`).
|
|
|
42
45
|
ownership silos, module health.
|
|
43
46
|
- Conservative cleanup review input (unreferenced files, unused exports,
|
|
44
47
|
internal-looking unused symbols). Never deletes code.
|
|
45
|
-
- A local viewer for memory, code graph, risks, review, and metrics
|
|
48
|
+
- A local viewer for memory, code graph, risks, review, and metrics, served
|
|
49
|
+
with conservative browser security headers.
|
|
50
|
+
- Local memory-access tracking in `.agent_memory/reports/memory-access.json`
|
|
51
|
+
so agents can learn which memories are reused and recommend what to verify,
|
|
52
|
+
ground, or clean up without changing shareable packet files on every recall.
|
|
53
|
+
- Memory lifecycle reporting in `.agent_memory/reports/lifecycle.json` so
|
|
54
|
+
teammates can review healthy, hot, stale, disputed, ungrounded, pending, and
|
|
55
|
+
generated packets with concrete actions.
|
|
56
|
+
- Memory timeline reporting in `.agent_memory/reports/timeline.json` so
|
|
57
|
+
handoffs show recently added, updated, pending, and retired repo knowledge.
|
|
58
|
+
- Memory lineage reporting in `.agent_memory/reports/lineage.json` so
|
|
59
|
+
superseded packets point at the current replacement memory agents should use.
|
|
60
|
+
- Memory audit reporting in `.agent_memory/audit/events.jsonl` and
|
|
61
|
+
`.agent_memory/reports/memory-audit.json` so memory mutations are reviewable.
|
|
62
|
+
- Memory handoff reporting in `.agent_memory/reports/handoff.json` so the next
|
|
63
|
+
teammate or agent gets one queue across inbox, lifecycle, audit, timeline,
|
|
64
|
+
lineage, and distillable session learnings.
|
|
65
|
+
- Project profile reporting in `.agent_memory/reports/profile.json` so agents
|
|
66
|
+
get a compact orientation across repo shape, top concepts, key files,
|
|
67
|
+
commands, memory focus, and next actions.
|
|
68
|
+
- Capability audit reporting in `.agent_memory/reports/capabilities.json` so
|
|
69
|
+
teams can see evidence-backed readiness across memory, collaboration,
|
|
70
|
+
benchmark proof, and dashboard/viewer proof.
|
|
71
|
+
- Pinned context slots in `.agent_memory/slots/slots.json` so teams can review
|
|
72
|
+
tiny always-relevant repo guidance that Kage includes before task-specific
|
|
73
|
+
recall.
|
|
74
|
+
- Session replay digest in `.agent_memory/reports/replay.json` so teams can
|
|
75
|
+
review observed agent timelines, paths, commands, durable candidates, and
|
|
76
|
+
distill actions without exposing raw transcript text.
|
|
77
|
+
- A viewer benchmark proof ledger that shows measured results, thresholds,
|
|
78
|
+
exact commands, and next actions for retrieval, scale, and repo trust gates.
|
|
46
79
|
|
|
47
80
|
No hosted service, external database, or API key is required.
|
|
48
81
|
|
|
@@ -52,8 +85,24 @@ No hosted service, external database, or API key is required.
|
|
|
52
85
|
kage recall "how do I run tests" --project .
|
|
53
86
|
kage code-graph "auth routes tests" --project .
|
|
54
87
|
kage risk --project . --targets src/auth.ts --json
|
|
88
|
+
kage profile --project . --json
|
|
89
|
+
kage capabilities --project . --json
|
|
90
|
+
kage slots set --project . --label project_context --content "Always run retry tests after changing retry modules." --paths src/retry.ts --tags retry,tests
|
|
91
|
+
kage slots --project . --json
|
|
55
92
|
kage learn --project . --learning "Use npm test after parser changes."
|
|
93
|
+
kage sessions --project . # observed sessions and distillation actions
|
|
94
|
+
kage replay --project . # privacy-preserving observed-session timeline
|
|
95
|
+
kage memory-access --project . # hot/cold memories and review actions
|
|
96
|
+
kage memory-audit --project . # auditable memory mutations
|
|
97
|
+
kage handoff --project . # combined teammate/agent handoff queue
|
|
98
|
+
kage lifecycle --project . # memory health, freshness, grounding, and feedback
|
|
99
|
+
kage timeline --project . # recent memory changes for handoff
|
|
100
|
+
kage lineage --project . # current replacements for retired memories
|
|
101
|
+
kage supersede --project . --packet <old-id> --replacement <new-id> --reason "why"
|
|
102
|
+
kage benchmark --memory-quality # coding-memory retrieval proof
|
|
103
|
+
kage benchmark --scale --sizes 240,1000,5000 # large-memory recall proof
|
|
56
104
|
kage refresh --project .
|
|
105
|
+
kage embeddings build --project . # optional dense local recall
|
|
57
106
|
kage hook install --project .
|
|
58
107
|
kage pr check --project .
|
|
59
108
|
kage viewer --project .
|
|
@@ -62,6 +111,14 @@ kage viewer --project .
|
|
|
62
111
|
MCP agents should start with `kage_context`. When the query or target list
|
|
63
112
|
mentions file paths, it also includes risk and dependency-path context.
|
|
64
113
|
|
|
114
|
+
Normal recall is local and dependency-free. For repos that need denser semantic
|
|
115
|
+
matching, install `@xenova/transformers` in the same Node environment as Kage,
|
|
116
|
+
then run `kage embeddings build --project .`. The default lexical layer is
|
|
117
|
+
Unicode-aware and adds CJK bigrams for memory written without spaces. Dense
|
|
118
|
+
embeddings write an optional rebuildable
|
|
119
|
+
`.agent_memory/indexes/embeddings-local.json` artifact, and
|
|
120
|
+
`kage recall "query" --project . --embeddings --explain` uses it.
|
|
121
|
+
|
|
65
122
|
For stale or wrong memory:
|
|
66
123
|
|
|
67
124
|
```bash
|
|
@@ -79,6 +136,46 @@ kage setup claude-code --project . --write
|
|
|
79
136
|
kage setup generic-mcp --project .
|
|
80
137
|
```
|
|
81
138
|
|
|
139
|
+
`kage setup claude-code --write` installs the MCP server plus SessionStart,
|
|
140
|
+
UserPromptSubmit, PostToolUse, PostToolUseFailure, PreCompact, Stop, and
|
|
141
|
+
SessionEnd hooks. The hooks observe reusable work signals, inject relevant
|
|
142
|
+
repo memory on new prompts, and distill durable learnings before compaction or
|
|
143
|
+
handoff.
|
|
144
|
+
|
|
145
|
+
`kage setup verify-agent --agent claude-code --project .` checks those hooks,
|
|
146
|
+
not only the MCP config. If a teammate has the server configured but missing
|
|
147
|
+
ambient hooks, verification reports the missing events and tells them to rerun
|
|
148
|
+
setup.
|
|
149
|
+
|
|
150
|
+
`kage setup doctor --project . --json` also includes the Claude hook summary,
|
|
151
|
+
so teams can audit partial installs before relying on automatic capture.
|
|
152
|
+
MCP agents can call `kage_setup_doctor` for the same audit without shelling out.
|
|
153
|
+
|
|
154
|
+
## REST daemon
|
|
155
|
+
|
|
156
|
+
HTTP-only agents can use the same memory system through the local daemon:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
kage daemon start --project .
|
|
160
|
+
curl -X POST http://127.0.0.1:3111/kage/context \
|
|
161
|
+
-H 'content-type: application/json' \
|
|
162
|
+
-d '{"query":"how does auth work?","limit":5}'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Useful endpoints:
|
|
166
|
+
|
|
167
|
+
- `POST /kage/context` - combined recall, graph facts, validation, risk, and dependency context.
|
|
168
|
+
- `POST /kage/recall` - repo memory recall.
|
|
169
|
+
- `POST /kage/capture` and `POST /kage/learn` - write durable repo memory.
|
|
170
|
+
- `POST /kage/feedback` - mark recalled memory helpful, wrong, or stale.
|
|
171
|
+
- `POST /kage/observe` and `POST /kage/distill` - session observation and durable learning distillation.
|
|
172
|
+
- `GET /kage/replay` - privacy-preserving session replay digest without raw transcript text.
|
|
173
|
+
- `GET /kage/setup-doctor` - supported-agent setup and Claude hook readiness.
|
|
174
|
+
- `GET /kage/profile` - compact project profile for agent orientation.
|
|
175
|
+
- `GET /kage/capabilities` - evidence-backed memory system readiness across memory, collaboration, benchmarks, and viewer proof.
|
|
176
|
+
- `GET /kage/context-slots`, `POST /kage/context-slots`, `DELETE /kage/context-slots/:label` - pinned repo context slots.
|
|
177
|
+
- `GET /kage/metrics`, `/kage/quality`, `/kage/inbox`, `/kage/benchmark`, `/kage/handoff`, `/kage/lifecycle`, `/kage/timeline`, `/kage/lineage`, `/kage/memory-audit` - human and agent review reports.
|
|
178
|
+
|
|
82
179
|
## Storage
|
|
83
180
|
|
|
84
181
|
Kage writes to `.agent_memory/`. Packets are durable repo memory; everything
|
|
@@ -90,7 +187,9 @@ else is rebuildable with `kage refresh`.
|
|
|
90
187
|
| `.agent_memory/graph/` | memory graph (rebuildable) |
|
|
91
188
|
| `.agent_memory/code_graph/` | source-derived code facts (rebuildable) |
|
|
92
189
|
| `.agent_memory/structural/` | files, symbols, imports |
|
|
93
|
-
| `.agent_memory/
|
|
190
|
+
| `.agent_memory/slots/` | pinned repo context slots |
|
|
191
|
+
| `.agent_memory/indexes/` | recall indexes, including optional embeddings |
|
|
192
|
+
| `.agent_memory/reports/` | profile, capabilities, context-slots, replay, risk, contributors, decisions, module health, workspace, quality, benchmark, handoff, lifecycle, timeline, lineage |
|
|
94
193
|
|
|
95
194
|
Repo-local packets are git-visible and reviewable. Generated indexes and
|
|
96
195
|
graphs are rebuildable.
|
package/dist/cli.js
CHANGED
|
@@ -34,7 +34,20 @@ Usage:
|
|
|
34
34
|
kage upgrade [--dry-run]
|
|
35
35
|
kage branch --project <dir> [--json]
|
|
36
36
|
kage metrics --project <dir> [--json]
|
|
37
|
+
kage memory-access --project <dir> [--json]
|
|
38
|
+
kage memory-audit --project <dir> [--limit <n>] [--json]
|
|
39
|
+
kage slots --project <dir> [--json]
|
|
40
|
+
kage slots set --project <dir> --label <label> --content <text> [--description <text>] [--paths a,b] [--tags a,b] [--size-limit <n>] [--unpinned] [--json]
|
|
41
|
+
kage slots delete --project <dir> --label <label> [--json]
|
|
42
|
+
kage handoff --project <dir> [--json]
|
|
43
|
+
kage lifecycle --project <dir> [--json]
|
|
44
|
+
kage reconcile --project <dir> [--session <id>] [--json]
|
|
45
|
+
kage timeline --project <dir> [--days <n>] [--json]
|
|
46
|
+
kage lineage --project <dir> [--json]
|
|
47
|
+
kage supersede --project <dir> --packet <old-id> --replacement <new-id> [--reason <text>] [--json]
|
|
37
48
|
kage contributors --project <dir> [--json]
|
|
49
|
+
kage profile --project <dir> [--json]
|
|
50
|
+
kage capabilities --project <dir> [--json]
|
|
38
51
|
kage decisions --project <dir> [--json]
|
|
39
52
|
kage module-health --project <dir> [--json]
|
|
40
53
|
kage graph-insights --project <dir> [--json]
|
|
@@ -44,6 +57,8 @@ Usage:
|
|
|
44
57
|
kage inbox --project <dir> [--json]
|
|
45
58
|
kage quality --project <dir> [--json]
|
|
46
59
|
kage benchmark --project <dir> [--json]
|
|
60
|
+
kage benchmark --memory-quality [--json]
|
|
61
|
+
kage benchmark --scale [--sizes 240,1000,5000] [--json]
|
|
47
62
|
kage benchmark --project <dir> --compare --task <task> [--json]
|
|
48
63
|
kage code-graph --project <dir> [--json]
|
|
49
64
|
kage code-graph "<query>" --project <dir> [--json]
|
|
@@ -57,8 +72,11 @@ Usage:
|
|
|
57
72
|
kage graph --project <dir> --mermaid
|
|
58
73
|
kage graph "<query>" --project <dir> [--json]
|
|
59
74
|
kage graph-registry --project <dir> [--json]
|
|
60
|
-
kage
|
|
75
|
+
kage embeddings build --project <dir> [--model Xenova/all-MiniLM-L6-v2] [--json]
|
|
76
|
+
kage recall "<query>" --project <dir> [--json] [--explain] [--embeddings]
|
|
61
77
|
kage observe --project <dir> --event <json>
|
|
78
|
+
kage sessions --project <dir> [--json]
|
|
79
|
+
kage replay --project <dir> [--session <id>] [--limit <n>] [--json]
|
|
62
80
|
kage distill --project <dir> --session <id>
|
|
63
81
|
kage learn --project <dir> --learning <text> [--title <title>] [--type <type>] [--evidence <text>] [--verified-by <text>] [--tags a,b] [--paths a,b]
|
|
64
82
|
kage feedback --project <dir> --packet <packet-id> --kind helpful|wrong|stale
|
|
@@ -220,7 +238,10 @@ async function main() {
|
|
|
220
238
|
}
|
|
221
239
|
console.log("Kage setup doctor");
|
|
222
240
|
for (const item of result) {
|
|
223
|
-
|
|
241
|
+
const hookStatus = item.hook_summary
|
|
242
|
+
? item.hook_summary.ready ? " hooks: installed" : ` hooks: missing ${item.hook_summary.missing.join(", ")}`
|
|
243
|
+
: "";
|
|
244
|
+
console.log(`- ${item.agent}: ${item.configured ? "configured" : "not detected"}${hookStatus}${item.config_path ? ` (${item.config_path})` : ""}`);
|
|
224
245
|
}
|
|
225
246
|
return;
|
|
226
247
|
}
|
|
@@ -240,6 +261,9 @@ async function main() {
|
|
|
240
261
|
console.log(`Indexes: ${result.checks.indexes_present ? "present" : "missing"}`);
|
|
241
262
|
console.log(`Recall: ${result.checks.recall_works ? "ok" : "failed"} (${result.recall_preview})`);
|
|
242
263
|
console.log(`Code graph: ${result.checks.code_graph_works ? "ok" : "failed"} (${result.code_graph_summary})`);
|
|
264
|
+
if (result.hook_summary) {
|
|
265
|
+
console.log(`Ambient hooks: ${result.checks.ambient_hooks_present ? "installed" : `missing ${result.hook_summary.missing.join(", ")}`}`);
|
|
266
|
+
}
|
|
243
267
|
console.log(`Active MCP tool: ${result.checks.mcp_tool_reachable ? "reachable" : "not verified from CLI"}`);
|
|
244
268
|
if (result.warnings.length)
|
|
245
269
|
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
@@ -641,6 +665,33 @@ async function main() {
|
|
|
641
665
|
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
642
666
|
return;
|
|
643
667
|
}
|
|
668
|
+
if (command === "profile") {
|
|
669
|
+
const result = (0, kernel_js_1.kageProjectProfile)(projectArg(args));
|
|
670
|
+
if (args.includes("--json")) {
|
|
671
|
+
console.log(JSON.stringify(result, null, 2));
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
console.log(`Kage project profile: ${result.summary}`);
|
|
675
|
+
console.log(`Files: ${result.totals.files} (${result.totals.source_files} source, ${result.totals.test_files} test), symbols: ${result.totals.symbols}`);
|
|
676
|
+
console.log(`Memory: ${result.totals.approved_memory} packets, ${result.totals.memory_code_coverage_percent}% memory-code coverage`);
|
|
677
|
+
if (result.top_concepts.length)
|
|
678
|
+
console.log(`Top concepts: ${result.top_concepts.slice(0, 6).map((item) => `${item.concept} (${item.count})`).join(", ")}`);
|
|
679
|
+
if (result.key_files.length) {
|
|
680
|
+
console.log("Key files:");
|
|
681
|
+
for (const file of result.key_files.slice(0, 8))
|
|
682
|
+
console.log(`- ${file.path}: ${file.why.slice(0, 3).join("; ")}`);
|
|
683
|
+
}
|
|
684
|
+
if (result.run_commands.length) {
|
|
685
|
+
console.log("Commands:");
|
|
686
|
+
for (const commandItem of result.run_commands.slice(0, 6))
|
|
687
|
+
console.log(`- ${commandItem.name}: ${commandItem.command}`);
|
|
688
|
+
}
|
|
689
|
+
if (result.next_actions.length)
|
|
690
|
+
console.log(`Next: ${result.next_actions[0]}`);
|
|
691
|
+
if (result.warnings.length)
|
|
692
|
+
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
644
695
|
if (command === "decisions") {
|
|
645
696
|
const result = (0, kernel_js_1.kageDecisionIntelligence)(projectArg(args));
|
|
646
697
|
if (args.includes("--json")) {
|
|
@@ -775,6 +826,256 @@ async function main() {
|
|
|
775
826
|
console.log(` Estimated tokens saved: ${result.pain.estimated_tokens_saved}`);
|
|
776
827
|
console.log(` Time to first use: ${result.pain.time_to_first_use_seconds}s`);
|
|
777
828
|
}
|
|
829
|
+
if (result.memory_access) {
|
|
830
|
+
console.log("\nMemory access:");
|
|
831
|
+
console.log(` Tracked packets: ${result.memory_access.tracked_packets}`);
|
|
832
|
+
console.log(` Uses in 30d: ${result.memory_access.uses_30d}`);
|
|
833
|
+
console.log(` Hot / cold packets: ${result.memory_access.hot_packets} / ${result.memory_access.cold_packets}`);
|
|
834
|
+
}
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
if (command === "memory-access") {
|
|
838
|
+
const result = (0, kernel_js_1.kageMemoryAccess)(projectArg(args));
|
|
839
|
+
if (args.includes("--json")) {
|
|
840
|
+
console.log(JSON.stringify(result, null, 2));
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
console.log(`Kage memory access: ${result.totals.tracked_packets} tracked packet${result.totals.tracked_packets === 1 ? "" : "s"}`);
|
|
844
|
+
console.log(`Recent uses: ${result.totals.uses_30d} in ${result.window_days} days`);
|
|
845
|
+
console.log(`Hot / cold: ${result.totals.hot_packets} / ${result.totals.cold_packets}`);
|
|
846
|
+
if (result.recommendations.length) {
|
|
847
|
+
console.log("\nRecommended review:");
|
|
848
|
+
for (const item of result.recommendations.slice(0, 5)) {
|
|
849
|
+
console.log(`- ${item.summary}`);
|
|
850
|
+
console.log(` ${item.action}`);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
console.log("\nTop recalled packets:");
|
|
854
|
+
for (const entry of result.entries.filter((item) => !(item.tags.includes("change-memory") && item.tags.includes("diff-proposal"))).slice(0, 10)) {
|
|
855
|
+
if (!entry.total_uses)
|
|
856
|
+
continue;
|
|
857
|
+
console.log(`- ${entry.title}: ${entry.uses_30d} recent, ${entry.total_uses} total${entry.best_rank ? `, best rank ${entry.best_rank}` : ""}`);
|
|
858
|
+
}
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
if (command === "lifecycle" || command === "memory-lifecycle") {
|
|
862
|
+
const result = (0, kernel_js_1.kageMemoryLifecycle)(projectArg(args));
|
|
863
|
+
if (args.includes("--json")) {
|
|
864
|
+
console.log(JSON.stringify(result, null, 2));
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
console.log(`Kage memory lifecycle: ${result.totals.approved} approved, ${result.totals.pending} pending`);
|
|
868
|
+
console.log(`Healthy / hot / stale: ${result.totals.healthy} / ${result.totals.hot} / ${result.totals.stale}`);
|
|
869
|
+
console.log(`Ungrounded / disputed / generated: ${result.totals.ungrounded} / ${result.totals.disputed} / ${result.totals.generated}`);
|
|
870
|
+
if (result.recommendations.length) {
|
|
871
|
+
console.log("\nRecommended actions:");
|
|
872
|
+
for (const item of result.recommendations.slice(0, 6)) {
|
|
873
|
+
console.log(`- ${item.title ? `${item.title}: ` : ""}${item.summary}`);
|
|
874
|
+
console.log(` ${item.action}`);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
if (command === "reconcile" || command === "memory-reconcile" || command === "memory-reconciliation") {
|
|
880
|
+
const result = (0, kernel_js_1.kageMemoryReconciliation)(projectArg(args), {
|
|
881
|
+
sessionId: takeArg(args, "--session"),
|
|
882
|
+
limit: numberArg(args, "--limit", 25),
|
|
883
|
+
});
|
|
884
|
+
if (args.includes("--json")) {
|
|
885
|
+
console.log(JSON.stringify(result, null, 2));
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
console.log(result.agent_instruction);
|
|
889
|
+
if (result.items.length) {
|
|
890
|
+
console.log("\nItems:");
|
|
891
|
+
for (const item of result.items) {
|
|
892
|
+
console.log(`- ${item.packet_id}: ${item.title}`);
|
|
893
|
+
console.log(` Paths: ${item.changed_paths.join(", ") || item.paths.join(", ")}`);
|
|
894
|
+
console.log(` Action: ${item.next_action}`);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
if (!result.ok)
|
|
899
|
+
process.exitCode = 2;
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
if (command === "memory-audit" || command === "audit-log") {
|
|
903
|
+
const result = (0, kernel_js_1.kageMemoryAudit)(projectArg(args), numberArg(args, "--limit", 100));
|
|
904
|
+
if (args.includes("--json")) {
|
|
905
|
+
console.log(JSON.stringify(result, null, 2));
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
console.log(`Kage memory audit: ${result.totals.total} mutation${result.totals.total === 1 ? "" : "s"}`);
|
|
909
|
+
console.log(`Capture / feedback / supersede: ${result.totals.capture} / ${result.totals.feedback} / ${result.totals.supersede}`);
|
|
910
|
+
for (const entry of result.entries.slice(0, 12)) {
|
|
911
|
+
console.log(`- ${entry.operation}: ${entry.packet_titles.join(", ") || entry.packet_ids.join(", ")} (${entry.timestamp.slice(0, 19)})`);
|
|
912
|
+
}
|
|
913
|
+
if (!result.entries.length)
|
|
914
|
+
console.log("No memory mutations have been audited yet.");
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
if (command === "capabilities" || command === "capability-audit" || command === "readiness") {
|
|
918
|
+
const result = (0, kernel_js_1.kageCapabilityAudit)(projectArg(args));
|
|
919
|
+
if (args.includes("--json")) {
|
|
920
|
+
console.log(JSON.stringify(result, null, 2));
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
console.log(`Kage capability audit: ${result.overall_score}/100 (${result.status})`);
|
|
924
|
+
console.log(result.summary);
|
|
925
|
+
for (const pillar of result.pillars) {
|
|
926
|
+
console.log(`\n${pillar.label}: ${pillar.score}/100 (${pillar.status})`);
|
|
927
|
+
for (const item of pillar.evidence.slice(0, 4))
|
|
928
|
+
console.log(` - ${item.label}: ${item.value}`);
|
|
929
|
+
if (pillar.gaps.length)
|
|
930
|
+
console.log(` Gap: ${pillar.gaps[0]}`);
|
|
931
|
+
if (pillar.actions.length)
|
|
932
|
+
console.log(` Action: ${pillar.actions[0]}`);
|
|
933
|
+
}
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if (command === "slots" || command === "context-slots") {
|
|
937
|
+
const action = args[1] && !args[1].startsWith("--") ? args[1] : undefined;
|
|
938
|
+
if (!action || action === "list") {
|
|
939
|
+
const result = (0, kernel_js_1.kageContextSlots)(projectArg(args));
|
|
940
|
+
if (args.includes("--json")) {
|
|
941
|
+
console.log(JSON.stringify(result, null, 2));
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
console.log(`Kage pinned context slots: ${result.summary}`);
|
|
945
|
+
for (const slot of result.slots) {
|
|
946
|
+
console.log(`- ${slot.label}${slot.pinned ? " [pinned]" : ""}: ${slot.description || "(no description)"}`);
|
|
947
|
+
console.log(` ${slot.content.slice(0, 160)}${slot.content.length > 160 ? "..." : ""}`);
|
|
948
|
+
}
|
|
949
|
+
if (!result.slots.length)
|
|
950
|
+
console.log("No slots yet. Add one with `kage slots set --label project_context --content \"...\" --project .`.");
|
|
951
|
+
if (result.warnings.length)
|
|
952
|
+
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
if (action === "set") {
|
|
956
|
+
const label = takeArg(args, "--label");
|
|
957
|
+
const content = takeArg(args, "--content");
|
|
958
|
+
if (!label || !content)
|
|
959
|
+
usage();
|
|
960
|
+
const result = (0, kernel_js_1.setContextSlot)(projectArg(args), {
|
|
961
|
+
label,
|
|
962
|
+
content,
|
|
963
|
+
description: takeArg(args, "--description"),
|
|
964
|
+
pinned: !args.includes("--unpinned"),
|
|
965
|
+
size_limit: numberArg(args, "--size-limit", 2000),
|
|
966
|
+
paths: listArg(takeArg(args, "--paths")),
|
|
967
|
+
tags: listArg(takeArg(args, "--tags")),
|
|
968
|
+
});
|
|
969
|
+
if (args.includes("--json")) {
|
|
970
|
+
console.log(JSON.stringify(result, null, 2));
|
|
971
|
+
if (!result.ok)
|
|
972
|
+
process.exit(2);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
if (!result.ok) {
|
|
976
|
+
console.error(`Context slot not saved:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
977
|
+
process.exit(2);
|
|
978
|
+
}
|
|
979
|
+
console.log(`Saved context slot: ${result.slot?.label}`);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
if (action === "delete") {
|
|
983
|
+
const label = takeArg(args, "--label");
|
|
984
|
+
if (!label)
|
|
985
|
+
usage();
|
|
986
|
+
const result = (0, kernel_js_1.deleteContextSlot)(projectArg(args), label);
|
|
987
|
+
if (args.includes("--json")) {
|
|
988
|
+
console.log(JSON.stringify(result, null, 2));
|
|
989
|
+
if (!result.ok)
|
|
990
|
+
process.exit(2);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
if (!result.ok) {
|
|
994
|
+
console.error(`Context slot not deleted:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
995
|
+
process.exit(2);
|
|
996
|
+
}
|
|
997
|
+
console.log(`Deleted context slot: ${result.deleted?.label}`);
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
usage();
|
|
1001
|
+
}
|
|
1002
|
+
if (command === "handoff" || command === "memory-handoff") {
|
|
1003
|
+
const result = (0, kernel_js_1.kageMemoryHandoff)(projectArg(args));
|
|
1004
|
+
if (args.includes("--json")) {
|
|
1005
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
console.log(`Kage memory handoff: ${result.totals.open_items} open item${result.totals.open_items === 1 ? "" : "s"}, ${result.totals.distillable_sessions} distillable session${result.totals.distillable_sessions === 1 ? "" : "s"}, ${result.totals.recent_mutations} recent mutation${result.totals.recent_mutations === 1 ? "" : "s"}`);
|
|
1009
|
+
console.log(result.summary);
|
|
1010
|
+
console.log(`Primary action: ${result.primary_action.label} — ${result.primary_action.action}`);
|
|
1011
|
+
if (result.items.length) {
|
|
1012
|
+
console.log("\nNext actions:");
|
|
1013
|
+
for (const item of result.items.slice(0, 10)) {
|
|
1014
|
+
console.log(`- [${item.severity}] ${item.title}: ${item.summary}`);
|
|
1015
|
+
console.log(` ${item.action}`);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
if (result.recommendations.length) {
|
|
1019
|
+
console.log("\nRecommendations:");
|
|
1020
|
+
for (const item of result.recommendations.slice(0, 5))
|
|
1021
|
+
console.log(`- ${item}`);
|
|
1022
|
+
}
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
if (command === "timeline" || command === "memory-timeline") {
|
|
1026
|
+
const result = (0, kernel_js_1.kageMemoryTimeline)(projectArg(args), numberArg(args, "--days", 14));
|
|
1027
|
+
if (args.includes("--json")) {
|
|
1028
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
console.log(`Kage memory timeline: last ${result.days} day${result.days === 1 ? "" : "s"} — ${result.totals.total} event${result.totals.total === 1 ? "" : "s"}`);
|
|
1032
|
+
console.log(`Added / updated / pending / deprecated: ${result.totals.added} / ${result.totals.updated} / ${result.totals.pending} / ${result.totals.deprecated}`);
|
|
1033
|
+
for (const entry of result.entries.slice(0, 12)) {
|
|
1034
|
+
const prefix = entry.kind === "added" ? "+" : entry.kind === "updated" ? "~" : entry.kind === "pending" ? "?" : "-";
|
|
1035
|
+
console.log(` ${prefix} [${entry.type}] ${entry.title} (${entry.date.slice(0, 10)})`);
|
|
1036
|
+
}
|
|
1037
|
+
if (!result.entries.length)
|
|
1038
|
+
console.log("No memory activity in this period.");
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
if (command === "lineage" || command === "memory-lineage") {
|
|
1042
|
+
const result = (0, kernel_js_1.kageMemoryLineage)(projectArg(args));
|
|
1043
|
+
if (args.includes("--json")) {
|
|
1044
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
console.log(`Kage memory lineage: ${result.totals.chains} replacement chain${result.totals.chains === 1 ? "" : "s"}, ${result.totals.orphans} orphan${result.totals.orphans === 1 ? "" : "s"}`);
|
|
1048
|
+
for (const chain of result.chains.slice(0, 10)) {
|
|
1049
|
+
console.log(`- ${chain.current_title}: replaces ${chain.superseded_packet_ids.length} packet${chain.superseded_packet_ids.length === 1 ? "" : "s"}`);
|
|
1050
|
+
console.log(` ${chain.action}`);
|
|
1051
|
+
}
|
|
1052
|
+
if (result.orphans.length) {
|
|
1053
|
+
console.log("\nNeeds repair:");
|
|
1054
|
+
for (const orphan of result.orphans.slice(0, 10))
|
|
1055
|
+
console.log(`- ${orphan.title}: ${orphan.action}`);
|
|
1056
|
+
}
|
|
1057
|
+
if (!result.chains.length && !result.orphans.length)
|
|
1058
|
+
console.log("No superseded memory chains yet.");
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
if (command === "supersede") {
|
|
1062
|
+
const oldId = takeArg(args, "--packet");
|
|
1063
|
+
const replacementId = takeArg(args, "--replacement");
|
|
1064
|
+
if (!oldId || !replacementId)
|
|
1065
|
+
usage();
|
|
1066
|
+
const result = (0, kernel_js_1.supersedeMemory)(projectArg(args), oldId, replacementId, takeArg(args, "--reason") ?? "");
|
|
1067
|
+
if (args.includes("--json")) {
|
|
1068
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
if (!result.ok) {
|
|
1072
|
+
console.error(`Failed to supersede memory: ${result.errors.join("; ")}`);
|
|
1073
|
+
process.exit(1);
|
|
1074
|
+
}
|
|
1075
|
+
console.log(`Superseded memory: ${result.old_packet_id}`);
|
|
1076
|
+
console.log(`Replacement: ${result.replacement_packet_id}`);
|
|
1077
|
+
if (result.warnings.length)
|
|
1078
|
+
console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
|
|
778
1079
|
return;
|
|
779
1080
|
}
|
|
780
1081
|
if (command === "module-health") {
|
|
@@ -935,6 +1236,55 @@ async function main() {
|
|
|
935
1236
|
return;
|
|
936
1237
|
}
|
|
937
1238
|
if (command === "benchmark") {
|
|
1239
|
+
if (args.includes("--memory-quality")) {
|
|
1240
|
+
const result = (0, kernel_js_1.benchmarkCodingMemoryQuality)({
|
|
1241
|
+
topK: Number(takeArg(args, "--top-k") ?? 10),
|
|
1242
|
+
packetsPerTopic: Number(takeArg(args, "--packets-per-topic") ?? 5),
|
|
1243
|
+
distractorsPerTopic: Number(takeArg(args, "--distractors-per-topic") ?? 7),
|
|
1244
|
+
keep: args.includes("--keep"),
|
|
1245
|
+
});
|
|
1246
|
+
if (args.includes("--json")) {
|
|
1247
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
console.log("Kage Coding Memory Quality Benchmark");
|
|
1251
|
+
console.log(`Packets: ${result.summary.packets}`);
|
|
1252
|
+
console.log(`Queries: ${result.summary.queries}`);
|
|
1253
|
+
console.log(`Refresh/index: ${result.summary.refresh_ms}ms`);
|
|
1254
|
+
console.log(`R@5: ${result.summary.recall_at_5_percent ?? "n/a"}%`);
|
|
1255
|
+
console.log(`R@10: ${result.summary.recall_at_10_percent ?? "n/a"}%`);
|
|
1256
|
+
console.log(`NDCG@10: ${result.summary.ndcg_at_10}`);
|
|
1257
|
+
console.log(`MRR: ${result.summary.mrr}`);
|
|
1258
|
+
console.log(`Median recall: ${result.summary.median_latency_ms}ms`);
|
|
1259
|
+
console.log(`Context reduction: ${result.summary.context_reduction_percent}%`);
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
if (args.includes("--scale")) {
|
|
1263
|
+
const sizes = String(takeArg(args, "--sizes") ?? "240,1000,5000")
|
|
1264
|
+
.split(",")
|
|
1265
|
+
.map((value) => Number(value.trim()))
|
|
1266
|
+
.filter((value) => Number.isFinite(value) && value > 0);
|
|
1267
|
+
const result = (0, kernel_js_1.benchmarkMemoryScale)({
|
|
1268
|
+
sizes,
|
|
1269
|
+
topK: Number(takeArg(args, "--top-k") ?? 10),
|
|
1270
|
+
keep: args.includes("--keep"),
|
|
1271
|
+
});
|
|
1272
|
+
if (args.includes("--json")) {
|
|
1273
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
console.log("Kage Memory Scale Benchmark");
|
|
1277
|
+
console.log(`Sizes: ${result.sizes.join(", ")}`);
|
|
1278
|
+
console.log(`Top K: ${result.top_k}`);
|
|
1279
|
+
console.log(`Largest corpus: ${result.summary.largest_packets} packets`);
|
|
1280
|
+
console.log(`Hit rate: ${result.summary.largest_hit_rate_percent}%`);
|
|
1281
|
+
console.log(`Median recall: ${result.summary.largest_median_recall_latency_ms}ms`);
|
|
1282
|
+
console.log(`Context reduction: ${result.summary.largest_context_reduction_percent}%`);
|
|
1283
|
+
for (const row of result.results) {
|
|
1284
|
+
console.log(`- ${row.packets} packets: ${row.recall_hit_rate_percent}% hit, ${row.median_recall_latency_ms}ms median, ${row.context_reduction_percent}% context reduction`);
|
|
1285
|
+
}
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
938
1288
|
if (args.includes("--compare")) {
|
|
939
1289
|
const result = (0, kernel_js_1.benchmarkTaskComparison)(projectArg(args), takeArg(args, "--task") ?? firstPositional(args) ?? "how do I run tests");
|
|
940
1290
|
if (args.includes("--json")) {
|
|
@@ -1193,13 +1543,36 @@ async function main() {
|
|
|
1193
1543
|
const query = firstPositional(args);
|
|
1194
1544
|
if (!query)
|
|
1195
1545
|
usage();
|
|
1196
|
-
const result =
|
|
1546
|
+
const result = args.includes("--embeddings")
|
|
1547
|
+
? await (0, kernel_js_1.recallWithEmbeddings)(projectArg(args), query, 5, args.includes("--explain"))
|
|
1548
|
+
: (0, kernel_js_1.recall)(projectArg(args), query, 5, args.includes("--explain"));
|
|
1197
1549
|
if (args.includes("--json"))
|
|
1198
1550
|
console.log(JSON.stringify(result, null, 2));
|
|
1199
1551
|
else
|
|
1200
1552
|
console.log(result.context_block);
|
|
1201
1553
|
return;
|
|
1202
1554
|
}
|
|
1555
|
+
if (command === "embeddings") {
|
|
1556
|
+
const action = firstPositional(args);
|
|
1557
|
+
if (action !== "build")
|
|
1558
|
+
usage();
|
|
1559
|
+
const result = await (0, kernel_js_1.buildEmbeddingIndex)(projectArg(args), { model: takeArg(args, "--model") });
|
|
1560
|
+
if (args.includes("--json")) {
|
|
1561
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1562
|
+
if (!result.ok)
|
|
1563
|
+
process.exitCode = 2;
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
if (!result.ok) {
|
|
1567
|
+
console.error(`Embedding index failed:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
|
|
1568
|
+
process.exit(2);
|
|
1569
|
+
}
|
|
1570
|
+
console.log(`Embedding index: ${result.path}`);
|
|
1571
|
+
console.log(`Provider: ${result.provider}`);
|
|
1572
|
+
console.log(`Model: ${result.model}`);
|
|
1573
|
+
console.log(`Packets: ${result.packet_count}`);
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1203
1576
|
if (command === "observe") {
|
|
1204
1577
|
const event = takeArg(args, "--event");
|
|
1205
1578
|
if (!event)
|
|
@@ -1217,6 +1590,59 @@ async function main() {
|
|
|
1217
1590
|
}
|
|
1218
1591
|
return;
|
|
1219
1592
|
}
|
|
1593
|
+
if (command === "sessions") {
|
|
1594
|
+
const result = (0, kernel_js_1.kageSessionCaptureReport)(projectArg(args));
|
|
1595
|
+
if (args.includes("--json")) {
|
|
1596
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
console.log(`Sessions: ${result.totals.sessions}`);
|
|
1600
|
+
console.log(`Observations: ${result.totals.observations}`);
|
|
1601
|
+
console.log(`Distillable observations: ${result.totals.durable_observations}`);
|
|
1602
|
+
for (const session of result.sessions.slice(0, 10)) {
|
|
1603
|
+
console.log(`\n${session.session_id} — ${session.observations} observation${session.observations === 1 ? "" : "s"}, ${session.durable_observations} distillable`);
|
|
1604
|
+
console.log(` ${session.first_at || "unknown"} → ${session.last_at || "unknown"}`);
|
|
1605
|
+
if (session.candidate_types.length)
|
|
1606
|
+
console.log(` Candidates: ${session.candidate_types.join(", ")}`);
|
|
1607
|
+
console.log(` Next: ${session.next_action}`);
|
|
1608
|
+
}
|
|
1609
|
+
if (!result.sessions.length)
|
|
1610
|
+
console.log("No local observation sessions recorded yet.");
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
if (command === "replay" || command === "session-replay") {
|
|
1614
|
+
const result = (0, kernel_js_1.kageSessionReplay)(projectArg(args), {
|
|
1615
|
+
sessionId: takeArg(args, "--session"),
|
|
1616
|
+
limit: Number(takeArg(args, "--limit") ?? 200),
|
|
1617
|
+
});
|
|
1618
|
+
if (args.includes("--json")) {
|
|
1619
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
console.log(`Session replay digest: ${result.totals.sessions} session${result.totals.sessions === 1 ? "" : "s"}, ${result.totals.events} event${result.totals.events === 1 ? "" : "s"}`);
|
|
1623
|
+
console.log(`Durable candidates: ${result.totals.durable_candidates}`);
|
|
1624
|
+
for (const session of result.sessions.slice(0, 8)) {
|
|
1625
|
+
console.log(`\n${session.session_id} — ${session.events} event${session.events === 1 ? "" : "s"}, ${session.durable_candidates} durable candidate${session.durable_candidates === 1 ? "" : "s"}`);
|
|
1626
|
+
console.log(` ${session.first_at || "unknown"} → ${session.last_at || "unknown"}`);
|
|
1627
|
+
if (session.paths.length)
|
|
1628
|
+
console.log(` Paths: ${session.paths.slice(0, 4).join(", ")}`);
|
|
1629
|
+
if (session.commands.length)
|
|
1630
|
+
console.log(` Commands: ${session.commands.slice(0, 3).join(", ")}`);
|
|
1631
|
+
if (session.durable_candidates)
|
|
1632
|
+
console.log(` Next: ${session.distill_command}`);
|
|
1633
|
+
}
|
|
1634
|
+
if (result.events.length) {
|
|
1635
|
+
console.log("\nTimeline:");
|
|
1636
|
+
for (const event of result.events.slice(0, 20)) {
|
|
1637
|
+
const durable = event.durable_candidate ? ` [${event.candidate_type ?? "durable"}]` : "";
|
|
1638
|
+
console.log(` ${event.timestamp} ${event.label}${durable}: ${event.summary}`);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
console.log("No local observation events recorded yet.");
|
|
1643
|
+
}
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1220
1646
|
if (command === "distill") {
|
|
1221
1647
|
const sessionId = takeArg(args, "--session");
|
|
1222
1648
|
if (!sessionId)
|