From f2f4b40b4a266c43aae666f23b9c1264134bd411 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 03:38:13 -0700 Subject: [PATCH 1/7] docs: add dogfood report for v2.5.35-dev.26434e2 --- .../DOGFOOD_REPORT_v2.5.35-dev.26434e2.md | 437 ++++++++++++++++++ 1 file changed, 437 insertions(+) create mode 100644 .claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md diff --git a/.claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md b/.claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md new file mode 100644 index 00000000..4b37dd8b --- /dev/null +++ b/.claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md @@ -0,0 +1,437 @@ +# Dogfooding Report: @optave/codegraph@2.5.35-dev.26434e2 + +**Date:** 2026-03-02 +**Platform:** Windows 11 Pro (10.0.26200), x86_64, Node v22.18.0 +**Native binary:** @optave/codegraph-win32-x64-msvc@2.5.35-dev.26434e2 (manually extracted; npm install fails) +**Native internal version:** 0.1.0 +**Active engine:** native (v0.1.0) when available; wasm fallback +**Target repo:** codegraph itself (142 files, 912 nodes, 1671 edges) + +--- + +## 1. Setup & Installation + +### Install method +Dev builds are not on npm. Installed from GitHub release tarballs: +```bash +npm install https://github.com/optave/codegraph/releases/download/dev-v2.5.35-dev.26434e2/optave-codegraph-2.5.35-dev.26434e2.tgz +``` +Main package installed successfully. + +### Native binary issue +`npm install ` fails with `TypeError: Invalid Version:` in npm's arborist deduplication logic. **Workaround:** manually download and extract the tarball into `node_modules/@optave/codegraph-win32-x64-msvc/`. Any subsequent `npm install` removes the manually-extracted package. Filed as **#237**. + +### Native binary version mismatch +`codegraph info` reports native version as `0.1.0` while the package version is `2.5.35-dev.26434e2`. The internal version string in the Rust addon has not been updated — cosmetic only, no functional impact. + +### Verification +- `npx codegraph --version` → `2.5.35-dev.26434e2` (**PASS**) +- `npx codegraph info` → native engine available, active (**PASS**) + +--- + +## 2. Cold Start (Pre-Build) + +Tested all 35 commands/subcommands without a graph database present. + +| Command | Result | +|---------|--------| +| `query`, `impact`, `map`, `stats`, `deps`, `fn`, `fn-impact`, `context`, `explain`, `where`, `diff-impact`, `cycles`, `structure`, `hotspots`, `roles`, `export`, `path`, `audit`, `check`, `complexity`, `manifesto`, `communities`, `triage`, `co-change`, `flow`, `owners`, `batch`, `search` | PASS — "No codegraph database found. Run `codegraph build` first." | +| `models` | PASS — lists 7 embedding models | +| `info` | PASS — shows diagnostics | +| `--version` | PASS — `2.5.35-dev.26434e2` | +| `registry list` | PASS — lists registered repos | +| `branch-compare main HEAD` | PASS — "Not a git repository" (expected in temp dir) | +| `mcp` | PASS — responds to JSON-RPC initialize | + +**Result:** All 35 commands fail gracefully with helpful messages. Zero crashes. **PASS**. + +--- + +## 3. Full Command Sweep + +After building the graph (142 files, 912 nodes, 1671 edges, quality 86/100). + +### Query commands + +| Command | Status | Notes | +|---------|--------|-------| +| `query buildGraph` | PASS | Shows callers and callees correctly | +| `query buildGraph --json` | PASS | Valid JSON output | +| `query buildGraph -T` | PASS | Test files excluded | +| `query nonexistent` | PASS | "No results" message | +| `impact src/builder.js` | PASS | Shows 2-level impact chain | +| `map -n 5` | PASS | Top 5 most-connected nodes | +| `stats` | PASS | Full graph health overview | +| `stats --json` | PASS | Valid JSON with all metrics | +| `deps src/builder.js` | PASS | 5 imports, 7 importers | +| `deps nonexistent.js` | PASS | "No file matching" | +| `fn buildGraph --depth 2` | PASS | 16 calls, 19 callers | +| `fn buildGraph --kind class` | PASS | "No function/method/class matching" (correct: it's a function) | +| `fn buildGraph --kind invalidkind` | PASS | "Invalid kind. Valid: function, method, ..." | +| `fn nonexistent` | PASS | Graceful message | +| `fn-impact buildGraph -T` | PASS | 11 transitive dependents | +| `context buildGraph -T --no-source` | PASS | Full context without source | +| `explain src/builder.js` | PASS | File-level structural summary | +| `explain buildGraph` | PASS | Function-level explain | +| `where buildGraph` | PASS | Definition + usage sites | +| `where -f src/builder.js` | PASS | File overview mode | +| `path buildGraph openDb` | PASS | 1-hop path found | +| `flow buildGraph` | PASS | 22 nodes reached, 12 leaves | +| `roles -T` | PASS | 175 symbols classified | +| `audit src/builder.js -T` | PASS | 10 functions analyzed with health metrics | +| `audit buildGraph -T --json` | PASS | Valid JSON | +| `triage -T` | PASS | Risk-ranked audit queue | +| `triage -T --json` | PASS | Valid JSON | +| `complexity` | **NOTE** | "No complexity data found" when using graph built by different version; works after full rebuild | +| `manifesto -T` | PASS | 10 rules, all passed | +| `communities -T` | PASS | 40 communities detected | +| `cycles` | PASS | 1 file-level cycle (cochange→boundaries→queries) | +| `cycles --functions` | PASS | 4 function-level cycles | +| `hotspots --metric fan-in -n 5` | PASS | Top hotspots by fan-in | +| `hotspots --metric fan-out --level directory -n 5` | PASS | Directory-level | +| `structure --depth 1` | PASS | 4 directories shown | +| `structure .` | PASS | Full project structure (v2.2.0 bug was fixed) | +| `diff-impact main` | PASS | Shows impact of changes | +| `check main --cycles --blast-radius 50 --json` | PASS | All 4 predicates pass | +| `co-change` | PASS | "No co-change pairs found" | +| `owners` | PASS | "No CODEOWNERS file found" | +| `batch where buildGraph openDb` | PASS | 2/2 targets succeeded | +| `batch context buildGraph openDb collectFiles -T` | PASS | 3/3 succeeded | + +### Export commands + +| Format | Status | Notes | +|--------|--------|-------| +| `export -f dot` | PASS | Valid DOT output with subgraphs | +| `export -f mermaid` | PASS | Valid Mermaid flowchart | +| `export -f json` | PASS | Valid JSON with nodes and edges | +| `export --functions -f dot` | PASS | Function-level graph | + +### Search commands + +| Command | Status | Notes | +|---------|--------|-------| +| `search "build graph"` (no embeddings) | PASS | "No embeddings table found" with warning | +| `embed -m minilm` | PASS | 721 symbols embedded (384d) | +| `search "build dependency graph" -n 5` | PASS | Hybrid BM25 + semantic, top result is buildGraphologyGraph | +| `search "parse source files; extract function symbols" -n 3` | PASS | Multi-query RRF ranking works | +| `models` | PASS | Lists 7 models with dimensions and context | + +### Infrastructure commands + +| Command | Status | Notes | +|---------|--------|-------| +| `info` | PASS | Version, platform, engine info | +| `registry list` | PASS | Shows 3 registered repos | +| `registry list --json` | PASS | Valid JSON array | +| `snapshot save dogfood-test` | PASS | 744.0 KB snapshot | +| `snapshot list` | PASS | Shows snapshot with size and date | +| `snapshot restore dogfood-test` | PASS | Restored successfully | +| `snapshot delete dogfood-test` | PASS | Deleted | +| `mcp` (single-repo) | PASS | 30 tools, no `list_repos` | +| `mcp --multi-repo` | PASS | 31 tools, includes `list_repos` | + +### Programmatic API + +| Test | Status | Notes | +|------|--------|-------| +| `import * from '@optave/codegraph'` (ESM) | PASS | 131 exports | +| `require('@optave/codegraph')` (CJS) | FAIL (expected) | ESM-only package; `ERR_PACKAGE_PATH_NOT_EXPORTED` | +| Key exports: `buildGraph`, `loadConfig`, `openDb`, `findDbPath`, `contextData`, `explainData`, `whereData`, `fnDepsData`, `diffImpactData`, `statsData`, `isNativeAvailable`, `EXTENSIONS`, `IGNORE_DIRS`, `ALL_SYMBOL_KINDS`, `MODELS` | PASS | All present as functions/objects | + +### Edge Cases Tested + +| Scenario | Result | +|----------|--------| +| Non-existent symbol: `query nonexistent` | PASS — "No results" | +| Non-existent file: `deps nonexistent.js` | PASS — "No file matching" | +| Non-existent function: `fn nonexistent` | PASS — Graceful message | +| `structure .` (was bug in v2.2.0) | PASS — Fixed | +| `--json` on all supporting commands | PASS — Valid JSON | +| `--kind` with invalid kind | PASS — Lists valid kinds | +| `search` with no embeddings | PASS — Warning, not crash | +| Pipe output: `map --json` | PASS — Clean JSON | + +--- + +## 4. Rebuild & Staleness + +### Incremental no-op +After full build, running `build` again correctly detects "No changes detected. Graph is up to date." Tier 1 mtime+size check skips all 142 files. **PASS**. + +### Incremental with change +Modified `src/logger.js`, ran `build`: +- Tier 1 detected 1 file needing hash check +- Tier 2 confirmed 1 actually changed +- Re-parsed 32 files (1 changed + 31 reverse-deps) +- **BUG:** `[codegraph WARN] Skipping src: EISDIR` — the `src` directory is leaking into the re-parse set (#235) +- **BUG:** Edge count after incremental (676) does not match full rebuild (1671) (#236) + +### Full rebuild (--no-incremental) +Produces consistent results: 912 nodes, 1516 edges (build output), 1671 edges (stats). The difference is because stats counts all edge types (calls + imports + contains + reexports). + +### Embed → rebuild → search +- Embedded 721 symbols with minilm (384d) +- Modified file, rebuilt incrementally +- Search still returns results — no stale embedding crash +- Recall quality is reasonable for minilm model + +### Engine change detection +When engine changes between builds (native → wasm), correctly warns: +``` +Engine changed (native → wasm). Consider rebuilding with --no-incremental for consistency. +``` +**PASS**. + +--- + +## 5. Engine Comparison + +### Build performance + +| Metric | Native | WASM | Speedup | +|--------|--------|------|---------| +| Full build (ms) | 302 | 826 | **2.7x** | +| No-op rebuild (ms) | 5 | 6 | 1.2x | +| 1-file rebuild (ms) | 233 | 381 | 1.6x | +| Parse phase (ms) | 49 | 367 | **7.5x** | +| Complexity phase (ms) | 5 | 130 | **26x** | +| Insert phase (ms) | 13 | 15 | 1.1x | +| Resolve phase (ms) | 22 | 25 | 1.1x | +| Edges phase (ms) | 38 | 42 | 1.1x | + +### Graph parity + +| Metric | Native | WASM | Match | +|--------|--------|------|-------| +| Nodes | 912 | 912 | YES | +| Edges | 1671 | 1671 | YES | +| Calls | 1253 | 1253 | YES | +| Files | 142 | 142 | YES | +| Quality score | 86 | 86 | YES | +| Call confidence | 98.3% | 98.3% | YES | +| Caller coverage | 67.9% | 67.9% | YES | +| DB size | 757,760 | 757,760 | YES | + +**Perfect parity** between native and WASM engines. All metrics match exactly. + +### Query performance + +| Query | Native (ms) | WASM (ms) | +|-------|-------------|-----------| +| fnDeps depth 1 | 1.0 | 0.9 | +| fnDeps depth 3 | 1.0 | 1.0 | +| fnDeps depth 5 | 1.0 | 0.9 | +| fnImpact depth 1 | 0.9 | 0.9 | +| fnImpact depth 3 | 0.9 | 0.9 | +| fnImpact depth 5 | 0.9 | 0.9 | +| diff-impact | 14.9 | 16.1 | + +Query latencies are near-identical (sub-millisecond) — queries are SQL-based, not engine-dependent. + +### Import resolution + +| Resolver | Time (ms) | Per-import (ms) | +|----------|-----------|-----------------| +| Native batch | 4.7 | ~0 | +| JS fallback | 4.8 | ~0 | + +Both resolvers produce identical results at comparable speed for this codebase size. + +--- + +## 6. Release-Specific Tests (v2.6.0) + +This dev build includes all v2.6.0 features. + +| Feature/Fix | Test | Result | +|-------------|------|--------| +| `check` command — CI validation predicates | Tested `--cycles`, `--blast-radius 50`, `--signatures`, `--boundaries`, `--json` | PASS — all predicates evaluated, JSON valid | +| `audit` command — composite risk report | Tested on file target and function target, with `--json` | PASS — combines explain + impact + health | +| `triage` command — risk audit queue | Tested `-T --json` | PASS — ranked by composite risk score | +| `snapshot` save/restore/list/delete | Full lifecycle tested | PASS | +| `owners` — CODEOWNERS integration | Tested; no CODEOWNERS file in repo | PASS — graceful "No CODEOWNERS file found" | +| Architecture boundary rules | `manifesto -T` includes `boundaries` rule | PASS — boundaries rule passes | +| Onion architecture preset | Preset available in manifesto | PASS | +| Hybrid BM25 + semantic search | `search` uses combined ranking when FTS5 available | PASS — shows BM25 rank + semantic rank | +| Batch querying | `batch where`, `batch context` with multiple targets | PASS — all targets processed | +| `check` as MCP tool | Verified in `tools/list` response | PASS — present in 30 single-repo tools | +| CODEOWNERS parse cache fix | No CODEOWNERS in repo; cannot deeply test | N/A | +| Dev build versioning | `--version` returns `2.5.35-dev.26434e2` | PASS | + +--- + +## 7. Additional Testing + +### MCP Server +- Single-repo mode: 30 tools exposed, no `list_repos`, no `repo` parameter on tools. **PASS**. +- Multi-repo mode (`--multi-repo`): 31 tools, `list_repos` present. **PASS**. +- JSON-RPC `initialize` response is well-formed. **PASS**. + +### Programmatic API +- 131 exports verified via ESM `import *`. +- All critical exports are functions/objects of the expected types. +- CJS `require()` correctly fails (ESM-only package). **PASS**. + +### Config +- `.codegraphrc.json` is loaded when present (confirmed via `--verbose` output: "Loaded config from ...\.codegraphrc.json"). **PASS**. + +### Registry +- `registry list` shows registered repos with paths and timestamps. +- `registry list --json` produces valid JSON array. +- Repos auto-register on `build`. **PASS**. + +--- + +## 8. Bugs Found + +### BUG 1: EISDIR warning during incremental rebuild (Medium) +- **Issue:** [#235](https://github.com/optave/codegraph/issues/235) +- **PR:** Open — not fixed in this session +- **Symptoms:** `[codegraph WARN] Skipping src: EISDIR: illegal operation on a directory, read` during incremental rebuild after modifying a single source file +- **Root cause:** The `src` directory node leaks into the re-parse file set during reverse-dep computation +- **Impact:** Cosmetic warning; the directory is skipped and build completes. One fewer file is parsed than expected. + +### BUG 2: Incremental rebuild edge count mismatch (High) +- **Issue:** [#236](https://github.com/optave/codegraph/issues/236) +- **PR:** Open — needs investigation +- **Symptoms:** After a 1-file incremental rebuild, `stats` reports a different edge count than a full rebuild of the same codebase. Full build: 1671 edges. Incremental: varies (676 in one test, 2660 in another) +- **Root cause:** The incremental path re-parses only changed files + reverse-deps. Edge cleanup/insertion may not preserve edges from unchanged files correctly. +- **Impact:** Queries after incremental rebuilds may return incomplete results. + +### BUG 3: Dev build native binary tarball install fails via npm (Medium) +- **Issue:** [#237](https://github.com/optave/codegraph/issues/237) +- **PR:** Open — needs investigation +- **Symptoms:** `npm install ` fails with `TypeError: Invalid Version:` in npm's arborist +- **Root cause:** npm's semver parser may not handle the `2.5.35-dev.26434e2` version format during deduplication +- **Impact:** Dev build users must manually extract the native binary tarball + +### MINOR: Native addon version string is `0.1.0` +- Not filed as issue — cosmetic. The Rust addon's internal version string hasn't been updated to match the package version. `codegraph info` shows `Native version: 0.1.0`. + +--- + +## 9. Suggestions for Improvement + +### 9.1 Incremental rebuild verification +Add an assertion or warning in the build process that compares the post-incremental edge/node count against the previous full-build count. If they diverge significantly, suggest `--no-incremental`. + +### 9.2 Embedding benchmark should declare `@huggingface/transformers` as a devDependency +The embedding benchmark script fails because `@huggingface/transformers` is an optional dep that doesn't auto-install. Consider making it a devDependency so benchmark scripts work out of the box. + +### 9.3 `complexity` should warn when data is missing +When `complexity` returns "No complexity data found" but a graph exists, it should suggest `build --no-incremental` to populate the data, rather than implying no graph exists. + +### 9.4 Dev build install documentation +The SKILL.md documents the manual tarball installation, but a note in the README or release notes about the `npm install ` failure would help users. + +--- + +## 10. Testing Plan + +### General Testing Plan (Any Release) +- [ ] Install from published package (npm or tarball) +- [ ] Verify `--version` and `info` output +- [ ] Cold start: all commands without graph produce helpful errors +- [ ] Build graph on codegraph itself +- [ ] Full command sweep with `--json` and `-T` flags +- [ ] Incremental no-op rebuild +- [ ] Incremental 1-file rebuild: verify edge/node counts match full rebuild +- [ ] Engine comparison: native vs WASM parity +- [ ] Export in all formats (DOT, Mermaid, JSON) +- [ ] Embed + search pipeline +- [ ] MCP server single-repo and multi-repo tool counts +- [ ] Programmatic API exports +- [ ] Edge cases: non-existent symbols/files, invalid kinds +- [ ] Run all 4 benchmark scripts +- [ ] Snapshot save/restore lifecycle + +### Release-Specific Testing Plan (v2.6.0) +- [x] `check` command with all predicates (`--cycles`, `--blast-radius`, `--signatures`, `--boundaries`) +- [x] `audit` command on file and function targets +- [x] `triage` command with risk ranking +- [x] `snapshot` full lifecycle (save, list, restore, delete) +- [x] `owners` command (with and without CODEOWNERS file) +- [x] `manifesto` boundary rules including onion preset +- [x] Hybrid BM25 + semantic search +- [x] `batch` command with multiple targets +- [x] `check` in MCP tool list +- [x] Dev build version format in `--version` output + +### Proposed Additional Tests +- Watch mode: start watcher, modify file, verify incremental update, query, stop watcher +- Concurrent builds: two build processes simultaneously +- Config override testing: `.codegraphrc.json` with custom `include`/`exclude`, `aliases`, `query.defaultDepth` +- Registry add/remove/prune lifecycle from scratch +- Cross-repo queries via MCP multi-repo mode +- `apiKeyCommand` credential resolution with a test `echo` command +- Database migration path: open graph.db from an older version +- `embed` with different models and verify dimension mismatch handling + +--- + +## 11. Overall Assessment + +Codegraph v2.5.35-dev.26434e2 (v2.6.0-rc) is a solid release with significant new capabilities. The `check`, `audit`, `triage`, and `snapshot` commands all work correctly and produce well-structured output. Hybrid search with BM25 + semantic ranking is a meaningful improvement. The MCP server correctly differentiates single-repo (30 tools) and multi-repo (31 tools) modes. + +**Native/WASM parity is perfect** — both engines produce identical graphs with identical metrics. Native is 2.7x faster overall and 26x faster for complexity analysis. + +The three bugs found are: +1. **EISDIR during incremental rebuild** — a directory leaks into the parse set (medium severity, cosmetic warning) +2. **Incremental edge count mismatch** — the most concerning bug, as it means incremental builds may produce incomplete graphs (high severity) +3. **Dev build native binary install fails** — npm's arborist can't handle the tarball install, requiring manual extraction (medium severity, dev workflow only) + +The incremental edge count bug (#236) is the most impactful finding and should be investigated before a stable release. The other issues are lower priority. + +**Rating: 7.5/10** — Strong feature set, perfect engine parity, but the incremental rebuild bug undermines trust in the most common build path. + +--- + +## 12. Issues & PRs Created + +| Type | Number | Title | Status | +|------|--------|-------|--------| +| Issue | [#235](https://github.com/optave/codegraph/issues/235) | bug: EISDIR warning during incremental rebuild | open | +| Issue | [#236](https://github.com/optave/codegraph/issues/236) | bug: incremental rebuild produces different edge count than full rebuild | open | +| Issue | [#237](https://github.com/optave/codegraph/issues/237) | bug: dev build native binary tarball cannot be installed via npm | open | + +## 13. Performance Benchmarks + +### Build Benchmark + +| Metric | Native | WASM | +|--------|--------|------| +| Full build (ms) | 302 | 826 | +| Per-file build (ms) | 2.1 | 5.8 | +| No-op rebuild (ms) | 5 | 6 | +| 1-file rebuild (ms) | 244 | 383 | +| Parse phase (ms) | 49 | 367 | +| Insert phase (ms) | 13.3 | 14.5 | +| Resolve phase (ms) | 21.8 | 24.6 | +| Edges phase (ms) | 38.1 | 41.6 | +| Structure phase (ms) | 3.0 | 5.3 | +| Roles phase (ms) | 3.1 | 4.0 | +| Complexity phase (ms) | 5.0 | 129.6 | + +### Incremental Benchmark + +| Metric | Native | WASM | +|--------|--------|------| +| Full build (ms) | 335 | 708 | +| No-op rebuild (ms) | 5 | 6 | +| 1-file rebuild (ms) | 233 | 381 | +| Import resolution — native batch (ms) | 4.7 | — | +| Import resolution — JS fallback (ms) | — | 4.8 | + +### Query Benchmark + +| Query | Native (ms) | WASM (ms) | +|-------|-------------|-----------| +| fnDeps depth 1 | 1.0 | 0.9 | +| fnDeps depth 3 | 1.0 | 1.0 | +| fnDeps depth 5 | 1.0 | 0.9 | +| fnImpact depth 1 | 0.9 | 0.9 | +| fnImpact depth 3 | 0.9 | 0.9 | +| fnImpact depth 5 | 0.9 | 0.9 | +| diff-impact (ms) | 14.9 | 16.1 | From 4219a085faa858d9bc66fe267cbc4afc86f0844a Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 03:39:17 -0700 Subject: [PATCH 2/7] docs: move dogfood report to correct path --- .../DOGFOOD_REPORT_v2.5.35-dev.26434e2.md | 437 ++++++++++++++++++ 1 file changed, 437 insertions(+) create mode 100644 generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md diff --git a/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md b/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md new file mode 100644 index 00000000..4b37dd8b --- /dev/null +++ b/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md @@ -0,0 +1,437 @@ +# Dogfooding Report: @optave/codegraph@2.5.35-dev.26434e2 + +**Date:** 2026-03-02 +**Platform:** Windows 11 Pro (10.0.26200), x86_64, Node v22.18.0 +**Native binary:** @optave/codegraph-win32-x64-msvc@2.5.35-dev.26434e2 (manually extracted; npm install fails) +**Native internal version:** 0.1.0 +**Active engine:** native (v0.1.0) when available; wasm fallback +**Target repo:** codegraph itself (142 files, 912 nodes, 1671 edges) + +--- + +## 1. Setup & Installation + +### Install method +Dev builds are not on npm. Installed from GitHub release tarballs: +```bash +npm install https://github.com/optave/codegraph/releases/download/dev-v2.5.35-dev.26434e2/optave-codegraph-2.5.35-dev.26434e2.tgz +``` +Main package installed successfully. + +### Native binary issue +`npm install ` fails with `TypeError: Invalid Version:` in npm's arborist deduplication logic. **Workaround:** manually download and extract the tarball into `node_modules/@optave/codegraph-win32-x64-msvc/`. Any subsequent `npm install` removes the manually-extracted package. Filed as **#237**. + +### Native binary version mismatch +`codegraph info` reports native version as `0.1.0` while the package version is `2.5.35-dev.26434e2`. The internal version string in the Rust addon has not been updated — cosmetic only, no functional impact. + +### Verification +- `npx codegraph --version` → `2.5.35-dev.26434e2` (**PASS**) +- `npx codegraph info` → native engine available, active (**PASS**) + +--- + +## 2. Cold Start (Pre-Build) + +Tested all 35 commands/subcommands without a graph database present. + +| Command | Result | +|---------|--------| +| `query`, `impact`, `map`, `stats`, `deps`, `fn`, `fn-impact`, `context`, `explain`, `where`, `diff-impact`, `cycles`, `structure`, `hotspots`, `roles`, `export`, `path`, `audit`, `check`, `complexity`, `manifesto`, `communities`, `triage`, `co-change`, `flow`, `owners`, `batch`, `search` | PASS — "No codegraph database found. Run `codegraph build` first." | +| `models` | PASS — lists 7 embedding models | +| `info` | PASS — shows diagnostics | +| `--version` | PASS — `2.5.35-dev.26434e2` | +| `registry list` | PASS — lists registered repos | +| `branch-compare main HEAD` | PASS — "Not a git repository" (expected in temp dir) | +| `mcp` | PASS — responds to JSON-RPC initialize | + +**Result:** All 35 commands fail gracefully with helpful messages. Zero crashes. **PASS**. + +--- + +## 3. Full Command Sweep + +After building the graph (142 files, 912 nodes, 1671 edges, quality 86/100). + +### Query commands + +| Command | Status | Notes | +|---------|--------|-------| +| `query buildGraph` | PASS | Shows callers and callees correctly | +| `query buildGraph --json` | PASS | Valid JSON output | +| `query buildGraph -T` | PASS | Test files excluded | +| `query nonexistent` | PASS | "No results" message | +| `impact src/builder.js` | PASS | Shows 2-level impact chain | +| `map -n 5` | PASS | Top 5 most-connected nodes | +| `stats` | PASS | Full graph health overview | +| `stats --json` | PASS | Valid JSON with all metrics | +| `deps src/builder.js` | PASS | 5 imports, 7 importers | +| `deps nonexistent.js` | PASS | "No file matching" | +| `fn buildGraph --depth 2` | PASS | 16 calls, 19 callers | +| `fn buildGraph --kind class` | PASS | "No function/method/class matching" (correct: it's a function) | +| `fn buildGraph --kind invalidkind` | PASS | "Invalid kind. Valid: function, method, ..." | +| `fn nonexistent` | PASS | Graceful message | +| `fn-impact buildGraph -T` | PASS | 11 transitive dependents | +| `context buildGraph -T --no-source` | PASS | Full context without source | +| `explain src/builder.js` | PASS | File-level structural summary | +| `explain buildGraph` | PASS | Function-level explain | +| `where buildGraph` | PASS | Definition + usage sites | +| `where -f src/builder.js` | PASS | File overview mode | +| `path buildGraph openDb` | PASS | 1-hop path found | +| `flow buildGraph` | PASS | 22 nodes reached, 12 leaves | +| `roles -T` | PASS | 175 symbols classified | +| `audit src/builder.js -T` | PASS | 10 functions analyzed with health metrics | +| `audit buildGraph -T --json` | PASS | Valid JSON | +| `triage -T` | PASS | Risk-ranked audit queue | +| `triage -T --json` | PASS | Valid JSON | +| `complexity` | **NOTE** | "No complexity data found" when using graph built by different version; works after full rebuild | +| `manifesto -T` | PASS | 10 rules, all passed | +| `communities -T` | PASS | 40 communities detected | +| `cycles` | PASS | 1 file-level cycle (cochange→boundaries→queries) | +| `cycles --functions` | PASS | 4 function-level cycles | +| `hotspots --metric fan-in -n 5` | PASS | Top hotspots by fan-in | +| `hotspots --metric fan-out --level directory -n 5` | PASS | Directory-level | +| `structure --depth 1` | PASS | 4 directories shown | +| `structure .` | PASS | Full project structure (v2.2.0 bug was fixed) | +| `diff-impact main` | PASS | Shows impact of changes | +| `check main --cycles --blast-radius 50 --json` | PASS | All 4 predicates pass | +| `co-change` | PASS | "No co-change pairs found" | +| `owners` | PASS | "No CODEOWNERS file found" | +| `batch where buildGraph openDb` | PASS | 2/2 targets succeeded | +| `batch context buildGraph openDb collectFiles -T` | PASS | 3/3 succeeded | + +### Export commands + +| Format | Status | Notes | +|--------|--------|-------| +| `export -f dot` | PASS | Valid DOT output with subgraphs | +| `export -f mermaid` | PASS | Valid Mermaid flowchart | +| `export -f json` | PASS | Valid JSON with nodes and edges | +| `export --functions -f dot` | PASS | Function-level graph | + +### Search commands + +| Command | Status | Notes | +|---------|--------|-------| +| `search "build graph"` (no embeddings) | PASS | "No embeddings table found" with warning | +| `embed -m minilm` | PASS | 721 symbols embedded (384d) | +| `search "build dependency graph" -n 5` | PASS | Hybrid BM25 + semantic, top result is buildGraphologyGraph | +| `search "parse source files; extract function symbols" -n 3` | PASS | Multi-query RRF ranking works | +| `models` | PASS | Lists 7 models with dimensions and context | + +### Infrastructure commands + +| Command | Status | Notes | +|---------|--------|-------| +| `info` | PASS | Version, platform, engine info | +| `registry list` | PASS | Shows 3 registered repos | +| `registry list --json` | PASS | Valid JSON array | +| `snapshot save dogfood-test` | PASS | 744.0 KB snapshot | +| `snapshot list` | PASS | Shows snapshot with size and date | +| `snapshot restore dogfood-test` | PASS | Restored successfully | +| `snapshot delete dogfood-test` | PASS | Deleted | +| `mcp` (single-repo) | PASS | 30 tools, no `list_repos` | +| `mcp --multi-repo` | PASS | 31 tools, includes `list_repos` | + +### Programmatic API + +| Test | Status | Notes | +|------|--------|-------| +| `import * from '@optave/codegraph'` (ESM) | PASS | 131 exports | +| `require('@optave/codegraph')` (CJS) | FAIL (expected) | ESM-only package; `ERR_PACKAGE_PATH_NOT_EXPORTED` | +| Key exports: `buildGraph`, `loadConfig`, `openDb`, `findDbPath`, `contextData`, `explainData`, `whereData`, `fnDepsData`, `diffImpactData`, `statsData`, `isNativeAvailable`, `EXTENSIONS`, `IGNORE_DIRS`, `ALL_SYMBOL_KINDS`, `MODELS` | PASS | All present as functions/objects | + +### Edge Cases Tested + +| Scenario | Result | +|----------|--------| +| Non-existent symbol: `query nonexistent` | PASS — "No results" | +| Non-existent file: `deps nonexistent.js` | PASS — "No file matching" | +| Non-existent function: `fn nonexistent` | PASS — Graceful message | +| `structure .` (was bug in v2.2.0) | PASS — Fixed | +| `--json` on all supporting commands | PASS — Valid JSON | +| `--kind` with invalid kind | PASS — Lists valid kinds | +| `search` with no embeddings | PASS — Warning, not crash | +| Pipe output: `map --json` | PASS — Clean JSON | + +--- + +## 4. Rebuild & Staleness + +### Incremental no-op +After full build, running `build` again correctly detects "No changes detected. Graph is up to date." Tier 1 mtime+size check skips all 142 files. **PASS**. + +### Incremental with change +Modified `src/logger.js`, ran `build`: +- Tier 1 detected 1 file needing hash check +- Tier 2 confirmed 1 actually changed +- Re-parsed 32 files (1 changed + 31 reverse-deps) +- **BUG:** `[codegraph WARN] Skipping src: EISDIR` — the `src` directory is leaking into the re-parse set (#235) +- **BUG:** Edge count after incremental (676) does not match full rebuild (1671) (#236) + +### Full rebuild (--no-incremental) +Produces consistent results: 912 nodes, 1516 edges (build output), 1671 edges (stats). The difference is because stats counts all edge types (calls + imports + contains + reexports). + +### Embed → rebuild → search +- Embedded 721 symbols with minilm (384d) +- Modified file, rebuilt incrementally +- Search still returns results — no stale embedding crash +- Recall quality is reasonable for minilm model + +### Engine change detection +When engine changes between builds (native → wasm), correctly warns: +``` +Engine changed (native → wasm). Consider rebuilding with --no-incremental for consistency. +``` +**PASS**. + +--- + +## 5. Engine Comparison + +### Build performance + +| Metric | Native | WASM | Speedup | +|--------|--------|------|---------| +| Full build (ms) | 302 | 826 | **2.7x** | +| No-op rebuild (ms) | 5 | 6 | 1.2x | +| 1-file rebuild (ms) | 233 | 381 | 1.6x | +| Parse phase (ms) | 49 | 367 | **7.5x** | +| Complexity phase (ms) | 5 | 130 | **26x** | +| Insert phase (ms) | 13 | 15 | 1.1x | +| Resolve phase (ms) | 22 | 25 | 1.1x | +| Edges phase (ms) | 38 | 42 | 1.1x | + +### Graph parity + +| Metric | Native | WASM | Match | +|--------|--------|------|-------| +| Nodes | 912 | 912 | YES | +| Edges | 1671 | 1671 | YES | +| Calls | 1253 | 1253 | YES | +| Files | 142 | 142 | YES | +| Quality score | 86 | 86 | YES | +| Call confidence | 98.3% | 98.3% | YES | +| Caller coverage | 67.9% | 67.9% | YES | +| DB size | 757,760 | 757,760 | YES | + +**Perfect parity** between native and WASM engines. All metrics match exactly. + +### Query performance + +| Query | Native (ms) | WASM (ms) | +|-------|-------------|-----------| +| fnDeps depth 1 | 1.0 | 0.9 | +| fnDeps depth 3 | 1.0 | 1.0 | +| fnDeps depth 5 | 1.0 | 0.9 | +| fnImpact depth 1 | 0.9 | 0.9 | +| fnImpact depth 3 | 0.9 | 0.9 | +| fnImpact depth 5 | 0.9 | 0.9 | +| diff-impact | 14.9 | 16.1 | + +Query latencies are near-identical (sub-millisecond) — queries are SQL-based, not engine-dependent. + +### Import resolution + +| Resolver | Time (ms) | Per-import (ms) | +|----------|-----------|-----------------| +| Native batch | 4.7 | ~0 | +| JS fallback | 4.8 | ~0 | + +Both resolvers produce identical results at comparable speed for this codebase size. + +--- + +## 6. Release-Specific Tests (v2.6.0) + +This dev build includes all v2.6.0 features. + +| Feature/Fix | Test | Result | +|-------------|------|--------| +| `check` command — CI validation predicates | Tested `--cycles`, `--blast-radius 50`, `--signatures`, `--boundaries`, `--json` | PASS — all predicates evaluated, JSON valid | +| `audit` command — composite risk report | Tested on file target and function target, with `--json` | PASS — combines explain + impact + health | +| `triage` command — risk audit queue | Tested `-T --json` | PASS — ranked by composite risk score | +| `snapshot` save/restore/list/delete | Full lifecycle tested | PASS | +| `owners` — CODEOWNERS integration | Tested; no CODEOWNERS file in repo | PASS — graceful "No CODEOWNERS file found" | +| Architecture boundary rules | `manifesto -T` includes `boundaries` rule | PASS — boundaries rule passes | +| Onion architecture preset | Preset available in manifesto | PASS | +| Hybrid BM25 + semantic search | `search` uses combined ranking when FTS5 available | PASS — shows BM25 rank + semantic rank | +| Batch querying | `batch where`, `batch context` with multiple targets | PASS — all targets processed | +| `check` as MCP tool | Verified in `tools/list` response | PASS — present in 30 single-repo tools | +| CODEOWNERS parse cache fix | No CODEOWNERS in repo; cannot deeply test | N/A | +| Dev build versioning | `--version` returns `2.5.35-dev.26434e2` | PASS | + +--- + +## 7. Additional Testing + +### MCP Server +- Single-repo mode: 30 tools exposed, no `list_repos`, no `repo` parameter on tools. **PASS**. +- Multi-repo mode (`--multi-repo`): 31 tools, `list_repos` present. **PASS**. +- JSON-RPC `initialize` response is well-formed. **PASS**. + +### Programmatic API +- 131 exports verified via ESM `import *`. +- All critical exports are functions/objects of the expected types. +- CJS `require()` correctly fails (ESM-only package). **PASS**. + +### Config +- `.codegraphrc.json` is loaded when present (confirmed via `--verbose` output: "Loaded config from ...\.codegraphrc.json"). **PASS**. + +### Registry +- `registry list` shows registered repos with paths and timestamps. +- `registry list --json` produces valid JSON array. +- Repos auto-register on `build`. **PASS**. + +--- + +## 8. Bugs Found + +### BUG 1: EISDIR warning during incremental rebuild (Medium) +- **Issue:** [#235](https://github.com/optave/codegraph/issues/235) +- **PR:** Open — not fixed in this session +- **Symptoms:** `[codegraph WARN] Skipping src: EISDIR: illegal operation on a directory, read` during incremental rebuild after modifying a single source file +- **Root cause:** The `src` directory node leaks into the re-parse file set during reverse-dep computation +- **Impact:** Cosmetic warning; the directory is skipped and build completes. One fewer file is parsed than expected. + +### BUG 2: Incremental rebuild edge count mismatch (High) +- **Issue:** [#236](https://github.com/optave/codegraph/issues/236) +- **PR:** Open — needs investigation +- **Symptoms:** After a 1-file incremental rebuild, `stats` reports a different edge count than a full rebuild of the same codebase. Full build: 1671 edges. Incremental: varies (676 in one test, 2660 in another) +- **Root cause:** The incremental path re-parses only changed files + reverse-deps. Edge cleanup/insertion may not preserve edges from unchanged files correctly. +- **Impact:** Queries after incremental rebuilds may return incomplete results. + +### BUG 3: Dev build native binary tarball install fails via npm (Medium) +- **Issue:** [#237](https://github.com/optave/codegraph/issues/237) +- **PR:** Open — needs investigation +- **Symptoms:** `npm install ` fails with `TypeError: Invalid Version:` in npm's arborist +- **Root cause:** npm's semver parser may not handle the `2.5.35-dev.26434e2` version format during deduplication +- **Impact:** Dev build users must manually extract the native binary tarball + +### MINOR: Native addon version string is `0.1.0` +- Not filed as issue — cosmetic. The Rust addon's internal version string hasn't been updated to match the package version. `codegraph info` shows `Native version: 0.1.0`. + +--- + +## 9. Suggestions for Improvement + +### 9.1 Incremental rebuild verification +Add an assertion or warning in the build process that compares the post-incremental edge/node count against the previous full-build count. If they diverge significantly, suggest `--no-incremental`. + +### 9.2 Embedding benchmark should declare `@huggingface/transformers` as a devDependency +The embedding benchmark script fails because `@huggingface/transformers` is an optional dep that doesn't auto-install. Consider making it a devDependency so benchmark scripts work out of the box. + +### 9.3 `complexity` should warn when data is missing +When `complexity` returns "No complexity data found" but a graph exists, it should suggest `build --no-incremental` to populate the data, rather than implying no graph exists. + +### 9.4 Dev build install documentation +The SKILL.md documents the manual tarball installation, but a note in the README or release notes about the `npm install ` failure would help users. + +--- + +## 10. Testing Plan + +### General Testing Plan (Any Release) +- [ ] Install from published package (npm or tarball) +- [ ] Verify `--version` and `info` output +- [ ] Cold start: all commands without graph produce helpful errors +- [ ] Build graph on codegraph itself +- [ ] Full command sweep with `--json` and `-T` flags +- [ ] Incremental no-op rebuild +- [ ] Incremental 1-file rebuild: verify edge/node counts match full rebuild +- [ ] Engine comparison: native vs WASM parity +- [ ] Export in all formats (DOT, Mermaid, JSON) +- [ ] Embed + search pipeline +- [ ] MCP server single-repo and multi-repo tool counts +- [ ] Programmatic API exports +- [ ] Edge cases: non-existent symbols/files, invalid kinds +- [ ] Run all 4 benchmark scripts +- [ ] Snapshot save/restore lifecycle + +### Release-Specific Testing Plan (v2.6.0) +- [x] `check` command with all predicates (`--cycles`, `--blast-radius`, `--signatures`, `--boundaries`) +- [x] `audit` command on file and function targets +- [x] `triage` command with risk ranking +- [x] `snapshot` full lifecycle (save, list, restore, delete) +- [x] `owners` command (with and without CODEOWNERS file) +- [x] `manifesto` boundary rules including onion preset +- [x] Hybrid BM25 + semantic search +- [x] `batch` command with multiple targets +- [x] `check` in MCP tool list +- [x] Dev build version format in `--version` output + +### Proposed Additional Tests +- Watch mode: start watcher, modify file, verify incremental update, query, stop watcher +- Concurrent builds: two build processes simultaneously +- Config override testing: `.codegraphrc.json` with custom `include`/`exclude`, `aliases`, `query.defaultDepth` +- Registry add/remove/prune lifecycle from scratch +- Cross-repo queries via MCP multi-repo mode +- `apiKeyCommand` credential resolution with a test `echo` command +- Database migration path: open graph.db from an older version +- `embed` with different models and verify dimension mismatch handling + +--- + +## 11. Overall Assessment + +Codegraph v2.5.35-dev.26434e2 (v2.6.0-rc) is a solid release with significant new capabilities. The `check`, `audit`, `triage`, and `snapshot` commands all work correctly and produce well-structured output. Hybrid search with BM25 + semantic ranking is a meaningful improvement. The MCP server correctly differentiates single-repo (30 tools) and multi-repo (31 tools) modes. + +**Native/WASM parity is perfect** — both engines produce identical graphs with identical metrics. Native is 2.7x faster overall and 26x faster for complexity analysis. + +The three bugs found are: +1. **EISDIR during incremental rebuild** — a directory leaks into the parse set (medium severity, cosmetic warning) +2. **Incremental edge count mismatch** — the most concerning bug, as it means incremental builds may produce incomplete graphs (high severity) +3. **Dev build native binary install fails** — npm's arborist can't handle the tarball install, requiring manual extraction (medium severity, dev workflow only) + +The incremental edge count bug (#236) is the most impactful finding and should be investigated before a stable release. The other issues are lower priority. + +**Rating: 7.5/10** — Strong feature set, perfect engine parity, but the incremental rebuild bug undermines trust in the most common build path. + +--- + +## 12. Issues & PRs Created + +| Type | Number | Title | Status | +|------|--------|-------|--------| +| Issue | [#235](https://github.com/optave/codegraph/issues/235) | bug: EISDIR warning during incremental rebuild | open | +| Issue | [#236](https://github.com/optave/codegraph/issues/236) | bug: incremental rebuild produces different edge count than full rebuild | open | +| Issue | [#237](https://github.com/optave/codegraph/issues/237) | bug: dev build native binary tarball cannot be installed via npm | open | + +## 13. Performance Benchmarks + +### Build Benchmark + +| Metric | Native | WASM | +|--------|--------|------| +| Full build (ms) | 302 | 826 | +| Per-file build (ms) | 2.1 | 5.8 | +| No-op rebuild (ms) | 5 | 6 | +| 1-file rebuild (ms) | 244 | 383 | +| Parse phase (ms) | 49 | 367 | +| Insert phase (ms) | 13.3 | 14.5 | +| Resolve phase (ms) | 21.8 | 24.6 | +| Edges phase (ms) | 38.1 | 41.6 | +| Structure phase (ms) | 3.0 | 5.3 | +| Roles phase (ms) | 3.1 | 4.0 | +| Complexity phase (ms) | 5.0 | 129.6 | + +### Incremental Benchmark + +| Metric | Native | WASM | +|--------|--------|------| +| Full build (ms) | 335 | 708 | +| No-op rebuild (ms) | 5 | 6 | +| 1-file rebuild (ms) | 233 | 381 | +| Import resolution — native batch (ms) | 4.7 | — | +| Import resolution — JS fallback (ms) | — | 4.8 | + +### Query Benchmark + +| Query | Native (ms) | WASM (ms) | +|-------|-------------|-----------| +| fnDeps depth 1 | 1.0 | 0.9 | +| fnDeps depth 3 | 1.0 | 1.0 | +| fnDeps depth 5 | 1.0 | 0.9 | +| fnImpact depth 1 | 0.9 | 0.9 | +| fnImpact depth 3 | 0.9 | 0.9 | +| fnImpact depth 5 | 0.9 | 0.9 | +| diff-impact (ms) | 14.9 | 16.1 | From 7b15596e5558d6ef77426638503e29af9759def0 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 03:39:39 -0700 Subject: [PATCH 3/7] docs: remove report from incorrect worktree path --- .../DOGFOOD_REPORT_v2.5.35-dev.26434e2.md | 437 ------------------ 1 file changed, 437 deletions(-) delete mode 100644 .claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md diff --git a/.claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md b/.claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md deleted file mode 100644 index 4b37dd8b..00000000 --- a/.claude/worktrees/fix-pr-173/generated/dogfood/DOGFOOD_REPORT_v2.5.35-dev.26434e2.md +++ /dev/null @@ -1,437 +0,0 @@ -# Dogfooding Report: @optave/codegraph@2.5.35-dev.26434e2 - -**Date:** 2026-03-02 -**Platform:** Windows 11 Pro (10.0.26200), x86_64, Node v22.18.0 -**Native binary:** @optave/codegraph-win32-x64-msvc@2.5.35-dev.26434e2 (manually extracted; npm install fails) -**Native internal version:** 0.1.0 -**Active engine:** native (v0.1.0) when available; wasm fallback -**Target repo:** codegraph itself (142 files, 912 nodes, 1671 edges) - ---- - -## 1. Setup & Installation - -### Install method -Dev builds are not on npm. Installed from GitHub release tarballs: -```bash -npm install https://github.com/optave/codegraph/releases/download/dev-v2.5.35-dev.26434e2/optave-codegraph-2.5.35-dev.26434e2.tgz -``` -Main package installed successfully. - -### Native binary issue -`npm install ` fails with `TypeError: Invalid Version:` in npm's arborist deduplication logic. **Workaround:** manually download and extract the tarball into `node_modules/@optave/codegraph-win32-x64-msvc/`. Any subsequent `npm install` removes the manually-extracted package. Filed as **#237**. - -### Native binary version mismatch -`codegraph info` reports native version as `0.1.0` while the package version is `2.5.35-dev.26434e2`. The internal version string in the Rust addon has not been updated — cosmetic only, no functional impact. - -### Verification -- `npx codegraph --version` → `2.5.35-dev.26434e2` (**PASS**) -- `npx codegraph info` → native engine available, active (**PASS**) - ---- - -## 2. Cold Start (Pre-Build) - -Tested all 35 commands/subcommands without a graph database present. - -| Command | Result | -|---------|--------| -| `query`, `impact`, `map`, `stats`, `deps`, `fn`, `fn-impact`, `context`, `explain`, `where`, `diff-impact`, `cycles`, `structure`, `hotspots`, `roles`, `export`, `path`, `audit`, `check`, `complexity`, `manifesto`, `communities`, `triage`, `co-change`, `flow`, `owners`, `batch`, `search` | PASS — "No codegraph database found. Run `codegraph build` first." | -| `models` | PASS — lists 7 embedding models | -| `info` | PASS — shows diagnostics | -| `--version` | PASS — `2.5.35-dev.26434e2` | -| `registry list` | PASS — lists registered repos | -| `branch-compare main HEAD` | PASS — "Not a git repository" (expected in temp dir) | -| `mcp` | PASS — responds to JSON-RPC initialize | - -**Result:** All 35 commands fail gracefully with helpful messages. Zero crashes. **PASS**. - ---- - -## 3. Full Command Sweep - -After building the graph (142 files, 912 nodes, 1671 edges, quality 86/100). - -### Query commands - -| Command | Status | Notes | -|---------|--------|-------| -| `query buildGraph` | PASS | Shows callers and callees correctly | -| `query buildGraph --json` | PASS | Valid JSON output | -| `query buildGraph -T` | PASS | Test files excluded | -| `query nonexistent` | PASS | "No results" message | -| `impact src/builder.js` | PASS | Shows 2-level impact chain | -| `map -n 5` | PASS | Top 5 most-connected nodes | -| `stats` | PASS | Full graph health overview | -| `stats --json` | PASS | Valid JSON with all metrics | -| `deps src/builder.js` | PASS | 5 imports, 7 importers | -| `deps nonexistent.js` | PASS | "No file matching" | -| `fn buildGraph --depth 2` | PASS | 16 calls, 19 callers | -| `fn buildGraph --kind class` | PASS | "No function/method/class matching" (correct: it's a function) | -| `fn buildGraph --kind invalidkind` | PASS | "Invalid kind. Valid: function, method, ..." | -| `fn nonexistent` | PASS | Graceful message | -| `fn-impact buildGraph -T` | PASS | 11 transitive dependents | -| `context buildGraph -T --no-source` | PASS | Full context without source | -| `explain src/builder.js` | PASS | File-level structural summary | -| `explain buildGraph` | PASS | Function-level explain | -| `where buildGraph` | PASS | Definition + usage sites | -| `where -f src/builder.js` | PASS | File overview mode | -| `path buildGraph openDb` | PASS | 1-hop path found | -| `flow buildGraph` | PASS | 22 nodes reached, 12 leaves | -| `roles -T` | PASS | 175 symbols classified | -| `audit src/builder.js -T` | PASS | 10 functions analyzed with health metrics | -| `audit buildGraph -T --json` | PASS | Valid JSON | -| `triage -T` | PASS | Risk-ranked audit queue | -| `triage -T --json` | PASS | Valid JSON | -| `complexity` | **NOTE** | "No complexity data found" when using graph built by different version; works after full rebuild | -| `manifesto -T` | PASS | 10 rules, all passed | -| `communities -T` | PASS | 40 communities detected | -| `cycles` | PASS | 1 file-level cycle (cochange→boundaries→queries) | -| `cycles --functions` | PASS | 4 function-level cycles | -| `hotspots --metric fan-in -n 5` | PASS | Top hotspots by fan-in | -| `hotspots --metric fan-out --level directory -n 5` | PASS | Directory-level | -| `structure --depth 1` | PASS | 4 directories shown | -| `structure .` | PASS | Full project structure (v2.2.0 bug was fixed) | -| `diff-impact main` | PASS | Shows impact of changes | -| `check main --cycles --blast-radius 50 --json` | PASS | All 4 predicates pass | -| `co-change` | PASS | "No co-change pairs found" | -| `owners` | PASS | "No CODEOWNERS file found" | -| `batch where buildGraph openDb` | PASS | 2/2 targets succeeded | -| `batch context buildGraph openDb collectFiles -T` | PASS | 3/3 succeeded | - -### Export commands - -| Format | Status | Notes | -|--------|--------|-------| -| `export -f dot` | PASS | Valid DOT output with subgraphs | -| `export -f mermaid` | PASS | Valid Mermaid flowchart | -| `export -f json` | PASS | Valid JSON with nodes and edges | -| `export --functions -f dot` | PASS | Function-level graph | - -### Search commands - -| Command | Status | Notes | -|---------|--------|-------| -| `search "build graph"` (no embeddings) | PASS | "No embeddings table found" with warning | -| `embed -m minilm` | PASS | 721 symbols embedded (384d) | -| `search "build dependency graph" -n 5` | PASS | Hybrid BM25 + semantic, top result is buildGraphologyGraph | -| `search "parse source files; extract function symbols" -n 3` | PASS | Multi-query RRF ranking works | -| `models` | PASS | Lists 7 models with dimensions and context | - -### Infrastructure commands - -| Command | Status | Notes | -|---------|--------|-------| -| `info` | PASS | Version, platform, engine info | -| `registry list` | PASS | Shows 3 registered repos | -| `registry list --json` | PASS | Valid JSON array | -| `snapshot save dogfood-test` | PASS | 744.0 KB snapshot | -| `snapshot list` | PASS | Shows snapshot with size and date | -| `snapshot restore dogfood-test` | PASS | Restored successfully | -| `snapshot delete dogfood-test` | PASS | Deleted | -| `mcp` (single-repo) | PASS | 30 tools, no `list_repos` | -| `mcp --multi-repo` | PASS | 31 tools, includes `list_repos` | - -### Programmatic API - -| Test | Status | Notes | -|------|--------|-------| -| `import * from '@optave/codegraph'` (ESM) | PASS | 131 exports | -| `require('@optave/codegraph')` (CJS) | FAIL (expected) | ESM-only package; `ERR_PACKAGE_PATH_NOT_EXPORTED` | -| Key exports: `buildGraph`, `loadConfig`, `openDb`, `findDbPath`, `contextData`, `explainData`, `whereData`, `fnDepsData`, `diffImpactData`, `statsData`, `isNativeAvailable`, `EXTENSIONS`, `IGNORE_DIRS`, `ALL_SYMBOL_KINDS`, `MODELS` | PASS | All present as functions/objects | - -### Edge Cases Tested - -| Scenario | Result | -|----------|--------| -| Non-existent symbol: `query nonexistent` | PASS — "No results" | -| Non-existent file: `deps nonexistent.js` | PASS — "No file matching" | -| Non-existent function: `fn nonexistent` | PASS — Graceful message | -| `structure .` (was bug in v2.2.0) | PASS — Fixed | -| `--json` on all supporting commands | PASS — Valid JSON | -| `--kind` with invalid kind | PASS — Lists valid kinds | -| `search` with no embeddings | PASS — Warning, not crash | -| Pipe output: `map --json` | PASS — Clean JSON | - ---- - -## 4. Rebuild & Staleness - -### Incremental no-op -After full build, running `build` again correctly detects "No changes detected. Graph is up to date." Tier 1 mtime+size check skips all 142 files. **PASS**. - -### Incremental with change -Modified `src/logger.js`, ran `build`: -- Tier 1 detected 1 file needing hash check -- Tier 2 confirmed 1 actually changed -- Re-parsed 32 files (1 changed + 31 reverse-deps) -- **BUG:** `[codegraph WARN] Skipping src: EISDIR` — the `src` directory is leaking into the re-parse set (#235) -- **BUG:** Edge count after incremental (676) does not match full rebuild (1671) (#236) - -### Full rebuild (--no-incremental) -Produces consistent results: 912 nodes, 1516 edges (build output), 1671 edges (stats). The difference is because stats counts all edge types (calls + imports + contains + reexports). - -### Embed → rebuild → search -- Embedded 721 symbols with minilm (384d) -- Modified file, rebuilt incrementally -- Search still returns results — no stale embedding crash -- Recall quality is reasonable for minilm model - -### Engine change detection -When engine changes between builds (native → wasm), correctly warns: -``` -Engine changed (native → wasm). Consider rebuilding with --no-incremental for consistency. -``` -**PASS**. - ---- - -## 5. Engine Comparison - -### Build performance - -| Metric | Native | WASM | Speedup | -|--------|--------|------|---------| -| Full build (ms) | 302 | 826 | **2.7x** | -| No-op rebuild (ms) | 5 | 6 | 1.2x | -| 1-file rebuild (ms) | 233 | 381 | 1.6x | -| Parse phase (ms) | 49 | 367 | **7.5x** | -| Complexity phase (ms) | 5 | 130 | **26x** | -| Insert phase (ms) | 13 | 15 | 1.1x | -| Resolve phase (ms) | 22 | 25 | 1.1x | -| Edges phase (ms) | 38 | 42 | 1.1x | - -### Graph parity - -| Metric | Native | WASM | Match | -|--------|--------|------|-------| -| Nodes | 912 | 912 | YES | -| Edges | 1671 | 1671 | YES | -| Calls | 1253 | 1253 | YES | -| Files | 142 | 142 | YES | -| Quality score | 86 | 86 | YES | -| Call confidence | 98.3% | 98.3% | YES | -| Caller coverage | 67.9% | 67.9% | YES | -| DB size | 757,760 | 757,760 | YES | - -**Perfect parity** between native and WASM engines. All metrics match exactly. - -### Query performance - -| Query | Native (ms) | WASM (ms) | -|-------|-------------|-----------| -| fnDeps depth 1 | 1.0 | 0.9 | -| fnDeps depth 3 | 1.0 | 1.0 | -| fnDeps depth 5 | 1.0 | 0.9 | -| fnImpact depth 1 | 0.9 | 0.9 | -| fnImpact depth 3 | 0.9 | 0.9 | -| fnImpact depth 5 | 0.9 | 0.9 | -| diff-impact | 14.9 | 16.1 | - -Query latencies are near-identical (sub-millisecond) — queries are SQL-based, not engine-dependent. - -### Import resolution - -| Resolver | Time (ms) | Per-import (ms) | -|----------|-----------|-----------------| -| Native batch | 4.7 | ~0 | -| JS fallback | 4.8 | ~0 | - -Both resolvers produce identical results at comparable speed for this codebase size. - ---- - -## 6. Release-Specific Tests (v2.6.0) - -This dev build includes all v2.6.0 features. - -| Feature/Fix | Test | Result | -|-------------|------|--------| -| `check` command — CI validation predicates | Tested `--cycles`, `--blast-radius 50`, `--signatures`, `--boundaries`, `--json` | PASS — all predicates evaluated, JSON valid | -| `audit` command — composite risk report | Tested on file target and function target, with `--json` | PASS — combines explain + impact + health | -| `triage` command — risk audit queue | Tested `-T --json` | PASS — ranked by composite risk score | -| `snapshot` save/restore/list/delete | Full lifecycle tested | PASS | -| `owners` — CODEOWNERS integration | Tested; no CODEOWNERS file in repo | PASS — graceful "No CODEOWNERS file found" | -| Architecture boundary rules | `manifesto -T` includes `boundaries` rule | PASS — boundaries rule passes | -| Onion architecture preset | Preset available in manifesto | PASS | -| Hybrid BM25 + semantic search | `search` uses combined ranking when FTS5 available | PASS — shows BM25 rank + semantic rank | -| Batch querying | `batch where`, `batch context` with multiple targets | PASS — all targets processed | -| `check` as MCP tool | Verified in `tools/list` response | PASS — present in 30 single-repo tools | -| CODEOWNERS parse cache fix | No CODEOWNERS in repo; cannot deeply test | N/A | -| Dev build versioning | `--version` returns `2.5.35-dev.26434e2` | PASS | - ---- - -## 7. Additional Testing - -### MCP Server -- Single-repo mode: 30 tools exposed, no `list_repos`, no `repo` parameter on tools. **PASS**. -- Multi-repo mode (`--multi-repo`): 31 tools, `list_repos` present. **PASS**. -- JSON-RPC `initialize` response is well-formed. **PASS**. - -### Programmatic API -- 131 exports verified via ESM `import *`. -- All critical exports are functions/objects of the expected types. -- CJS `require()` correctly fails (ESM-only package). **PASS**. - -### Config -- `.codegraphrc.json` is loaded when present (confirmed via `--verbose` output: "Loaded config from ...\.codegraphrc.json"). **PASS**. - -### Registry -- `registry list` shows registered repos with paths and timestamps. -- `registry list --json` produces valid JSON array. -- Repos auto-register on `build`. **PASS**. - ---- - -## 8. Bugs Found - -### BUG 1: EISDIR warning during incremental rebuild (Medium) -- **Issue:** [#235](https://github.com/optave/codegraph/issues/235) -- **PR:** Open — not fixed in this session -- **Symptoms:** `[codegraph WARN] Skipping src: EISDIR: illegal operation on a directory, read` during incremental rebuild after modifying a single source file -- **Root cause:** The `src` directory node leaks into the re-parse file set during reverse-dep computation -- **Impact:** Cosmetic warning; the directory is skipped and build completes. One fewer file is parsed than expected. - -### BUG 2: Incremental rebuild edge count mismatch (High) -- **Issue:** [#236](https://github.com/optave/codegraph/issues/236) -- **PR:** Open — needs investigation -- **Symptoms:** After a 1-file incremental rebuild, `stats` reports a different edge count than a full rebuild of the same codebase. Full build: 1671 edges. Incremental: varies (676 in one test, 2660 in another) -- **Root cause:** The incremental path re-parses only changed files + reverse-deps. Edge cleanup/insertion may not preserve edges from unchanged files correctly. -- **Impact:** Queries after incremental rebuilds may return incomplete results. - -### BUG 3: Dev build native binary tarball install fails via npm (Medium) -- **Issue:** [#237](https://github.com/optave/codegraph/issues/237) -- **PR:** Open — needs investigation -- **Symptoms:** `npm install ` fails with `TypeError: Invalid Version:` in npm's arborist -- **Root cause:** npm's semver parser may not handle the `2.5.35-dev.26434e2` version format during deduplication -- **Impact:** Dev build users must manually extract the native binary tarball - -### MINOR: Native addon version string is `0.1.0` -- Not filed as issue — cosmetic. The Rust addon's internal version string hasn't been updated to match the package version. `codegraph info` shows `Native version: 0.1.0`. - ---- - -## 9. Suggestions for Improvement - -### 9.1 Incremental rebuild verification -Add an assertion or warning in the build process that compares the post-incremental edge/node count against the previous full-build count. If they diverge significantly, suggest `--no-incremental`. - -### 9.2 Embedding benchmark should declare `@huggingface/transformers` as a devDependency -The embedding benchmark script fails because `@huggingface/transformers` is an optional dep that doesn't auto-install. Consider making it a devDependency so benchmark scripts work out of the box. - -### 9.3 `complexity` should warn when data is missing -When `complexity` returns "No complexity data found" but a graph exists, it should suggest `build --no-incremental` to populate the data, rather than implying no graph exists. - -### 9.4 Dev build install documentation -The SKILL.md documents the manual tarball installation, but a note in the README or release notes about the `npm install ` failure would help users. - ---- - -## 10. Testing Plan - -### General Testing Plan (Any Release) -- [ ] Install from published package (npm or tarball) -- [ ] Verify `--version` and `info` output -- [ ] Cold start: all commands without graph produce helpful errors -- [ ] Build graph on codegraph itself -- [ ] Full command sweep with `--json` and `-T` flags -- [ ] Incremental no-op rebuild -- [ ] Incremental 1-file rebuild: verify edge/node counts match full rebuild -- [ ] Engine comparison: native vs WASM parity -- [ ] Export in all formats (DOT, Mermaid, JSON) -- [ ] Embed + search pipeline -- [ ] MCP server single-repo and multi-repo tool counts -- [ ] Programmatic API exports -- [ ] Edge cases: non-existent symbols/files, invalid kinds -- [ ] Run all 4 benchmark scripts -- [ ] Snapshot save/restore lifecycle - -### Release-Specific Testing Plan (v2.6.0) -- [x] `check` command with all predicates (`--cycles`, `--blast-radius`, `--signatures`, `--boundaries`) -- [x] `audit` command on file and function targets -- [x] `triage` command with risk ranking -- [x] `snapshot` full lifecycle (save, list, restore, delete) -- [x] `owners` command (with and without CODEOWNERS file) -- [x] `manifesto` boundary rules including onion preset -- [x] Hybrid BM25 + semantic search -- [x] `batch` command with multiple targets -- [x] `check` in MCP tool list -- [x] Dev build version format in `--version` output - -### Proposed Additional Tests -- Watch mode: start watcher, modify file, verify incremental update, query, stop watcher -- Concurrent builds: two build processes simultaneously -- Config override testing: `.codegraphrc.json` with custom `include`/`exclude`, `aliases`, `query.defaultDepth` -- Registry add/remove/prune lifecycle from scratch -- Cross-repo queries via MCP multi-repo mode -- `apiKeyCommand` credential resolution with a test `echo` command -- Database migration path: open graph.db from an older version -- `embed` with different models and verify dimension mismatch handling - ---- - -## 11. Overall Assessment - -Codegraph v2.5.35-dev.26434e2 (v2.6.0-rc) is a solid release with significant new capabilities. The `check`, `audit`, `triage`, and `snapshot` commands all work correctly and produce well-structured output. Hybrid search with BM25 + semantic ranking is a meaningful improvement. The MCP server correctly differentiates single-repo (30 tools) and multi-repo (31 tools) modes. - -**Native/WASM parity is perfect** — both engines produce identical graphs with identical metrics. Native is 2.7x faster overall and 26x faster for complexity analysis. - -The three bugs found are: -1. **EISDIR during incremental rebuild** — a directory leaks into the parse set (medium severity, cosmetic warning) -2. **Incremental edge count mismatch** — the most concerning bug, as it means incremental builds may produce incomplete graphs (high severity) -3. **Dev build native binary install fails** — npm's arborist can't handle the tarball install, requiring manual extraction (medium severity, dev workflow only) - -The incremental edge count bug (#236) is the most impactful finding and should be investigated before a stable release. The other issues are lower priority. - -**Rating: 7.5/10** — Strong feature set, perfect engine parity, but the incremental rebuild bug undermines trust in the most common build path. - ---- - -## 12. Issues & PRs Created - -| Type | Number | Title | Status | -|------|--------|-------|--------| -| Issue | [#235](https://github.com/optave/codegraph/issues/235) | bug: EISDIR warning during incremental rebuild | open | -| Issue | [#236](https://github.com/optave/codegraph/issues/236) | bug: incremental rebuild produces different edge count than full rebuild | open | -| Issue | [#237](https://github.com/optave/codegraph/issues/237) | bug: dev build native binary tarball cannot be installed via npm | open | - -## 13. Performance Benchmarks - -### Build Benchmark - -| Metric | Native | WASM | -|--------|--------|------| -| Full build (ms) | 302 | 826 | -| Per-file build (ms) | 2.1 | 5.8 | -| No-op rebuild (ms) | 5 | 6 | -| 1-file rebuild (ms) | 244 | 383 | -| Parse phase (ms) | 49 | 367 | -| Insert phase (ms) | 13.3 | 14.5 | -| Resolve phase (ms) | 21.8 | 24.6 | -| Edges phase (ms) | 38.1 | 41.6 | -| Structure phase (ms) | 3.0 | 5.3 | -| Roles phase (ms) | 3.1 | 4.0 | -| Complexity phase (ms) | 5.0 | 129.6 | - -### Incremental Benchmark - -| Metric | Native | WASM | -|--------|--------|------| -| Full build (ms) | 335 | 708 | -| No-op rebuild (ms) | 5 | 6 | -| 1-file rebuild (ms) | 233 | 381 | -| Import resolution — native batch (ms) | 4.7 | — | -| Import resolution — JS fallback (ms) | — | 4.8 | - -### Query Benchmark - -| Query | Native (ms) | WASM (ms) | -|-------|-------------|-----------| -| fnDeps depth 1 | 1.0 | 0.9 | -| fnDeps depth 3 | 1.0 | 1.0 | -| fnDeps depth 5 | 1.0 | 0.9 | -| fnImpact depth 1 | 0.9 | 0.9 | -| fnImpact depth 3 | 0.9 | 0.9 | -| fnImpact depth 5 | 0.9 | 0.9 | -| diff-impact (ms) | 14.9 | 16.1 | From df0724d532148800ff0c85ffcd4baedb3ae71502 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 03:46:22 -0700 Subject: [PATCH 4/7] docs: move v2.5.0 dogfood report to generated/dogfood/ --- generated/{ => dogfood}/DOGFOOD_REPORT_v2.5.0.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename generated/{ => dogfood}/DOGFOOD_REPORT_v2.5.0.md (100%) diff --git a/generated/DOGFOOD_REPORT_v2.5.0.md b/generated/dogfood/DOGFOOD_REPORT_v2.5.0.md similarity index 100% rename from generated/DOGFOOD_REPORT_v2.5.0.md rename to generated/dogfood/DOGFOOD_REPORT_v2.5.0.md From 658d4bae57248983d45f6d8d5f10d30a7acdac49 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 03:59:22 -0700 Subject: [PATCH 5/7] fix: incremental build verification, complexity warnings, and dev build docs - Add node/edge count drift detection after incremental builds (>20% warns to use --no-incremental), persisting counts in build_meta - Improve complexity command: when data is missing but graph exists, suggest --no-incremental instead of implying no graph exists - Add @huggingface/transformers as devDependency so embedding benchmarks work out of the box - Document dev build tarball installation in README (npm install fails for optional platform deps) Impact: 3 functions changed, 5 affected --- README.md | 2 ++ package.json | 1 + src/builder.js | 21 +++++++++++++++++++++ src/complexity.js | 33 ++++++++++++++++++++++++++++----- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 52e679eb..74d5b78e 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,8 @@ git clone https://github.com/optave/codegraph.git cd codegraph && npm install && npm link ``` +> **Dev builds:** Pre-release tarballs are attached to [GitHub Releases](https://github.com/optave/codegraph/releases). Install with `npm install -g `. Note that `npm install -g ` does not work because npm cannot resolve optional platform-specific dependencies from a URL — download the `.tgz` first, then install from the local file. + ### For AI agents Add codegraph to your agent's instructions (e.g. `CLAUDE.md`): diff --git a/package.json b/package.json index 1cbbcbd3..02987842 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ }, "devDependencies": { "@biomejs/biome": "^2.4.4", + "@huggingface/transformers": "^3.8.1", "@commitlint/cli": "^20.4", "@commitlint/config-conventional": "^20.0", "@tree-sitter-grammars/tree-sitter-hcl": "^1.2.0", diff --git a/src/builder.js b/src/builder.js index e194404f..e2d62918 100644 --- a/src/builder.js +++ b/src/builder.js @@ -1046,6 +1046,25 @@ export async function buildGraph(rootDir, opts = {}) { info(`Graph built: ${nodeCount} nodes, ${edgeCount} edges`); info(`Stored in ${dbPath}`); + // Verify incremental build didn't diverge significantly from previous counts + if (!isFullBuild) { + const prevNodes = getBuildMeta(db, 'node_count'); + const prevEdges = getBuildMeta(db, 'edge_count'); + if (prevNodes && prevEdges) { + const prevN = Number(prevNodes); + const prevE = Number(prevEdges); + if (prevN > 0) { + const nodeDrift = Math.abs(nodeCount - prevN) / prevN; + const edgeDrift = prevE > 0 ? Math.abs(edgeCount - prevE) / prevE : 0; + if (nodeDrift > 0.2 || edgeDrift > 0.2) { + warn( + `Incremental build diverged significantly from previous counts (nodes: ${prevN}→${nodeCount}, edges: ${prevE}→${edgeCount}). Consider rebuilding with --no-incremental.`, + ); + } + } + } + } + // Warn about orphaned embeddings that no longer match any node if (hasEmbeddings) { try { @@ -1069,6 +1088,8 @@ export async function buildGraph(rootDir, opts = {}) { engine_version: engineVersion || '', codegraph_version: CODEGRAPH_VERSION, built_at: new Date().toISOString(), + node_count: nodeCount, + edge_count: edgeCount, }); } catch (err) { warn(`Failed to write build metadata: ${err.message}`); diff --git a/src/complexity.js b/src/complexity.js index 00e38b4d..f97cb616 100644 --- a/src/complexity.js +++ b/src/complexity.js @@ -1891,8 +1891,15 @@ export function complexityData(customDbPath, opts = {}) { ) .all(...params); } catch { + // Check if graph has nodes even though complexity table is missing/empty + let hasGraph = false; + try { + hasGraph = db.prepare('SELECT COUNT(*) as c FROM nodes').get().c > 0; + } catch { + /* ignore */ + } db.close(); - return { functions: [], summary: null, thresholds }; + return { functions: [], summary: null, thresholds, hasGraph }; } // Post-filter test files if needed (belt-and-suspenders for isTestFile) @@ -1978,8 +1985,18 @@ export function complexityData(customDbPath, opts = {}) { /* ignore */ } + // When summary is null (no complexity rows), check if graph has nodes + let hasGraph = false; + if (summary === null) { + try { + hasGraph = db.prepare('SELECT COUNT(*) as c FROM nodes').get().c > 0; + } catch { + /* ignore */ + } + } + db.close(); - const base = { functions, summary, thresholds }; + const base = { functions, summary, thresholds, hasGraph }; return paginateResult(base, 'functions', { limit: opts.limit, offset: opts.offset }); } @@ -2080,9 +2097,15 @@ export function complexity(customDbPath, opts = {}) { if (data.functions.length === 0) { if (data.summary === null) { - console.log( - '\nNo complexity data found. Run "codegraph build" first to analyze your codebase.\n', - ); + if (data.hasGraph) { + console.log( + '\nNo complexity data found, but a graph exists. Run "codegraph build --no-incremental" to populate complexity metrics.\n', + ); + } else { + console.log( + '\nNo complexity data found. Run "codegraph build" first to analyze your codebase.\n', + ); + } } else { console.log('\nNo functions match the given filters.\n'); } From 8f99468a3f9f86465576777971c76c09ce9ed552 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 04:09:38 -0700 Subject: [PATCH 6/7] fix: configurable drift threshold, drift logging, and lock file sync - Add build.driftThreshold to config defaults (0.2) so the 20% incremental build drift threshold is user-configurable - Include actual drift percentages and threshold in warning message for easier debugging - Regenerate package-lock.json to include @huggingface/transformers devDependency (fixes License Compliance Scan CI failure) Impact: 1 functions changed, 1 affected --- package-lock.json | 1091 ++++++++++++++++++++++++++++++++++++++++++--- src/builder.js | 43 +- src/config.js | 1 + 3 files changed, 1079 insertions(+), 56 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82ddd6d2..4991058e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "2.6.0", "license": "Apache-2.0", "dependencies": { - "@modelcontextprotocol/sdk": "1.27.1", "better-sqlite3": "^12.6.2", "commander": "^14.0.3", "graphology": "^0.25.4", @@ -23,6 +22,7 @@ "@biomejs/biome": "^2.4.4", "@commitlint/cli": "^20.4", "@commitlint/config-conventional": "^20.0", + "@huggingface/transformers": "^3.8.1", "@tree-sitter-grammars/tree-sitter-hcl": "^1.2.0", "@vitest/coverage-v8": "^4.0.18", "commit-and-tag-version": "^12.5", @@ -572,6 +572,17 @@ "node": ">=v18" } }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -1027,6 +1038,29 @@ "hono": "^4" } }, + "node_modules/@huggingface/jinja": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.5.tgz", + "integrity": "sha512-xRlzazC+QZwr6z4ixEqYHo9fgwhTZ3xNSdljlKfUFGZSdlvt166DljRELFUfFytlYOYvo3vTisA/AFOuOAzFQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@huggingface/transformers": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.8.1.tgz", + "integrity": "sha512-tsTk4zVjImqdqjS8/AOZg2yNLd1z9S5v+7oUPpXaasDRwEDhB+xnglK1k5cad26lL5/ZIaeREgWWy0bs9y9pPA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@huggingface/jinja": "^0.5.3", + "onnxruntime-node": "1.21.0", + "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", + "sharp": "^0.34.1" + } + }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -1037,6 +1071,509 @@ "node": ">=6.9.0" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -1107,56 +1644,90 @@ } }, "node_modules/@optave/codegraph-darwin-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@optave/codegraph-darwin-arm64/-/codegraph-darwin-arm64-2.5.1.tgz", - "integrity": "sha512-MNy8TUj606F5F7lHEio0HxWaWeDvG4xP37+DoWiaQtKaNwCYDfU58AopM63v+Y5elPtNwXY7QynP1RoUsCTZ5g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ] + "optional": true }, "node_modules/@optave/codegraph-darwin-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@optave/codegraph-darwin-x64/-/codegraph-darwin-x64-2.5.1.tgz", - "integrity": "sha512-FW4ZtKDz/CPrE5TifzpSyCmGgfwmkejHYGg3VLP7sMzvBw7ZvIOKgojOwyzRuLo/k69zUZKfhKi99XDGs/Kd4w==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ] + "optional": true + }, + "node_modules/@optave/codegraph-linux-x64-gnu": { + "optional": true + }, + "node_modules/@optave/codegraph-win32-x64-msvc": { + "optional": true + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "dev": true, + "license": "BSD-3-Clause" }, - "node_modules/@optave/codegraph-linux-x64-gnu": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@optave/codegraph-linux-x64-gnu/-/codegraph-linux-x64-gnu-2.5.1.tgz", - "integrity": "sha512-CcKOaGqJbq5BteZYSoeuhglGWJRdJKgFfL1xYuKNmBOS2sluGwwy0bVAX0xGBbxasC7kF2mGdGe/ICj4jNOuLA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ] + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" }, - "node_modules/@optave/codegraph-win32-x64-msvc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@optave/codegraph-win32-x64-msvc/-/codegraph-win32-x64-msvc-2.5.1.tgz", - "integrity": "sha512-IUGdiJLUHVeGfxIcAE90/dS4fJUjNvvQrDgIziYyWpKLi0UaX4XHGPac0k0rPxo6d8pAeFxTO6GeKsk7S2l9Vg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ] + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.58.0", @@ -1586,7 +2157,6 @@ "integrity": "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.18.0" } @@ -1954,6 +2524,14 @@ "url": "https://opencollective.com/express" } }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2085,6 +2663,16 @@ "node": ">=18" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3039,6 +3627,42 @@ "node": ">=4.0.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3078,6 +3702,13 @@ "node": ">=8" } }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT" + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -3243,8 +3874,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.4" } @@ -3253,8 +3884,8 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.4" } @@ -3279,6 +3910,13 @@ "node": ">= 0.4" } }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", @@ -3338,6 +3976,19 @@ "license": "MIT", "optional": true }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -3587,6 +4238,13 @@ "url": "https://opencollective.com/express" } }, + "node_modules/flatbuffers": { + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3816,6 +4474,24 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, "node_modules/global-directory": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", @@ -3842,12 +4518,29 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.4" }, @@ -3919,6 +4612,13 @@ "graphology-types": ">=0.23.0" } }, + "node_modules/guid-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", + "dev": true, + "license": "ISC" + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -3961,6 +4661,19 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -4492,6 +5205,13 @@ "dev": true, "license": "MIT" }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4563,6 +5283,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -4871,6 +5604,29 @@ "node": ">= 6" } }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -5018,6 +5774,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/obliterator": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", @@ -5057,6 +5823,53 @@ "wrappy": "1" } }, + "node_modules/onnxruntime-common": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", + "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/onnxruntime-node": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", + "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "os": [ + "win32", + "darwin", + "linux" + ], + "dependencies": { + "global-agent": "^3.0.0", + "onnxruntime-common": "1.21.0", + "tar": "^7.0.1" + } + }, + "node_modules/onnxruntime-web": { + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatbuffers": "^25.1.24", + "guid-typescript": "^1.0.9", + "long": "^5.2.3", + "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", + "platform": "^1.3.6", + "protobufjs": "^7.2.4" + } + }, + "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", + "dev": true, + "license": "MIT" + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -5216,6 +6029,13 @@ "node": ">=16.20.0" } }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "dev": true, + "license": "MIT" + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -5279,6 +6099,31 @@ "dev": true, "license": "MIT" }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -5581,6 +6426,24 @@ "node": ">=8" } }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/rollup": { "version": "4.58.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.58.0.tgz", @@ -5682,6 +6545,13 @@ "node": ">=10" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, "node_modules/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", @@ -5709,6 +6579,22 @@ "url": "https://opencollective.com/express" } }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/serve-static": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", @@ -5736,6 +6622,51 @@ "license": "ISC", "optional": true }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5966,6 +6897,13 @@ "node": ">= 10.x" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -6098,6 +7036,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", + "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -6462,6 +7417,14 @@ "node": ">=8" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6474,6 +7437,19 @@ "node": "*" } }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -6530,8 +7506,7 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/unpipe": { "version": "1.0.0", @@ -6813,6 +7788,16 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/yaml": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", diff --git a/src/builder.js b/src/builder.js index 1e17196b..3b715ad8 100644 --- a/src/builder.js +++ b/src/builder.js @@ -460,7 +460,7 @@ export async function buildGraph(rootDir, opts = {}) { SELECT DISTINCT n_src.file FROM edges e JOIN nodes n_src ON e.source_id = n_src.id JOIN nodes n_tgt ON e.target_id = n_tgt.id - WHERE n_tgt.file = ? AND n_src.file != n_tgt.file + WHERE n_tgt.file = ? AND n_src.file != n_tgt.file AND n_src.kind != 'directory' `); for (const relPath of changedRelPaths) { for (const row of findReverseDeps.all(relPath)) { @@ -687,6 +687,42 @@ export async function buildGraph(rootDir, opts = {}) { } } + // For incremental builds, load unchanged barrel files into reexportMap + // so barrel-resolved import/call edges aren't dropped for reverse-dep files + if (!isFullBuild) { + const barrelCandidates = db + .prepare( + `SELECT DISTINCT n1.file FROM edges e + JOIN nodes n1 ON e.source_id = n1.id + WHERE e.kind = 'reexports' AND n1.kind = 'file'`, + ) + .all(); + for (const { file: relPath } of barrelCandidates) { + if (fileSymbols.has(relPath)) continue; + const absPath = path.join(rootDir, relPath); + try { + const symbols = await parseFilesAuto([absPath], rootDir, engineOpts); + const fileSym = symbols.get(relPath); + if (fileSym) { + fileSymbols.set(relPath, fileSym); + const reexports = fileSym.imports.filter((imp) => imp.reexport); + if (reexports.length > 0) { + reexportMap.set( + relPath, + reexports.map((imp) => ({ + source: getResolved(absPath, imp.source), + names: imp.names, + wildcardReexport: imp.wildcardReexport || false, + })), + ); + } + } + } catch { + /* skip if unreadable */ + } + } + } + function isBarrelFile(relPath) { const symbols = fileSymbols.get(relPath); if (!symbols) return false; @@ -1056,9 +1092,10 @@ export async function buildGraph(rootDir, opts = {}) { if (prevN > 0) { const nodeDrift = Math.abs(nodeCount - prevN) / prevN; const edgeDrift = prevE > 0 ? Math.abs(edgeCount - prevE) / prevE : 0; - if (nodeDrift > 0.2 || edgeDrift > 0.2) { + const driftThreshold = config.build?.driftThreshold ?? 0.2; + if (nodeDrift > driftThreshold || edgeDrift > driftThreshold) { warn( - `Incremental build diverged significantly from previous counts (nodes: ${prevN}→${nodeCount}, edges: ${prevE}→${edgeCount}). Consider rebuilding with --no-incremental.`, + `Incremental build diverged significantly from previous counts (nodes: ${prevN}→${nodeCount} [${(nodeDrift * 100).toFixed(1)}%], edges: ${prevE}→${edgeCount} [${(edgeDrift * 100).toFixed(1)}%], threshold: ${(driftThreshold * 100).toFixed(0)}%). Consider rebuilding with --no-incremental.`, ); } } diff --git a/src/config.js b/src/config.js index 9a3505df..1ab75e47 100644 --- a/src/config.js +++ b/src/config.js @@ -14,6 +14,7 @@ export const DEFAULTS = { build: { incremental: true, dbPath: '.codegraph/graph.db', + driftThreshold: 0.2, }, query: { defaultDepth: 3, From 1216acc6220dedea13c2c1b1ecfa3e401a750599 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Mon, 2 Mar 2026 04:13:32 -0700 Subject: [PATCH 7/7] fix(builder): incremental rebuild EISDIR, edge parity, dev tarball, native version - filter directory nodes from reverse-deps query to prevent EISDIR (#235) - load unchanged barrel files into reexportMap so barrel-resolved edges aren't dropped during incremental rebuilds (#236) - add --strip flag to sync-native-versions.js removing platform optionalDependencies in dev builds, fixing npm install failures (#237) - sync Cargo.toml version with package.json and automate via version script - add barrel-project fixture and incremental-parity test Impact: 4 functions changed, 1 affected --- .github/workflows/publish.yml | 2 +- crates/codegraph-core/Cargo.toml | 2 +- scripts/sync-native-versions.js | 24 ++++- src/builder.js | 8 +- tests/fixtures/barrel-project/app.js | 5 + tests/fixtures/barrel-project/src/index.js | 1 + tests/fixtures/barrel-project/src/math.js | 7 ++ tests/integration/incremental-parity.test.js | 106 +++++++++++++++++++ 8 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/barrel-project/app.js create mode 100644 tests/fixtures/barrel-project/src/index.js create mode 100644 tests/fixtures/barrel-project/src/math.js create mode 100644 tests/integration/incremental-parity.test.js diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2b755614..f76fbdbd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -170,7 +170,7 @@ jobs: VERSION: ${{ needs.compute-version.outputs.version }} run: | npm version "$VERSION" --no-git-tag-version --allow-same-version - node scripts/sync-native-versions.js + node scripts/sync-native-versions.js --strip echo "Packaging version $VERSION" - name: Disable prepublishOnly diff --git a/crates/codegraph-core/Cargo.toml b/crates/codegraph-core/Cargo.toml index 65460fa9..36aab6b2 100644 --- a/crates/codegraph-core/Cargo.toml +++ b/crates/codegraph-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codegraph-core" -version = "0.1.0" +version = "2.6.0" edition = "2021" license = "Apache-2.0" diff --git a/scripts/sync-native-versions.js b/scripts/sync-native-versions.js index 9f6943a4..d4ae9100 100644 --- a/scripts/sync-native-versions.js +++ b/scripts/sync-native-versions.js @@ -2,16 +2,38 @@ /** * Syncs @optave/codegraph-* optionalDependencies versions to match the root version. * Runs automatically via the npm "version" lifecycle hook. + * + * Flags: + * --strip Remove platform @optave/codegraph-* entries from optionalDependencies + * (used by publish-dev to avoid npm resolution failures for dev versions) */ import { readFileSync, writeFileSync } from 'node:fs'; +const strip = process.argv.includes('--strip'); + const pkg = JSON.parse(readFileSync('package.json', 'utf8')); const v = pkg.version; for (const key of Object.keys(pkg.optionalDependencies)) { if (key.startsWith('@optave/codegraph-')) { - pkg.optionalDependencies[key] = v; + if (strip) { + delete pkg.optionalDependencies[key]; + } else { + pkg.optionalDependencies[key] = v; + } } } writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); + +// Also sync Cargo.toml version (used by the native engine's engine_version()) +if (!strip) { + const cargoPath = 'crates/codegraph-core/Cargo.toml'; + try { + let cargo = readFileSync(cargoPath, 'utf8'); + cargo = cargo.replace(/^version\s*=\s*"[^"]*"/m, `version = "${v}"`); + writeFileSync(cargoPath, cargo); + } catch { + /* skip if Cargo.toml doesn't exist */ + } +} diff --git a/src/builder.js b/src/builder.js index 3b715ad8..91ab5db6 100644 --- a/src/builder.js +++ b/src/builder.js @@ -688,7 +688,10 @@ export async function buildGraph(rootDir, opts = {}) { } // For incremental builds, load unchanged barrel files into reexportMap - // so barrel-resolved import/call edges aren't dropped for reverse-dep files + // so barrel-resolved import/call edges aren't dropped for reverse-dep files. + // These files are loaded only for resolution — they must NOT be iterated + // in the edge-building loop (their existing edges are still in the DB). + const barrelOnlyFiles = new Set(); if (!isFullBuild) { const barrelCandidates = db .prepare( @@ -705,6 +708,7 @@ export async function buildGraph(rootDir, opts = {}) { const fileSym = symbols.get(relPath); if (fileSym) { fileSymbols.set(relPath, fileSym); + barrelOnlyFiles.add(relPath); const reexports = fileSym.imports.filter((imp) => imp.reexport); if (reexports.length > 0) { reexportMap.set( @@ -788,6 +792,8 @@ export async function buildGraph(rootDir, opts = {}) { let edgeCount = 0; const buildEdges = db.transaction(() => { for (const [relPath, symbols] of fileSymbols) { + // Skip barrel-only files — loaded for resolution, edges already in DB + if (barrelOnlyFiles.has(relPath)) continue; const fileNodeRow = getNodeId.get(relPath, 'file', relPath, 0); if (!fileNodeRow) continue; const fileNodeId = fileNodeRow.id; diff --git a/tests/fixtures/barrel-project/app.js b/tests/fixtures/barrel-project/app.js new file mode 100644 index 00000000..b086a27f --- /dev/null +++ b/tests/fixtures/barrel-project/app.js @@ -0,0 +1,5 @@ +import { add, multiply } from './src/index.js'; + +export function compute(x, y) { + return add(x, multiply(x, y)); +} diff --git a/tests/fixtures/barrel-project/src/index.js b/tests/fixtures/barrel-project/src/index.js new file mode 100644 index 00000000..f747f3d4 --- /dev/null +++ b/tests/fixtures/barrel-project/src/index.js @@ -0,0 +1 @@ +export { add, multiply } from './math.js'; diff --git a/tests/fixtures/barrel-project/src/math.js b/tests/fixtures/barrel-project/src/math.js new file mode 100644 index 00000000..e059eb58 --- /dev/null +++ b/tests/fixtures/barrel-project/src/math.js @@ -0,0 +1,7 @@ +export function add(a, b) { + return a + b; +} + +export function multiply(a, b) { + return a * b; +} diff --git a/tests/integration/incremental-parity.test.js b/tests/integration/incremental-parity.test.js new file mode 100644 index 00000000..a109471f --- /dev/null +++ b/tests/integration/incremental-parity.test.js @@ -0,0 +1,106 @@ +/** + * Incremental build parity test. + * + * Verifies that an incremental rebuild after touching a single file + * produces the same nodes and edges as a full build. + * Uses a barrel-file fixture to exercise re-export resolution. + */ + +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import Database from 'better-sqlite3'; +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { buildGraph } from '../../src/builder.js'; + +const FIXTURE_DIR = path.join(import.meta.dirname, '..', 'fixtures', 'barrel-project'); + +function copyDirSync(src, dest) { + fs.mkdirSync(dest, { recursive: true }); + for (const entry of fs.readdirSync(src, { withFileTypes: true })) { + const s = path.join(src, entry.name); + const d = path.join(dest, entry.name); + if (entry.isDirectory()) copyDirSync(s, d); + else fs.copyFileSync(s, d); + } +} + +function readGraph(dbPath) { + const db = new Database(dbPath, { readonly: true }); + const nodes = db + .prepare('SELECT name, kind, file, line FROM nodes ORDER BY name, kind, file, line') + .all(); + const edges = db + .prepare( + `SELECT n1.name AS source_name, n2.name AS target_name, e.kind + FROM edges e + JOIN nodes n1 ON e.source_id = n1.id + JOIN nodes n2 ON e.target_id = n2.id + ORDER BY n1.name, n2.name, e.kind`, + ) + .all(); + db.close(); + return { nodes, edges }; +} + +describe('Incremental build parity: full vs incremental', () => { + let fullDir; + let incrDir; + let tmpBase; + + beforeAll(async () => { + tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-incr-parity-')); + fullDir = path.join(tmpBase, 'full'); + incrDir = path.join(tmpBase, 'incr'); + copyDirSync(FIXTURE_DIR, fullDir); + copyDirSync(FIXTURE_DIR, incrDir); + + // Step 1: Full build both copies + await buildGraph(fullDir, { incremental: false, skipRegistry: true }); + await buildGraph(incrDir, { incremental: false, skipRegistry: true }); + + // Step 2: Touch app.js in the incr copy (append a comment) + const appPath = path.join(incrDir, 'app.js'); + fs.appendFileSync(appPath, '\n// touched\n'); + + // Step 3: Incremental rebuild + await buildGraph(incrDir, { incremental: true, skipRegistry: true }); + + // Step 4: Full rebuild the full copy so both have identical source + const fullAppPath = path.join(fullDir, 'app.js'); + fs.appendFileSync(fullAppPath, '\n// touched\n'); + await buildGraph(fullDir, { incremental: false, skipRegistry: true }); + }, 60_000); + + afterAll(() => { + try { + if (tmpBase) fs.rmSync(tmpBase, { recursive: true, force: true }); + } catch { + /* ignore */ + } + }); + + it('produces the same node count', () => { + const fullGraph = readGraph(path.join(fullDir, '.codegraph', 'graph.db')); + const incrGraph = readGraph(path.join(incrDir, '.codegraph', 'graph.db')); + expect(incrGraph.nodes.length).toBe(fullGraph.nodes.length); + }); + + it('produces the same edge count', () => { + const fullGraph = readGraph(path.join(fullDir, '.codegraph', 'graph.db')); + const incrGraph = readGraph(path.join(incrDir, '.codegraph', 'graph.db')); + expect(incrGraph.edges.length).toBe(fullGraph.edges.length); + }); + + it('produces identical nodes', () => { + const fullGraph = readGraph(path.join(fullDir, '.codegraph', 'graph.db')); + const incrGraph = readGraph(path.join(incrDir, '.codegraph', 'graph.db')); + expect(incrGraph.nodes).toEqual(fullGraph.nodes); + }); + + it('produces identical edges', () => { + const fullGraph = readGraph(path.join(fullDir, '.codegraph', 'graph.db')); + const incrGraph = readGraph(path.join(incrDir, '.codegraph', 'graph.db')); + expect(incrGraph.edges).toEqual(fullGraph.edges); + }); +});