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.
- package/README.md +74 -34
- package/contribs/web_visualisation/README.md +28 -0
- package/contribs/web_visualisation/web/css/style.css +104 -0
- package/contribs/web_visualisation/web/data/.gitignore +1 -0
- package/contribs/web_visualisation/web/data/kind_descriptions.js +38 -0
- package/contribs/web_visualisation/web/index.html +20 -4
- package/contribs/web_visualisation/web/js/app.js +581 -35
- package/contribs/web_visualisation/web/tsconfig.json +18 -0
- package/contribs/web_visualisation/web/types/app_globals.d.ts +146 -0
- package/dist/benchmark/benchmark_stats.d.ts +41 -0
- package/dist/benchmark/benchmark_stats.d.ts.map +1 -0
- package/dist/benchmark/benchmark_stats.js +61 -0
- package/dist/benchmark/benchmark_stats.js.map +1 -0
- package/dist/benchmark/node_benchmark.d.ts +78 -0
- package/dist/benchmark/node_benchmark.d.ts.map +1 -0
- package/dist/benchmark/node_benchmark.js +112 -0
- package/dist/benchmark/node_benchmark.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/benchmark_command.d.ts +11 -0
- package/dist/commands/benchmark_command.d.ts.map +1 -0
- package/dist/commands/benchmark_command.js +91 -0
- package/dist/commands/benchmark_command.js.map +1 -0
- package/dist/commands/blast_radius_command.js +1 -1
- package/dist/commands/blast_radius_command.js.map +1 -1
- package/dist/commands/cost_command.d.ts +13 -0
- package/dist/commands/cost_command.d.ts.map +1 -0
- package/dist/commands/cost_command.js +122 -0
- package/dist/commands/cost_command.js.map +1 -0
- package/dist/commands/{load.d.ts → enrich_command.d.ts} +3 -2
- package/dist/commands/enrich_command.d.ts.map +1 -0
- package/dist/commands/enrich_command.js +62 -0
- package/dist/commands/enrich_command.js.map +1 -0
- package/dist/commands/hotspots_command.d.ts +7 -0
- package/dist/commands/hotspots_command.d.ts.map +1 -0
- package/dist/commands/hotspots_command.js +67 -0
- package/dist/commands/hotspots_command.js.map +1 -0
- package/dist/commands/install_command.d.ts +2 -3
- package/dist/commands/install_command.d.ts.map +1 -1
- package/dist/commands/install_command.js +7 -8
- package/dist/commands/install_command.js.map +1 -1
- package/dist/commands/load_command.d.ts.map +1 -1
- package/dist/commands/load_command.js +2 -0
- package/dist/commands/load_command.js.map +1 -1
- package/dist/commands/verify_command.d.ts +8 -0
- package/dist/commands/verify_command.d.ts.map +1 -0
- package/dist/commands/verify_command.js +57 -0
- package/dist/commands/verify_command.js.map +1 -0
- package/dist/commands/web_command.d.ts +27 -0
- package/dist/commands/web_command.d.ts.map +1 -1
- package/dist/commands/web_command.js +109 -3
- package/dist/commands/web_command.js.map +1 -1
- package/dist/enrich/cpu_profile.d.ts +127 -0
- package/dist/enrich/cpu_profile.d.ts.map +1 -0
- package/dist/enrich/cpu_profile.js +97 -0
- package/dist/enrich/cpu_profile.js.map +1 -0
- package/dist/enrich/runtime_enricher.d.ts +56 -0
- package/dist/enrich/runtime_enricher.d.ts.map +1 -0
- package/dist/enrich/runtime_enricher.js +80 -0
- package/dist/enrich/runtime_enricher.js.map +1 -0
- package/dist/enrich/runtime_join.d.ts +100 -0
- package/dist/enrich/runtime_join.d.ts.map +1 -0
- package/dist/enrich/runtime_join.js +227 -0
- package/dist/enrich/runtime_join.js.map +1 -0
- package/dist/extract/api_extractor.d.ts +24 -0
- package/dist/extract/api_extractor.d.ts.map +1 -0
- package/dist/extract/api_extractor.js +71 -0
- package/dist/extract/api_extractor.js.map +1 -0
- package/dist/extract/config_extractor.d.ts +22 -0
- package/dist/extract/config_extractor.d.ts.map +1 -0
- package/dist/extract/config_extractor.js +61 -0
- package/dist/extract/config_extractor.js.map +1 -0
- package/dist/extract/endpoint_extractor.d.ts +36 -0
- package/dist/extract/endpoint_extractor.d.ts.map +1 -0
- package/dist/extract/endpoint_extractor.js +117 -0
- package/dist/extract/endpoint_extractor.js.map +1 -0
- package/dist/extract/graph_builder.d.ts +8 -0
- package/dist/extract/graph_builder.d.ts.map +1 -1
- package/dist/extract/graph_builder.js +23 -1
- package/dist/extract/graph_builder.js.map +1 -1
- package/dist/extract/node_id.d.ts +16 -0
- package/dist/extract/node_id.d.ts.map +1 -1
- package/dist/extract/node_id.js +22 -0
- package/dist/extract/node_id.js.map +1 -1
- package/dist/extract/scope_resolver.d.ts +22 -0
- package/dist/extract/scope_resolver.d.ts.map +1 -0
- package/dist/extract/scope_resolver.js +53 -0
- package/dist/extract/scope_resolver.js.map +1 -0
- package/dist/extract/semantic_extractor.d.ts +25 -0
- package/dist/extract/semantic_extractor.d.ts.map +1 -1
- package/dist/extract/semantic_extractor.js +96 -2
- package/dist/extract/semantic_extractor.js.map +1 -1
- package/dist/extract/structural_extractor.d.ts +6 -0
- package/dist/extract/structural_extractor.d.ts.map +1 -1
- package/dist/extract/structural_extractor.js +22 -12
- package/dist/extract/structural_extractor.js.map +1 -1
- package/dist/project_root.d.ts +7 -0
- package/dist/project_root.d.ts.map +1 -0
- package/dist/project_root.js +9 -0
- package/dist/project_root.js.map +1 -0
- package/dist/query/graph_query.d.ts +234 -0
- package/dist/query/graph_query.d.ts.map +1 -1
- package/dist/query/graph_query.js +522 -11
- package/dist/query/graph_query.js.map +1 -1
- package/dist/schema/edge.d.ts +40 -5
- package/dist/schema/edge.d.ts.map +1 -1
- package/dist/schema/edge.js +70 -0
- package/dist/schema/edge.js.map +1 -1
- package/dist/schema/node.d.ts +20 -5
- package/dist/schema/node.d.ts.map +1 -1
- package/dist/schema/node.js +36 -0
- package/dist/schema/node.js.map +1 -1
- package/dist/schema/runtime_manifest.d.ts +36 -0
- package/dist/schema/runtime_manifest.d.ts.map +1 -0
- package/dist/schema/runtime_manifest.js +23 -0
- package/dist/schema/runtime_manifest.js.map +1 -0
- package/dist/store/kuzu_store.d.ts +46 -0
- package/dist/store/kuzu_store.d.ts.map +1 -1
- package/dist/store/kuzu_store.js +95 -5
- package/dist/store/kuzu_store.js.map +1 -1
- package/dist/verify/project_verifier.d.ts +85 -0
- package/dist/verify/project_verifier.d.ts.map +1 -0
- package/dist/verify/project_verifier.js +138 -0
- package/dist/verify/project_verifier.js.map +1 -0
- package/{skills/ts-knowledge-graph → dotclaude_folder/skills/code-graph-query}/SKILL.md +2 -2
- package/package.json +86 -7
- package/.env-sample +0 -34
- package/dist/agent/agent-tools.d.ts +0 -13
- package/dist/agent/agent-tools.d.ts.map +0 -1
- package/dist/agent/agent-tools.js +0 -153
- package/dist/agent/agent-tools.js.map +0 -1
- package/dist/agent/agent_tools.d.ts +0 -13
- package/dist/agent/agent_tools.d.ts.map +0 -1
- package/dist/agent/agent_tools.js +0 -153
- package/dist/agent/agent_tools.js.map +0 -1
- package/dist/agent/code-editor.d.ts +0 -18
- package/dist/agent/code-editor.d.ts.map +0 -1
- package/dist/agent/code-editor.js +0 -43
- package/dist/agent/code-editor.js.map +0 -1
- package/dist/agent/code_editor.d.ts +0 -18
- package/dist/agent/code_editor.d.ts.map +0 -1
- package/dist/agent/code_editor.js +0 -43
- package/dist/agent/code_editor.js.map +0 -1
- package/dist/agent/optimizer-agent.d.ts +0 -30
- package/dist/agent/optimizer-agent.d.ts.map +0 -1
- package/dist/agent/optimizer-agent.js +0 -97
- package/dist/agent/optimizer-agent.js.map +0 -1
- package/dist/agent/optimizer_agent.d.ts +0 -30
- package/dist/agent/optimizer_agent.d.ts.map +0 -1
- package/dist/agent/optimizer_agent.js +0 -97
- package/dist/agent/optimizer_agent.js.map +0 -1
- package/dist/agent/verifier.d.ts +0 -9
- package/dist/agent/verifier.d.ts.map +0 -1
- package/dist/agent/verifier.js +0 -19
- package/dist/agent/verifier.js.map +0 -1
- package/dist/commands/blast-radius.d.ts +0 -5
- package/dist/commands/blast-radius.d.ts.map +0 -1
- package/dist/commands/blast-radius.js +0 -18
- package/dist/commands/blast-radius.js.map +0 -1
- package/dist/commands/blast_radius.d.ts +0 -5
- package/dist/commands/blast_radius.d.ts.map +0 -1
- package/dist/commands/blast_radius.js +0 -18
- package/dist/commands/blast_radius.js.map +0 -1
- package/dist/commands/calls.d.ts +0 -5
- package/dist/commands/calls.d.ts.map +0 -1
- package/dist/commands/calls.js +0 -7
- package/dist/commands/calls.js.map +0 -1
- package/dist/commands/command-helpers.d.ts +0 -15
- package/dist/commands/command-helpers.d.ts.map +0 -1
- package/dist/commands/command-helpers.js +0 -61
- package/dist/commands/command-helpers.js.map +0 -1
- package/dist/commands/dead-exports.d.ts +0 -5
- package/dist/commands/dead-exports.d.ts.map +0 -1
- package/dist/commands/dead-exports.js +0 -7
- package/dist/commands/dead-exports.js.map +0 -1
- package/dist/commands/dead_exports.d.ts +0 -5
- package/dist/commands/dead_exports.d.ts.map +0 -1
- package/dist/commands/dead_exports.js +0 -7
- package/dist/commands/dead_exports.js.map +0 -1
- package/dist/commands/extract.d.ts +0 -8
- package/dist/commands/extract.d.ts.map +0 -1
- package/dist/commands/extract.js +0 -49
- package/dist/commands/extract.js.map +0 -1
- package/dist/commands/find.d.ts +0 -5
- package/dist/commands/find.d.ts.map +0 -1
- package/dist/commands/find.js +0 -7
- package/dist/commands/find.js.map +0 -1
- package/dist/commands/load.d.ts.map +0 -1
- package/dist/commands/load.js +0 -28
- package/dist/commands/load.js.map +0 -1
- package/dist/commands/neighbors.d.ts +0 -5
- package/dist/commands/neighbors.d.ts.map +0 -1
- package/dist/commands/neighbors.js +0 -17
- package/dist/commands/neighbors.js.map +0 -1
- package/dist/commands/optimize.d.ts +0 -6
- package/dist/commands/optimize.d.ts.map +0 -1
- package/dist/commands/optimize.js +0 -59
- package/dist/commands/optimize.js.map +0 -1
- package/dist/commands/optimize_command.d.ts +0 -6
- package/dist/commands/optimize_command.d.ts.map +0 -1
- package/dist/commands/optimize_command.js +0 -59
- package/dist/commands/optimize_command.js.map +0 -1
- package/dist/commands/references.d.ts +0 -5
- package/dist/commands/references.d.ts.map +0 -1
- package/dist/commands/references.js +0 -17
- package/dist/commands/references.js.map +0 -1
- package/dist/commands/web.d.ts +0 -19
- package/dist/commands/web.d.ts.map +0 -1
- package/dist/commands/web.js +0 -120
- package/dist/commands/web.js.map +0 -1
- package/dist/commands/who-calls.d.ts +0 -5
- package/dist/commands/who-calls.d.ts.map +0 -1
- package/dist/commands/who-calls.js +0 -7
- package/dist/commands/who-calls.js.map +0 -1
- package/dist/commands/who_calls.d.ts +0 -5
- package/dist/commands/who_calls.d.ts.map +0 -1
- package/dist/commands/who_calls.js +0 -7
- package/dist/commands/who_calls.js.map +0 -1
- package/dist/extract/graph-builder.d.ts +0 -16
- package/dist/extract/graph-builder.d.ts.map +0 -1
- package/dist/extract/graph-builder.js +0 -39
- package/dist/extract/graph-builder.js.map +0 -1
- package/dist/extract/node-id.d.ts +0 -8
- package/dist/extract/node-id.d.ts.map +0 -1
- package/dist/extract/node-id.js +0 -22
- package/dist/extract/node-id.js.map +0 -1
- package/dist/extract/project-loader.d.ts +0 -5
- package/dist/extract/project-loader.d.ts.map +0 -1
- package/dist/extract/project-loader.js +0 -19
- package/dist/extract/project-loader.js.map +0 -1
- package/dist/extract/semantic-extractor.d.ts +0 -22
- package/dist/extract/semantic-extractor.d.ts.map +0 -1
- package/dist/extract/semantic-extractor.js +0 -254
- package/dist/extract/semantic-extractor.js.map +0 -1
- package/dist/extract/structural-extractor.d.ts +0 -18
- package/dist/extract/structural-extractor.d.ts.map +0 -1
- package/dist/extract/structural-extractor.js +0 -97
- package/dist/extract/structural-extractor.js.map +0 -1
- package/dist/query/graph-query.d.ts +0 -28
- package/dist/query/graph-query.d.ts.map +0 -1
- package/dist/query/graph-query.js +0 -93
- package/dist/query/graph-query.js.map +0 -1
- package/dist/store/jsonl-reader.d.ts +0 -11
- package/dist/store/jsonl-reader.d.ts.map +0 -1
- package/dist/store/jsonl-reader.js +0 -19
- package/dist/store/jsonl-reader.js.map +0 -1
- package/dist/store/jsonl-store.d.ts +0 -7
- package/dist/store/jsonl-store.d.ts.map +0 -1
- package/dist/store/jsonl-store.js +0 -13
- package/dist/store/jsonl-store.js.map +0 -1
- package/dist/store/kuzu-store.d.ts +0 -14
- package/dist/store/kuzu-store.d.ts.map +0 -1
- package/dist/store/kuzu-store.js +0 -52
- 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,
|
|
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
|
|
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=
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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
|
|
11
|
-
*
|
|
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":"
|
|
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
|
-
|
|
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,
|
|
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
|
|
34
|
-
*
|
|
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
|
-
|
|
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,
|
|
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;
|
|
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 @@
|
|
|
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
|