# Edge Confidence Scoring in code-review-graph: EXTRACTED vs INFERRED vs AMBIGUOUS Explained

> Understand edge confidence scoring EXTRACTED INFERRED AMBIGUOUS in code-review-graph. Learn how tirth8205/code-review-graph assesses connection certainty for improved static analysis.

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

---

**Edge confidence scoring in `code-review-graph` assigns every relationship edge one of three tiers—EXTRACTED, INFERRED, or AMBIGUOUS—to indicate how certain the static analyzer is about the connection's existence.**

The `tirth8205/code-review-graph` project models codebase architecture as a graph of structural relationships, but static analysis of dynamic languages cannot always resolve connections with absolute certainty. **Edge confidence scoring** provides a three-tier taxonomy that tells downstream tools exactly how each relationship was derived, enabling precise impact analysis and risk calculation when tracing dependencies across Python or JavaScript projects.

## The Three Confidence Tiers

Every edge stored in the graph database includes a `confidence_tier` column that classifies the relationship's reliability. 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) (lines 70–73), the tier is stored as a `TEXT` field with a default value of `'EXTRACTED'`, alongside a numeric `confidence REAL` column defaulting to `1.0`.

The three tiers represent distinct levels of analytical certainty:

- **EXTRACTED**: The edge was parsed directly from the abstract syntax tree (AST) and represents an explicit reference in source code, such as a literal function call `foo()` or a concrete `import` statement.
- **INFERRED**: The edge was heuristically deduced because static analysis could not find a concrete reference, but contextual clues suggest a likely relationship, such as dynamic dispatch or a function passed as a callback.
- **AMBIGUOUS**: The analyzer identified multiple possible targets for a single reference and cannot determine which candidate is correct, often occurring with overloaded functions or wildcard imports.

## How Edge Confidence Is Derived

### EXTRACTED: Direct AST Analysis

Edges marked as **EXTRACTED** come from unambiguous syntactic evidence. When the parser encounters explicit calls or inheritance declarations, it creates an edge with this tier. This is the most reliable classification and serves as the default for all edges unless the analyzer encounters uncertainty.

### INFERRED: Heuristic Resolution

When analyzing dynamic patterns, the system creates **INFERRED** edges. In [`code_review_graph/event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/event_resolver.py) at line 107, the resolver explicitly assigns the `INFERRED` tier to edges representing dynamic relationships that lack direct AST evidence but match heuristic patterns. This commonly occurs with duck-typed code, metaprogramming constructs, or callbacks where the target function isn't explicitly named at the call site.

### AMBIGUOUS: Unresolved Multiple Candidates

**AMBIGUOUS** edges arise during name resolution when the analyzer finds several plausible definitions for a single reference. Rather than dropping the potential relationship, the system preserves the edge with this uncertainty marker. This tier frequently appears with wildcard imports or polymorphic dispatch where the concrete type cannot be statically determined.

## Querying and Filtering by Confidence Tier

### Inspecting Edge Metadata

The `query_graph_tool` exposes the confidence tier for every relationship. When querying callers or dependencies, the returned JSON includes a `confidence_tier` field that you can inspect programmatically:

```python
from code_review_graph.mcp_tools import query_graph_tool

result = query_graph_tool(
    pattern="callers_of",
    qualified_name="my_module.my_function",
)

for edge in result["edges"]:
    print(
        f"{edge['source_qualified']} → {edge['target_qualified']}: "
        f"tier={edge['confidence_tier']}"
    )

```

### Filtering for High-Confidence Edges

Downstream analysis tools often exclude uncertain connections to reduce false positives. You can filter result sets to include only directly extracted relationships:

```python
high_conf_edges = [
    e for e in result["edges"]
    if e["confidence_tier"] == "EXTRACTED"
]

```

This pattern ensures that impact radius calculations and change detection logic rely solely on explicit, syntactically verified dependencies.

### Database Schema Storage

The SQLite schema defines the confidence tier in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) (lines 70–71) and was added via migration in [`code_review_graph/migrations.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/migrations.py) (lines 234–236):

```sql
CREATE TABLE IF NOT EXISTS edges (
    source_qualified TEXT NOT NULL,
    target_qualified TEXT NOT NULL,
    edge_type TEXT NOT NULL,
    confidence REAL DEFAULT 1.0,
    confidence_tier TEXT DEFAULT 'EXTRACTED',
    PRIMARY KEY (source_qualified, target_qualified, edge_type)
);

```

The `confidence_tier` field allows tools like `detect_changes_tool` to weight edges differently when computing risk scores, biasing results toward more certain relationships even though all edges carry a default numeric confidence of `1.0`.

## Why Confidence Tiers Matter for Impact Analysis

The FAQ documentation in [`docs/FAQ.md`](https://github.com/tirth8205/code-review-graph/blob/main/docs/FAQ.md) (lines 45–48) explains that dynamic dispatch, metaprogramming, and duck typing inherently produce uncertainty in static analysis. Without tiered confidence scoring, tools would either miss potential dependencies entirely or overwhelm users with false positives.

By distinguishing between **EXTRACTED**, **INFERRED**, and **AMBIGUOUS** relationships, `code-review-graph` enables precise control over dependency graphs. Security scanners can ignore inferred call chains, while refactoring tools might surface ambiguous edges for manual review. This granularity is essential for maintaining accurate codebase intelligence in dynamic language ecosystems.

## Summary

- **Edge confidence scoring** classifies every relationship in the codebase graph as EXTRACTED, INFERRED, or AMBIGUOUS based on analytical certainty.
- **EXTRACTED** edges represent direct AST parses and provide the highest reliability, stored by default in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py).
- **INFERRED** edges capture heuristic relationships from dynamic patterns, created in [`code_review_graph/event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/event_resolver.py).
- **AMBIGUOUS** edges indicate multiple possible targets, preserving potential connections without asserting certainty.
- Downstream tools filter by `confidence_tier` to bias impact analysis toward verified dependencies and reduce noise from dynamic language features.

## Frequently Asked Questions

### What is the default confidence tier for new edges?

By default, all edges created in `code_review_graph` receive the **EXTRACTED** tier and a numeric confidence score of `1.0`. The database schema in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) defines these defaults at lines 70–71, ensuring that edges are treated as reliable unless the analyzer specifically encounters ambiguity.

### How does edge confidence scoring handle dynamic dispatch in Python?

Dynamic dispatch creates **INFERRED** edges because the concrete target of a method call cannot be resolved statically from the AST alone. When the [`event_resolver.py`](https://github.com/tirth8205/code-review-graph/blob/main/event_resolver.py) module (line 107) encounters patterns like duck typing or callbacks, it marks these relationships as INFERRED to signal that they rely on heuristic analysis rather than direct parsing.

### Can I filter graph queries to exclude AMBIGUOUS edges?

Yes. When using `query_graph_tool` or processing edge lists directly, filter the results to include only edges where `confidence_tier == "EXTRACTED"`. This pattern ensures that impact analysis, change detection, and risk scoring rely exclusively on unambiguous, syntactically verified relationships rather than uncertain candidates.

### Where is the confidence tier stored in the database?

The `confidence_tier` column lives in the `edges` table of the SQLite database, defined in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) at lines 70–73. It stores the tier as a `TEXT` value (`'EXTRACTED'`, `'INFERRED'`, or `'AMBIGUOUS'`), while the accompanying `confidence` column stores a real number defaulting to `1.0`. The column was added via the migration script in [`code_review_graph/migrations.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/migrations.py) (lines 234–236).