Commit 0a7a8aa
feat(resolver): WS0-WS6 context-intelligence upgrade (ambiguity groups, inheritance closure, non-destructive same-dir ranking)
Implements docs/plans/2026-08-18-context-intelligence-upgrade-plan.md's
WS3-WS5 (WS0-WS2 shipped in earlier commits; WS6 evaluated and deferred,
see below). Every workstream verified against the plan's own WS0
precision/false-confidence benchmark before and after, with full
`cargo test --workspace` green throughout.
WS3 -- record ambiguity groups instead of silently dropping them:
`resolve_sites_to_edges` now returns `(Vec<CallEdge>, Vec<AmbiguityGroup>)`.
A call site whose surviving candidate set exceeds MAX_CALLEE_CANDIDATES
no longer vanishes with zero trace -- it's recorded in a new
`ambiguity_groups` table (call_site_id, from_path, candidate_group_key,
candidate_count, reason), persisted by both rebuild_graph and
incremental_graph_update. `callers()` gains `unresolved_group_count` plus
a caveat that fires even when direct_count > 0; `reference_impact()`
gains the sibling `unresolved_many_count`.
WS4 -- inheritance closure as a real resolution mechanism:
`build_resolution_context` now builds a depth-level-aware
inheritance/interface closure from `type_relations` (extends/implements),
gated to `resolved`-confidence rows only -- never `textual`, per the
plan's own hard, non-negotiable rule. `resolve_cross_file_type_relations`
was moved to run before `build_resolution_context` in both graph-rebuild
paths (previously ran after resolve_sites_to_edges, making the closure
exactly one pass stale). resolve_via_inheritance_closure walks levels
nearest-first and only trusts a singleton match at the nearest declaring
level, refusing to pick between two same-depth ancestors that both
declare the same method name (e.g. `interface Mixed extends IA, IB`).
WS5 -- same_dir becomes a non-destructive ranker (C/C++ only):
`call_edges` gains `candidate_rank` (0 = preferred/same-dir, 1+ =
alternate). Found during implementation that the plan's own root-cause
text was wrong for Go/Java: both have real, compiler-enforced package
scoping (confirmed by two existing regression tests breaking under the
naive all-four-languages interpretation), so only C/C++ -- which have no
package/namespace-to-directory correspondence at all -- get the
non-destructive treatment; Go/Java keep the pre-WS5 hard filter.
`callers()`/`callees()` sort `ambiguous` by `candidate_rank`.
WS6 -- evaluated against its own WS0-evidence gate, not met: the
corpus's one real false-confidence case (fixture I / D8) is a different
defect (overlay/static-layer reconciliation) than what WS6 targets
(ambiguous-candidate disambiguation via StackGraph's definition_symbol).
Documented as a reasoned defer in the plan doc; recommends a new WS7 for
D8 instead of building WS6 speculatively.
Net WS0 benchmark result across the whole sequence: call_recall 0.75 ->
0.875 (WS5's fixture E recovering a previously-silently-dropped true
target), false_confidence_rate/false_confident_site_rate unchanged
(0.25 / 0.125) -- a clean recall gain with no precision cost.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>1 parent 54a9f89 commit 0a7a8aa
102 files changed
Lines changed: 3074 additions & 98 deletions
File tree
- benchmarks/resolution_precision
- fixtures
- A_import_narrows_fanout
- B_fanout_over_cap_dropped
- C_inherited_method_ancestor
- D_interface_polymorphic_dispatch
- E_same_dir_decoy_vs_true_target
- dir1
- dir2
- F_weak_receiver_no_false_positive
- G_cross_language_no_collision
- H_module_qualifier_wins
- src
- I_file_symbol_wins_over_import
- J_reflection_getattr_invisible
- K_overload_arity_elixir
- lib
- L_css_false_positive_floor
- src/main/resources/static/css
- crates
- calm-core/src
- db
- indexer
- calm-server/src
- __toolsnaps__
- tools
- docs/plans
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
66 | 70 | | |
67 | 71 | | |
68 | 72 | | |
| |||
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
0 commit comments