Uncertainty States & Entropy Scoring
Status: Implemented for reachability facts in Signals (tier calculation and tier-aware risk score). Verified against commit
942a18727c(2026-09-26). Re-verify with:grep -n 'CalculateTier\|GetRiskModifier\|CalculateRiskScore' -A12 src/Signals/StellaOps.Signals/Lattice/UncertaintyTier.cs; grep -n 'class UncertaintyTierGateOptions' -A20 src/Policy/StellaOps.Policy.Engine/Gates/PolicyGateOptions.csOwnership note: this guide describes Signals uncertainty states, not the Unknowns service. TheUnknownsRegistryevidence type below is Signals’ own unresolved-symbol count, not a call tounknowns-web. Owners: Signals Guild · Policy Guild · UI Guild.
Audience: Signals, Policy, and Console engineers who consume or act on uncertainty data.
Stella Ops treats missing data and untrusted evidence as first-class uncertainty states, not silent false negatives. Signals persists uncertainty state entries alongside reachability facts and derives a deterministic riskScore that increases when entropy is high. Policy gates and the Console then reason over those states explicitly, so a release decision can never quietly rest on an unproven “not affected”.
1. Core states (extensible)
| Code | Name | Meaning |
|---|---|---|
U1 | MissingSymbolResolution | Unresolved symbols/edges prevent a complete reachability proof. |
U2 | MissingPurl | Package identity/version is ambiguous (lockfile absent, heuristics only). |
U3 | UntrustedAdvisory | Advisory source lacks provenance/corroboration. |
U4 | Unknown | No analyzers have processed this subject; baseline uncertainty. |
Each state records:
entropy(0…1)evidence[]list pointing to analyzers/heuristics/sources- optional
timestamp(UTC)
1.1 Uncertainty Tiers (v1 — Sprint 0401)
Uncertainty states are grouped into tiers that determine policy thresholds and UI treatment.
Tier Definitions
| Tier | Entropy Range | States | Risk Modifier | Policy Implication |
|---|---|---|---|---|
| T1 (High) | 0.7 - 1.0 | U1 (high), U4 | +50% | Block “not_affected”, require human review |
| T2 (Medium) | 0.4 - 0.69 | U1 (medium), U2 | +25% | Warn on “not_affected”, flag for review |
| T3 (Low) | 0.1 - 0.39 | U2 (low), U3 | +10% | Allow “not_affected” with advisory note |
| T4 (Negligible) | 0.0 - 0.09 | U3 (low) | +0% | Normal processing, no special handling |
Tier Assignment Rules
U1 (MissingSymbolResolution):
entropy >= 0.7→ T1 (>30% unknowns in callgraph)entropy >= 0.4→ T2 (15-30% unknowns)entropy < 0.4→ T3 (<15% unknowns)
U2 (MissingPurl):
entropy >= 0.5→ T2 (>50% packages unresolved)entropy < 0.5→ T3 (<50% packages unresolved)
U3 (UntrustedAdvisory):
entropy >= 0.6→ T3 (no corroboration)entropy < 0.6→ T4 (partial corroboration)
U4 (Unknown):
- Always T1 (no analysis performed = maximum uncertainty)
Aggregate Tier Calculation
When multiple uncertainty states exist, the aggregate tier is the maximum (most severe):
aggregateTier = max(tier(state) for state in uncertainty.states)
2. JSON shape
{
"uncertainty": {
"states": [
{
"code": "U1",
"name": "MissingSymbolResolution",
"entropy": 0.72,
"timestamp": "2025-11-12T14:12:00Z",
"evidence": [
{
"type": "UnknownsRegistry",
"sourceId": "signals.unknowns",
"detail": "unknownsCount=12;unknownsPressure=0.375"
}
]
}
]
}
}
3. Risk score math (Signals)
Signals computes a riskScore deterministically during reachability recompute:
meanEntropy = avg(uncertainty.states[].entropy) // 0 when no states
entropyBoost = clamp(meanEntropy * k, 0 .. boostCeiling)
riskScore = clamp(baseScore * (1 + entropyBoost), 0 .. 1)
Where:
baseScoreis the average of per-target reachability state scores (before unknowns penalty).kdefaults to0.5(Signals:Scoring:UncertaintyEntropyMultiplier).boostCeilingdefaults to0.5(Signals:Scoring:UncertaintyBoostCeiling).
§5 adds the tier modifier; the implemented formula is the §5 one.
4. Policy guidance (high level)
Uncertainty should bias decisions away from “not affected” when evidence is missing:
- High entropy (
U1with highentropy) should lead to under investigation and drive remediation (upload symbols, run probes, close unknowns). - Low entropy should allow normal confidence-based gates.
See the reachability lattice guide for the current reachability score model and the Signals reachability contract for the Signals API contract.
5. Tier-Based Risk Score (v1 — Sprint 0401)
Risk Score Formula
Building on §3, the v1 risk score incorporates tier-based modifiers:
tierModifier = {
T1: 0.50,
T2: 0.25,
T3: 0.10,
T4: 0.00
}[aggregateTier]
riskScore = clamp(baseScore * (1 + tierModifier + entropyBoost), 0 .. 1)
Where:
baseScoreis the average of per-target reachability state scorestierModifieris the tier-based risk increaseentropyBoostis the existing entropy-based boost (§3)
Example Calculation
Given:
- baseScore = 0.4 (moderate reachability)
- uncertainty.states = [
{code: "U1", entropy: 0.72}, // T1 tier
{code: "U3", entropy: 0.45} // T3 tier
]
- aggregateTier = T1 (max of T1, T3)
- tierModifier = 0.50
meanEntropy = (0.72 + 0.45) / 2 = 0.585
entropyBoost = clamp(0.585 * 0.5, 0 .. 0.5) = 0.2925
riskScore = clamp(0.4 * (1 + 0.50 + 0.2925), 0 .. 1)
= clamp(0.4 * 1.7925, 0 .. 1)
= clamp(0.717, 0 .. 1)
= 0.717
Policy gate behavior per tier
The Policy Engine uncertainty-tier gate is configured by PolicyGates:UncertaintyTier (UncertaintyTierGateOptions in src/Policy/StellaOps.Policy.Engine/Gates/PolicyGateOptions.cs):
| Option | Default | Effect |
|---|---|---|
BlockT1ForNotAffected | true | T1 uncertainty blocks a not_affected claim |
WarnT2ForNotAffected | true | T2 uncertainty warns on a not_affected claim |
ReviewT1ForAffected | true | T1 uncertainty on an affected claim requires an explicit override |
Signals exposes the same per-tier semantics through UncertaintyTierExtensions.BlocksNotAffected (T1) and RequiresWarning (T1 and T2).
6. JSON Schema (v1)
Extended schema with tier information:
{
"uncertainty": {
"states": [
{
"code": "U1",
"name": "MissingSymbolResolution",
"entropy": 0.72,
"tier": "T1",
"timestamp": "2025-12-13T10:00:00Z",
"evidence": [
{
"type": "UnknownsRegistry",
"sourceId": "signals.unknowns",
"detail": "unknownsCount=45;totalSymbols=125;unknownsPressure=0.36"
}
]
},
{
"code": "U4",
"name": "Unknown",
"entropy": 1.0,
"tier": "T1",
"timestamp": "2025-12-13T10:00:00Z",
"evidence": [
{
"type": "NoAnalysis",
"sourceId": "signals.bootstrap",
"detail": "subject not yet analyzed"
}
]
}
],
"aggregateTier": "T1",
"riskScore": 0.717,
"computedAt": "2025-12-13T10:00:00Z"
}
}
7. Implementation Pointers
- Tier calculation and risk score:
UncertaintyTierCalculator(CalculateTier,CalculateAggregateTier,CalculateRiskScore) insrc/Signals/StellaOps.Signals/Lattice/UncertaintyTier.cs - Where it runs:
src/Signals/StellaOps.Signals/Services/ReachabilityScoringService.csbuilds the uncertainty document (U1 from the unknowns pressure) during reachability recompute - Policy gate options:
UncertaintyTierGateOptionsinsrc/Policy/StellaOps.Policy.Engine/Gates/PolicyGateOptions.cs - Policy integration: Policy DSL §12 — Uncertainty Gates
- Lattice integration: reachability lattice guide §9 for v1 lattice states
8. Policy Guidance (v1 — Sprint 0401)
Uncertainty gates enforce evidence-quality thresholds in the Policy Engine. When entropy is too high or evidence is missing, policies block or downgrade VEX decisions.
8.1 Gate Mapping
| Gate | Uncertainty State | Tier | Policy Action |
|---|---|---|---|
U1 | MissingSymbolResolution | T1/T2 | Block not_affected, require review |
U2 | MissingPurl | T2/T3 | Warn on not_affected, add review flag |
U3 | UntrustedAdvisory | T3/T4 | Advisory caveat, no blocking |
8.2 Policy rules and configuration
Gate configuration is the PolicyGates:UncertaintyTier section described in §5. For DSL rules that act on uncertainty, see Policy DSL §12 — Uncertainty Gates, which owns the rule syntax.
9. Remediation Actions
Each uncertainty state has recommended remediation steps:
| State | Code | Remediation |
|---|---|---|
| MissingSymbolResolution | U1 | Supply debug symbols or resolve the unresolved call-graph nodes |
| MissingPurl | U2 | Provide a lockfile or an SBOM with exact package coordinates |
| UntrustedAdvisory | U3 | Corroborate the advisory from a trusted source |
| Unknown | U4 | Run the initial analysis (scan) |
9.1 Automated Remediation Flow
1. Policy blocks decision with U1/U2 gate
↓
2. Console/CLI shows remediation hint
↓
3. User performs the remediation (§9 table)
↓
4. Signals recomputes uncertainty states
↓
5. Risk score updates, tier may drop
↓
6. Policy re-evaluates, decision may proceed
9.2 Remediation Priority
When multiple uncertainty states exist, prioritize by tier:
- T1 states first — Block all exclusions until resolved
- T2 states — May proceed with warnings if T1 cleared
- T3/T4 states — Normal flow with caveats
Content originates from Sprint 0401; re-verified against src/ on 2026-09-26.
