# Dogfooding Report: @optave/codegraph@2.4.0

**Date:** 2026-02-25
**Platform:** Windows 11 Pro (win32-x64), Node.js v22.18.0
**Native binary:** @optave/codegraph-win32-x64-msvc@2.4.0 (manually installed — missing from optionalDependencies)
**Active engine:** native (v0.1.0), after manual binary install; WASM by default
**Target repo:** codegraph itself (99 files, 2 languages: JS 80, Rust 19)

---

## 1. Setup & Installation

| Step | Result |
|------|--------|
| `npm install @optave/codegraph@2.4.0` | 206 packages, 6s, 0 vulnerabilities |
| `npx codegraph --version` | `2.4.0` |
| Native binary package | **MISSING** from optionalDependencies (BUG #1) |
| `optionalDependencies` pinned | darwin-arm64, darwin-x64, linux-x64-gnu at 2.4.0; **win32-x64-msvc absent** |
| `npx codegraph info` (before fix) | `engine: wasm` (fallback due to missing binary) |
| Manual `npm install @optave/codegraph-win32-x64-msvc@2.4.0` | Installed successfully |
| `npx codegraph info` (after fix) | `engine: native (v0.1.0)` |

**Bug #1 (High):** The `@optave/codegraph-win32-x64-msvc` package exists on npm at v2.4.0 but is not listed in `optionalDependencies`. Windows users silently get WASM fallback with no indication that native should be available. Filed as #113, fixed in PR #117.

---

## 2. Cold Start (Pre-Build)

Every command was tested against a non-existent database:

| Command | Status | Message |
|---------|--------|---------|
| `query buildGraph` | PASS | "No codegraph database found... Run `codegraph build` first" |
| `stats` | PASS | Same graceful message |
| `cycles` | PASS | Same graceful message |
| `export` | PASS | Same graceful message |
| `embed` | PASS | Note: `--db` flag not supported (reports "unknown option") |
| `search "test"` | PASS | Same graceful message |
| `map` | PASS | Same graceful message |
| `deps src/cli.js` | PASS | Same graceful message |
| `fn buildGraph` | PASS | Same graceful message |
| `fn-impact buildGraph` | PASS | Same graceful message |
| `context buildGraph` | PASS | Same graceful message |
| `explain src/cli.js` | PASS | Same graceful message |
| `where buildGraph` | PASS | Same graceful message |
| `impact src/cli.js` | PASS | Same graceful message |
| `diff-impact` | PASS | Same graceful message |
| `structure` | PASS | Same graceful message |
| `hotspots` | PASS | Same graceful message |
| `roles` | PASS | Same graceful message |
| `co-change` | PASS | Same graceful message |
| `models` | PASS | Lists 7 models (no DB needed) |
| `registry list` | PASS | Lists registered repos (no DB needed) |
| `info` | PASS | Engine diagnostics (no DB needed) |

**All 22 commands pass cold-start gracefully.** No crashes, no stack traces.

---

## 3. Full Command Sweep

### Build

```
codegraph build <repo> --engine native --no-incremental --verbose
```
- 99 files parsed, 579 nodes, 795 edges (build output)
- Stats: 906 edges total (includes 111 `contains` edges from structure analysis)
- Time: 0.377s (native), 0.546s (WASM)

### Query Commands

| Command | Flags Tested | Status | Notes |
|---------|-------------|--------|-------|
| `query <name>` | `-T`, `--json` | PASS | |
| `impact <file>` | default | PASS | Shows 6 transitive dependents |
| `map` | `-n 5`, `--json` | PASS | Clean JSON output |
| `stats` | `--json`, `-T` | PASS | 82/100 quality score |
| `deps <file>` | default | PASS | Shows imports and importers |
| `fn <name>` | `--depth 2`, `-f`, `-k`, `-T`, `--json` | PASS | All flags work |
| `fn-impact <name>` | `-T`, `--json` | PASS | 5 transitive dependents |
| `context <name>` | `--depth`, `--no-source`, `--json` | PASS | Role classification visible |
| `explain <target>` | file path, function name, `--json` | PASS | Data flow section accurate |
| `where <name>` | default, `-f <file>`, `--json` | PASS | File overview mode works |
| `diff-impact [ref]` | `main`, `--staged` | PASS | 57 files, 79 functions changed vs main |
| `cycles` | default, `--functions` | PASS | 1 file-level, 2 function-level cycles |
| `structure [dir]` | `.`, `--depth 1`, `--sort` | PASS | `.` filter works (v2.2.0 fix confirmed) |
| `hotspots` | `--metric fan-in/fan-out/density/coupling`, `--level file/directory`, `-n`, `--json` | PASS | All metrics and levels work |
| `roles` | default, `--json` | PASS | 462 classified: 216 dead, 166 core, 80 utility |
| `co-change` | `--analyze`, file query, `-n`, `--json` | PASS | 155 pairs from 236 commits |

### Export Commands

| Command | Flags | Status | Notes |
|---------|-------|--------|-------|
| `export -f dot` | default, `--functions` | PASS | Valid DOT graph |
| `export -f mermaid` | default, `--functions` | PASS | Enhanced with subgraphs, node shapes |
| `export -f json` | `-o <file>` | PASS | 77KB JSON file written |

### Embedding & Search

| Command | Flags | Status | Notes |
|---------|-------|--------|-------|
| `models` | default | PASS | 7 models listed |
| `embed` | `-m minilm`, `--strategy structured` | **BUG** (with stale data) | Crashes with stale graph (BUG #2). Works with clean build |
| `embed` | `-m minilm`, `--strategy source` | PASS | 450 symbols embedded |
| `search` | `-n`, `--min-score`, `-k`, `--file`, `--json` | PASS | Results relevant; `--file` glob works |
| `search` | multi-query with `;` | PASS | RRF ranking works correctly |

### Infrastructure Commands

| Command | Status | Notes |
|---------|--------|-------|
| `info` | PASS | Shows native availability, version |
| `--version` | PASS | `2.4.0` |
| `watch .` | PASS | Starts, detects changes, graceful Ctrl+C |
| `registry list` | PASS | JSON and text output |
| `registry prune --ttl 365` | PASS | "No stale entries" |
| `mcp` (single-repo) | PASS | 23 tools, `list_repos` absent (was 18 at time of report; now includes complexity, communities, execution_flow, list_entry_points, co_changes) |
| `mcp --multi-repo` | PASS | 24 tools, `list_repos` present |

### 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 — "No function/method/class matching" |
| `--kind` with invalid kind | PASS — Lists valid kinds |
| `structure .` (v2.2.0 bug regression) | PASS — Fixed |
| `--json` on every command | PASS — Valid JSON |
| `--no-tests` effect | PASS — 630→511 nodes, 1018→756 edges, 107→67 files |
| `search` with no embeddings | PASS — "No embeddings found" |
| Pipe output: `map --json 2>/dev/null` | PASS — Clean JSON |
| `search --json 2>/dev/null` | **BUG** — Model loading messages on stdout (BUG #3) |

### Programmatic API

```javascript
import * as cg from '@optave/codegraph';
```
- **73 exports** verified: `buildGraph`, `loadConfig`, `openDb`, `contextData`, `explainData`, `whereData`, `fnDepsData`, `diffImpactData`, `statsData`, `isNativeAvailable`, `EXTENSIONS`, `IGNORE_DIRS`, `ALL_SYMBOL_KINDS`, `MODELS`, and 59 more.
- All key exports present and typed as expected.

---

## 4. Rebuild & Staleness

### Incremental No-Op

| Metric | Full Build | No-Op Rebuild |
|--------|-----------|---------------|
| Nodes | 579 | 579 (unchanged) |
| Edges | 906 | 906 (unchanged) |
| Time | 0.377s | instant ("Graph is up to date") |
| Result | PASS | Correctly detects no changes |

### Incremental with Change

Appended `// test comment` to `src/logger.js`:

| Metric | Full Build | Incremental | Delta |
|--------|-----------|-------------|-------|
| Files parsed | 99 | 1 | Correct |
| Nodes | 579 | 579 | OK |
| Calls | 655 | 622 | **-33** |
| Imports | 115 | 103 | **-12** |
| Reexports | 25 | 24 | **-1** |
| Contains | 111 | 111 | OK |
| **Total edges** | **906** | **860** | **-46 (BUG #4)** |

**Bug #4 (High):** Incremental rebuild drops 46 edges when re-parsing a single file. Root cause: edge deletion removes ALL edges touching the changed file (both incoming and outgoing), but edge rebuilding only runs for the changed file — not for files that import it. Filed as #116.

### Embed-Rebuild-Search Pipeline

| Scenario | Result |
|----------|--------|
| embed → no-op rebuild → search | PASS — Results identical |
| embed → modify file → incremental rebuild → search | PASS — Results still return |
| Delete graph.db → full rebuild → search | PASS — "No embeddings table found" |

### Three-Tier Change Detection

| Tier | Test | Result |
|------|------|--------|
| Tier 0 (journal) | No journal entries present | Fell through to Tier 1 |
| Tier 1 (mtime+size) | 98 skipped by mtime+size, 1 need hash check | PASS |
| Tier 2 (content hash) | 1 actually changed, 0 metadata-only | PASS |

---

## 5. Engine Comparison

| Metric | Native | WASM | Delta |
|--------|--------|------|-------|
| Build time | 0.377s | 0.546s | Native 31% faster |
| Nodes | 579 | 579 | Identical |
| Edges | 906 | 906 | Identical |
| Functions | 387 | 387 | Identical |
| Call edges | 655 | 655 | Identical |
| High-conf calls | 641 (97.9%) | 641 (97.9%) | Identical |
| Quality score | 82/100 | 82/100 | Identical |
| Caller coverage | 56.4% | 56.4% | Identical |

**Perfect parity.** Native is 31% faster on build. All query results are identical:
- `fn buildGraph` — 16 callees, exact match
- `cycles --functions` — 2 cycles, exact match
- `stats --json` — full metric match

### Performance Benchmarks (WASM engine, from source repo)

**Build Benchmark:**
| Metric | Value |
|--------|-------|
| Build time | 481ms (4.9ms/file) |
| Query time | 2.2ms |
| Nodes | 579 (5.8/file) |
| Edges | 906 (9.2/file) |
| DB size | 384KB (3.9KB/file) |

**Incremental Benchmark:**
| Metric | Value |
|--------|-------|
| Full build | 416ms |
| No-op rebuild | 4ms |
| 1-file rebuild | 154ms |
| Import resolution (JS) | 1.9ms (84 pairs) |

**Query Benchmark:**
| Metric | Depth 1 | Depth 3 | Depth 5 |
|--------|---------|---------|---------|
| `fn-deps` | 0.9ms | 1.9ms | 1.8ms |
| `fn-impact` | 0.8ms | 1.2ms | 1.2ms |
| `diff-impact` | 20.4ms | — | — |

---

## 6. Release-Specific Tests

### v2.4.0 Features

| Feature | Test | Result |
|---------|------|--------|
| Co-change analysis (`co-change --analyze`) | Scanned git history, found 155 pairs from 236 commits | PASS |
| Co-change file query (`co-change src/parser.js`) | Found 2 partners: constants.js (43%), watcher.js (32%) | PASS |
| Co-change `--full` re-scan | Full re-scan produces same results | PASS |
| Node role classification (`roles`) | 462 classified: dead 216, core 166, utility 80 | PASS |
| Roles in context output | `[utility]` tag visible in context/explain output | PASS |
| Roles `--json` | Valid JSON with summary + symbol list | PASS |
| Enhanced Mermaid export (subgraphs, shapes) | Subgraphs by file, rounded node shapes `([...])` for functions | PASS |
| `search --json` output | Valid JSON with similarity scores | PASS |
| `search --file` glob filter | `--file "src/resolve*"` correctly scopes results | PASS |
| Update notification | Not observed (likely suppressed in non-TTY or recent install) | UNTESTED |
| tree-sitter Query API parser (performance) | Parser works, benchmarks show good perf | PASS |

### v2.4.0 Bug Fixes Verified

| Fix | Test | Result |
|-----|------|--------|
| Preserve structure data during incremental builds | Touch file → rebuild → `structure` still shows data | PASS |
| Config `embeddings.model` respected | Config field present in `.codegraphrc.json` schema | PASS |
| `DEFAULT_MODEL` as single source of truth | `models` shows `nomic-v1.5 (default)` then overridden to `bge-large` | PASS |
| Model disposal (ONNX memory leak) | `disposeModel` export available in API | PASS |
| Escape quotes in Mermaid labels | Mermaid export generates valid syntax | PASS |
| Jaccard recompute during incremental co-change | `co-change --analyze --full` produces consistent results | PASS |
| Collect all distinct edge kinds per pair | Stats show correct edge kind breakdown | PASS |
| Skip keys without `::` in role lookup | `roles` command doesn't crash | PASS |
| `indexOf` for `::` split (paths with colons) | No crashes on Windows paths | PASS |
| Validate glob patterns | Invalid patterns don't crash | PASS |

---

## 7. Additional Testing

### MCP Server

| Test | Result |
|------|--------|
| Single-repo initialization (JSON-RPC) | PASS — Valid response |
| `tools/list` (single-repo) | PASS — 23 tools, `list_repos` absent (updated from 18 after complexity, communities, execution_flow, list_entry_points, co_changes added) |
| `tools/list` (multi-repo) | PASS — 24 tools, `list_repos` present |
| New tools: `node_roles`, `co_changes`, `complexity`, `communities`, `execution_flow`, `list_entry_points` | Present in tool list |

### Config & Environment

| Test | Result |
|------|--------|
| `.codegraphrc.json` loading | PASS — Config loaded during build |
| `--engine` flag (native/wasm/auto) | PASS — All three work |
| `CODEGRAPH_REGISTRY_PATH` | Not tested (env var override) |

### Multi-Repo Registry

| Test | Result |
|------|--------|
| `registry list` | PASS — Shows 5 registered repos |
| `registry list --json` | PASS — Valid JSON |
| `registry prune --ttl 365` | PASS — "No stale entries" |

---

## 8. Bugs Found

### BUG 1: Missing win32 native binary in optionalDependencies (High)
- **Issue:** [#113](https://github.com/optave/codegraph/issues/113)
- **PR:** [#117](https://github.com/optave/codegraph/pull/117)
- **Symptoms:** Windows installs silently fall back to WASM engine. `codegraph info` reports `engine: wasm`.
- **Root cause:** `@optave/codegraph-win32-x64-msvc` was never added to `optionalDependencies` in `package.json`. The package exists on npm but isn't pulled in.
- **Fix applied:** Added win32 package and pinned all platform packages to 2.4.0.

### BUG 2: extractLeadingComment crashes on out-of-bounds access (Medium)
- **Issue:** [#114](https://github.com/optave/codegraph/issues/114)
- **PR:** [#117](https://github.com/optave/codegraph/pull/117)
- **Symptoms:** `codegraph embed --strategy structured` crashes with `TypeError: Cannot read properties of undefined (reading 'trim')` when graph has stale node data (line numbers beyond file length).
- **Root cause:** `extractLeadingComment()` in `embedder.js` doesn't bounds-check `lines[i]`. When `fnLineIndex > lines.length`, the loop accesses `undefined`.
- **Fix applied:** Added bounds check at loop start: `if (fnLineIndex > lines.length) return null` and `if (i >= lines.length) continue`.

### BUG 3: search --json leaks model loading to stdout (Low)
- **Issue:** [#115](https://github.com/optave/codegraph/issues/115)
- **PR:** [#117](https://github.com/optave/codegraph/pull/117)
- **Symptoms:** `codegraph search "query" --json 2>/dev/null` outputs "Loading embedding model..." and "Model loaded." before the JSON, breaking pipe consumers.
- **Root cause:** `loadModel()` used `console.log()` instead of the stderr-routed `info()` logger.
- **Fix applied:** Replaced `console.log` with `info()` for both messages.

### BUG 4: ~~Incremental rebuild drops edges~~ — FIXED
- **Issue:** [#116](https://github.com/optave/codegraph/issues/116) — Closed
- **PR:** Fixed via reverse-dependency cascade in `builder.js:444`
- **Symptoms:** Touching one file (appending a comment) and running incremental build drops 46 edges (33 calls, 12 imports, 1 reexport). Full rebuild restores them.
- **Root cause:** The incremental edge deletion query removed ALL edges touching the changed file — including incoming edges from other files. The edge rebuilding phase only processed changed files.
- **Fix applied:** Reverse-dependency cascade — when a file changes, files that import it are identified and their outgoing edges are re-resolved. Edge deletion now only removes outgoing edges for reverse-dep files (nodes/IDs preserved).

---

## 9. Suggestions for Improvement

### 9.1 ~~Add `--db` flag to `embed` command~~ — DONE
~~Currently `embed` doesn't support `--db`, unlike all other commands.~~ Fixed: `embed` now supports `-d, --db <path>`.

### 9.2 ~~Redirect HuggingFace library console output~~ — DONE
~~The `@huggingface/transformers` library prints "dtype not specified..." via `console.warn` which goes to stderr.~~ Fixed in PR #117: `loadModel()` messages switched from `console.log` to `info()` (stderr-routed logger). The HF library's own `console.warn` goes to stderr naturally and doesn't affect stdout pipe consumers.

### 9.3 ~~Incremental rebuild needs reverse-dep edge cascade~~ — DONE
~~The most impactful fix would be making incremental rebuilds re-resolve edges for files that import changed files.~~ Implemented at `builder.js:444` — reverse-dependency cascade detects files that import changed files and re-resolves their outgoing edges, fixing Bug #4.

### 9.4 Update notification testing — RESOLVED in v2.5.0
The update notification feature was not observable during testing. Consider adding a `--check-update` flag for manual testing, or document when the notification appears.

> v2.5.0 moved dev builds to GitHub pre-releases, resolving false-positive notification issues. The notification works correctly on stable npm releases.

---

## 10. Testing Plan

### General Testing Plan (Any Release)

- [ ] Install from npm, verify version
- [ ] Verify native binary installed for current platform
- [ ] `codegraph info` reports expected engine
- [ ] All commands graceful with no database
- [ ] `build` succeeds with `--verbose`, `--no-incremental`, `--engine native/wasm`
- [ ] All query commands work with `-T`, `--json`
- [ ] Edge cases: non-existent symbol/file/function, invalid `--kind`
- [ ] `structure .` works (regression from v2.2.0)
- [ ] Incremental no-op: "Graph is up to date"
- [ ] Incremental 1-file change: node/edge counts match full rebuild
- [ ] `embed` → `search` pipeline works
- [ ] `embed` → `build` → `search` (no re-embed) still returns results
- [ ] Delete DB → rebuild → search warns about missing embeddings
- [ ] Engine parity: native vs WASM node/edge/quality match
- [ ] MCP single-repo: correct tool count, no `list_repos`
- [ ] MCP multi-repo: `list_repos` present
- [ ] Programmatic API: key exports present
- [ ] `--json` output pipe-clean (no status on stdout)
- [ ] All benchmarks run without regression

### Release-Specific Testing Plan (v2.4.0)

- [ ] `co-change --analyze` scans git history
- [ ] `co-change <file>` returns partners
- [ ] `co-change --full` forces re-scan
- [ ] `roles` command classifies nodes
- [ ] `roles --json` valid output
- [ ] Enhanced Mermaid export: subgraphs, node shapes present
- [ ] `search --json` returns valid JSON
- [ ] `search --file <glob>` filters correctly
- [ ] Structure data preserved during incremental build
- [ ] Config `embeddings.model` respected
- [ ] Mermaid label quoting works

### Proposed Additional Tests

- [ ] Concurrent builds: two `build` commands at once
- [ ] Build while watch is running
- [ ] `apiKeyCommand` credential resolution with simple echo command
- [ ] Test on a repo other than codegraph itself (different language mix)
- [ ] Database migration path: v1→v6 schema upgrade from older graph.db
- [ ] `search` with dimension-mismatched model after re-embed
- [ ] `co-change` incremental scan (modify, re-analyze without `--full`)
- [ ] Registry `add`/`remove`/`prune --ttl 0` lifecycle

---

## 11. Overall Assessment

Codegraph v2.4.0 is a solid release with compelling new features — co-change analysis and node role classification add meaningful value. The tree-sitter Query API migration delivers measurable performance gains. Engine parity remains perfect.

**All 4 bugs found during dogfooding have been fixed:**

1. ~~Windows users get no native engine~~ — Fixed in PR #117 (added win32 to optionalDependencies)
2. ~~extractLeadingComment crashes~~ — Fixed in PR #117 (bounds check)
3. ~~search --json leaks to stdout~~ — Fixed in PR #117 (switched to stderr logger)
4. ~~Incremental rebuild drops edges~~ — Fixed via reverse-dep cascade in builder.js

3 of 4 improvement suggestions also addressed (9.1 `--db` on embed, 9.2 HF output, 9.3 reverse-dep cascade). Only 9.4 (update notification testing) remains open as low priority.

**Rating: 7/10 → 9/10 (post-fix)**

Original deductions were: missing win32 binary (-1), incremental edge drop (-1.5), stdout pollution (-0.5). All three are now fixed. Remaining -1: update notification untested, and the HF library's `console.warn` to stderr is cosmetic but not fully silenced.

---

## 12. Issues & PRs Created

| Type | Number | Title | Status |
|------|--------|-------|--------|
| Issue | [#113](https://github.com/optave/codegraph/issues/113) | bug: @optave/codegraph-win32-x64-msvc missing from optionalDependencies | Closed via PR #117 |
| Issue | [#114](https://github.com/optave/codegraph/issues/114) | bug(embedder): extractLeadingComment crashes on out-of-bounds line access | Closed via PR #117 |
| Issue | [#115](https://github.com/optave/codegraph/issues/115) | bug(embedder): search --json leaks model loading messages to stdout | Closed via PR #117 |
| Issue | [#116](https://github.com/optave/codegraph/issues/116) | bug(builder): incremental rebuild drops edges when re-parsing a file | Closed — fixed via reverse-dep cascade |
| PR | [#117](https://github.com/optave/codegraph/pull/117) | fix: dogfood v2.4.0 — win32 native binary, embedder crashes, stdout pollution | Merged |
