Summary
Discovered while verifying phase-11 Titan decomposition of src/domain/graph/builder/stages/build-edges.ts (a pure extract-method refactor, unrelated to this bug — reproduces identically on unmodified HEAD).
For the native engine, a call edge's technique column differs depending on whether it was inserted via a full build vs. an incremental rebuild of the same final source state:
- Full build (
codegraph build --engine native or --no-incremental): applyEdgeTechniquesAfterNativeInsert in build-edges.ts backfills technique = 'ts-native' on every natively-inserted calls edge that doesn't already have an explicit technique.
- Incremental rebuild (
codegraph build --engine native after a single-file edit): buildCallEdges → emitIncrementalCallEdges in src/domain/graph/builder/incremental.ts inserts edges via stmts.insertEdge.run(...), which never sets technique at all — it's left NULL.
Repro
- Build a small fixture project fully with
--engine native.
- Make a trivial one-line edit to any file that has a
calls edge into it (e.g. append an unrelated comment).
- Rebuild incrementally (
codegraph build --engine native).
- Dump the
edges table and compare technique for the affected edges against a fresh --no-incremental full rebuild of the same post-edit state.
Example divergence on tests/fixtures/sample-project:
incremental: {"src":"main","tgt":"Calculator.compute", ..., "technique":null}
full: {"src":"main","tgt":"Calculator.compute", ..., "technique":"ts-native"}
All other edge fields (source, target, kind, confidence, dynamic) are identical — only technique diverges.
Impact
Any query or feature that filters/groups by edges.technique (e.g. codegraph roles, technique-coverage reporting in the resolution benchmark, coverage dashboards) will undercount native-engine edges that were last touched by an incremental rebuild vs. a full rebuild, even though the edges themselves are correct.
Suggested fix
Mirror applyEdgeTechniquesAfterNativeInsert's backfill behavior in incremental.ts's emitIncrementalCallEdges (or run an equivalent scoped backfill after incremental native inserts), so technique is populated consistently regardless of which rebuild path produced the edge.
Summary
Discovered while verifying phase-11 Titan decomposition of
src/domain/graph/builder/stages/build-edges.ts(a pure extract-method refactor, unrelated to this bug — reproduces identically on unmodifiedHEAD).For the native engine, a call edge's
techniquecolumn differs depending on whether it was inserted via a full build vs. an incremental rebuild of the same final source state:codegraph build --engine nativeor--no-incremental):applyEdgeTechniquesAfterNativeInsertinbuild-edges.tsbackfillstechnique = 'ts-native'on every natively-insertedcallsedge that doesn't already have an explicit technique.codegraph build --engine nativeafter a single-file edit):buildCallEdges→emitIncrementalCallEdgesinsrc/domain/graph/builder/incremental.tsinserts edges viastmts.insertEdge.run(...), which never setstechniqueat all — it's leftNULL.Repro
--engine native.callsedge into it (e.g. append an unrelated comment).codegraph build --engine native).edgestable and comparetechniquefor the affected edges against a fresh--no-incrementalfull rebuild of the same post-edit state.Example divergence on
tests/fixtures/sample-project:All other edge fields (source, target, kind, confidence, dynamic) are identical — only
techniquediverges.Impact
Any query or feature that filters/groups by
edges.technique(e.g.codegraph roles, technique-coverage reporting in the resolution benchmark, coverage dashboards) will undercount native-engine edges that were last touched by an incremental rebuild vs. a full rebuild, even though the edges themselves are correct.Suggested fix
Mirror
applyEdgeTechniquesAfterNativeInsert's backfill behavior inincremental.ts'semitIncrementalCallEdges(or run an equivalent scoped backfill after incremental native inserts), sotechniqueis populated consistently regardless of which rebuild path produced the edge.