Dimensions
How facts are categorized by what they affect. Read more
When Unfault analyzes your code, it produces facts. A fact is a discrete observation about your codebase: something Unfault noticed, measured, or inferred.
Facts are the foundation of everything Unfault tells you. They’re not opinions or suggestions. They’re observations that you can query, filter, aggregate, and reason about.
A fact is a typed signal with context. Each fact has:
Facts are objective. They describe what is, not what should be. The interpretation, whether something needs action, is up to you.
The most common fact type today is a finding: a pattern detected by a rule.
fact_type: rule_findingrule_id: python.http.missing_timeoutseverity: Highdimension: stabilityfile: src/client.pyline: 42payload: title: "HTTP call has no timeout" description: "This requests.get call will block indefinitely if the server doesn't respond." fix_preview: "Add timeout parameter: requests.get(url, timeout=30)"Findings tell you “here’s a pattern that often causes problems.” They’re actionable observations with suggested fixes.
When you link SLOs to your codebase, Unfault can capture their current state as facts:
fact_type: slo_stateslo_name: "API Availability"provider: gcptarget_percent: 99.9current_percent: 99.87error_budget_remaining: -0.03dimension: observabilityroutes_covered: 15SLO facts tell you “here’s what your observability systems are reporting.” They connect your code to production reality.
The fact model is extensible. Future fact types might include:
Each fact type adds a new lens for understanding your code.
If you’ve used Unfault before, you’re familiar with “findings.” Here’s how they relate:
| Findings | Facts | |
|---|---|---|
| Scope | Rule-detected patterns | Any observation about your code |
| Action | Usually suggests a fix | May or may not be actionable |
| Tone | ”Here’s a problem" | "Here’s what I observed” |
| Examples | Missing timeout, N+1 query | Finding, SLO state, dependency version |
Findings are facts. They’re the rule_finding fact type. But facts are broader: they’re the general model for everything Unfault knows.
The unfault ask command queries across all fact types:
# Ask about findingsunfault ask "What are my main stability concerns?"
# Ask about patternsunfault ask "How do we handle HTTP timeouts?"As more fact types are added, ask becomes more powerful. You’ll be able to ask about SLO compliance, dependency health, and more, all in natural language.
Every analysis session produces facts. When you run unfault review, the facts from that run are stored and associated with your workspace.
Session (Jan 10, 2025)├── 12 rule_finding facts├── 2 slo_state facts (coming)└── Graph dataThis history lets you track how facts change over time. Are findings increasing or decreasing? Is your SLO compliance improving?
Unfault aggregates facts into insights: high-level summaries that help you understand patterns across your codebase.
For example, facts might show 47 individual findings across 185 files. An insight might tell you “the src/clients/ directory has the highest concentration of stability issues, primarily missing timeouts and circuit breakers.”
Insights are derived from facts. As more fact types are added, insights become richer.
The shift to facts reflects how we think about code understanding:
Facts are composable. You can combine findings with SLO data to ask “which stability findings affect routes that are close to burning error budget?” That question spans two fact types.
Facts are queryable. Instead of just getting a report, you can ask questions. The fact model makes your codebase knowledge queryable.
Facts tell a story. A finding says “here’s a problem.” A collection of facts says “here’s what’s happening in your system.” The story is richer than any single observation.
Facts scale. As Unfault learns more about your code, it produces more fact types. The model grows without changing fundamentally.