@optave/codegraph 3.10.0 → 3.11.1
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 +40 -33
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +91 -60
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/rules/index.d.ts.map +1 -1
- package/dist/ast-analysis/rules/index.js +77 -0
- package/dist/ast-analysis/rules/index.js.map +1 -1
- package/dist/ast-analysis/visitor-utils.d.ts +3 -0
- package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
- package/dist/ast-analysis/visitor-utils.js +83 -49
- package/dist/ast-analysis/visitor-utils.js.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js +78 -62
- package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.js +61 -42
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/audit.js +1 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +2 -0
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/check.js +1 -1
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/children.js +1 -1
- package/dist/cli/commands/children.js.map +1 -1
- package/dist/cli/commands/diff-impact.js +1 -1
- package/dist/cli/commands/diff-impact.js.map +1 -1
- package/dist/cli/commands/embed.d.ts.map +1 -1
- package/dist/cli/commands/embed.js +49 -4
- package/dist/cli/commands/embed.js.map +1 -1
- package/dist/cli/commands/roles.js +1 -1
- package/dist/cli/commands/roles.js.map +1 -1
- package/dist/cli/commands/structure.js +1 -1
- package/dist/cli/commands/structure.js.map +1 -1
- package/dist/cli/shared/options.js +1 -1
- package/dist/cli/shared/options.js.map +1 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +8 -0
- package/dist/db/connection.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +106 -80
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +77 -52
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +132 -121
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +4 -4
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +47 -33
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts +6 -6
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +148 -99
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts +1 -0
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +23 -637
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +141 -98
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.js +82 -65
- package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +84 -56
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +60 -51
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts +8 -6
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.js +107 -122
- package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-db-lifecycle.d.ts +14 -0
- package/dist/domain/graph/builder/stages/native-db-lifecycle.d.ts.map +1 -0
- package/dist/domain/graph/builder/stages/native-db-lifecycle.js +77 -0
- package/dist/domain/graph/builder/stages/native-db-lifecycle.js.map +1 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts +62 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.js +747 -0
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -0
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +73 -22
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/cycles.d.ts +6 -4
- package/dist/domain/graph/cycles.d.ts.map +1 -1
- package/dist/domain/graph/cycles.js +50 -55
- package/dist/domain/graph/cycles.js.map +1 -1
- package/dist/domain/graph/journal.d.ts.map +1 -1
- package/dist/domain/graph/journal.js +89 -70
- package/dist/domain/graph/journal.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +28 -20
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +12 -23
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +153 -80
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/generator.d.ts +3 -1
- package/dist/domain/search/generator.d.ts.map +1 -1
- package/dist/domain/search/generator.js +68 -45
- package/dist/domain/search/generator.js.map +1 -1
- package/dist/domain/search/models.d.ts +18 -0
- package/dist/domain/search/models.d.ts.map +1 -1
- package/dist/domain/search/models.js +72 -4
- package/dist/domain/search/models.js.map +1 -1
- package/dist/domain/search/search/hybrid.d.ts.map +1 -1
- package/dist/domain/search/search/hybrid.js +49 -40
- package/dist/domain/search/search/hybrid.js.map +1 -1
- package/dist/domain/search/search/semantic.d.ts.map +1 -1
- package/dist/domain/search/search/semantic.js +69 -49
- package/dist/domain/search/search/semantic.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +209 -137
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/extractors/c.js +25 -6
- package/dist/extractors/c.js.map +1 -1
- package/dist/extractors/cpp.js +47 -6
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/cuda.js +90 -14
- package/dist/extractors/cuda.js.map +1 -1
- package/dist/extractors/elixir.js +108 -4
- package/dist/extractors/elixir.js.map +1 -1
- package/dist/extractors/erlang.js +56 -20
- package/dist/extractors/erlang.js.map +1 -1
- package/dist/extractors/fsharp.d.ts +7 -0
- package/dist/extractors/fsharp.d.ts.map +1 -1
- package/dist/extractors/fsharp.js +94 -0
- package/dist/extractors/fsharp.js.map +1 -1
- package/dist/extractors/gleam.d.ts.map +1 -1
- package/dist/extractors/gleam.js +29 -33
- package/dist/extractors/gleam.js.map +1 -1
- package/dist/extractors/groovy.js +41 -1
- package/dist/extractors/groovy.js.map +1 -1
- package/dist/extractors/haskell.js +48 -4
- package/dist/extractors/haskell.js.map +1 -1
- package/dist/extractors/helpers.d.ts +79 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +137 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +37 -49
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +44 -44
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/julia.js +198 -74
- package/dist/extractors/julia.js.map +1 -1
- package/dist/extractors/kotlin.js +4 -0
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/objc.js +184 -47
- package/dist/extractors/objc.js.map +1 -1
- package/dist/extractors/python.js +7 -4
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/r.d.ts.map +1 -1
- package/dist/extractors/r.js +103 -87
- package/dist/extractors/r.js.map +1 -1
- package/dist/extractors/scala.d.ts.map +1 -1
- package/dist/extractors/scala.js +18 -32
- package/dist/extractors/scala.js.map +1 -1
- package/dist/extractors/solidity.d.ts.map +1 -1
- package/dist/extractors/solidity.js +55 -69
- package/dist/extractors/solidity.js.map +1 -1
- package/dist/extractors/verilog.js +80 -15
- package/dist/extractors/verilog.js.map +1 -1
- package/dist/features/boundaries.d.ts.map +1 -1
- package/dist/features/boundaries.js +49 -39
- package/dist/features/boundaries.js.map +1 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +90 -63
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +43 -34
- package/dist/features/check.js.map +1 -1
- package/dist/features/cochange.d.ts.map +1 -1
- package/dist/features/cochange.js +68 -56
- package/dist/features/cochange.js.map +1 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +105 -75
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +37 -29
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/flow.d.ts.map +1 -1
- package/dist/features/flow.js +31 -22
- package/dist/features/flow.js.map +1 -1
- package/dist/features/graph-enrichment.d.ts.map +1 -1
- package/dist/features/graph-enrichment.js +77 -70
- package/dist/features/graph-enrichment.js.map +1 -1
- package/dist/features/owners.d.ts +17 -26
- package/dist/features/owners.d.ts.map +1 -1
- package/dist/features/owners.js +120 -109
- package/dist/features/owners.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +59 -54
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +60 -60
- package/dist/features/structure-query.js.map +1 -1
- package/dist/features/structure.js +28 -36
- package/dist/features/structure.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +100 -69
- package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
- package/dist/graph/classifiers/roles.d.ts.map +1 -1
- package/dist/graph/classifiers/roles.js +63 -59
- package/dist/graph/classifiers/roles.js.map +1 -1
- package/dist/infrastructure/config.d.ts +1 -1
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +1 -1
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +4 -0
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/mcp/tools/semantic-search.d.ts +1 -0
- package/dist/mcp/tools/semantic-search.d.ts.map +1 -1
- package/dist/mcp/tools/semantic-search.js +1 -0
- package/dist/mcp/tools/semantic-search.js.map +1 -1
- package/dist/presentation/cfg.d.ts.map +1 -1
- package/dist/presentation/cfg.js +44 -29
- package/dist/presentation/cfg.js.map +1 -1
- package/dist/presentation/flow.d.ts.map +1 -1
- package/dist/presentation/flow.js +58 -38
- package/dist/presentation/flow.js.map +1 -1
- package/dist/types.d.ts +16 -2
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-erlang.wasm +0 -0
- package/grammars/tree-sitter-fsharp.wasm +0 -0
- package/grammars/tree-sitter-fsharp_signature.wasm +0 -0
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +10 -10
- package/src/ast-analysis/engine.ts +145 -61
- package/src/ast-analysis/rules/index.ts +87 -0
- package/src/ast-analysis/visitor-utils.ts +86 -46
- package/src/ast-analysis/visitors/ast-store-visitor.ts +104 -69
- package/src/ast-analysis/visitors/dataflow-visitor.ts +86 -47
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +2 -0
- package/src/cli/commands/check.ts +1 -1
- package/src/cli/commands/children.ts +1 -1
- package/src/cli/commands/diff-impact.ts +1 -1
- package/src/cli/commands/embed.ts +54 -4
- package/src/cli/commands/roles.ts +1 -1
- package/src/cli/commands/structure.ts +1 -1
- package/src/cli/shared/options.ts +1 -1
- package/src/db/connection.ts +8 -0
- package/src/domain/analysis/dependencies.ts +166 -85
- package/src/domain/analysis/fn-impact.ts +120 -50
- package/src/domain/analysis/module-map.ts +175 -140
- package/src/domain/graph/builder/helpers.ts +85 -76
- package/src/domain/graph/builder/incremental.ts +223 -131
- package/src/domain/graph/builder/pipeline.ts +32 -785
- package/src/domain/graph/builder/stages/build-edges.ts +207 -142
- package/src/domain/graph/builder/stages/build-structure.ts +115 -82
- package/src/domain/graph/builder/stages/detect-changes.ts +107 -64
- package/src/domain/graph/builder/stages/finalize.ts +72 -70
- package/src/domain/graph/builder/stages/insert-nodes.ts +154 -120
- package/src/domain/graph/builder/stages/native-db-lifecycle.ts +74 -0
- package/src/domain/graph/builder/stages/native-orchestrator.ts +942 -0
- package/src/domain/graph/builder/stages/resolve-imports.ts +79 -25
- package/src/domain/graph/cycles.ts +51 -49
- package/src/domain/graph/journal.ts +84 -69
- package/src/domain/graph/watcher.ts +29 -25
- package/src/domain/parser.ts +170 -67
- package/src/domain/search/generator.ts +132 -74
- package/src/domain/search/models.ts +75 -4
- package/src/domain/search/search/hybrid.ts +53 -42
- package/src/domain/search/search/semantic.ts +105 -65
- package/src/domain/wasm-worker-entry.ts +243 -153
- package/src/extractors/c.ts +27 -8
- package/src/extractors/cpp.ts +50 -8
- package/src/extractors/cuda.ts +90 -16
- package/src/extractors/elixir.ts +103 -4
- package/src/extractors/erlang.ts +63 -20
- package/src/extractors/fsharp.ts +104 -0
- package/src/extractors/gleam.ts +40 -39
- package/src/extractors/groovy.ts +45 -1
- package/src/extractors/haskell.ts +45 -4
- package/src/extractors/helpers.ts +205 -1
- package/src/extractors/java.ts +42 -45
- package/src/extractors/javascript.ts +44 -43
- package/src/extractors/julia.ts +191 -77
- package/src/extractors/kotlin.ts +4 -0
- package/src/extractors/objc.ts +171 -47
- package/src/extractors/python.ts +5 -3
- package/src/extractors/r.ts +104 -82
- package/src/extractors/scala.ts +24 -36
- package/src/extractors/solidity.ts +59 -78
- package/src/extractors/verilog.ts +83 -15
- package/src/features/boundaries.ts +64 -46
- package/src/features/cfg.ts +145 -74
- package/src/features/check.ts +60 -43
- package/src/features/cochange.ts +95 -72
- package/src/features/complexity.ts +134 -79
- package/src/features/dataflow.ts +57 -34
- package/src/features/flow.ts +48 -24
- package/src/features/graph-enrichment.ts +105 -70
- package/src/features/owners.ts +186 -146
- package/src/features/sequence.ts +99 -69
- package/src/features/structure-query.ts +94 -79
- package/src/features/structure.ts +56 -56
- package/src/graph/algorithms/leiden/optimiser.ts +142 -87
- package/src/graph/classifiers/roles.ts +64 -54
- package/src/infrastructure/config.ts +1 -1
- package/src/mcp/tool-registry.ts +5 -0
- package/src/mcp/tools/semantic-search.ts +2 -0
- package/src/presentation/cfg.ts +48 -32
- package/src/presentation/flow.ts +100 -52
- package/src/types.ts +16 -1
|
@@ -181,46 +181,17 @@ function newTypesFor(astTypeMap: Record<string, string>): Set<string> {
|
|
|
181
181
|
return s;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
defs: Definition[],
|
|
187
|
-
relPath: string,
|
|
188
|
-
nodeIdMap: Map<string, number>,
|
|
189
|
-
stringConfig: AstStringConfig = DEFAULT_STRING_CONFIG,
|
|
190
|
-
stopRecurseKinds: ReadonlySet<string> = new Set(),
|
|
191
|
-
): Visitor {
|
|
192
|
-
const rows: AstStoreRow[] = [];
|
|
193
|
-
const matched = new Set<number>();
|
|
194
|
-
const newTypes = newTypesFor(astTypeMap);
|
|
195
|
-
// When nodeIdMap is empty, parentNodeId resolution is wasted work — the
|
|
196
|
-
// worker passes an empty map and the main thread re-resolves against its
|
|
197
|
-
// own DB-populated map in features/ast.ts::collectFileAstRows. Skip the
|
|
198
|
-
// findParentDef linear scan in that case.
|
|
199
|
-
const skipParentLookup = nodeIdMap.size === 0;
|
|
200
|
-
|
|
201
|
-
function findParentDef(line: number): Definition | null {
|
|
202
|
-
let best: Definition | null = null;
|
|
203
|
-
for (const def of defs) {
|
|
204
|
-
if (def.line <= line && (def.endLine == null || def.endLine >= line)) {
|
|
205
|
-
if (!best || (def.endLine ?? 0) - def.line < (best.endLine ?? 0) - best.line) {
|
|
206
|
-
best = def;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return best;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function resolveParentNodeId(line: number): number | null {
|
|
214
|
-
if (skipParentLookup) return null;
|
|
215
|
-
const parentDef = findParentDef(line);
|
|
216
|
-
if (!parentDef) return null;
|
|
217
|
-
return nodeIdMap.get(`${parentDef.name}|${parentDef.kind}|${parentDef.line}`) || null;
|
|
218
|
-
}
|
|
184
|
+
type NameTextResult = { name: string | null | undefined; text: string | null; skip?: boolean };
|
|
185
|
+
type KindHandler = (node: TreeSitterNode) => NameTextResult;
|
|
219
186
|
|
|
220
|
-
|
|
221
|
-
type KindHandler = (node: TreeSitterNode) => NameTextResult;
|
|
187
|
+
const DEFAULT_NAME_TEXT_RESULT: NameTextResult = { name: undefined, text: null };
|
|
222
188
|
|
|
223
|
-
|
|
189
|
+
/** Build the per-kind resolver map for name/text extraction. */
|
|
190
|
+
function buildKindHandlers(
|
|
191
|
+
newTypes: Set<string>,
|
|
192
|
+
stringConfig: AstStringConfig,
|
|
193
|
+
): Record<string, KindHandler> {
|
|
194
|
+
return {
|
|
224
195
|
new: (node) => ({ name: extractConstructorName(node), text: truncate(node.text) }),
|
|
225
196
|
throw: (node) => ({
|
|
226
197
|
name: extractThrowName(node, newTypes),
|
|
@@ -234,31 +205,102 @@ export function createAstStoreVisitor(
|
|
|
234
205
|
},
|
|
235
206
|
regex: (node) => ({ name: node.text || '?', text: truncate(node.text) }),
|
|
236
207
|
};
|
|
237
|
-
|
|
208
|
+
}
|
|
238
209
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
210
|
+
/** Find the innermost definition whose line range contains `line`. */
|
|
211
|
+
function findParentDef(line: number, defs: Definition[]): Definition | null {
|
|
212
|
+
let best: Definition | null = null;
|
|
213
|
+
for (const def of defs) {
|
|
214
|
+
if (def.line <= line && (def.endLine == null || def.endLine >= line)) {
|
|
215
|
+
if (!best || (def.endLine ?? 0) - def.line < (best.endLine ?? 0) - best.line) {
|
|
216
|
+
best = def;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
242
219
|
}
|
|
220
|
+
return best;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Resolve the parent definition's node id for a given source line. */
|
|
224
|
+
function resolveParentNodeId(
|
|
225
|
+
line: number,
|
|
226
|
+
defs: Definition[],
|
|
227
|
+
nodeIdMap: Map<string, number>,
|
|
228
|
+
skipParentLookup: boolean,
|
|
229
|
+
): number | null {
|
|
230
|
+
if (skipParentLookup) return null;
|
|
231
|
+
const parentDef = findParentDef(line, defs);
|
|
232
|
+
if (!parentDef) return null;
|
|
233
|
+
return nodeIdMap.get(`${parentDef.name}|${parentDef.kind}|${parentDef.line}`) || null;
|
|
234
|
+
}
|
|
243
235
|
|
|
244
|
-
|
|
245
|
-
|
|
236
|
+
interface CollectCtx {
|
|
237
|
+
rows: AstStoreRow[];
|
|
238
|
+
matched: Set<number>;
|
|
239
|
+
relPath: string;
|
|
240
|
+
defs: Definition[];
|
|
241
|
+
nodeIdMap: Map<string, number>;
|
|
242
|
+
skipParentLookup: boolean;
|
|
243
|
+
kindHandlers: Record<string, KindHandler>;
|
|
244
|
+
}
|
|
246
245
|
|
|
247
|
-
|
|
248
|
-
|
|
246
|
+
function collectNode(ctx: CollectCtx, node: TreeSitterNode, kind: string): void {
|
|
247
|
+
if (ctx.matched.has(node.id)) return;
|
|
248
|
+
|
|
249
|
+
const handler = ctx.kindHandlers[kind];
|
|
250
|
+
const resolved = handler ? handler(node) : DEFAULT_NAME_TEXT_RESULT;
|
|
251
|
+
if (resolved.skip) return;
|
|
252
|
+
|
|
253
|
+
const line = node.startPosition.row + 1;
|
|
254
|
+
ctx.rows.push({
|
|
255
|
+
file: ctx.relPath,
|
|
256
|
+
line,
|
|
257
|
+
kind,
|
|
258
|
+
name: resolved.name,
|
|
259
|
+
text: resolved.text,
|
|
260
|
+
receiver: null,
|
|
261
|
+
parentNodeId: resolveParentNodeId(line, ctx.defs, ctx.nodeIdMap, ctx.skipParentLookup),
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
ctx.matched.add(node.id);
|
|
265
|
+
}
|
|
249
266
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Resolve the kind for a tree-sitter node, or `null` if the node should be ignored.
|
|
269
|
+
*
|
|
270
|
+
* Gate with `hasOwn` because plain-object lookup walks Object.prototype:
|
|
271
|
+
* tree-sitter node types like `constructor` (Haskell sum-types: Left,
|
|
272
|
+
* Right) would otherwise resolve to `Object.prototype.constructor` (the
|
|
273
|
+
* Object() function), which then crashes the worker boundary with
|
|
274
|
+
* "function Object() { [native code] } could not be cloned" when the
|
|
275
|
+
* resulting astNodes row is structured-cloned back to the main thread.
|
|
276
|
+
*/
|
|
277
|
+
function resolveAstKind(node: TreeSitterNode, astTypeMap: Record<string, string>): string | null {
|
|
278
|
+
if (!Object.hasOwn(astTypeMap, node.type)) return null;
|
|
279
|
+
return astTypeMap[node.type] || null;
|
|
280
|
+
}
|
|
259
281
|
|
|
260
|
-
|
|
261
|
-
|
|
282
|
+
export function createAstStoreVisitor(
|
|
283
|
+
astTypeMap: Record<string, string>,
|
|
284
|
+
defs: Definition[],
|
|
285
|
+
relPath: string,
|
|
286
|
+
nodeIdMap: Map<string, number>,
|
|
287
|
+
stringConfig: AstStringConfig = DEFAULT_STRING_CONFIG,
|
|
288
|
+
stopRecurseKinds: ReadonlySet<string> = new Set(),
|
|
289
|
+
): Visitor {
|
|
290
|
+
const newTypes = newTypesFor(astTypeMap);
|
|
291
|
+
// When nodeIdMap is empty, parentNodeId resolution is wasted work — the
|
|
292
|
+
// worker passes an empty map and the main thread re-resolves against its
|
|
293
|
+
// own DB-populated map in features/ast.ts::collectFileAstRows. Skip the
|
|
294
|
+
// findParentDef linear scan in that case.
|
|
295
|
+
const ctx: CollectCtx = {
|
|
296
|
+
rows: [],
|
|
297
|
+
matched: new Set<number>(),
|
|
298
|
+
relPath,
|
|
299
|
+
defs,
|
|
300
|
+
nodeIdMap,
|
|
301
|
+
skipParentLookup: nodeIdMap.size === 0,
|
|
302
|
+
kindHandlers: buildKindHandlers(newTypes, stringConfig),
|
|
303
|
+
};
|
|
262
304
|
|
|
263
305
|
return {
|
|
264
306
|
name: 'ast-store',
|
|
@@ -267,19 +309,12 @@ export function createAstStoreVisitor(
|
|
|
267
309
|
// Guard: skip re-collection but do NOT skipChildren — node.id (memory address)
|
|
268
310
|
// can be reused by tree-sitter, so a collision would incorrectly suppress an
|
|
269
311
|
// unrelated subtree. The parent call's skipChildren handles the intended case.
|
|
270
|
-
if (matched.has(node.id)) return;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
// tree-sitter node types like `constructor` (Haskell sum-types: Left,
|
|
274
|
-
// Right) would otherwise resolve to `Object.prototype.constructor` (the
|
|
275
|
-
// Object() function), which then crashes the worker boundary with
|
|
276
|
-
// "function Object() { [native code] } could not be cloned" when the
|
|
277
|
-
// resulting astNodes row is structured-cloned back to the main thread.
|
|
278
|
-
if (!Object.hasOwn(astTypeMap, node.type)) return;
|
|
279
|
-
const kind = astTypeMap[node.type];
|
|
312
|
+
if (ctx.matched.has(node.id)) return;
|
|
313
|
+
|
|
314
|
+
const kind = resolveAstKind(node, astTypeMap);
|
|
280
315
|
if (!kind) return;
|
|
281
316
|
|
|
282
|
-
collectNode(node, kind);
|
|
317
|
+
collectNode(ctx, node, kind);
|
|
283
318
|
|
|
284
319
|
// Mirror the native walker's recursion policy. In JS/TS, the native
|
|
285
320
|
// javascript.rs walker returns after collecting `new` or `throw` to
|
|
@@ -293,7 +328,7 @@ export function createAstStoreVisitor(
|
|
|
293
328
|
},
|
|
294
329
|
|
|
295
330
|
finish(): AstStoreRow[] {
|
|
296
|
-
return rows;
|
|
331
|
+
return ctx.rows;
|
|
297
332
|
},
|
|
298
333
|
};
|
|
299
334
|
}
|
|
@@ -405,6 +405,79 @@ function handleReturn(
|
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
+
/** Collect parameter entries for a function and push a new scope onto the stack. */
|
|
409
|
+
function enterFunctionScope(
|
|
410
|
+
funcNode: TreeSitterNode,
|
|
411
|
+
rules: AnyRules,
|
|
412
|
+
scopeStack: ScopeEntry[],
|
|
413
|
+
parameters: DataflowParam[],
|
|
414
|
+
): void {
|
|
415
|
+
const name = functionName(funcNode, rules);
|
|
416
|
+
const paramsNode = funcNode.childForFieldName(rules.paramListField);
|
|
417
|
+
const paramList = extractParams(paramsNode, rules);
|
|
418
|
+
const paramMap = new Map<string, number>();
|
|
419
|
+
for (const p of paramList) {
|
|
420
|
+
paramMap.set(p.name, p.index);
|
|
421
|
+
if (name) {
|
|
422
|
+
parameters.push({
|
|
423
|
+
funcName: name,
|
|
424
|
+
paramName: p.name,
|
|
425
|
+
paramIndex: p.index,
|
|
426
|
+
line: (paramsNode?.startPosition?.row ?? funcNode.startPosition.row) + 1,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
scopeStack.push({ funcName: name, funcNode, params: paramMap, locals: new Map() });
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
interface DataflowDispatchCtx {
|
|
434
|
+
rules: AnyRules;
|
|
435
|
+
scopeStack: ScopeEntry[];
|
|
436
|
+
returns: DataflowReturnEntry[];
|
|
437
|
+
assignments: DataflowAssignment[];
|
|
438
|
+
argFlows: DataflowArgFlow[];
|
|
439
|
+
mutations: DataflowMutation[];
|
|
440
|
+
isCallNode: (t: string) => boolean;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Route a node to the appropriate dataflow handler based on its type.
|
|
445
|
+
* Function-definition nodes are short-circuited with an early return.
|
|
446
|
+
*/
|
|
447
|
+
function dispatchDataflowNode(ctx: DataflowDispatchCtx, node: TreeSitterNode): void {
|
|
448
|
+
const { rules } = ctx;
|
|
449
|
+
const t = node.type;
|
|
450
|
+
|
|
451
|
+
if (rules.functionNodes.has(t)) return;
|
|
452
|
+
|
|
453
|
+
if (rules.returnNode && t === rules.returnNode) {
|
|
454
|
+
handleReturn(node, rules, ctx.scopeStack, ctx.returns);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (
|
|
459
|
+
(rules.varDeclaratorNode && t === rules.varDeclaratorNode) ||
|
|
460
|
+
rules.varDeclaratorNodes?.has(t)
|
|
461
|
+
) {
|
|
462
|
+
handleVarDeclarator(node, rules, ctx.scopeStack, ctx.assignments, ctx.isCallNode);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (ctx.isCallNode(t)) {
|
|
467
|
+
handleCallExpr(node, rules, ctx.scopeStack, ctx.argFlows);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (rules.assignmentNode && t === rules.assignmentNode) {
|
|
472
|
+
handleAssignment(node, rules, ctx.scopeStack, ctx.assignments, ctx.mutations, ctx.isCallNode);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (rules.expressionStmtNode && t === rules.expressionStmtNode) {
|
|
477
|
+
handleExprStmtMutation(node, rules, ctx.scopeStack, ctx.mutations, ctx.isCallNode);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
408
481
|
export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
409
482
|
const isCallNode: (t: string) => boolean = rules.callNodes
|
|
410
483
|
? (t: string) => rules.callNodes.has(t)
|
|
@@ -417,6 +490,16 @@ export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
|
417
490
|
const mutations: DataflowMutation[] = [];
|
|
418
491
|
const scopeStack: ScopeEntry[] = [];
|
|
419
492
|
|
|
493
|
+
const dispatchCtx: DataflowDispatchCtx = {
|
|
494
|
+
rules,
|
|
495
|
+
scopeStack,
|
|
496
|
+
returns,
|
|
497
|
+
assignments,
|
|
498
|
+
argFlows,
|
|
499
|
+
mutations,
|
|
500
|
+
isCallNode,
|
|
501
|
+
};
|
|
502
|
+
|
|
420
503
|
return {
|
|
421
504
|
name: 'dataflow',
|
|
422
505
|
functionNodeTypes: rules.functionNodes,
|
|
@@ -426,22 +509,7 @@ export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
|
426
509
|
_funcName: string | null,
|
|
427
510
|
_context: VisitorContext,
|
|
428
511
|
): void {
|
|
429
|
-
|
|
430
|
-
const paramsNode = funcNode.childForFieldName(rules.paramListField);
|
|
431
|
-
const paramList = extractParams(paramsNode, rules);
|
|
432
|
-
const paramMap = new Map<string, number>();
|
|
433
|
-
for (const p of paramList) {
|
|
434
|
-
paramMap.set(p.name, p.index);
|
|
435
|
-
if (name) {
|
|
436
|
-
parameters.push({
|
|
437
|
-
funcName: name,
|
|
438
|
-
paramName: p.name,
|
|
439
|
-
paramIndex: p.index,
|
|
440
|
-
line: (paramsNode?.startPosition?.row ?? funcNode.startPosition.row) + 1,
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
scopeStack.push({ funcName: name, funcNode, params: paramMap, locals: new Map() });
|
|
512
|
+
enterFunctionScope(funcNode, rules, scopeStack, parameters);
|
|
445
513
|
},
|
|
446
514
|
|
|
447
515
|
exitFunction(
|
|
@@ -453,37 +521,8 @@ export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
|
453
521
|
},
|
|
454
522
|
|
|
455
523
|
enterNode(node: TreeSitterNode, _context: VisitorContext): EnterNodeResult | undefined {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
if (rules.functionNodes.has(t)) return;
|
|
459
|
-
|
|
460
|
-
if (rules.returnNode && t === rules.returnNode) {
|
|
461
|
-
handleReturn(node, rules, scopeStack, returns);
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
if (rules.varDeclaratorNode && t === rules.varDeclaratorNode) {
|
|
466
|
-
handleVarDeclarator(node, rules, scopeStack, assignments, isCallNode);
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
if (rules.varDeclaratorNodes?.has(t)) {
|
|
470
|
-
handleVarDeclarator(node, rules, scopeStack, assignments, isCallNode);
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (isCallNode(t)) {
|
|
475
|
-
handleCallExpr(node, rules, scopeStack, argFlows);
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (rules.assignmentNode && t === rules.assignmentNode) {
|
|
480
|
-
handleAssignment(node, rules, scopeStack, assignments, mutations, isCallNode);
|
|
481
|
-
return;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
if (rules.expressionStmtNode && t === rules.expressionStmtNode) {
|
|
485
|
-
handleExprStmtMutation(node, rules, scopeStack, mutations, isCallNode);
|
|
486
|
-
}
|
|
524
|
+
dispatchDataflowNode(dispatchCtx, node);
|
|
525
|
+
return undefined;
|
|
487
526
|
},
|
|
488
527
|
|
|
489
528
|
finish(): DataflowResultInternal {
|
|
@@ -17,7 +17,7 @@ export const command: CommandDefinition = {
|
|
|
17
17
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
18
18
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
19
19
|
['-j, --json', 'Output as JSON'],
|
|
20
|
-
['--limit <number>', 'Max results to return (quick mode)'],
|
|
20
|
+
['-n, --limit <number>', 'Max results to return (quick mode)'],
|
|
21
21
|
['--offset <number>', 'Skip N results (quick mode)'],
|
|
22
22
|
['--ndjson', 'Newline-delimited JSON output (quick mode)'],
|
|
23
23
|
],
|
|
@@ -7,6 +7,7 @@ export const command: CommandDefinition = {
|
|
|
7
7
|
name: 'build [dir]',
|
|
8
8
|
description: 'Parse repo and build graph in .codegraph/graph.db',
|
|
9
9
|
options: [
|
|
10
|
+
['-d, --db <path>', 'Path to graph.db (default: <dir>/.codegraph/graph.db)'],
|
|
10
11
|
['--no-incremental', 'Force full rebuild (ignore file hashes)'],
|
|
11
12
|
['--no-ast', 'Skip AST node extraction (calls, new, string, regex, throw, await)'],
|
|
12
13
|
['--no-complexity', 'Skip complexity metrics computation'],
|
|
@@ -23,6 +24,7 @@ export const command: CommandDefinition = {
|
|
|
23
24
|
engine: engine as EngineMode,
|
|
24
25
|
dataflow: opts.dataflow as boolean,
|
|
25
26
|
cfg: opts.cfg as boolean,
|
|
27
|
+
dbPath: opts.db ? path.resolve(opts.db as string) : undefined,
|
|
26
28
|
});
|
|
27
29
|
},
|
|
28
30
|
};
|
|
@@ -38,7 +38,7 @@ export const command: CommandDefinition = {
|
|
|
38
38
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
39
39
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
40
40
|
['-j, --json', 'Output as JSON'],
|
|
41
|
-
['--limit <number>', 'Max results to return (manifesto mode)'],
|
|
41
|
+
['-n, --limit <number>', 'Max results to return (manifesto mode)'],
|
|
42
42
|
['--offset <number>', 'Skip N results (manifesto mode)'],
|
|
43
43
|
['--ndjson', 'Newline-delimited JSON output (manifesto mode)'],
|
|
44
44
|
],
|
|
@@ -16,7 +16,7 @@ export const command: CommandDefinition = {
|
|
|
16
16
|
['-k, --kind <kind>', 'Filter to a specific symbol kind'],
|
|
17
17
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
18
18
|
['-j, --json', 'Output as JSON'],
|
|
19
|
-
['--limit <number>', 'Max results to return'],
|
|
19
|
+
['-n, --limit <number>', 'Max results to return'],
|
|
20
20
|
['--offset <number>', 'Skip N results (default: 0)'],
|
|
21
21
|
],
|
|
22
22
|
validate([_name], opts) {
|
|
@@ -8,7 +8,7 @@ export const command: CommandDefinition = {
|
|
|
8
8
|
['-d, --db <path>', 'Path to graph.db'],
|
|
9
9
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
10
10
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
11
|
-
['--limit <number>', 'Max results to return'],
|
|
11
|
+
['-n, --limit <number>', 'Max results to return'],
|
|
12
12
|
['--offset <number>', 'Skip N results (default: 0)'],
|
|
13
13
|
['--ndjson', 'Newline-delimited JSON output'],
|
|
14
14
|
['--staged', 'Analyze staged changes instead of unstaged'],
|
|
@@ -1,7 +1,37 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { openReadonlyOrFail } from '../../db/index.js';
|
|
3
|
+
import { getEmbeddingMeta } from '../../db/repository/embeddings.js';
|
|
4
|
+
import {
|
|
5
|
+
buildEmbeddings,
|
|
6
|
+
DEFAULT_MODEL,
|
|
7
|
+
EMBEDDING_STRATEGIES,
|
|
8
|
+
MODELS,
|
|
9
|
+
} from '../../domain/search/index.js';
|
|
10
|
+
import { info, warn } from '../../infrastructure/logger.js';
|
|
3
11
|
import type { CommandDefinition } from '../types.js';
|
|
4
12
|
|
|
13
|
+
function resolveStickyModel(dbPath: string | undefined): string | null {
|
|
14
|
+
try {
|
|
15
|
+
const db = openReadonlyOrFail(dbPath);
|
|
16
|
+
try {
|
|
17
|
+
const storedName = getEmbeddingMeta(db, 'model');
|
|
18
|
+
if (!storedName) return null;
|
|
19
|
+
for (const [key, cfg] of Object.entries(MODELS)) {
|
|
20
|
+
if (cfg.name === storedName) return key;
|
|
21
|
+
}
|
|
22
|
+
warn(
|
|
23
|
+
`Stored embedding model "${storedName}" is no longer recognised — falling back to default. ` +
|
|
24
|
+
'Embeddings will be rebuilt with the new model.',
|
|
25
|
+
);
|
|
26
|
+
return null;
|
|
27
|
+
} finally {
|
|
28
|
+
db.close();
|
|
29
|
+
}
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
5
35
|
export const command: CommandDefinition = {
|
|
6
36
|
name: 'embed [dir]',
|
|
7
37
|
description:
|
|
@@ -9,7 +39,7 @@ export const command: CommandDefinition = {
|
|
|
9
39
|
options: [
|
|
10
40
|
[
|
|
11
41
|
'-m, --model <name>',
|
|
12
|
-
'Embedding model
|
|
42
|
+
'Embedding model. Defaults to config, then the model used by existing embeddings, then the built-in default. Run `codegraph models` for options',
|
|
13
43
|
],
|
|
14
44
|
[
|
|
15
45
|
'-s, --strategy <name>',
|
|
@@ -25,8 +55,28 @@ export const command: CommandDefinition = {
|
|
|
25
55
|
},
|
|
26
56
|
async execute([dir], opts, ctx) {
|
|
27
57
|
const root = path.resolve(dir || '.');
|
|
58
|
+
const dbPath = opts.db as string | undefined;
|
|
28
59
|
const embeddingsConfig = ctx.config.embeddings;
|
|
29
|
-
const
|
|
30
|
-
|
|
60
|
+
const flagModel = opts.model as string | undefined;
|
|
61
|
+
const configModel = (embeddingsConfig?.model as string | null | undefined) ?? null;
|
|
62
|
+
|
|
63
|
+
let model: string;
|
|
64
|
+
if (flagModel) {
|
|
65
|
+
model = flagModel;
|
|
66
|
+
} else if (configModel) {
|
|
67
|
+
model = configModel;
|
|
68
|
+
} else {
|
|
69
|
+
const sticky = resolveStickyModel(dbPath);
|
|
70
|
+
if (sticky) {
|
|
71
|
+
info(
|
|
72
|
+
`Reusing previously-stored embedding model "${sticky}". Pass --model to switch, or set embeddings.model in your config.`,
|
|
73
|
+
);
|
|
74
|
+
model = sticky;
|
|
75
|
+
} else {
|
|
76
|
+
model = DEFAULT_MODEL;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await buildEmbeddings(root, model, dbPath, { strategy: opts.strategy });
|
|
31
81
|
},
|
|
32
82
|
};
|
|
@@ -14,7 +14,7 @@ export const command: CommandDefinition = {
|
|
|
14
14
|
['-T, --no-tests', 'Exclude test/spec files'],
|
|
15
15
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
16
16
|
['-j, --json', 'Output as JSON'],
|
|
17
|
-
['--limit <number>', 'Max results to return'],
|
|
17
|
+
['-n, --limit <number>', 'Max results to return'],
|
|
18
18
|
['--offset <number>', 'Skip N results (default: 0)'],
|
|
19
19
|
['--ndjson', 'Newline-delimited JSON output'],
|
|
20
20
|
],
|
|
@@ -12,7 +12,7 @@ export const command: CommandDefinition = {
|
|
|
12
12
|
['-T, --no-tests', 'Exclude test/spec files'],
|
|
13
13
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
14
14
|
['-j, --json', 'Output as JSON'],
|
|
15
|
-
['--limit <number>', 'Max results to return'],
|
|
15
|
+
['-n, --limit <number>', 'Max results to return'],
|
|
16
16
|
['--offset <number>', 'Skip N results (default: 0)'],
|
|
17
17
|
['--ndjson', 'Newline-delimited JSON output'],
|
|
18
18
|
['--modules', 'Show module boundaries (directories with high cohesion)'],
|
|
@@ -13,7 +13,7 @@ export function applyQueryOpts(cmd: Command): Command {
|
|
|
13
13
|
.option('-T, --no-tests', 'Exclude test/spec files from results')
|
|
14
14
|
.option('--include-tests', 'Include test/spec files (overrides excludeTests config)')
|
|
15
15
|
.option('-j, --json', 'Output as JSON')
|
|
16
|
-
.option('--limit <number>', 'Max results to return')
|
|
16
|
+
.option('-n, --limit <number>', 'Max results to return')
|
|
17
17
|
.option('--offset <number>', 'Skip N results (default: 0)')
|
|
18
18
|
.option('--ndjson', 'Newline-delimited JSON output')
|
|
19
19
|
.option('--table', 'Output as aligned table')
|
package/src/db/connection.ts
CHANGED
|
@@ -292,6 +292,14 @@ export function findDbPath(customPath?: string): string {
|
|
|
292
292
|
debug(`findDbPath: stopped at git ceiling ${ceiling}`);
|
|
293
293
|
break;
|
|
294
294
|
}
|
|
295
|
+
// Outside a git repo, cwd is the first (and only) directory we'll check.
|
|
296
|
+
// Walking past it risks attaching to a stale .codegraph/ in an unrelated
|
|
297
|
+
// parent — e.g. /private/tmp/.codegraph/ leaking into every /tmp/foo/ run,
|
|
298
|
+
// or $HOME/.codegraph/ leaking into every scratch dir under $HOME.
|
|
299
|
+
if (!ceiling) {
|
|
300
|
+
debug(`findDbPath: no git ceiling, stopping at ${dir}`);
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
295
303
|
const parent = path.dirname(dir);
|
|
296
304
|
if (parent === dir) break;
|
|
297
305
|
dir = parent;
|