Blast Radius

Blast radius measures the impact of a claim state change. High-impact changes are escalated to humans for review, keeping critical decisions under human control.

What is Blast Radius?

When a claim changes state (e.g., from SUPPORTED to OUTDATED), it may affect other claims that depend on it. The blast radius is the count of all transitively affected claims.

Claim A (SUPPORTED → OUTDATED)
    │
    ├── Claim B depends on A (HARD)     ─► OUTDATED
    │       │
    │       └── Claim D depends on B    ─► STALE
    │
    ├── Claim C depends on A (SOFT)     ─► CONTESTED
    │       │
    │       ├── Claim E depends on C    ─► SUSPECT
    │       └── Claim F depends on C    ─► SUSPECT
    │
    └── Claim G depends on A (DERIVED)  ─► STALE

Blast Radius = 6 (claims B, C, D, E, F, G)

Calculating Blast Radius

TruthKeeper calculates blast radius by traversing the dependency graph:

from truthkeeper import BlastRadiusCalculator

calculator = BlastRadiusCalculator(client)

# Calculate blast radius for a potential change
analysis = await calculator.analyze(
    claim_id="clm_abc123",
    new_state="OUTDATED"
)

print(f"Direct dependents: {analysis.direct_count}")
print(f"Transitive dependents: {analysis.transitive_count}")
print(f"Total blast radius: {analysis.total}")
print(f"Risk score: {analysis.risk_score}")

Risk Scoring

The risk score combines blast radius with claim importance:

risk_score = (
    blast_radius * 0.4 +
    avg_dependent_confidence * 0.3 +
    critical_path_factor * 0.3
)

# critical_path_factor is higher if affected claims
# are on critical paths (e.g., auth, payment)

Human Review Thresholds

Claims with high blast radius are queued for human review before state changes are applied:

Blast RadiusAction
< 5Auto-apply state change
5-20Apply with notification
20-50Queue for review (normal priority)
> 50Queue for review (high priority)
# Configure thresholds
client.configure_blast_radius(
    auto_apply_threshold=5,
    notify_threshold=20,
    review_threshold=50,
    critical_tags=["auth", "payment", "security"]
)

Human Review Queue

When blast radius exceeds thresholds, changes go to the review queue:

# Get pending reviews
reviews = await client.get_review_queue(
    min_blast_radius=20,
    status="PENDING"
)

for review in reviews:
    print(f"Claim: {review.claim.content}")
    print(f"Proposed change: {review.old_state} → {review.new_state}")
    print(f"Blast radius: {review.blast_radius}")
    print(f"Affected claims: {review.affected_claims}")
    print("---")

# Submit a review decision
await client.submit_review(
    review_id=review.id,
    decision="APPROVE",  # or "REJECT", "MODIFY"
    reason="Verified the refactoring is complete",
    reviewer="alice@example.com"
)

Cascade Simulation

Before making changes, you can simulate the cascade to understand the impact:

# Simulate what would happen if this source changes
simulation = await client.simulate_source_change(
    source="file://src/auth/service.py",
    change_type="MODIFIED"
)

print(f"Claims that would become STALE: {simulation.stale_count}")
print(f"Claims that would become OUTDATED: {simulation.outdated_count}")
print(f"Total blast radius: {simulation.blast_radius}")

# See the cascade tree
for claim in simulation.affected_claims:
    print(f"  {claim.id}: {claim.current_state} → {claim.new_state}")
    print(f"    Reason: {claim.cascade_reason}")

Notifications

Configure notifications for high-impact changes:

client.configure_notifications(
    channels={
        "slack": {
            "webhook_url": "https://hooks.slack.com/...",
            "min_blast_radius": 10
        },
        "email": {
            "recipients": ["team@example.com"],
            "min_blast_radius": 20
        }
    },
    templates={
        "high_impact_change": """
            High-impact change detected!

            Claim: {claim.content}
            Change: {old_state} → {new_state}
            Blast radius: {blast_radius}

            Review at: {review_url}
        """
    }
)

Blast Radius Visualization

TruthKeeper can export blast radius data for visualization:

# Export as graph
graph = await client.export_blast_radius_graph(
    claim_id="clm_abc123",
    format="graphviz"
)

# Or as JSON for custom visualization
data = await client.export_blast_radius_graph(
    claim_id="clm_abc123",
    format="json"
)
# Returns: {"nodes": [...], "edges": [...], "levels": [...]}

Best Practices

Reducing Blast Radius

  • Use fine-grained dependencies: Depend on specific symbols, not entire files
  • Prefer SOFT over HARD: When the relationship is contextual, not critical
  • Break up large claims: Smaller claims have smaller blast radii
  • Regular maintenance: Remove outdated claims to shrink the graph

Managing High-Impact Claims

  • Tag critical claims: ["critical", "security", "payment"]
  • Set lower thresholds for critical areas
  • Require multiple reviewers for highest-impact changes
  • Maintain audit logs for compliance

Next Steps