@colbymchenry/codegraph 1.2.0 → 1.3.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.
Files changed (48) hide show
  1. package/README.md +94 -1
  2. package/dist/bin/codegraph.d.ts +1 -1
  3. package/dist/db/index.d.ts +17 -5
  4. package/dist/db/migrations.d.ts +1 -1
  5. package/dist/db/queries.d.ts +76 -1
  6. package/dist/directory.d.ts +9 -5
  7. package/dist/extraction/cfml-extractor.d.ts +107 -0
  8. package/dist/extraction/grammars.d.ts +9 -0
  9. package/dist/extraction/index.d.ts +46 -1
  10. package/dist/extraction/languages/arkts.d.ts +3 -0
  11. package/dist/extraction/languages/c-cpp.d.ts +42 -0
  12. package/dist/extraction/languages/cfquery.d.ts +12 -0
  13. package/dist/extraction/languages/cfscript.d.ts +3 -0
  14. package/dist/extraction/languages/cobol.d.ts +33 -0
  15. package/dist/extraction/languages/erlang.d.ts +3 -0
  16. package/dist/extraction/languages/nix.d.ts +3 -0
  17. package/dist/extraction/languages/solidity.d.ts +3 -0
  18. package/dist/extraction/languages/terraform.d.ts +3 -0
  19. package/dist/extraction/languages/vbnet.d.ts +11 -0
  20. package/dist/extraction/mybatis-extractor.d.ts +30 -10
  21. package/dist/extraction/tree-sitter-types.d.ts +3 -1
  22. package/dist/extraction/tree-sitter.d.ts +38 -0
  23. package/dist/index.d.ts +63 -1
  24. package/dist/mcp/daemon.d.ts +25 -3
  25. package/dist/mcp/early-ppid.d.ts +26 -0
  26. package/dist/mcp/query-pool.d.ts +14 -0
  27. package/dist/mcp/startup-handshake.d.ts +44 -0
  28. package/dist/mcp/tools.d.ts +22 -0
  29. package/dist/project-config.d.ts +38 -0
  30. package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -1
  31. package/dist/resolution/frameworks/cics.d.ts +20 -0
  32. package/dist/resolution/frameworks/terraform.d.ts +38 -0
  33. package/dist/resolution/goframe-synthesizer.d.ts +2 -1
  34. package/dist/resolution/import-resolver.d.ts +7 -0
  35. package/dist/resolution/index.d.ts +49 -6
  36. package/dist/resolution/name-matcher.d.ts +0 -3
  37. package/dist/resolution/strip-comments.d.ts +1 -1
  38. package/dist/resolution/types.d.ts +29 -0
  39. package/dist/resolution/workspace-packages.d.ts +10 -0
  40. package/dist/search/identifier-segments.d.ts +60 -0
  41. package/dist/sync/watcher.d.ts +10 -5
  42. package/dist/types.d.ts +19 -1
  43. package/npm-shim.js +8 -1
  44. package/package.json +7 -7
  45. package/dist/reasoning/config.d.ts +0 -45
  46. package/dist/reasoning/credentials.d.ts +0 -5
  47. package/dist/reasoning/login.d.ts +0 -21
  48. package/dist/reasoning/reasoner.d.ts +0 -43
package/README.md CHANGED
@@ -41,6 +41,29 @@ Follow [@getcodegraph](https://x.com/getcodegraph) on X for updates.
41
41
 
42
42
  </div>
43
43
 
44
+ ## Contents
45
+
46
+ - [Get Started](#get-started)
47
+ - [Language Support](#language-support)
48
+ - [Why CodeGraph?](#why-codegraph)
49
+ - [Key Features](#key-features)
50
+ - [Framework-aware Routes](#framework-aware-routes)
51
+ - [Mixed iOS / React Native / Expo bridging](#mixed-ios--react-native--expo-bridging)
52
+ - [Quick Start](#quick-start)
53
+ - [How It Works](#how-it-works)
54
+ - [CLI Reference](#cli-reference)
55
+ - [MCP Tools](#mcp-tools)
56
+ - [Library Usage](#library-usage)
57
+ - [Configuration](#configuration)
58
+ - [Telemetry](#telemetry)
59
+ - [Supported Platforms](#supported-platforms)
60
+ - [Supported Agents](#supported-agents)
61
+ - [Supported Languages](#supported-languages)
62
+ - [Measured cross-file coverage](#measured-cross-file-coverage)
63
+ - [Troubleshooting](#troubleshooting)
64
+ - [Star History](#star-history)
65
+ - [License](#license)
66
+
44
67
  ## Get Started
45
68
 
46
69
  ### 1. Install the CLI
@@ -109,6 +132,51 @@ codegraph uninstall
109
132
 
110
133
  ---
111
134
 
135
+ ## Language Support
136
+
137
+ Every language below gets the same treatment — full structural extraction and cross-file resolution into one graph, no per-language setup:
138
+
139
+ <p align="center">
140
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/typescript.svg?v=1" width="104" height="104" alt="TypeScript" />
141
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/javascript.svg?v=1" width="104" height="104" alt="JavaScript" />
142
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/arkts.svg?v=1" width="104" height="104" alt="ArkTS" />
143
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/python.svg?v=1" width="104" height="104" alt="Python" />
144
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/go.svg?v=1" width="104" height="104" alt="Go" />
145
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/rust.svg?v=1" width="104" height="104" alt="Rust" />
146
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/java.svg?v=1" width="104" height="104" alt="Java" />
147
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/csharp.svg?v=1" width="104" height="104" alt="C#" />
148
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/php.svg?v=1" width="104" height="104" alt="PHP" />
149
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/ruby.svg?v=1" width="104" height="104" alt="Ruby" />
150
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/c.svg?v=1" width="104" height="104" alt="C" />
151
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/cpp.svg?v=1" width="104" height="104" alt="C++" />
152
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/objective-c.svg?v=1" width="104" height="104" alt="Objective-C" />
153
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/metal.svg?v=1" width="104" height="104" alt="Metal" />
154
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/cuda.svg?v=1" width="104" height="104" alt="CUDA" />
155
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/swift.svg?v=1" width="104" height="104" alt="Swift" />
156
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/kotlin.svg?v=1" width="104" height="104" alt="Kotlin" />
157
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/scala.svg?v=1" width="104" height="104" alt="Scala" />
158
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/dart.svg?v=1" width="104" height="104" alt="Dart" />
159
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/svelte.svg?v=1" width="104" height="104" alt="Svelte" />
160
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/vue.svg?v=1" width="104" height="104" alt="Vue" />
161
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/astro.svg?v=1" width="104" height="104" alt="Astro" />
162
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/liquid.svg?v=1" width="104" height="104" alt="Liquid" />
163
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/delphi.svg?v=1" width="104" height="104" alt="Pascal / Delphi" />
164
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/lua.svg?v=1" width="104" height="104" alt="Lua" />
165
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/r.svg?v=1" width="104" height="104" alt="R" />
166
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/luau.svg?v=1" width="104" height="104" alt="Luau" />
167
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/cfml.svg?v=1" width="104" height="104" alt="CFML" />
168
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/cobol.svg?v=1" width="104" height="104" alt="COBOL" />
169
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/vbnet.svg?v=1" width="104" height="104" alt="Visual Basic .NET" />
170
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/erlang.svg?v=1" width="104" height="104" alt="Erlang" />
171
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/solidity.svg?v=1" width="104" height="104" alt="Solidity" />
172
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/terraform.svg?v=1" width="104" height="104" alt="Terraform / OpenTofu" />
173
+ <img src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/languages/nix.svg?v=1" width="104" height="104" alt="Nix" />
174
+ </p>
175
+
176
+ <sub>Per-language details — extensions, frameworks, and what exactly gets extracted — in [Supported Languages](#supported-languages).</sub>
177
+
178
+ ---
179
+
112
180
  ## Why CodeGraph?
113
181
 
114
182
  When an AI agent needs to understand code — to answer a question or make a change — it discovers structure the slow way: grep, glob, and Read, one file at a time, rebuilding call paths and dependencies by hand. That's a pile of tool calls and round-trips before it even starts the real work.
@@ -244,7 +312,7 @@ The reliable, universal payoff is **surgical context and speed**: CodeGraph coll
244
312
  | **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 |
245
313
  | **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes |
246
314
  | **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync — the graph stays current as you code, zero config |
247
- | **20+ Languages** | TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Objective-C, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Svelte, Vue, Astro, Liquid, Pascal/Delphi |
315
+ | **20+ Languages** | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi |
248
316
  | **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 17 frameworks |
249
317
  | **Mixed iOS / React Native / Expo** | Closes cross-language flows that static parsing misses: Swift ↔ ObjC bridging, React Native legacy bridge + TurboModules + Fabric view components, native → JS event emitters, Expo Modules |
250
318
  | **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only |
@@ -618,6 +686,21 @@ watch:
618
686
  }
619
687
  ```
620
688
 
689
+ Conversely, when real source is gitignored on purpose — a project under a second
690
+ VCS (SVN, Perforce) that `.gitignore`s its own source so it stays out of Git —
691
+ force it back in with `include` (the opposite of `exclude`; `includeIgnored`
692
+ only revives embedded git repos, not plain source):
693
+
694
+ ```json
695
+ {
696
+ "include": ["Tools/", "Local/typescript/"]
697
+ }
698
+ ```
699
+
700
+ CodeGraph discovers those files off disk, overriding `.gitignore`, on index,
701
+ sync, and watch. An explicit `exclude` still wins, and built-in skips
702
+ (`node_modules`, `dist`, `.git`) are never re-included.
703
+
621
704
  ### Custom file extensions
622
705
 
623
706
  If your project uses a non-standard extension for a [supported
@@ -692,6 +775,7 @@ is written):
692
775
  |----------|-----------|--------|
693
776
  | TypeScript | `.ts`, `.tsx` | Full support |
694
777
  | JavaScript | `.js`, `.jsx`, `.mjs` | Full support |
778
+ | ArkTS (HarmonyOS) | `.ets` | Full support (everything TypeScript has, plus `@Component`/`@ComponentV2` structs with their ArkUI decorators (`@State`/`@Prop`/`@Link`/`@Local`/`@Builder`/…), `build()` view trees — parent→child component edges, chained-attribute links to `@Extend`/`@Styles` functions, `.onClick(this.handler)` event bindings — dynamic-dispatch bridges for state→`build()` re-renders, `@ohos.events.emitter` emit→subscriber pairs (static event keys only), and `router.pushUrl` literal urls → the target page struct; ohpm workspace modules resolve bare `import { X } from "data"` through `oh-package.json5` `file:` dependencies, honoring each module's `main` entry) |
695
779
  | Python | `.py` | Full support |
696
780
  | Go | `.go` | Full support |
697
781
  | Rust | `.rs` | Full support |
@@ -702,6 +786,8 @@ is written):
702
786
  | C | `.c`, `.h` | Full support |
703
787
  | C++ | `.cpp`, `.hpp`, `.cc` | Full support |
704
788
  | Objective-C | `.m`, `.mm`, `.h` | Partial support (classes, protocols, methods, `@property`, `#import`, message sends; `.mm` ObjC++ may parse incompletely) |
789
+ | Metal | `.metal` | Full support (vertex/fragment/kernel functions, structs, type aliases, call edges — MSL parses as C++, with `[[attribute]]` annotations handled) |
790
+ | CUDA | `.cu`, `.cuh` | Full support (kernels and device/host functions, structs, classes, host→kernel call edges through `<<<grid, block>>>` launch syntax — templated launches, function-pointer launches (`auto kernel = &fn<...>`), `dim3{...}` configs, and macro-defined kernels included; `__global__`/`__device__`/`__launch_bounds__` specifiers handled; CUDA in plain `.h`/`.hpp` headers recognized by content) |
705
791
  | Swift | `.swift` | Full support |
706
792
  | Kotlin | `.kt`, `.kts` | Full support |
707
793
  | Scala | `.scala`, `.sc` | Full support (classes, traits, methods, type aliases, Scala 3 enums) |
@@ -714,6 +800,13 @@ is written):
714
800
  | Lua | `.lua` | Full support (functions, methods with receivers, local variables, `require` imports, call edges) |
715
801
  | R | `.R` `.r` | Full support (functions in every assignment form, S4/R5/R6 classes with methods, `library`/`require` imports, `source()` file references, call edges) |
716
802
  | Luau | `.luau` | Full support (everything in Lua, plus `type`/`export type` aliases, typed signatures, and Roblox instance-path `require`) |
803
+ | CFML | `.cfc`, `.cfm`, `.cfs` | Full support (tag-based `<cfcomponent>`/`<cffunction>` and bare-script `component { ... }` styles, `extends`/`implements`, embedded `<cfscript>` delegation, call edges) |
804
+ | COBOL | `.cbl`, `.cob`, `.cpy` | Full support (programs, sections/paragraphs with PERFORM/GO TO call edges, CALL 'literal' cross-program calls, COPY copybook imports — including standalone `.cpy` files — DATA DIVISION records/fields/88-levels, EXEC CICS LINK/XCTL and EXEC SQL INCLUDE targets; fixed and free format) |
805
+ | Visual Basic .NET | `.vb` | Full support (classes, Modules, interfaces, structures, enums, properties, events, `Declare` P/Invoke, `Handles`/`WithEvents`, `Inherits`/`Implements` edges, call edges through VB's call/index paren ambiguity, `As New` instantiation, interpolated strings, LINQ, Unicode identifiers) |
806
+ | Erlang | `.erl`, `.hrl`, `.escript`, `.app.src`, `.app` | Full support (functions with multi-clause/multi-arity grouping, `-spec` signatures, records with fields, `-type`/`-opaque` aliases, `-define` macros, `-include`/`-include_lib`/`-import` edges, local and `mod:fn` remote call edges, `fun name/arity` references, `spawn`/`apply`/`proc_lib`/`timer`/`rpc` MFA-argument call edges, `gen_server:call/cast(?MODULE)` → own `handle_call`/`handle_cast` links, `-behaviour` links, `-export`-based visibility) |
807
+ | Solidity | `.sol` | Full support (contracts, libraries, interfaces, structs, enums, modifiers, events, errors, state variables, `import`/`using` directives, `emit`/`revert` calls) |
808
+ | Terraform / OpenTofu | `.tf`, `.tfvars`, `.tofu` | Full support (resources, data sources, modules, variables, outputs, providers incl. aliases, `locals`; `var.`/`local.`/`module.`/resource references with Terraform's per-directory scoping enforced; module calls bridged across the boundary — inputs to the child module's variables, `module.M.out` to the child's output, `source` to the module's files; cloudposse/atmos `remote-state` cross-component wiring when the component is statically named; `provider = aws.east` selections resolved up the module tree; `moved`/`import`/`removed`/`check` block references; `.tfvars` assignments linked to the variables they set) |
809
+ | Nix | `.nix` | Full support (functions with simple/destructured/curried params, `let`/attrset bindings, `inherit`, `import ./path` file edges — `./dir` resolving through `default.nix` — plus NixOS module `imports = [ ./x.nix ]` lists and `callPackage ./pkg.nix` file edges; call edges; module-system option wiring — a config write like `launchd.user.agents.x = { ... }` links to the module declaring `options.launchd.user.agents`, so option flows trace across modules) |
717
810
 
718
811
  ## Measured cross-file coverage
719
812
 
@@ -22,5 +22,5 @@
22
22
  * codegraph affected [files] Find test files affected by changes
23
23
  * codegraph upgrade [version] Update CodeGraph to the latest release
24
24
  */
25
- export {};
25
+ import '../mcp/early-ppid';
26
26
  //# sourceMappingURL=codegraph.d.ts.map
@@ -73,8 +73,8 @@ export declare class DatabaseConnection {
73
73
  */
74
74
  optimize(): void;
75
75
  /**
76
- * Lightweight, non-blocking maintenance to run after bulk writes
77
- * (indexAll, sync). Two operations:
76
+ * Lightweight maintenance to run after bulk writes (indexAll, sync).
77
+ * Two operations:
78
78
  *
79
79
  * - `PRAGMA optimize` — incremental ANALYZE; SQLite only re-analyzes
80
80
  * tables whose row counts changed materially since the last
@@ -86,10 +86,22 @@ export declare class DatabaseConnection {
86
86
  * unboundedly between automatic checkpoints (auto-fires at 1000
87
87
  * pages by default; large indexAll runs blow past that).
88
88
  *
89
- * Both operations are silently swallowed on failure they're a
90
- * best-effort optimization, never load-bearing for correctness.
89
+ * Runs on a WORKER THREAD with its own connection: on a multi-GB index
90
+ * these pragmas are minutes of synchronous IO (a 95k-file kernel index
91
+ * left a 593MB WAL whose checkpoint alone blew the #850 watchdog's 60s
92
+ * window and got a COMPLETED index SIGKILLed at the finish line). WAL
93
+ * checkpointing from a second connection is standard SQLite; `PRAGMA
94
+ * optimize` persists its statistics in sqlite_stat tables, so the main
95
+ * connection benefits the same. The main thread just awaits a message,
96
+ * so the event loop — and the watchdog heartbeat — keep turning.
97
+ *
98
+ * Everything is silently swallowed on failure — best-effort
99
+ * optimization, never load-bearing for correctness. If worker threads
100
+ * are unavailable, falls back to a bounded in-line `PRAGMA optimize`
101
+ * and SKIPS the checkpoint (the final close() checkpoints after the
102
+ * CLI has already disarmed its watchdog).
91
103
  */
92
- runMaintenance(): void;
104
+ runMaintenance(): Promise<void>;
93
105
  /**
94
106
  * Close the database connection
95
107
  */
@@ -7,7 +7,7 @@ import { SqliteDatabase } from './sqlite-adapter';
7
7
  /**
8
8
  * Current schema version
9
9
  */
10
- export declare const CURRENT_SCHEMA_VERSION = 6;
10
+ export declare const CURRENT_SCHEMA_VERSION = 7;
11
11
  /**
12
12
  * Migration definition
13
13
  */
@@ -4,7 +4,7 @@
4
4
  * Prepared statements for CRUD operations on the knowledge graph.
5
5
  */
6
6
  import { SqliteDatabase } from './sqlite-adapter';
7
- import { Node, Edge, FileRecord, UnresolvedReference, NodeKind, EdgeKind, GraphStats, SearchOptions, SearchResult } from '../types';
7
+ import { Node, Edge, FileRecord, UnresolvedReference, NodeKind, EdgeKind, Language, GraphStats, SearchOptions, SearchResult } from '../types';
8
8
  /**
9
9
  * Query builder for the knowledge graph database
10
10
  */
@@ -14,6 +14,8 @@ export declare class QueryBuilder {
14
14
  private nodeCache;
15
15
  private readonly maxCacheSize;
16
16
  private stmts;
17
+ private segmentedNames;
18
+ private static readonly MAX_SEGMENTED_NAMES;
17
19
  constructor(db: SqliteDatabase);
18
20
  /** Set the normalized project-name tokens used to down-weight non-discriminative
19
21
  * query words in path scoring (#720). Called once when the project opens. */
@@ -24,6 +26,12 @@ export declare class QueryBuilder {
24
26
  * Insert a new node
25
27
  */
26
28
  insertNode(node: Node): void;
29
+ /** Which node kinds contribute their name to the segment vocabulary — the
30
+ * single gate shared by insertNode, updateNode, and the rebuild page query
31
+ * (getDistinctNodeNames), so the write paths can't drift apart. */
32
+ private isSegmentableKind;
33
+ /** Write `name`'s segments into name_segment_vocab (idempotent). */
34
+ private insertNameSegments;
27
35
  /**
28
36
  * Insert multiple nodes in a transaction
29
37
  */
@@ -40,6 +48,44 @@ export declare class QueryBuilder {
40
48
  * Delete all nodes for a file
41
49
  */
42
50
  deleteNodesByFile(filePath: string): void;
51
+ /** Wipe the segment vocabulary. A full index calls this at its start; the
52
+ * node write path repopulates it as files (re-)index, so the end state is
53
+ * exactly the current names with no orphan rows. */
54
+ clearNameSegmentVocab(): void;
55
+ /** True when the vocab has no rows — an index built before the table existed.
56
+ * `sync` uses this to heal such databases (see rebuildNameSegmentVocabFrom). */
57
+ isNameSegmentVocabEmpty(): boolean;
58
+ /** One page of distinct segmentable node names, for batched vocab rebuilds
59
+ * (file basenames and import specifiers are excluded from the vocab — see
60
+ * insertNode). */
61
+ getDistinctNodeNames(limit: number, offset: number): string[];
62
+ /** Insert segments for a batch of names in one transaction (vocab heal path). */
63
+ insertNameSegmentsBatch(names: string[]): void;
64
+ /**
65
+ * Names whose segments cover at least `minWords` distinct PROMPT WORDS —
66
+ * the co-occurrence probe behind the prompt hook's medium tier: the words
67
+ * "state" and "machine" both being segments of `OrderStateMachine` is strong
68
+ * evidence the prompt names that symbol in prose. Ordered by coverage.
69
+ *
70
+ * Takes (segment variant → original word) pairs and folds variants back to
71
+ * their word INSIDE the SQL: a name matching both `service` and `services`
72
+ * counts ONE word, not two. Counting raw variants let plural-variant pairs
73
+ * of a single word tie with genuine two-word matches and — because ORDER
74
+ * BY/LIMIT run here, before any JS-side re-check — crowd a real match past
75
+ * the LIMIT on vocab-heavy repos (#1146).
76
+ */
77
+ getSegmentCoOccurrence(variants: Array<{
78
+ segment: string;
79
+ word: string;
80
+ }>, minWords: number, limit: number): Array<{
81
+ name: string;
82
+ matches: number;
83
+ }>;
84
+ /** How many distinct names each segment appears in — the rarity signal that
85
+ * separates a discriminative word ("checkout") from a ubiquitous one ("state"). */
86
+ getSegmentNameCounts(segments: string[]): Map<string, number>;
87
+ /** Names containing the given segment (rare-single-word tier). */
88
+ getNamesForSegment(segment: string, limit: number): string[];
43
89
  /**
44
90
  * Get a node by ID
45
91
  */
@@ -152,10 +198,32 @@ export declare class QueryBuilder {
152
198
  * Get all nodes in the database
153
199
  */
154
200
  getAllNodes(): Node[];
201
+ /**
202
+ * Stream nodes of one language whose `decorators` JSON array contains
203
+ * `decorator`. The LIKE on the JSON text is a cheap index-free pre-filter
204
+ * (a decorator name can appear as a substring of another), so callers must
205
+ * still exact-check `node.decorators.includes(decorator)`. Exists so the
206
+ * kotlin expect/actual synthesizer never materializes the whole node table
207
+ * the way `getAllNodes().filter(...)` did — that array alone OOM'd Node's
208
+ * default heap on a 2M-node graph (#1212).
209
+ */
210
+ iterateNodesByLanguageWithDecorator(language: Language, decorator: string): IterableIterator<Node>;
211
+ /**
212
+ * Distinct languages present in the files table. One indexed aggregate —
213
+ * lets the dynamic-edge synthesizers skip passes for languages the project
214
+ * doesn't contain at all (a Kotlin pass has no work on a pure-C repo), so
215
+ * their cost is zero rather than a full-graph scan that finds nothing (#1212).
216
+ */
217
+ getDistinctFileLanguages(): Set<string>;
155
218
  /**
156
219
  * Get nodes by exact name match (uses idx_nodes_name index)
157
220
  */
158
221
  getNodesByName(name: string): Node[];
222
+ /**
223
+ * Nodes whose name starts with `prefix`, by index range scan (a LIKE would
224
+ * skip idx_nodes_name under SQLite's default case-insensitive LIKE).
225
+ */
226
+ getNodesByNamePrefix(prefix: string, limit?: number): Node[];
159
227
  /**
160
228
  * Get nodes by exact qualified name match (uses idx_nodes_qualified_name index)
161
229
  */
@@ -344,6 +412,13 @@ export declare class QueryBuilder {
344
412
  * Get all distinct node names (lightweight — just name strings for pre-filtering)
345
413
  */
346
414
  getAllNodeNames(): string[];
415
+ /**
416
+ * Stream the distinct node names one row at a time — the incremental
417
+ * counterpart to {@link getAllNodeNames} for callers that need to yield
418
+ * to the event loop mid-scan (resolver cache warm-up on multi-million-node
419
+ * indexes). Fresh statement per call: the iterator holds an open cursor.
420
+ */
421
+ iterateNodeNames(): IterableIterator<string>;
347
422
  /**
348
423
  * Get unresolved references scoped to specific file paths.
349
424
  * Uses the idx_unresolved_file_path index for efficient lookup.
@@ -86,10 +86,14 @@ export declare function findIndexedSubprojectRoots(root: string, opts?: {
86
86
  max?: number;
87
87
  }): string[];
88
88
  /**
89
- * Does `prompt` contain an explicit structural keyword (English or CJK)? A
90
- * keyword is a strong, self-contained signal, so the front-load hook fires on it
91
- * directly — no graph check needed. (A *code-token* match, by contrast, is only
92
- * a candidate the hook verifies against the graph first; see {@link extractCodeTokens}.)
89
+ * Does `prompt` contain an explicit structural keyword? A keyword is a strong,
90
+ * self-contained signal, so the front-load hook fires on it directly — no graph
91
+ * check needed. (A *code-token* match, by contrast, is only a candidate the
92
+ * hook verifies against the graph first; see {@link extractCodeTokens}.)
93
+ * Coverage is multilingual (#994, #1126): the ~29 languages with the largest
94
+ * developer populations, across Latin, Cyrillic, Greek, CJK, Hangul, Arabic,
95
+ * Hebrew, Thai, and Devanagari scripts. Languages beyond the keyword table
96
+ * still fire through the language-agnostic code-token path.
93
97
  */
94
98
  export declare function hasStructuralKeyword(prompt: string): boolean;
95
99
  /**
@@ -110,7 +114,7 @@ export declare function extractCodeTokens(prompt: string): string[];
110
114
  /**
111
115
  * Cheap, graph-free candidate gate for the front-load hook: could `prompt` be a
112
116
  * structural / flow / impact / "where-how" question worth front-loading context
113
- * for? True on an explicit keyword (English or CJK, issue #994) OR an
117
+ * for? True on an explicit keyword in any covered language (#994, #1126) OR an
114
118
  * identifier-shaped token. A keyword is sufficient to fire on its own; a
115
119
  * token-only match is only a candidate the hook then verifies against the graph
116
120
  * (a brand name like `JavaScript` is token-shaped but isn't a symbol). Every
@@ -0,0 +1,107 @@
1
+ import { ExtractionResult, Language } from '../types';
2
+ /**
3
+ * CfmlExtractor - Extracts code relationships from CFML source (.cfc/.cfm).
4
+ *
5
+ * tree-sitter-cfml splits CFML into two related grammars: `cfml` (tag-based —
6
+ * `<cfcomponent>`/`<cffunction>`/HTML) and `cfscript` (modern bare-script
7
+ * `component { ... }` syntax). The `cfml` grammar's own injections.scm treats
8
+ * bare-script content as an opaque blob meant to be re-parsed by `cfscript` —
9
+ * that re-parsing only happens at the editor/highlighting layer, not in the
10
+ * raw AST, so this extractor replicates it: a file whose first real token
11
+ * isn't `<` is delegated wholesale to the cfscript grammar (the dominant
12
+ * modern style); otherwise the file is walked tag-by-tag with the cfml
13
+ * grammar, delegating any `<cfscript>` tag bodies the same way.
14
+ */
15
+ export declare class CfmlExtractor {
16
+ private filePath;
17
+ private source;
18
+ private language;
19
+ private nodes;
20
+ private edges;
21
+ private unresolvedReferences;
22
+ private errors;
23
+ /** `language` is the file's detected language — `'cfml'` for `.cfc`/`.cfm`, `'cfscript'` for `.cfs`. Both dialect-switch internally; this only controls the language tag stamped onto emitted nodes/refs. */
24
+ constructor(filePath: string, source: string, language?: Language);
25
+ extract(): ExtractionResult;
26
+ /** Modern bare-script `.cfc`/`.cfm`: delegate the whole file to the cfscript grammar. */
27
+ private extractBareScript;
28
+ /** Legacy tag-based CFML: walk `<cfcomponent>`/`<cffunction>`, delegating `<cfscript>` bodies. */
29
+ private extractTagBased;
30
+ /** Build the file's own `kind:'file'` node, spanning the whole source. Tag-based files need this explicitly — unlike `extractBareScript` (which delegates the whole file to `TreeSitterExtractor` and inherits its file node), `extractTagBased` walks the tree itself and has no other source of one. */
31
+ private createFileNode;
32
+ /**
33
+ * Walks `program`'s named children with a single forward cursor (not an
34
+ * index loop) — `extractComponent` consumes a variable run of FOLLOWING
35
+ * siblings as the component body (see its doc comment), so this must
36
+ * resume from whatever it last consumed rather than revisiting those same
37
+ * cffunction/cfscript siblings a second time as bogus top-level symbols.
38
+ */
39
+ private walkProgram;
40
+ /**
41
+ * `<cfcomponent extends="Base" implements="IFoo,IBar">...</cfcomponent>`.
42
+ * The grammar's implicit-end-tag scanner means component body content
43
+ * (cffunction tags, cfscript tags, etc.) appears as the open tag's FOLLOWING
44
+ * siblings in `program`, not nested children — walk forward to the matching
45
+ * cf_component_close_tag.
46
+ */
47
+ private extractComponent;
48
+ /**
49
+ * `<cffunction name="..." access="..." returntype="...">...</cffunction>`.
50
+ * `parentClassId` decides `method` vs top-level `function`; `containerId` is
51
+ * the `contains`-edge target (the class when inside one, otherwise the file
52
+ * node for a bare top-level cffunction) — kept separate so a top-level
53
+ * function still gets a containment edge without being misclassified as a
54
+ * method of the file. A method's qualifiedName is scoped under
55
+ * `parentClassName` (`TagService::save`, the same `Class::member` shape the
56
+ * generic extractor produces) so type-validated method resolution can match.
57
+ */
58
+ private extractFunctionTag;
59
+ /**
60
+ * Recursively delegates any `cf_script_tag`/`cf_query_tag` found within
61
+ * `node`'s subtree — e.g. a `<cfscript>`/`<cfquery>` nested inside
62
+ * `<cfif>`/`<cfloop>`/`<cftry>` control-flow tags, which (unlike
63
+ * `<cfcomponent>`'s body — see the implicit-end-tag note on `extractComponent`)
64
+ * ARE normal children, just possibly several levels deep, so a direct-children
65
+ * check misses them. Does not descend into a nested `cf_function_tag` — that
66
+ * has its own scope and is walked separately. `parentClassName` rides along
67
+ * so a `<cfscript>` at component scope classifies its functions as methods
68
+ * scoped under the component.
69
+ */
70
+ private delegateNestedTags;
71
+ /**
72
+ * Delegate a `<cfscript>...</cfscript>` tag body to the cfscript grammar.
73
+ * With `parentClassName` set (the block sits at component scope), functions
74
+ * declared at the script's top level are the component's methods
75
+ * (`<cfcomponent><cfscript>function configure(){}` — the standard ColdBox
76
+ * ModuleConfig shape): they're re-kinded `function` → `method`, and every
77
+ * merged symbol's qualifiedName is prefixed with the component scope
78
+ * (`configure` → `ModuleConfig::configure`) so type-validated method
79
+ * resolution can match them. Functions nested inside another function
80
+ * (closures) keep kind `function`.
81
+ */
82
+ private delegateScriptTag;
83
+ /**
84
+ * Delegate a `<cfquery>...</cfquery>` tag's SQL body to the `cfquery` grammar.
85
+ * `#hash#` expressions inside the SQL (e.g. `#getCurrentUser().getId()#` in a
86
+ * WHERE clause) are real CFML calls/references — tree-sitter-cfml's `cfquery`
87
+ * grammar parses them structurally (same `call_expression`/`member_expression`
88
+ * shape as cfscript), so without this delegation they're silently dropped as
89
+ * opaque SQL text. The grammar models no other symbols, so only call/reference
90
+ * extraction is relevant here — unlike `delegateScriptTag`, there are no nodes
91
+ * or contains-edges to merge.
92
+ */
93
+ private delegateQueryTag;
94
+ /** Read a `cf_attribute`'s value by name from a tag node's direct `cf_attribute`/`cf_tag_attributes` children. */
95
+ private tagAttr;
96
+ private componentNameFromPath;
97
+ }
98
+ /**
99
+ * Sniff whether CFML source is bare-script (`component { ... }`, modern style)
100
+ * vs tag-based (`<cfcomponent>`, `<cfif>`, HTML). Skips a leading UTF-8 BOM
101
+ * (endemic in CFML's Windows-editor history — 17% of ColdBox's files carry
102
+ * one; both grammars parse fine with it once routed correctly), whitespace,
103
+ * and `//`/`/* *\/` comments to find the first real token; tag-based files
104
+ * start with `<`, script-based files don't.
105
+ */
106
+ export declare function isBareScriptCfml(source: string): boolean;
107
+ //# sourceMappingURL=cfml-extractor.d.ts.map
@@ -28,6 +28,15 @@ export declare function isSourceFile(filePath: string, overrides?: Record<string
28
28
  * extractor links them. (config/ + locales/ JSON have no section refs.)
29
29
  */
30
30
  export declare function isShopifyLiquidJson(filePath: string): boolean;
31
+ /**
32
+ * OTP application resource file: `<app>.app.src` (checked into every rebar3/
33
+ * erlang.mk app) or its compiled `<app>.app`. Erlang TERMS, not forms — the
34
+ * grammar parses them as top-level expressions, and the Erlang extractor's
35
+ * application-tuple handler turns `{mod, {Mod, _}}` and `{applications, […]}`
36
+ * into entry-module and dependency edges. Routed by full suffix because the
37
+ * last-dot extension (`.src`) is far too generic for EXTENSION_MAP.
38
+ */
39
+ export declare function isErlangAppFile(filePath: string): boolean;
31
40
  /**
32
41
  * Play Framework routes file: the extensionless `conf/routes` (and included
33
42
  * `conf/*.routes`). No grammar — route extraction is done by the Play framework
@@ -24,6 +24,14 @@ export interface IndexResult {
24
24
  filesIndexed: number;
25
25
  filesSkipped: number;
26
26
  filesErrored: number;
27
+ /**
28
+ * How many indexable files the scan discovered — the ground truth the
29
+ * indexed/skipped/errored tallies must add up to. A shortfall means files
30
+ * were silently dropped mid-pipeline (e.g. a killed worker under load) and
31
+ * the index is PARTIAL; callers surface that rather than trusting the
32
+ * counts. Only set by full-index runs (indexAll), not indexFiles/sync.
33
+ */
34
+ filesDiscovered?: number;
27
35
  nodesCreated: number;
28
36
  edgesCreated: number;
29
37
  errors: ExtractionError[];
@@ -72,6 +80,17 @@ export declare class ScopeIgnore {
72
80
  * exclude applies even to tracked files and even inside embedded repos.
73
81
  */
74
82
  private exclude;
83
+ /**
84
+ * Project `codegraph.json` `include` patterns — first-party source forced
85
+ * INTO the index despite `.gitignore`. When a path matches, it is NOT
86
+ * ignored (so the watcher watches it), overriding `.gitignore`/`rootMatcher`
87
+ * — but never `exclude` (checked first) and never a built-in default-ignored
88
+ * dir. `includeRoots` are the static prefixes so a gitignored ANCESTOR
89
+ * directory of an included subtree still isn't pruned by the directory
90
+ * walker/watcher.
91
+ */
92
+ private include;
93
+ private includeRoots;
75
94
  private embedded;
76
95
  private defaults;
77
96
  constructor(rootMatcher: Ignore, embedded: Array<{
@@ -83,7 +102,17 @@ export declare class ScopeIgnore {
83
102
  * full root-relative path. Wins over everything else — an explicit user
84
103
  * exclude applies even to tracked files and even inside embedded repos.
85
104
  */
86
- exclude?: Ignore | null);
105
+ exclude?: Ignore | null,
106
+ /**
107
+ * Project `codegraph.json` `include` patterns — first-party source forced
108
+ * INTO the index despite `.gitignore`. When a path matches, it is NOT
109
+ * ignored (so the watcher watches it), overriding `.gitignore`/`rootMatcher`
110
+ * — but never `exclude` (checked first) and never a built-in default-ignored
111
+ * dir. `includeRoots` are the static prefixes so a gitignored ANCESTOR
112
+ * directory of an included subtree still isn't pruned by the directory
113
+ * walker/watcher.
114
+ */
115
+ include?: Ignore | null, includeRoots?: string[]);
87
116
  ignores(rel: string): boolean;
88
117
  }
89
118
  /**
@@ -102,6 +131,22 @@ export declare function buildScopeIgnore(rootDir: string, embeddedRoots?: Iterab
102
131
  * there already.
103
132
  */
104
133
  export declare function discoverEmbeddedRepoRoots(rootDir: string): string[];
134
+ /**
135
+ * The INVERSE of the gitignored side of {@link discoverEmbeddedRepoRoots}:
136
+ * nested git repositories under a gitignored directory that the project has NOT
137
+ * opted into via `codegraph.json` `includeIgnored`. These are real repos the
138
+ * default `init`/`index` deliberately skips because `.gitignore` excludes them
139
+ * (#970, #976) — most visibly the "super-repo `.gitignore`s its child repos"
140
+ * layout (#1156), where `init` at the parent correctly indexes ~nothing while
141
+ * `init` inside each child works. The CLI uses this to turn that silent empty
142
+ * index into an actionable hint: it names the skipped repos and offers to opt
143
+ * them in. Paths are `rootDir`-relative and trailing-slashed (valid
144
+ * `includeIgnored` patterns as-is). Returns `[]` for a non-git root (a
145
+ * filesystem walk already descends into nested repos there), skips built-in
146
+ * default-ignored dirs (`node_modules`, …), and is bounded so it never stalls
147
+ * on a giant ignored tree.
148
+ */
149
+ export declare function findUnindexedIgnoredRepos(rootDir: string): string[];
105
150
  /**
106
151
  * Recursively scan a directory for source files.
107
152
  *
@@ -0,0 +1,3 @@
1
+ import type { LanguageExtractor } from '../tree-sitter-types';
2
+ export declare const arktsExtractor: LanguageExtractor;
3
+ //# sourceMappingURL=arkts.d.ts.map
@@ -64,5 +64,47 @@ export declare function blankCppInlineMacros(source: string): string;
64
64
  * that is a bare primitive/keyword rather than a real identifier.
65
65
  */
66
66
  export declare function recoverMangledCppName(name: string): string;
67
+ export declare function blankMetalAttributes(source: string): string;
68
+ /**
69
+ * Blank annotation-style macro invocations that decorate a declaration but carry
70
+ * NO terminating semicolon — the pervasive Unreal-Engine reflection markup
71
+ * (`UPROPERTY(...)`, `UFUNCTION(...)`, `UCLASS(...)`, `GENERATED_BODY()`,
72
+ * `UE_DEPRECATED_FORGAME(...)`, `DECLARE_DELEGATE_*(...)`, …) that sits on its
73
+ * own line right before a member/type. tree-sitter's C++ grammar doesn't know
74
+ * these are macros, so each one drops into error recovery; in a big reflected
75
+ * class (`CharacterMovementComponent.h` has ~240 of them) the errors accumulate
76
+ * until the enclosing `class_specifier` can't close and collapses into an ERROR
77
+ * node — the whole class definition, its members, and its `extends` edges vanish
78
+ * from the graph. Neither `blankCppExportMacros` (class-header export macros) nor
79
+ * `blankCppInlineMacros` (return-type inline specifiers) touches these in-body
80
+ * markup macros. Replacing each with equal-length spaces preserves every byte
81
+ * offset (so line/column stay exact) and the class then parses normally.
82
+ *
83
+ * Deliberately name-list-FREE — UE alone has hundreds of such macros and projects
84
+ * add their own — so it keys on structure, not a curated list, matched tightly to
85
+ * avoid touching legitimate C++:
86
+ * - the macro must be the FIRST non-whitespace token on its line (`^[ \t]*`),
87
+ * which is where declaration markup lives — so a macro used inside an
88
+ * expression or condition (`if (CHECK(x))`, `x = MACRO(a) + b`) is never
89
+ * matched (it isn't line-leading);
90
+ * - the name must be ALL-CAPS (`[A-Z][A-Z0-9_]{2,}`), since ordinary
91
+ * function/type names called at line start are lower/mixed case;
92
+ * - the char after the balanced `(...)` must START A DECLARATION — a letter,
93
+ * `_`, `~` (destructor), or `#` (a following directive). Declaration markup is
94
+ * always followed by the thing it decorates (`UPROPERTY(...)\n float X;`,
95
+ * `UE_DEPRECATED(...) UPROPERTY(...)`), whereas a statement call is followed by
96
+ * `;` (`FOO(x);`), an init-list item by `,`/`{`, and an expression fragment by
97
+ * an operator (`MAKE(a) + 1`) — all rejected. String/char literals inside the
98
+ * args are skipped so an embedded `)` can't mis-close the balance.
99
+ *
100
+ * C++-only (wired into cppExtractor). A blanked macro inside a block comment is
101
+ * harmless (comments don't parse), and the rare line-leading no-semicolon
102
+ * ALL-CAPS call that isn't markup only loses that one annotation, never a whole
103
+ * class.
104
+ */
105
+ export declare function blankCppAnnotationMacroCalls(source: string): string;
106
+ export declare function blankCppApiPrefixMacros(source: string): string;
107
+ export declare function blankCppInlineAnnotationMacros(source: string): string;
108
+ export declare function blankCudaConstructs(source: string): string;
67
109
  export declare const cppExtractor: LanguageExtractor;
68
110
  //# sourceMappingURL=c-cpp.d.ts.map
@@ -0,0 +1,12 @@
1
+ import type { LanguageExtractor } from '../tree-sitter-types';
2
+ /**
3
+ * `<cfquery>` SQL bodies: `#hash#` expressions inside the SQL text are real
4
+ * CFML expressions (tree-sitter-cfml's `cfquery` grammar parses them
5
+ * structurally — `call_expression`/`member_expression`, same shape as
6
+ * cfscript's), so a call like `#getCurrentUser().getId()#` embedded in a
7
+ * WHERE clause is a genuine call edge. The surrounding SQL keywords/
8
+ * identifiers aren't symbols CodeGraph models — only `call_expression` is
9
+ * mapped, so extraction yields call references and nothing else.
10
+ */
11
+ export declare const cfqueryExtractor: LanguageExtractor;
12
+ //# sourceMappingURL=cfquery.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { LanguageExtractor } from '../tree-sitter-types';
2
+ export declare const cfscriptExtractor: LanguageExtractor;
3
+ //# sourceMappingURL=cfscript.d.ts.map