project-librarian 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1856 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runCodeIndexMode = runCodeIndexMode;
37
+ exports.runCodeQueryMode = runCodeQueryMode;
38
+ exports.runCodeReportMode = runCodeReportMode;
39
+ exports.runCodeStatusMode = runCodeStatusMode;
40
+ exports.runCodeFilesMode = runCodeFilesMode;
41
+ exports.runCodeImpactMode = runCodeImpactMode;
42
+ exports.runCodeSearchSymbolMode = runCodeSearchSymbolMode;
43
+ exports.isCodeEvidenceMode = isCodeEvidenceMode;
44
+ exports.isCodeEvidenceModeFor = isCodeEvidenceModeFor;
45
+ const crypto = __importStar(require("node:crypto"));
46
+ const childProcess = __importStar(require("node:child_process"));
47
+ const fs = __importStar(require("node:fs"));
48
+ const path = __importStar(require("node:path"));
49
+ const ts = __importStar(require("typescript"));
50
+ const args_1 = require("./args");
51
+ const code_index_db_1 = require("./code-index-db");
52
+ const code_index_file_policy_1 = require("./code-index-file-policy");
53
+ const code_index_sql_1 = require("./code-index-sql");
54
+ const workspace_1 = require("./workspace");
55
+ const codeEvidenceDirectory = ".project-wiki";
56
+ const codeIndexSchemaVersion = "3";
57
+ const httpMethods = new Set(["all", "delete", "get", "patch", "post", "put"]);
58
+ const treeSitterGrammarPackages = {
59
+ "tree-sitter-c": "@sengac/tree-sitter-c",
60
+ "tree-sitter-cpp": "@sengac/tree-sitter-cpp",
61
+ "tree-sitter-csharp": "@sengac/tree-sitter-c-sharp",
62
+ "tree-sitter-go": "@sengac/tree-sitter-go",
63
+ "tree-sitter-java": "@sengac/tree-sitter-java",
64
+ "tree-sitter-javascript": "@sengac/tree-sitter-javascript",
65
+ "tree-sitter-kotlin": "@sengac/tree-sitter-kotlin",
66
+ "tree-sitter-php": "@sengac/tree-sitter-php",
67
+ "tree-sitter-python": "@sengac/tree-sitter-python",
68
+ "tree-sitter-rust": "@sengac/tree-sitter-rust",
69
+ "tree-sitter-swift": "@sengac/tree-sitter-swift",
70
+ };
71
+ const codeReportSectionAliases = {
72
+ config: "configs",
73
+ configs: "configs",
74
+ coverage: "coverage",
75
+ dependencies: "hotspots",
76
+ dependency: "hotspots",
77
+ dependency_hotspots: "hotspots",
78
+ edge: "edges",
79
+ edge_summary: "edges",
80
+ edges: "edges",
81
+ evidence: "coverage",
82
+ evidence_coverage: "coverage",
83
+ hotspot: "hotspots",
84
+ hotspots: "hotspots",
85
+ language: "languages",
86
+ language_profile_summary: "languages",
87
+ languages: "languages",
88
+ ownership: "ownership",
89
+ ownership_summary: "ownership",
90
+ parser: "parsers",
91
+ parser_backend_summary: "parsers",
92
+ parser_backends: "parsers",
93
+ parsers: "parsers",
94
+ route: "routes",
95
+ route_inventory: "routes",
96
+ routes: "routes",
97
+ workspace: "workspaces",
98
+ workspace_graph: "workspace-graph",
99
+ "workspace-graph": "workspace-graph",
100
+ workspacegraph: "workspace-graph",
101
+ monorepo: "workspace-graph",
102
+ monorepo_graph: "workspace-graph",
103
+ workspace_summary: "workspaces",
104
+ workspaces: "workspaces",
105
+ };
106
+ function fail(message) {
107
+ console.error(message);
108
+ process.exit(1);
109
+ }
110
+ function normalizeProjectRelative(input, label) {
111
+ const raw = input.trim() || ".";
112
+ const resolved = path.isAbsolute(raw) ? path.resolve(raw) : path.resolve(workspace_1.root, raw);
113
+ const rootResolved = path.resolve(workspace_1.root);
114
+ if (resolved !== rootResolved && !resolved.startsWith(`${rootResolved}${path.sep}`)) {
115
+ fail(`${label} must stay inside the project root: ${input}`);
116
+ }
117
+ return (0, workspace_1.normalizePath)(path.relative(rootResolved, resolved)) || ".";
118
+ }
119
+ function codeEvidenceDatabasePath() {
120
+ const raw = args_1.codeIndexOutput.trim() || `${codeEvidenceDirectory}/code-evidence.sqlite`;
121
+ const absolutePath = path.isAbsolute(raw) ? path.resolve(raw) : path.resolve(workspace_1.root, raw);
122
+ const evidenceRoot = path.resolve(workspace_1.root, codeEvidenceDirectory);
123
+ if (absolutePath === evidenceRoot || !absolutePath.startsWith(`${evidenceRoot}${path.sep}`)) {
124
+ fail(`--code-index-out must stay inside ${codeEvidenceDirectory}/`);
125
+ }
126
+ return {
127
+ absolutePath,
128
+ relativePath: (0, workspace_1.normalizePath)(path.relative(workspace_1.root, absolutePath)),
129
+ };
130
+ }
131
+ function selectedCodeParserMode() {
132
+ const requested = args_1.codeParser.trim().toLowerCase();
133
+ if (!requested || requested === "default")
134
+ return "default";
135
+ if (requested === "tree-sitter" || requested === "treesitter")
136
+ return "tree-sitter";
137
+ fail(`invalid --code-parser: ${args_1.codeParser}; expected one of: default, tree-sitter`);
138
+ }
139
+ function treeSitterProfile(relativePath) {
140
+ const extension = path.extname(relativePath).toLowerCase();
141
+ const language = (0, code_index_file_policy_1.fileLanguage)(relativePath);
142
+ if (language === "c")
143
+ return "tree-sitter-c";
144
+ if (language === "cpp")
145
+ return "tree-sitter-cpp";
146
+ if (language === "csharp")
147
+ return "tree-sitter-csharp";
148
+ if ([".js", ".jsx", ".cjs", ".mjs"].includes(extension))
149
+ return "tree-sitter-javascript";
150
+ if ([".ts", ".mts", ".cts"].includes(extension))
151
+ return "tree-sitter-typescript";
152
+ if (extension === ".tsx")
153
+ return "tree-sitter-tsx";
154
+ if (language === "java")
155
+ return "tree-sitter-java";
156
+ if (language === "kotlin")
157
+ return "tree-sitter-kotlin";
158
+ if (language === "php")
159
+ return "tree-sitter-php";
160
+ if (language === "python")
161
+ return "tree-sitter-python";
162
+ if (language === "go")
163
+ return "tree-sitter-go";
164
+ if (language === "rust")
165
+ return "tree-sitter-rust";
166
+ if (language === "swift")
167
+ return "tree-sitter-swift";
168
+ if (language === "config")
169
+ return "config";
170
+ return "inventory-only";
171
+ }
172
+ function extractionProfile(relativePath, parserMode) {
173
+ if (parserMode === "tree-sitter")
174
+ return treeSitterProfile(relativePath);
175
+ if ((0, code_index_file_policy_1.isJavaScriptLike)(relativePath))
176
+ return "typescript-ast";
177
+ if ((0, code_index_file_policy_1.fileLanguage)(relativePath) === "python")
178
+ return "python-light";
179
+ if ((0, code_index_file_policy_1.fileLanguage)(relativePath) === "go")
180
+ return "go-light";
181
+ if ((0, code_index_file_policy_1.fileLanguage)(relativePath) === "config")
182
+ return "config";
183
+ return "inventory-only";
184
+ }
185
+ function walkCodeFiles(relativePath, files = []) {
186
+ if ((0, code_index_file_policy_1.isIgnoredCodePath)(relativePath))
187
+ return files.sort();
188
+ const target = (0, workspace_1.abs)(relativePath);
189
+ if (!fs.existsSync(target))
190
+ return files;
191
+ const stat = fs.statSync(target);
192
+ if (stat.isFile()) {
193
+ if (stat.size <= code_index_file_policy_1.maxIndexedBytes && (0, code_index_file_policy_1.shouldIndexFile)(relativePath))
194
+ files.push(relativePath);
195
+ return files.sort();
196
+ }
197
+ for (const entry of fs.readdirSync(target, { withFileTypes: true })) {
198
+ const child = (0, workspace_1.normalizePath)(path.join(relativePath, entry.name));
199
+ if (entry.isDirectory()) {
200
+ if (!code_index_file_policy_1.ignoredDirectories.has(entry.name))
201
+ walkCodeFiles(child, files);
202
+ }
203
+ else if (entry.isFile() && (0, code_index_file_policy_1.shouldIndexFile)(child)) {
204
+ const childStat = fs.statSync((0, workspace_1.abs)(child));
205
+ if (childStat.size <= code_index_file_policy_1.maxIndexedBytes)
206
+ files.push(child);
207
+ }
208
+ }
209
+ return files.sort();
210
+ }
211
+ function gitTrackedAndUnignoredFiles(scopes) {
212
+ try {
213
+ const output = childProcess.execFileSync("git", ["ls-files", "--cached", "--others", "--exclude-standard", "-z", "--", ...scopes], {
214
+ cwd: workspace_1.root,
215
+ encoding: "buffer",
216
+ stdio: ["ignore", "pipe", "ignore"],
217
+ });
218
+ return output.toString("utf8").split("\0").filter(Boolean).map((file) => normalizeProjectRelative(file, "git-indexed file"));
219
+ }
220
+ catch {
221
+ return null;
222
+ }
223
+ }
224
+ function discoverCodeFiles(scopes) {
225
+ const gitFiles = gitTrackedAndUnignoredFiles(scopes);
226
+ const candidates = gitFiles ?? scopes.flatMap((scope) => walkCodeFiles(scope));
227
+ return Array.from(new Set(candidates))
228
+ .filter((file) => !(0, code_index_file_policy_1.isIgnoredCodePath)(file))
229
+ .filter((file) => fs.existsSync((0, workspace_1.abs)(file)))
230
+ .filter((file) => fs.statSync((0, workspace_1.abs)(file)).isFile())
231
+ .filter((file) => (0, code_index_file_policy_1.shouldIndexFile)(file))
232
+ .filter((file) => fs.statSync((0, workspace_1.abs)(file)).size <= code_index_file_policy_1.maxIndexedBytes)
233
+ .sort();
234
+ }
235
+ function readCodeFile(relativePath, parserMode = "default") {
236
+ const text = fs.readFileSync((0, workspace_1.abs)(relativePath), "utf8");
237
+ return {
238
+ bytes: Buffer.byteLength(text),
239
+ hash: crypto.createHash("sha256").update(text).digest("hex"),
240
+ language: (0, code_index_file_policy_1.fileLanguage)(relativePath) || "config",
241
+ lines: text.length === 0 ? 0 : text.split(/\r?\n/).length,
242
+ path: relativePath,
243
+ profile: extractionProfile(relativePath, parserMode),
244
+ text,
245
+ };
246
+ }
247
+ function lineNumber(text, index) {
248
+ return text.slice(0, index).split(/\r?\n/).length;
249
+ }
250
+ function scriptKindForPath(relativePath) {
251
+ const extension = path.extname(relativePath).toLowerCase();
252
+ if (extension === ".tsx")
253
+ return ts.ScriptKind.TSX;
254
+ if (extension === ".jsx")
255
+ return ts.ScriptKind.JSX;
256
+ if ([".ts", ".mts", ".cts"].includes(extension))
257
+ return ts.ScriptKind.TS;
258
+ return ts.ScriptKind.JS;
259
+ }
260
+ function setupDatabase(database) {
261
+ database.exec(`
262
+ PRAGMA journal_mode = WAL;
263
+ CREATE TABLE meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);
264
+ CREATE TABLE files (
265
+ path TEXT PRIMARY KEY,
266
+ language TEXT NOT NULL,
267
+ profile TEXT NOT NULL,
268
+ kind TEXT NOT NULL,
269
+ bytes INTEGER NOT NULL,
270
+ lines INTEGER NOT NULL,
271
+ hash TEXT NOT NULL
272
+ );
273
+ CREATE TABLE symbols (
274
+ id INTEGER PRIMARY KEY,
275
+ name TEXT NOT NULL,
276
+ kind TEXT NOT NULL,
277
+ file_path TEXT NOT NULL,
278
+ line INTEGER NOT NULL,
279
+ signature TEXT NOT NULL
280
+ );
281
+ CREATE TABLE imports (
282
+ id INTEGER PRIMARY KEY,
283
+ from_file TEXT NOT NULL,
284
+ to_ref TEXT NOT NULL,
285
+ imported TEXT NOT NULL,
286
+ line INTEGER NOT NULL,
287
+ raw TEXT NOT NULL
288
+ );
289
+ CREATE TABLE routes (
290
+ id INTEGER PRIMARY KEY,
291
+ method TEXT NOT NULL,
292
+ route TEXT NOT NULL,
293
+ file_path TEXT NOT NULL,
294
+ line INTEGER NOT NULL,
295
+ handler TEXT NOT NULL
296
+ );
297
+ CREATE TABLE configs (
298
+ id INTEGER PRIMARY KEY,
299
+ key TEXT NOT NULL,
300
+ value TEXT NOT NULL,
301
+ file_path TEXT NOT NULL,
302
+ line INTEGER NOT NULL
303
+ );
304
+ CREATE TABLE edges (
305
+ id INTEGER PRIMARY KEY,
306
+ kind TEXT NOT NULL,
307
+ source_kind TEXT NOT NULL,
308
+ source TEXT NOT NULL,
309
+ target_kind TEXT NOT NULL,
310
+ target TEXT NOT NULL,
311
+ file_path TEXT NOT NULL,
312
+ line INTEGER NOT NULL,
313
+ evidence TEXT NOT NULL
314
+ );
315
+ CREATE VIRTUAL TABLE files_fts USING fts5(path, language, profile, content);
316
+ CREATE VIRTUAL TABLE symbols_fts USING fts5(name, kind, file_path, signature);
317
+ CREATE INDEX idx_symbols_file ON symbols(file_path);
318
+ CREATE INDEX idx_symbols_name ON symbols(name);
319
+ CREATE INDEX idx_imports_from ON imports(from_file);
320
+ CREATE INDEX idx_routes_path ON routes(route);
321
+ CREATE INDEX idx_configs_file ON configs(file_path);
322
+ CREATE INDEX idx_edges_source ON edges(source_kind, source);
323
+ CREATE INDEX idx_edges_target ON edges(target_kind, target);
324
+ CREATE INDEX idx_edges_kind ON edges(kind);
325
+ `);
326
+ }
327
+ function createIndexStatements(database) {
328
+ return {
329
+ deleteConfig: database.prepare("DELETE FROM configs WHERE file_path = ?"),
330
+ deleteEdge: database.prepare("DELETE FROM edges WHERE file_path = ?"),
331
+ deleteFile: database.prepare("DELETE FROM files WHERE path = ?"),
332
+ deleteFileFts: database.prepare("DELETE FROM files_fts WHERE path = ?"),
333
+ deleteImport: database.prepare("DELETE FROM imports WHERE from_file = ?"),
334
+ deleteRoute: database.prepare("DELETE FROM routes WHERE file_path = ?"),
335
+ deleteSymbol: database.prepare("DELETE FROM symbols WHERE file_path = ?"),
336
+ deleteSymbolFts: database.prepare("DELETE FROM symbols_fts WHERE file_path = ?"),
337
+ insertConfig: database.prepare("INSERT INTO configs (key, value, file_path, line) VALUES (?, ?, ?, ?)"),
338
+ insertEdge: database.prepare("INSERT INTO edges (kind, source_kind, source, target_kind, target, file_path, line, evidence) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"),
339
+ insertFile: database.prepare("INSERT INTO files (path, language, profile, kind, bytes, lines, hash) VALUES (?, ?, ?, ?, ?, ?, ?)"),
340
+ insertFileFts: database.prepare("INSERT INTO files_fts (path, language, profile, content) VALUES (?, ?, ?, ?)"),
341
+ insertImport: database.prepare("INSERT INTO imports (from_file, to_ref, imported, line, raw) VALUES (?, ?, ?, ?, ?)"),
342
+ insertMeta: database.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)"),
343
+ insertRoute: database.prepare("INSERT INTO routes (method, route, file_path, line, handler) VALUES (?, ?, ?, ?, ?)"),
344
+ insertSymbol: database.prepare("INSERT INTO symbols (name, kind, file_path, line, signature) VALUES (?, ?, ?, ?, ?)"),
345
+ insertSymbolFts: database.prepare("INSERT INTO symbols_fts (name, kind, file_path, signature) VALUES (?, ?, ?, ?)"),
346
+ };
347
+ }
348
+ function removeIndexedFile(filePath, statements) {
349
+ statements.deleteConfig.run(filePath);
350
+ statements.deleteEdge.run(filePath);
351
+ statements.deleteImport.run(filePath);
352
+ statements.deleteRoute.run(filePath);
353
+ statements.deleteSymbol.run(filePath);
354
+ statements.deleteSymbolFts.run(filePath);
355
+ statements.deleteFileFts.run(filePath);
356
+ statements.deleteFile.run(filePath);
357
+ }
358
+ const treeSitterParsers = new Map();
359
+ function requireTreeSitterPackage(packageName) {
360
+ try {
361
+ return require(packageName);
362
+ }
363
+ catch (error) {
364
+ const message = error instanceof Error ? error.message : String(error);
365
+ fail(`--code-parser tree-sitter requires optional package ${packageName}; install project optional dependencies with npm install. Error: ${message}`);
366
+ }
367
+ }
368
+ function treeSitterGrammarForProfile(profile) {
369
+ if (profile === "tree-sitter-typescript" || profile === "tree-sitter-tsx") {
370
+ const grammars = requireTreeSitterPackage("@sengac/tree-sitter-typescript");
371
+ const grammar = profile === "tree-sitter-tsx" ? grammars.tsx : grammars.typescript;
372
+ if (!grammar)
373
+ fail(`tree-sitter-typescript did not expose the expected ${profile === "tree-sitter-tsx" ? "tsx" : "typescript"} grammar`);
374
+ return grammar;
375
+ }
376
+ const packageName = treeSitterGrammarPackages[profile];
377
+ if (packageName) {
378
+ const grammarModule = requireTreeSitterPackage(packageName);
379
+ const grammar = profile === "tree-sitter-php"
380
+ ? grammarModule.php ?? grammarModule.php_only
381
+ : grammarModule;
382
+ if (!grammar)
383
+ fail(`${packageName} did not expose a Tree-sitter grammar for ${profile}`);
384
+ return grammar;
385
+ }
386
+ fail(`missing Tree-sitter grammar for profile: ${profile}`);
387
+ }
388
+ function treeSitterParserForProfile(profile) {
389
+ const cached = treeSitterParsers.get(profile);
390
+ if (cached)
391
+ return cached;
392
+ const Parser = requireTreeSitterPackage("@sengac/tree-sitter");
393
+ const parser = new Parser();
394
+ parser.setLanguage(treeSitterGrammarForProfile(profile));
395
+ treeSitterParsers.set(profile, parser);
396
+ return parser;
397
+ }
398
+ function treeSitterLine(node) {
399
+ return node.startPosition.row + 1;
400
+ }
401
+ function treeSitterFieldText(node, fieldName) {
402
+ return node.childForFieldName(fieldName)?.text ?? "";
403
+ }
404
+ function treeSitterSignature(node) {
405
+ return oneLine(node.text);
406
+ }
407
+ function unquoteLiteral(text) {
408
+ const trimmed = text.trim();
409
+ if (trimmed.length >= 2) {
410
+ const first = trimmed[0];
411
+ const last = trimmed[trimmed.length - 1];
412
+ if ((first === "\"" && last === "\"") || (first === "'" && last === "'") || (first === "`" && last === "`"))
413
+ return trimmed.slice(1, -1);
414
+ }
415
+ return trimmed;
416
+ }
417
+ function forEachNamedTreeSitterNode(node, visit) {
418
+ visit(node);
419
+ for (let index = 0; index < node.namedChildCount; index += 1) {
420
+ const child = node.namedChild(index);
421
+ if (child)
422
+ forEachNamedTreeSitterNode(child, visit);
423
+ }
424
+ }
425
+ function firstNamedChildOfType(node, type) {
426
+ for (let index = 0; index < node.namedChildCount; index += 1) {
427
+ const child = node.namedChild(index);
428
+ if (child?.type === type)
429
+ return child;
430
+ }
431
+ return null;
432
+ }
433
+ function treeSitterModuleSpecifier(node) {
434
+ const source = treeSitterFieldText(node, "source");
435
+ if (source)
436
+ return unquoteLiteral(source);
437
+ const raw = node.text;
438
+ return raw.match(/\bfrom\s*["'`]([^"'`]+)["'`]/)?.[1]
439
+ ?? raw.match(/^\s*import\s*["'`]([^"'`]+)["'`]/)?.[1]
440
+ ?? raw.match(/\brequire\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/)?.[1]
441
+ ?? "";
442
+ }
443
+ function indexTreeSitterJavaScriptLike(file, statements) {
444
+ const tree = treeSitterParserForProfile(file.profile).parse(file.text);
445
+ function visit(node, context) {
446
+ let nextContext = context;
447
+ if (node.type === "function_declaration") {
448
+ const name = treeSitterFieldText(node, "name");
449
+ insertSymbol(statements, name, "function", file, treeSitterLine(node), treeSitterSignature(node));
450
+ if (name)
451
+ nextContext = name;
452
+ }
453
+ else if (node.type === "class_declaration") {
454
+ const name = treeSitterFieldText(node, "name");
455
+ insertSymbol(statements, name, "class", file, treeSitterLine(node), treeSitterSignature(node));
456
+ if (name)
457
+ nextContext = name;
458
+ }
459
+ else if (node.type === "method_definition" || node.type === "method_signature") {
460
+ const name = treeSitterFieldText(node, "name");
461
+ insertSymbol(statements, name, "method", file, treeSitterLine(node), treeSitterSignature(node));
462
+ if (name)
463
+ nextContext = name;
464
+ }
465
+ else if (node.type === "interface_declaration") {
466
+ insertSymbol(statements, treeSitterFieldText(node, "name"), "interface", file, treeSitterLine(node), treeSitterSignature(node));
467
+ }
468
+ else if (node.type === "type_alias_declaration") {
469
+ insertSymbol(statements, treeSitterFieldText(node, "name"), "type", file, treeSitterLine(node), treeSitterSignature(node));
470
+ }
471
+ else if (node.type === "enum_declaration") {
472
+ insertSymbol(statements, treeSitterFieldText(node, "name"), "enum", file, treeSitterLine(node), treeSitterSignature(node));
473
+ }
474
+ else if (node.type === "variable_declarator") {
475
+ const name = treeSitterFieldText(node, "name");
476
+ const valueType = node.childForFieldName("value")?.type ?? "";
477
+ const symbolKind = ["arrow_function", "function", "function_expression"].includes(valueType) ? "function" : "variable";
478
+ insertSymbol(statements, name, symbolKind, file, treeSitterLine(node), treeSitterSignature(node));
479
+ if (symbolKind === "function" && name)
480
+ nextContext = name;
481
+ }
482
+ else if (node.type === "import_statement" || node.type === "export_statement") {
483
+ const toRef = treeSitterModuleSpecifier(node);
484
+ if (toRef) {
485
+ const imported = node.text.match(/^\s*import\s+(.+?)\s+from\s*["'`]/)?.[1] ?? node.text.match(/^\s*export\s+(.+?)\s+from\s*["'`]/)?.[1] ?? "";
486
+ statements.insertImport.run(file.path, toRef, oneLine(imported), treeSitterLine(node), treeSitterSignature(node));
487
+ insertEdge(statements, node.type === "export_statement" ? "export" : "import", "file", file.path, "module", toRef, file, treeSitterLine(node), treeSitterSignature(node));
488
+ }
489
+ }
490
+ else if (node.type === "call_expression") {
491
+ const raw = node.text;
492
+ const routeMatch = raw.match(/^(?:app|router|server)\.(get|post|put|patch|delete|all)\s*\(\s*["'`]([^"'`]+)["'`]\s*,\s*([^,)]+)/);
493
+ if (routeMatch) {
494
+ const method = (routeMatch[1] ?? "").toUpperCase();
495
+ const route = routeMatch[2] ?? "";
496
+ const handler = oneLine(routeMatch[3] ?? "");
497
+ statements.insertRoute.run(method, route, file.path, treeSitterLine(node), handler);
498
+ insertEdge(statements, "route_to_handler", "route", `${method} ${route}`, "symbol", handler, file, treeSitterLine(node), treeSitterSignature(node));
499
+ }
500
+ const requireRef = treeSitterModuleSpecifier(node);
501
+ if (requireRef) {
502
+ statements.insertImport.run(file.path, requireRef, "", treeSitterLine(node), treeSitterSignature(node));
503
+ insertEdge(statements, "import", "file", file.path, "module", requireRef, file, treeSitterLine(node), treeSitterSignature(node));
504
+ }
505
+ else {
506
+ const target = treeSitterFieldText(node, "function");
507
+ insertEdge(statements, "call", context ? "symbol" : "file", context || file.path, "symbol", target, file, treeSitterLine(node), treeSitterSignature(node));
508
+ }
509
+ }
510
+ for (let index = 0; index < node.namedChildCount; index += 1) {
511
+ const child = node.namedChild(index);
512
+ if (child)
513
+ visit(child, nextContext);
514
+ }
515
+ }
516
+ visit(tree.rootNode, "");
517
+ }
518
+ function indexTreeSitterPython(file, statements) {
519
+ const tree = treeSitterParserForProfile(file.profile).parse(file.text);
520
+ forEachNamedTreeSitterNode(tree.rootNode, (node) => {
521
+ if (node.type === "function_definition") {
522
+ const name = treeSitterFieldText(node, "name");
523
+ insertSymbol(statements, name, "function", file, treeSitterLine(node), treeSitterSignature(node));
524
+ }
525
+ else if (node.type === "class_definition") {
526
+ const name = treeSitterFieldText(node, "name");
527
+ insertSymbol(statements, name, "class", file, treeSitterLine(node), treeSitterSignature(node));
528
+ }
529
+ else if (node.type === "import_statement" || node.type === "import_from_statement") {
530
+ const raw = node.text.trim();
531
+ const fromMatch = raw.match(/^from\s+([A-Za-z0-9_.$]+)\s+import\s+(.+)$/);
532
+ const importMatch = raw.match(/^import\s+(.+)$/);
533
+ const toRef = fromMatch?.[1] ?? importMatch?.[1] ?? "";
534
+ const imported = fromMatch?.[2] ?? "";
535
+ if (toRef) {
536
+ statements.insertImport.run(file.path, toRef, imported.trim(), treeSitterLine(node), raw);
537
+ insertEdge(statements, "import", "file", file.path, "module", toRef, file, treeSitterLine(node), raw);
538
+ }
539
+ }
540
+ });
541
+ }
542
+ function indexTreeSitterGo(file, statements) {
543
+ const tree = treeSitterParserForProfile(file.profile).parse(file.text);
544
+ forEachNamedTreeSitterNode(tree.rootNode, (node) => {
545
+ if (node.type === "function_declaration") {
546
+ const name = treeSitterFieldText(node, "name");
547
+ insertSymbol(statements, name, "function", file, treeSitterLine(node), treeSitterSignature(node));
548
+ }
549
+ else if (node.type === "method_declaration") {
550
+ const name = treeSitterFieldText(node, "name");
551
+ insertSymbol(statements, name, "method", file, treeSitterLine(node), treeSitterSignature(node));
552
+ }
553
+ else if (node.type === "type_declaration") {
554
+ const spec = firstNamedChildOfType(node, "type_spec");
555
+ const name = spec ? treeSitterFieldText(spec, "name") : "";
556
+ insertSymbol(statements, name, "type", file, treeSitterLine(node), treeSitterSignature(node));
557
+ }
558
+ else if (node.type === "const_declaration" || node.type === "var_declaration") {
559
+ const spec = firstNamedChildOfType(node, node.type === "const_declaration" ? "const_spec" : "var_spec");
560
+ const name = spec ? treeSitterFieldText(spec, "name") : "";
561
+ insertSymbol(statements, name, node.type === "const_declaration" ? "constant" : "variable", file, treeSitterLine(node), treeSitterSignature(node));
562
+ }
563
+ else if (node.type === "import_spec") {
564
+ const toRef = unquoteLiteral(treeSitterFieldText(node, "path") || (node.text.match(/"([^"]+)"/)?.[1] ?? ""));
565
+ const imported = treeSitterFieldText(node, "name");
566
+ insertGoImport(file, statements, toRef, imported, treeSitterLine(node), treeSitterSignature(node));
567
+ }
568
+ });
569
+ }
570
+ function treeSitterGenericLanguage(file) {
571
+ const normalized = file.profile.replace(/^tree-sitter-/, "");
572
+ if (["c", "cpp", "csharp", "java", "kotlin", "php", "rust", "swift"].includes(normalized))
573
+ return normalized;
574
+ fail(`unsupported generic Tree-sitter profile: ${file.profile}`);
575
+ }
576
+ function symbolNameFromPatterns(text, patterns) {
577
+ for (const pattern of patterns) {
578
+ const match = text.match(pattern);
579
+ if (match?.[1])
580
+ return match[1];
581
+ }
582
+ return "";
583
+ }
584
+ function treeSitterGenericSymbol(node, language) {
585
+ const raw = node.text;
586
+ const fieldName = treeSitterFieldText(node, "name");
587
+ const patterns = {
588
+ c: [
589
+ [["function_definition"], "function", [/\b([A-Za-z_]\w*)\s*\([^;{}]*\)\s*\{/]],
590
+ [["struct_specifier"], "struct", [/\bstruct\s+([A-Za-z_]\w*)/]],
591
+ [["enum_specifier"], "enum", [/\benum\s+([A-Za-z_]\w*)/]],
592
+ ],
593
+ cpp: [
594
+ [["function_definition"], "function", [/\b([A-Za-z_]\w*)\s*\([^;{}]*\)\s*(?:const\s*)?\{/]],
595
+ [["class_specifier"], "class", [/\bclass\s+([A-Za-z_]\w*)/, /\bstruct\s+([A-Za-z_]\w*)/]],
596
+ [["namespace_definition"], "namespace", [/\bnamespace\s+([A-Za-z_]\w*)/]],
597
+ [["enum_specifier"], "enum", [/\benum(?:\s+class)?\s+([A-Za-z_]\w*)/]],
598
+ ],
599
+ csharp: [
600
+ [["method_declaration", "constructor_declaration"], "method", [/\b([A-Za-z_]\w*)\s*\(/]],
601
+ [["class_declaration"], "class", [/\bclass\s+([A-Za-z_]\w*)/]],
602
+ [["interface_declaration"], "interface", [/\binterface\s+([A-Za-z_]\w*)/]],
603
+ [["struct_declaration"], "struct", [/\bstruct\s+([A-Za-z_]\w*)/]],
604
+ [["enum_declaration"], "enum", [/\benum\s+([A-Za-z_]\w*)/]],
605
+ ],
606
+ java: [
607
+ [["method_declaration", "constructor_declaration"], "method", [/\b([A-Za-z_]\w*)\s*\(/]],
608
+ [["class_declaration"], "class", [/\bclass\s+([A-Za-z_]\w*)/]],
609
+ [["interface_declaration"], "interface", [/\binterface\s+([A-Za-z_]\w*)/]],
610
+ [["enum_declaration"], "enum", [/\benum\s+([A-Za-z_]\w*)/]],
611
+ ],
612
+ kotlin: [
613
+ [["function_declaration"], "function", [/\bfun\s+([A-Za-z_]\w*)/]],
614
+ [["class_declaration"], "class", [/\bclass\s+([A-Za-z_]\w*)/, /\binterface\s+([A-Za-z_]\w*)/]],
615
+ [["object_declaration"], "object", [/\bobject\s+([A-Za-z_]\w*)/]],
616
+ ],
617
+ php: [
618
+ [["function_definition"], "function", [/\bfunction\s+([A-Za-z_]\w*)/]],
619
+ [["method_declaration"], "method", [/\bfunction\s+([A-Za-z_]\w*)/]],
620
+ [["class_declaration"], "class", [/\bclass\s+([A-Za-z_]\w*)/]],
621
+ [["interface_declaration"], "interface", [/\binterface\s+([A-Za-z_]\w*)/]],
622
+ [["trait_declaration"], "trait", [/\btrait\s+([A-Za-z_]\w*)/]],
623
+ ],
624
+ rust: [
625
+ [["function_item"], "function", [/\bfn\s+([A-Za-z_]\w*)/]],
626
+ [["struct_item"], "struct", [/\bstruct\s+([A-Za-z_]\w*)/]],
627
+ [["enum_item"], "enum", [/\benum\s+([A-Za-z_]\w*)/]],
628
+ [["trait_item"], "trait", [/\btrait\s+([A-Za-z_]\w*)/]],
629
+ [["impl_item"], "impl", [/\bimpl(?:\s*<[^>]+>)?\s+([A-Za-z_]\w*)/]],
630
+ ],
631
+ swift: [
632
+ [["function_declaration"], "function", [/\bfunc\s+([A-Za-z_]\w*)/]],
633
+ [["class_declaration"], "class", [/\bclass\s+([A-Za-z_]\w*)/]],
634
+ [["struct_declaration"], "struct", [/\bstruct\s+([A-Za-z_]\w*)/]],
635
+ [["protocol_declaration"], "protocol", [/\bprotocol\s+([A-Za-z_]\w*)/]],
636
+ [["enum_declaration"], "enum", [/\benum\s+([A-Za-z_]\w*)/]],
637
+ ],
638
+ };
639
+ for (const [types, kind, regexes] of patterns[language] ?? []) {
640
+ if (!types.includes(node.type))
641
+ continue;
642
+ const name = fieldName || symbolNameFromPatterns(raw, regexes);
643
+ return name ? { kind, name } : null;
644
+ }
645
+ return null;
646
+ }
647
+ function treeSitterGenericImport(node, language) {
648
+ const raw = node.text.trim();
649
+ const importTypes = {
650
+ c: ["preproc_include"],
651
+ cpp: ["preproc_include", "using_declaration", "namespace_alias_definition"],
652
+ csharp: ["using_directive"],
653
+ java: ["import_declaration"],
654
+ kotlin: ["import_header"],
655
+ php: ["namespace_use_declaration"],
656
+ rust: ["use_declaration"],
657
+ swift: ["import_declaration"],
658
+ };
659
+ if (!(importTypes[language] ?? []).includes(node.type))
660
+ return null;
661
+ const toRef = raw.match(/#include\s*[<"]([^>"]+)[>"]/)?.[1]
662
+ ?? raw.match(/\bimport\s+([A-Za-z0-9_.*.$\\/-]+)/)?.[1]
663
+ ?? raw.match(/\busing\s+([A-Za-z0-9_.*.$\\/-]+)/)?.[1]
664
+ ?? raw.match(/\buse\s+([A-Za-z0-9_:{}*,\s]+);?/)?.[1]?.replace(/\s+/g, " ").trim()
665
+ ?? "";
666
+ return toRef ? { imported: "", kind: language === "rust" ? "use" : "import", toRef } : null;
667
+ }
668
+ function indexTreeSitterGeneric(file, statements) {
669
+ const language = treeSitterGenericLanguage(file);
670
+ const tree = treeSitterParserForProfile(file.profile).parse(file.text);
671
+ forEachNamedTreeSitterNode(tree.rootNode, (node) => {
672
+ const symbol = treeSitterGenericSymbol(node, language);
673
+ if (symbol)
674
+ insertSymbol(statements, symbol.name, symbol.kind, file, treeSitterLine(node), treeSitterSignature(node));
675
+ const imported = treeSitterGenericImport(node, language);
676
+ if (imported) {
677
+ statements.insertImport.run(file.path, imported.toRef, imported.imported, treeSitterLine(node), treeSitterSignature(node));
678
+ insertEdge(statements, imported.kind, "file", file.path, "module", imported.toRef, file, treeSitterLine(node), treeSitterSignature(node));
679
+ }
680
+ });
681
+ }
682
+ const extractionBackends = [
683
+ {
684
+ id: "typescript-compiler",
685
+ index: indexJavaScriptLike,
686
+ label: "TypeScript compiler API",
687
+ profile: "typescript-ast",
688
+ strength: "structural",
689
+ },
690
+ {
691
+ id: "regex-light",
692
+ index: indexPythonLight,
693
+ label: "Python lightweight regex",
694
+ profile: "python-light",
695
+ strength: "light",
696
+ },
697
+ {
698
+ id: "regex-light",
699
+ index: indexGoLight,
700
+ label: "Go lightweight regex",
701
+ profile: "go-light",
702
+ strength: "light",
703
+ },
704
+ {
705
+ id: "tree-sitter-javascript",
706
+ index: indexTreeSitterJavaScriptLike,
707
+ label: "Tree-sitter JavaScript grammar",
708
+ profile: "tree-sitter-javascript",
709
+ strength: "structural",
710
+ },
711
+ {
712
+ id: "tree-sitter-typescript",
713
+ index: indexTreeSitterJavaScriptLike,
714
+ label: "Tree-sitter TypeScript grammar",
715
+ profile: "tree-sitter-typescript",
716
+ strength: "structural",
717
+ },
718
+ {
719
+ id: "tree-sitter-typescript",
720
+ index: indexTreeSitterJavaScriptLike,
721
+ label: "Tree-sitter TSX grammar",
722
+ profile: "tree-sitter-tsx",
723
+ strength: "structural",
724
+ },
725
+ {
726
+ id: "tree-sitter-python",
727
+ index: indexTreeSitterPython,
728
+ label: "Tree-sitter Python grammar",
729
+ profile: "tree-sitter-python",
730
+ strength: "structural",
731
+ },
732
+ {
733
+ id: "tree-sitter-go",
734
+ index: indexTreeSitterGo,
735
+ label: "Tree-sitter Go grammar",
736
+ profile: "tree-sitter-go",
737
+ strength: "structural",
738
+ },
739
+ {
740
+ id: "tree-sitter-c",
741
+ index: indexTreeSitterGeneric,
742
+ label: "Tree-sitter C grammar",
743
+ profile: "tree-sitter-c",
744
+ strength: "structural",
745
+ },
746
+ {
747
+ id: "tree-sitter-cpp",
748
+ index: indexTreeSitterGeneric,
749
+ label: "Tree-sitter C++ grammar",
750
+ profile: "tree-sitter-cpp",
751
+ strength: "structural",
752
+ },
753
+ {
754
+ id: "tree-sitter-csharp",
755
+ index: indexTreeSitterGeneric,
756
+ label: "Tree-sitter C# grammar",
757
+ profile: "tree-sitter-csharp",
758
+ strength: "structural",
759
+ },
760
+ {
761
+ id: "tree-sitter-java",
762
+ index: indexTreeSitterGeneric,
763
+ label: "Tree-sitter Java grammar",
764
+ profile: "tree-sitter-java",
765
+ strength: "structural",
766
+ },
767
+ {
768
+ id: "tree-sitter-kotlin",
769
+ index: indexTreeSitterGeneric,
770
+ label: "Tree-sitter Kotlin grammar",
771
+ profile: "tree-sitter-kotlin",
772
+ strength: "structural",
773
+ },
774
+ {
775
+ id: "tree-sitter-php",
776
+ index: indexTreeSitterGeneric,
777
+ label: "Tree-sitter PHP grammar",
778
+ profile: "tree-sitter-php",
779
+ strength: "structural",
780
+ },
781
+ {
782
+ id: "tree-sitter-rust",
783
+ index: indexTreeSitterGeneric,
784
+ label: "Tree-sitter Rust grammar",
785
+ profile: "tree-sitter-rust",
786
+ strength: "structural",
787
+ },
788
+ {
789
+ id: "tree-sitter-swift",
790
+ index: indexTreeSitterGeneric,
791
+ label: "Tree-sitter Swift grammar",
792
+ profile: "tree-sitter-swift",
793
+ strength: "structural",
794
+ },
795
+ {
796
+ id: "config-key-value",
797
+ index: (file, statements) => indexConfigs(file, statements.insertConfig),
798
+ label: "Configuration key/value extractor",
799
+ profile: "config",
800
+ strength: "config",
801
+ },
802
+ {
803
+ id: "inventory-only",
804
+ index: () => undefined,
805
+ label: "Inventory-only file listing",
806
+ profile: "inventory-only",
807
+ strength: "inventory",
808
+ },
809
+ ];
810
+ const extractionBackendsByProfile = new Map(extractionBackends.map((backend) => [backend.profile, backend]));
811
+ function extractionBackendForProfile(profile) {
812
+ const backend = extractionBackendsByProfile.get(profile);
813
+ if (!backend)
814
+ fail(`missing extraction backend for profile: ${profile}`);
815
+ return backend;
816
+ }
817
+ function indexCodeFile(file, statements) {
818
+ statements.insertFile.run(file.path, file.language, file.profile, file.language === "config" ? "config" : "source", file.bytes, file.lines, file.hash);
819
+ statements.insertFileFts.run(file.path, file.language, file.profile, file.text);
820
+ extractionBackendForProfile(file.profile).index(file, statements);
821
+ }
822
+ function writeIndexMetadata(scopes, parserMode, statements) {
823
+ statements.insertMeta.run("schema_version", codeIndexSchemaVersion);
824
+ statements.insertMeta.run("updated_at", new Date().toISOString());
825
+ statements.insertMeta.run("root", workspace_1.root);
826
+ statements.insertMeta.run("scopes", scopes.join(", "));
827
+ statements.insertMeta.run("scopes_json", JSON.stringify(scopes));
828
+ statements.insertMeta.run("parser_mode", parserMode);
829
+ statements.insertMeta.run("terminology", "code evidence index");
830
+ }
831
+ function oneLine(text) {
832
+ return text.replace(/\s+/g, " ").trim().slice(0, 240);
833
+ }
834
+ function printRows(rows) {
835
+ console.log(JSON.stringify(rows, null, 2));
836
+ }
837
+ function printJson(value) {
838
+ console.log(JSON.stringify(value, null, 2));
839
+ }
840
+ function tsLine(sourceFile, node) {
841
+ return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
842
+ }
843
+ function nodeName(node, sourceFile) {
844
+ if (ts.isIdentifier(node))
845
+ return node.text;
846
+ if (ts.isStringLiteral(node) || ts.isNumericLiteral(node))
847
+ return node.text;
848
+ if (ts.isPrivateIdentifier(node))
849
+ return node.text;
850
+ return oneLine(node.getText(sourceFile));
851
+ }
852
+ function propertyNameText(name, sourceFile) {
853
+ if (!name)
854
+ return "";
855
+ return nodeName(name, sourceFile);
856
+ }
857
+ function callTarget(expression, sourceFile) {
858
+ if (ts.isIdentifier(expression))
859
+ return expression.text;
860
+ if (ts.isPropertyAccessExpression(expression))
861
+ return oneLine(expression.getText(sourceFile));
862
+ if (ts.isElementAccessExpression(expression))
863
+ return oneLine(expression.getText(sourceFile));
864
+ return oneLine(expression.getText(sourceFile));
865
+ }
866
+ function insertSymbol(statements, name, kind, file, line, signature) {
867
+ if (!name)
868
+ return;
869
+ statements.insertSymbol.run(name, kind, file.path, line, signature);
870
+ statements.insertSymbolFts.run(name, kind, file.path, signature);
871
+ }
872
+ function insertEdge(statements, kind, sourceKind, source, targetKind, target, file, line, evidence) {
873
+ if (!target)
874
+ return;
875
+ statements.insertEdge.run(kind, sourceKind, source, targetKind, target, file.path, line, evidence);
876
+ }
877
+ function importBindingText(importClause, sourceFile) {
878
+ if (!importClause)
879
+ return "";
880
+ const names = [];
881
+ if (importClause.name)
882
+ names.push(importClause.name.text);
883
+ const namedBindings = importClause.namedBindings;
884
+ if (namedBindings && ts.isNamespaceImport(namedBindings))
885
+ names.push(`* as ${namedBindings.name.text}`);
886
+ if (namedBindings && ts.isNamedImports(namedBindings)) {
887
+ for (const element of namedBindings.elements)
888
+ names.push(element.name.text);
889
+ }
890
+ return names.join(", ") || oneLine(importClause.getText(sourceFile));
891
+ }
892
+ function stringArg(node) {
893
+ if (!node)
894
+ return "";
895
+ return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node) ? node.text : "";
896
+ }
897
+ function handlerArg(node, sourceFile) {
898
+ if (!node)
899
+ return "";
900
+ return callTarget(node, sourceFile);
901
+ }
902
+ function routeFromCall(node, sourceFile) {
903
+ if (!ts.isPropertyAccessExpression(node.expression))
904
+ return null;
905
+ const method = node.expression.name.text.toLowerCase();
906
+ if (!httpMethods.has(method))
907
+ return null;
908
+ const receiver = node.expression.expression;
909
+ if (!ts.isIdentifier(receiver) || !["app", "router", "server"].includes(receiver.text))
910
+ return null;
911
+ const route = stringArg(node.arguments[0]);
912
+ if (!route)
913
+ return null;
914
+ return {
915
+ handler: handlerArg(node.arguments[1], sourceFile),
916
+ method: method.toUpperCase(),
917
+ route,
918
+ };
919
+ }
920
+ function routeFromDecorator(node, sourceFile) {
921
+ const decorators = ts.canHaveDecorators(node) ? ts.getDecorators(node) ?? [] : [];
922
+ const routes = [];
923
+ for (const decorator of decorators) {
924
+ const expression = decorator.expression;
925
+ if (!ts.isCallExpression(expression))
926
+ continue;
927
+ const callee = expression.expression;
928
+ if (!ts.isIdentifier(callee))
929
+ continue;
930
+ const method = callee.text.toLowerCase();
931
+ if (!httpMethods.has(method))
932
+ continue;
933
+ routes.push({ method: method.toUpperCase(), route: stringArg(expression.arguments[0]) || "/" });
934
+ }
935
+ return routes;
936
+ }
937
+ function signatureFor(node, sourceFile) {
938
+ return oneLine(node.getText(sourceFile));
939
+ }
940
+ function indexJavaScriptLike(file, statements) {
941
+ const sourceFile = ts.createSourceFile(file.path, file.text, ts.ScriptTarget.Latest, true, scriptKindForPath(file.path));
942
+ function visit(node, context) {
943
+ let nextContext = context;
944
+ if (ts.isFunctionDeclaration(node)) {
945
+ const name = node.name?.text ?? "";
946
+ insertSymbol(statements, name, "function", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
947
+ if (name)
948
+ nextContext = name;
949
+ }
950
+ else if (ts.isClassDeclaration(node)) {
951
+ const name = node.name?.text ?? "";
952
+ insertSymbol(statements, name, "class", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
953
+ if (name)
954
+ nextContext = name;
955
+ }
956
+ else if (ts.isInterfaceDeclaration(node)) {
957
+ insertSymbol(statements, node.name.text, "interface", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
958
+ }
959
+ else if (ts.isTypeAliasDeclaration(node)) {
960
+ insertSymbol(statements, node.name.text, "type", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
961
+ }
962
+ else if (ts.isEnumDeclaration(node)) {
963
+ insertSymbol(statements, node.name.text, "enum", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
964
+ }
965
+ else if (ts.isMethodDeclaration(node)) {
966
+ const name = propertyNameText(node.name, sourceFile);
967
+ insertSymbol(statements, name, "method", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
968
+ for (const route of routeFromDecorator(node, sourceFile)) {
969
+ statements.insertRoute.run(route.method, route.route, file.path, tsLine(sourceFile, node), name);
970
+ insertEdge(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", name, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
971
+ }
972
+ if (name)
973
+ nextContext = name;
974
+ }
975
+ else if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
976
+ const symbolKind = node.initializer && (ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer)) ? "function" : "variable";
977
+ insertSymbol(statements, node.name.text, symbolKind, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
978
+ if (symbolKind === "function")
979
+ nextContext = node.name.text;
980
+ }
981
+ else if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
982
+ const imported = importBindingText(node.importClause, sourceFile);
983
+ statements.insertImport.run(file.path, node.moduleSpecifier.text, imported, tsLine(sourceFile, node), signatureFor(node, sourceFile));
984
+ insertEdge(statements, "import", "file", file.path, "module", node.moduleSpecifier.text, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
985
+ }
986
+ else if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
987
+ const exported = node.exportClause ? oneLine(node.exportClause.getText(sourceFile)) : "";
988
+ statements.insertImport.run(file.path, node.moduleSpecifier.text, exported, tsLine(sourceFile, node), signatureFor(node, sourceFile));
989
+ insertEdge(statements, "export", "file", file.path, "module", node.moduleSpecifier.text, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
990
+ }
991
+ else if (ts.isCallExpression(node)) {
992
+ const route = routeFromCall(node, sourceFile);
993
+ if (route) {
994
+ statements.insertRoute.run(route.method, route.route, file.path, tsLine(sourceFile, node), route.handler);
995
+ insertEdge(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", route.handler, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
996
+ }
997
+ if (ts.isIdentifier(node.expression) && node.expression.text === "require") {
998
+ const moduleName = stringArg(node.arguments[0]);
999
+ if (moduleName) {
1000
+ statements.insertImport.run(file.path, moduleName, "", tsLine(sourceFile, node), signatureFor(node, sourceFile));
1001
+ insertEdge(statements, "import", "file", file.path, "module", moduleName, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
1002
+ }
1003
+ }
1004
+ else {
1005
+ insertEdge(statements, "call", context ? "symbol" : "file", context || file.path, "symbol", callTarget(node.expression, sourceFile), file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
1006
+ }
1007
+ }
1008
+ ts.forEachChild(node, (child) => visit(child, nextContext));
1009
+ }
1010
+ visit(sourceFile, "");
1011
+ }
1012
+ function insertMatches(file, regex, insert) {
1013
+ for (const match of file.text.matchAll(regex)) {
1014
+ insert(match, lineNumber(file.text, match.index ?? 0));
1015
+ }
1016
+ }
1017
+ function indexPythonLight(file, statements) {
1018
+ const symbolPatterns = [
1019
+ [/^\s*def\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/gm, "function", (match) => `def ${match[1] ?? ""}(${match[2] ?? ""})`],
1020
+ [/^\s*class\s+([A-Za-z_]\w*)/gm, "class", (match) => `class ${match[1] ?? ""}`],
1021
+ ];
1022
+ for (const [regex, kind, signature] of symbolPatterns) {
1023
+ insertMatches(file, regex, (match, line) => insertSymbol(statements, match[1] ?? "", kind, file, line, signature(match)));
1024
+ }
1025
+ const importPatterns = [
1026
+ [/^\s*from\s+([A-Za-z0-9_.$]+)\s+import\s+(.+)$/gm, (match) => [match[1] ?? "", match[2] ?? ""]],
1027
+ [/^\s*import\s+([A-Za-z0-9_.$,\s]+)$/gm, (match) => [match[1] ?? "", ""]],
1028
+ ];
1029
+ for (const [regex, fields] of importPatterns) {
1030
+ insertMatches(file, regex, (match, line) => {
1031
+ const [toRef, imported] = fields(match);
1032
+ statements.insertImport.run(file.path, toRef, imported.trim(), line, match[0].trim());
1033
+ insertEdge(statements, "import", "file", file.path, "module", toRef, file, line, match[0].trim());
1034
+ });
1035
+ }
1036
+ }
1037
+ function insertGoImport(file, statements, toRef, imported, line, raw) {
1038
+ if (!toRef)
1039
+ return;
1040
+ statements.insertImport.run(file.path, toRef, imported, line, raw);
1041
+ insertEdge(statements, "import", "file", file.path, "module", toRef, file, line, raw);
1042
+ }
1043
+ function indexGoLight(file, statements) {
1044
+ const symbolPatterns = [
1045
+ [/^\s*func\s*\(\s*[^)]*\)\s*([A-Za-z_]\w*)\s*\(([^)]*)\)/gm, "method", (match) => match[1] ?? "", (match) => `func (...) ${match[1] ?? ""}(${match[2] ?? ""})`],
1046
+ [/^\s*func\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/gm, "function", (match) => match[1] ?? "", (match) => `func ${match[1] ?? ""}(${match[2] ?? ""})`],
1047
+ [/^\s*type\s+([A-Za-z_]\w*)\s+(struct|interface)?/gm, "type", (match) => match[1] ?? "", (match) => `type ${match[1] ?? ""} ${match[2] ?? ""}`.trim()],
1048
+ [/^\s*const\s+([A-Za-z_]\w*)\b/gm, "constant", (match) => match[1] ?? "", (match) => `const ${match[1] ?? ""}`],
1049
+ [/^\s*var\s+([A-Za-z_]\w*)\b/gm, "variable", (match) => match[1] ?? "", (match) => `var ${match[1] ?? ""}`],
1050
+ ];
1051
+ for (const [regex, kind, name, signature] of symbolPatterns) {
1052
+ insertMatches(file, regex, (match, line) => insertSymbol(statements, name(match), kind, file, line, signature(match)));
1053
+ }
1054
+ insertMatches(file, /^\s*import\s+(?:(?:([A-Za-z_]\w*|[_.])\s+)?\"([^\"]+)\"|`([^`]+)`)/gm, (match, line) => {
1055
+ const imported = match[1] ?? "";
1056
+ const toRef = match[2] ?? match[3] ?? "";
1057
+ insertGoImport(file, statements, toRef, imported, line, match[0].trim());
1058
+ });
1059
+ insertMatches(file, /^\s*import\s*\(([\s\S]*?)^\s*\)/gm, (blockMatch) => {
1060
+ const block = blockMatch[1] ?? "";
1061
+ const blockStart = blockMatch.index ?? 0;
1062
+ for (const lineMatch of block.matchAll(/^\s*(?:([A-Za-z_]\w*|[_.])\s+)?\"([^\"]+)\"/gm)) {
1063
+ const imported = lineMatch[1] ?? "";
1064
+ const toRef = lineMatch[2] ?? "";
1065
+ const line = lineNumber(file.text, blockStart + (lineMatch.index ?? 0));
1066
+ insertGoImport(file, statements, toRef, imported, line, lineMatch[0].trim());
1067
+ }
1068
+ });
1069
+ }
1070
+ function indexConfigs(file, insertConfig) {
1071
+ if (path.basename(file.path) === "package.json") {
1072
+ try {
1073
+ const parsed = JSON.parse(file.text);
1074
+ for (const [name, value] of Object.entries(parsed.scripts ?? {}))
1075
+ insertConfig.run(`script:${name}`, value, file.path, 1);
1076
+ for (const [name, value] of Object.entries(parsed.dependencies ?? {}))
1077
+ insertConfig.run(`dependency:${name}`, value, file.path, 1);
1078
+ for (const [name, value] of Object.entries(parsed.devDependencies ?? {}))
1079
+ insertConfig.run(`devDependency:${name}`, value, file.path, 1);
1080
+ }
1081
+ catch {
1082
+ insertConfig.run("parse-error", "package.json is not valid JSON", file.path, 1);
1083
+ }
1084
+ return;
1085
+ }
1086
+ insertMatches(file, /^\s*([A-Za-z0-9_.-]+)\s*[:=]\s*(.+)$/gm, (match, line) => {
1087
+ insertConfig.run(match[1] ?? "", (match[2] ?? "").trim(), file.path, line);
1088
+ });
1089
+ }
1090
+ function codeScopes() {
1091
+ const scopes = args_1.codeIndexScopes.length > 0 ? args_1.codeIndexScopes : ["."];
1092
+ return scopes.map((scope) => normalizeProjectRelative(scope, "--code-scope"));
1093
+ }
1094
+ function openDatabase(databasePath) {
1095
+ return (0, code_index_db_1.openDatabase)(databasePath, fail);
1096
+ }
1097
+ function requireExistingIndex() {
1098
+ const databasePath = codeEvidenceDatabasePath();
1099
+ if (!fs.existsSync(databasePath.absolutePath)) {
1100
+ console.error(`missing code evidence index: ${databasePath.relativePath}; run --code-index first`);
1101
+ process.exit(1);
1102
+ }
1103
+ }
1104
+ function readMetaValue(database, key) {
1105
+ const rows = database.prepare("SELECT value FROM meta WHERE key = ?").all(key);
1106
+ const value = rows[0]?.value;
1107
+ return typeof value === "string" ? value : "";
1108
+ }
1109
+ function indexedScopes(database) {
1110
+ const scopesJson = readMetaValue(database, "scopes_json");
1111
+ if (scopesJson) {
1112
+ try {
1113
+ const parsed = JSON.parse(scopesJson);
1114
+ if (Array.isArray(parsed) && parsed.every((scope) => typeof scope === "string"))
1115
+ return parsed;
1116
+ }
1117
+ catch {
1118
+ // Fall back to the legacy comma-separated scope metadata below.
1119
+ }
1120
+ }
1121
+ return readMetaValue(database, "scopes")
1122
+ .split(",")
1123
+ .map((scope) => scope.trim())
1124
+ .filter(Boolean);
1125
+ }
1126
+ function indexedParserMode(database) {
1127
+ const mode = readMetaValue(database, "parser_mode");
1128
+ return mode === "tree-sitter" ? "tree-sitter" : "default";
1129
+ }
1130
+ function scopesMatch(left, right) {
1131
+ return left.length === right.length && left.every((scope, index) => scope === right[index]);
1132
+ }
1133
+ function incrementalCompatibility(database, scopes, parserMode) {
1134
+ const existingSchemaVersion = readMetaValue(database, "schema_version");
1135
+ if (existingSchemaVersion !== codeIndexSchemaVersion) {
1136
+ return {
1137
+ compatible: false,
1138
+ reason: `existing schema version ${existingSchemaVersion || "(missing)"} does not match ${codeIndexSchemaVersion}`,
1139
+ };
1140
+ }
1141
+ const existingScopes = indexedScopes(database);
1142
+ if (!scopesMatch(existingScopes, scopes)) {
1143
+ return {
1144
+ compatible: false,
1145
+ reason: `indexed scopes do not match requested scopes: indexed [${existingScopes.join(", ")}], requested [${scopes.join(", ")}]`,
1146
+ };
1147
+ }
1148
+ const existingParserMode = indexedParserMode(database);
1149
+ if (existingParserMode !== parserMode) {
1150
+ return {
1151
+ compatible: false,
1152
+ reason: `indexed parser mode ${existingParserMode} does not match requested parser mode ${parserMode}`,
1153
+ };
1154
+ }
1155
+ return { compatible: true, reason: "" };
1156
+ }
1157
+ function removeDatabaseFiles(databasePath) {
1158
+ for (const filePath of [databasePath, `${databasePath}-wal`, `${databasePath}-shm`]) {
1159
+ if (fs.existsSync(filePath))
1160
+ fs.unlinkSync(filePath);
1161
+ }
1162
+ }
1163
+ function codeIndexStaleness(database) {
1164
+ const scopes = indexedScopes(database);
1165
+ const parserMode = indexedParserMode(database);
1166
+ const current = new Map(discoverCodeFiles(scopes.length > 0 ? scopes : ["."]).map((file) => {
1167
+ const codeFile = readCodeFile(file, parserMode);
1168
+ return [codeFile.path, codeFile.hash];
1169
+ }));
1170
+ const indexed = new Map(database.prepare("SELECT path, hash FROM files").all().map((row) => [String(row.path), String(row.hash)]));
1171
+ let changed = 0;
1172
+ let deleted = 0;
1173
+ for (const [filePath, hash] of indexed) {
1174
+ const currentHash = current.get(filePath);
1175
+ if (!currentHash)
1176
+ deleted += 1;
1177
+ else if (currentHash !== hash)
1178
+ changed += 1;
1179
+ }
1180
+ let added = 0;
1181
+ for (const filePath of current.keys()) {
1182
+ if (!indexed.has(filePath))
1183
+ added += 1;
1184
+ }
1185
+ return {
1186
+ added,
1187
+ changed,
1188
+ deleted,
1189
+ stale: added > 0 || changed > 0 || deleted > 0,
1190
+ };
1191
+ }
1192
+ function warnIfCodeIndexStale(database) {
1193
+ const staleness = codeIndexStaleness(database);
1194
+ if (!staleness.stale)
1195
+ return;
1196
+ console.error(`code evidence index may be stale: ${staleness.changed} changed, ${staleness.added} added, ${staleness.deleted} deleted; rerun --code-index`);
1197
+ }
1198
+ function pathOwnerKey(filePath) {
1199
+ const parts = (0, workspace_1.normalizePath)(filePath).split("/").filter(Boolean);
1200
+ if (parts.length === 0)
1201
+ return ".";
1202
+ if (["apps", "libs", "packages", "services"].includes(parts[0] ?? "") && parts[1])
1203
+ return `${parts[0]}/${parts[1]}`;
1204
+ return parts[0] ?? ".";
1205
+ }
1206
+ function readJsonObject(relativePath) {
1207
+ try {
1208
+ const parsed = JSON.parse(fs.readFileSync((0, workspace_1.abs)(relativePath), "utf8"));
1209
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
1210
+ }
1211
+ catch {
1212
+ return null;
1213
+ }
1214
+ }
1215
+ function workspacePatternsFromRootPackage() {
1216
+ const rootPackage = readJsonObject("package.json");
1217
+ const workspaces = rootPackage?.workspaces;
1218
+ if (Array.isArray(workspaces))
1219
+ return workspaces.filter((value) => typeof value === "string");
1220
+ if (workspaces && typeof workspaces === "object" && !Array.isArray(workspaces)) {
1221
+ const packages = workspaces.packages;
1222
+ if (Array.isArray(packages))
1223
+ return packages.filter((value) => typeof value === "string");
1224
+ }
1225
+ return [];
1226
+ }
1227
+ function workspacePatternCandidates(pattern) {
1228
+ const normalized = (0, workspace_1.normalizePath)(pattern).replace(/^\/+/, "").replace(/\/+$/, "");
1229
+ if (!normalized || normalized.includes(".."))
1230
+ return [];
1231
+ if (!normalized.includes("*"))
1232
+ return [normalized];
1233
+ const starIndex = normalized.indexOf("*");
1234
+ const prefix = normalized.slice(0, starIndex).replace(/\/+$/, "");
1235
+ const suffix = normalized.slice(starIndex + 1).replace(/^\/+/, "");
1236
+ const base = prefix || ".";
1237
+ const basePath = (0, workspace_1.abs)(base);
1238
+ if (!fs.existsSync(basePath) || !fs.statSync(basePath).isDirectory())
1239
+ return [];
1240
+ return fs.readdirSync(basePath, { withFileTypes: true })
1241
+ .filter((entry) => entry.isDirectory())
1242
+ .map((entry) => (0, workspace_1.normalizePath)(path.join(base, entry.name, suffix)))
1243
+ .filter((candidate) => fs.existsSync((0, workspace_1.abs)(candidate)) && fs.statSync((0, workspace_1.abs)(candidate)).isDirectory());
1244
+ }
1245
+ function workspacePackages() {
1246
+ const packages = new Map();
1247
+ for (const pattern of workspacePatternsFromRootPackage()) {
1248
+ for (const candidate of workspacePatternCandidates(pattern)) {
1249
+ const packageJsonPath = (0, workspace_1.normalizePath)(path.join(candidate, "package.json"));
1250
+ if (!fs.existsSync((0, workspace_1.abs)(packageJsonPath)))
1251
+ continue;
1252
+ const packageJson = readJsonObject(packageJsonPath);
1253
+ const packageName = typeof packageJson?.name === "string" ? packageJson.name : candidate;
1254
+ packages.set(candidate, {
1255
+ name: packageName,
1256
+ root: candidate,
1257
+ source: "package.json workspaces",
1258
+ workspace_pattern: pattern,
1259
+ });
1260
+ }
1261
+ }
1262
+ return Array.from(packages.values()).sort((left, right) => left.root.localeCompare(right.root));
1263
+ }
1264
+ function matchingWorkspace(filePath, workspaces) {
1265
+ const normalized = (0, workspace_1.normalizePath)(filePath);
1266
+ return workspaces
1267
+ .filter((workspace) => normalized === workspace.root || normalized.startsWith(`${workspace.root}/`))
1268
+ .sort((left, right) => right.root.length - left.root.length)[0] ?? null;
1269
+ }
1270
+ function codeownerRules() {
1271
+ const files = [".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS"];
1272
+ const rules = [];
1273
+ for (const filePath of files) {
1274
+ if (!fs.existsSync((0, workspace_1.abs)(filePath)))
1275
+ continue;
1276
+ const lines = fs.readFileSync((0, workspace_1.abs)(filePath), "utf8").split(/\r?\n/);
1277
+ lines.forEach((lineText, index) => {
1278
+ const trimmed = lineText.trim();
1279
+ if (!trimmed || trimmed.startsWith("#"))
1280
+ return;
1281
+ const parts = trimmed.split(/\s+/);
1282
+ const pattern = parts[0] ?? "";
1283
+ const owners = parts.slice(1);
1284
+ if (!pattern || owners.length === 0)
1285
+ return;
1286
+ rules.push({ file_path: filePath, line: index + 1, owners, pattern });
1287
+ });
1288
+ }
1289
+ return rules;
1290
+ }
1291
+ function codeownerPatternRegex(pattern) {
1292
+ const normalized = (0, workspace_1.normalizePath)(pattern).replace(/^\/+/, "");
1293
+ const source = normalized
1294
+ .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
1295
+ .replace(/\*\*/g, ".*")
1296
+ .replace(/\*/g, "[^/]*");
1297
+ if (normalized.endsWith("/"))
1298
+ return new RegExp(`^${source}.*$`);
1299
+ return new RegExp(`^${source}(?:/.*)?$`);
1300
+ }
1301
+ function codeownerPatternMatches(pattern, filePath) {
1302
+ const normalized = (0, workspace_1.normalizePath)(pattern).replace(/^\/+/, "");
1303
+ const target = (0, workspace_1.normalizePath)(filePath);
1304
+ if (normalized === "*")
1305
+ return true;
1306
+ if (normalized.startsWith("*."))
1307
+ return path.basename(target).endsWith(normalized.slice(1));
1308
+ return codeownerPatternRegex(normalized).test(target);
1309
+ }
1310
+ function matchingCodeowners(filePath, rules) {
1311
+ const matches = rules.filter((rule) => codeownerPatternMatches(rule.pattern, filePath));
1312
+ return matches[matches.length - 1]?.owners ?? [];
1313
+ }
1314
+ function ownershipContext() {
1315
+ return {
1316
+ codeownerRules: codeownerRules(),
1317
+ workspaces: workspacePackages(),
1318
+ };
1319
+ }
1320
+ function ownershipInfo(filePath, context) {
1321
+ const workspace = matchingWorkspace(filePath, context.workspaces);
1322
+ const owners = matchingCodeowners(filePath, context.codeownerRules);
1323
+ return {
1324
+ codeowners: owners.join(", "),
1325
+ owner: workspace?.root ?? pathOwnerKey(filePath),
1326
+ owner_source: workspace ? "workspace" : "path",
1327
+ };
1328
+ }
1329
+ function incrementOwnerField(owners, context, filePath, field, increment = 1) {
1330
+ const info = ownershipInfo(filePath, context);
1331
+ const key = info.owner;
1332
+ const current = owners.get(key) ?? {
1333
+ bytes: 0,
1334
+ codeowners: info.codeowners,
1335
+ configs: 0,
1336
+ file_count: 0,
1337
+ imports: 0,
1338
+ languages: "",
1339
+ lines: 0,
1340
+ owner: key,
1341
+ owner_source: info.owner_source,
1342
+ routes: 0,
1343
+ symbols: 0,
1344
+ };
1345
+ if (info.codeowners && !current.codeowners.split(", ").includes(info.codeowners))
1346
+ current.codeowners = current.codeowners ? `${current.codeowners}; ${info.codeowners}` : info.codeowners;
1347
+ current[field] += increment;
1348
+ owners.set(key, current);
1349
+ }
1350
+ function evidenceCoverage(database) {
1351
+ const rows = database.prepare(`
1352
+ SELECT 'files' AS table_name, count(*) AS rows FROM files
1353
+ UNION ALL SELECT 'symbols', count(*) FROM symbols
1354
+ UNION ALL SELECT 'imports', count(*) FROM imports
1355
+ UNION ALL SELECT 'routes', count(*) FROM routes
1356
+ UNION ALL SELECT 'configs', count(*) FROM configs
1357
+ UNION ALL SELECT 'edges', count(*) FROM edges
1358
+ `).all();
1359
+ return Object.fromEntries(rows.map((row) => [String(row.table_name), Number(row.rows ?? 0)]));
1360
+ }
1361
+ function ownershipSummary(database) {
1362
+ const files = database.prepare("SELECT path, language, profile, lines, bytes FROM files ORDER BY path").all();
1363
+ const context = ownershipContext();
1364
+ const owners = new Map();
1365
+ const ownerLanguages = new Map();
1366
+ for (const row of files) {
1367
+ const filePath = String(row.path);
1368
+ const key = ownershipInfo(filePath, context).owner;
1369
+ incrementOwnerField(owners, context, filePath, "file_count");
1370
+ incrementOwnerField(owners, context, filePath, "lines", Number(row.lines ?? 0));
1371
+ incrementOwnerField(owners, context, filePath, "bytes", Number(row.bytes ?? 0));
1372
+ const languages = ownerLanguages.get(key) ?? new Set();
1373
+ languages.add(String(row.language));
1374
+ ownerLanguages.set(key, languages);
1375
+ }
1376
+ for (const row of database.prepare("SELECT file_path, count(*) AS count FROM symbols GROUP BY file_path").all())
1377
+ incrementOwnerField(owners, context, String(row.file_path), "symbols", Number(row.count ?? 0));
1378
+ for (const row of database.prepare("SELECT file_path, count(*) AS count FROM routes GROUP BY file_path").all())
1379
+ incrementOwnerField(owners, context, String(row.file_path), "routes", Number(row.count ?? 0));
1380
+ for (const row of database.prepare("SELECT from_file, count(*) AS count FROM imports GROUP BY from_file").all())
1381
+ incrementOwnerField(owners, context, String(row.from_file), "imports", Number(row.count ?? 0));
1382
+ for (const row of database.prepare("SELECT file_path, count(*) AS count FROM configs GROUP BY file_path").all())
1383
+ incrementOwnerField(owners, context, String(row.file_path), "configs", Number(row.count ?? 0));
1384
+ return Array.from(owners.values()).map((owner) => ({
1385
+ ...owner,
1386
+ languages: Array.from(ownerLanguages.get(String(owner.owner)) ?? []).sort().join(", "),
1387
+ })).sort((left, right) => right.file_count - left.file_count || left.owner.localeCompare(right.owner)).slice(0, 25);
1388
+ }
1389
+ function languageProfileSummary(database) {
1390
+ return database.prepare("SELECT language, profile, count(*) AS files, sum(lines) AS lines, sum(bytes) AS bytes FROM files GROUP BY language, profile ORDER BY files DESC, language").all();
1391
+ }
1392
+ function parserBackendSummary(database) {
1393
+ return database.prepare("SELECT language, profile, count(*) AS files, sum(lines) AS lines, sum(bytes) AS bytes FROM files GROUP BY language, profile ORDER BY files DESC, language").all().map((row) => {
1394
+ const profile = String(row.profile);
1395
+ const backend = extractionBackendForProfile(profile);
1396
+ return {
1397
+ language: row.language,
1398
+ profile,
1399
+ backend: backend.id,
1400
+ label: backend.label,
1401
+ extraction_strength: backend.strength,
1402
+ files: row.files,
1403
+ lines: row.lines,
1404
+ bytes: row.bytes,
1405
+ };
1406
+ });
1407
+ }
1408
+ function workspaceSummary(database) {
1409
+ const context = ownershipContext();
1410
+ const counts = new Map();
1411
+ for (const workspace of context.workspaces) {
1412
+ counts.set(workspace.root, { ...workspace, bytes: 0, files: 0, lines: 0 });
1413
+ }
1414
+ for (const row of database.prepare("SELECT path, lines, bytes FROM files ORDER BY path").all()) {
1415
+ const workspace = matchingWorkspace(String(row.path), context.workspaces);
1416
+ if (!workspace)
1417
+ continue;
1418
+ const current = counts.get(workspace.root) ?? { ...workspace, bytes: 0, files: 0, lines: 0 };
1419
+ current.files += 1;
1420
+ current.lines += Number(row.lines ?? 0);
1421
+ current.bytes += Number(row.bytes ?? 0);
1422
+ counts.set(workspace.root, current);
1423
+ }
1424
+ return {
1425
+ workspace_packages: Array.from(counts.values()).sort((left, right) => left.root.localeCompare(right.root)),
1426
+ codeowners: context.codeownerRules.map((rule) => ({
1427
+ file_path: rule.file_path,
1428
+ line: rule.line,
1429
+ pattern: rule.pattern,
1430
+ owners: rule.owners.join(", "),
1431
+ })),
1432
+ };
1433
+ }
1434
+ function packageManagerFromLockfile(filePath) {
1435
+ const base = path.basename(filePath);
1436
+ if (base === "package-lock.json" || base === "npm-shrinkwrap.json")
1437
+ return "npm";
1438
+ if (base === "pnpm-lock.yaml")
1439
+ return "pnpm";
1440
+ if (base === "yarn.lock")
1441
+ return "yarn";
1442
+ if (base === "bun.lockb" || base === "bun.lock")
1443
+ return "bun";
1444
+ return "unknown";
1445
+ }
1446
+ function workspaceDependencyGraph() {
1447
+ const workspaces = workspacePackages();
1448
+ const byName = new Map(workspaces.map((workspace) => [workspace.name, workspace]));
1449
+ const lockfiles = ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"]
1450
+ .filter((filePath) => fs.existsSync((0, workspace_1.abs)(filePath)))
1451
+ .map((filePath) => ({ file_path: filePath, package_manager: packageManagerFromLockfile(filePath), scope: "root" }));
1452
+ const workspaceRows = [];
1453
+ const internalEdges = [];
1454
+ const externalDependencies = new Map();
1455
+ for (const workspace of workspaces) {
1456
+ const packageJsonPath = (0, workspace_1.normalizePath)(path.join(workspace.root, "package.json"));
1457
+ const packageJson = readJsonObject(packageJsonPath);
1458
+ const dependencyFields = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
1459
+ const dependencyCounts = {};
1460
+ const workspaceInternalEdges = [];
1461
+ for (const field of dependencyFields) {
1462
+ const dependencies = packageJson?.[field];
1463
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies))
1464
+ continue;
1465
+ for (const [dependencyName, version] of Object.entries(dependencies)) {
1466
+ dependencyCounts[field] = (dependencyCounts[field] ?? 0) + 1;
1467
+ const target = byName.get(dependencyName);
1468
+ if (target) {
1469
+ const edge = {
1470
+ from_workspace: workspace.root,
1471
+ from_package: workspace.name,
1472
+ to_workspace: target.root,
1473
+ to_package: target.name,
1474
+ dependency_type: field,
1475
+ version: typeof version === "string" ? version : String(version),
1476
+ };
1477
+ internalEdges.push(edge);
1478
+ workspaceInternalEdges.push(edge);
1479
+ }
1480
+ else {
1481
+ const key = `${dependencyName}\0${field}`;
1482
+ const current = externalDependencies.get(key) ?? { dependency: dependencyName, dependency_type: field, workspaces: new Set() };
1483
+ current.workspaces.add(workspace.root);
1484
+ externalDependencies.set(key, current);
1485
+ }
1486
+ }
1487
+ }
1488
+ for (const lockfileName of ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"]) {
1489
+ const lockfilePath = (0, workspace_1.normalizePath)(path.join(workspace.root, lockfileName));
1490
+ if (fs.existsSync((0, workspace_1.abs)(lockfilePath))) {
1491
+ lockfiles.push({ file_path: lockfilePath, package_manager: packageManagerFromLockfile(lockfilePath), scope: workspace.root });
1492
+ }
1493
+ }
1494
+ workspaceRows.push({
1495
+ name: workspace.name,
1496
+ root: workspace.root,
1497
+ dependency_counts: dependencyCounts,
1498
+ internal_dependency_count: workspaceInternalEdges.length,
1499
+ });
1500
+ }
1501
+ return {
1502
+ workspace_count: workspaces.length,
1503
+ package_managers: Array.from(new Set(lockfiles.map((lockfile) => lockfile.package_manager))).sort(),
1504
+ lockfiles,
1505
+ workspaces: workspaceRows.sort((left, right) => String(left.root).localeCompare(String(right.root))),
1506
+ internal_dependencies: internalEdges.sort((left, right) => String(left.from_workspace).localeCompare(String(right.from_workspace)) || String(left.to_workspace).localeCompare(String(right.to_workspace))),
1507
+ external_dependency_hotspots: Array.from(externalDependencies.values()).map((entry) => ({
1508
+ dependency: entry.dependency,
1509
+ dependency_type: entry.dependency_type,
1510
+ workspace_count: entry.workspaces.size,
1511
+ workspaces: Array.from(entry.workspaces).sort().join(", "),
1512
+ })).sort((left, right) => right.workspace_count - left.workspace_count || left.dependency.localeCompare(right.dependency)).slice(0, 100),
1513
+ };
1514
+ }
1515
+ function routeInventory(database) {
1516
+ return database.prepare("SELECT method, route, file_path, line, handler FROM routes ORDER BY file_path, line LIMIT 100").all();
1517
+ }
1518
+ function dependencyHotspots(database) {
1519
+ return {
1520
+ imports: database.prepare("SELECT to_ref, count(DISTINCT from_file) AS importing_files, count(*) AS reference_count FROM imports GROUP BY to_ref ORDER BY importing_files DESC, reference_count DESC, to_ref LIMIT 50").all(),
1521
+ package_dependencies: database.prepare("SELECT substr(key, 12) AS package, value AS version, file_path FROM configs WHERE key LIKE 'dependency:%' ORDER BY file_path, package LIMIT 100").all(),
1522
+ };
1523
+ }
1524
+ function configInventory(database) {
1525
+ return database.prepare("SELECT key, value, file_path, line FROM configs WHERE key LIKE 'script:%' OR key LIKE 'dependency:%' OR key LIKE 'devDependency:%' ORDER BY file_path, key LIMIT 150").all();
1526
+ }
1527
+ function edgeSummary(database) {
1528
+ return {
1529
+ by_kind: database.prepare("SELECT kind, count(*) AS edges FROM edges GROUP BY kind ORDER BY edges DESC, kind").all(),
1530
+ fanout: database.prepare("SELECT source_kind, source, kind, count(DISTINCT target) AS targets, file_path FROM edges GROUP BY source_kind, source, kind, file_path ORDER BY targets DESC, source LIMIT 50").all(),
1531
+ };
1532
+ }
1533
+ function codeReportSectionData(database, section) {
1534
+ switch (section) {
1535
+ case "coverage":
1536
+ return evidenceCoverage(database);
1537
+ case "ownership":
1538
+ return ownershipSummary(database);
1539
+ case "languages":
1540
+ return languageProfileSummary(database);
1541
+ case "parsers":
1542
+ return parserBackendSummary(database);
1543
+ case "workspaces":
1544
+ return workspaceSummary(database);
1545
+ case "workspace-graph":
1546
+ return workspaceDependencyGraph();
1547
+ case "routes":
1548
+ return routeInventory(database);
1549
+ case "hotspots":
1550
+ return dependencyHotspots(database);
1551
+ case "configs":
1552
+ return configInventory(database);
1553
+ case "edges":
1554
+ return edgeSummary(database);
1555
+ }
1556
+ }
1557
+ function codeReportMetadata(database) {
1558
+ const databasePath = codeEvidenceDatabasePath();
1559
+ const staleness = codeIndexStaleness(database);
1560
+ return {
1561
+ schema_version: 1,
1562
+ generated_at: new Date().toISOString(),
1563
+ database: databasePath.relativePath,
1564
+ scopes: indexedScopes(database),
1565
+ parser_mode: indexedParserMode(database),
1566
+ stale: {
1567
+ files: staleness.added + staleness.changed + staleness.deleted,
1568
+ changed: staleness.changed,
1569
+ added: staleness.added,
1570
+ deleted: staleness.deleted,
1571
+ },
1572
+ };
1573
+ }
1574
+ function codeReport(database) {
1575
+ return {
1576
+ ...codeReportMetadata(database),
1577
+ report_sections: ["evidence_coverage", "ownership_summary", "language_profile_summary", "parser_backend_summary", "workspace_summary", "workspace_dependency_graph", "route_inventory", "dependency_hotspots", "config_inventory", "edge_summary"],
1578
+ evidence_coverage: evidenceCoverage(database),
1579
+ ownership_summary: ownershipSummary(database),
1580
+ language_profile_summary: languageProfileSummary(database),
1581
+ parser_backend_summary: parserBackendSummary(database),
1582
+ workspace_summary: workspaceSummary(database),
1583
+ workspace_dependency_graph: workspaceDependencyGraph(),
1584
+ route_inventory: routeInventory(database),
1585
+ dependency_hotspots: dependencyHotspots(database),
1586
+ config_inventory: configInventory(database),
1587
+ edge_summary: edgeSummary(database),
1588
+ };
1589
+ }
1590
+ function selectedCodeReportSection() {
1591
+ const requested = args_1.codeReportSection.trim().toLowerCase();
1592
+ if (!requested || requested === "all" || requested === "full")
1593
+ return "";
1594
+ const section = codeReportSectionAliases[requested];
1595
+ if (!section) {
1596
+ const valid = ["coverage", "ownership", "languages", "parsers", "workspaces", "workspace-graph", "routes", "hotspots", "configs", "edges"].join(", ");
1597
+ fail(`invalid --code-report-section: ${args_1.codeReportSection}; expected one of: ${valid}`);
1598
+ }
1599
+ return section;
1600
+ }
1601
+ function codeReportForRequestedSection(database) {
1602
+ const section = selectedCodeReportSection();
1603
+ if (!section)
1604
+ return codeReport(database);
1605
+ return {
1606
+ ...codeReportMetadata(database),
1607
+ section,
1608
+ data: codeReportSectionData(database, section),
1609
+ };
1610
+ }
1611
+ function codeImpact(database, target) {
1612
+ const like = `%${target}%`;
1613
+ const fileMatches = database.prepare("SELECT path, language, profile, lines, bytes FROM files WHERE path LIKE ? ORDER BY path LIMIT 25").all(like);
1614
+ const symbolMatches = database.prepare("SELECT name, kind, file_path, line, signature FROM symbols WHERE name LIKE ? OR signature LIKE ? OR file_path LIKE ? ORDER BY file_path, line LIMIT 50").all(like, like, like);
1615
+ const routeMatches = database.prepare("SELECT method, route, file_path, line, handler FROM routes WHERE route LIKE ? OR handler LIKE ? OR file_path LIKE ? ORDER BY file_path, line LIMIT 50").all(like, like, like);
1616
+ const importMatches = database.prepare("SELECT from_file, to_ref, imported, line, raw FROM imports WHERE from_file LIKE ? OR to_ref LIKE ? OR imported LIKE ? ORDER BY from_file, line LIMIT 75").all(like, like, like);
1617
+ const outgoingEdges = database.prepare("SELECT kind, source_kind, source, target_kind, target, file_path, line, evidence FROM edges WHERE file_path LIKE ? OR source LIKE ? ORDER BY file_path, line LIMIT 100").all(like, like);
1618
+ const incomingEdges = database.prepare("SELECT kind, source_kind, source, target_kind, target, file_path, line, evidence FROM edges WHERE target LIKE ? ORDER BY file_path, line LIMIT 100").all(like);
1619
+ const routeTargets = routeMatches.map((row) => `${String(row.method)} ${String(row.route)}`);
1620
+ const routeEdges = routeTargets.length === 0 ? [] : database.prepare(`SELECT kind, source_kind, source, target_kind, target, file_path, line, evidence FROM edges WHERE source IN (${routeTargets.map(() => "?").join(", ")}) ORDER BY file_path, line LIMIT 100`).all(...routeTargets);
1621
+ const relatedFilePaths = Array.from(new Set([
1622
+ ...fileMatches.map((row) => String(row.path)),
1623
+ ...symbolMatches.map((row) => String(row.file_path)),
1624
+ ...routeMatches.map((row) => String(row.file_path)),
1625
+ ...importMatches.map((row) => String(row.from_file)),
1626
+ ...outgoingEdges.map((row) => String(row.file_path)),
1627
+ ...incomingEdges.map((row) => String(row.file_path)),
1628
+ ...routeEdges.map((row) => String(row.file_path)),
1629
+ ].filter(Boolean))).sort();
1630
+ const ownership = ownershipContext();
1631
+ const impactedOwners = new Map();
1632
+ for (const filePath of relatedFilePaths) {
1633
+ const info = ownershipInfo(filePath, ownership);
1634
+ const current = impactedOwners.get(info.owner) ?? {
1635
+ codeowners: new Set(),
1636
+ files: 0,
1637
+ owner: info.owner,
1638
+ owner_source: info.owner_source,
1639
+ sample_files: [],
1640
+ };
1641
+ current.files += 1;
1642
+ if (current.sample_files.length < 10)
1643
+ current.sample_files.push(filePath);
1644
+ if (info.codeowners) {
1645
+ for (const owner of info.codeowners.split(", ").filter(Boolean))
1646
+ current.codeowners.add(owner);
1647
+ }
1648
+ impactedOwners.set(info.owner, current);
1649
+ }
1650
+ return {
1651
+ ...codeReportMetadata(database),
1652
+ target,
1653
+ matches: {
1654
+ files: fileMatches,
1655
+ symbols: symbolMatches,
1656
+ routes: routeMatches,
1657
+ imports: importMatches,
1658
+ },
1659
+ edges: {
1660
+ outgoing: outgoingEdges,
1661
+ incoming: incomingEdges,
1662
+ routes: routeEdges,
1663
+ },
1664
+ impacted_owners: Array.from(impactedOwners.values()).map((owner) => ({
1665
+ owner: owner.owner,
1666
+ owner_source: owner.owner_source,
1667
+ files: owner.files,
1668
+ codeowners: Array.from(owner.codeowners).sort().join(", "),
1669
+ sample_files: owner.sample_files,
1670
+ })).sort((left, right) => right.files - left.files || left.owner.localeCompare(right.owner)),
1671
+ };
1672
+ }
1673
+ function prepareOutputPath() {
1674
+ const databasePath = codeEvidenceDatabasePath();
1675
+ (0, workspace_1.mkdirp)(path.dirname(databasePath.relativePath));
1676
+ (0, workspace_1.mkdirp)(codeEvidenceDirectory);
1677
+ fs.writeFileSync((0, workspace_1.abs)(`${codeEvidenceDirectory}/.gitignore`), "*\n!.gitignore\n");
1678
+ }
1679
+ function runCodeIndexMode() {
1680
+ const databasePath = codeEvidenceDatabasePath();
1681
+ const scopes = codeScopes();
1682
+ const parserMode = selectedCodeParserMode();
1683
+ const existingIndex = fs.existsSync(databasePath.absolutePath);
1684
+ if (args_1.codeIndexIncrementalMode && !existingIndex) {
1685
+ fail(`--incremental requires an existing compatible code evidence index: ${databasePath.relativePath}`);
1686
+ }
1687
+ let incremental = false;
1688
+ if (existingIndex && !args_1.codeIndexFullMode) {
1689
+ let compatibility = { compatible: false, reason: "compatibility was not checked" };
1690
+ const existingDatabase = openDatabase(databasePath.absolutePath);
1691
+ try {
1692
+ compatibility = incrementalCompatibility(existingDatabase, scopes, parserMode);
1693
+ }
1694
+ finally {
1695
+ existingDatabase.close();
1696
+ }
1697
+ incremental = !args_1.codeIndexFullMode && compatibility.compatible;
1698
+ if (args_1.codeIndexIncrementalMode && !compatibility.compatible)
1699
+ fail(`--incremental cannot update ${databasePath.relativePath}: ${compatibility.reason}`);
1700
+ }
1701
+ prepareOutputPath();
1702
+ if (!incremental)
1703
+ removeDatabaseFiles(databasePath.absolutePath);
1704
+ const database = openDatabase(databasePath.absolutePath);
1705
+ try {
1706
+ if (!incremental)
1707
+ setupDatabase(database);
1708
+ const statements = createIndexStatements(database);
1709
+ const currentFiles = discoverCodeFiles(scopes).map((filePath) => readCodeFile(filePath, parserMode));
1710
+ const currentByPath = new Map(currentFiles.map((file) => [file.path, file]));
1711
+ const indexed = incremental ? new Map(database.prepare("SELECT path, hash FROM files").all().map((row) => [String(row.path), String(row.hash)])) : new Map();
1712
+ const deletedPaths = incremental ? Array.from(indexed.keys()).filter((filePath) => !currentByPath.has(filePath)) : [];
1713
+ const reindexedFiles = incremental
1714
+ ? currentFiles.filter((file) => indexed.get(file.path) !== file.hash)
1715
+ : currentFiles;
1716
+ const unchangedFiles = incremental ? currentFiles.length - reindexedFiles.length : 0;
1717
+ database.exec("BEGIN");
1718
+ if (!incremental)
1719
+ statements.insertMeta.run("created_at", new Date().toISOString());
1720
+ writeIndexMetadata(scopes, parserMode, statements);
1721
+ for (const filePath of deletedPaths)
1722
+ removeIndexedFile(filePath, statements);
1723
+ for (const file of reindexedFiles) {
1724
+ if (incremental && indexed.has(file.path))
1725
+ removeIndexedFile(file.path, statements);
1726
+ indexCodeFile(file, statements);
1727
+ }
1728
+ database.exec("COMMIT");
1729
+ console.log("Project wiki code evidence index complete.");
1730
+ console.log(`database: ${databasePath.relativePath}`);
1731
+ console.log(`mode: ${incremental ? "incremental" : "full"}`);
1732
+ console.log(`parser_mode: ${parserMode}`);
1733
+ console.log(`scopes: ${scopes.join(", ")}`);
1734
+ console.log(`files: ${currentFiles.length}`);
1735
+ console.log(`reindexed_files: ${reindexedFiles.length}`);
1736
+ console.log(`deleted_files: ${deletedPaths.length}`);
1737
+ console.log(`unchanged_files: ${unchangedFiles}`);
1738
+ }
1739
+ catch (error) {
1740
+ try {
1741
+ database.exec("ROLLBACK");
1742
+ }
1743
+ catch {
1744
+ // Ignore rollback failures after setup errors.
1745
+ }
1746
+ throw error;
1747
+ }
1748
+ finally {
1749
+ database.close();
1750
+ }
1751
+ }
1752
+ function runCodeQueryMode() {
1753
+ if (!args_1.codeQuerySql.trim()) {
1754
+ console.error("missing SQL: use --code-query \"select ...\"");
1755
+ process.exit(1);
1756
+ }
1757
+ requireExistingIndex();
1758
+ if (!(0, code_index_sql_1.isReadOnlySql)(args_1.codeQuerySql)) {
1759
+ console.error("code queries must be read-only SQL starting with SELECT or WITH");
1760
+ process.exit(1);
1761
+ }
1762
+ const database = openDatabase(codeEvidenceDatabasePath().absolutePath);
1763
+ try {
1764
+ database.exec("PRAGMA query_only = ON");
1765
+ warnIfCodeIndexStale(database);
1766
+ printRows(database.prepare(args_1.codeQuerySql).all());
1767
+ }
1768
+ finally {
1769
+ database.close();
1770
+ }
1771
+ }
1772
+ function runCodeReportMode() {
1773
+ requireExistingIndex();
1774
+ const database = openDatabase(codeEvidenceDatabasePath().absolutePath);
1775
+ try {
1776
+ warnIfCodeIndexStale(database);
1777
+ printJson(codeReportForRequestedSection(database));
1778
+ }
1779
+ finally {
1780
+ database.close();
1781
+ }
1782
+ }
1783
+ function runCodeStatusMode() {
1784
+ requireExistingIndex();
1785
+ const database = openDatabase(codeEvidenceDatabasePath().absolutePath);
1786
+ try {
1787
+ const rows = database.prepare(`
1788
+ SELECT 'files' AS metric, count(*) AS value FROM files
1789
+ UNION ALL SELECT 'symbols', count(*) FROM symbols
1790
+ UNION ALL SELECT 'imports', count(*) FROM imports
1791
+ UNION ALL SELECT 'routes', count(*) FROM routes
1792
+ UNION ALL SELECT 'edges', count(*) FROM edges
1793
+ UNION ALL SELECT 'configs', count(*) FROM configs
1794
+ `).all();
1795
+ const staleness = codeIndexStaleness(database);
1796
+ rows.push({ metric: "stale_files", value: staleness.added + staleness.changed + staleness.deleted }, { metric: "stale_changed_files", value: staleness.changed }, { metric: "stale_added_files", value: staleness.added }, { metric: "stale_deleted_files", value: staleness.deleted });
1797
+ printRows(rows);
1798
+ }
1799
+ finally {
1800
+ database.close();
1801
+ }
1802
+ }
1803
+ function runCodeFilesMode() {
1804
+ requireExistingIndex();
1805
+ const database = openDatabase(codeEvidenceDatabasePath().absolutePath);
1806
+ try {
1807
+ warnIfCodeIndexStale(database);
1808
+ printRows(database.prepare("SELECT path, language, profile, kind, lines, bytes FROM files ORDER BY path").all());
1809
+ }
1810
+ finally {
1811
+ database.close();
1812
+ }
1813
+ }
1814
+ function runCodeImpactMode() {
1815
+ if (!args_1.codeImpactTarget.trim()) {
1816
+ console.error("missing impact target: use --code-impact \"path-or-symbol-or-module\"");
1817
+ process.exit(1);
1818
+ }
1819
+ requireExistingIndex();
1820
+ const database = openDatabase(codeEvidenceDatabasePath().absolutePath);
1821
+ try {
1822
+ warnIfCodeIndexStale(database);
1823
+ printJson(codeImpact(database, args_1.codeImpactTarget.trim()));
1824
+ }
1825
+ finally {
1826
+ database.close();
1827
+ }
1828
+ }
1829
+ function runCodeSearchSymbolMode() {
1830
+ if (!args_1.codeSearchSymbol.trim()) {
1831
+ console.error("missing symbol search term: use --code-search-symbol \"term\"");
1832
+ process.exit(1);
1833
+ }
1834
+ requireExistingIndex();
1835
+ const database = openDatabase(codeEvidenceDatabasePath().absolutePath);
1836
+ try {
1837
+ warnIfCodeIndexStale(database);
1838
+ const like = `%${args_1.codeSearchSymbol}%`;
1839
+ printRows(database.prepare("SELECT name, kind, file_path, line, signature FROM symbols WHERE name LIKE ? OR signature LIKE ? ORDER BY file_path, line LIMIT 50").all(like, like));
1840
+ }
1841
+ finally {
1842
+ database.close();
1843
+ }
1844
+ }
1845
+ function isCodeEvidenceMode() {
1846
+ return isCodeEvidenceModeFor({ codeFilesMode: args_1.codeFilesMode, codeImpactMode: args_1.codeImpactMode, codeIndexMode: args_1.codeIndexMode, codeQuerySql: args_1.codeQuerySql, codeReportMode: args_1.codeReportMode, codeSearchSymbol: args_1.codeSearchSymbol, codeStatusMode: args_1.codeStatusMode });
1847
+ }
1848
+ function isCodeEvidenceModeFor(flags) {
1849
+ return flags.codeIndexMode
1850
+ || Boolean(flags.codeQuerySql)
1851
+ || flags.codeReportMode
1852
+ || flags.codeStatusMode
1853
+ || flags.codeFilesMode
1854
+ || flags.codeImpactMode
1855
+ || Boolean(flags.codeSearchSymbol);
1856
+ }