ts-knowledge-graph 0.1.1 → 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 +104 -43
- package/contribs/web_visualisation/README.md +83 -0
- package/contribs/web_visualisation/web/css/style.css +219 -0
- package/contribs/web_visualisation/web/data/.gitignore +3 -0
- package/contribs/web_visualisation/web/data/kind_descriptions.js +38 -0
- package/contribs/web_visualisation/web/index.html +74 -0
- package/contribs/web_visualisation/web/js/app.js +910 -0
- 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 +0 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +32 -208
- 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.d.ts +5 -0
- package/dist/commands/blast_radius_command.d.ts.map +1 -0
- package/dist/commands/blast_radius_command.js +18 -0
- package/dist/commands/blast_radius_command.js.map +1 -0
- package/dist/commands/calls_command.d.ts +5 -0
- package/dist/commands/calls_command.d.ts.map +1 -0
- package/dist/commands/calls_command.js +7 -0
- package/dist/commands/calls_command.js.map +1 -0
- package/dist/commands/command_helpers.d.ts +15 -0
- package/dist/commands/command_helpers.d.ts.map +1 -0
- package/dist/commands/command_helpers.js +61 -0
- package/dist/commands/command_helpers.js.map +1 -0
- 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/dead_exports_command.d.ts +5 -0
- package/dist/commands/dead_exports_command.d.ts.map +1 -0
- package/dist/commands/dead_exports_command.js +7 -0
- package/dist/commands/dead_exports_command.js.map +1 -0
- package/dist/commands/enrich_command.d.ts +7 -0
- 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/extract_command.d.ts +8 -0
- package/dist/commands/extract_command.d.ts.map +1 -0
- package/dist/commands/extract_command.js +49 -0
- package/dist/commands/extract_command.js.map +1 -0
- package/dist/commands/find_command.d.ts +5 -0
- package/dist/commands/find_command.d.ts.map +1 -0
- package/dist/commands/find_command.js +7 -0
- package/dist/commands/find_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 +15 -0
- package/dist/commands/install_command.d.ts.map +1 -0
- package/dist/commands/install_command.js +41 -0
- package/dist/commands/install_command.js.map +1 -0
- package/dist/commands/load_command.d.ts +6 -0
- package/dist/commands/load_command.d.ts.map +1 -0
- package/dist/commands/load_command.js +30 -0
- package/dist/commands/load_command.js.map +1 -0
- package/dist/commands/neighbors_command.d.ts +5 -0
- package/dist/commands/neighbors_command.d.ts.map +1 -0
- package/dist/commands/neighbors_command.js +17 -0
- package/dist/commands/neighbors_command.js.map +1 -0
- package/dist/commands/references_command.d.ts +5 -0
- package/dist/commands/references_command.d.ts.map +1 -0
- package/dist/commands/references_command.js +17 -0
- package/dist/commands/references_command.js.map +1 -0
- 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 +46 -0
- package/dist/commands/web_command.d.ts.map +1 -0
- package/dist/commands/web_command.js +226 -0
- package/dist/commands/web_command.js.map +1 -0
- package/dist/commands/who_calls_command.d.ts +5 -0
- package/dist/commands/who_calls_command.d.ts.map +1 -0
- package/dist/commands/who_calls_command.js +7 -0
- package/dist/commands/who_calls_command.js.map +1 -0
- 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 → graph_builder.d.ts} +9 -1
- package/dist/extract/graph_builder.d.ts.map +1 -0
- package/dist/extract/graph_builder.js +61 -0
- package/dist/extract/graph_builder.js.map +1 -0
- package/dist/extract/node_id.d.ts +24 -0
- package/dist/extract/node_id.d.ts.map +1 -0
- package/dist/extract/node_id.js +44 -0
- package/dist/extract/node_id.js.map +1 -0
- package/dist/extract/{project-loader.d.ts → project_loader.d.ts} +1 -1
- package/dist/extract/project_loader.d.ts.map +1 -0
- package/dist/extract/{project-loader.js → project_loader.js} +1 -1
- package/dist/extract/{project-loader.js.map → project_loader.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 +47 -0
- package/dist/extract/semantic_extractor.d.ts.map +1 -0
- package/dist/extract/{semantic-extractor.js → semantic_extractor.js} +98 -4
- package/dist/extract/semantic_extractor.js.map +1 -0
- package/dist/extract/{structural-extractor.d.ts → structural_extractor.d.ts} +7 -1
- package/dist/extract/{structural-extractor.d.ts.map → structural_extractor.d.ts.map} +1 -1
- package/dist/extract/{structural-extractor.js → structural_extractor.js} +24 -14
- package/dist/extract/structural_extractor.js.map +1 -0
- 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 +262 -0
- package/dist/query/graph_query.d.ts.map +1 -0
- package/dist/query/graph_query.js +604 -0
- package/dist/query/graph_query.js.map +1 -0
- 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/{jsonl-reader.d.ts → jsonl_reader.d.ts} +1 -1
- package/dist/store/{jsonl-reader.d.ts.map → jsonl_reader.d.ts.map} +1 -1
- package/dist/store/{jsonl-reader.js → jsonl_reader.js} +1 -1
- package/dist/store/{jsonl-reader.js.map → jsonl_reader.js.map} +1 -1
- package/dist/store/{jsonl-store.d.ts → jsonl_store.d.ts} +1 -1
- package/dist/store/{jsonl-store.d.ts.map → jsonl_store.d.ts.map} +1 -1
- package/dist/store/{jsonl-store.js → jsonl_store.js} +1 -1
- package/dist/store/{jsonl-store.js.map → jsonl_store.js.map} +1 -1
- package/dist/store/kuzu_store.d.ts +66 -0
- package/dist/store/kuzu_store.d.ts.map +1 -0
- package/dist/store/kuzu_store.js +156 -0
- package/dist/store/kuzu_store.js.map +1 -0
- 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/dotclaude_folder/skills/code-graph-query/SKILL.md +91 -0
- package/package.json +88 -5
- 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/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/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/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.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.map +0 -1
- 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/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,156 @@
|
|
|
1
|
+
import { mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { Connection, Database } from 'kuzu';
|
|
4
|
+
const SCHEMA = [
|
|
5
|
+
'CREATE NODE TABLE IF NOT EXISTS GraphNode (id STRING, kind STRING, name STRING, filePath STRING, exported BOOLEAN, startLine INT64, endLine INT64, metadata STRING, PRIMARY KEY (id))',
|
|
6
|
+
'CREATE REL TABLE IF NOT EXISTS Edge (FROM GraphNode TO GraphNode, kind STRING, metadata STRING)',
|
|
7
|
+
'CREATE NODE TABLE IF NOT EXISTS GraphMeta (key STRING, value STRING, PRIMARY KEY (key))',
|
|
8
|
+
];
|
|
9
|
+
export class KuzuStore {
|
|
10
|
+
constructor(dbPath) {
|
|
11
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
12
|
+
this.db = new Database(dbPath);
|
|
13
|
+
this.conn = new Connection(this.db);
|
|
14
|
+
}
|
|
15
|
+
async initSchema() {
|
|
16
|
+
for (const statement of SCHEMA) {
|
|
17
|
+
KuzuStore.closeResults(await this.conn.query(statement));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async load(nodes, edges) {
|
|
21
|
+
const nodeStmt = await this.conn.prepare('MERGE (n:GraphNode {id: $id}) SET n.kind = $kind, n.name = $name, n.filePath = $filePath, n.exported = $exported, n.startLine = $startLine, n.endLine = $endLine, n.metadata = $metadata');
|
|
22
|
+
for (const node of nodes) {
|
|
23
|
+
KuzuStore.closeResults(await this.conn.execute(nodeStmt, {
|
|
24
|
+
id: node.id,
|
|
25
|
+
kind: node.kind,
|
|
26
|
+
name: node.name,
|
|
27
|
+
filePath: node.filePath,
|
|
28
|
+
exported: node.exported ?? false,
|
|
29
|
+
startLine: node.range?.startLine ?? 0,
|
|
30
|
+
endLine: node.range?.endLine ?? 0,
|
|
31
|
+
metadata: KuzuStore.encodeMetadata(node.metadata),
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
const edgeStmt = await this.conn.prepare('MATCH (f:GraphNode {id: $from}), (t:GraphNode {id: $to}) MERGE (f)-[e:Edge {kind: $kind}]->(t) SET e.metadata = $metadata');
|
|
35
|
+
for (const edge of edges) {
|
|
36
|
+
KuzuStore.closeResults(await this.conn.execute(edgeStmt, {
|
|
37
|
+
from: edge.from,
|
|
38
|
+
to: edge.to,
|
|
39
|
+
kind: edge.kind,
|
|
40
|
+
metadata: KuzuStore.encodeMetadata(edge.metadata),
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Reads every node back from the store, decoding the `metadata` column. Used
|
|
46
|
+
* by enrichment to resolve profile frames against the loaded graph's ranges
|
|
47
|
+
* and to merge new metadata onto existing records.
|
|
48
|
+
*/
|
|
49
|
+
async readNodes() {
|
|
50
|
+
const rows = await this.run('MATCH (n:GraphNode) RETURN n.id AS id, n.kind AS kind, n.name AS name, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine, n.metadata AS metadata');
|
|
51
|
+
return rows.map((row) => ({
|
|
52
|
+
id: String(row.id),
|
|
53
|
+
kind: String(row.kind),
|
|
54
|
+
name: String(row.name),
|
|
55
|
+
filePath: String(row.filePath),
|
|
56
|
+
startLine: Number(row.startLine),
|
|
57
|
+
endLine: Number(row.endLine),
|
|
58
|
+
metadata: KuzuStore.decodeMetadata(row.metadata),
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Overwrites the `metadata` column for the given nodes. The caller is
|
|
63
|
+
* responsible for merging so that only the intended keys change; passing the
|
|
64
|
+
* full record keeps the write idempotent for unchanged keys.
|
|
65
|
+
*/
|
|
66
|
+
async writeNodeMetadata(entries) {
|
|
67
|
+
if (entries.length === 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const stmt = await this.conn.prepare('MATCH (n:GraphNode {id: $id}) SET n.metadata = $metadata');
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
KuzuStore.closeResults(await this.conn.execute(stmt, {
|
|
73
|
+
id: entry.id,
|
|
74
|
+
metadata: KuzuStore.encodeMetadata(entry.metadata),
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Writes a graph-level metadata record under `key` (a `GraphMeta` row), encoding
|
|
80
|
+
* the value as JSON. Used for facts about the whole graph rather than one node —
|
|
81
|
+
* e.g. the runtime ingest manifest `enrich` records for coverage reporting.
|
|
82
|
+
*/
|
|
83
|
+
async writeGraphMeta(key, value) {
|
|
84
|
+
const stmt = await this.conn.prepare('MERGE (m:GraphMeta {key: $key}) SET m.value = $value');
|
|
85
|
+
KuzuStore.closeResults(await this.conn.execute(stmt, { key, value: KuzuStore.encodeMetadata(value) }));
|
|
86
|
+
}
|
|
87
|
+
/** Reads the graph-level metadata record stored under `key`, decoded, or null when absent. */
|
|
88
|
+
async readGraphMeta(key) {
|
|
89
|
+
const rows = await this.run('MATCH (m:GraphMeta {key: $key}) RETURN m.value AS value', { key });
|
|
90
|
+
if (rows.length === 0) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return KuzuStore.decodeMetadata(rows[0].value);
|
|
94
|
+
}
|
|
95
|
+
/** Removes the graph-level metadata record stored under `key`, if any. */
|
|
96
|
+
async clearGraphMeta(key) {
|
|
97
|
+
const stmt = await this.conn.prepare('MATCH (m:GraphMeta {key: $key}) DELETE m');
|
|
98
|
+
KuzuStore.closeResults(await this.conn.execute(stmt, { key }));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Serializes an optional metadata record to a JSON string for storage in the
|
|
102
|
+
* `metadata` column. Absent metadata is stored as an empty object so the
|
|
103
|
+
* column is never null.
|
|
104
|
+
*/
|
|
105
|
+
static encodeMetadata(metadata) {
|
|
106
|
+
return JSON.stringify(metadata ?? {});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Decodes the JSON `metadata` column back into a record. A missing, empty, or
|
|
110
|
+
* malformed value decodes to an empty object so callers always receive a record.
|
|
111
|
+
*/
|
|
112
|
+
static decodeMetadata(value) {
|
|
113
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
114
|
+
return {};
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const parsed = JSON.parse(value);
|
|
118
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
119
|
+
return parsed;
|
|
120
|
+
}
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return {};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async run(cypher, params) {
|
|
128
|
+
const result = params === undefined
|
|
129
|
+
? await this.conn.query(cypher)
|
|
130
|
+
: await this.conn.execute(await this.conn.prepare(cypher), params);
|
|
131
|
+
try {
|
|
132
|
+
return await KuzuStore.first(result).getAll();
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
KuzuStore.closeResults(result);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async close() {
|
|
139
|
+
await this.conn.close();
|
|
140
|
+
await this.db.close();
|
|
141
|
+
}
|
|
142
|
+
static first(result) {
|
|
143
|
+
return Array.isArray(result) ? result[0] : result;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Releases the native memory behind one or more query results. Results left
|
|
147
|
+
* unclosed are finalized after the database shuts down at process exit,
|
|
148
|
+
* which crashes the kuzu native module with a segmentation fault.
|
|
149
|
+
*/
|
|
150
|
+
static closeResults(result) {
|
|
151
|
+
for (const item of Array.isArray(result) ? result : [result]) {
|
|
152
|
+
item.close();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=kuzu_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kuzu_store.js","sourceRoot":"","sources":["../../src/store/kuzu_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reusable verify path for the optimization loop: run the project's
|
|
3
|
+
* type-check and test gates and reduce them to one pass/fail verdict, plus the
|
|
4
|
+
* honesty flags an agent needs (was *behaviour* verified, or only types?).
|
|
5
|
+
*
|
|
6
|
+
* A type-check proves the edit compiles; it cannot see a swapped operator, an
|
|
7
|
+
* off-by-one, or a dropped branch. Running the test suite alongside `tsc` is
|
|
8
|
+
* what turns "still compiles" into "still works". When a project has no test
|
|
9
|
+
* script the test gate degrades to skipped and {@link VerifyReport.behaviorVerified}
|
|
10
|
+
* stays false, so the caller can report the change as unverified rather than
|
|
11
|
+
* implying it was behaviourally checked.
|
|
12
|
+
*/
|
|
13
|
+
/** The two correctness gates, run in order. */
|
|
14
|
+
export type CheckName = 'typecheck' | 'test';
|
|
15
|
+
/** A gate ran and passed, ran and failed, or never ran. */
|
|
16
|
+
export type CheckStatus = 'pass' | 'fail' | 'skipped';
|
|
17
|
+
/** A gate resolved from the project's package.json: its command, or why it was skipped. */
|
|
18
|
+
export type PlannedCheck = {
|
|
19
|
+
name: CheckName;
|
|
20
|
+
/** The shell command to run, or `null` when the gate is skipped. */
|
|
21
|
+
command: string | null;
|
|
22
|
+
/** Why the gate will not run (e.g. no matching npm script), set when `command` is null. */
|
|
23
|
+
skippedReason?: string;
|
|
24
|
+
};
|
|
25
|
+
/** The outcome of executing (or skipping) one gate. */
|
|
26
|
+
export type CheckResult = {
|
|
27
|
+
name: CheckName;
|
|
28
|
+
command: string | null;
|
|
29
|
+
status: CheckStatus;
|
|
30
|
+
/** Process exit code; `null` when the gate was skipped or the process died on a signal. */
|
|
31
|
+
exitCode: number | null;
|
|
32
|
+
durationMs: number;
|
|
33
|
+
/** Combined stdout+stderr, tail-bounded to the last `outputTailLines` lines. */
|
|
34
|
+
output: string;
|
|
35
|
+
skippedReason?: string;
|
|
36
|
+
};
|
|
37
|
+
/** The single verdict the optimize loop consumes to keep or revert an edit. */
|
|
38
|
+
export type VerifyReport = {
|
|
39
|
+
/** True when at least one gate ran and no gate that ran failed. */
|
|
40
|
+
ok: boolean;
|
|
41
|
+
/** True only when the test gate actually ran and passed — behaviour, not just types, was checked. */
|
|
42
|
+
behaviorVerified: boolean;
|
|
43
|
+
/** True when a gate was skipped (e.g. the project has no test script), so `ok` is weaker than a full pass. */
|
|
44
|
+
degraded: boolean;
|
|
45
|
+
checks: CheckResult[];
|
|
46
|
+
/** A one-line, quotable verdict that states exactly what was and was not verified. */
|
|
47
|
+
summary: string;
|
|
48
|
+
};
|
|
49
|
+
export type VerifyOptions = {
|
|
50
|
+
/** Project root whose package.json is read and whose scripts are run. Defaults to `process.cwd()`. */
|
|
51
|
+
cwd?: string;
|
|
52
|
+
/** npm script name for the type-check gate. Default `typecheck`. */
|
|
53
|
+
typecheckScript?: string;
|
|
54
|
+
/** npm script name for the test gate. Default `test`. */
|
|
55
|
+
testScript?: string;
|
|
56
|
+
/** Skip the type-check gate entirely. */
|
|
57
|
+
skipTypecheck?: boolean;
|
|
58
|
+
/** Skip the test gate entirely (degrades to type-check-only, reported honestly). */
|
|
59
|
+
skipTests?: boolean;
|
|
60
|
+
/** Keep only the last N lines of each gate's captured output. Default 80. */
|
|
61
|
+
outputTailLines?: number;
|
|
62
|
+
};
|
|
63
|
+
/** How a planned gate is executed. Injectable so tests need not spawn npm. */
|
|
64
|
+
export type CheckExecutor = (command: string, cwd: string) => Promise<{
|
|
65
|
+
exitCode: number | null;
|
|
66
|
+
output: string;
|
|
67
|
+
}>;
|
|
68
|
+
export declare class ProjectVerifier {
|
|
69
|
+
/**
|
|
70
|
+
* Run the project's verify gates and return one verdict. `exec` defaults to a
|
|
71
|
+
* real subprocess spawn; tests inject a fake to avoid running npm.
|
|
72
|
+
*/
|
|
73
|
+
static verify(options?: VerifyOptions, exec?: CheckExecutor): Promise<VerifyReport>;
|
|
74
|
+
/** Resolve each gate against the project's scripts, deciding what will run and what is skipped (pure). */
|
|
75
|
+
static planChecks(scripts: Record<string, string>, options?: VerifyOptions): PlannedCheck[];
|
|
76
|
+
/** Reduce a set of gate results to the single verdict, including the honesty flags (pure). */
|
|
77
|
+
static summarize(checks: CheckResult[]): VerifyReport;
|
|
78
|
+
private static planOne;
|
|
79
|
+
private static runCheck;
|
|
80
|
+
private static buildSummary;
|
|
81
|
+
private static readScripts;
|
|
82
|
+
private static tail;
|
|
83
|
+
private static spawnCommand;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=project_verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project_verifier.d.ts","sourceRoot":"","sources":["../../src/verify/project_verifier.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;AAE7C,2DAA2D;AAC3D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEtD,2FAA2F;AAC3F,MAAM,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,WAAW,CAAC;IACpB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,YAAY,GAAG;IAC1B,mEAAmE;IACnE,EAAE,EAAE,OAAO,CAAC;IACZ,qGAAqG;IACrG,gBAAgB,EAAE,OAAO,CAAC;IAC1B,8GAA8G;IAC9G,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,sGAAsG;IACtG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAQnH,qBAAa,eAAe;IAC3B;;;OAGG;WACU,MAAM,CAAC,OAAO,GAAE,aAAkB,EAAE,IAAI,GAAE,aAA4C,GAAG,OAAO,CAAC,YAAY,CAAC;IAY3H,0GAA0G;IAC1G,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAE,aAAkB,GAAG,YAAY,EAAE;IAS/F,8FAA8F;IAC9F,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY;IAWrD,OAAO,CAAC,MAAM,CAAC,OAAO;mBAUD,QAAQ;IAwB7B,OAAO,CAAC,MAAM,CAAC,YAAY;mBAoBN,WAAW;IAmBhC,OAAO,CAAC,MAAM,CAAC,IAAI;IAWnB,OAAO,CAAC,MAAM,CAAC,YAAY;CAkB3B"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const DEFAULT_TYPECHECK_SCRIPT = 'typecheck';
|
|
6
|
+
const DEFAULT_TEST_SCRIPT = 'test';
|
|
7
|
+
const DEFAULT_TAIL_LINES = 80;
|
|
8
|
+
const PackageJsonSchema = z.object({ scripts: z.record(z.unknown()).optional() });
|
|
9
|
+
export class ProjectVerifier {
|
|
10
|
+
/**
|
|
11
|
+
* Run the project's verify gates and return one verdict. `exec` defaults to a
|
|
12
|
+
* real subprocess spawn; tests inject a fake to avoid running npm.
|
|
13
|
+
*/
|
|
14
|
+
static async verify(options = {}, exec = ProjectVerifier.spawnCommand) {
|
|
15
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
16
|
+
const tailLines = options.outputTailLines ?? DEFAULT_TAIL_LINES;
|
|
17
|
+
const scripts = await ProjectVerifier.readScripts(cwd);
|
|
18
|
+
const plan = ProjectVerifier.planChecks(scripts, options);
|
|
19
|
+
const results = [];
|
|
20
|
+
for (const check of plan) {
|
|
21
|
+
results.push(await ProjectVerifier.runCheck(check, cwd, tailLines, exec));
|
|
22
|
+
}
|
|
23
|
+
return ProjectVerifier.summarize(results);
|
|
24
|
+
}
|
|
25
|
+
/** Resolve each gate against the project's scripts, deciding what will run and what is skipped (pure). */
|
|
26
|
+
static planChecks(scripts, options = {}) {
|
|
27
|
+
const typecheckScript = options.typecheckScript ?? DEFAULT_TYPECHECK_SCRIPT;
|
|
28
|
+
const testScript = options.testScript ?? DEFAULT_TEST_SCRIPT;
|
|
29
|
+
return [
|
|
30
|
+
ProjectVerifier.planOne('typecheck', typecheckScript, scripts, options.skipTypecheck === true),
|
|
31
|
+
ProjectVerifier.planOne('test', testScript, scripts, options.skipTests === true),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
/** Reduce a set of gate results to the single verdict, including the honesty flags (pure). */
|
|
35
|
+
static summarize(checks) {
|
|
36
|
+
const ran = checks.filter((check) => check.status !== 'skipped');
|
|
37
|
+
const failed = ran.filter((check) => check.status === 'fail');
|
|
38
|
+
const test = checks.find((check) => check.name === 'test');
|
|
39
|
+
const behaviorVerified = test !== undefined && test.status === 'pass';
|
|
40
|
+
const ok = ran.length > 0 && failed.length === 0;
|
|
41
|
+
const degraded = checks.some((check) => check.status === 'skipped');
|
|
42
|
+
const summary = ProjectVerifier.buildSummary(ran, failed, test, ok, behaviorVerified);
|
|
43
|
+
return { ok, behaviorVerified, degraded, checks, summary };
|
|
44
|
+
}
|
|
45
|
+
static planOne(name, script, scripts, skip) {
|
|
46
|
+
if (skip === true) {
|
|
47
|
+
return { name, command: null, skippedReason: 'skipped by request' };
|
|
48
|
+
}
|
|
49
|
+
if (typeof scripts[script] !== 'string') {
|
|
50
|
+
return { name, command: null, skippedReason: `no "${script}" script in package.json` };
|
|
51
|
+
}
|
|
52
|
+
return { name, command: `npm run ${script}` };
|
|
53
|
+
}
|
|
54
|
+
static async runCheck(check, cwd, tailLines, exec) {
|
|
55
|
+
if (check.command === null) {
|
|
56
|
+
return {
|
|
57
|
+
name: check.name,
|
|
58
|
+
command: null,
|
|
59
|
+
status: 'skipped',
|
|
60
|
+
exitCode: null,
|
|
61
|
+
durationMs: 0,
|
|
62
|
+
output: '',
|
|
63
|
+
skippedReason: check.skippedReason,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const startedAt = Date.now();
|
|
67
|
+
const { exitCode, output } = await exec(check.command, cwd);
|
|
68
|
+
return {
|
|
69
|
+
name: check.name,
|
|
70
|
+
command: check.command,
|
|
71
|
+
status: exitCode === 0 ? 'pass' : 'fail',
|
|
72
|
+
exitCode,
|
|
73
|
+
durationMs: Date.now() - startedAt,
|
|
74
|
+
output: ProjectVerifier.tail(output, tailLines),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
static buildSummary(ran, failed, test, ok, behaviorVerified) {
|
|
78
|
+
if (ran.length === 0) {
|
|
79
|
+
return 'could not verify: no type-check or test script found — change is unverified';
|
|
80
|
+
}
|
|
81
|
+
if (ok === false) {
|
|
82
|
+
return `FAILED: ${failed.map((check) => check.name).join(' and ')} did not pass — revert the edit`;
|
|
83
|
+
}
|
|
84
|
+
if (behaviorVerified === true) {
|
|
85
|
+
return `verified: ${ran.map((check) => check.name).join(' + ')} passed (behaviour checked)`;
|
|
86
|
+
}
|
|
87
|
+
const why = test?.skippedReason ?? 'tests did not run';
|
|
88
|
+
return `type-check passed, but ${why} — behaviour NOT verified`;
|
|
89
|
+
}
|
|
90
|
+
static async readScripts(cwd) {
|
|
91
|
+
try {
|
|
92
|
+
const raw = await readFile(resolve(cwd, 'package.json'), 'utf8');
|
|
93
|
+
const parsed = PackageJsonSchema.safeParse(JSON.parse(raw));
|
|
94
|
+
if (parsed.success === false) {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
const scripts = {};
|
|
98
|
+
for (const [name, value] of Object.entries(parsed.data.scripts ?? {})) {
|
|
99
|
+
if (typeof value === 'string') {
|
|
100
|
+
scripts[name] = value;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return scripts;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
static tail(text, lines) {
|
|
110
|
+
if (lines <= 0) {
|
|
111
|
+
return text;
|
|
112
|
+
}
|
|
113
|
+
const allLines = text.split('\n');
|
|
114
|
+
if (allLines.length <= lines) {
|
|
115
|
+
return text;
|
|
116
|
+
}
|
|
117
|
+
return allLines.slice(allLines.length - lines).join('\n');
|
|
118
|
+
}
|
|
119
|
+
static spawnCommand(command, cwd) {
|
|
120
|
+
return new Promise((resolvePromise) => {
|
|
121
|
+
const child = spawn(command, { cwd, shell: true });
|
|
122
|
+
let output = '';
|
|
123
|
+
const append = (chunk) => {
|
|
124
|
+
output += chunk.toString();
|
|
125
|
+
};
|
|
126
|
+
child.stdout.on('data', append);
|
|
127
|
+
child.stderr.on('data', append);
|
|
128
|
+
child.on('error', (error) => {
|
|
129
|
+
output += `\n${error.message}`;
|
|
130
|
+
resolvePromise({ exitCode: 1, output });
|
|
131
|
+
});
|
|
132
|
+
child.on('close', (code) => {
|
|
133
|
+
resolvePromise({ exitCode: code, output });
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=project_verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project_verifier.js","sourceRoot":"","sources":["../../src/verify/project_verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0ExB,MAAM,wBAAwB,GAAG,WAAW,CAAC;AAC7C,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAElF,MAAM,OAAO,eAAe;IAC3B;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAyB,EAAE,EAAE,OAAsB,eAAe,CAAC,YAAY;QAClG,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,IAAI,kBAAkB,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,MAAM,eAAe,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,0GAA0G;IAC1G,MAAM,CAAC,UAAU,CAAC,OAA+B,EAAE,UAAyB,EAAE;QAC7E,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,wBAAwB,CAAC;QAC5E,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC7D,OAAO;YACN,eAAe,CAAC,OAAO,CAAC,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,KAAK,IAAI,CAAC;YAC9F,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC;SAChF,CAAC;IACH,CAAC;IAED,8FAA8F;IAC9F,MAAM,CAAC,SAAS,CAAC,MAAqB;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC3D,MAAM,gBAAgB,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC;QACtE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,eAAe,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC;QACtF,OAAO,EAAE,EAAE,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC5D,CAAC;IAEO,MAAM,CAAC,OAAO,CAAC,IAAe,EAAE,MAAc,EAAE,OAA+B,EAAE,IAAa;QACrG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC;QACrE,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;YACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,MAAM,0BAA0B,EAAE,CAAC;QACxF,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,MAAM,EAAE,EAAE,CAAC;IAC/C,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAmB,EAAE,GAAW,EAAE,SAAiB,EAAE,IAAmB;QACrG,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO;gBACN,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,EAAE;gBACV,aAAa,EAAE,KAAK,CAAC,aAAa;aAClC,CAAC;QACH,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5D,OAAO;YACN,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YACxC,QAAQ;YACR,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC;SAC/C,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,YAAY,CAC1B,GAAkB,EAClB,MAAqB,EACrB,IAA6B,EAC7B,EAAW,EACX,gBAAyB;QAEzB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,6EAA6E,CAAC;QACtF,CAAC;QACD,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;YAClB,OAAO,WAAW,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC;QACpG,CAAC;QACD,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC/B,OAAO,aAAa,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC;QAC7F,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,EAAE,aAAa,IAAI,mBAAmB,CAAC;QACvD,OAAO,0BAA0B,GAAG,2BAA2B,CAAC;IACjE,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAW;QAC3C,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5D,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;YACX,CAAC;YACD,MAAM,OAAO,GAA2B,EAAE,CAAC;YAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;gBACvE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;gBACvB,CAAC;YACF,CAAC;YACD,OAAO,OAAO,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC;IAEO,MAAM,CAAC,IAAI,CAAC,IAAY,EAAE,KAAa;QAC9C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACb,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IAEO,MAAM,CAAC,YAAY,CAAC,OAAe,EAAE,GAAW;QACvD,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,CAAC,KAAa,EAAQ,EAAE;gBACtC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC3B,MAAM,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/B,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC1B,cAAc,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5C,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-graph-query
|
|
3
|
+
description: >-
|
|
4
|
+
Query a TypeScript codebase as a knowledge graph to answer impact, caller,
|
|
5
|
+
dependency, and dead-code questions. Use this instead of grep/glob for
|
|
6
|
+
"who calls X", "what breaks if I change X" (blast radius), "is X dead code",
|
|
7
|
+
"what references this type", and "what is X connected to". Requires the
|
|
8
|
+
ts-knowledge-graph CLI and a built graph database.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# code-graph-query
|
|
12
|
+
|
|
13
|
+
Answer structural questions about a TypeScript project by querying a semantic
|
|
14
|
+
knowledge graph (built with the TypeScript compiler API) rather than reading or
|
|
15
|
+
grepping source files. The graph has resolved symbols and types, so its answers
|
|
16
|
+
are precise where text search is not.
|
|
17
|
+
|
|
18
|
+
## When to use this skill
|
|
19
|
+
|
|
20
|
+
Reach for these commands — not `Grep`/`Glob` — when the question is about code
|
|
21
|
+
structure or impact:
|
|
22
|
+
|
|
23
|
+
- **Callers** — "who calls this function?" → `who-calls`
|
|
24
|
+
- **Callees** — "what does this function call?" → `calls`
|
|
25
|
+
- **Impact / blast radius** — "what breaks if I change this?" → `blast-radius`
|
|
26
|
+
- **References** — "what uses this symbol or type?" → `references`
|
|
27
|
+
- **Dead code** — "which exports are unused?" → `dead-exports`
|
|
28
|
+
- **Neighbourhood** — "what is this connected to?" → `neighbors`
|
|
29
|
+
|
|
30
|
+
For reading the actual implementation of a known file, normal file tools are
|
|
31
|
+
still the right choice. Use this skill to decide *which* code matters first.
|
|
32
|
+
|
|
33
|
+
## Prerequisite: build the graph once
|
|
34
|
+
|
|
35
|
+
Querying needs a Kùzu database at `./outputs/graph.kuzu`. If it is missing,
|
|
36
|
+
build it first (the `--semantic` flag is required for `CALLS` and heritage
|
|
37
|
+
edges, which power `who-calls`, `calls`, and `blast-radius`):
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx ts-knowledge-graph extract <path-to-project> --semantic # writes ./outputs/graph/*.jsonl
|
|
41
|
+
npx ts-knowledge-graph load # writes ./outputs/graph.kuzu
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Inside this repository's own checkout, substitute `npm run dev --` for the
|
|
45
|
+
`ts-knowledge-graph` binary (e.g. `npm run dev -- load`).
|
|
46
|
+
|
|
47
|
+
## Core workflow: names are not ids
|
|
48
|
+
|
|
49
|
+
Every query that inspects a symbol takes a **node id**, not a name. Resolve a
|
|
50
|
+
name to id(s) first with `find`, then pass an id to the other commands. Never
|
|
51
|
+
hand-write ids.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx ts-knowledge-graph find <name> --json # -> array of { id, name, kind, filePath, startLine }
|
|
55
|
+
npx ts-knowledge-graph who-calls <id> --json # use an id from the find result
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Always pass `--json`; consume the JSON, not the human-readable output.
|
|
59
|
+
|
|
60
|
+
## Command reference
|
|
61
|
+
|
|
62
|
+
All commands accept `--json` and `-d, --db <path>` (default `./outputs/graph.kuzu`).
|
|
63
|
+
|
|
64
|
+
| Command | Argument | Purpose |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| `find <pattern>` | name substring | resolve a name to node id(s) |
|
|
67
|
+
| `who-calls <id>` | node id | direct callers of a symbol |
|
|
68
|
+
| `calls <id>` | node id | what a symbol directly calls |
|
|
69
|
+
| `blast-radius <id> [--depth <n>]` | node id | transitive callers / impact set (default depth 10) |
|
|
70
|
+
| `references <id>` | node id | everything referencing a symbol/type (calls, type usage, heritage, new) |
|
|
71
|
+
| `neighbors <id>` | node id | one-hop neighbourhood, inbound and outbound |
|
|
72
|
+
| `dead-exports` | (none) | exported symbols with no inbound references |
|
|
73
|
+
|
|
74
|
+
## Output contract
|
|
75
|
+
|
|
76
|
+
- `find`, `who-calls`, `calls`, `blast-radius`, `dead-exports` return a JSON
|
|
77
|
+
array of `SymbolRef`: `{ id, kind, name, filePath, startLine }`.
|
|
78
|
+
- `references` and `neighbors` return `NeighborRef`: a `SymbolRef` plus
|
|
79
|
+
`edgeKind` and `direction` (`"in"` or `"out"`).
|
|
80
|
+
|
|
81
|
+
## Worked example
|
|
82
|
+
|
|
83
|
+
> "Is it safe to change the signature of `loadProject`?"
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx ts-knowledge-graph find loadProject --json # -> get its id
|
|
87
|
+
npx ts-knowledge-graph blast-radius <id> --json # -> every symbol transitively impacted
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Report the impacted set (file paths + names) as the blast radius, then read
|
|
91
|
+
those specific call sites to judge the change.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-knowledge-graph",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Parse TypeScript source into a knowledge graph for autonomous code optimization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
+
"contribs/web_visualisation/web",
|
|
12
|
+
"dotclaude_folder/skills/code-graph-query/SKILL.md",
|
|
11
13
|
"README.md",
|
|
12
|
-
"LICENSE"
|
|
13
|
-
".env-sample"
|
|
14
|
+
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"engines": {
|
|
16
17
|
"node": ">=18"
|
|
@@ -20,16 +21,98 @@
|
|
|
20
21
|
},
|
|
21
22
|
"scripts": {
|
|
22
23
|
"extract": "tsx src/cli.ts extract",
|
|
24
|
+
"web": "tsx src/cli.ts web",
|
|
23
25
|
"dev": "tsx src/cli.ts",
|
|
24
26
|
"build": "tsc -p tsconfig.build.json",
|
|
27
|
+
"clean": "npm run clean:dist && npm run clean:outputs",
|
|
28
|
+
"clean:dist": "rm -rf ./dist",
|
|
29
|
+
"clean:outputs": "rm -rf ./outputs/*/",
|
|
30
|
+
"symlink:dotclaude": "bash scripts/symlink_dotclaude.sh",
|
|
25
31
|
"publish:all": "npm run build && npm version patch && npm publish",
|
|
26
|
-
"typecheck": "tsc --noEmit"
|
|
32
|
+
"typecheck": "tsc --noEmit && tsc -p contribs/web_visualisation/web/tsconfig.json",
|
|
33
|
+
"test": "node --import tsx --test \"tests/**/*.test.ts\"",
|
|
34
|
+
"verify": "tsx src/cli.ts verify",
|
|
35
|
+
"project01": "npm run project01:rebuild && npm run project01:dead-exports",
|
|
36
|
+
"project01:tour": "bash scripts/project_01_tour.sh",
|
|
37
|
+
"project01:rebuild": "npm run project01:clean && npm run project01:extract && npm run project01:load",
|
|
38
|
+
"project01:clean": "rm -rf ./outputs/project_01",
|
|
39
|
+
"project01:extract": "tsx src/cli.ts extract sample_projects/project_01 --semantic --out ./outputs/project_01/graph",
|
|
40
|
+
"project01:load": "tsx src/cli.ts load ./outputs/project_01/graph --db ./outputs/project_01/graph.kuzu",
|
|
41
|
+
"project01:enrich": "bash scripts/profile_and_enrich.sh project_01",
|
|
42
|
+
"project01:benchmark": "tsx src/cli.ts benchmark titleCase --workload scripts/benchmarks/project_01_workload.ts --db ./outputs/project_01/graph.kuzu --root ./sample_projects/project_01 --runs 5",
|
|
43
|
+
"project01:verify": "tsx src/cli.ts verify --cwd sample_projects/project_01",
|
|
44
|
+
"project01:dead-exports": "tsx src/cli.ts dead-exports --db ./outputs/project_01/graph.kuzu",
|
|
45
|
+
"project01:hotspots": "tsx src/cli.ts hotspots --db ./outputs/project_01/graph.kuzu",
|
|
46
|
+
"project01:cost": "tsx src/cli.ts cost --db ./outputs/project_01/graph.kuzu",
|
|
47
|
+
"project01:find": "tsx src/cli.ts find --db ./outputs/project_01/graph.kuzu",
|
|
48
|
+
"project01:who-calls": "tsx src/cli.ts who-calls --db ./outputs/project_01/graph.kuzu",
|
|
49
|
+
"project01:calls": "tsx src/cli.ts calls --db ./outputs/project_01/graph.kuzu",
|
|
50
|
+
"project01:references": "tsx src/cli.ts references --db ./outputs/project_01/graph.kuzu",
|
|
51
|
+
"project01:neighbors": "tsx src/cli.ts neighbors --db ./outputs/project_01/graph.kuzu",
|
|
52
|
+
"project01:blast-radius": "tsx src/cli.ts blast-radius --db ./outputs/project_01/graph.kuzu",
|
|
53
|
+
"project01:web": "tsx src/cli.ts web --db ./outputs/project_01/graph.kuzu",
|
|
54
|
+
"project02": "npm run project02:rebuild && npm run project02:dead-exports",
|
|
55
|
+
"project02:tour": "bash scripts/project_02_tour.sh",
|
|
56
|
+
"project02:rebuild": "npm run project02:clean && npm run project02:extract && npm run project02:load",
|
|
57
|
+
"project02:clean": "rm -rf ./outputs/project_02",
|
|
58
|
+
"project02:extract": "tsx src/cli.ts extract sample_projects/project_02 --semantic --out ./outputs/project_02/graph",
|
|
59
|
+
"project02:load": "tsx src/cli.ts load ./outputs/project_02/graph --db ./outputs/project_02/graph.kuzu",
|
|
60
|
+
"project02:enrich": "bash scripts/profile_and_enrich.sh project_02",
|
|
61
|
+
"project02:benchmark": "tsx src/cli.ts benchmark parseTerm --workload scripts/benchmarks/project_02_workload.ts --db ./outputs/project_02/graph.kuzu --root ./sample_projects/project_02 --runs 5",
|
|
62
|
+
"project02:verify": "tsx src/cli.ts verify --cwd sample_projects/project_02",
|
|
63
|
+
"project02:dead-exports": "tsx src/cli.ts dead-exports --db ./outputs/project_02/graph.kuzu",
|
|
64
|
+
"project02:hotspots": "tsx src/cli.ts hotspots --db ./outputs/project_02/graph.kuzu",
|
|
65
|
+
"project02:cost": "tsx src/cli.ts cost --db ./outputs/project_02/graph.kuzu",
|
|
66
|
+
"project02:find": "tsx src/cli.ts find --db ./outputs/project_02/graph.kuzu",
|
|
67
|
+
"project02:who-calls": "tsx src/cli.ts who-calls --db ./outputs/project_02/graph.kuzu",
|
|
68
|
+
"project02:calls": "tsx src/cli.ts calls --db ./outputs/project_02/graph.kuzu",
|
|
69
|
+
"project02:references": "tsx src/cli.ts references --db ./outputs/project_02/graph.kuzu",
|
|
70
|
+
"project02:neighbors": "tsx src/cli.ts neighbors --db ./outputs/project_02/graph.kuzu",
|
|
71
|
+
"project02:blast-radius": "tsx src/cli.ts blast-radius --db ./outputs/project_02/graph.kuzu",
|
|
72
|
+
"project02:web": "tsx src/cli.ts web --db ./outputs/project_02/graph.kuzu",
|
|
73
|
+
"project03": "npm run project03:rebuild && npm run project03:dead-exports",
|
|
74
|
+
"project03:tour": "bash scripts/project_03_tour.sh",
|
|
75
|
+
"project03:rebuild": "npm run project03:clean && npm run project03:extract && npm run project03:load",
|
|
76
|
+
"project03:clean": "rm -rf ./outputs/project_03",
|
|
77
|
+
"project03:extract": "tsx src/cli.ts extract sample_projects/project_03 --semantic --out ./outputs/project_03/graph",
|
|
78
|
+
"project03:load": "tsx src/cli.ts load ./outputs/project_03/graph --db ./outputs/project_03/graph.kuzu",
|
|
79
|
+
"project03:enrich": "bash scripts/profile_and_enrich.sh project_03",
|
|
80
|
+
"project03:benchmark": "tsx src/cli.ts benchmark describe --workload scripts/benchmarks/project_03_workload.ts --db ./outputs/project_03/graph.kuzu --root ./sample_projects/project_03 --runs 5",
|
|
81
|
+
"project03:verify": "tsx src/cli.ts verify --cwd sample_projects/project_03",
|
|
82
|
+
"project03:dead-exports": "tsx src/cli.ts dead-exports --db ./outputs/project_03/graph.kuzu",
|
|
83
|
+
"project03:hotspots": "tsx src/cli.ts hotspots --db ./outputs/project_03/graph.kuzu",
|
|
84
|
+
"project03:cost": "tsx src/cli.ts cost --db ./outputs/project_03/graph.kuzu",
|
|
85
|
+
"project03:find": "tsx src/cli.ts find --db ./outputs/project_03/graph.kuzu",
|
|
86
|
+
"project03:who-calls": "tsx src/cli.ts who-calls --db ./outputs/project_03/graph.kuzu",
|
|
87
|
+
"project03:calls": "tsx src/cli.ts calls --db ./outputs/project_03/graph.kuzu",
|
|
88
|
+
"project03:references": "tsx src/cli.ts references --db ./outputs/project_03/graph.kuzu",
|
|
89
|
+
"project03:neighbors": "tsx src/cli.ts neighbors --db ./outputs/project_03/graph.kuzu",
|
|
90
|
+
"project03:blast-radius": "tsx src/cli.ts blast-radius --db ./outputs/project_03/graph.kuzu",
|
|
91
|
+
"project03:web": "tsx src/cli.ts web --db ./outputs/project_03/graph.kuzu",
|
|
92
|
+
"project04": "npm run project04:rebuild && npm run project04:dead-exports",
|
|
93
|
+
"project04:tour": "bash scripts/project_04_tour.sh",
|
|
94
|
+
"project04:rebuild": "npm run project04:clean && npm run project04:extract && npm run project04:load",
|
|
95
|
+
"project04:clean": "rm -rf ./outputs/project_04",
|
|
96
|
+
"project04:extract": "tsx src/cli.ts extract sample_projects/project_04 --semantic --out ./outputs/project_04/graph",
|
|
97
|
+
"project04:load": "tsx src/cli.ts load ./outputs/project_04/graph --db ./outputs/project_04/graph.kuzu",
|
|
98
|
+
"project04:enrich": "bash scripts/profile_and_enrich.sh project_04",
|
|
99
|
+
"project04:workload": "tsx scripts/benchmarks/project_04_workload.ts",
|
|
100
|
+
"project04:verify": "tsx src/cli.ts verify --cwd sample_projects/project_04",
|
|
101
|
+
"project04:dead-exports": "tsx src/cli.ts dead-exports --db ./outputs/project_04/graph.kuzu",
|
|
102
|
+
"project04:hotspots": "tsx src/cli.ts hotspots --db ./outputs/project_04/graph.kuzu",
|
|
103
|
+
"project04:cost": "tsx src/cli.ts cost --db ./outputs/project_04/graph.kuzu",
|
|
104
|
+
"project04:find": "tsx src/cli.ts find --db ./outputs/project_04/graph.kuzu",
|
|
105
|
+
"project04:who-calls": "tsx src/cli.ts who-calls --db ./outputs/project_04/graph.kuzu",
|
|
106
|
+
"project04:calls": "tsx src/cli.ts calls --db ./outputs/project_04/graph.kuzu",
|
|
107
|
+
"project04:references": "tsx src/cli.ts references --db ./outputs/project_04/graph.kuzu",
|
|
108
|
+
"project04:neighbors": "tsx src/cli.ts neighbors --db ./outputs/project_04/graph.kuzu",
|
|
109
|
+
"project04:blast-radius": "tsx src/cli.ts blast-radius --db ./outputs/project_04/graph.kuzu",
|
|
110
|
+
"project04:web": "tsx src/cli.ts web --db ./outputs/project_04/graph.kuzu"
|
|
27
111
|
},
|
|
28
112
|
"dependencies": {
|
|
29
113
|
"chalk": "^5.3.0",
|
|
30
114
|
"commander": "^12.1.0",
|
|
31
115
|
"kuzu": "^0.11.3",
|
|
32
|
-
"openai": "^6.42.0",
|
|
33
116
|
"ts-morph": "^23.0.0",
|
|
34
117
|
"zod": "^3.23.8"
|
|
35
118
|
},
|