|
| 1 | +# Codegraph v2.0.0 Improvement Plan |
| 2 | + |
| 3 | +Results from dogfooding codegraph on itself (February 2026). Includes bugs found, fixes applied, and strategic improvement recommendations. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Bugs Found & Fixed |
| 8 | + |
| 9 | +### Fixed in this session |
| 10 | + |
| 11 | +| # | Severity | Bug | Fix | |
| 12 | +|---|----------|-----|-----| |
| 13 | +| 1 | **CRITICAL** | Native Rust engine produces 0 import edges — `resolveImport` returns `"src/./db.js"` instead of `"src/db.js"` | Fixed in Rust (`import_resolution.rs`) via `Path::components().collect()` normalization + JS-side `path.normalize()` wrapper in `resolve.js` as defense-in-depth | |
| 14 | +| 2 | **HIGH** | `--version` reports `1.3.0` instead of `2.0.0` — hardcoded in `cli.js:35` | Read version from `package.json` dynamically | |
| 15 | +| 3 | **MEDIUM** | `resolveViaAlias` crashes on `node:` prefixed imports when `aliases.paths` is null | Added null guard: `Object.entries(aliases.paths \|\| {})` | |
| 16 | +| 4 | **MEDIUM** | Registry polluted with 30+ dead temp directory entries from tests | Added `skipRegistry` option to `buildGraph`; integration tests now pass `skipRegistry: true`; CLI tests call `pruneRegistry()` in `afterAll` | |
| 17 | +| 5 | **LOW** | `git diff` usage spam in test output (hundreds of lines of stderr) | Added `.git` directory check before running `git diff` in `diffImpactData`; returns clean error `"Not a git repository"` instead; suppressed stderr via `stdio: ['pipe','pipe','pipe']` | |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Graph Health Snapshot |
| 22 | + |
| 23 | +| Metric | Value | |
| 24 | +|--------|-------| |
| 25 | +| Files parsed | 74 | |
| 26 | +| Symbols (nodes) | 426 | |
| 27 | +| Edges total | 1,570 | |
| 28 | +| Import edges | 80 | |
| 29 | +| Reexport edges | 15 | |
| 30 | +| Call edges | ~1,390 | |
| 31 | +| File-level cycles | 0 | |
| 32 | +| Function-level cycles | 1 (findPythonParentClass <-> walk in parser.js) | |
| 33 | + |
| 34 | +### Module coupling (top 10) |
| 35 | + |
| 36 | +| File | Fan-in | Fan-out | Notes | |
| 37 | +|------|--------|---------|-------| |
| 38 | +| db.js | 16 | 1 | Most-imported module | |
| 39 | +| parser.js | 15 | 2 | Second most-imported; 2200+ line monolith | |
| 40 | +| logger.js | 12 | 0 | Pure leaf (no imports) | |
| 41 | +| native.js | 11 | 0 | Pure leaf | |
| 42 | +| builder.js | 7 | 7 | Orchestrator; highest fan-out | |
| 43 | +| constants.js | 7 | 1 | Widely used | |
| 44 | +| resolve.js | 6 | 2 | | |
| 45 | +| cycles.js | 5 | 1 | | |
| 46 | +| queries.js | 5 | 1 | | |
| 47 | +| config.js | 4 | 1 | | |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | +## Improvement Plan |
| 52 | + |
| 53 | +### P0 — Critical (fix before next release) |
| 54 | + |
| 55 | +All P0 items have been fixed in this session: |
| 56 | + |
| 57 | +- **Native engine path normalization** — Fixed in both Rust (`import_resolution.rs`: `Path::components().collect()`) and JS (`resolve.js`: `path.normalize()` wrapper). Import edges now correctly resolve with both engines. |
| 58 | +- **Version string** — `cli.js` now reads from `package.json` dynamically. |
| 59 | +- **Registry pollution** — Tests no longer pollute the global registry. |
| 60 | +- **Git diff noise** — Clean error handling for non-git directories. |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +### P1 — High priority (next 1-2 releases) |
| 65 | + |
| 66 | +#### 3. Split parser.js into per-language extractors |
| 67 | +**Found by:** `codegraph deps src/parser.js` (fan-in 15), `codegraph cycles --functions` (1 cycle) |
| 68 | + |
| 69 | +`parser.js` is a 2200+ line file with 47 function definitions. Each language extractor has its own `walk()` function, creating ambiguous function names in the graph. The Rust engine already has this structure (`crates/codegraph-core/src/extractors/`). |
| 70 | + |
| 71 | +**Action:** Create `src/extractors/` directory with one file per language: |
| 72 | +``` |
| 73 | +src/extractors/ |
| 74 | + javascript.js # JS/TS/TSX |
| 75 | + python.js |
| 76 | + go.js |
| 77 | + rust.js |
| 78 | + java.js |
| 79 | + csharp.js |
| 80 | + ruby.js |
| 81 | + php.js |
| 82 | + hcl.js |
| 83 | +``` |
| 84 | + |
| 85 | +Keep `LANGUAGE_REGISTRY` in `parser.js` but import extractors from the new files. |
| 86 | + |
| 87 | +**Benefits:** |
| 88 | +- Resolves the `findPythonParentClass <-> walk` function-level cycle |
| 89 | +- Disambiguates function names for codegraph's own analysis |
| 90 | +- Each extractor becomes independently testable |
| 91 | +- Aligns with Rust codebase structure |
| 92 | + |
| 93 | +#### 4. Clean up stale registry entries |
| 94 | +**Found by:** `codegraph registry list` (30+ dead temp dir entries) |
| 95 | + |
| 96 | +Integration tests register temp directories that are never cleaned up. The registry grows unbounded. |
| 97 | + |
| 98 | +**Action:** |
| 99 | +- Add `registry prune` command (or make existing `pruneRegistry` accessible via CLI) to remove entries with missing DBs |
| 100 | +- Add `afterAll` cleanup in integration test fixtures |
| 101 | +- Consider adding a TTL or auto-prune on `registry list` |
| 102 | +- Optionally: skip registry for paths under `$TMPDIR`/`os.tmpdir()` |
| 103 | + |
| 104 | +#### 5. Improve search relevance for own codebase |
| 105 | +**Found by:** `codegraph search "build dependency graph"` — top results were Rust extractors' `walk_node`, not `buildGraph` |
| 106 | + |
| 107 | +The search query "build dependency graph" should rank `buildGraph` (src/builder.js:142) in the top 3, but it didn't appear at all. The default embedding model (minilm) may not understand code-specific semantics well enough. |
| 108 | + |
| 109 | +**Action:** |
| 110 | +- Run `codegraph embed --model jina-code` to use the code-aware embedding model and compare results |
| 111 | +- Consider making `jina-code` the recommended default for code repositories |
| 112 | +- Explore prepending function context (file path, kind) to the embedding input for better disambiguation |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +### P2 — Medium priority (next 2-3 releases) |
| 117 | + |
| 118 | +#### 6. Guard `git diff` in non-repo contexts |
| 119 | +**Found by:** Test output noise from `diff-impact` tests |
| 120 | + |
| 121 | +When `diff-impact` runs in a non-git directory (e.g., temp dirs during tests), `git diff` prints its full usage help to stderr. This is noisy but doesn't fail tests. |
| 122 | + |
| 123 | +**Action:** Check for `.git` directory or run `git rev-parse --git-dir` before calling `git diff`. Return a clear error message instead of letting git dump its help text. |
| 124 | + |
| 125 | +#### 7. Add a `codegraph stats` command |
| 126 | +**Found by:** Dogfooding — no single command shows graph health overview |
| 127 | + |
| 128 | +Currently you need to run `map`, `cycles`, and read build output separately to assess graph health. |
| 129 | + |
| 130 | +**Action:** Add `codegraph stats` that shows: |
| 131 | +- Node/edge counts by kind |
| 132 | +- File count and language distribution |
| 133 | +- Cycle count (file + function level) |
| 134 | +- Top 5 coupling hotspots |
| 135 | +- Embedding status (model, count, staleness) |
| 136 | + |
| 137 | +#### 8. Improve map command ranking |
| 138 | +**Found by:** `codegraph map --limit 20` (WASM build) |
| 139 | + |
| 140 | +When Rust files are parsed, the map is dominated by Rust extractor files (all with `inEdges: 1, outEdges: 0`). The ranking should prioritize files with meaningful import relationships over files with only `contains` edges. |
| 141 | + |
| 142 | +**Action:** Weight import/reexport edges higher than `contains` edges in the `map` ranking algorithm. Consider filtering out files below a minimum edge threshold. |
| 143 | + |
| 144 | +#### 9. builder.js fan-out reduction |
| 145 | +**Found by:** `codegraph map` (fan-out 7, highest in codebase) |
| 146 | + |
| 147 | +`builder.js` imports from 7 modules: config, constants, db, logger, parser, resolve, structure. As the build orchestrator this is somewhat expected, but the `structure.js` integration (already lazy-loaded via dynamic import) pattern could apply to other optional post-build steps. |
| 148 | + |
| 149 | +**Action:** Consider lazy-loading `config.js` (only needed once at build start) and `resolve.js` (only needed during edge building). |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +### P3 — Low priority (future consideration) |
| 154 | + |
| 155 | +#### 10. Improve test isolation for registry |
| 156 | +Tests should not pollute the global `~/.codegraph/registry.json`. Consider using `XDG_DATA_HOME` or a test-specific registry path. |
| 157 | + |
| 158 | +#### 11. Native engine fallback transparency |
| 159 | +When the native engine is requested but unavailable, the warning is logged but easy to miss. Consider a more prominent indicator in the build output, or make `--engine native` fail hard instead of silently falling back. |
| 160 | + |
| 161 | +#### 12. Embed and search as CI validation |
| 162 | +Add an optional CI step that runs `codegraph embed` + `codegraph search` against known queries and validates that key functions appear in the top N results. This would catch embedding regressions. |
| 163 | + |
| 164 | +#### 13. Python search improvements |
| 165 | +`codegraph search` for Python-related queries could be improved if the `extractPythonSymbols` function names were more descriptive (currently `walk` is ambiguous across all language extractors). |
| 166 | + |
| 167 | +--- |
| 168 | + |
| 169 | +## Testing Summary |
| 170 | + |
| 171 | +| Test Suite | Result | |
| 172 | +|-----------|--------| |
| 173 | +| All tests | 367 passed, 43 skipped | |
| 174 | +| `build` | Works (both WASM and native) | |
| 175 | +| `cycles` | Works (0 file-level, 1 function-level) | |
| 176 | +| `map` | Works (correct ranking with WASM) | |
| 177 | +| `query` | Works | |
| 178 | +| `deps` | Works with WASM; broken with native (fixed with JS workaround) | |
| 179 | +| `impact` | Works with WASM; broken with native (fixed with JS workaround) | |
| 180 | +| `fn` / `fn-impact` | Works | |
| 181 | +| `diff-impact` | Works | |
| 182 | +| `export` (dot/mermaid/json) | Works | |
| 183 | +| `embed` | Works (310 symbols embedded) | |
| 184 | +| `search` | Works (single + multi-query) | |
| 185 | +| `models` | Works | |
| 186 | +| `registry` | Works (but polluted with dead entries) | |
| 187 | +| `--version` | Fixed (was 1.3.0, now reads from package.json) | |
| 188 | +| Lint (biome) | Clean after format | |
| 189 | + |
| 190 | +--- |
| 191 | + |
| 192 | +## Commands Used for This Analysis |
| 193 | + |
| 194 | +```bash |
| 195 | +# Install and verify |
| 196 | +npm install -g @optave/codegraph@2.0.0 |
| 197 | + |
| 198 | +# Build graph |
| 199 | +codegraph build . |
| 200 | +node src/cli.js build . --no-incremental --engine wasm |
| 201 | + |
| 202 | +# Test all commands |
| 203 | +codegraph cycles |
| 204 | +codegraph cycles --functions |
| 205 | +codegraph map --limit 20 |
| 206 | +codegraph query buildGraph |
| 207 | +codegraph deps src/builder.js |
| 208 | +codegraph impact src/parser.js |
| 209 | +codegraph fn buildGraph --no-tests |
| 210 | +codegraph fn-impact buildGraph --no-tests |
| 211 | +codegraph diff-impact main |
| 212 | +codegraph export -f dot |
| 213 | +codegraph export -f mermaid |
| 214 | +codegraph export -f json |
| 215 | +codegraph embed |
| 216 | +codegraph search "build dependency graph" |
| 217 | +codegraph search "parse source code; extract symbols" |
| 218 | +codegraph models |
| 219 | +codegraph registry list |
| 220 | +``` |
0 commit comments