Skip to content

crp.provenance

Auto-generated reference for the crp.provenance subpackage.

provenance

crp.provenance

Decision Provenance Engine (DPE) - §7.14.3.

Orchestrates claim detection, attribution scoring, provenance chain construction, and report generation for every LLM dispatch window.

Usage::

from crp.provenance import DecisionProvenanceEngine, ProvenanceConfig

dpe = DecisionProvenanceEngine(config=ProvenanceConfig())
report = dpe.analyse(
    output_text="The server uses AES-256 encryption...",
    packed_facts=envelope_result.packed_facts,
    session_id=session.id,
    window_id=window.id,
)

AttributionType

Bases: str, Enum

How a claim maps to its knowledge source.

ClaimAttribution dataclass

Attribution result for a single claim in the LLM output.

Attributes:

Name Type Description
claim_text str

Text of the claim sentence.

claim_index int

Zero-based position of the claim in the output.

claim_type ClaimType

Classification of the claim.

attributed_facts list[FactScore]

Scored facts matched to this claim.

top_score float

Highest composite score among matched facts.

attribution_type AttributionType

How the claim maps to its source.

confidence float

Overall attribution confidence 0.0-1.0.

ClaimType

Bases: str, Enum

Classification of individual sentences/claims in LLM output.

EntailmentResult dataclass

Semantic entailment verdict for a single claim↔fact pair.

Uses Natural Language Inference (NLI) to determine whether a claim is semantically supported by its attributed source fact - beyond lexical overlap.

FactScore dataclass

Attribution score between a single claim and a single envelope fact.

Attributes:

Name Type Description
fact_id str

UUID of the attributed fact.

fact_text_preview str

First 120 characters of the fact text.

semantic_similarity float

Cosine similarity between claim and fact embeddings.

lexical_overlap float

N-gram token overlap ratio.

composite_score float

Weighted combination of semantic and lexical signals.

fact_source_window str

Window ID that produced the fact.

fact_extraction_stage int

Pipeline stage (1-6) that extracted the fact.

FidelityReport dataclass

Complete fidelity verification results for a dispatch window.

Answers: "Given source attribution, did the model faithfully represent the sources, or did it distort, fabricate, omit, or contradict?"

HallucinationRiskReport dataclass

Window-level hallucination risk report.

Answers: "For each claim, how likely is it that the model hallucinated, and what is the overall risk profile of this output?"

ProvenanceChain dataclass

Full provenance chain for one claim - linked list from output to input.

Attributes:

Name Type Description
claim_text str

Text of the claim being traced.

claim_index int

Position of the claim in the output.

attribution_type AttributionType

How the claim is attributed.

links list[ProvenanceLink]

Ordered list of provenance links from claim to task.

ProvenanceConfig dataclass

Configuration for the Decision Provenance Engine.

Attributes:

Name Type Description
enabled bool

Master switch for the entire DPE pipeline.

min_claim_length int

Minimum claim text length to analyse.

max_claims_per_output int

Maximum claims to process per window.

similarity_threshold float

Score below which attribution is PARAMETRIC.

mixed_threshold float

Boundary between MIXED and PARAMETRIC attribution.

min_grounding_semantic float

Minimum semantic score for grounding.

min_grounding_lexical float

Minimum lexical score for grounding.

min_mixed_semantic float

Minimum semantic score for mixed attribution.

lexical_weight float

Weight applied to lexical overlap.

semantic_weight float

Weight applied to semantic similarity.

generate_report bool

Whether to emit a structured report.

fact_preview_length int

Characters of fact text included in previews.

entailment_enabled bool

Whether to run semantic entailment verification.

entailment_model str

HuggingFace model id for entailment (if available).

entailment_contradiction_threshold float

P(contradiction) threshold for flagging.

risk_scoring_enabled bool

Whether to compute hallucination risk scores.

risk_weight_attribution float

Weight of attribution signal in risk score.

risk_weight_fidelity float

Weight of fidelity signal in risk score.

risk_weight_entailment float

Weight of entailment signal in risk score.

risk_weight_specificity float

Weight of specificity signal in risk score.

amplifiers_enabled bool

Whether regulatory amplifiers are active.

amplifier_gdpr_pii float

Multiplier when GDPR PII is present.

amplifier_eu_ai_act_high float

Multiplier for high-risk EU AI Act systems.

amplifier_sector float

Multiplier for financial/medical domains.

amplifier_agent_depth float

Multiplier for deep agent loops.

amplifier_cross_window float

Multiplier for cross-window contradictions.

amplifier_severe_repetition float

Multiplier for severe repetition.

rqa_enabled bool

Whether RQA stages 6-9 run.

rqa_weight_repetition float

Weight of repetition in composite quality score.

rqa_weight_completeness float

Weight of completeness in composite quality score.

rqa_weight_flow float

Weight of flow in composite quality score.

rqa_weight_coherence float

Weight of coherence in composite quality score.

Single link in a provenance chain - traces from claim → source.

Attributes:

Name Type Description
level str

Provenance level - "claim", "fact", "window", "envelope", or "task".

label str

Human-readable label for this link.

detail dict[str, Any]

Arbitrary key-value context for the link.

ProvenanceReport dataclass

Complete provenance report for a single dispatch window.

Attributes:

Name Type Description
session_id str

CRP session identifier.

window_id str

Dispatch window identifier.

timestamp float

Unix timestamp when the report was generated.

total_claims int

Total claims detected in the output.

factual_claims int

Number of factual claims.

opinion_claims int

Number of opinion claims.

procedural_claims int

Number of procedural claims.

hedge_claims int

Number of hedge claims.

connective_claims int

Number of connective claims.

context_grounded_count int

Claims grounded in envelope facts.

parametric_count int

Claims likely from model parametric knowledge.

mixed_count int

Claims with mixed context and parametric support.

uncertain_count int

Claims with low-confidence attribution.

grounding_ratio float

context_grounded / factual_claims.

attributions list[ClaimAttribution]

Per-claim attribution results.

chains list[ProvenanceChain]

Provenance chains for attributed claims.

chain_verified bool

Whether the provenance chain passed integrity checks.

output_token_count int

Approximate output token count.

envelope_facts_count int

Number of facts packed into the envelope.

fidelity FidelityReport | None

Fidelity verification report (distortions, fabrications, etc.).

entailment_results list[EntailmentResult]

Semantic entailment verdicts.

risk_report HallucinationRiskReport | None

Hallucination risk assessment.

coherence object | None

Cross-window coherence result (RQA stage 6).

repetition object | None

Repetition detection result (RQA stage 7).

completeness object | None

Completeness result (RQA stage 8).

flow object | None

Flow analysis result (RQA stage 9).

rqa object | None

Composite RQA quality score.

amplifier_result object | None

Regulatory amplifier result.

quality_tier str

Final quality tier after downgrade.

redispatch object | None

Re-dispatch decision.

AmplifierContext dataclass

The regulatory/agentic signals that may amplify the composite score.

AmplifierResult dataclass

The outcome of applying amplifiers to a base composite score.

amplified property

Return whether the amplified condition holds.

DetectedClaim dataclass

A single detected claim with its classification.

RQAResult dataclass

The computed RQA quality score and resulting tier cap.

headers property

Return the headers.

RQASignals dataclass

The four RQA-stage inputs (all 0.0–1.0).

CoherenceResult dataclass

Stage 6 output.

contradiction_ratio property

Fraction signal for the RQA score; 0.0 when none found.

has_critical property

Return whether this object has critical.

headers property

Return the headers.

CompletenessResult dataclass

Stage 8 output.

should_auto_continue property

Return whether this object should auto continue.

headers property

Return the headers.

FlowResult dataclass

Stage 9 output.

triggers_redispatch property

Return whether the triggers redispatch condition holds.

headers property

Return the headers.

RedispatchDecision dataclass

Whether a window should be re-dispatched and why (§19).

headers property

Return the headers.

RepetitionResult dataclass

Stage 7 output.

repetition_ratio property

RQA signal - the worse of the two overlap measures.

triggers_redispatch property

Return whether the triggers redispatch condition holds.

headers property

Return the headers.

ChainIntegrity

Bases: str, Enum

Result of verifying a window provenance chain.

ChainVerification dataclass

Outcome of a chain verification (CRP-SPEC-011 §3.3).

headers property

Return the headers.

WindowChainRecord dataclass

A window's stored HMAC plus the inputs needed to recompute it.

recompute(key, prev_window_hmac)

Recompute this window's expected HMAC.

Parameters:

Name Type Description Default
key bytes

HMAC key bytes.

required
prev_window_hmac str

Parent window HMAC (ignored for fan-in windows).

required

Returns:

Type Description
str

The recomputed HMAC string.

WindowHmacInput dataclass

Inputs to a window's summary HMAC.

HMAC-SHA256(session_id ‖ window_number ‖ timestamp ‖ response_hash ‖ dpe_report_hash ‖ prev_window_hmac, key) - CRP-SPEC-011 §2.3.

message()

Return the canonical message bytes used for window HMAC computation.

DecisionProvenanceEngine

Main entry point for the Decision Provenance Engine.

Ties together claim detection → attribution scoring → provenance chain construction → report generation into a single analyse() call.

config property

Current provenance configuration.

enabled property

Whether the DPE pipeline is enabled.

analyse(output_text, packed_facts, *, session_id='', window_id='', envelope_saturation=0.0, task_input_preview='', fact_metadata=None, query='', window_number=1, prior_window_texts=None, envelope_tier='', amplifier_context=None, upgrade_on_risk=False, revision_round=0, embedder=None, nli=None)

Run the full DPE pipeline and return a provenance report.

Parameters:

Name Type Description Default
output_text str

Raw LLM output text for this window.

required
packed_facts Sequence[PackedFact]

Facts that were packed into the envelope.

required
session_id str

Current CRP session ID.

''
window_id str

Current dispatch window ID.

''
envelope_saturation float

Envelope token saturation ratio (0.0-1.0).

0.0
task_input_preview str

First 120 chars of the task input.

''
fact_metadata dict[str, dict[str, object]] | None

Optional mapping of fact_id → metadata dict containing source_window_id and extraction_stage for chain enrichment.

None
query str

Original task query (used for RQA completeness analysis).

''
window_number int

Current window number in the session.

1
prior_window_texts Sequence[str] | None

Previous window outputs for cross-window analysis.

None
envelope_tier str

Envelope quality tier assigned by the packer.

''
amplifier_context AmplifierContext | None

Regulatory amplifier context for risk scoring.

None
upgrade_on_risk bool

Whether to trigger re-dispatch on elevated risk.

False
revision_round int

Current revision iteration count.

0
embedder Callable[[str], Sequence[float]] | None

Optional embedding callable for semantic RQA stages.

None
nli Callable[[str, str], float] | None

Optional NLI callable for contradiction detection.

None

Returns:

Type Description
ProvenanceReport

ProvenanceReport with attribution data, chains, fidelity, risk,

ProvenanceReport

and RQA results.

generate_markdown(report)

Generate a human-readable markdown provenance report.

Parameters:

Name Type Description Default
report ProvenanceReport

Provenance report to render.

required

Returns:

Type Description
str

Markdown-formatted provenance report string.

generate_json(report)

Generate a machine-readable JSON provenance report.

Parameters:

Name Type Description Default
report ProvenanceReport

Provenance report to serialise.

required

Returns:

Type Description
dict

Dict representation of the provenance report.

apply_amplifiers(base_score, context, *, config=None)

Apply regulatory amplifiers to base_score (CRP-SPEC-005 §17).

Amplifiers are multiplicative and compound; the result is clamped to [0.0, 1.0]. Returns an :class:AmplifierResult recording which amplifiers fired and the resulting risk band.

score_all_claims(claims, packed_facts, *, config=None, _embedder_override=None)

Score all claims against all envelope facts.

Only FACTUAL_CLAIM and HEDGE types are scored against facts. Other types (OPINION, PROCEDURAL, CONNECTIVE) are returned with empty attribution (they don't require source grounding).

Parameters:

Name Type Description Default
claims list[DetectedClaim]

All detected claims from claim_detector.

required
packed_facts list[PackedFact]

Facts that were packed into the envelope.

required
config ProvenanceConfig | None

Scoring configuration.

None
_embedder_override Any

Injected embedding model for testing.

None

Returns:

Type Description
list[ClaimAttribution]

List of ClaimAttribution objects in claim order.

detect_claims(text, *, min_length=10, max_claims=50)

Detect and classify all claims in LLM output text.

Parameters:

Name Type Description Default
text str

Raw LLM output text.

required
min_length int

Minimum character length for a claim (shorter → skipped).

10
max_claims int

Maximum number of claims to return (safety limit).

50

Returns:

Type Description
list[DetectedClaim]

List of DetectedClaim objects, ordered by position in text.

detect_contradictions(attributions, *, prior_claims=None, content_overlap_threshold=0.3)

Detect contradictions between claims.

Checks all factual/hedge claim pairs within the current window for three types of contradiction: 1. NEGATION - Same content + negation flip 2. NUMBER_CONFLICT - Same topic + different numbers 3. SEMANTIC - High word overlap + opposing sentiment

If prior_claims are provided, also checks current claims against them for cross-window contradictions.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions for the current window.

required
prior_claims list[str] | None

Optional list of claim texts from prior windows.

None
content_overlap_threshold float

Minimum content word overlap ratio (Jaccard) to consider two claims as discussing the same topic.

0.3

Returns:

Type Description
list[ContradictionResult]

List of ContradictionResult - one per detected contradiction.

detect_distortions(attributions, packed_facts)

Detect distortions in context-grounded claims.

For each CONTEXT_GROUNDED or MIXED attribution, compares the claim against its top source fact looking for subtle but critical changes: numbers altered, negations flipped, qualifiers dropped, etc.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from attribution_scorer.

required
packed_facts list[PackedFact]

All envelope facts (for full-text lookup).

required

Returns:

Type Description
list[DistortionResult]

List of DistortionResult - one per detected distortion.

list[DistortionResult]

Empty list means no distortions found (perfect fidelity).

verify_entailment(attributions, packed_facts, *, config=None, _model_override=None)

Verify semantic entailment between grounded claims and their source facts.

For each CONTEXT_GROUNDED or MIXED claim, runs NLI inference against the top source fact. Returns an EntailmentResult per checked pair.

The NLI model classifies (premise=fact, hypothesis=claim): - ENTAILED: claim logically follows from fact - CONTRADICTION: claim conflicts with fact - NEUTRAL: claim is unrelated to fact

When the NLI model is unavailable, falls back to a heuristic based on word overlap + negation detection. The used_model field in each result indicates which method was used.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from the DPE pipeline.

required
packed_facts Sequence[PackedFact]

All envelope facts (for full-text lookup).

required
config ProvenanceConfig | None

ProvenanceConfig (controls model name, thresholds).

None
_model_override Any

Override NLI model for testing (internal).

None

Returns:

Type Description
list[EntailmentResult]

List of EntailmentResult - one per checked claim-fact pair.

detect_fabrications(attributions, packed_facts)

Detect fabricated entities in claims that appear in no source fact.

Examines FACTUAL_CLAIM and HEDGE claims for specific entities (numbers, percentages, dates, proper nouns, citations) and flags those not found in any envelope fact.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions.

required
packed_facts Sequence[PackedFact]

All envelope facts.

required

Returns:

Type Description
list[FabricationResult]

List of FabricationResult - one per fabricated entity found.

score_hallucination_risk(attributions, *, fidelity=None, entailment_results=None, config=None)

Score hallucination risk for every claim in the output.

Combines four independent signals per claim
  1. Attribution - how well-sourced is the claim?
  2. Fidelity - did lexical checks find distortions?
  3. Entailment - does NLI confirm semantic support?
  4. Specificity - how specific (and thus risky) is the claim?

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from the DPE pipeline.

required
fidelity FidelityReport | None

FidelityReport from the fidelity verification layer.

None
entailment_results list[EntailmentResult] | None

EntailmentResults from the entailment verifier.

None
config ProvenanceConfig | None

ProvenanceConfig with risk weight configuration.

None

Returns:

Type Description
HallucinationRiskReport

HallucinationRiskReport with per-claim assessments and aggregates.

analyze_omissions(attributions, packed_facts, *, attribution_floor=0.2)

Identify envelope facts that the model ignored.

For each packed fact, finds the maximum attribution score any output claim gave it. Facts with a maximum score below attribution_floor are considered omitted.

Results are sorted by fact relevance score descending - the most important omissions first.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from the attribution scorer.

required
packed_facts Sequence[PackedFact]

All facts that were packed into the envelope.

required
attribution_floor float

Maximum composite score below which a fact is considered "not used" (default 0.20).

0.2

Returns:

Type Description
list[OmissionResult]

List of OmissionResult sorted by importance (highest first).

build_all_chains(attributions, *, session_id='', window_id='', envelope_saturation=0.0, envelope_facts_included=0, task_input_preview='')

Build provenance chains for all attributed claims.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

All claim attributions from scorer.

required
session_id str

Current session ID.

''
window_id str

Current window ID.

''
envelope_saturation float

Envelope saturation ratio.

0.0
envelope_facts_included int

Facts in envelope.

0
task_input_preview str

First 120 chars of task input.

''

Returns:

Type Description
list[ProvenanceChain]

List of ProvenanceChain objects, one per attribution.

enrich_fact_metadata(attributions, fact_metadata)

Enrich FactScore entries with fact provenance metadata (in-place).

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

List of claim attributions to enrich.

required
fact_metadata dict[str, dict[str, Any]]

Dict mapping fact_id → metadata dict. Expected keys include source_window_id (str), extraction_stage (int), and optionally confidence (float).

required

Returns:

Type Description
None

None. Updates attributed_facts on each attribution in place.

generate_json_report(report)

Generate a machine-readable JSON provenance report.

Suitable for API responses, database storage, or integration with compliance management systems.

Parameters:

Name Type Description Default
report ProvenanceReport

Complete provenance report from the DPE pipeline.

required

Returns:

Type Description
dict[str, Any]

JSON-serializable dictionary.

generate_markdown_report(report)

Generate a human-readable markdown provenance report.

Suitable for regulatory audit, compliance review, or integration into documentation. Format follows EU AI Act Article 12 logging requirements.

Parameters:

Name Type Description Default
report ProvenanceReport

Complete provenance report from the DPE pipeline.

required

Returns:

Type Description
str

Markdown-formatted report string.

compute_quality_score(signals, *, config=None)

Compute the RQA composite quality score (CRP-SPEC-005 §18.2).

downgrade_tier(envelope_tier, quality_score)

Downgrade envelope_tier if the RQA quality score requires it (§18.4).

The emitted tier is the worse of the envelope tier and the score-derived ceiling - e.g. envelope A with score 0.62 → emitted B.

analyze_flow(current_response, prior_response, *, window_number=2, embedder=None)

Stage 9 (§11): flow & continuity for continuation windows (window>1).

detect_cross_window_contradictions(current_response, prior_window_texts, *, nli=None, threshold=0.75)

Stage 6 (§8): detect contradictions between current and prior windows.

detect_repetition(current_response, prior_responses, *, embedder=None, semantic_threshold=0.92)

Stage 7 (§9): n-gram + semantic overlap with prior responses.

evaluate_redispatch(*, repetition=None, coherence=None, flow=None, risk_upgrade_triggered=False, upgrade_on_risk=False, revision_round=0, max_revisions=2)

Decide whether to re-dispatch a window (§19.1-19.2).

Triggers: upgrade-on-risk + risk threshold, SEVERE repetition, CRITICAL cross-window contradiction, or flow_score < 0.30. Capped at max_revisions per window; re-dispatch does NOT decrement the safety budget (§19.3).

verify_completeness(query, session_responses, *, decompose=None, embedder=None, coverage_threshold=0.7)

Stage 8 (§10): does the cumulative answer cover every sub-query?

build_fan_in_window_hmac(*, session_id, window_number, timestamp, response_hash, dpe_report_hash, parent_hmacs, key)

Compute a fan-in window HMAC merging multiple parents (§9.3).

Parent HMACs are sorted lexicographically and joined with | so the result is deterministic regardless of child completion order.

build_window_hmac(inp, key)

Compute a window summary HMAC (linear chain extension, §9.1).

verify_window_chain(records, key)

Verify a session's complete window chain from root to leaf (§3.1).

Returns UNVERIFIED for an empty/single-root chain that has nothing to chain from, BROKEN (with broken_at_window) on the first mismatch, and VALID when every link verifies.

verify_window_partial(record, parent_window_hmac, key)

Verify a single window against its parent's HMAC (§3.2).

Auditors holding only one window and its parent tip get PARTIAL on success (the full chain was not checked) or BROKEN on mismatch.

collect_quality_headers(report)

Merge every RQA quality/safety header emitted by the stage results.

Includes CRP-Quality-Repetition / -Completeness / -Flow / -Score and CRP-Safety-Contradictions when the corresponding stage ran (CRP-SPEC-005 §8-11, §18, §20).

provenance.amplifiers

crp.provenance.amplifiers

Regulatory amplifiers for the hallucination composite (CRP-SPEC-005 §17).

After the base composite hallucination score is computed, regulatory amplifiers multiply it upward when the regulatory context raises the stakes of a given risk level (PII exposure, EU AI Act HIGH-risk domain, financial/medical sector, deep agent chains, cross-window contradictions, severe repetition). The amplified score is capped at 1.0 and may push the window into a higher :class:HallucinationRisk band.

Amplifier values are configuration (kept symbolic in the public spec); the conditions are specified.

AmplifierContext dataclass

The regulatory/agentic signals that may amplify the composite score.

AmplifierResult dataclass

The outcome of applying amplifiers to a base composite score.

amplified property

Return whether the amplified condition holds.

apply_amplifiers(base_score, context, *, config=None)

Apply regulatory amplifiers to base_score (CRP-SPEC-005 §17).

Amplifiers are multiplicative and compound; the result is clamped to [0.0, 1.0]. Returns an :class:AmplifierResult recording which amplifiers fired and the resulting risk band.

provenance.attribution_scorer

crp.provenance.attribution_scorer

Attribution Scorer - map claims to envelope facts (§7.14.3).

For each factual claim in the LLM output, scores how likely it came from each envelope fact vs. parametric knowledge. Uses two signals:

  1. Semantic similarity: When available, uses dense sentence-transformer embeddings (all-MiniLM-L6-v2, 384-dim) for genuine semantic comparison. Falls back to hash-projected bag-of-words when the model is unavailable.
  2. Lexical overlap: Token-level Jaccard overlap - fast, complements semantic similarity for surface-level attribution.
The composite score is a weighted blend

composite = semantic_weight × semantic + lexical_weight × lexical

Claims with no fact scoring above similarity_threshold are flagged as PARAMETRIC (likely from model training data). Claims with a top score between mixed_threshold and similarity_threshold are MIXED.

score_claim_against_facts(claim, packed_facts, *, config=None, _embedder_override=None)

Score a single claim against all envelope facts.

Attempts to use dense sentence-transformer embeddings for semantic similarity. Falls back to hash-projected bag-of-words if the embedding model is unavailable.

Parameters:

Name Type Description Default
claim DetectedClaim

Detected claim from claim_detector.

required
packed_facts list[PackedFact]

Facts that were packed into the envelope.

required
config ProvenanceConfig | None

Scoring configuration (thresholds, weights).

None
_embedder_override Any

Injected embedding model for testing.

None

Returns:

Type Description
ClaimAttribution

ClaimAttribution with ranked fact scores and attribution type.

score_all_claims(claims, packed_facts, *, config=None, _embedder_override=None)

Score all claims against all envelope facts.

Only FACTUAL_CLAIM and HEDGE types are scored against facts. Other types (OPINION, PROCEDURAL, CONNECTIVE) are returned with empty attribution (they don't require source grounding).

Parameters:

Name Type Description Default
claims list[DetectedClaim]

All detected claims from claim_detector.

required
packed_facts list[PackedFact]

Facts that were packed into the envelope.

required
config ProvenanceConfig | None

Scoring configuration.

None
_embedder_override Any

Injected embedding model for testing.

None

Returns:

Type Description
list[ClaimAttribution]

List of ClaimAttribution objects in claim order.

provenance.calibration

crp.provenance.calibration

Calibration harnesses for CRP scoring thresholds.

Provides ground-truth evaluation of attribution and hallucination risk scorers so that hard-coded thresholds can be tuned against labelled data instead of arbitrary constants.

AttributionExample dataclass

A labelled claim/fact pair for attribution calibration.

HallucinationExample dataclass

A labelled claim for hallucination-risk calibration.

ThresholdMetrics dataclass

Binary-classification metrics at a single threshold.

precision property

Return the precision.

recall property

Return the recall.

f1 property

Return the f1.

fpr property

Return the fpr.

fnr property

Return the fnr.

CalibrationResult dataclass

Outcome of evaluating a scorer over a labelled dataset.

AttributionCalibrationHarness

Calibrate attribution thresholds against ground-truth labels.

A claim is considered "grounded" if its top composite score is at or above the threshold. Labels must be grounded (positive) or ungrounded (negative).

add(claim_text, facts, label)

Add a labelled claim/fact pair to the calibration set.

Parameters:

Name Type Description Default
claim_text str

The claim to evaluate.

required
facts list[PackedFact]

Candidate facts to attribute the claim against.

required
label Literal['grounded', 'ungrounded']

Ground-truth label, either grounded or ungrounded.

required

score()

Return [(label, top_score), ...] for every example.

evaluate(thresholds=None)

Compute precision/recall/FPR/FNR across thresholds and AUC.

HallucinationCalibrationHarness

Calibrate hallucination-risk thresholds against ground-truth labels.

The risk score (higher = more likely hallucinated) is taken from the window mean risk score produced by :func:score_hallucination_risk. Labels must be hallucinated (positive) or faithful (negative).

add(claim, label)

Add a labelled claim for hallucination-risk calibration.

Parameters:

Name Type Description Default
claim ClaimAttribution

Claim attribution result to evaluate.

required
label Literal['hallucinated', 'faithful']

Ground-truth label, either hallucinated or faithful.

required

score()

Return [(label, mean_risk_score), ...] for every example.

evaluate(thresholds=None)

Compute precision/recall/FPR/FNR across thresholds and AUC.

Parameters:

Name Type Description Default
thresholds list[float] | None

Thresholds to evaluate. Defaults to a standard set.

None

Returns:

Type Description
CalibrationResult

Calibration result with per-threshold metrics and best F1 threshold.

provenance.claim_detector

crp.provenance.claim_detector

Claim Detector - segment LLM output into attributable claims (§7.14.3).

Splits model output into individual sentences/claims and classifies each as: - FACTUAL_CLAIM: verifiable factual assertion (requires attribution) - OPINION: subjective view or judgment - PROCEDURAL: action or instruction - HEDGE: qualified/uncertain statement - CONNECTIVE: structural/transitional text

Uses rule-based heuristics - no ML model required for classification, keeping overhead under 5ms for typical outputs.

DetectedClaim dataclass

A single detected claim with its classification.

split_into_sentences(text)

Split text into sentences.

Uses regex-based sentence boundary detection with abbreviation handling and paragraph boundary support.

Returns:

Type Description
list[str]

List of sentence strings, stripped of leading/trailing whitespace.

classify_claim(text)

Classify a single sentence/claim by type.

Returns:

Type Description
ClaimType

Tuple of (ClaimType, confidence_score).

float

confidence_score is 0.0-1.0 indicating classification confidence.

detect_claims(text, *, min_length=10, max_claims=50)

Detect and classify all claims in LLM output text.

Parameters:

Name Type Description Default
text str

Raw LLM output text.

required
min_length int

Minimum character length for a claim (shorter → skipped).

10
max_claims int

Maximum number of claims to return (safety limit).

50

Returns:

Type Description
list[DetectedClaim]

List of DetectedClaim objects, ordered by position in text.

provenance.contradiction_detector

crp.provenance.contradiction_detector

Contradiction Detector - catch self-contradictions in LLM output.

Within the same dispatch window

Claim 2: "The system is secure." Claim 7: "The system has critical vulnerabilities."

Across windows (if prior claims supplied): Window 1: "Revenue increased 10%." Window 3: "Revenue declined significantly."

This module detects contradictions through three signals
  1. NEGATION conflicts - same content words + negation flip
  2. NUMBER conflicts - same entity referenced with different values
  3. SEMANTIC conflicts - high similarity + opposing sentiment signals

detect_contradictions(attributions, *, prior_claims=None, content_overlap_threshold=0.3)

Detect contradictions between claims.

Checks all factual/hedge claim pairs within the current window for three types of contradiction: 1. NEGATION - Same content + negation flip 2. NUMBER_CONFLICT - Same topic + different numbers 3. SEMANTIC - High word overlap + opposing sentiment

If prior_claims are provided, also checks current claims against them for cross-window contradictions.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions for the current window.

required
prior_claims list[str] | None

Optional list of claim texts from prior windows.

None
content_overlap_threshold float

Minimum content word overlap ratio (Jaccard) to consider two claims as discussing the same topic.

0.3

Returns:

Type Description
list[ContradictionResult]

List of ContradictionResult - one per detected contradiction.

provenance.distortion_detector

crp.provenance.distortion_detector

Distortion Detector - catch when grounded claims misrepresent source facts.

The most dangerous failure in AI attribution: a claim is scored as CONTEXT_GROUNDED (high similarity to a source fact) but the model has subtly CHANGED a key detail - a number, a negation, a qualifier. The auditor sees "grounded, confidence 0.89" and trusts it. But the claim is wrong.

This module catches six distortion types
  • NUMBER_CHANGED: "10%" → "15%"
  • NEGATION_FLIP: "is safe" → "is not safe"
  • QUALIFIER_DROPPED: "approximately 10" → "10" (false precision)
  • QUALIFIER_ADDED: "10" → "always 10" (over-generalisation)
  • SCOPE_CHANGED: "in Q3" → "annually"
  • ENTITY_SUBSTITUTED: "Company A" → "Company B"

detect_distortions(attributions, packed_facts)

Detect distortions in context-grounded claims.

For each CONTEXT_GROUNDED or MIXED attribution, compares the claim against its top source fact looking for subtle but critical changes: numbers altered, negations flipped, qualifiers dropped, etc.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from attribution_scorer.

required
packed_facts list[PackedFact]

All envelope facts (for full-text lookup).

required

Returns:

Type Description
list[DistortionResult]

List of DistortionResult - one per detected distortion.

list[DistortionResult]

Empty list means no distortions found (perfect fidelity).

provenance.entailment_verifier

crp.provenance.entailment_verifier

Semantic Entailment Verifier - ML-powered claim↔fact verification (§7.14.3).

THE PROBLEM rule-based fidelity cannot solve:

Fact:  "The treatment significantly reduced patient mortality."
Claim: "The treatment showed some positive outcomes for patients."

Lexically similar. Zero number distortions. No negation flip. But the claim lost critical specificity - a regulator reading the claim would make a DIFFERENT decision than one reading the fact.

Rule-based detectors catch surface edits: 10→25, "safe"→"not safe". They cannot detect: - Specificity loss ("reduced mortality" → "positive outcomes") - Causation inflation ("correlation observed" → "X causes Y") - Scope generalisation ("in clinical settings" → "broadly") - Hedging removal ("might reduce" → "reduces")

THE SOLUTION: Natural Language Inference (NLI).

A lightweight cross-encoder NLI model (~80 MB, CPU-only, <50 ms/pair) classifies each (premise=fact, hypothesis=claim) pair as: - ENTAILED - claim logically follows from the fact ✅ - NEUTRAL - claim is unrelated to the fact ⚠️ - CONTRADICTION - claim conflicts with the fact ❌

This gives CRP a semantic fidelity layer that sits above the lexical layer, catching meaning-level distortions no regex can reach.

When the NLI model is unavailable (not installed, resource-constrained), the verifier degrades gracefully to a heuristic based on bag-of-words similarity - still better than nothing, while flagging that the result is heuristic-only.

reset_model_cache()

Reset the module-level model cache (for testing).

verify_entailment(attributions, packed_facts, *, config=None, _model_override=None)

Verify semantic entailment between grounded claims and their source facts.

For each CONTEXT_GROUNDED or MIXED claim, runs NLI inference against the top source fact. Returns an EntailmentResult per checked pair.

The NLI model classifies (premise=fact, hypothesis=claim): - ENTAILED: claim logically follows from fact - CONTRADICTION: claim conflicts with fact - NEUTRAL: claim is unrelated to fact

When the NLI model is unavailable, falls back to a heuristic based on word overlap + negation detection. The used_model field in each result indicates which method was used.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from the DPE pipeline.

required
packed_facts Sequence[PackedFact]

All envelope facts (for full-text lookup).

required
config ProvenanceConfig | None

ProvenanceConfig (controls model name, thresholds).

None
_model_override Any

Override NLI model for testing (internal).

None

Returns:

Type Description
list[EntailmentResult]

List of EntailmentResult - one per checked claim-fact pair.

provenance.fabrication_detector

crp.provenance.fabrication_detector

Fabrication Detector - catch invented entities not in any source fact.

The model outputs "According to the 2024 Johnson report, revenue grew 23%." The envelope contains no entity "Johnson", no year "2024", no number "23". The model fabricated a citation to sound authoritative.

This module extracts specific entities from claims (numbers, percentages, dates, proper nouns, citations) and cross-references them against ALL envelope facts. Entities found in no source are flagged as fabrications.

detect_fabrications(attributions, packed_facts)

Detect fabricated entities in claims that appear in no source fact.

Examines FACTUAL_CLAIM and HEDGE claims for specific entities (numbers, percentages, dates, proper nouns, citations) and flags those not found in any envelope fact.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions.

required
packed_facts Sequence[PackedFact]

All envelope facts.

required

Returns:

Type Description
list[FabricationResult]

List of FabricationResult - one per fabricated entity found.

provenance.hallucination_scorer

crp.provenance.hallucination_scorer

Hallucination Risk Scorer - per-claim composite risk assessment (§7.14.3).

WHY THIS EXISTS

An auditor reviewing AI output asks ONE question:

"How likely is it that THIS claim is a hallucination?"
Currently they must mentally fuse
  • Attribution score (was it grounded?)
  • Fidelity score (was the source distorted?)
  • Entailment verdict (does NLI confirm semantic support?)
  • Claim specificity (is this a precise claim that's dangerous if wrong?)

This module fuses those four signals into ONE auditable risk score per claim, with a clear risk level (LOW / MEDIUM / HIGH / CRITICAL) and a list of human-readable risk factors explaining WHY.

RISK FORMULA

risk = 1.0 - (w_a * attribution + w_f * fidelity + w_e * entailment + w_s * (1 - specificity))
Where
  • attribution: top_score from DPE (0-1, higher = better sourced)
  • fidelity: 1.0 if no distortions/fabrications for this claim, else degraded
  • entailment: P(ENTAILED) from NLI (0-1, higher = semantically confirmed)
  • specificity: density of specific entities in the claim (higher = riskier)
  • w_a, w_f, w_e, w_s: configurable weights (default 0.30, 0.25, 0.30, 0.15)
Risk levels
  • risk < 0.25 → LOW
  • risk < 0.50 → MEDIUM
  • risk < 0.75 → HIGH
  • risk ≥ 0.75 → CRITICAL

compute_specificity(claim_text)

Compute how specific a claim is (0.0=vague, 1.0=highly specific).

More specific claims are riskier if unsupported - "Revenue grew 23.4% in Q3 2024 according to Deloitte" is far more dangerous wrong than "Performance improved."

Specificity = min(1.0, entity_count / 5) - normalised density of numbers, dates, proper nouns, and measurements.

score_hallucination_risk(attributions, *, fidelity=None, entailment_results=None, config=None)

Score hallucination risk for every claim in the output.

Combines four independent signals per claim
  1. Attribution - how well-sourced is the claim?
  2. Fidelity - did lexical checks find distortions?
  3. Entailment - does NLI confirm semantic support?
  4. Specificity - how specific (and thus risky) is the claim?

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from the DPE pipeline.

required
fidelity FidelityReport | None

FidelityReport from the fidelity verification layer.

None
entailment_results list[EntailmentResult] | None

EntailmentResults from the entailment verifier.

None
config ProvenanceConfig | None

ProvenanceConfig with risk weight configuration.

None

Returns:

Type Description
HallucinationRiskReport

HallucinationRiskReport with per-claim assessments and aggregates.

provenance.omission_analyzer

crp.provenance.omission_analyzer

Omission Analyzer - detect when the model silently ignores important facts.

15 high-priority facts went into the envelope. The model used 4 and ignored 11. If Fact #3 was "Product has a known safety defect" and the model never mentioned it - that is a material omission.

This module identifies which envelope facts received NO attribution from any output claim and ranks them by importance (original packing score). High-importance omissions are flagged for manual review.

analyze_omissions(attributions, packed_facts, *, attribution_floor=0.2)

Identify envelope facts that the model ignored.

For each packed fact, finds the maximum attribution score any output claim gave it. Facts with a maximum score below attribution_floor are considered omitted.

Results are sorted by fact relevance score descending - the most important omissions first.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

Scored claim attributions from the attribution scorer.

required
packed_facts Sequence[PackedFact]

All facts that were packed into the envelope.

required
attribution_floor float

Maximum composite score below which a fact is considered "not used" (default 0.20).

0.2

Returns:

Type Description
list[OmissionResult]

List of OmissionResult sorted by importance (highest first).

provenance.provenance_chain

crp.provenance.provenance_chain

Provenance Chain Builder - link claims → facts → windows → tasks (§7.14.3).

Constructs full provenance chains from attribution results, tracing each claim back through the CRP pipeline:

Claim → attributed Fact → source Window → Envelope → original Task

Also enriches FactScore objects with fact metadata (source_window_id, extraction_stage) when a WarmStateStore or fact lookup is available.

enrich_fact_metadata(attributions, fact_metadata)

Enrich FactScore entries with fact provenance metadata (in-place).

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

List of claim attributions to enrich.

required
fact_metadata dict[str, dict[str, Any]]

Dict mapping fact_id → metadata dict. Expected keys include source_window_id (str), extraction_stage (int), and optionally confidence (float).

required

Returns:

Type Description
None

None. Updates attributed_facts on each attribution in place.

build_provenance_chain(attribution, *, session_id='', window_id='', envelope_saturation=0.0, envelope_facts_included=0, task_input_preview='')

Build a full provenance chain for a single claim attribution.

The chain traces from the claim back to its source

Claim → Fact → Window → Envelope → Task

For PARAMETRIC claims (no supporting fact), the chain is shorter.

Parameters:

Name Type Description Default
attribution ClaimAttribution

Scored claim attribution from attribution_scorer.

required
session_id str

Current session ID.

''
window_id str

Current window ID.

''
envelope_saturation float

Envelope saturation ratio.

0.0
envelope_facts_included int

Number of facts in the envelope.

0
task_input_preview str

First 120 chars of the task input.

''

Returns:

Type Description
ProvenanceChain

ProvenanceChain with linked provenance levels from claim to task.

build_all_chains(attributions, *, session_id='', window_id='', envelope_saturation=0.0, envelope_facts_included=0, task_input_preview='')

Build provenance chains for all attributed claims.

Parameters:

Name Type Description Default
attributions list[ClaimAttribution]

All claim attributions from scorer.

required
session_id str

Current session ID.

''
window_id str

Current window ID.

''
envelope_saturation float

Envelope saturation ratio.

0.0
envelope_facts_included int

Facts in envelope.

0
task_input_preview str

First 120 chars of task input.

''

Returns:

Type Description
list[ProvenanceChain]

List of ProvenanceChain objects, one per attribution.

provenance.report_generator

crp.provenance.report_generator

Report Generator - human-readable provenance reports (§7.14.3).

Produces regulator-auditable decision provenance reports in markdown and JSON formats. Reports answer: "For each claim in the AI output, what evidence supported it and how confident are we in that attribution?"

generate_markdown_report(report)

Generate a human-readable markdown provenance report.

Suitable for regulatory audit, compliance review, or integration into documentation. Format follows EU AI Act Article 12 logging requirements.

Parameters:

Name Type Description Default
report ProvenanceReport

Complete provenance report from the DPE pipeline.

required

Returns:

Type Description
str

Markdown-formatted report string.

generate_json_report(report)

Generate a machine-readable JSON provenance report.

Suitable for API responses, database storage, or integration with compliance management systems.

Parameters:

Name Type Description Default
report ProvenanceReport

Complete provenance report from the DPE pipeline.

required

Returns:

Type Description
dict[str, Any]

JSON-serializable dictionary.

provenance.rqa

crp.provenance.rqa

Response Quality Assurance composite score (CRP-SPEC-005 §18).

The RQA quality score is distinct from the safety hallucination score: safety measures truthfulness, quality measures usefulness. It fuses the four RQA-stage signals - repetition (Stage 7), completeness (Stage 8), flow (Stage 9), and cross-window coherence (Stage 6) - into one CRP-Quality-Score and can downgrade the emitted CRP-Context-Quality-Tier.

quality_score = 0.25·(1−repetition) + 0.35·completeness
              + 0.25·flow          + 0.15·(1−contradiction)

RQASignals dataclass

The four RQA-stage inputs (all 0.0–1.0).

RQAResult dataclass

The computed RQA quality score and resulting tier cap.

headers property

Return the headers.

max_tier_for_score(quality_score)

Return the best quality tier permitted by quality_score (§18.4).

compute_quality_score(signals, *, config=None)

Compute the RQA composite quality score (CRP-SPEC-005 §18.2).

downgrade_tier(envelope_tier, quality_score)

Downgrade envelope_tier if the RQA quality score requires it (§18.4).

The emitted tier is the worse of the envelope tier and the score-derived ceiling - e.g. envelope A with score 0.62 → emitted B.

provenance.rqa_stages

crp.provenance.rqa_stages

RQA Stages 6-9 + re-dispatch protocol (CRP-SPEC-005 §8-11, §19).

These are the Response Quality Assurance stages that operate across windows in a session (as opposed to the single-window fidelity/attribution stages):

  • Stage 6 - Cross-window coherence (§8): contradictions vs prior windows.
  • Stage 7 - Repetition (§9): 4-gram + semantic overlap with prior windows.
  • Stage 8 - Completeness (§10): sub-query coverage of the cumulative answer.
  • Stage 9 - Flow & continuity (§11): opening/topic/register/transition.
  • Re-dispatch (§19): trigger conditions + augmented-prompt construction.

The module is callback-pluggable and degrades gracefully. A caller MAY pass an embedder (text → vector) and/or an nli (premise, hypothesis → P(contradiction)); when absent, lexical fallbacks (bag-of-words cosine, Jaccard, 4-gram overlap, rule-based contradiction) are used so the engine never hard-depends on a model.

CoherenceResult dataclass

Stage 6 output.

contradiction_ratio property

Fraction signal for the RQA score; 0.0 when none found.

has_critical property

Return whether this object has critical.

headers property

Return the headers.

RepetitionResult dataclass

Stage 7 output.

repetition_ratio property

RQA signal - the worse of the two overlap measures.

triggers_redispatch property

Return whether the triggers redispatch condition holds.

headers property

Return the headers.

CompletenessResult dataclass

Stage 8 output.

should_auto_continue property

Return whether this object should auto continue.

headers property

Return the headers.

FlowResult dataclass

Stage 9 output.

triggers_redispatch property

Return whether the triggers redispatch condition holds.

headers property

Return the headers.

RedispatchDecision dataclass

Whether a window should be re-dispatched and why (§19).

headers property

Return the headers.

detect_cross_window_contradictions(current_response, prior_window_texts, *, nli=None, threshold=0.75)

Stage 6 (§8): detect contradictions between current and prior windows.

detect_repetition(current_response, prior_responses, *, embedder=None, semantic_threshold=0.92)

Stage 7 (§9): n-gram + semantic overlap with prior responses.

verify_completeness(query, session_responses, *, decompose=None, embedder=None, coverage_threshold=0.7)

Stage 8 (§10): does the cumulative answer cover every sub-query?

analyze_flow(current_response, prior_response, *, window_number=2, embedder=None)

Stage 9 (§11): flow & continuity for continuation windows (window>1).

evaluate_redispatch(*, repetition=None, coherence=None, flow=None, risk_upgrade_triggered=False, upgrade_on_risk=False, revision_round=0, max_revisions=2)

Decide whether to re-dispatch a window (§19.1-19.2).

Triggers: upgrade-on-risk + risk threshold, SEVERE repetition, CRITICAL cross-window contradiction, or flow_score < 0.30. Capped at max_revisions per window; re-dispatch does NOT decrement the safety budget (§19.3).

build_anti_repetition_prompt(prior_summary)

Augmented system prompt for SEVERE repetition re-dispatch (§9.3).

build_flow_prompt(prior_last_sentences)

Augmented system prompt for flow remediation (§11.5 Option A).

provenance.window_chain

crp.provenance.window_chain

Window-level HMAC provenance chain (CRP-SPEC-004 §9, CRP-SPEC-011 §2-3).

Each window in a session carries a summary HMAC that chains from its parent window(s). The chain is tamper-evident: modifying or removing any ancestor invalidates every descendant. This module computes window HMACs (linear and fan-in) and verifies the chain, emitting the CRP-Provenance-Chain-Integrity status defined in CRP-SPEC-011 §3.3.

PRIVATE REFERENCE IMPLEMENTATION - SPEC internals are not published.

ChainIntegrity

Bases: str, Enum

Result of verifying a window provenance chain.

WindowHmacInput dataclass

Inputs to a window's summary HMAC.

HMAC-SHA256(session_id ‖ window_number ‖ timestamp ‖ response_hash ‖ dpe_report_hash ‖ prev_window_hmac, key) - CRP-SPEC-011 §2.3.

message()

Return the canonical message bytes used for window HMAC computation.

WindowChainRecord dataclass

A window's stored HMAC plus the inputs needed to recompute it.

recompute(key, prev_window_hmac)

Recompute this window's expected HMAC.

Parameters:

Name Type Description Default
key bytes

HMAC key bytes.

required
prev_window_hmac str

Parent window HMAC (ignored for fan-in windows).

required

Returns:

Type Description
str

The recomputed HMAC string.

ChainVerification dataclass

Outcome of a chain verification (CRP-SPEC-011 §3.3).

headers property

Return the headers.

build_window_hmac(inp, key)

Compute a window summary HMAC (linear chain extension, §9.1).

build_fan_in_window_hmac(*, session_id, window_number, timestamp, response_hash, dpe_report_hash, parent_hmacs, key)

Compute a fan-in window HMAC merging multiple parents (§9.3).

Parent HMACs are sorted lexicographically and joined with | so the result is deterministic regardless of child completion order.

verify_window_chain(records, key)

Verify a session's complete window chain from root to leaf (§3.1).

Returns UNVERIFIED for an empty/single-root chain that has nothing to chain from, BROKEN (with broken_at_window) on the first mismatch, and VALID when every link verifies.

verify_window_partial(record, parent_window_hmac, key)

Verify a single window against its parent's HMAC (§3.2).

Auditors holding only one window and its parent tip get PARTIAL on success (the full chain was not checked) or BROKEN on mismatch.