4.0 KiB
4.0 KiB
Exponential Confidence Decay for Unknown Reachability (Half-Life Calculator)
Module
Policy
Status
IMPLEMENTED
Description
Exponential half-life decay of confidence scores implemented in DecayedConfidenceCalculator with formula exp(-ln(2) * ageDays / halfLifeDays), configurable half-life (default 14 days), floor value, and metrics emission. Includes ObservationDecay models, uncertainty scoring, signal state tracking, and property-based tests. Integrated into policy determinization gate.
Implementation Details
- DecayedConfidenceCalculator:
src/Policy/__Libraries/StellaOps.Policy.Determinization/Scoring/DecayedConfidenceCalculator.cs(sealed class implementsIDecayedConfidenceCalculator)Calculate(baseConfidence, ageDays, halfLifeDays=14.0, floor=0.1)-- applies exponential decay:max(floor, baseConfidence * exp(-ln(2) * ageDays / halfLifeDays))CalculateDecayFactor(ageDays, halfLifeDays=14.0)-- returns raw decay factor clamped to [0.0, 1.0]- Parameter validation: baseConfidence [0.0-1.0], ageDays >= 0, halfLifeDays > 0, floor [0.0-1.0]
- Metrics emission:
stellaops_determinization_decay_multiplierhistogram with half_life_days and age_days tags
- ObservationDecay:
src/Policy/__Libraries/StellaOps.Policy.Determinization/Models/ObservationDecay.cs(sealed record)- ObservedAt, RefreshedAt, HalfLifeDays (default 14.0), Floor (default 0.35), StalenessThreshold (default 0.50)
CalculateDecay(now)computes current multiplier:max(Floor, exp(-ln(2) * ageDays / HalfLifeDays))CheckIsStale(now)returns true if decay multiplier < StalenessThreshold- Factory methods:
Create(observedAt, refreshedAt?),Fresh(now),WithSettings(observedAt, refreshedAt, halfLifeDays, floor, stalenessThreshold) - Pre-computed fields: AgeDays, DecayedMultiplier, IsStale, LastSignalUpdate
- DeterminizationOptions:
src/Policy/__Libraries/StellaOps.Policy.Determinization/DeterminizationOptions.cs-- global decay configuration - DeterminizationContext:
src/Policy/__Libraries/StellaOps.Policy.Determinization/Models/DeterminizationContext.cs-- evaluation context with observation state - DeterminizationResult:
src/Policy/__Libraries/StellaOps.Policy.Determinization/Models/DeterminizationResult.cs-- result including decayed confidence - DeterminizationGate:
src/Policy/StellaOps.Policy.Engine/Gates/Determinization/DeterminizationGate.cs-- policy gate using DecayedConfidenceCalculator - Property-based tests:
src/Policy/__Tests/StellaOps.Policy.Determinization.Tests/PropertyTests/DecayPropertyTests.cs-- FsCheck property tests for decay formula - Unit tests:
src/Policy/__Tests/StellaOps.Policy.Determinization.Tests/DecayedConfidenceCalculatorTests.cs - ObservationDecay tests:
src/Policy/__Tests/StellaOps.Policy.Determinization.Tests/Models/ObservationDecayTests.cs
E2E Test Plan
- Calculate decay with baseConfidence=1.0, ageDays=0: verify result=1.0 (no decay)
- Calculate decay with baseConfidence=1.0, ageDays=14.0, halfLifeDays=14.0: verify result~0.5 (one half-life)
- Calculate decay with baseConfidence=1.0, ageDays=28.0, halfLifeDays=14.0: verify result~0.25 (two half-lives)
- Calculate decay with baseConfidence=0.8, ageDays=100.0, halfLifeDays=14.0: verify result=floor (0.1)
- Calculate decay with custom floor=0.3: verify result never drops below 0.3
- CalculateDecayFactor with ageDays=7, halfLifeDays=14: verify factor~0.707
- ObservationDecay.Create with observedAt 30 days ago: verify CheckIsStale(now)=true (decay < 0.50 staleness threshold)
- ObservationDecay.Fresh(now): verify CalculateDecay(now)=1.0, CheckIsStale(now)=false
- ObservationDecay.WithSettings(halfLifeDays=7, floor=0.2, stalenessThreshold=0.60): verify custom settings applied
- Verify DeterminizationGate uses decayed confidence in gate evaluation; stale observation triggers gate warning or block
- Verify
stellaops_determinization_decay_multiplierhistogram metric is recorded after Calculate() call