fix(resolution): clean up processed refs by row id so batch boundaries can't drop sibling call sites (#1269) (#1270)

Post-batch cleanup deleted resolved refs (and parked failed ones) by
(from_node_id, reference_name, reference_kind) — no line/col. When one
caller had several call sites to the same callee and a batch boundary
split them, the first batch's cleanup removed every row with that key,
including later-batch siblings that were never attempted — their edges
were silently never created. On nlohmann/json this ate 422 real call
edges (write_cbor's 38 to_char_type calls indexed as 11).

Refs loaded from unresolved_refs now carry their row id through
resolution, and all three persist paths (sync resolveAndPersist, the
yielding retry pass, the batched drain loop) delete / mark-failed by
exactly that id. The key-tuple methods remain only as the fallback for
hand-built refs from the public API. Failed-parking gains the same
precision: outcome can differ per call site (receiver inference reads
the ref's line), so a sibling must not inherit another row's failure.

Also untracks the zz-scratch local test files that slipped into #1268
and gitignores the pattern.

Validation: red-green regression test (5 sites, batch size 2 — old code
kept 2 edges, fix keeps 5); nlohmann/json re-index is a strict superset
of the previous edge set (0 lost, 422 recovered, spot-checked against
source).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-07-12 20:09:03 -05:00
committed by GitHub
co-authored by Claude Fable 5
parent 6103f5e228
commit e871c49a31
11 changed files with 277 additions and 145 deletions
+1
View File
@@ -11,6 +11,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### Fixes
- Callers and impact analysis no longer silently under-count a function that calls the same callee many times. When one caller contained several call sites to the same callee and an internal resolution batch boundary happened to split them, cleanup after the first batch removed the later sites' pending rows before they were ever attempted — their edges were never created, deterministically, and which edges went missing shifted with unrelated changes to the project's total reference count. Post-pass cleanup now targets the exact database row each processed reference came from. Found while validating the operator-call fix on nlohmann/json, where `write_cbor`'s 11 calls to `to_char_type` indexed as 10. (#1269)
- C++ explicit operator calls — `a.operator+(b)`, `p->operator+(b)`, `a.operator[](3)`, and the other symbolic forms — now produce a `calls` edge to the operator method, so an operator invoked only through the explicit syntax no longer looks uncalled in callers and impact analysis. tree-sitter parses these call sites with the operator name stranded in an error node (never as a normal member access), so the call's target was silently read as just the receiver variable; the operator name is now recovered from the error node and resolved through receiver-type inference like any other member call — a same-named operator on an unrelated class can never capture the edge. Infix uses (`a + b`, `a[i]`) need real type inference and are tracked separately. (#1247)
## [1.4.1] - 2026-07-10