diff --git a/.github/workflows/ci-integration.yml b/.github/workflows/ci-integration.yml index f15b788b37..e7da8049a3 100644 --- a/.github/workflows/ci-integration.yml +++ b/.github/workflows/ci-integration.yml @@ -12,29 +12,29 @@ on: jobs: # ── Integration test matrix ───────────────────────────────────────── # Each test-group runs on a SEPARATE runner per OS, giving full process - # isolation for the KuzuDB native C++ addon. + # isolation for the LadybugDB native C++ addon. # 3 OS x 4 groups = 12 parallel jobs. # # Groups: - # kuzu-db — 7 files using withTestKuzuDB / kuzu-adapter (native addon) + # lbug-db — 7 files using withTestLbugDB / lbug-adapter (native addon) # Each file runs as its own `vitest run` invocation for full - # process isolation. KuzuDB's native N-API addon registers + # process isolation. LadybugDB's native N-API addon registers # persistent handles that prevent fork workers from exiting # on Linux, and its C++ destructors segfault during # process.exit(). Running each file in its own process lets # the OS reclaim all resources cleanly. - # pipeline — 13 files: ingestion pipeline + csv + 10 resolver tests - # e2e — 2 files: child-process only (spawnSync), no in-process kuzu - # standalone — 4 files: pure logic, no kuzu, no child processes + # pipeline — 12 files: ingestion pipeline + csv + 9 resolver tests + # e2e — 2 files: child-process only (spawnSync), no in-process lbug + # standalone — 4 files: pure logic, no lbug, no child processes test-matrix: name: integration (${{ matrix.os }} / ${{ matrix.test-group }}) strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - test-group: [kuzu-db, pipeline, e2e, standalone] + test-group: [lbug-db, pipeline, e2e, standalone] include: - - test-group: kuzu-db + - test-group: lbug-db # Marker — actual files are listed in the run step below test-glob: '' - test-group: pipeline @@ -72,18 +72,18 @@ jobs: with: build: 'true' - # kuzu-db: run each file in its own vitest process for full isolation. - # KuzuDB's native addon hangs fork workers on Linux — process isolation + # lbug-db: run each file in its own vitest process for full isolation. + # LadybugDB's native addon hangs fork workers on Linux — process isolation # is the only reliable fix boundary. - - name: Run integration tests — kuzu-db (process-isolated) - if: matrix.test-group == 'kuzu-db' + - name: Run integration tests — lbug-db (process-isolated) + if: matrix.test-group == 'lbug-db' working-directory: gitnexus shell: bash run: | set -e files=( - test/integration/kuzu-core-adapter.test.ts - test/integration/kuzu-pool.test.ts + test/integration/lbug-core-adapter.test.ts + test/integration/lbug-pool.test.ts test/integration/local-backend.test.ts test/integration/local-backend-calltool.test.ts test/integration/search-core.test.ts @@ -101,9 +101,9 @@ jobs: done exit $exit_code - # Non-kuzu groups: run all files in a single vitest invocation + # Non-lbug groups: run all files in a single vitest invocation - name: Run integration tests — ${{ matrix.test-group }} - if: matrix.test-group != 'kuzu-db' + if: matrix.test-group != 'lbug-db' shell: bash env: TEST_GLOB: ${{ matrix.test-glob }} @@ -111,9 +111,9 @@ jobs: working-directory: gitnexus # ── Coverage collection (ubuntu only) ───────────────────────────────── - # Runs non-kuzu integration tests with coverage enabled so the PR report + # Runs non-lbug integration tests with coverage enabled so the PR report # can merge integration + unit coverage for a combined view. - # kuzu-db tests are excluded because each file must run in its own vitest + # lbug-db tests are excluded because each file must run in its own vitest # process (native addon isolation) which prevents single-run coverage merge. coverage: name: integration (ubuntu / coverage) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8bf147085..23077f538d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to GitNexus will be documented in this file. +## [Unreleased] + +### Changed +- Migrated from KuzuDB to LadybugDB v0.15 (`@ladybugdb/core`, `@ladybugdb/wasm-core`) +- Renamed all internal paths from `kuzu` to `lbug` (storage: `.gitnexus/kuzu` → `.gitnexus/lbug`) +- Added automatic cleanup of stale KuzuDB index files +- LadybugDB v0.15 requires explicit VECTOR extension loading for semantic search + ## [1.4.0] - 2026-03-13 ### Added diff --git a/README.md b/README.md index 58fc0f5146..1f60e24424 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ https://github.com/user-attachments/assets/172685ba-8e54-4ea7-9ad1-e31a3398da72 | **For** | Daily development with Cursor, Claude Code, Windsurf, OpenCode | Quick exploration, demos, one-off analysis | | **Scale** | Full repos, any size | Limited by browser memory (~5k files), or unlimited via backend mode | | **Install** | `npm install -g gitnexus` | No install —[gitnexus.vercel.app](https://gitnexus.vercel.app) | -| **Storage** | KuzuDB native (fast, persistent) | KuzuDB WASM (in-memory, per session) | +| **Storage** | LadybugDB native (fast, persistent) | LadybugDB WASM (in-memory, per session) | | **Parsing** | Tree-sitter native bindings | Tree-sitter WASM | | **Privacy** | Everything local, no network | Everything in-browser, no server | @@ -224,8 +224,8 @@ flowchart TD Server["server.ts"] Backend["LocalBackend"] Pool["Connection Pool"] - ConnA["KuzuDB conn A"] - ConnB["KuzuDB conn B"] + ConnA["LadybugDB conn A"] + ConnB["LadybugDB conn B"] end Setup -->|"writes global MCP config"| CursorConfig["~/.cursor/mcp.json"] @@ -242,7 +242,7 @@ flowchart TD ConnB -->|"queries"| RepoB ``` -**How it works:** Each `gitnexus analyze` stores the index in `.gitnexus/` inside the repo (portable, gitignored) and registers a pointer in `~/.gitnexus/registry.json`. When an AI agent starts, the MCP server reads the registry and can serve any indexed repo. KuzuDB connections are opened lazily on first query and evicted after 5 minutes of inactivity (max 5 concurrent). If only one repo is indexed, the `repo` parameter is optional on all tools — agents don't need to change anything. +**How it works:** Each `gitnexus analyze` stores the index in `.gitnexus/` inside the repo (portable, gitignored) and registers a pointer in `~/.gitnexus/registry.json`. When an AI agent starts, the MCP server reads the registry and can serve any indexed repo. LadybugDB connections are opened lazily on first query and evicted after 5 minutes of inactivity (max 5 concurrent). If only one repo is indexed, the `repo` parameter is optional on all tools — agents don't need to change anything. --- @@ -263,7 +263,7 @@ npm install npm run dev ``` -The web UI uses the same indexing pipeline as the CLI but runs entirely in WebAssembly (Tree-sitter WASM, KuzuDB WASM, in-browser embeddings). It's great for quick exploration but limited by browser memory for larger repos. +The web UI uses the same indexing pipeline as the CLI but runs entirely in WebAssembly (Tree-sitter WASM, LadybugDB WASM, in-browser embeddings). It's great for quick exploration but limited by browser memory for larger repos. **Local Backend Mode:** Run `gitnexus serve` and open the web UI locally — it auto-detects the server and shows all your indexed repos, with full AI chat support. No need to re-upload or re-index. The agent's tools (Cypher queries, search, code navigation) route through the backend HTTP API automatically. @@ -482,7 +482,7 @@ The wiki generator reads the indexed graph structure, groups files into modules | ------------------------- | ------------------------------------- | --------------------------------------- | | **Runtime** | Node.js (native) | Browser (WASM) | | **Parsing** | Tree-sitter native bindings | Tree-sitter WASM | -| **Database** | KuzuDB native | KuzuDB WASM | +| **Database** | LadybugDB native | LadybugDB WASM | | **Embeddings** | HuggingFace transformers.js (GPU/CPU) | transformers.js (WebGPU/WASM) | | **Search** | BM25 + semantic + RRF | BM25 + semantic + RRF | | **Agent Interface** | MCP (stdio) | LangChain ReAct agent | @@ -523,7 +523,7 @@ The wiki generator reads the indexed graph structure, groups files into modules ## Acknowledgments - [Tree-sitter](https://tree-sitter.github.io/) — AST parsing -- [KuzuDB](https://kuzudb.com/) — Embedded graph database with vector support +- [LadybugDB](https://ladybugdb.com/) — Embedded graph database with vector support (formerly KuzuDB) - [Sigma.js](https://www.sigmajs.org/) — WebGL graph rendering - [transformers.js](https://huggingface.co/docs/transformers.js) — Browser ML - [Graphology](https://graphology.github.io/) — Graph data structures diff --git a/eval/README.md b/eval/README.md index d268e67b05..d20f8b837e 100644 --- a/eval/README.md +++ b/eval/README.md @@ -148,7 +148,7 @@ Each mode has a `system_{mode}.jinja` + `instance_{mode}.jinja` pair. The agent 1. Docker container starts with SWE-bench instance (repo at specific commit) 2. **GitNexus setup**: Node.js + gitnexus installed, `gitnexus analyze` runs (or restores from cache) -3. **Eval-server starts**: `gitnexus eval-server` daemon (persistent HTTP server, keeps KuzuDB warm) +3. **Eval-server starts**: `gitnexus eval-server` daemon (persistent HTTP server, keeps LadybugDB warm) 4. **Standalone tool scripts installed** in `/usr/local/bin/` — works with `subprocess.run` (no `.bashrc` needed) 5. Agent runs with the configured model + system prompt + GitNexus tools 6. Agent's patch is extracted as a git diff @@ -167,7 +167,7 @@ Each tool script in `/usr/local/bin/` is standalone — no sourcing, no env inhe ### Eval-server The eval-server is a lightweight HTTP daemon that: -- Keeps KuzuDB warm in memory (no cold start per tool call) +- Keeps LadybugDB warm in memory (no cold start per tool call) - Returns LLM-friendly text (not raw JSON — saves tokens) - Includes next-step hints to guide tool chaining (query → context → impact → fix) - Auto-shuts down after idle timeout diff --git a/gitnexus-claude-plugin/hooks/gitnexus-hook.js b/gitnexus-claude-plugin/hooks/gitnexus-hook.js index 4c45c92d95..4cc79c100b 100644 --- a/gitnexus-claude-plugin/hooks/gitnexus-hook.js +++ b/gitnexus-claude-plugin/hooks/gitnexus-hook.js @@ -160,7 +160,7 @@ function handlePreToolUse(input) { * PostToolUse handler — detect index staleness after git mutations. * * Instead of spawning a full `gitnexus analyze` synchronously (which blocks - * the agent for up to 120s and risks KuzuDB corruption on timeout), we do a + * the agent for up to 120s and risks LadybugDB corruption on timeout), we do a * lightweight staleness check: compare `git rev-parse HEAD` against the * lastCommit stored in `.gitnexus/meta.json`. If they differ, notify the * agent so it can decide when to reindex. diff --git a/gitnexus-web/package-lock.json b/gitnexus-web/package-lock.json index 97942ca4d2..dd7bce991b 100644 --- a/gitnexus-web/package-lock.json +++ b/gitnexus-web/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@huggingface/transformers": "^3.0.0", "@isomorphic-git/lightning-fs": "^4.6.2", + "@ladybugdb/wasm-core": "^0.15.1", "@langchain/anthropic": "^1.3.10", "@langchain/core": "^1.1.15", "@langchain/google-genai": "^2.1.10", @@ -30,7 +31,6 @@ "graphology-utils": "^2.3.0", "isomorphic-git": "^1.36.1", "jszip": "^3.10.1", - "kuzu-wasm": "^0.11.1", "langchain": "^1.2.10", "lru-cache": "^11.2.4", "lucide-react": "^0.562.0", @@ -1643,6 +1643,30 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@ladybugdb/wasm-core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@ladybugdb/wasm-core/-/wasm-core-0.15.1.tgz", + "integrity": "sha512-dHEq8inJQBkHnJrqZMKGdltSfeSv9OHECkzWQixqDLApXXGlbJ5Ugq5rRfk2PLJuZ74LVHT0cZvcn4JLmsnAIA==", + "license": "MIT", + "dependencies": { + "threads": "^1.7.0", + "tiny-worker": "^2.3.0", + "uuid": "^11.0.3" + } + }, + "node_modules/@ladybugdb/wasm-core/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/@langchain/anthropic": { "version": "1.3.10", "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-1.3.10.tgz", @@ -6194,31 +6218,6 @@ "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" }, - "node_modules/kuzu-wasm": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/kuzu-wasm/-/kuzu-wasm-0.11.3.tgz", - "integrity": "sha512-+bLOqXgYZJJ2dHJG1y9LTLyb9ZB73eLxErRZahZz2rPokfIdyLaktTJFzJH7wX39hgyukKn8QxeRNobH6gl27g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT", - "dependencies": { - "threads": "^1.7.0", - "tiny-worker": "^2.3.0", - "uuid": "^11.0.3" - } - }, - "node_modules/kuzu-wasm/node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/langchain": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/langchain/-/langchain-1.2.10.tgz", diff --git a/gitnexus-web/package.json b/gitnexus-web/package.json index d66c421132..25263b0b4a 100644 --- a/gitnexus-web/package.json +++ b/gitnexus-web/package.json @@ -33,7 +33,7 @@ "graphology-layout-noverlap": "^0.4.2", "isomorphic-git": "^1.36.1", "jszip": "^3.10.1", - "kuzu-wasm": "^0.11.1", + "@ladybugdb/wasm-core": "^0.15.1", "langchain": "^1.2.10", "lru-cache": "^11.2.4", "lucide-react": "^0.562.0", diff --git a/gitnexus-web/public/wasm/kuzu-wasm.wasm b/gitnexus-web/public/wasm/kuzu-wasm.wasm deleted file mode 100644 index d7d0f7fced..0000000000 Binary files a/gitnexus-web/public/wasm/kuzu-wasm.wasm and /dev/null differ diff --git a/gitnexus-web/src/components/EmbeddingStatus.tsx b/gitnexus-web/src/components/EmbeddingStatus.tsx index e5a0e54184..4bf6001c90 100644 --- a/gitnexus-web/src/components/EmbeddingStatus.tsx +++ b/gitnexus-web/src/components/EmbeddingStatus.tsx @@ -83,7 +83,7 @@ export const EmbeddingStatus = () => {