Grounding & Trust Tiers
How CodeRadius tells you where every fact in the graph came from, what supports it, and how much to trust it. Covers the dashboard quality dot, the cr review pending triage workflow, and the diagnostic filters.
Grounding & Trust Tiers
Every node and every edge inferred by CodeRadius carries a grounding stamp answering three questions:
- Source: who or what produced the fact (a deterministic AST walk, an LLM call, a customer-declared override).
- Evidence: what supports it (which extractors fired, which heuristic fallbacks ran, which welders merged predecessors).
- Quality: how much you should trust it (categorical tier: Verified, Strong, Probable, Weak, Guess).
The grounding system replaces the older "confidence percentage" model. Floats compound badly across pipeline hops, and a 0.8 from an AST extractor and a 0.8 from an LLM are not the same kind of 0.8. The categorical model surfaces why an entity is trusted (or not) without forcing operators to mentally translate probability scores.
The 5 Trust Tiers
Every inferred entity (MessageChannel, DataContainer, APIEndpoint, etc.) is stamped with one of five tiers. On the dashboard, the tier is shown as a small colored dot.
| Dot | Label | Meaning |
|---|---|---|
| ● green | Verified | Direct evidence in source or contract (a decorator, an OpenAPI spec, a declared catalog entry). The strongest tier. |
| ● light green | Strong | Multiple extractors agree. Composite of static analysis + LLM confirmation. |
| ● amber | Probable | Single signal, plausible. Typically an LLM extraction that passed sanitizer guards. |
| ● orange | Weak | Inferred from indirect evidence. The engine had to guess. |
| ● red | Guess | No direct evidence; surfaced only when the engine had to invent something. Treat with skepticism. |
The dot color is the visual language; the label appears in the inspect drawer and the popover. Hover the dot anywhere to see the descriptive tagline.
Where You See It
Dashboard
Graph cards (the radial blast-radius view): each inferred node has a small colored dot in its bottom-right corner. Cluster supernodes show the worst quality among their members ("at least one node in this cluster is speculative").
Inspect drawer (click any node): the Grounding section reads as one line:
GROUNDING
● Verified Static code analysisHover the dot for the tagline ("Direct evidence in source or contract"). Hover the source label for the longer explanation of how that extractor works.
Popover (single-click any node): same composed line in the status row.
Suppressed on structural entities
The dot is hidden by default on structural labels (Repository, Service, SourceFile, Function, Class, ...) because they are uniformly Verified by definition: they're direct AST artefacts. Showing the dot on every file and function would drown out the decision-relevant tiers on inferred entities.
The 7 Source Types
The dot tells you how much to trust; the source label tells you how the fact was established. The dashboard shows the source as a muted label next to the dot ("Static code analysis", "LLM inference", etc.).
| Internal id | Label | How to read it |
|---|---|---|
ast | Static code analysis | Parsed directly from source (decorator, function signature, deterministic config walk). |
heuristic | Naming heuristic | Pattern matched (file naming, symbol convention). The weakest static signal. |
llm | LLM inference | Extracted by a language model from code semantics. |
composite | Cross-verified | Multiple extractors independently agreed. |
declared | Declared in catalog | Asserted by coderadius.yaml or a service catalog entry. |
infra | Infrastructure match | Confirmed by a live infrastructure snapshot (RabbitMQ admin, K8s, Terraform). |
runtime | Runtime trace | Observed in production traffic (OTel span). |
Operator Workflows
See the trust distribution after every sync
Every cr analyze code run prints a grounding breakdown at the end:
Grounding distribution
MessageChannel 3 exact, 1 high, 1 medium, 0 low, 0 speculative
DataContainer 7 exact, 4 high, 2 medium, 1 low, 0 speculative needs-review: 1
APIEndpoint 27 exact, 0 high, 0 medium, 0 low, 0 speculativeA needs-review count > 0 means the engine has flagged entities for human triage (see cr review pending below).
Triage flagged entities
cr review pending
cr review pending --label MessageChannel
cr review pending --quality-at-least medium --source llmLists every node with needsReview = true, grouped by label. Flags entities the engine wants a human to adjudicate (ambiguous welds, weak LLM-only signals with no static cross-check, sanitizer fallbacks that fired on already-shaky source).
Filters narrow the result:
--label <name>: restrict to a single inferred label (MessageChannel, DataContainer, ...).--quality-at-least <tier>: keep only entities whose quality is at least the given tier (exact ≥ high ≥ medium ≥ low ≥ speculative).--source <s>: keep only entities whose grounding source matches. Repeat the flag for multiple sources.
Nothing in the database is changed by these commands; they are read-only triage views.
Filter coverage diagnostics
The diagnostic dump accepts the same filter vocabulary:
bun run scripts/diag-graph-coverage.ts --quality-at-least high
bun run scripts/diag-graph-coverage.ts --source ast
bun run scripts/diag-graph-coverage.ts --repo my-repo --source llmUseful queries:
- "Show me only the entities I should trust" →
--quality-at-least high. - "Show me what the LLM inferred (so I can sanity-check it)" →
--source llm. - "Show me what came from the AST (the deterministic, high-trust baseline)" →
--source ast.
The output dumps every inferred node label (DataContainer, MessageChannel, APIEndpoint, Datastore, ExternalAPI) with its grounding columns alongside the existing discriminators.
What Drives the Tier?
The engine assigns quality categorically based on which pipeline path produced the fact. The matrix:
| If the fact came from | Source | Quality |
|---|---|---|
| Pure AST extraction (provider, decorator, deterministic walk) | ast | Verified |
| Static analyzer + registry hit | composite | Strong |
| LLM extraction with full static context in the prompt | composite | Strong |
| LLM extraction with weak static context | llm | Probable |
| LLM extraction surviving only sanitizer guards by exclusion | llm | Weak |
| Sanitizer applied a fallback (env-stem normalize, name promotion) | (upstream) | demoted one tier |
| Welder merged two predecessors | composite | min(predecessors) |
coderadius.yaml declared | declared | Verified |
| Infrastructure snapshot match | infra | Verified |
| Runtime trace match | runtime | Verified |
Cross-source composite promotion is capped at Strong: Verified is reserved for single-source ground truth (pure AST, declared, infra, runtime). The cap prevents the engine from claiming the strongest tier just because two unrelated signals agreed.
Inspecting an Entity's Evidence
The Inspect Drawer (open by clicking any node) shows the full grounding block. The descriptive tooltip on the dot lists:
- The tagline for the tier ("Direct evidence in source or contract").
- The source's detail line ("Parsed directly from source: decorator, function signature, AST walk").
- The extractor identities that contributed (
symfony-messenger-php@v1,unified-analyzer@v1, ...). Each is versioned so a prompt or regex change produces a new identity, leaving stale entries queryable.
If the entity was welded from multiple predecessors, the evidence block will list the merged URNs. If a sanitizer transform fired, the applied fallback is listed (e.g. env-var-stem-normalize means the engine canonicalized acme.inventory{envSuffix}.X.Y to acme.inventory.X.Y).
FAQ
Why categorical and not a percentage?
Because a 0.8 from an AST extractor and a 0.8 from an LLM mean different things, and multiplying them along path computations produces silently-wrong math. The categorical tiers are explicit assignments per pipeline path, not derived statistics.
Can I override the tier on a specific entity?
Yes, via coderadius.yaml declaration. An entity asserted in the catalog gets source: declared, quality: Verified and overrides whatever the engine inferred.
Why is everything in my graph "Verified"?
You probably just opened the dashboard on a fresh sync of well-typed code (OpenAPI specs, decorators, AmqpConfig YAML). That's the happy path. The decision-relevant tiers (Probable, Weak, Guess) appear when the engine had to infer from ambiguous code.
Why is everything "Probable"?
The codebase exposes weak static signals (no decorators, no config files, no contracts), so the LLM is doing most of the inference. Consider declaring the canonical entities in coderadius.yaml to promote them to Verified.
The needs-review count is large. What now?
Run cr review pending to see the flagged entities and their grounding. The most common causes:
- The engine welded an ambiguous match.
- An LLM-inferred entity has no static cross-check.
- The defensive
untagged@v1default fired: grepevidence_extractors CONTAINS 'untagged@v1'to find them; a mutation was invoked without a grounding argument.
In all cases, you can either accept the engine's inference (no action), refine the source code so the static extractor catches it, or declare the entity in coderadius.yaml to promote it.