# How to Interpret Three-Tier Edge Confidence Scoring (EXTRACTED/INFERRED/AMBIGUOUS) in code-review-graph

> Understand code-review-graph's edge confidence scores EXTRACTED INFERRED and AMBIGUOUS. Learn to interpret reliability tiers for your code analysis with this guide.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: deep-dive
- Published: 2026-07-29

---

**TLDR:** The `code-review-graph` repository uses three confidence tiers—**EXTRACTED** for direct parser observations, **INFERRED** for type-based deductions, and **AMBIGUOUS** for unresolved matches—to rank the reliability of edges in its SQLite-backed knowledge graph.

The `code-review-graph` repository constructs a knowledge graph of code relationships stored in SQLite, where each edge represents a dependency or call between entities. Understanding the **three-tier edge confidence scoring** system is essential for accurately interpreting query results and visualizations, as it distinguishes between directly observed syntax and algorithmically deduced connections.

## The Three-Tier Confidence System

Every edge in the graph carries a **confidence tier** (stored in the `confidence_tier` column) that indicates how the relationship was derived. This classification operates alongside a numeric **confidence score** (float in the `confidence` column) to provide both categorical and probabilistic measures of edge reliability.

### EXTRACTED (High Confidence)

**EXTRACTED** edges originate from concrete syntactic elements that the parser can unambiguously locate. These represent the highest tier of confidence because they map directly to source code constructs. Typical examples include explicit function calls, `import` statements, class inheritance declarations, and test-to-code links.

According to the source code in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py), edges default to this tier upon insertion. Lines 90-91 set the `confidence_tier` column to `'EXTRACTED'` when a new edge is first created, reflecting that the relationship was directly observed rather than deduced.

### INFERRED (Medium Confidence)

**INFERRED** edges are added by resolver modules that deduce relationships not explicitly present in the source but determinable through type information, method overrides, or runtime-like analysis. For example, when a method call resolves to a specific implementation via an interface or when dispatch is discovered after analyzing class hierarchies, the edge is marked as inferred.

The [`scoped_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/scoped_resolver.py) module handles these rewrites. At lines 33-34, the resolver updates existing edges with `confidence_tier = 'INFERRED'` after performing type resolution. Similarly, [`event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/event_resolver.py) tags event-driven inferred relationships with this tier. These edges typically carry a reduced confidence float (e.g., 0.85) reflecting the heuristic nature of the deduction.

### AMBIGUOUS (Low Confidence)

**AMBIGUOUS** edges point to targets that could not be uniquely identified, usually because multiple symbols match the name (overloads), language-specific dynamic features obscure the target, or type information is missing. These edges are preserved in the graph to maintain completeness but are considered the least trustworthy.

When a resolver cannot select a single qualified name from multiple candidates, it assigns the `AMBIGUOUS` tier. These edges carry lower confidence scores (often around 0.4) and signal to downstream consumers that human verification may be required.

## Implementation Details

The tier assignment logic spans three critical files:

- **[`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py)** defines the SQLite schema and establishes the default. When `add_edge()` is called, the database schema automatically sets `confidence_tier` to `'EXTRACTED'` unless explicitly overridden.
- **[`code_review_graph/scoped_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/scoped_resolver.py)** performs type-based resolution. When resolving scoped calls (particularly for Rust and PHP), it rewrites edges using `rewrite_edge()` with the tier set to `'INFERRED'`.
- **[`code_review_graph/event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/event_resolver.py)** handles event-driven inference pathways, also tagging edges as `INFERRED` when relationships are discovered through indirect analysis.

Unit tests in [`tests/test_rust_scoped_calls.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_rust_scoped_calls.py) and [`tests/test_php_scoped_calls.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_php_scoped_calls.py) assert correct tier transitions, ensuring that extracted edges remain stable while inferred and ambiguous edges are properly classified during resolution passes.

## Working with Confidence Tiers in Python

When constructing or querying the graph programmatically, you interact with tiers through the store API:

```python
from code_review_graph import GraphStore

store = GraphStore("knowledge.db")

# Adding a direct observation - defaults to EXTRACTED tier

edge_id = store.add_edge(
    kind="CALLS",
    source_qualified="my_pkg.moduleA.func_a",
    target_qualified="my_pkg.moduleB.func_b",
    file_path="moduleA.py",
    line=42,
    confidence=1.0
)

# Resolver rewriting after type inference

store.rewrite_edge(
    edge_id=edge_id,
    new_target="my_pkg.moduleB.impl_func_b",
    confidence=0.85,
    confidence_tier="INFERRED"
)

# Handling ambiguous resolution

store.add_edge(
    kind="CALLS",
    source_qualified="my_pkg.moduleC.call_dynamic",
    target_qualified="my_pkg.moduleD.unknown",
    confidence=0.4,
    confidence_tier="AMBIGUOUS"
)

```

Query filters can leverage these tiers to adjust result precision:

```python

# High-precision query (EXTRACTED only)

precise_edges = store.query_edges(
    source="my_pkg.moduleA",
    confidence_tier="EXTRACTED"
)

# Include inferred relationships with threshold

broad_edges = store.query_edges(
    source="my_pkg.moduleA",
    min_confidence=0.5
)

```

## Why Confidence Tiers Matter

The three-tier system enables sophisticated graph analysis strategies:

- **Impact-radius queries** use tier information to weight edges during traversal. High-confidence `EXTRACTED` edges contribute fully to impact calculations, while `INFERRED` edges may be down-weighted and `AMBIGUOUS` edges filtered out entirely, allowing developers to trade completeness for precision.
- **Visualization** components (such as those in [`visualization.py`](https://github.com/tirth8205/code-review-graph/blob/main/visualization.py)) color-code edges by tier, enabling code reviewers to immediately distinguish between directly observed calls and speculative connections.
- **Incremental updates** maintain tier stability as the codebase evolves. When new code is parsed, previously `INFERRED` edges may be promoted to `EXTRACTED` if the parser now locates a concrete syntactic element, progressively improving graph accuracy without requiring full rebuilds.

## Summary

- **EXTRACTED** edges represent direct parser observations and default to confidence 1.0, defined in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py).
- **INFERRED** edges are type-resolved deductions created by [`scoped_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/scoped_resolver.py) and [`event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/event_resolver.py), typically with reduced confidence scores.
- **AMBIGUOUS** edges indicate unresolved multiple matches, retained for completeness but marked with low confidence.
- The `confidence_tier` column (TEXT) works alongside the `confidence` float column to enable both categorical filtering and probabilistic weighting.
- Query and visualization tools use these tiers to balance precision against recall when analyzing code dependencies.

## Frequently Asked Questions

### How does the confidence float relate to the confidence tier?

The **confidence float** (column `confidence`) stores a probabilistic value between 0.0 and 1.0 indicating the likelihood that an edge is correct, while the **confidence tier** (column `confidence_tier`) provides a categorical classification of how the edge was derived. Typically, `EXTRACTED` edges carry 1.0 confidence, `INFERRED` edges range from 0.7-0.9, and `AMBIGUOUS` edges fall below 0.5. Queries can filter by tier for semantic meaning or by float threshold for probabilistic tolerance.

### Can an edge change tiers after initial creation?

Yes. Edges may be **promoted** or **rewritten** by resolver modules. For instance, when [`scoped_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/scoped_resolver.py) performs type analysis, it may rewrite an `EXTRACTED` edge to `INFERRED` if it discovers the original target was an interface requiring dispatch resolution. Conversely, during incremental updates, an `INFERRED` edge may be replaced by an `EXTRACTED` edge if the parser subsequently locates a concrete call site for that relationship.

### Why keep AMBIGUOUS edges in the graph instead of discarding them?

`AMBIGUOUS` edges are retained to prevent **false negatives** in dependency analysis. While they indicate uncertainty about the specific target, they signal that a relationship likely exists between the source and one of several candidate targets. This allows visualization tools to flag areas requiring manual review and ensures that impact analysis doesn't miss potential dependencies simply because type resolution was inconclusive.

### Which resolver modules assign the INFERRED tier?

The **[`scoped_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/scoped_resolver.py)** module assigns `INFERRED` when resolving method calls through class hierarchies and interfaces, particularly for Rust and PHP scoped calls. The **[`event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/event_resolver.py)** module also tags edges as `INFERRED` when deducing relationships through event-driven or callback-based analysis. Both modules use the `rewrite_edge()` method to update the tier while preserving the edge's provenance.