@kage-core/kage-graph-mcp 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -2,18 +2,37 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const node_child_process_1 = require("node:child_process");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_os_1 = require("node:os");
7
+ const node_path_1 = require("node:path");
5
8
  const promises_1 = require("node:readline/promises");
6
9
  const node_process_1 = require("node:process");
7
10
  const daemon_js_1 = require("./daemon.js");
8
11
  const kernel_js_1 = require("./kernel.js");
9
12
  const graph_registry_js_1 = require("./graph-registry.js");
10
- function usage() {
11
- console.log(`Kage repo memory and code graph
13
+ const CORE_USAGE = `Kage — code-grounded memory for coding agents
14
+
15
+ Core commands:
16
+ kage demo 30-second trust demo (temp dir)
17
+ kage scan --project <dir> 60-second truth report on any repo (zero setup)
18
+ kage init --project <dir> create repo memory (.agent_memory only)
19
+ kage index --project <dir> [--full] build/refresh code graph + indexes
20
+ kage recall "<query>" --project <dir> grounded recall from repo memory
21
+ kage learn --project <dir> ... capture a learning as a memory packet
22
+ kage gains --project <dir> what Kage saved you (tokens, cost, stale blocks)
23
+ kage verify --project <dir> check memory citations against code
24
+ kage setup <agent> --project <dir> --write wire your agent (claude-code, codex, cursor, ...)
25
+ kage doctor --project <dir> health check
26
+ kage viewer --project <dir> local dashboard
27
+
28
+ Run 'kage help --all' for the full command list (lifecycle, CI, benchmarks, daemon, workspace).`;
29
+ const FULL_USAGE = `Kage — full command reference
12
30
 
13
31
  Usage:
14
32
  kage index --project <dir>
33
+ kage scan --project <dir> [--json]
15
34
  kage demo [--project <dir>]
16
- kage init --project <dir>
35
+ kage init --project <dir> [--with-policy]
17
36
  kage policy --project <dir>
18
37
  kage doctor --project <dir>
19
38
  kage setup list
@@ -35,9 +54,11 @@ Usage:
35
54
  kage suppressed --project <dir> [--json]
36
55
  kage pr summarize --project <dir> [--json]
37
56
  kage pr check --project <dir> [--json]
57
+ kage staleguard --project <dir> [--json]
38
58
  kage upgrade [--dry-run]
39
59
  kage branch --project <dir> [--json]
40
60
  kage metrics --project <dir> [--json]
61
+ kage gains --project <dir> [--json]
41
62
  kage memory-access --project <dir> [--json]
42
63
  kage activity --project <dir> [--json]
43
64
  kage memory-audit --project <dir> [--limit <n>] [--json]
@@ -93,23 +114,30 @@ Usage:
93
114
  kage promote --project <dir> --public <packet-id>
94
115
  kage export-public --project <dir>
95
116
  kage registry --project <dir> [--json]
96
- kage marketplace --project <dir> [--json]
97
- kage org status --project <dir> --org <org> [--json]
98
- kage org upload --project <dir> --org <org> --packet <approved-packet-id>
99
- kage org review --project <dir> --org <org> --packet <org-packet-id> --approve|--reject
100
- kage org recall "<query>" --project <dir> --org <org> [--json]
101
- kage org export --project <dir> --org <org> [--json]
102
- kage layered-recall "<query>" --project <dir> [--org <org>] [--global] [--json]
103
- kage global build --project <dir> [--org <org>] [--json]
104
117
  kage changelog --project <dir> [--days <n>] [--json]
105
118
  kage review --project <dir>
106
119
  kage validate --project <dir>
107
120
 
108
121
  Types:
109
- ${kernel_js_1.MEMORY_TYPES.join(", ")}
110
- `);
122
+ ${kernel_js_1.MEMORY_TYPES.join(", ")}`;
123
+ function usage() {
124
+ console.log(CORE_USAGE);
111
125
  process.exit(1);
112
126
  }
127
+ // Stale-catch lines lead with color when attached to a terminal so the
128
+ // retention heartbeat is impossible to miss; plain text otherwise (CI, pipes).
129
+ function printStaleCatch(result) {
130
+ const useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
131
+ const [headline, ...rest] = (0, kernel_js_1.formatStaleCatch)(result);
132
+ if (!useColor) {
133
+ console.log([headline, ...rest].join("\n"));
134
+ return;
135
+ }
136
+ const tint = result.invalidated.length ? "\u001b[33m" : "\u001b[32m";
137
+ console.log(`${tint}${headline}\u001b[0m`);
138
+ if (rest.length)
139
+ console.log(rest.join("\n"));
140
+ }
113
141
  function takeArg(args, name) {
114
142
  const index = args.indexOf(name);
115
143
  if (index === -1)
@@ -170,6 +198,11 @@ async function main() {
170
198
  const command = args[0];
171
199
  if (!command)
172
200
  usage();
201
+ if (command === "help") {
202
+ console.log(args.includes("--all") ? FULL_USAGE : CORE_USAGE);
203
+ return;
204
+ }
205
+ await (0, kernel_js_1.ensureTreeSitterLanguages)();
173
206
  if (command === "index") {
174
207
  const result = (0, kernel_js_1.indexProject)(projectArg(args));
175
208
  console.log(`Indexed ${result.projectDir}`);
@@ -180,15 +213,54 @@ async function main() {
180
213
  console.log(`Indexes:\n${result.indexes.map((path) => ` - ${path}`).join("\n")}`);
181
214
  return;
182
215
  }
216
+ if (command === "scan") {
217
+ const result = (0, kernel_js_1.truthReport)(projectArg(args));
218
+ if (args.includes("--json")) {
219
+ console.log(JSON.stringify(result, null, 2));
220
+ return;
221
+ }
222
+ console.log(`Kage Truth Report — ${result.project_dir}`);
223
+ console.log(`Scanned ${result.totals.files_scanned} files, ${result.totals.symbols_scanned} symbols${result.totals.docs_scanned ? `, ${result.totals.docs_scanned} doc file(s)` : ""}\n`);
224
+ console.log(` ${result.headline}\n`);
225
+ const sections = [
226
+ { kind: "duplicate_cluster", heading: "DUPLICATE IMPLEMENTATIONS", count: result.totals.duplicate_clusters },
227
+ { kind: "ghost_export", heading: "GHOST KNOWLEDGE — exported, never called", count: result.totals.ghost_exports },
228
+ { kind: "bus_factor", heading: "BUS FACTOR 1 — one head holds it all", count: result.totals.bus_factor_files },
229
+ { kind: "knowledge_void", heading: "KNOWLEDGE VOID — high churn, zero memory", count: result.totals.knowledge_voids },
230
+ { kind: "doc_lie", heading: "DOC LIES — the README vs reality", count: result.totals.doc_lies },
231
+ ];
232
+ for (const section of sections) {
233
+ const items = result.findings.filter((finding) => finding.kind === section.kind);
234
+ if (!items.length)
235
+ continue;
236
+ console.log(`■ ${section.heading} (${section.count}${section.count > items.length ? `, showing top ${items.length}` : ""})`);
237
+ for (const finding of items) {
238
+ console.log(` • ${finding.title}`);
239
+ console.log(` ${finding.detail}`);
240
+ for (const evidence of finding.evidence)
241
+ console.log(` ${evidence}`);
242
+ }
243
+ console.log("");
244
+ }
245
+ if (!result.findings.length)
246
+ console.log("No surprising findings — this repo's knowledge is unusually well distributed.\n");
247
+ if (result.warnings.length)
248
+ console.log(`Warnings:\n${result.warnings.map((warning) => ` - ${warning}`).join("\n")}\n`);
249
+ console.log("Fix the void:");
250
+ for (const action of result.next_actions)
251
+ console.log(` ${action}`);
252
+ return;
253
+ }
183
254
  if (command === "demo") {
184
- const demoDir = takeArg(args, "--project") ?? `${process.cwd()}/kage-demo`;
255
+ // Default to a temp dir: the demo must never write into the user's cwd uninvited.
256
+ const demoDir = takeArg(args, "--project") ?? (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "kage-demo-"));
185
257
  const result = (0, kernel_js_1.runDemo)(demoDir);
186
258
  if (args.includes("--json")) {
187
259
  console.log(JSON.stringify(result, null, 2));
188
260
  return;
189
261
  }
190
262
  console.log("Kage demo — can you trust your agent's memory?\n");
191
- console.log(`Seeded ${result.captured.length} grounded memories in ${result.project_dir}\n`);
263
+ console.log(`Seeded ${result.captured.length} grounded memories in a throwaway project (${result.project_dir})\n`);
192
264
  console.log("1. Hallucinated citation — REJECTED on write:");
193
265
  if (result.rejected_hallucination) {
194
266
  console.log(` ✗ "${result.rejected_hallucination.title}"`);
@@ -201,23 +273,40 @@ async function main() {
201
273
  for (const t of result.recalled)
202
274
  console.log(` ✓ ${t}`);
203
275
  console.log(`\nTrust score: ${result.trust_score}/100`);
204
- console.log(`\nSee it in the viewer: ${result.viewer_command}`);
276
+ console.log("\nNext, in your own repo:");
277
+ console.log(" kage init --project . create repo memory");
278
+ console.log(" kage setup <agent> --project . --write wire your agent (claude-code, codex, cursor, ...)");
279
+ console.log(" kage viewer --project . see the dashboard");
205
280
  return;
206
281
  }
207
282
  if (command === "init") {
208
- const result = (0, kernel_js_1.initProject)(projectArg(args));
283
+ const withPolicy = args.includes("--with-policy");
284
+ const result = (0, kernel_js_1.initProject)(projectArg(args), { policy: withPolicy });
209
285
  console.log(`Initialized Kage memory for ${result.index.projectDir}`);
210
- console.log(`Packets: ${result.index.packets}`);
211
- console.log(`Migrated legacy nodes: ${result.index.migrated}`);
212
- if (result.index.policyPath)
213
- console.log(`Agent policy: ${result.index.policyPath}`);
286
+ console.log("\nCreated:");
287
+ console.log(" .agent_memory/ memory packets + indexes (only directory Kage owns)");
288
+ if (result.policyInstalled) {
289
+ console.log(" AGENTS.md, CLAUDE.md agent policy (requested via --with-policy)");
290
+ console.log(" .claude/settings.json allowed kage tools (requested via --with-policy)");
291
+ }
292
+ console.log(`\nPackets: ${result.index.packets}`);
293
+ if (result.index.migrated)
294
+ console.log(`Migrated legacy nodes: ${result.index.migrated}`);
214
295
  console.log(result.validation.ok ? "Validation passed." : "Validation failed.");
215
296
  if (result.validation.errors.length)
216
297
  console.log(`Errors:\n${result.validation.errors.map((error) => ` - ${error}`).join("\n")}`);
217
298
  if (result.validation.warnings.length)
218
299
  console.log(`Warnings:\n${result.validation.warnings.map((warning) => ` - ${warning}`).join("\n")}`);
219
- console.log("\nFirst recall preview:\n");
220
- console.log(result.sampleRecall.context_block);
300
+ console.log("\nTip version control:");
301
+ console.log(" commit .agent_memory/packets/ (your team's reviewed memory)");
302
+ console.log(" ignore .agent_memory/indexes/ .agent_memory/reports/ (regenerated)");
303
+ if (!result.policyInstalled) {
304
+ console.log("\nNot written (opt-in): agent policy files. Add them with `kage policy --project .`");
305
+ console.log("or rerun `kage init --with-policy` when you're ready to commit them.");
306
+ }
307
+ console.log("\nNext:");
308
+ console.log(" kage setup <agent> --project . --write wire your agent (claude-code, codex, cursor, ...)");
309
+ console.log(" kage viewer --project . see the dashboard");
221
310
  if (!result.validation.ok)
222
311
  process.exit(2);
223
312
  return;
@@ -570,6 +659,10 @@ async function main() {
570
659
  process.exit(2);
571
660
  return;
572
661
  }
662
+ // The stale-catch moment comes first: the human-readable heartbeat that a
663
+ // change just invalidated team memory beats the mechanical check output.
664
+ printStaleCatch((0, kernel_js_1.staleCatch)(projectArg(args)));
665
+ console.log("");
573
666
  console.log(`PR memory check for ${result.project_dir}`);
574
667
  console.log(`Branch: ${result.branch ?? "(detached)"}`);
575
668
  console.log(`Changed files: ${result.changed_files.length}`);
@@ -588,6 +681,18 @@ async function main() {
588
681
  }
589
682
  usage();
590
683
  }
684
+ if (command === "staleguard") {
685
+ // Lightweight stale-catch for pre-commit/pre-push hooks: no graph builds,
686
+ // no validation — just "did this change invalidate team memory?". Advisory
687
+ // by design (exit 0) so it informs the commit instead of blocking it.
688
+ const result = (0, kernel_js_1.staleCatch)(projectArg(args));
689
+ if (args.includes("--json")) {
690
+ console.log(JSON.stringify(result, null, 2));
691
+ return;
692
+ }
693
+ printStaleCatch(result);
694
+ return;
695
+ }
591
696
  if (command === "upgrade") {
592
697
  const commandLine = "npm install -g @kage-core/kage-graph-mcp@latest";
593
698
  if (args.includes("--dry-run")) {
@@ -960,6 +1065,30 @@ async function main() {
960
1065
  }
961
1066
  return;
962
1067
  }
1068
+ if (command === "gains") {
1069
+ const summary = (0, kernel_js_1.valueSummary)(projectArg(args));
1070
+ if (args.includes("--json")) {
1071
+ console.log(JSON.stringify(summary, null, 2));
1072
+ return;
1073
+ }
1074
+ const plural = (count, singular, pluralForm) => (count === 1 ? singular : pluralForm);
1075
+ const week = summary.last_7d;
1076
+ if (!summary.all_time.recalls && !summary.all_time.stale_withheld && !summary.all_time.stale_caught && !summary.all_time.caller_answers) {
1077
+ console.log("No value events recorded yet. Run kage recall (or let your agent call kage_context) and check back.");
1078
+ return;
1079
+ }
1080
+ console.log(`This week Kage saved you ~${(0, kernel_js_1.formatTokenCount)(week.tokens_saved)} tokens (~$${week.estimated_dollars.toFixed(2)}), ` +
1081
+ `blocked ${week.stale_withheld} stale ${plural(week.stale_withheld, "memory", "memories")}, ` +
1082
+ `caught ${week.stale_caught} stale at change-time, ` +
1083
+ `answered ${week.recalls} ${plural(week.recalls, "recall", "recalls")}.`);
1084
+ const windowLine = (label, window) => ` ${label} ~${(0, kernel_js_1.formatTokenCount)(window.tokens_saved)} tokens (~$${window.estimated_dollars.toFixed(2)}) · ` +
1085
+ `${window.stale_withheld} stale blocked · ${window.stale_caught} stale caught at change-time · ` +
1086
+ `${window.recalls} ${plural(window.recalls, "recall", "recalls")} · ` +
1087
+ `${window.caller_answers} caller ${plural(window.caller_answers, "answer", "answers")}`;
1088
+ console.log(windowLine("Today: ", summary.today));
1089
+ console.log(windowLine("All time:", summary.all_time));
1090
+ return;
1091
+ }
963
1092
  if (command === "memory-access") {
964
1093
  const result = (0, kernel_js_1.kageMemoryAccess)(projectArg(args));
965
1094
  if (args.includes("--json")) {
@@ -1588,119 +1717,6 @@ async function main() {
1588
1717
  }
1589
1718
  return;
1590
1719
  }
1591
- if (command === "marketplace") {
1592
- const result = (0, kernel_js_1.buildMarketplace)(projectArg(args));
1593
- if (args.includes("--json")) {
1594
- console.log(JSON.stringify(result, null, 2));
1595
- return;
1596
- }
1597
- console.log(`Marketplace manifest: ${result.path}`);
1598
- console.log(`Packs: ${result.packs.length}`);
1599
- for (const pack of result.packs) {
1600
- console.log(`- ${pack.id} [${pack.kind}] ${pack.title} (${pack.install})`);
1601
- }
1602
- return;
1603
- }
1604
- if (command === "org") {
1605
- const action = args[1];
1606
- const org = takeArg(args, "--org") ?? "local";
1607
- const projectDir = projectArg(args);
1608
- if (action === "status") {
1609
- const result = (0, kernel_js_1.orgStatus)(projectDir, org);
1610
- if (args.includes("--json"))
1611
- console.log(JSON.stringify(result, null, 2));
1612
- else {
1613
- console.log(`Org memory: ${result.org}`);
1614
- console.log(`Path: ${result.path}`);
1615
- console.log(`Inbox: ${result.inbox}`);
1616
- console.log(`Approved: ${result.approved}`);
1617
- console.log(`Rejected: ${result.rejected}`);
1618
- console.log(`Audit events: ${result.audit_events}`);
1619
- if (result.registry_path)
1620
- console.log(`Registry: ${result.registry_path}`);
1621
- }
1622
- return;
1623
- }
1624
- if (action === "upload") {
1625
- const id = takeArg(args, "--packet");
1626
- if (!id)
1627
- usage();
1628
- const result = (0, kernel_js_1.orgUploadPacket)(projectDir, org, id);
1629
- if (!result.ok) {
1630
- console.error(`Org upload blocked:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
1631
- process.exit(2);
1632
- }
1633
- console.log(`Created org review candidate: ${result.path}`);
1634
- console.log("Approve explicitly with: kage org review --approve");
1635
- return;
1636
- }
1637
- if (action === "review") {
1638
- const id = takeArg(args, "--packet");
1639
- if (!id || (!args.includes("--approve") && !args.includes("--reject")))
1640
- usage();
1641
- const result = (0, kernel_js_1.orgReviewPacket)(projectDir, org, id, args.includes("--approve") ? "approve" : "reject");
1642
- if (!result.ok) {
1643
- console.error(`Org review failed:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
1644
- process.exit(2);
1645
- }
1646
- console.log(`Org review wrote: ${result.path}`);
1647
- return;
1648
- }
1649
- if (action === "recall") {
1650
- const query = firstPositional(args.slice(1));
1651
- if (!query)
1652
- usage();
1653
- const result = (0, kernel_js_1.orgRecall)(projectDir, org, query);
1654
- if (args.includes("--json"))
1655
- console.log(JSON.stringify(result, null, 2));
1656
- else
1657
- console.log(result.context_block);
1658
- return;
1659
- }
1660
- if (action === "export") {
1661
- const result = (0, kernel_js_1.exportOrgRegistry)(projectDir, org);
1662
- if (args.includes("--json"))
1663
- console.log(JSON.stringify(result, null, 2));
1664
- else
1665
- console.log(`Exported org registry: ${result.registry_path}`);
1666
- return;
1667
- }
1668
- usage();
1669
- }
1670
- if (command === "layered-recall") {
1671
- const query = firstPositional(args);
1672
- if (!query)
1673
- usage();
1674
- const result = (0, kernel_js_1.layeredRecall)(projectArg(args), query, {
1675
- org: takeArg(args, "--org"),
1676
- includeGlobal: args.includes("--global"),
1677
- });
1678
- if (args.includes("--json"))
1679
- console.log(JSON.stringify(result, null, 2));
1680
- else
1681
- console.log(result.context_block);
1682
- return;
1683
- }
1684
- if (command === "global") {
1685
- const action = args[1];
1686
- if (action !== "build")
1687
- usage();
1688
- const result = (0, kernel_js_1.buildGlobalCdnBundle)(projectArg(args), takeArg(args, "--org") ?? "local");
1689
- if (args.includes("--json")) {
1690
- console.log(JSON.stringify(result, null, 2));
1691
- return;
1692
- }
1693
- if (!result.ok) {
1694
- console.error(`Global bundle failed:\n${result.errors.map((error) => ` - ${error}`).join("\n")}`);
1695
- process.exit(2);
1696
- }
1697
- console.log(`Global registry: ${result.manifest_path}`);
1698
- console.log(`Latest alias: ${result.alias_path}`);
1699
- console.log(`Marketplace: ${result.marketplace_path}`);
1700
- console.log(`Public packets: ${result.packet_count}`);
1701
- console.log(`Marketplace packs: ${result.marketplace_packs}`);
1702
- return;
1703
- }
1704
1720
  if (command === "recall") {
1705
1721
  const query = firstPositional(args);
1706
1722
  if (!query)
@@ -1712,8 +1728,12 @@ async function main() {
1712
1728
  : (0, kernel_js_1.recall)(projectArg(args), query, 5, args.includes("--explain"), { maxContextTokens, structuralHops });
1713
1729
  if (args.includes("--json"))
1714
1730
  console.log(JSON.stringify(result, null, 2));
1715
- else
1731
+ else {
1716
1732
  console.log(result.context_block);
1733
+ if (result.value_receipt) {
1734
+ console.log(`\n↳ saved ~${(0, kernel_js_1.formatTokenCount)(result.value_receipt.tokens_saved)} tokens vs reading source · ${result.value_receipt.stale_withheld} stale withheld`);
1735
+ }
1736
+ }
1717
1737
  return;
1718
1738
  }
1719
1739
  if (command === "embeddings") {
package/dist/daemon.js CHANGED
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.viewerStaticHeaders = viewerStaticHeaders;
4
4
  exports.viewerRedirectLocation = viewerRedirectLocation;
5
+ exports.viewerReportPaths = viewerReportPaths;
6
+ exports.viewerUrl = viewerUrl;
5
7
  exports.viewerBenchmarkReport = viewerBenchmarkReport;
6
8
  exports.daemonContextReport = daemonContextReport;
7
9
  exports.readDaemonStatus = readDaemonStatus;
@@ -63,6 +65,52 @@ function viewerRedirectLocation(pathname, search, fallbackSearch) {
63
65
  return null;
64
66
  return `/viewer/index.html${search || fallbackSearch}`;
65
67
  }
68
+ // Every report file the dashboard reads, keyed by its query-string param name.
69
+ // `value` points at the cumulative value ledger written by recall — it is read-only
70
+ // here and must never be regenerated, or the all-time savings history is lost.
71
+ function viewerReportPaths(projectRoot) {
72
+ const agentDir = (0, node_path_1.join)(projectRoot, ".agent_memory");
73
+ const reportsDir = (0, node_path_1.join)(agentDir, "reports");
74
+ return {
75
+ graph: (0, node_path_1.join)(agentDir, "graph", "graph.json"),
76
+ code: (0, node_path_1.join)(agentDir, "code_graph", "graph.json"),
77
+ metrics: (0, node_path_1.join)(agentDir, "metrics.json"),
78
+ inbox: (0, node_path_1.join)(agentDir, "inbox.json"),
79
+ review: (0, node_path_1.join)(agentDir, "review", "memory-review.md"),
80
+ pending: (0, node_path_1.join)(agentDir, "pending"),
81
+ quality: (0, node_path_1.join)(reportsDir, "quality.json"),
82
+ benchmark: (0, node_path_1.join)(reportsDir, "benchmark.json"),
83
+ contributors: (0, node_path_1.join)(reportsDir, "contributors.json"),
84
+ profile: (0, node_path_1.join)(reportsDir, "profile.json"),
85
+ xray: (0, node_path_1.join)(reportsDir, "xray.json"),
86
+ capabilities: (0, node_path_1.join)(reportsDir, "capabilities.json"),
87
+ slots: (0, node_path_1.join)(reportsDir, "context-slots.json"),
88
+ decisions: (0, node_path_1.join)(reportsDir, "decisions.json"),
89
+ risk: (0, node_path_1.join)(reportsDir, "risk.json"),
90
+ moduleHealth: (0, node_path_1.join)(reportsDir, "module-health.json"),
91
+ graphInsights: (0, node_path_1.join)(reportsDir, "graph-insights.json"),
92
+ workspace: (0, node_path_1.join)(reportsDir, "workspace.json"),
93
+ sessions: (0, node_path_1.join)(reportsDir, "sessions.json"),
94
+ replay: (0, node_path_1.join)(reportsDir, "replay.json"),
95
+ memoryAccess: (0, node_path_1.join)(reportsDir, "memory-access.json"),
96
+ memoryAudit: (0, node_path_1.join)(reportsDir, "memory-audit.json"),
97
+ handoff: (0, node_path_1.join)(reportsDir, "handoff.json"),
98
+ lifecycle: (0, node_path_1.join)(reportsDir, "lifecycle.json"),
99
+ activity: (0, node_path_1.join)(reportsDir, "activity.json"),
100
+ timeline: (0, node_path_1.join)(reportsDir, "timeline.json"),
101
+ lineage: (0, node_path_1.join)(reportsDir, "lineage.json"),
102
+ setup: (0, node_path_1.join)(reportsDir, "setup.json"),
103
+ trust: (0, node_path_1.join)(reportsDir, "trust.json"),
104
+ suppressed: (0, node_path_1.join)(reportsDir, "suppressed.json"),
105
+ value: (0, node_path_1.join)(reportsDir, "value.json"),
106
+ };
107
+ }
108
+ function viewerUrl(host, port, projectRoot) {
109
+ const query = Object.entries(viewerReportPaths(projectRoot))
110
+ .map(([name, path]) => `${name}=${encodeURIComponent(path)}`)
111
+ .join("&");
112
+ return `http://${host}:${port}/viewer/index.html?${query}&view=code`;
113
+ }
66
114
  function viewerBenchmarkReport(projectDir) {
67
115
  const gates = (0, kernel_js_1.benchmarkProject)(projectDir);
68
116
  const memoryQuality = (0, kernel_js_1.benchmarkCodingMemoryQuality)();
@@ -545,73 +593,46 @@ async function startViewer(projectDir, options = {}) {
545
593
  const viewerDir = (0, node_path_1.resolve)(__dirname, "..", "viewer");
546
594
  const threeDir = (0, node_path_1.resolve)(__dirname, "..", "node_modules", "three");
547
595
  const projectRoot = (0, node_path_1.resolve)(projectDir);
548
- const graphPath = (0, node_path_1.join)(projectRoot, ".agent_memory", "graph", "graph.json");
549
- const codePath = (0, node_path_1.join)(projectRoot, ".agent_memory", "code_graph", "graph.json");
550
- const metricsPath = (0, node_path_1.join)(projectRoot, ".agent_memory", "metrics.json");
551
- const inboxPath = (0, node_path_1.join)(projectRoot, ".agent_memory", "inbox.json");
552
- const reviewPath = (0, node_path_1.join)(projectRoot, ".agent_memory", "review", "memory-review.md");
553
- const pendingDir = (0, node_path_1.join)(projectRoot, ".agent_memory", "pending");
596
+ const reports = viewerReportPaths(projectRoot);
554
597
  const reportsDir = (0, node_path_1.join)(projectRoot, ".agent_memory", "reports");
555
- const qualityPath = (0, node_path_1.join)(reportsDir, "quality.json");
556
- const benchmarkPath = (0, node_path_1.join)(reportsDir, "benchmark.json");
557
- const contributorsPath = (0, node_path_1.join)(reportsDir, "contributors.json");
558
- const profilePath = (0, node_path_1.join)(reportsDir, "profile.json");
559
- const xrayPath = (0, node_path_1.join)(reportsDir, "xray.json");
560
- const capabilitiesPath = (0, node_path_1.join)(reportsDir, "capabilities.json");
561
- const slotsPath = (0, node_path_1.join)(reportsDir, "context-slots.json");
562
- const decisionsPath = (0, node_path_1.join)(reportsDir, "decisions.json");
563
- const riskPath = (0, node_path_1.join)(reportsDir, "risk.json");
564
- const moduleHealthPath = (0, node_path_1.join)(reportsDir, "module-health.json");
565
- const graphInsightsPath = (0, node_path_1.join)(reportsDir, "graph-insights.json");
566
- const workspacePath = (0, node_path_1.join)(reportsDir, "workspace.json");
567
- const sessionsPath = (0, node_path_1.join)(reportsDir, "sessions.json");
568
- const replayPath = (0, node_path_1.join)(reportsDir, "replay.json");
569
- const memoryAccessPath = (0, node_path_1.join)(reportsDir, "memory-access.json");
570
- const memoryAuditPath = (0, node_path_1.join)(reportsDir, "memory-audit.json");
571
- const handoffPath = (0, node_path_1.join)(reportsDir, "handoff.json");
572
- const lifecyclePath = (0, node_path_1.join)(reportsDir, "lifecycle.json");
573
- const activityPath = (0, node_path_1.join)(reportsDir, "activity.json");
574
- const timelinePath = (0, node_path_1.join)(reportsDir, "timeline.json");
575
- const lineagePath = (0, node_path_1.join)(reportsDir, "lineage.json");
576
- const setupPath = (0, node_path_1.join)(reportsDir, "setup.json");
577
- const trustPath = (0, node_path_1.join)(reportsDir, "trust.json");
578
- const suppressedPath = (0, node_path_1.join)(reportsDir, "suppressed.json");
579
598
  // Pre-generate lightweight JSON reports so the viewer can load them directly.
599
+ // Note: reports.value (the cumulative value ledger written by recall) is served
600
+ // as-is and intentionally never regenerated here.
580
601
  try {
581
602
  (0, node_fs_1.mkdirSync)(reportsDir, { recursive: true });
582
603
  const metrics = (0, kernel_js_1.kageMetrics)(projectDir);
583
- (0, node_fs_1.writeFileSync)(metricsPath, JSON.stringify(metrics, null, 2));
604
+ (0, node_fs_1.writeFileSync)(reports.metrics, JSON.stringify(metrics, null, 2));
584
605
  const inbox = (0, kernel_js_1.memoryInbox)(projectDir);
585
- (0, node_fs_1.writeFileSync)(inboxPath, JSON.stringify(inbox, null, 2));
586
- (0, node_fs_1.writeFileSync)(qualityPath, JSON.stringify((0, kernel_js_1.qualityReport)(projectDir), null, 2));
587
- (0, node_fs_1.writeFileSync)(benchmarkPath, JSON.stringify(viewerBenchmarkReport(projectDir), null, 2));
588
- (0, node_fs_1.writeFileSync)(contributorsPath, JSON.stringify((0, kernel_js_1.kageContributors)(projectDir), null, 2));
589
- (0, node_fs_1.writeFileSync)(profilePath, JSON.stringify((0, kernel_js_1.kageProjectProfile)(projectDir), null, 2));
590
- (0, node_fs_1.writeFileSync)(xrayPath, JSON.stringify((0, kernel_js_1.kageRepoXray)(projectDir), null, 2));
591
- (0, node_fs_1.writeFileSync)(capabilitiesPath, JSON.stringify((0, kernel_js_1.kageCapabilityAudit)(projectDir), null, 2));
592
- (0, node_fs_1.writeFileSync)(slotsPath, JSON.stringify((0, kernel_js_1.kageContextSlots)(projectDir), null, 2));
593
- (0, node_fs_1.writeFileSync)(decisionsPath, JSON.stringify((0, kernel_js_1.kageDecisionIntelligence)(projectDir), null, 2));
594
- (0, node_fs_1.writeFileSync)(riskPath, JSON.stringify((0, kernel_js_1.kageRisk)(projectDir), null, 2));
595
- (0, node_fs_1.writeFileSync)(moduleHealthPath, JSON.stringify((0, kernel_js_1.kageModuleHealth)(projectDir), null, 2));
596
- (0, node_fs_1.writeFileSync)(graphInsightsPath, JSON.stringify((0, kernel_js_1.kageGraphInsights)(projectDir), null, 2));
597
- (0, node_fs_1.writeFileSync)(workspacePath, JSON.stringify((0, kernel_js_1.kageWorkspace)(projectDir), null, 2));
598
- (0, node_fs_1.writeFileSync)(sessionsPath, JSON.stringify((0, kernel_js_1.kageSessionCaptureReport)(projectDir), null, 2));
599
- (0, node_fs_1.writeFileSync)(replayPath, JSON.stringify((0, kernel_js_1.kageSessionReplay)(projectDir), null, 2));
600
- (0, node_fs_1.writeFileSync)(memoryAccessPath, JSON.stringify((0, kernel_js_1.kageMemoryAccess)(projectDir), null, 2));
601
- (0, node_fs_1.writeFileSync)(memoryAuditPath, JSON.stringify((0, kernel_js_1.kageMemoryAudit)(projectDir), null, 2));
602
- (0, node_fs_1.writeFileSync)(handoffPath, JSON.stringify((0, kernel_js_1.kageMemoryHandoff)(projectDir), null, 2));
603
- (0, node_fs_1.writeFileSync)(lifecyclePath, JSON.stringify((0, kernel_js_1.kageMemoryLifecycle)(projectDir), null, 2));
604
- (0, node_fs_1.writeFileSync)(activityPath, JSON.stringify((0, kernel_js_1.kageActivity)(projectDir), null, 2));
605
- (0, node_fs_1.writeFileSync)(timelinePath, JSON.stringify((0, kernel_js_1.kageMemoryTimeline)(projectDir), null, 2));
606
- (0, node_fs_1.writeFileSync)(lineagePath, JSON.stringify((0, kernel_js_1.kageMemoryLineage)(projectDir), null, 2));
607
- (0, node_fs_1.writeFileSync)(setupPath, JSON.stringify((0, kernel_js_1.setupDoctor)(projectDir), null, 2));
608
- (0, node_fs_1.writeFileSync)(trustPath, JSON.stringify((0, kernel_js_1.benchmarkTrust)(projectDir), null, 2));
609
- (0, node_fs_1.writeFileSync)(suppressedPath, JSON.stringify((0, kernel_js_1.kageSuppressedMemory)(projectDir), null, 2));
606
+ (0, node_fs_1.writeFileSync)(reports.inbox, JSON.stringify(inbox, null, 2));
607
+ (0, node_fs_1.writeFileSync)(reports.quality, JSON.stringify((0, kernel_js_1.qualityReport)(projectDir), null, 2));
608
+ (0, node_fs_1.writeFileSync)(reports.benchmark, JSON.stringify(viewerBenchmarkReport(projectDir), null, 2));
609
+ (0, node_fs_1.writeFileSync)(reports.contributors, JSON.stringify((0, kernel_js_1.kageContributors)(projectDir), null, 2));
610
+ (0, node_fs_1.writeFileSync)(reports.profile, JSON.stringify((0, kernel_js_1.kageProjectProfile)(projectDir), null, 2));
611
+ (0, node_fs_1.writeFileSync)(reports.xray, JSON.stringify((0, kernel_js_1.kageRepoXray)(projectDir), null, 2));
612
+ (0, node_fs_1.writeFileSync)(reports.capabilities, JSON.stringify((0, kernel_js_1.kageCapabilityAudit)(projectDir), null, 2));
613
+ (0, node_fs_1.writeFileSync)(reports.slots, JSON.stringify((0, kernel_js_1.kageContextSlots)(projectDir), null, 2));
614
+ (0, node_fs_1.writeFileSync)(reports.decisions, JSON.stringify((0, kernel_js_1.kageDecisionIntelligence)(projectDir), null, 2));
615
+ (0, node_fs_1.writeFileSync)(reports.risk, JSON.stringify((0, kernel_js_1.kageRisk)(projectDir), null, 2));
616
+ (0, node_fs_1.writeFileSync)(reports.moduleHealth, JSON.stringify((0, kernel_js_1.kageModuleHealth)(projectDir), null, 2));
617
+ (0, node_fs_1.writeFileSync)(reports.graphInsights, JSON.stringify((0, kernel_js_1.kageGraphInsights)(projectDir), null, 2));
618
+ (0, node_fs_1.writeFileSync)(reports.workspace, JSON.stringify((0, kernel_js_1.kageWorkspace)(projectDir), null, 2));
619
+ (0, node_fs_1.writeFileSync)(reports.sessions, JSON.stringify((0, kernel_js_1.kageSessionCaptureReport)(projectDir), null, 2));
620
+ (0, node_fs_1.writeFileSync)(reports.replay, JSON.stringify((0, kernel_js_1.kageSessionReplay)(projectDir), null, 2));
621
+ (0, node_fs_1.writeFileSync)(reports.memoryAccess, JSON.stringify((0, kernel_js_1.kageMemoryAccess)(projectDir), null, 2));
622
+ (0, node_fs_1.writeFileSync)(reports.memoryAudit, JSON.stringify((0, kernel_js_1.kageMemoryAudit)(projectDir), null, 2));
623
+ (0, node_fs_1.writeFileSync)(reports.handoff, JSON.stringify((0, kernel_js_1.kageMemoryHandoff)(projectDir), null, 2));
624
+ (0, node_fs_1.writeFileSync)(reports.lifecycle, JSON.stringify((0, kernel_js_1.kageMemoryLifecycle)(projectDir), null, 2));
625
+ (0, node_fs_1.writeFileSync)(reports.activity, JSON.stringify((0, kernel_js_1.kageActivity)(projectDir), null, 2));
626
+ (0, node_fs_1.writeFileSync)(reports.timeline, JSON.stringify((0, kernel_js_1.kageMemoryTimeline)(projectDir), null, 2));
627
+ (0, node_fs_1.writeFileSync)(reports.lineage, JSON.stringify((0, kernel_js_1.kageMemoryLineage)(projectDir), null, 2));
628
+ (0, node_fs_1.writeFileSync)(reports.setup, JSON.stringify((0, kernel_js_1.setupDoctor)(projectDir), null, 2));
629
+ (0, node_fs_1.writeFileSync)(reports.trust, JSON.stringify((0, kernel_js_1.benchmarkTrust)(projectDir), null, 2));
630
+ (0, node_fs_1.writeFileSync)(reports.suppressed, JSON.stringify((0, kernel_js_1.kageSuppressedMemory)(projectDir), null, 2));
610
631
  }
611
632
  catch {
612
633
  // non-fatal: viewer will show 404 for reports if generation fails
613
634
  }
614
- 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)}&xray=${encodeURIComponent(xrayPath)}&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)}&activity=${encodeURIComponent(activityPath)}&timeline=${encodeURIComponent(timelinePath)}&lineage=${encodeURIComponent(lineagePath)}&setup=${encodeURIComponent(setupPath)}&trust=${encodeURIComponent(trustPath)}&suppressed=${encodeURIComponent(suppressedPath)}&view=code`;
635
+ const url = viewerUrl(host, port, projectRoot);
615
636
  const server = (0, node_http_1.createServer)((req, res) => {
616
637
  const requestUrl = new URL(req.url ?? "/", `http://${host}:${port}`);
617
638
  let filePath = null;