Bug
During 1-file incremental rebuilds with --engine native, complexity metrics, CFG blocks, and dataflow edges for the changed file are purged but never re-computed. The data silently disappears until the next full build.
Evidence
BUILD-BENCHMARKS.md v3.1.4 1-file rebuild phases:
| Phase |
Native (1-file) |
WASM (1-file) |
Native (full) |
WASM (full) |
| Complexity |
0.1 ms |
0.1 ms |
15.6 ms |
76.5 ms |
| CFG |
0.1 ms |
0.1 ms |
126.2 ms |
124.5 ms |
| Dataflow |
0.2 ms |
0.2 ms |
99.6 ms |
98.4 ms |
0.1ms is the cost of importing the module and iterating zero files — no actual analysis runs.
Root cause
purgeFilesFromGraph deletes the changed file's rows from function_complexity, cfg_blocks, cfg_edges, and dataflow tables
- The native parser produces symbols without a
_tree (WASM tree-sitter tree)
- The unified walk in
ast-analysis/engine.js:108-109 skips files with no _tree:
if (!symbols._tree) continue; // No WASM tree — native path handles it
- The
buildXxx functions then check for pre-computed data on definitions (d.complexity, d.cfg?.blocks), find none (native doesn't compute these), and also skip
ensureWasmTrees (line 79-98) only triggers for dataflow and only when !symbols.dataflow — but native provides basic dataflow data, so it's skipped too
Result: purged data is never replaced.
Affected scope
- Only affects incremental rebuilds (1-file or scoped), not full builds
- Only affects native engine (
--engine native or --engine auto on systems with the native addon)
- WASM engine is unaffected because it always has
_tree available
Proposed fix
In ast-analysis/engine.js, call ensureWasmTrees for files that lack a _tree when any of complexity/CFG/dataflow are enabled — not just for dataflow. The existing gate:
if (doDataflow) {
// only checks !symbols.dataflow
}
Should be broadened to:
if (doComplexity || doCfg || doDataflow) {
// check for any file missing _tree that needs analysis
}
This ensures the WASM tree is available for the unified visitor walk even when the native engine handled parsing.