Explainable Provenance¶
trails.explain traces PROV-O provenance chains and produces human-readable
explanations of how a result was derived. It builds citation graphs, propagates
confidence scores through derivation chains, and supports counterfactual analysis
("what would change if this source were removed?").
Operates entirely on existing provenance triples -- no AI/LLM dependency.
See ADR-0038 for the full design rationale.
Quick start¶
from trails.explain import (
explain_result,
citation_graph,
propagate_confidence,
counterfactual,
format_explanation,
)
# Trace an activity and get a structured explanation
explanation = explain_result(store, activity_iri, max_depth=10)
print(f"Confidence: {explanation.confidence:.2f}")
print(f"Citations: {len(explanation.citations)}")
# Render as markdown or plain text
print(format_explanation(explanation, fmt="markdown"))
# Build a citation graph: {node_iri: [activities that used it]}
cites = citation_graph(store, activity_iri)
# Walk derivation chains and compute confidence per node
confidences = propagate_confidence(store, node_iri, base_confidence=0.9)
# {"node_iri_1": 0.9, "derived_node": 0.81, ...}
# Counterfactual: what breaks if we remove a source?
affected = counterfactual(store, remove_iri="urn:source:42", activity_iri=root_iri)
for entry in affected:
print(f" Activity {entry['activity']} depends via {entry['dependency_path']}")
Key types¶
| Type | Description |
|---|---|
Citation |
Reference from an activity to a source node: node_iri, node_type, relevance, accessed_by |
ReasoningStep |
One step in a reasoning chain: step_number, action, cited_nodes, confidence_contribution |
Explanation |
Structured result: answer, citations, confidence, reasoning_chain, provenance_iris |
API¶
| Function | Signature | Description |
|---|---|---|
explain_result |
(store, activity_iri, *, max_depth=10) -> Explanation |
Trace provenance and produce a structured explanation |
citation_graph |
(store, activity_iri, *, max_depth=10) -> dict[str, list[str]] |
Map of {node_iri: [activities that used it]} |
propagate_confidence |
(store, node_iri, base_confidence=1.0, *, max_depth=10) -> dict[str, float] |
Walk derivation chains, compute per-node confidence |
counterfactual |
(store, remove_iri, activity_iri, *, max_depth=10) -> list[dict] |
Estimate impact of removing a source node |
format_explanation |
(explanation, fmt="text") -> str |
Render as "text", "markdown", or "json" |