ts-knowledge-graph 0.1.2 → 0.1.4

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.
Files changed (255) hide show
  1. package/README.md +74 -34
  2. package/contribs/web_visualisation/README.md +28 -0
  3. package/contribs/web_visualisation/web/css/style.css +104 -0
  4. package/contribs/web_visualisation/web/data/.gitignore +1 -0
  5. package/contribs/web_visualisation/web/data/kind_descriptions.js +38 -0
  6. package/contribs/web_visualisation/web/index.html +20 -4
  7. package/contribs/web_visualisation/web/js/app.js +581 -35
  8. package/contribs/web_visualisation/web/tsconfig.json +18 -0
  9. package/contribs/web_visualisation/web/types/app_globals.d.ts +146 -0
  10. package/dist/benchmark/benchmark_stats.d.ts +41 -0
  11. package/dist/benchmark/benchmark_stats.d.ts.map +1 -0
  12. package/dist/benchmark/benchmark_stats.js +61 -0
  13. package/dist/benchmark/benchmark_stats.js.map +1 -0
  14. package/dist/benchmark/node_benchmark.d.ts +78 -0
  15. package/dist/benchmark/node_benchmark.d.ts.map +1 -0
  16. package/dist/benchmark/node_benchmark.js +112 -0
  17. package/dist/benchmark/node_benchmark.js.map +1 -0
  18. package/dist/cli.d.ts.map +1 -1
  19. package/dist/cli.js +10 -2
  20. package/dist/cli.js.map +1 -1
  21. package/dist/commands/benchmark_command.d.ts +11 -0
  22. package/dist/commands/benchmark_command.d.ts.map +1 -0
  23. package/dist/commands/benchmark_command.js +91 -0
  24. package/dist/commands/benchmark_command.js.map +1 -0
  25. package/dist/commands/blast_radius_command.js +1 -1
  26. package/dist/commands/blast_radius_command.js.map +1 -1
  27. package/dist/commands/cost_command.d.ts +13 -0
  28. package/dist/commands/cost_command.d.ts.map +1 -0
  29. package/dist/commands/cost_command.js +122 -0
  30. package/dist/commands/cost_command.js.map +1 -0
  31. package/dist/commands/{load.d.ts → enrich_command.d.ts} +3 -2
  32. package/dist/commands/enrich_command.d.ts.map +1 -0
  33. package/dist/commands/enrich_command.js +62 -0
  34. package/dist/commands/enrich_command.js.map +1 -0
  35. package/dist/commands/hotspots_command.d.ts +7 -0
  36. package/dist/commands/hotspots_command.d.ts.map +1 -0
  37. package/dist/commands/hotspots_command.js +67 -0
  38. package/dist/commands/hotspots_command.js.map +1 -0
  39. package/dist/commands/install_command.d.ts +2 -3
  40. package/dist/commands/install_command.d.ts.map +1 -1
  41. package/dist/commands/install_command.js +7 -8
  42. package/dist/commands/install_command.js.map +1 -1
  43. package/dist/commands/load_command.d.ts.map +1 -1
  44. package/dist/commands/load_command.js +2 -0
  45. package/dist/commands/load_command.js.map +1 -1
  46. package/dist/commands/verify_command.d.ts +8 -0
  47. package/dist/commands/verify_command.d.ts.map +1 -0
  48. package/dist/commands/verify_command.js +57 -0
  49. package/dist/commands/verify_command.js.map +1 -0
  50. package/dist/commands/web_command.d.ts +27 -0
  51. package/dist/commands/web_command.d.ts.map +1 -1
  52. package/dist/commands/web_command.js +109 -3
  53. package/dist/commands/web_command.js.map +1 -1
  54. package/dist/enrich/cpu_profile.d.ts +127 -0
  55. package/dist/enrich/cpu_profile.d.ts.map +1 -0
  56. package/dist/enrich/cpu_profile.js +97 -0
  57. package/dist/enrich/cpu_profile.js.map +1 -0
  58. package/dist/enrich/runtime_enricher.d.ts +56 -0
  59. package/dist/enrich/runtime_enricher.d.ts.map +1 -0
  60. package/dist/enrich/runtime_enricher.js +80 -0
  61. package/dist/enrich/runtime_enricher.js.map +1 -0
  62. package/dist/enrich/runtime_join.d.ts +100 -0
  63. package/dist/enrich/runtime_join.d.ts.map +1 -0
  64. package/dist/enrich/runtime_join.js +227 -0
  65. package/dist/enrich/runtime_join.js.map +1 -0
  66. package/dist/extract/api_extractor.d.ts +24 -0
  67. package/dist/extract/api_extractor.d.ts.map +1 -0
  68. package/dist/extract/api_extractor.js +71 -0
  69. package/dist/extract/api_extractor.js.map +1 -0
  70. package/dist/extract/config_extractor.d.ts +22 -0
  71. package/dist/extract/config_extractor.d.ts.map +1 -0
  72. package/dist/extract/config_extractor.js +61 -0
  73. package/dist/extract/config_extractor.js.map +1 -0
  74. package/dist/extract/endpoint_extractor.d.ts +36 -0
  75. package/dist/extract/endpoint_extractor.d.ts.map +1 -0
  76. package/dist/extract/endpoint_extractor.js +117 -0
  77. package/dist/extract/endpoint_extractor.js.map +1 -0
  78. package/dist/extract/graph_builder.d.ts +8 -0
  79. package/dist/extract/graph_builder.d.ts.map +1 -1
  80. package/dist/extract/graph_builder.js +23 -1
  81. package/dist/extract/graph_builder.js.map +1 -1
  82. package/dist/extract/node_id.d.ts +16 -0
  83. package/dist/extract/node_id.d.ts.map +1 -1
  84. package/dist/extract/node_id.js +22 -0
  85. package/dist/extract/node_id.js.map +1 -1
  86. package/dist/extract/scope_resolver.d.ts +22 -0
  87. package/dist/extract/scope_resolver.d.ts.map +1 -0
  88. package/dist/extract/scope_resolver.js +53 -0
  89. package/dist/extract/scope_resolver.js.map +1 -0
  90. package/dist/extract/semantic_extractor.d.ts +25 -0
  91. package/dist/extract/semantic_extractor.d.ts.map +1 -1
  92. package/dist/extract/semantic_extractor.js +96 -2
  93. package/dist/extract/semantic_extractor.js.map +1 -1
  94. package/dist/extract/structural_extractor.d.ts +6 -0
  95. package/dist/extract/structural_extractor.d.ts.map +1 -1
  96. package/dist/extract/structural_extractor.js +22 -12
  97. package/dist/extract/structural_extractor.js.map +1 -1
  98. package/dist/project_root.d.ts +7 -0
  99. package/dist/project_root.d.ts.map +1 -0
  100. package/dist/project_root.js +9 -0
  101. package/dist/project_root.js.map +1 -0
  102. package/dist/query/graph_query.d.ts +234 -0
  103. package/dist/query/graph_query.d.ts.map +1 -1
  104. package/dist/query/graph_query.js +522 -11
  105. package/dist/query/graph_query.js.map +1 -1
  106. package/dist/schema/edge.d.ts +40 -5
  107. package/dist/schema/edge.d.ts.map +1 -1
  108. package/dist/schema/edge.js +70 -0
  109. package/dist/schema/edge.js.map +1 -1
  110. package/dist/schema/node.d.ts +20 -5
  111. package/dist/schema/node.d.ts.map +1 -1
  112. package/dist/schema/node.js +36 -0
  113. package/dist/schema/node.js.map +1 -1
  114. package/dist/schema/runtime_manifest.d.ts +36 -0
  115. package/dist/schema/runtime_manifest.d.ts.map +1 -0
  116. package/dist/schema/runtime_manifest.js +23 -0
  117. package/dist/schema/runtime_manifest.js.map +1 -0
  118. package/dist/store/kuzu_store.d.ts +46 -0
  119. package/dist/store/kuzu_store.d.ts.map +1 -1
  120. package/dist/store/kuzu_store.js +95 -5
  121. package/dist/store/kuzu_store.js.map +1 -1
  122. package/dist/verify/project_verifier.d.ts +85 -0
  123. package/dist/verify/project_verifier.d.ts.map +1 -0
  124. package/dist/verify/project_verifier.js +138 -0
  125. package/dist/verify/project_verifier.js.map +1 -0
  126. package/{skills/ts-knowledge-graph → dotclaude_folder/skills/code-graph-query}/SKILL.md +2 -2
  127. package/package.json +86 -7
  128. package/.env-sample +0 -34
  129. package/dist/agent/agent-tools.d.ts +0 -13
  130. package/dist/agent/agent-tools.d.ts.map +0 -1
  131. package/dist/agent/agent-tools.js +0 -153
  132. package/dist/agent/agent-tools.js.map +0 -1
  133. package/dist/agent/agent_tools.d.ts +0 -13
  134. package/dist/agent/agent_tools.d.ts.map +0 -1
  135. package/dist/agent/agent_tools.js +0 -153
  136. package/dist/agent/agent_tools.js.map +0 -1
  137. package/dist/agent/code-editor.d.ts +0 -18
  138. package/dist/agent/code-editor.d.ts.map +0 -1
  139. package/dist/agent/code-editor.js +0 -43
  140. package/dist/agent/code-editor.js.map +0 -1
  141. package/dist/agent/code_editor.d.ts +0 -18
  142. package/dist/agent/code_editor.d.ts.map +0 -1
  143. package/dist/agent/code_editor.js +0 -43
  144. package/dist/agent/code_editor.js.map +0 -1
  145. package/dist/agent/optimizer-agent.d.ts +0 -30
  146. package/dist/agent/optimizer-agent.d.ts.map +0 -1
  147. package/dist/agent/optimizer-agent.js +0 -97
  148. package/dist/agent/optimizer-agent.js.map +0 -1
  149. package/dist/agent/optimizer_agent.d.ts +0 -30
  150. package/dist/agent/optimizer_agent.d.ts.map +0 -1
  151. package/dist/agent/optimizer_agent.js +0 -97
  152. package/dist/agent/optimizer_agent.js.map +0 -1
  153. package/dist/agent/verifier.d.ts +0 -9
  154. package/dist/agent/verifier.d.ts.map +0 -1
  155. package/dist/agent/verifier.js +0 -19
  156. package/dist/agent/verifier.js.map +0 -1
  157. package/dist/commands/blast-radius.d.ts +0 -5
  158. package/dist/commands/blast-radius.d.ts.map +0 -1
  159. package/dist/commands/blast-radius.js +0 -18
  160. package/dist/commands/blast-radius.js.map +0 -1
  161. package/dist/commands/blast_radius.d.ts +0 -5
  162. package/dist/commands/blast_radius.d.ts.map +0 -1
  163. package/dist/commands/blast_radius.js +0 -18
  164. package/dist/commands/blast_radius.js.map +0 -1
  165. package/dist/commands/calls.d.ts +0 -5
  166. package/dist/commands/calls.d.ts.map +0 -1
  167. package/dist/commands/calls.js +0 -7
  168. package/dist/commands/calls.js.map +0 -1
  169. package/dist/commands/command-helpers.d.ts +0 -15
  170. package/dist/commands/command-helpers.d.ts.map +0 -1
  171. package/dist/commands/command-helpers.js +0 -61
  172. package/dist/commands/command-helpers.js.map +0 -1
  173. package/dist/commands/dead-exports.d.ts +0 -5
  174. package/dist/commands/dead-exports.d.ts.map +0 -1
  175. package/dist/commands/dead-exports.js +0 -7
  176. package/dist/commands/dead-exports.js.map +0 -1
  177. package/dist/commands/dead_exports.d.ts +0 -5
  178. package/dist/commands/dead_exports.d.ts.map +0 -1
  179. package/dist/commands/dead_exports.js +0 -7
  180. package/dist/commands/dead_exports.js.map +0 -1
  181. package/dist/commands/extract.d.ts +0 -8
  182. package/dist/commands/extract.d.ts.map +0 -1
  183. package/dist/commands/extract.js +0 -49
  184. package/dist/commands/extract.js.map +0 -1
  185. package/dist/commands/find.d.ts +0 -5
  186. package/dist/commands/find.d.ts.map +0 -1
  187. package/dist/commands/find.js +0 -7
  188. package/dist/commands/find.js.map +0 -1
  189. package/dist/commands/load.d.ts.map +0 -1
  190. package/dist/commands/load.js +0 -28
  191. package/dist/commands/load.js.map +0 -1
  192. package/dist/commands/neighbors.d.ts +0 -5
  193. package/dist/commands/neighbors.d.ts.map +0 -1
  194. package/dist/commands/neighbors.js +0 -17
  195. package/dist/commands/neighbors.js.map +0 -1
  196. package/dist/commands/optimize.d.ts +0 -6
  197. package/dist/commands/optimize.d.ts.map +0 -1
  198. package/dist/commands/optimize.js +0 -59
  199. package/dist/commands/optimize.js.map +0 -1
  200. package/dist/commands/optimize_command.d.ts +0 -6
  201. package/dist/commands/optimize_command.d.ts.map +0 -1
  202. package/dist/commands/optimize_command.js +0 -59
  203. package/dist/commands/optimize_command.js.map +0 -1
  204. package/dist/commands/references.d.ts +0 -5
  205. package/dist/commands/references.d.ts.map +0 -1
  206. package/dist/commands/references.js +0 -17
  207. package/dist/commands/references.js.map +0 -1
  208. package/dist/commands/web.d.ts +0 -19
  209. package/dist/commands/web.d.ts.map +0 -1
  210. package/dist/commands/web.js +0 -120
  211. package/dist/commands/web.js.map +0 -1
  212. package/dist/commands/who-calls.d.ts +0 -5
  213. package/dist/commands/who-calls.d.ts.map +0 -1
  214. package/dist/commands/who-calls.js +0 -7
  215. package/dist/commands/who-calls.js.map +0 -1
  216. package/dist/commands/who_calls.d.ts +0 -5
  217. package/dist/commands/who_calls.d.ts.map +0 -1
  218. package/dist/commands/who_calls.js +0 -7
  219. package/dist/commands/who_calls.js.map +0 -1
  220. package/dist/extract/graph-builder.d.ts +0 -16
  221. package/dist/extract/graph-builder.d.ts.map +0 -1
  222. package/dist/extract/graph-builder.js +0 -39
  223. package/dist/extract/graph-builder.js.map +0 -1
  224. package/dist/extract/node-id.d.ts +0 -8
  225. package/dist/extract/node-id.d.ts.map +0 -1
  226. package/dist/extract/node-id.js +0 -22
  227. package/dist/extract/node-id.js.map +0 -1
  228. package/dist/extract/project-loader.d.ts +0 -5
  229. package/dist/extract/project-loader.d.ts.map +0 -1
  230. package/dist/extract/project-loader.js +0 -19
  231. package/dist/extract/project-loader.js.map +0 -1
  232. package/dist/extract/semantic-extractor.d.ts +0 -22
  233. package/dist/extract/semantic-extractor.d.ts.map +0 -1
  234. package/dist/extract/semantic-extractor.js +0 -254
  235. package/dist/extract/semantic-extractor.js.map +0 -1
  236. package/dist/extract/structural-extractor.d.ts +0 -18
  237. package/dist/extract/structural-extractor.d.ts.map +0 -1
  238. package/dist/extract/structural-extractor.js +0 -97
  239. package/dist/extract/structural-extractor.js.map +0 -1
  240. package/dist/query/graph-query.d.ts +0 -28
  241. package/dist/query/graph-query.d.ts.map +0 -1
  242. package/dist/query/graph-query.js +0 -93
  243. package/dist/query/graph-query.js.map +0 -1
  244. package/dist/store/jsonl-reader.d.ts +0 -11
  245. package/dist/store/jsonl-reader.d.ts.map +0 -1
  246. package/dist/store/jsonl-reader.js +0 -19
  247. package/dist/store/jsonl-reader.js.map +0 -1
  248. package/dist/store/jsonl-store.d.ts +0 -7
  249. package/dist/store/jsonl-store.d.ts.map +0 -1
  250. package/dist/store/jsonl-store.js +0 -13
  251. package/dist/store/jsonl-store.js.map +0 -1
  252. package/dist/store/kuzu-store.d.ts +0 -14
  253. package/dist/store/kuzu-store.d.ts.map +0 -1
  254. package/dist/store/kuzu-store.js +0 -52
  255. package/dist/store/kuzu-store.js.map +0 -1
@@ -0,0 +1,91 @@
1
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import chalk from 'chalk';
5
+ import { z } from 'zod';
6
+ import { BenchmarkStats } from '../benchmark/benchmark_stats.js';
7
+ import { NodeBenchmark } from '../benchmark/node_benchmark.js';
8
+ import { KuzuStore } from '../store/kuzu_store.js';
9
+ import { DEFAULT_DB_PATH } from './command_helpers.js';
10
+ const METRICS = ['self-time', 'inclusive-time', 'samples'];
11
+ /** A saved baseline is just a prior report; we only need its median back. */
12
+ const BaselineFileSchema = z.object({ stats: z.object({ median: z.number() }) });
13
+ export class BenchmarkCommand {
14
+ static register(program) {
15
+ program
16
+ .command('benchmark')
17
+ .description('measure a target node\'s runtime metric over N profiling runs and report the median + spread (advisory)')
18
+ .argument('<target>', 'symbol name to benchmark; resolved against the current graph like `find`')
19
+ .requiredOption('--workload <path>', 'repeatable workload entry (.ts/.js) that exercises the target under load')
20
+ .option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
21
+ .option('-r, --root <path>', 'project root the profile paths resolve against', process.cwd())
22
+ .option('--by <metric>', `metric: ${METRICS.join(', ')}`, 'self-time')
23
+ .option('--runs <n>', 'number of profiling runs to take the median of', '5')
24
+ .option('--baseline <file>', 'compare against the median saved in this baseline file (advisory delta)')
25
+ .option('--save-baseline <file>', 'write this run as a baseline for a later --baseline comparison')
26
+ .option('--json', 'emit the benchmark report as JSON', false)
27
+ .action(async (target, options) => {
28
+ if (METRICS.includes(options.by) === false) {
29
+ console.error(chalk.red(`unknown metric '${options.by}' — choose one of: ${METRICS.join(', ')}`));
30
+ process.exitCode = 1;
31
+ return;
32
+ }
33
+ await BenchmarkCommand.run(target, options);
34
+ });
35
+ }
36
+ static async run(target, options) {
37
+ const store = new KuzuStore(resolve(options.db));
38
+ await store.initSchema();
39
+ const profileDir = await mkdtemp(join(tmpdir(), 'tkg-bench-'));
40
+ try {
41
+ const baselineMedian = options.baseline === undefined ? undefined : await BenchmarkCommand.readBaselineMedian(options.baseline);
42
+ const config = { workload: resolve(options.workload), root: resolve(options.root), profileDir };
43
+ const report = await NodeBenchmark.measure(store, { target, metric: options.by, runs: Number(options.runs), baselineMedian }, () => NodeBenchmark.profileAndEnrich(store, config));
44
+ if (options.saveBaseline !== undefined) {
45
+ await BenchmarkCommand.writeBaseline(options.saveBaseline, report);
46
+ }
47
+ BenchmarkCommand.print(report, options.json === true);
48
+ }
49
+ finally {
50
+ await store.close();
51
+ await rm(profileDir, { recursive: true, force: true });
52
+ }
53
+ }
54
+ static async readBaselineMedian(file) {
55
+ const parsed = BaselineFileSchema.parse(JSON.parse(await readFile(resolve(file), 'utf8')));
56
+ return parsed.stats.median;
57
+ }
58
+ static async writeBaseline(file, report) {
59
+ const path = resolve(file);
60
+ await mkdir(dirname(path), { recursive: true });
61
+ await writeFile(path, JSON.stringify(report, null, 2), 'utf8');
62
+ }
63
+ static print(report, json) {
64
+ if (json === true) {
65
+ console.log(JSON.stringify(report, null, 2));
66
+ return;
67
+ }
68
+ const target = report.target;
69
+ console.log(chalk.bold(target.name) + chalk.gray(` ${target.kind} · ${target.filePath}:${target.startLine}`));
70
+ const stats = report.stats;
71
+ const median = chalk.cyan(`${BenchmarkCommand.round(stats.median)} ${report.unit}`);
72
+ const spread = chalk.gray(`(min ${BenchmarkCommand.round(stats.min)} · max ${BenchmarkCommand.round(stats.max)} · ` +
73
+ `spread ${BenchmarkCommand.round(stats.spread)} · mean ${BenchmarkCommand.round(stats.mean)} · ${stats.runs} runs)`);
74
+ console.log(` ${chalk.bold(report.metric)} median ${median} ${spread}`);
75
+ if (report.delta !== null) {
76
+ BenchmarkCommand.printDelta(report, report.delta);
77
+ }
78
+ console.log(chalk.yellow(` ${report.advisory}`));
79
+ }
80
+ static printDelta(report, delta) {
81
+ const direction = BenchmarkStats.direction(delta, report.stats.spread);
82
+ const colour = direction === 'improved' ? chalk.green : direction === 'regressed' ? chalk.red : chalk.gray;
83
+ const absolute = `${delta.absolute > 0 ? '+' : ''}${BenchmarkCommand.round(delta.absolute)} ${report.unit}`;
84
+ const percent = BenchmarkStats.formatPercent(delta.percent);
85
+ console.log(` ${chalk.bold('Δ vs baseline')} ${colour(`${absolute} (${percent})`)} ${colour(direction)}`);
86
+ }
87
+ static round(value) {
88
+ return Math.round(value * 1000) / 1000;
89
+ }
90
+ }
91
+ //# sourceMappingURL=benchmark_command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark_command.js","sourceRoot":"","sources":["../../src/commands/benchmark_command.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ export class BlastRadiusCommand {
6
6
  .description('list every symbol transitively impacted by changing <id>')
7
7
  .argument('<id>', 'node id to analyse')
8
8
  .option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
9
- .option('--depth <n>', 'maximum traversal depth', '10')
9
+ .option('--depth <n>', 'maximum traversal depth (clamped to 1–30)', '10')
10
10
  .option('--json', 'emit raw JSON', false)
11
11
  .action(async (id, options) => {
12
12
  await CommandHelpers.withQuery(options.db, async (query) => {
@@ -1 +1 @@
1
- {"version":3,"file":"blast_radius_command.js","sourceRoot":"","sources":["../../src/commands/blast_radius_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAgB,MAAM,sBAAsB,CAAC;AAMrF,MAAM,OAAO,kBAAkB;IAC9B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,cAAc,CAAC;aACvB,WAAW,CAAC,0DAA0D,CAAC;aACvE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;aACtC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,aAAa,EAAE,yBAAyB,EAAE,IAAI,CAAC;aACtD,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;aACxC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAAqB,EAAE,EAAE;YACnD,MAAM,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC1D,cAAc,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACrG,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACD"}
1
+ {"version":3,"file":"blast_radius_command.js","sourceRoot":"","sources":["../../src/commands/blast_radius_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAgB,MAAM,sBAAsB,CAAC;AAMrF,MAAM,OAAO,kBAAkB;IAC9B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,cAAc,CAAC;aACvB,WAAW,CAAC,0DAA0D,CAAC;aACvE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;aACtC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,aAAa,EAAE,2CAA2C,EAAE,IAAI,CAAC;aACxE,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;aACxC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAAqB,EAAE,EAAE;YACnD,MAAM,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC1D,cAAc,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACrG,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACD"}
@@ -0,0 +1,13 @@
1
+ import { Command } from 'commander';
2
+ export declare class CostCommand {
3
+ static register(program: Command): void;
4
+ private static printRanking;
5
+ private static printAttribution;
6
+ private static printFlows;
7
+ private static formatAmount;
8
+ private static formatShare;
9
+ private static formatCoverage;
10
+ /** A one-line gloss under the ranking: what coverage means, or how to record it when missing. */
11
+ private static printCoverageHint;
12
+ }
13
+ //# sourceMappingURL=cost_command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost_command.d.ts","sourceRoot":"","sources":["../../src/commands/cost_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,qBAAa,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IA4BvC,OAAO,CAAC,MAAM,CAAC,YAAY;IA2B3B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAgC/B,OAAO,CAAC,MAAM,CAAC,UAAU;IAazB,OAAO,CAAC,MAAM,CAAC,YAAY;IAK3B,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,MAAM,CAAC,cAAc;IAI7B,iGAAiG;IACjG,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAUhC"}
@@ -0,0 +1,122 @@
1
+ import chalk from 'chalk';
2
+ import { CommandHelpers, DEFAULT_DB_PATH } from './command_helpers.js';
3
+ const METRICS = ['self-time', 'samples'];
4
+ const NO_RUNTIME_NOTICE = '! no runtime data in graph — run `enrich` first. Inclusive cost needs measured self cost to propagate.';
5
+ export class CostCommand {
6
+ static register(program) {
7
+ program
8
+ .command('cost')
9
+ .description('propagate runtime self cost into inclusive cost and rank nodes by share of total')
10
+ .argument('[id]', 'node id to break down causally; omit to rank the whole graph')
11
+ .option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
12
+ .option('--by <metric>', `cost metric: ${METRICS.join(', ')}`, 'self-time')
13
+ .option('--limit <n>', 'maximum number of ranked nodes to return', '20')
14
+ .option('--json', 'emit raw JSON', false)
15
+ .action(async (id, options) => {
16
+ if (options.by !== undefined && METRICS.includes(options.by) === false) {
17
+ console.error(chalk.red(`unknown metric '${options.by}' — choose one of: ${METRICS.join(', ')}`));
18
+ process.exitCode = 1;
19
+ return;
20
+ }
21
+ const by = options.by;
22
+ await CommandHelpers.withQuery(options.db, async (query) => {
23
+ if (id === undefined) {
24
+ const report = await query.costRanking({ by, limit: Number(options.limit) });
25
+ CostCommand.printRanking(report, options.json === true);
26
+ return;
27
+ }
28
+ const attribution = await query.costAttribution(id, { by });
29
+ CostCommand.printAttribution(attribution, options.json === true);
30
+ });
31
+ });
32
+ }
33
+ static printRanking(report, json) {
34
+ if (json === true) {
35
+ console.log(JSON.stringify(report, null, 2));
36
+ return;
37
+ }
38
+ if (report.enriched === false) {
39
+ console.log(chalk.yellow(NO_RUNTIME_NOTICE));
40
+ return;
41
+ }
42
+ const total = CostCommand.formatAmount(report.metric, report.totalSelf);
43
+ const coverage = CostCommand.formatCoverage(report.coverage);
44
+ console.log(chalk.bold(`Inclusive cost by ${report.metric}`) + chalk.gray(` (total self ${total} · coverage ${coverage})`));
45
+ if (report.nodes.length === 0) {
46
+ console.log(chalk.yellow('(no results)'));
47
+ return;
48
+ }
49
+ report.nodes.forEach((node, index) => {
50
+ const rank = chalk.gray(`${String(index + 1).padStart(2)}.`);
51
+ const inclusive = chalk.cyan(CostCommand.formatAmount(report.metric, node.inclusiveCost).padStart(14));
52
+ const share = chalk.green(CostCommand.formatShare(node.shareOfTotal).padStart(7));
53
+ const mark = node.cyclic === true ? chalk.magenta(' ↺') : '';
54
+ console.log(`${rank} ${inclusive} ${share} ${chalk.gray(node.kind.padEnd(10))} ${chalk.bold(node.name)}${mark} ${chalk.gray(`${node.filePath}:${node.startLine}`)}`);
55
+ });
56
+ console.log(chalk.gray(`\n${report.nodes.length} node(s) · share is of total self cost · ↺ = in a call cycle`));
57
+ CostCommand.printCoverageHint(report.coverage, report.metric);
58
+ }
59
+ static printAttribution(attribution, json) {
60
+ if (json === true) {
61
+ console.log(JSON.stringify(attribution, null, 2));
62
+ return;
63
+ }
64
+ if (attribution.node === null) {
65
+ console.log(chalk.yellow('(no such node — resolve an id with `find` first)'));
66
+ return;
67
+ }
68
+ if (attribution.enriched === false) {
69
+ console.log(chalk.yellow(NO_RUNTIME_NOTICE));
70
+ return;
71
+ }
72
+ const node = attribution.node;
73
+ const metric = attribution.metric;
74
+ console.log(chalk.bold(node.name) + chalk.gray(` ${node.kind} · ${node.filePath}:${node.startLine}`));
75
+ console.log(` self ${chalk.cyan(CostCommand.formatAmount(metric, node.selfCost))}`
76
+ + ` · inclusive ${chalk.cyan(CostCommand.formatAmount(metric, node.inclusiveCost))}`
77
+ + ` · share of total ${chalk.green(CostCommand.formatShare(node.shareOfTotal))}`);
78
+ const coverageLine = attribution.coverage === null
79
+ ? 'graph coverage: unknown — re-run `enrich` to record it'
80
+ : `graph coverage: ${CostCommand.formatCoverage(attribution.coverage)} of profiled ${metric} is attributed to nodes`;
81
+ console.log(chalk.gray(` ${coverageLine}`));
82
+ if (node.cyclic === true) {
83
+ console.log(chalk.magenta(` ↺ part of a ${node.cycleSize}-node call cycle — inclusive cost is the cycle total, shared by its members`));
84
+ }
85
+ CostCommand.printFlows('Cost flows into (callees)', attribution.callees, metric, '->');
86
+ CostCommand.printFlows('Attributed to callers', attribution.callers, metric, '<-');
87
+ }
88
+ static printFlows(title, flows, metric, arrow) {
89
+ console.log(chalk.bold(`\n${title}`));
90
+ if (flows.length === 0) {
91
+ console.log(chalk.gray(' (none)'));
92
+ return;
93
+ }
94
+ for (const flow of flows) {
95
+ const amount = chalk.cyan(CostCommand.formatAmount(metric, flow.amount).padStart(14));
96
+ const share = chalk.green(CostCommand.formatShare(flow.share).padStart(7));
97
+ console.log(` ${chalk.gray(arrow)} ${amount} ${share} ${chalk.bold(flow.name)} ${chalk.gray(`${flow.filePath}:${flow.startLine}`)}`);
98
+ }
99
+ }
100
+ static formatAmount(metric, value) {
101
+ const rounded = Math.round(value * 1000) / 1000;
102
+ return metric === 'self-time' ? `${rounded} ms` : `${rounded} samples`;
103
+ }
104
+ static formatShare(share) {
105
+ return `${(share * 100).toFixed(1)}%`;
106
+ }
107
+ static formatCoverage(coverage) {
108
+ return coverage === null ? 'unknown' : `${(coverage * 100).toFixed(0)}%`;
109
+ }
110
+ /** A one-line gloss under the ranking: what coverage means, or how to record it when missing. */
111
+ static printCoverageHint(coverage, metric) {
112
+ if (coverage === null) {
113
+ console.log(chalk.gray('coverage unknown — re-run `enrich` to record what fraction of the profile lands on the graph'));
114
+ return;
115
+ }
116
+ const outsidePct = Math.round((1 - coverage) * 100);
117
+ if (outsidePct > 0) {
118
+ console.log(chalk.gray(`coverage = ${CostCommand.formatCoverage(coverage)} of profiled ${metric} attributed to the graph; ${outsidePct}% fell outside it (dropped by the join)`));
119
+ }
120
+ }
121
+ }
122
+ //# sourceMappingURL=cost_command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost_command.js","sourceRoot":"","sources":["../../src/commands/cost_command.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { Command } from 'commander';
2
- export declare class Load {
2
+ export declare class EnrichCommand {
3
3
  static register(program: Command): void;
4
4
  private static run;
5
+ private static print;
5
6
  }
6
- //# sourceMappingURL=load.d.ts.map
7
+ //# sourceMappingURL=enrich_command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich_command.d.ts","sourceRoot":"","sources":["../../src/commands/enrich_command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,qBAAa,aAAa;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAalB,GAAG;IAaxB,OAAO,CAAC,MAAM,CAAC,KAAK;CAqCpB"}
@@ -0,0 +1,62 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import chalk from 'chalk';
4
+ import { RuntimeEnricher } from '../enrich/runtime_enricher.js';
5
+ import { KuzuStore } from '../store/kuzu_store.js';
6
+ import { DEFAULT_DB_PATH } from './command_helpers.js';
7
+ export class EnrichCommand {
8
+ static register(program) {
9
+ program
10
+ .command('enrich')
11
+ .description('ingest a V8 CPU profile and attach runtime metrics onto graph nodes')
12
+ .argument('<profile>', 'path to a V8 .cpuprofile file (node --cpu-prof)')
13
+ .option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
14
+ .option('-r, --root <path>', 'project root the profile paths resolve against', process.cwd())
15
+ .option('--json', 'emit the enrichment report as JSON', false)
16
+ .action(async (profile, options) => {
17
+ await EnrichCommand.run(profile, options);
18
+ });
19
+ }
20
+ static async run(profile, options) {
21
+ const profilePath = resolve(profile);
22
+ const profileText = await readFile(profilePath, 'utf8');
23
+ const store = new KuzuStore(resolve(options.db));
24
+ await store.initSchema();
25
+ try {
26
+ const report = await RuntimeEnricher.enrich(store, profileText, { root: resolve(options.root) });
27
+ EnrichCommand.print(report, options.json === true);
28
+ }
29
+ finally {
30
+ await store.close();
31
+ }
32
+ }
33
+ static print(report, json) {
34
+ if (json === true) {
35
+ console.log(JSON.stringify(report, null, 2));
36
+ return;
37
+ }
38
+ const coverage = report.totalSamples > 0
39
+ ? Math.round((report.matchedSamples / report.totalSamples) * 100)
40
+ : 0;
41
+ console.log(chalk.green(`✓ enriched ${report.matchedNodes} node(s) with metadata.runtime`));
42
+ console.log(` attributed ${chalk.bold(report.matchedSamples)} / ${report.totalSamples} samples (${coverage}%), ` +
43
+ `${chalk.bold(`${report.matchedSelfMs} ms`)} self time`);
44
+ console.log(` joined ${chalk.bold(report.matchedFrames)} frame(s): ` +
45
+ `${report.matchedByName} by name, ${report.matchedByRange} by range`);
46
+ console.log(` dropped ${chalk.bold(report.droppedFrames)} frame(s), ${report.droppedSamples} sample(s) — not in graph`);
47
+ if (report.hotspots.length > 0) {
48
+ console.log(chalk.bold('\nTop self time'));
49
+ for (const hotspot of report.hotspots.slice(0, 10)) {
50
+ console.log(` ${chalk.gray(`${hotspot.selfMs} ms`.padStart(10))} ${chalk.bold(hotspot.name)} ` +
51
+ `${chalk.gray(`(${hotspot.samples} samples)`)} ${chalk.gray(hotspot.filePath)}`);
52
+ }
53
+ }
54
+ if (report.dropped.length > 0) {
55
+ console.log(chalk.bold('\nTop unattributed'));
56
+ for (const group of report.dropped.slice(0, 5)) {
57
+ console.log(` ${chalk.gray(`${group.samples} samples`.padStart(12))} ${chalk.gray(group.label)}`);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ //# sourceMappingURL=enrich_command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich_command.js","sourceRoot":"","sources":["../../src/commands/enrich_command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Command } from 'commander';
2
+ export declare class HotspotsCommand {
3
+ static register(program: Command): void;
4
+ private static print;
5
+ private static formatScore;
6
+ }
7
+ //# sourceMappingURL=hotspots_command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hotspots_command.d.ts","sourceRoot":"","sources":["../../src/commands/hotspots_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,qBAAa,eAAe;IAC3B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IA0BvC,OAAO,CAAC,MAAM,CAAC,KAAK;IAsBpB,OAAO,CAAC,MAAM,CAAC,WAAW;CAe1B"}
@@ -0,0 +1,67 @@
1
+ import chalk from 'chalk';
2
+ import { CommandHelpers, DEFAULT_DB_PATH } from './command_helpers.js';
3
+ const METRICS = ['self-time', 'samples', 'callers', 'call-count', 'blast-radius'];
4
+ export class HotspotsCommand {
5
+ static register(program) {
6
+ program
7
+ .command('hotspots')
8
+ .description('rank nodes by optimization leverage (runtime self-time, fan-in, call-count, or blast radius)')
9
+ .option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
10
+ .option('--by <metric>', `ranking metric: ${METRICS.join(', ')} (default: self-time when enriched, else callers)`)
11
+ .option('--limit <n>', 'maximum number of hotspots to return', '20')
12
+ .option('--measured-only', 'restrict ranking to nodes that carry runtime metrics', false)
13
+ .option('--json', 'emit raw JSON', false)
14
+ .action(async (options) => {
15
+ if (options.by !== undefined && METRICS.includes(options.by) === false) {
16
+ console.error(chalk.red(`unknown metric '${options.by}' — choose one of: ${METRICS.join(', ')}`));
17
+ process.exitCode = 1;
18
+ return;
19
+ }
20
+ await CommandHelpers.withQuery(options.db, async (query) => {
21
+ const report = await query.hotspots({
22
+ by: options.by,
23
+ limit: Number(options.limit),
24
+ measuredOnly: options.measuredOnly === true,
25
+ });
26
+ HotspotsCommand.print(report, options.json === true);
27
+ });
28
+ });
29
+ }
30
+ static print(report, json) {
31
+ if (json === true) {
32
+ console.log(JSON.stringify(report, null, 2));
33
+ return;
34
+ }
35
+ if (report.fellBack === true) {
36
+ console.log(chalk.yellow('! no runtime data in graph — run `enrich` first. Ranking by `callers` (static fan-in) instead.'));
37
+ }
38
+ const scope = report.measuredOnly === true ? chalk.gray(' (measured nodes only)') : '';
39
+ console.log(chalk.bold(`Hotspots by ${report.metric}`) + scope);
40
+ if (report.hotspots.length === 0) {
41
+ console.log(chalk.yellow('(no results)'));
42
+ return;
43
+ }
44
+ report.hotspots.forEach((hotspot, index) => {
45
+ const rank = chalk.gray(`${String(index + 1).padStart(2)}.`);
46
+ const score = chalk.cyan(HotspotsCommand.formatScore(report.metric, hotspot.score).padStart(14));
47
+ console.log(`${rank} ${score} ${chalk.gray(hotspot.kind.padEnd(10))} ${chalk.bold(hotspot.name)} ${chalk.gray(`${hotspot.filePath}:${hotspot.startLine}`)}`);
48
+ });
49
+ console.log(chalk.gray(`\n${report.hotspots.length} hotspot(s)`));
50
+ }
51
+ static formatScore(metric, score) {
52
+ if (metric === 'self-time') {
53
+ return `${score} ms`;
54
+ }
55
+ if (metric === 'samples') {
56
+ return `${score} samples`;
57
+ }
58
+ if (metric === 'callers') {
59
+ return `${score} callers`;
60
+ }
61
+ if (metric === 'call-count') {
62
+ return `${score} calls`;
63
+ }
64
+ return `${score} impacted`;
65
+ }
66
+ }
67
+ //# sourceMappingURL=hotspots_command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hotspots_command.js","sourceRoot":"","sources":["../../src/commands/hotspots_command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAgB,MAAM,sBAAsB,CAAC;AAQrF,MAAM,OAAO,GAAoB,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;AAEnG,MAAM,OAAO,eAAe;IAC3B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,UAAU,CAAC;aACnB,WAAW,CAAC,8FAA8F,CAAC;aAC3G,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,eAAe,EAAE,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,mDAAmD,CAAC;aACjH,MAAM,CAAC,aAAa,EAAE,sCAAsC,EAAE,IAAI,CAAC;aACnE,MAAM,CAAC,iBAAiB,EAAE,sDAAsD,EAAE,KAAK,CAAC;aACxF,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;aACxC,MAAM,CAAC,KAAK,EAAE,OAAwB,EAAE,EAAE;YAC1C,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAmB,CAAC,KAAK,KAAK,EAAE,CAAC;gBACzF,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,EAAE,sBAAsB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBAClG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACR,CAAC;YACD,MAAM,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC1D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC;oBACnC,EAAE,EAAE,OAAO,CAAC,EAA+B;oBAC3C,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;oBAC5B,YAAY,EAAE,OAAO,CAAC,YAAY,KAAK,IAAI;iBAC3C,CAAC,CAAC;gBACH,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACtD,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,MAAqB,EAAE,IAAa;QACxD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,OAAO;QACR,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gGAAgG,CAAC,CAAC,CAAC;QAC7H,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;YAC1C,OAAO;QACR,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;YAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;YACjG,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;QAChK,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC,CAAC;IACnE,CAAC;IAEO,MAAM,CAAC,WAAW,CAAC,MAAqB,EAAE,KAAa;QAC9D,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAC5B,OAAO,GAAG,KAAK,KAAK,CAAC;QACtB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,GAAG,KAAK,UAAU,CAAC;QAC3B,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,GAAG,KAAK,UAAU,CAAC;QAC3B,CAAC;QACD,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC7B,OAAO,GAAG,KAAK,QAAQ,CAAC;QACzB,CAAC;QACD,OAAO,GAAG,KAAK,WAAW,CAAC;IAC5B,CAAC;CACD"}
@@ -7,9 +7,8 @@ export declare class InstallCommand {
7
7
  static register(program: Command): void;
8
8
  private static run;
9
9
  /**
10
- * Resolves the bundled SKILL.md relative to this module. The `../../` prefix
11
- * reaches the package root from both `src/commands` (run via tsx) and
12
- * `dist/commands` (run from the built output).
10
+ * Resolves the bundled SKILL.md from the package root, which works whether
11
+ * running via tsx from `src` or from the built `dist` output.
13
12
  */
14
13
  private static sourceSkillPath;
15
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"install_command.d.ts","sourceRoot":"","sources":["../../src/commands/install_command.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC;;;GAGG;AACH,qBAAa,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;IAcxB;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;CAI9B"}
1
+ {"version":3,"file":"install_command.d.ts","sourceRoot":"","sources":["../../src/commands/install_command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC;;;GAGG;AACH,qBAAa,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;IAcxB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;CAG9B"}
@@ -1,8 +1,9 @@
1
1
  import { copyFileSync, existsSync, mkdirSync } from 'node:fs';
2
2
  import { dirname, resolve } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
3
  import chalk from 'chalk';
5
- const SKILL_RELATIVE_PATH = 'skills/ts-knowledge-graph/SKILL.md';
4
+ import { PROJECT_ROOT } from '../project_root.js';
5
+ const SKILL_SOURCE_PATH = 'dotclaude_folder/skills/code-graph-query/SKILL.md';
6
+ const SKILL_TARGET_PATH = 'skills/code-graph-query/SKILL.md';
6
7
  /**
7
8
  * Installs the bundled Claude Code skill into a target project so an agent can
8
9
  * query the knowledge graph through the ts-knowledge-graph CLI.
@@ -20,7 +21,7 @@ export class InstallCommand {
20
21
  }
21
22
  static async run(destFolder, options) {
22
23
  const source = InstallCommand.sourceSkillPath();
23
- const target = resolve(destFolder, SKILL_RELATIVE_PATH);
24
+ const target = resolve(destFolder, SKILL_TARGET_PATH);
24
25
  if (existsSync(target) === true && options.force === false) {
25
26
  console.log(chalk.yellow(`✗ ${target} already exists — pass --force to overwrite`));
26
27
  return;
@@ -30,13 +31,11 @@ export class InstallCommand {
30
31
  console.log(chalk.green(`✓ installed skill -> ${target}`));
31
32
  }
32
33
  /**
33
- * Resolves the bundled SKILL.md relative to this module. The `../../` prefix
34
- * reaches the package root from both `src/commands` (run via tsx) and
35
- * `dist/commands` (run from the built output).
34
+ * Resolves the bundled SKILL.md from the package root, which works whether
35
+ * running via tsx from `src` or from the built `dist` output.
36
36
  */
37
37
  static sourceSkillPath() {
38
- const here = dirname(fileURLToPath(import.meta.url));
39
- return resolve(here, '..', '..', SKILL_RELATIVE_PATH);
38
+ return resolve(PROJECT_ROOT, SKILL_SOURCE_PATH);
40
39
  }
41
40
  }
42
41
  //# sourceMappingURL=install_command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install_command.js","sourceRoot":"","sources":["../../src/commands/install_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,mBAAmB,GAAG,oCAAoC,CAAC;AAMjE;;;GAGG;AACH,MAAM,OAAO,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,SAAS,CAAC;aAClB,WAAW,CAAC,iEAAiE,CAAC;aAC9E,QAAQ,CAAC,cAAc,EAAE,wCAAwC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;aACjF,MAAM,CAAC,SAAS,EAAE,gCAAgC,EAAE,KAAK,CAAC;aAC1D,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAAuB,EAAE,EAAE;YAC7D,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAkB,EAAE,OAAuB;QACnE,MAAM,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;QAExD,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,MAAM,6CAA6C,CAAC,CAAC,CAAC;YACpF,OAAO;QACR,CAAC;QAED,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,eAAe;QAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACvD,CAAC;CACD"}
1
+ {"version":3,"file":"install_command.js","sourceRoot":"","sources":["../../src/commands/install_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,iBAAiB,GAAG,mDAAmD,CAAC;AAC9E,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AAM7D;;;GAGG;AACH,MAAM,OAAO,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,SAAS,CAAC;aAClB,WAAW,CAAC,iEAAiE,CAAC;aAC9E,QAAQ,CAAC,cAAc,EAAE,wCAAwC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;aACjF,MAAM,CAAC,SAAS,EAAE,gCAAgC,EAAE,KAAK,CAAC;aAC1D,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAAuB,EAAE,EAAE;YAC7D,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAkB,EAAE,OAAuB;QACnE,MAAM,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;QAEtD,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,MAAM,6CAA6C,CAAC,CAAC,CAAC;YACpF,OAAO;QACR,CAAC;QAED,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,eAAe;QAC7B,OAAO,OAAO,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;IACjD,CAAC;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"load_command.d.ts","sourceRoot":"","sources":["../../src/commands/load_command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,qBAAa,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;CAUxB"}
1
+ {"version":3,"file":"load_command.d.ts","sourceRoot":"","sources":["../../src/commands/load_command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,qBAAa,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;CAWxB"}
@@ -1,5 +1,6 @@
1
1
  import { resolve } from 'node:path';
2
2
  import chalk from 'chalk';
3
+ import { RUNTIME_MANIFEST_KEY } from '../schema/runtime_manifest.js';
3
4
  import { JsonlReader } from '../store/jsonl_reader.js';
4
5
  import { KuzuStore } from '../store/kuzu_store.js';
5
6
  import { DEFAULT_DB_PATH, DEFAULT_GRAPH_DIR } from './command_helpers.js';
@@ -21,6 +22,7 @@ export class LoadCommand {
21
22
  const store = new KuzuStore(resolvedDb);
22
23
  await store.initSchema();
23
24
  await store.load(nodes, edges);
25
+ await store.clearGraphMeta(RUNTIME_MANIFEST_KEY);
24
26
  await store.close();
25
27
  console.log(chalk.green(`✓ loaded ${nodes.length} nodes, ${edges.length} edges`));
26
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"load_command.js","sourceRoot":"","sources":["../../src/commands/load_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,MAAM,OAAO,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,MAAM,CAAC;aACf,WAAW,CAAC,mDAAmD,CAAC;aAChE,QAAQ,CAAC,YAAY,EAAE,+CAA+C,EAAE,iBAAiB,CAAC;aAC1F,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAAuB,EAAE,EAAE;YAC3D,MAAM,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,MAAc;QACxD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,QAAQ,CAAC,SAAS,UAAU,MAAM,CAAC,CAAC,CAAC;QAC/E,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC;IACnF,CAAC;CACD"}
1
+ {"version":3,"file":"load_command.js","sourceRoot":"","sources":["../../src/commands/load_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,MAAM,OAAO,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,MAAM,CAAC;aACf,WAAW,CAAC,mDAAmD,CAAC;aAChE,QAAQ,CAAC,YAAY,EAAE,+CAA+C,EAAE,iBAAiB,CAAC;aAC1F,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAAuB,EAAE,EAAE;YAC3D,MAAM,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,MAAc;QACxD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,QAAQ,CAAC,SAAS,UAAU,MAAM,CAAC,CAAC,CAAC;QAC/E,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,MAAM,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC;IACnF,CAAC;CACD"}
@@ -0,0 +1,8 @@
1
+ import { Command } from 'commander';
2
+ export declare class VerifyCommand {
3
+ static register(program: Command): void;
4
+ private static print;
5
+ private static printCheck;
6
+ private static printFailureOutput;
7
+ }
8
+ //# sourceMappingURL=verify_command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify_command.d.ts","sourceRoot":"","sources":["../../src/commands/verify_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,qBAAa,aAAa;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAuBvC,OAAO,CAAC,MAAM,CAAC,KAAK;IAapB,OAAO,CAAC,MAAM,CAAC,UAAU;IAUzB,OAAO,CAAC,MAAM,CAAC,kBAAkB;CASjC"}
@@ -0,0 +1,57 @@
1
+ import chalk from 'chalk';
2
+ import { ProjectVerifier } from '../verify/project_verifier.js';
3
+ export class VerifyCommand {
4
+ static register(program) {
5
+ program
6
+ .command('verify')
7
+ .description('run the project type-check + test gates and return one keep/revert verdict for an edit')
8
+ .option('-C, --cwd <path>', 'project directory whose package.json scripts are run', process.cwd())
9
+ .option('--typecheck-script <name>', 'npm script for the type-check gate', 'typecheck')
10
+ .option('--test-script <name>', 'npm script for the test gate', 'test')
11
+ .option('--skip-typecheck', 'skip the type-check gate', false)
12
+ .option('--skip-tests', 'skip the test gate (degrades to type-check-only)', false)
13
+ .option('--json', 'emit the verdict as JSON', false)
14
+ .action(async (options) => {
15
+ const report = await ProjectVerifier.verify({
16
+ cwd: options.cwd,
17
+ typecheckScript: options.typecheckScript,
18
+ testScript: options.testScript,
19
+ skipTypecheck: options.skipTypecheck === true,
20
+ skipTests: options.skipTests === true,
21
+ });
22
+ VerifyCommand.print(report, options.json === true);
23
+ process.exitCode = report.ok === true ? 0 : 1;
24
+ });
25
+ }
26
+ static print(report, json) {
27
+ if (json === true) {
28
+ console.log(JSON.stringify(report, null, 2));
29
+ return;
30
+ }
31
+ for (const check of report.checks) {
32
+ VerifyCommand.printCheck(check);
33
+ }
34
+ const verdict = report.ok === true ? chalk.green('✓') : chalk.red('✗');
35
+ console.log(`\n${verdict} ${report.summary}`);
36
+ VerifyCommand.printFailureOutput(report);
37
+ }
38
+ static printCheck(check) {
39
+ if (check.status === 'skipped') {
40
+ console.log(`${chalk.yellow('•')} ${chalk.bold(check.name.padEnd(10))} ${chalk.yellow('skipped')} ${chalk.gray(check.skippedReason ?? '')}`);
41
+ return;
42
+ }
43
+ const mark = check.status === 'pass' ? chalk.green('✓') : chalk.red('✗');
44
+ const timing = chalk.gray(`${(check.durationMs / 1000).toFixed(1)}s`);
45
+ console.log(`${mark} ${chalk.bold(check.name.padEnd(10))} ${chalk.gray(check.command ?? '')} ${timing}`);
46
+ }
47
+ static printFailureOutput(report) {
48
+ if (report.ok === true) {
49
+ return;
50
+ }
51
+ for (const check of report.checks.filter((candidate) => candidate.status === 'fail')) {
52
+ console.log(chalk.bold(`\n— ${check.name} output (tail) —`));
53
+ console.log(check.output.trimEnd());
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=verify_command.js.map