@colbymchenry/codegraph 0.9.9 โ†’ 1.0.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.
Files changed (47) hide show
  1. package/README.md +100 -17
  2. package/dist/bin/codegraph.d.ts +1 -0
  3. package/dist/db/migrations.d.ts +1 -1
  4. package/dist/db/queries.d.ts +43 -0
  5. package/dist/db/sqlite-adapter.d.ts +7 -0
  6. package/dist/directory.d.ts +34 -2
  7. package/dist/extraction/astro-extractor.d.ts +79 -0
  8. package/dist/extraction/extraction-version.d.ts +25 -0
  9. package/dist/extraction/function-ref.d.ts +118 -0
  10. package/dist/extraction/grammars.d.ts +7 -1
  11. package/dist/extraction/index.d.ts +34 -0
  12. package/dist/extraction/languages/c-cpp.d.ts +8 -0
  13. package/dist/extraction/languages/csharp.d.ts +22 -0
  14. package/dist/extraction/languages/r.d.ts +3 -0
  15. package/dist/extraction/languages/typescript.d.ts +13 -0
  16. package/dist/extraction/liquid-extractor.d.ts +7 -0
  17. package/dist/extraction/razor-extractor.d.ts +42 -0
  18. package/dist/extraction/tree-sitter-types.d.ts +33 -0
  19. package/dist/extraction/tree-sitter.d.ts +211 -0
  20. package/dist/extraction/vue-extractor.d.ts +15 -0
  21. package/dist/index.d.ts +34 -2
  22. package/dist/installer/instructions-template.d.ts +34 -11
  23. package/dist/installer/targets/opencode.d.ts +9 -1
  24. package/dist/installer/targets/shared.d.ts +14 -0
  25. package/dist/mcp/daemon.d.ts +60 -1
  26. package/dist/mcp/dynamic-boundaries.d.ts +41 -0
  27. package/dist/mcp/ppid-watchdog.d.ts +44 -0
  28. package/dist/mcp/proxy.d.ts +6 -0
  29. package/dist/mcp/server-instructions.d.ts +12 -1
  30. package/dist/mcp/session.d.ts +2 -0
  31. package/dist/mcp/stdin-teardown.d.ts +27 -0
  32. package/dist/mcp/tools.d.ts +71 -0
  33. package/dist/resolution/callback-synthesizer.d.ts +3 -3
  34. package/dist/resolution/frameworks/astro.d.ts +9 -0
  35. package/dist/resolution/frameworks/index.d.ts +1 -0
  36. package/dist/resolution/import-resolver.d.ts +10 -0
  37. package/dist/resolution/index.d.ts +80 -0
  38. package/dist/resolution/name-matcher.d.ts +61 -0
  39. package/dist/resolution/types.d.ts +27 -3
  40. package/dist/resolution/workspace-packages.d.ts +48 -0
  41. package/dist/search/query-utils.d.ts +17 -1
  42. package/dist/sync/watcher.d.ts +124 -32
  43. package/dist/telemetry/index.d.ts +146 -0
  44. package/dist/types.d.ts +17 -2
  45. package/dist/upgrade/index.d.ts +132 -0
  46. package/dist/utils.d.ts +30 -24
  47. package/package.json +7 -7
package/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  # CodeGraph
4
4
 
5
+ ## ๐ŸŽ‰ 1.0 Released!
6
+
7
+ Follow [@getcodegraph](https://x.com/getcodegraph) on X for updates.
8
+
5
9
  ### Supercharge Claude Code, Cursor, Codex, OpenCode, Hermes Agent, Gemini, Antigravity, and Kiro with Semantic Code Intelligence
6
10
 
7
11
  **~16% cheaper ยท ~58% fewer tool calls ยท 100% local**
@@ -25,10 +29,20 @@
25
29
  [![Antigravity](https://img.shields.io/badge/Antigravity-supported-blueviolet.svg)](#supported-agents)
26
30
  [![Kiro](https://img.shields.io/badge/Kiro-supported-blueviolet.svg)](#supported-agents)
27
31
 
32
+ <br>
33
+
34
+ **The CodeGraph platform is coming** โ€” for every PR, know exactly what to test, what could break, which flows are affected, and whether business logic is compromised.
35
+
36
+ <a href="https://getcodegraph.com"><img alt="Join the waitlist for early beta access" src="https://raw.githubusercontent.com/colbymchenry/codegraph/main/assets/waitlist.svg?v=2" height="52"></a>
37
+
38
+ <sub>Get <b>early beta access</b> to the hosted product ยท <a href="https://getcodegraph.com">getcodegraph.com</a></sub>
39
+
28
40
  </div>
29
41
 
30
42
  ## Get Started
31
43
 
44
+ ### 1. Install the CLI
45
+
32
46
  **No Node.js required** โ€” one command grabs the right build for your OS:
33
47
 
34
48
  ```bash
@@ -42,13 +56,24 @@ irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 |
42
56
  Already have Node? Use npm instead (works on any version):
43
57
 
44
58
  ```bash
45
- npx @colbymchenry/codegraph # zero-install, or:
46
59
  npm i -g @colbymchenry/codegraph
47
60
  ```
48
61
 
49
- <sub>CodeGraph bundles its own runtime โ€” nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures your agent(s) โ€” Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, Kiro.</sub>
62
+ <sub>CodeGraph bundles its own runtime โ€” nothing to compile, no native build, works the same everywhere. The installer puts `codegraph` on your PATH but **doesn't change your current shell** โ€” open a new terminal before the next step so the command resolves.</sub>
63
+
64
+ <sub>**Upgrade any time** with `codegraph upgrade` โ€” it detects how you installed (bundle, npm, or npx) and updates in place. Add `--check` to see if an update is available, or `codegraph upgrade <version>` to pin one.</sub>
65
+
66
+ ### 2. Wire up your agent(s)
67
+
68
+ In a **new terminal**, run the installer to connect CodeGraph to the agents you use:
69
+
70
+ ```bash
71
+ codegraph install
72
+ ```
73
+
74
+ <sub>Detects and auto-configures Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, and Kiro โ€” wiring the CodeGraph MCP server into each. **This is the step that connects CodeGraph to your agent;** installing the CLI in step 1 does not do it on its own. (Shortcut: `npx @colbymchenry/codegraph` downloads and runs this in one go.)</sub>
50
75
 
51
- ### Initialize Projects
76
+ ### 3. Initialize each project
52
77
 
53
78
  ```bash
54
79
  cd your-project
@@ -204,8 +229,8 @@ CodeGraph cuts **tokens, tool calls, and wall-clock time on every repo** โ€” acr
204
229
  | **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 |
205
230
  | **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes |
206
231
  | **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync โ€” the graph stays current as you code, zero config |
207
- | **20+ Languages** | TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Objective-C, Swift, Kotlin, Dart, Lua, Luau, Svelte, Liquid, Pascal/Delphi |
208
- | **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 14 frameworks |
232
+ | **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 |
233
+ | **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 17 frameworks |
209
234
  | **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 |
210
235
  | **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only |
211
236
 
@@ -253,11 +278,14 @@ CodeGraph detects web-framework routing files and emits `route` nodes linked by
253
278
  | **Drupal** | `*.routing.yml` routes (`_controller`, `_form`, entity handlers); `hook_*` implementations in `.module`/`.theme`/`.install`/`.inc` |
254
279
  | **Rails** | `get '/x', to: 'users#index'`, hash-rocket `=>` syntax |
255
280
  | **Spring** | `@GetMapping`, `@PostMapping`, `@RequestMapping` on methods |
281
+ | **Play** | `GET`/`POST`/โ€ฆ verb routes in `conf/routes` โ†’ `Controller.method` actions (Scala + Java) |
256
282
  | **Gin / chi / gorilla / mux** | `r.GET(...)`, `router.HandleFunc(...)` |
257
283
  | **Axum / actix / Rocket** | `.route("/x", get(handler))` |
258
284
  | **ASP.NET** | `[HttpGet("/x")]` attributes on action methods |
259
285
  | **Vapor** | `app.get("x", use: handler)` |
260
286
  | **React Router** / **SvelteKit** | Route component nodes |
287
+ | **Vue Router** / **Nuxt** | `pages/` file-based routes, `server/api/` endpoints, route middleware |
288
+ | **Astro** | `src/pages/` file-based routes (`.astro` pages + `.ts` endpoints, `[param]`/`[...rest]` syntax) |
261
289
 
262
290
  ---
263
291
 
@@ -302,7 +330,7 @@ The installer will:
302
330
  - Ask which agent(s) to configure โ€” auto-detects installed ones from: **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**, **Gemini CLI**, **Antigravity IDE**, **Kiro**
303
331
  - Prompt to install `codegraph` on your PATH (so agents can launch the MCP server)
304
332
  - Ask whether configs apply to all your projects or just this one
305
- - Write each chosen agent's MCP server config (the codegraph usage guide is delivered by the MCP server itself, so no instructions file is added to `CLAUDE.md` / `AGENTS.md` / etc.)
333
+ - Write each chosen agent's MCP server config, plus a small marker-fenced CodeGraph section in the agent's instructions file (`CLAUDE.md` / `AGENTS.md` / `GEMINI.md`) โ€” that's how subagents and non-MCP agents learn the `codegraph explore` / `codegraph node` commands, since the MCP server's own guidance only reaches the main agent. Removed cleanly by `codegraph uninstall`.
306
334
  - Set up auto-allow permissions when Claude Code is one of the targets
307
335
  - Initialize your current project (local installs only)
308
336
 
@@ -382,14 +410,14 @@ npm install -g @colbymchenry/codegraph
382
410
  <details>
383
411
  <summary><strong>Agent Tool Guidance</strong></summary>
384
412
 
385
- CodeGraph's MCP server delivers its usage guidance to your agent **automatically**, in the MCP `initialize` response โ€” there's no instructions file to manage and nothing is added to your `CLAUDE.md` / `AGENTS.md` / `GEMINI.md`. In short, it tells the agent to:
413
+ CodeGraph's MCP server delivers its usage guidance to your agent **automatically**, in the MCP `initialize` response. In short, it tells the agent to:
386
414
 
387
415
  - **Answer structural questions directly with CodeGraph** โ€” it *is* the pre-built index, so a grep/read loop just repeats work it already did. Treat the returned source as already read.
388
- - **Pick the tool by intent:** `codegraph_explore` for almost anything โ€” "how does X work", a flow/"how does X reach Y", or surveying an area (one call returns the relevant symbols' source grouped by file); `codegraph_search` to just locate a symbol; `codegraph_callers`/`codegraph_callees` to walk call flow; `codegraph_impact` before editing; `codegraph_node` for one specific symbol's full source (it returns every overload for an ambiguous name).
416
+ - **Pick the tool by intent:** `codegraph_explore` for almost anything โ€” "how does X work", a flow/"how does X reach Y", or surveying an area (one call returns the relevant symbols' source grouped by file); `codegraph_search` to just locate a symbol; `codegraph_callers` for every call site (including callback registrations); `codegraph_node` for one symbol's full source + callers, or to read a file like the Read tool.
389
417
  - **Trust the results โ€” don't re-verify with grep**, and check the staleness banner after edits.
390
- - If `.codegraph/` doesn't exist yet, offer to run `codegraph init -i`.
418
+ - In a workspace with no index, CodeGraph announces itself inactive and serves no tools โ€” indexing stays your decision.
391
419
 
392
- The exact text is `src/mcp/server-instructions.ts` โ€” the single source of truth.
420
+ The exact text is `src/mcp/server-instructions.ts` โ€” the single source of truth for the main agent. Because subagents and non-MCP harnesses never see the MCP guidance, the installer also writes a four-line marker-fenced section into the agent's instructions file pointing at the `codegraph explore` / `codegraph node` CLI equivalents.
393
421
 
394
422
  </details>
395
423
 
@@ -440,12 +468,15 @@ codegraph index [path] # Full index (--force to re-index, --quiet for
440
468
  codegraph sync [path] # Incremental update
441
469
  codegraph status [path] # Show statistics
442
470
  codegraph query <search> # Search symbols (--kind, --limit, --json)
471
+ codegraph explore <query> # Relevant symbols' source + call paths in one shot (same output as the codegraph_explore MCP tool)
472
+ codegraph node <symbol|file> # One symbol's source + callers, or read a file with line numbers (same output as codegraph_node)
443
473
  codegraph files [path] # Show file structure (--format, --filter, --max-depth, --json)
444
474
  codegraph callers <symbol> # Find what calls a function/method (--limit, --json)
445
475
  codegraph callees <symbol> # Find what a function/method calls (--limit, --json)
446
476
  codegraph impact <symbol> # Analyze what code is affected by changing a symbol (--depth, --json)
447
477
  codegraph affected [files...] # Find test files affected by changes (see below)
448
478
  codegraph serve --mcp # Start MCP server
479
+ codegraph upgrade [version] # Update to the latest release (--check, --force)
449
480
  ```
450
481
 
451
482
  ### `codegraph affected`
@@ -480,18 +511,18 @@ fi
480
511
 
481
512
  ## MCP Tools
482
513
 
483
- When running as an MCP server, CodeGraph exposes these tools to Claude Code:
514
+ When running as an MCP server, CodeGraph exposes a focused set of four tools โ€” measured agent behavior showed a leaner list steers agents to the right tool and saves context every session:
484
515
 
485
516
  | Tool | Purpose |
486
517
  |------|---------|
487
518
  | `codegraph_explore` | **Primary.** Answer almost any question in one call โ€” "how does X work", a flow ("how does X reach Y"), or surveying an area โ€” returning the relevant symbols' verbatim source grouped by file, plus a relationship map and blast radius. Surfaces dynamic-dispatch hops (callbacks, React re-render, interfaceโ†’impl) grep can't follow. |
519
+ | `codegraph_node` | One symbol's full source + caller/callee trail (every overload for an ambiguous name) โ€” or pass a file path to **read a whole file like the Read tool** (same line-numbered output, `offset`/`limit`), with its dependents attached. |
488
520
  | `codegraph_search` | Find symbols by name across the codebase |
489
- | `codegraph_callers` | Find what calls a function |
490
- | `codegraph_callees` | Find what a function calls |
491
- | `codegraph_impact` | Analyze what code is affected by changing a symbol |
492
- | `codegraph_node` | Get one specific symbol's details + full source (returns every overload for an ambiguous name) |
493
- | `codegraph_files` | Get indexed file structure (faster than filesystem scanning) |
494
- | `codegraph_status` | Check index health and statistics |
521
+ | `codegraph_callers` | Every call site of a function โ€” including where it's registered as a callback โ€” with one section per definition when several share a name |
522
+
523
+ Four more tools (`codegraph_callees`, `codegraph_impact`, `codegraph_files`, `codegraph_status`) stay fully functional but unlisted by default โ€” measured across eval runs, agents never or rarely picked them, and their information already arrives inline on the four above (explore's blast-radius section, node's dependents note, a symbol's body as its callee list). Re-enable any of them with the `CODEGRAPH_MCP_TOOLS` environment variable (e.g. `CODEGRAPH_MCP_TOOLS=explore,node,search,callers,impact`), or use their CLI equivalents (`codegraph callees` / `impact` / `files` / `status`).
524
+
525
+ In a workspace with no `.codegraph/` index, the server announces itself inactive and lists **no** tools โ€” agents work normally with their built-in tools, and indexing stays your decision.
495
526
 
496
527
  ---
497
528
 
@@ -562,6 +593,23 @@ add a negation โ€” `!vendor/`. The defaults apply uniformly, so committing a
562
593
  dependency or build directory doesn't force it into the graph; the `.gitignore`
563
594
  negation is the explicit opt-in.
564
595
 
596
+ ## Telemetry
597
+
598
+ CodeGraph collects **anonymous usage statistics** โ€” which tools and commands get
599
+ used, which languages get indexed โ€” to guide where language and agent support
600
+ work goes. **Never** any code, paths, file or symbol names, queries, or IP
601
+ addresses; usage is aggregated locally into daily totals before anything is
602
+ sent, and the ingest endpoint is [public code in this repo](telemetry-worker/)
603
+ that enforces the documented field list. The installer asks up front; turn it
604
+ off any time:
605
+
606
+ ```bash
607
+ codegraph telemetry off # or: CODEGRAPH_TELEMETRY=0, or DO_NOT_TRACK=1
608
+ ```
609
+
610
+ [`TELEMETRY.md`](TELEMETRY.md) lists every field, with the off-switches and the
611
+ full data-handling story.
612
+
565
613
  ## Supported Platforms
566
614
 
567
615
  Every release ships a self-contained build (bundled Node runtime โ€” nothing to
@@ -612,11 +660,44 @@ is written):
612
660
  | Dart | `.dart` | Full support |
613
661
  | Svelte | `.svelte` | Full support (script extraction, Svelte 5 runes, SvelteKit routes) |
614
662
  | Vue | `.vue` | Full support (script + script-setup extraction, Nuxt page/API/middleware routes) |
663
+ | Astro | `.astro` | Full support (frontmatter + script extraction, template component/call references, `src/pages/` routes) |
615
664
  | Liquid | `.liquid` | Full support |
616
665
  | Pascal / Delphi | `.pas`, `.dpr`, `.dpk`, `.lpr` | Full support (classes, records, interfaces, enums, DFM/FMX form files) |
617
666
  | Lua | `.lua` | Full support (functions, methods with receivers, local variables, `require` imports, call edges) |
667
+ | R | `.R` `.r` | Full support (functions in every assignment form, S4/R5/R6 classes with methods, `library`/`require` imports, `source()` file references, call edges) |
618
668
  | Luau | `.luau` | Full support (everything in Lua, plus `type`/`export type` aliases, typed signatures, and Roblox instance-path `require`) |
619
669
 
670
+ ## Measured cross-file coverage
671
+
672
+ Impact and blast-radius queries are only as good as the dependency graph behind them, so coverage is measured rather than asserted. **Fair coverage** = the share of symbol-bearing source files that have at least one *resolved cross-file dependent* โ€” something that imports, calls, references, or (through a framework convention) routes to them โ€” on a real-world benchmark repo per language. The residual is always a genuine static-analysis frontier (runtime dynamic dispatch, reflection / DI containers, framework-convention entry points, vendored third-party code), never hidden by gaming the denominator.
673
+
674
+ | Language | Benchmark repo | Coverage |
675
+ |---|---|---|
676
+ | TypeScript / JavaScript | this repo | 95.8% |
677
+ | Python | psf/requests | 100% |
678
+ | Go | gin-gonic/gin | 96.6% |
679
+ | Rust | BurntSushi/ripgrep | 86.7% |
680
+ | Java | google/gson | 93.3% |
681
+ | C# | jbogard/MediatR | 85.2% |
682
+ | PHP | guzzle/guzzle | 100% |
683
+ | Ruby | sidekiq/sidekiq | 100% |
684
+ | C | redis/redis | 92.2% |
685
+ | C++ | google/leveldb | 94.8% |
686
+ | Objective-C | SDWebImage | 91.6% |
687
+ | Swift | Alamofire | 95.3% |
688
+ | Kotlin | square/okhttp | 96.2% |
689
+ | Scala | gatling/gatling | 91.2% |
690
+ | Dart | flutter/packages | 92.4% |
691
+ | Svelte / SvelteKit | sveltejs/realworld | 100% |
692
+ | Vue / Nuxt | nuxt/movies | 93.5% |
693
+ | Astro | xingwangzhe/stalux | 93.0% |
694
+ | Lua | nvim-telescope/telescope.nvim | 84.2% |
695
+ | Luau | dphfox/Fusion | 92.2% |
696
+ | Liquid | Shopify/dawn | 73.8% |
697
+ | Pascal / Delphi | PascalCoin | 77.4% |
698
+
699
+ Framework routing is validated the same way, on a canonical app per framework: Express 100%, FastAPI 98%, Flask 100%, NestJS 96.8%, Gin 96.5%, Axum 100%, Rocket 93.8%, Vapor 100%, Laravel 92%, Rails 89.6%, React Router 100% โ€” and the convention/reflection-heavy ones at their honest static-analysis ceiling: ASP.NET 83.9%, Spring 83.3%, Drupal 78.9%, Play 76.3%, Django 74.1%. SvelteKit, Vue/Nuxt, and Astro use file-based routing, so their page/endpoint coverage is the Svelte/SvelteKit (100%), Vue/Nuxt (93.5%), and Astro (93.0% โ€” every `src/pages/` file maps to a route node on the two validation repos) figures in the table above.
700
+
620
701
  ## Troubleshooting
621
702
 
622
703
  **"CodeGraph not initialized"** โ€” Run `codegraph init` in your project directory first.
@@ -632,6 +713,8 @@ is written):
632
713
 
633
714
  **Missing symbols** โ€” The MCP server auto-syncs on save (wait a couple seconds). Run `codegraph sync` manually if needed. Check that the file's language is supported and isn't inside a `.gitignore`d or default-excluded directory (e.g. `node_modules`, `dist`).
634
715
 
716
+ **Sharing one checkout between Windows and WSL** โ€” Don't point both at the same `.codegraph/`: the background-server lock and the SQLite index are tied to the OS that wrote them, and SQLite locking across the WSL2/Windows filesystem boundary is unreliable. Give each side its own index in the same tree by setting `CODEGRAPH_DIR` to a distinct name on one of them โ€” e.g. `CODEGRAPH_DIR=.codegraph-win` on Windows, leaving WSL on the default `.codegraph`. CodeGraph skips any sibling `.codegraph-*` directory when indexing and watching, so the two never trip over each other.
717
+
635
718
  ## Star History
636
719
 
637
720
  <a href="https://www.star-history.com/?repos=colbymchenry%2Fcodegraph&type=date&legend=top-left">
@@ -20,6 +20,7 @@
20
20
  * codegraph callees <symbol> Find what a function/method calls
21
21
  * codegraph impact <symbol> Analyze what code is affected by changing a symbol
22
22
  * codegraph affected [files] Find test files affected by changes
23
+ * codegraph upgrade [version] Update CodeGraph to the latest release
23
24
  */
24
25
  export {};
25
26
  //# sourceMappingURL=codegraph.d.ts.map
@@ -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 = 4;
10
+ export declare const CURRENT_SCHEMA_VERSION = 5;
11
11
  /**
12
12
  * Migration definition
13
13
  */
@@ -10,10 +10,16 @@ import { Node, Edge, FileRecord, UnresolvedReference, NodeKind, EdgeKind, GraphS
10
10
  */
11
11
  export declare class QueryBuilder {
12
12
  private db;
13
+ private projectNameTokens;
13
14
  private nodeCache;
14
15
  private readonly maxCacheSize;
15
16
  private stmts;
16
17
  constructor(db: SqliteDatabase);
18
+ /** Set the normalized project-name tokens used to down-weight non-discriminative
19
+ * query words in path scoring (#720). Called once when the project opens. */
20
+ setProjectNameTokens(tokens: Set<string>): void;
21
+ /** The normalized project-name tokens (#720); empty if none were derived. */
22
+ getProjectNameTokens(): Set<string>;
17
23
  /**
18
24
  * Insert a new node
19
25
  */
@@ -134,6 +140,14 @@ export declare class QueryBuilder {
134
140
  * Get all nodes of a specific kind
135
141
  */
136
142
  getNodesByKind(kind: NodeKind): Node[];
143
+ /**
144
+ * Stream every node of a kind one at a time (lazy) instead of materializing
145
+ * them all like {@link getNodesByKind}. For unbounded kinds (`function`,
146
+ * `method`) on a symbol-dense project the full array is gigabytes; the
147
+ * dynamic-edge synthesizers only scan-and-filter, so they iterate to keep
148
+ * memory O(1) in the node count rather than O(nodes) (#610).
149
+ */
150
+ iterateNodesByKind(kind: NodeKind): IterableIterator<Node>;
137
151
  /**
138
152
  * Get all nodes in the database
139
153
  */
@@ -230,6 +244,30 @@ export declare class QueryBuilder {
230
244
  * Useful for recovering inter-node connectivity after BFS.
231
245
  */
232
246
  findEdgesBetweenNodes(nodeIds: string[], kinds?: EdgeKind[]): Edge[];
247
+ /**
248
+ * Distinct file paths that DEPEND ON `filePath`: every file containing a
249
+ * symbol with a cross-file edge (any kind except `contains`) into a symbol
250
+ * of this file. This is the file-level projection of the symbol dependency
251
+ * graph and the basis for blast-radius / `affected` test selection.
252
+ *
253
+ * It deliberately does NOT restrict to `imports` edges. In this graph an
254
+ * `imports` edge connects a file to its own local import declarations
255
+ * (it is always same-file), so an imports-only lookup returns zero
256
+ * cross-file dependents for every file. The real cross-file dependency
257
+ * signal is the resolved call/reference graph โ€” calls, references,
258
+ * instantiates, extends, implements, overrides, type_of, returns,
259
+ * decorates โ€” exactly what {@link GraphTraverser.getImpactRadius} traverses.
260
+ * `contains` is excluded: a parent containing a symbol does not *depend* on
261
+ * it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
262
+ */
263
+ getDependentFilePaths(filePath: string): string[];
264
+ /**
265
+ * Distinct file paths that `filePath` DEPENDS ON โ€” the inverse of
266
+ * {@link getDependentFilePaths}: every file containing a symbol that a
267
+ * symbol of this file has a cross-file edge into. Same edge-kind rules
268
+ * (all kinds except `contains`); same reason imports-only is insufficient.
269
+ */
270
+ getDependencyFilePaths(filePath: string): string[];
233
271
  /**
234
272
  * Insert or update a file record
235
273
  */
@@ -246,6 +284,11 @@ export declare class QueryBuilder {
246
284
  * Get all tracked files
247
285
  */
248
286
  getAllFiles(): FileRecord[];
287
+ /**
288
+ * Most recent index timestamp (ms since epoch) across all tracked files, or
289
+ * null when nothing is indexed yet. One indexed aggregate, no per-row scan. (#329)
290
+ */
291
+ getLastIndexedAt(): number | null;
249
292
  /**
250
293
  * Get files that need re-indexing (hash changed)
251
294
  */
@@ -16,6 +16,13 @@ export interface SqliteStatement {
16
16
  };
17
17
  get(...params: any[]): any;
18
18
  all(...params: any[]): any[];
19
+ /**
20
+ * Lazily yield result rows one at a time instead of materializing the whole
21
+ * set with `all()`. Use for unbounded scans (e.g. every function/method node)
22
+ * so memory stays O(1) in the row count rather than O(rows) โ€” see #610, where
23
+ * `all()`-ing every symbol on a dense project spiked the heap into an OOM.
24
+ */
25
+ iterate(...params: any[]): IterableIterator<any>;
19
26
  }
20
27
  export interface SqliteDatabase {
21
28
  prepare(sql: string): SqliteStatement;
@@ -4,9 +4,41 @@
4
4
  * Manages the .codegraph/ directory structure for CodeGraph data.
5
5
  */
6
6
  /**
7
- * CodeGraph directory name
7
+ * Resolve the per-project data directory name, honoring the `CODEGRAPH_DIR`
8
+ * environment override (default `.codegraph`). The override is a single path
9
+ * segment that lives in the project root.
10
+ *
11
+ * Why this exists: two environments that share one working tree must NOT share
12
+ * one `.codegraph/` โ€” most concretely Windows-native and WSL (issue #636). The
13
+ * daemon lockfile (`.codegraph/daemon.pid`) records a platform-specific pid and
14
+ * socket path (a Windows named pipe vs a WSL Unix socket), and SQLite file
15
+ * locking across the WSL2 โ†” Windows filesystem boundary is unreliable, so two
16
+ * daemons sharing one index risks corruption. Setting `CODEGRAPH_DIR=.codegraph-win`
17
+ * on one side gives each environment its own index in the same tree.
18
+ *
19
+ * Read live (not captured at load) so it is both process-accurate and testable.
20
+ * An override that isn't a plain directory name โ€” empty, containing a path
21
+ * separator, `.`, `..`/traversal, or absolute โ€” is ignored (we keep the
22
+ * default) rather than risk writing the index outside the project or into the
23
+ * project root itself; we warn once to stderr so the misconfiguration is seen.
24
+ */
25
+ export declare function codeGraphDirName(): string;
26
+ /**
27
+ * CodeGraph directory name โ€” a load-time snapshot of {@link codeGraphDirName}.
28
+ * A running process's environment is fixed, so this equals the live value;
29
+ * it's kept as a stable string export for backward compatibility. Internal code
30
+ * resolves the name through {@link codeGraphDirName} / {@link getCodeGraphDir}
31
+ * so the `CODEGRAPH_DIR` override always applies.
32
+ */
33
+ export declare const CODEGRAPH_DIR: string;
34
+ /**
35
+ * Is `name` (a single path segment) a CodeGraph data directory? Matches the
36
+ * default `.codegraph`, the active `CODEGRAPH_DIR` override, and any
37
+ * `.codegraph-*` sibling. File-watching and the indexer skip ALL of these, so
38
+ * when two environments share one working tree (Windows + WSL, issue #636)
39
+ * neither indexes or watches the other's index directory.
8
40
  */
9
- export declare const CODEGRAPH_DIR = ".codegraph";
41
+ export declare function isCodeGraphDataDir(name: string): boolean;
10
42
  /**
11
43
  * Get the .codegraph directory path for a project
12
44
  */
@@ -0,0 +1,79 @@
1
+ import { ExtractionResult } from '../types';
2
+ /**
3
+ * AstroExtractor - Extracts code relationships from Astro component files
4
+ *
5
+ * Astro files are multi-language: a TypeScript frontmatter block fenced by
6
+ * `---` lines, a JSX-like HTML template, and optional <script>/<style> blocks.
7
+ * Rather than parsing a full Astro grammar, we extract the frontmatter and
8
+ * <script> contents and delegate them to the TypeScript TreeSitterExtractor
9
+ * (Astro processes both as TypeScript by default โ€” no `lang` attr needed).
10
+ *
11
+ * Also extracts function calls from template expressions (`{fn(...)}`) and
12
+ * component usages (`<PascalCase>`) so cross-file edges are captured even
13
+ * when the only reference lives in markup.
14
+ *
15
+ * Every .astro file produces a component node (Astro components are always
16
+ * importable).
17
+ */
18
+ export declare class AstroExtractor {
19
+ private filePath;
20
+ private source;
21
+ private nodes;
22
+ private edges;
23
+ private unresolvedReferences;
24
+ private errors;
25
+ constructor(filePath: string, source: string);
26
+ /**
27
+ * Extract from Astro source
28
+ */
29
+ extract(): ExtractionResult;
30
+ /**
31
+ * Create a component node for the .astro file
32
+ */
33
+ private createComponentNode;
34
+ /**
35
+ * Extract the frontmatter block: the content between the opening `---`
36
+ * fence (first non-blank line of the file) and the closing `---` fence.
37
+ * An unclosed fence is treated as "no frontmatter" rather than swallowing
38
+ * the whole template as TypeScript.
39
+ *
40
+ * Returns the content plus its 0-indexed start line, or null.
41
+ */
42
+ private extractFrontmatter;
43
+ /**
44
+ * Extract <script> blocks from the template portion
45
+ */
46
+ private extractScriptBlocks;
47
+ /**
48
+ * Process frontmatter / script content by delegating to TreeSitterExtractor.
49
+ * Astro treats both as TypeScript by default.
50
+ */
51
+ private processScriptContent;
52
+ /**
53
+ * Line ranges (0-indexed, inclusive) the template scans must skip:
54
+ * the frontmatter block and <script>/<style> blocks.
55
+ */
56
+ private getCoveredRanges;
57
+ /**
58
+ * Extract function calls from Astro template expressions.
59
+ *
60
+ * Astro templates embed JSX-like expressions (`{formatDate(post.date)}`,
61
+ * `class:list={cn(...)}`), so calls frequently live in markup rather than
62
+ * the frontmatter. We scan template lines for `{expression}` groups and
63
+ * extract call patterns from them. A `{` group left open at end-of-line
64
+ * (the pervasive `{posts.map((post) => (` pattern) contributes the calls
65
+ * on its opening line.
66
+ */
67
+ private extractTemplateCalls;
68
+ /**
69
+ * Extract component usages from the Astro template.
70
+ *
71
+ * PascalCase tags like <Layout>, <PostCard /> represent component
72
+ * instantiations โ€” analogous to function calls in imperative code.
73
+ * Lowercase tags are native HTML (Astro does not register kebab-case
74
+ * components the way Vue does, so those are real custom elements and
75
+ * are skipped).
76
+ */
77
+ private extractTemplateComponents;
78
+ }
79
+ //# sourceMappingURL=astro-extractor.d.ts.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Extraction version
3
+ *
4
+ * A monotonically-increasing integer that identifies the *shape and depth* of
5
+ * what the extractor writes into the graph. Unlike `CURRENT_SCHEMA_VERSION`
6
+ * (which tracks the SQLite table layout and is migrated in place), this tracks
7
+ * the EXTRACTED CONTENT โ€” node kinds, edges, synthesizers, resolver coverage.
8
+ *
9
+ * When an index was built by an older engine whose `EXTRACTION_VERSION` is
10
+ * below the running engine's, the data on disk is structurally fine but
11
+ * *stale*: it's missing whatever a newer extractor would now produce. A schema
12
+ * migration can't backfill that โ€” only a re-index can. So this is the signal
13
+ * `codegraph status` uses to recommend a re-index, and the reason `codegraph
14
+ * upgrade` reminds users to refresh their projects.
15
+ *
16
+ * BUMP THIS when a release changes extraction output enough that existing
17
+ * indexes should be rebuilt to benefit โ€” e.g. a new language/framework
18
+ * extractor, a new dynamic-dispatch synthesizer, a new node/edge kind, or a
19
+ * resolver fix that materially changes which edges exist. Do NOT bump for
20
+ * pure bug fixes, CLI/UX changes, or schema-only migrations. Over-bumping
21
+ * turns the re-index hint into noise โ€” keep it honest (see CLAUDE.md, "Honesty
22
+ * in the product is load-bearing").
23
+ */
24
+ export declare const EXTRACTION_VERSION = 24;
25
+ //# sourceMappingURL=extraction-version.d.ts.map
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Function-as-value capture (#756) โ€” registration-linking for callbacks.
3
+ *
4
+ * A function name used as a VALUE โ€” passed as a call argument
5
+ * (`register_handler(target_cb)`, `signal(SIGINT, handler)`), assigned to a
6
+ * field or function pointer (`o->cb = target_cb`, `OnFire := TargetCb`),
7
+ * placed in a struct/object initializer (`{ .recv_cb = my_cb }`,
8
+ * `{ recv: targetCb }`, `Ops{Cb: targetCb}`), or listed in a function table
9
+ * (`static cb_t table[] = { cb_a, cb_b }`) โ€” is a real dependency that static
10
+ * call extraction misses entirely: `callers(target_cb)` showed nothing but
11
+ * direct calls, so every callback looked dead and its registration sites were
12
+ * invisible to impact analysis.
13
+ *
14
+ * This module captures those value positions during the AST walk as
15
+ * `function_ref` candidates. Capture is table-driven per language (the value
16
+ * positions and wrapper forms differ per grammar โ€” `&fn` in C, `Main::fn` in
17
+ * Java, `::fn` in Kotlin, `#selector(fn)` in Swift, `@TargetCb` in Pascal,
18
+ * `method(:fn)` in Ruby). Candidates are GATED at end-of-file extraction
19
+ * (see `TreeSitterExtractor.flushFnRefCandidates`): only names matching a
20
+ * same-file function/method or an imported binding survive, which bounds
21
+ * volume and keeps precision high. Resolution then matches survivors against
22
+ * function/method nodes ONLY (`matchFunctionRef` in
23
+ * `src/resolution/name-matcher.ts`) and persists them as `references` edges,
24
+ * which `callers`/`impact` already traverse.
25
+ *
26
+ * Deliberately NOT covered (resolving the *dispatch* โ€” `o->cb(x)` โ†’ the
27
+ * registered function โ€” needs data-flow through struct fields; a wrong edge
28
+ * is worse than none): indirect-call resolution and `obj.method` member
29
+ * values where `obj` isn't `this`/`self` (the receiver's type is statically
30
+ * unknowable without local data-flow).
31
+ */
32
+ import type { Node as SyntaxNode } from 'web-tree-sitter';
33
+ export interface FnRefCandidate {
34
+ name: string;
35
+ line: number;
36
+ column: number;
37
+ /** Which capture position produced this candidate (gate policy keys on it). */
38
+ mode: CaptureMode;
39
+ /**
40
+ * True when the value was an explicit reference form (`&fn`, `&Cls::m`,
41
+ * `::fn`, `#selector`, `method(:sym)`) rather than a bare identifier โ€”
42
+ * C++'s flush policy keys on it.
43
+ */
44
+ explicitRef: boolean;
45
+ /**
46
+ * Skip the same-file/import name gate for this candidate. Set for PHP
47
+ * string callables in known HOF positions: PHP global functions are
48
+ * referenced cross-file WITHOUT imports (global namespace), so the gate
49
+ * can't see them โ€” the strong positional prior (a string argument to
50
+ * `usort`/`array_map`/โ€ฆ) plus resolution's unique-or-drop rule carry the
51
+ * precision instead.
52
+ */
53
+ skipGate?: boolean;
54
+ }
55
+ /** How to pull candidate value nodes out of a dispatched container node. */
56
+ type CaptureMode = 'args' | 'rhs' | 'value' | 'list' | 'varinit';
57
+ interface CaptureRule {
58
+ mode: CaptureMode;
59
+ /** Field holding the value for rhs/value/varinit (defaults per mode). */
60
+ field?: string;
61
+ }
62
+ export interface FnRefSpec {
63
+ /** Bare identifier node types that can act as a function value. */
64
+ idTypes: Set<string>;
65
+ /** Container node type โ†’ how to extract candidate values from it. */
66
+ dispatch: Map<string, CaptureRule>;
67
+ /**
68
+ * Transparent wrapper layers between a container and its values
69
+ * (`argument`, `value_argument`, `literal_element`, `expression_list`โ€ฆ).
70
+ * Value: the field to descend into, or null for "named children".
71
+ * `expression_list` fans out to ALL named children (Go multi-assign).
72
+ */
73
+ layers?: Map<string, string | null>;
74
+ /**
75
+ * Unary wrappers whose operand is the function value โ€” C/C++ `&fn`
76
+ * (pointer_expression), Pascal `@Fn` (exprUnary), Scala eta `fn _`
77
+ * (postfix_expression). Value: operand field, or null for first named child.
78
+ */
79
+ unwrap?: Map<string, string | null>;
80
+ /**
81
+ * Whole-node reference forms needing bespoke name extraction โ€”
82
+ * `method_reference` (Java), `callable_reference` / `navigation_expression`
83
+ * (Kotlin), `selector_expression` (Swift `#selector` / ObjC `@selector`),
84
+ * Ruby `method(:sym)` calls, and `this.method` member forms.
85
+ */
86
+ special?: Set<string>;
87
+ /**
88
+ * Capture modes whose candidates skip the same-file/import gate and rely on
89
+ * resolution's unique-or-drop rule instead. C-family only: an initializer
90
+ * value, function-pointer assignment RHS, or table element is a
91
+ * function-pointer position by construction, and C has no symbol imports โ€”
92
+ * the dominant repo-scale pattern (`server.c`'s command table naming
93
+ * handlers defined across files) would otherwise be invisible. Call
94
+ * arguments stay gated everywhere (locals passed as args dwarf callbacks).
95
+ */
96
+ ungatedModes?: Set<CaptureMode>;
97
+ /**
98
+ * C++ only: in args/rhs/varinit positions, accept ONLY explicit reference
99
+ * forms (`&fn`, `&Cls::method`) โ€” never bare identifiers. C++ codebases are
100
+ * dense with generic free-function/accessor names (`begin`, `end`, `out`,
101
+ * `size`, `data`) that collide with parameters and locals, and out-of-line
102
+ * member definitions extract as function-kind nodes โ€” bare-id matching on
103
+ * fmt was mostly wrong edges. File-scope initializer tables (value/list)
104
+ * still accept bare identifiers, same as C.
105
+ */
106
+ addressOfOnly?: boolean;
107
+ }
108
+ /**
109
+ * Capture specs by language.
110
+ */
111
+ export declare const FN_REF_SPECS: Record<string, FnRefSpec | undefined>;
112
+ /**
113
+ * Extract candidate names from a dispatched container node. Returns the
114
+ * (name, position) pairs of every function-value-shaped expression found.
115
+ */
116
+ export declare function captureFnRefCandidates(container: SyntaxNode, rule: CaptureRule, spec: FnRefSpec, source: string): FnRefCandidate[];
117
+ export {};
118
+ //# sourceMappingURL=function-ref.d.ts.map
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { Parser } from 'web-tree-sitter';
9
9
  import { Language } from '../types';
10
- export type GrammarLanguage = Exclude<Language, 'svelte' | 'vue' | 'liquid' | 'yaml' | 'twig' | 'xml' | 'properties' | 'unknown'>;
10
+ export type GrammarLanguage = Exclude<Language, 'svelte' | 'vue' | 'astro' | 'liquid' | 'razor' | 'yaml' | 'twig' | 'xml' | 'properties' | 'unknown'>;
11
11
  /**
12
12
  * File extension to Language mapping
13
13
  */
@@ -18,6 +18,12 @@ export declare const EXTENSION_MAP: Record<string, Language>;
18
18
  * from EXTENSION_MAP so parser support and indexing selection never drift.
19
19
  */
20
20
  export declare function isSourceFile(filePath: string): boolean;
21
+ /**
22
+ * Shopify OS 2.0 JSON template (`templates/*.json`) or section group
23
+ * (`sections/*.json`) โ€” these reference sections by `"type"`, so the Liquid
24
+ * extractor links them. (config/ + locales/ JSON have no section refs.)
25
+ */
26
+ export declare function isShopifyLiquidJson(filePath: string): boolean;
21
27
  /**
22
28
  * Play Framework routes file: the extensionless `conf/routes` (and included
23
29
  * `conf/*.routes`). No grammar โ€” route extraction is done by the Play framework