Verification, Repair, and Rejection

Explain this chapter with AI

Copy this prompt into ChatGPT, Claude, Gemini, a local model, or another AI.

Apply this chapter with AI

Copy this prompt into ChatGPT, Claude, Gemini, a local model, or another AI.

Chapter 12 gave the system a control plane.

It can now say:

commitment = HOLD
next_action = VERIFY

or:

commitment = HOLD
next_action = RETRIEVE

or:

commitment = HOLD
next_action = REFINE

or:

commitment = DENY
response_mode = REJECTION

Those are policy decisions.

They are not yet recovery implementations.

The obvious implementation is dangerously tempting:

The answer failed a check.
Ask the model to fix it.

But the model that produced the first unsupported statement can produce a second unsupported statement while “correcting” it.

A fluent repair is not evidence that the repair is correct.

A more confident repair is not evidence that the repair is correct.

A longer explanation of the repair is not evidence that the repair is correct.

The system needs a stricter loop:

    graph TD
    CS[candidate state] --> V[verification]
    V --> FR[localized failure record]
    FR --> RC[repair contract]
    RC --> RA[repair action]
    RA --> NCS[NEW CANDIDATE STATE]
    NCS --> IM[invalidate affected measurements]
    IM --> RM[re-measure]
    RM --> RAUTH[re-authorize]
  

Repair changes the candidate state, so the system must invalidate affected measurements and require authorization again.

The central invariant is:

$$ c_i \xrightarrow{\text{repair}} c_{i+1} $$
does **not** imply:
$$ \operatorname{authorized}(c_{i+1}). $$
Instead:
$$ \operatorname{commitment}(c_{i+1}) = \text{UNDECIDED} $$
until the new state has passed through measurement and policy again.

A repaired claim is still a claim.


Where we are

The book now has:

GENERATOR
    ↓
CANDIDATE
    ↓
MEASUREMENTS
    ↓
RELIABILITY RECORD
    ↓
POLICY
    ↓
COMMITMENT + NEXT ACTION

Chapter 13 implements several of those next actions:

VERIFY
RETRIEVE
REFINE
REJECT_CANDIDATE
ABSTAIN
REVIEW

The engineering problem is not merely:

How do we improve a bad answer?

It is:

How do we improve a bad answer without silently discarding the reliability guarantees we just built?

That requires six disciplines:

1. verify with evidence-bearing signals
2. localize the failure at the right granularity
3. choose a repair whose dependency boundary is understood
4. treat the result as a new candidate state
5. revalidate every affected dependency
6. stop when recovery no longer makes structural progress

1. Start with the failure, not the repair

Consider:

CANDIDATE cand_v1

c1  Q2 revenue was $43.8 million.
c2  Second-half demand is expected to improve.
c3  Q3 revenue was approximately $46 million.

The admissible evidence contains:

Q2 revenue = $43.8 million
second-half outlook = improve

but no Q3 revenue value.

The correct verifier state is not:

c3 = FALSE

because the evidence does not establish that $46 million is false.

It is:

c3 = INSUFFICIENT_EVIDENCE

A deterministic reference controller used in this chapter produced:

cand_v1 {
  'c1': 'SUPPORTED',
  'c2': 'SUPPORTED',
  'c3': 'INSUFFICIENT_EVIDENCE'
}

Two recovery strategies then behaved very differently.

Omission

cand_v1 {
  'c1': 'SUPPORTED',
  'c2': 'SUPPORTED',
  'c3': 'INSUFFICIENT_EVIDENCE'
}
cand_v2 {
  'c1': 'SUPPORTED',
  'c2': 'SUPPORTED'
}
terminal=PERMIT

Hedging

cand_v1 {
  'c1': 'SUPPORTED',
  'c2': 'SUPPORTED',
  'c3': 'INSUFFICIENT_EVIDENCE'
}
cand_v2 {
  'c1': 'SUPPORTED',
  'c2': 'SUPPORTED',
  'c3': 'INSUFFICIENT_EVIDENCE'
}
cand_v3 {
  'c1': 'SUPPORTED',
  'c2': 'SUPPORTED',
  'c3': 'INSUFFICIENT_EVIDENCE'
}
terminal=ABSTAIN reason=CYCLE_DETECTED

The second strategy changed the wording:

Q3 revenue was approximately $46 million.

into:

Q3 revenue may have been approximately $46 million.

The evidence state did not improve.

That is the first demonstration of the chapter’s main rule:

A successful edit is not a successful verification.


2. Verification is not self-confidence

Suppose we ask the generator:

Are you sure?

It may answer:

Yes. Based on the trend, approximately $46 million is reasonable.

Nothing has been verified.

We have sampled another output from the same generative process.

The useful distinction is:

SELF-ASSERTED CONFIDENCE
What does the model say about its own answer?

VERIFICATION
What external or mechanically grounded evidence
bears on the answer?

Strong verification signals can include:

authoritative retrieved evidence
database lookup
schema validation
compiler result
unit test
calculator
formal solver
runtime state
source provenance
human review

A second LLM judge may also contribute.

But it is not automatically independent merely because it has a different role name.

Useful questions include:

generator-independent?
model-family-independent?
source-lineage-independent?
mechanically checkable?

A 2024 critical survey of LLM self-correction found little general evidence for successful prompted intrinsic self-correction outside unusually favorable tasks, while reliable external feedback substantially improves the conditions under which correction works.[1]

So:

Do not confuse another generation with an external or mechanically grounded check.


3. Use a verification state model

Recovery becomes much safer when the verifier preserves why a claim did not pass.

A useful vocabulary is:

State Meaning
SUPPORTED admissible evidence licenses the claim
REFUTED admissible evidence contradicts the claim
INSUFFICIENT_EVIDENCE current evidence cannot establish the claim
CONFLICTING credible evidence disagrees
UNRESOLVED verifier cannot determine the relation
NOT_VERIFIABLE no available verification procedure can establish the claim

This matters because the recovery action changes.

REFUTED
β†’ correct or remove the proposition

INSUFFICIENT_EVIDENCE
β†’ retrieve, narrow to supported content, omit, or abstain

CONFLICTING
β†’ reconcile / verify sources

NOT_VERIFIABLE
β†’ review / qualify / abstain according to policy

The Q3 case should therefore produce something like:

verification_record = {
    "candidate_id": "cand_v1",
    "claim_id": "c3",
    "claim": "Q3 revenue was approximately $46 million.",
    "state": "INSUFFICIENT_EVIDENCE",
    "evidence_ids": ["filing_q1", "filing_q2"],
    "missing_evidence": ["q3_revenue_value"],
    "verification_method": "required_field_check",
    "verifier_version": "financial-verifier-v4",
}

That is far more useful than:

BAD

because it constrains what a legitimate repair is allowed to do.

The recovery flow based on verification state is:

    graph TD
    V[Verification State] --> REF[REFUTED] --> COR[correct or remove the proposition]
    V --> INS[INSUFFICIENT_EVIDENCE] --> RET[retrieve, narrow, omit, or abstain]
    V --> CON[CONFLICTING] --> REC[reconcile / verify sources]
    V --> UNV[NOT_VERIFIABLE] --> REV[review / qualify / abstain]
  

Repair is keyed to verification state because different epistemic failures require different recovery operations, not a single generic rewrite.


4. Verify the smallest unit that contains the failure β€” but no smaller

Claim-level verification is often ideal.

But not every failure is claim-local.

Consider:

c1: Drug X was associated with lower symptom scores.
c2: The study was observational.
c3: Therefore Drug X should be prescribed.

Each sentence can be individually grammatical and factual while the argument remains unjustified.

Or:

all individual claims = SUPPORTED
response-level omission = decisive adverse evidence absent

So the verification unit may be:

claim
claim–evidence edge
claim pair
argument
response
trajectory

The correct rule is:

Verify the smallest unit that contains the failureβ€”but no smaller.

The same principle determines whether a local repair is appropriate.


5. Choose the repair surface from demonstrated failure locality

Local repair is not inherently safer.

It is safer when:

failure is localized
dependencies are known
protected content remains valid

Then:

prefer local repair

But if the failure comes from:

false global premise
dense downstream dependence
broken argument structure
response-level omission

then a local sentence patch can preserve the real defect.

A practical decision rule is:

    graph TD
    LF[LOCAL FAILURE] --> KD[KNOWN DEPENDENCIES] --> LP[local patch / omission / rebind]
    GF[GLOBAL PREMISE FAILURE] --> LR[larger-region rebuild / full regeneration / review]
    UF[UNKNOWN DEPENDENCY BOUNDARY] --> LR
  

Repair scope should therefore be selected from the verified failure record, not from a general preference for small edits.


6. Measure both surface and dependency blast radius

The original repair-blast-radius idea remains useful:

$$ B_{\text{surface}} = \frac{\text{changed answer units}} {\text{total answer units}}. $$
The unit might be:
claims
sentences
structured fields
code hunks

But textual change is not the whole risk.

Changing one token:

did
β†’
did not

may invalidate:

polarity
support
summary conclusion
recommendation
policy decision

So define a second quantity:

$$ B_{\text{dep}} = \frac{\text{dependent checks invalidated}} {\text{relevant checks}}. $$
A repair can therefore have:
low surface blast radius
high dependency blast radius

or the reverse.

For reliability, the second often matters more.


7. Repair operations are different types

A recovery controller should distinguish at least:

Repair type What changes
Evidence repair evidence snapshot
Candidate patch localized proposition/text
Decomposition repair claim granularity
Attribution repair source binding
Structural repair role, polarity, quantity, time
Scope repair strength or domain of assertion
Omission unsupported content removed
Full regeneration whole candidate rebuilt

REFINE is a policy route (Chapter 12). Repair is the operation that route executes. One route can map to several repair types.

The policy route provides a useful starting map:

RETRIEVE
β†’ evidence repair

VERIFY
β†’ resolve evidence / source / relation state

REFINE
β†’ candidate / structure / scope repair

REJECT_CANDIDATE
β†’ discard version

ABSTAIN
β†’ stop asserting

But the recovery operator still needs a contract describing exactly what it may alter.


8. Retrieval changes the evidence snapshot, not truth

Suppose policy returns:

HOLD + RETRIEVE

The system retrieves a new document.

That does not repair the candidate automatically.

The new material must itself pass:

source admissibility
freshness
provenance
relevance
conflict checks

Then create:

evidence_snapshot_v2

and invalidate every measurement that depended on evidence_snapshot_v1.

That can include:

support checks
provenance checks
conflict checks
freshness checks
containment geometry
downstream policy decision

The safe sequence is:

    graph LR
    CV[candidate_v1] --> EG[evidence gap] --> RET[retrieve]
    RET --> VE[validate evidence] --> ES[evidence_snapshot_v2]
    ES --> IM[invalidate dependent measurements] --> RV[re-verify candidate_v1]
  

New evidence cannot simply be appended to the old verdict; it creates a new evidence snapshot that forces dependent measurements to be checked again.

New evidence can even make previously accepted claims less secure by revealing:

contradiction
newer information
source conflict
scope limitation

Corrective RAG is relevant here because it explicitly evaluates retrieval quality and triggers corrective retrieval behavior rather than treating initial retrieval as automatically adequate.[3]


9. Omission is a repair only if the remaining response stays sound

Sometimes the strongest repair is deletion.

If no evidence establishes Q3 revenue:

Q3 revenue may have been around $46 million.

is not a repair.

It is the same unsupported proposition under weaker rhetoric.

Qualification does not convert an unsupported fact into a supported fact.

But deletion can create another class of failure.

Consider:

Revenue grew.
However, margins shrank.
This was due to inflation.      [REMOVE]
Therefore, we must cut costs.

Deleting the third sentence can leave:

Therefore

without a valid premise.

Likewise, removing a sentence may create:

dangling pronoun
broken causal link
missing caveat
misleading partial presentation

So omission requires a cohesion and salvage-integrity pass.

A partial answer is valid only if the retained content remains:

grammatically coherent
referentially closed
logically coherent
not materially misleading through omission

This may require a surface-realization edit after factual deletion.

That edit creates a new candidate state too.


10. Partial salvage needs dependency closure

Suppose the candidate contains claims:

$$ C=\{c_1,c_2,\ldots,c_n\}. $$
Let each claim have application-defined utility:
$$ u(c_i)\ge0. $$
We can conceptualize partial salvage as:
$$ S^* = \arg\max_{S\subseteq C} \sum_{c_i\in S}u(c_i) $$
subject to:
every retained critical claim is authorized
response-level obligations remain satisfied
cohesion constraints hold

But claims may depend on each other.

Let:

$$ c_j\rightarrow c_i $$
mean that retaining \(c_i\) requires retaining, substituting, or explicitly accounting for \(c_j\).

Then the retained set must satisfy dependency closure.

This prevents a superficially factual partial answer from becoming misleading because a required premise, adverse caveat, or qualification was removed.

The objective is therefore not:

retain the most sentences

but:

maximize verified retained utility subject to authorization and coherence.


11. Repair contracts should contain executable invariants

A repair contract can be typed as:

repair_contract = {
    "target_claim_ids": ["c3"],
    "allowed_operations": [
        "OMIT_CLAIM",
        "REPLACE_WITH_EVIDENCE",
        "NARROW_TO_SUPPORTED_SCOPE",
    ],
    "protected_claim_ids": ["c1", "c2"],
    "invariants": [
        "company_id(child) == company_id(parent)",
        "reporting_period(child) == reporting_period(parent)",
        "currency(child) == currency(parent)",
        "all_protected_claims_remain_supported(child)",
    ],
    "must_not_add": [
        "new_unverified_financial_values",
    ],
    "max_surface_blast_radius": 0.33,
}

The phrase:

narrow scope

needs precision.

This is legitimate:

Q3 revenue was $46 million.
        ↓
The supplied evidence establishes Q2 revenue at $43.8 million,
but does not establish Q3 revenue.

This is not:

Q3 revenue may have been $46 million.

The first reduces the assertion to what the evidence licenses.

The second merely hedges an unsupported proposition.


12. Every repair creates a new candidate state

This is the chapter’s canonical wording.

A deletion may shrink the assertion surface.

A citation correction may not introduce a new factual proposition.

A deterministic patch may change only one structured field.

Yet all create a new state:

cand_v1
β†’
cand_v2

and trust attaches to the versioned state, not to the lineage as a whole.

So:

$$ \operatorname{authorization}(c_i) \not\Rightarrow \operatorname{authorization}(c_{i+1}) $$
even if the difference is one token.

A repair record should preserve provenance:

repair_record = {
    "candidate_id": "cand_v2",
    "parent_candidate_id": "cand_v1",
    "parent_verification_record": "verify_1842",
    "repair_action": "OMIT_CLAIM",
    "changed_claim_ids": ["c3"],
    "evidence_snapshot_uri": "cas://evidence/7f...",
    "evidence_snapshot_hash": "sha256:...",
    "repair_model": "generator-v17",
    "repair_prompt_version": "repair-v5",
}

The hash proves integrity.

The immutable snapshot or content-addressed URI makes replay possible.


13. Dependency-aware remeasurement is an invalidation problem

A repair controller should think like an incremental build system.

Suppose:

dependencies = {
    "c3": [
        "polarity_check",
        "support_check",
        "summary_conclusion",
        "response_cohesion",
        "policy_decision",
    ],
}

Editing c3 invalidates those checks.

A cache key should conceptually include:

subject/candidate-component hash
evidence snapshot hash
detector version
detector configuration
calibration version where relevant

For example:

measurement_key = (
    claim_hash,
    evidence_hash,
    verifier_version,
    verifier_config,
)

A cached measurement may be reused only when all of its dependencies are unchanged.

Policy is always recomputed because the reliability record itself may have changed.


14. Repair-induced regression is the Whac-A-Mole failure

A repair can fix one problem and create another.

ORIGINAL
Company A acquired Company B in March 2024.

Suppose only the date is wrong.

A careless patch produces:

Company B acquired Company A in April 2024.

The date has improved.

The relation has regressed.

This is the familiar Whac-A-Mole pattern of generative repair.

Define the set of previously passing properties on candidate \(c_i\) as:

$$ \mathcal P(c_i). $$
At candidate level, regression severity can be measured as:
$$ RSI(c_i,c_{i+1}) = \frac{ |\mathcal P(c_i)\setminus\mathcal P(c_{i+1})| }{ \max(1,|\mathcal P(c_i)|) }. $$
Across a repair benchmark \(\mathcal D\), define a case-level repair-induced regression rate:
$$ RIR_{\text{case}} = \frac1{|\mathcal D|} \sum_{d\in\mathcal D} \mathbb I \left( |\mathcal P(c_i)\setminus\mathcal P(c_{i+1})|>0 \right). $$
And a property-level rate:
$$ RIR_{\text{property}} = \frac{ \text{previously passing exposed checks that become failures} }{ \text{previously passing exposed checks} }. $$
Report these on **valid repair attempts**.

A malformed patch should not be mistaken for evidence about the same failure mechanism.

And do not use generic embedding similarity as the preservation oracle.

A relation reversal can remain semantically similar.

Protected-content checks should preserve:

claim identity
roles
polarity
quantities
time
scope
declared invariants

15. External feedback and critics are themselves fallible sensors

The correction loop has two hard tasks:

1. identify what is wrong
2. produce a better candidate

The first is often the bottleneck.

The TACL self-correction survey emphasizes the importance of reliable feedback.[1]

CRITIC demonstrates a tool-interactive pattern in which external tools provide feedback used for revision rather than relying only on introspection.[2]

RePAIR starts from a related problem: agentic RAG systems can rely on critic categories or correction plans that are themselves wrong, and it instead learns response-to-action mappings without requiring an explicit fine-grained taxonomy.[5]

The lesson is not:

typed failure states are useless.

It is:

A component does not become an oracle because we call it a critic.

Evaluate critics with:

failure-localization precision
failure-localization recall
false repair-trigger rate
correct recovery-action rate

Self-RAG provides another useful contrast: retrieval, generation, and learned reflection signals can be integrated into one trained model.[6]

That can improve behavior.

It does not remove the architectural question:

Which signal is allowed to authorize the repaired candidate?

Reflection remains evidence for a decision, not authorization by itself.


16. Full regeneration needs a taint boundary

Sometimes the entire argument is built on a false premise.

Then local repair is inappropriate.

Use:

repair_mode = FULL_REGENERATION
blast_radius = WHOLE_CANDIDATE

But do not feed the failed answer back as unquestioned factual context. Give it a typed record, the same shape Chapter 14 uses for memory, so the boundary travels with it:

tainted_context = {
    "candidate_id": "cand_v3",
    "origin": "FAILED_CANDIDATE",
    "verification_state": "REFUTED",       # or INSUFFICIENT_EVIDENCE
    "allowed_uses": [
        "FAILURE_LOCALIZATION",
        "USER_INTENT_RECONSTRUCTION",
        "STYLE_CONSTRAINT",
        "PROTECTED_STRUCTURE",
    ],
    "forbidden_uses": [
        "FACTUAL_EVIDENCE",
        "SOURCE_AUTHORITY",
        "PROPOSITION_SEED",
    ],
    "parent_verification_record": "verify_1842",
}

origin = FAILED_CANDIDATE is not an authoritative external source and not an authorized derived artifact β€” the lineage classes from Section 21. The regeneration step reads allowed_uses; a step that tries to consume the failed candidate as FACTUAL_EVIDENCE fails the same check a memory read would (Chapter 14).

A safer regeneration request is:

Generate a new answer from the verified evidence package.
The previous candidate is available only as a record of failures
and user-intent constraints.
Do not treat its factual assertions as evidence.

After regeneration:

new candidate
β†’ full affected measurement bundle
β†’ policy

No inherited trust.


17. A bounded recovery controller needs budgets, progress, and cycle detection

Attempt count is only one resource.

A real recovery budget may include:

max_repair_attempts
max_retrieval_queries
max_verifier_calls
max_critic_tokens
max_wall_clock_latency
max_monetary_cost
max_human_escalations

The controller should also detect repeated states.

For example, store:

candidate_hash
verification_state_vector
repair_action

and stop if the same candidate/failure state reappears.

Repeated state is evidence that the current recovery strategy has stopped learning anything.

The reference controller in this chapter detects exactly that.

The hedge repair repeatedly changes rhetoric without changing evidence status, producing:

terminal=ABSTAIN reason=CYCLE_DETECTED

Progress should not be one weighted “quality” score.

Use structural progress such as:

hard blockers decreased?
critical unresolved claims decreased?
repair regressions stayed zero?
evidence completeness increased?
policy state moved toward PERMIT?
verified retained utility increased?

One conceptual progress vector is:

$$ \Phi(c) = ( N_{\text{hard blockers}}, N_{\text{critical unresolved}}, N_{\text{regressions}}, -\text{verified utility} ). $$
The exact ordering is application-specific.

The principle is not:

keep trying while score rises

but:

continue only while a declared reliability dimension is genuinely improving.

The recovery loop with budgets and cycle detection:

    graph TD
    START[start] --> VER[verify candidate]
    VER --> ALL{all claims SUPPORTED?}
    ALL -- yes --> PERMIT[PERMIT]
    ALL -- no --> SIG[compute signature]
    SIG --> SEEN{signature seen?}
    SEEN -- yes --> ABSTAIN[ABSTAIN: CYCLE_DETECTED]
    SEEN -- no --> BUDGET{repair budget left?}
    BUDGET -- no --> ABSTAIN2[ABSTAIN: BUDGET_EXHAUSTED]
    BUDGET -- yes --> REPAIR[apply repair operation]
    REPAIR --> VER
  

The loop permits repair only while it can produce a new verification state; repeated signatures and exhausted budgets terminate in abstention instead of endless revision.


18. A small deterministic recovery controller

Reference environment

Environment: Python 3.13
Dependencies: Python standard library only
Canonical implementation: experiments/hallucination/recovery_demo.py

Run it with:

python experiments/hallucination/recovery_demo.py

The core controller is intentionally small:

from dataclasses import dataclass
from enum import Enum
import hashlib

class V(str, Enum):
    SUPPORTED = "SUPPORTED"
    INSUFFICIENT_EVIDENCE = "INSUFFICIENT_EVIDENCE"

@dataclass(frozen=True)
class Claim:
    id: str
    text: str
    requirement: str

@dataclass
class Candidate:
    id: str
    parent: str | None
    claims: list[Claim]
    authorized: bool = False

def verify(candidate, evidence):
    return {
        c.id: (
            V.SUPPORTED
            if c.requirement in evidence
            else V.INSUFFICIENT_EVIDENCE
        )
        for c in candidate.claims
    }

def signature(candidate, states):
    body = "|".join(f"{c.id}:{c.text}" for c in candidate.claims)
    h = hashlib.sha256(body.encode()).hexdigest()[:12]
    return h, tuple(sorted((k, v.value) for k, v in states.items()))

The loop then, in outline:

while True:
    states = verify(current, evidence)

    if all(v == V.SUPPORTED for v in states.values()):
        current.authorized = True
        return "PERMIT", current

    sig = signature(current, states)

    if sig in seen:
        return "ABSTAIN:CYCLE_DETECTED", current
    if repairs >= max_repairs:
        return "ABSTAIN:REPAIR_BUDGET_EXHAUSTED", current
    if verifier_calls >= max_verifier_calls:
        return "REVIEW:CRITIC_BUDGET_EXHAUSTED", current

    seen.add(sig)
    current = REPAIRS[mode](current, states)   # a new candidate; no inherited authorization

Two repair modes exercise the loop.

omission removes every claim the verifier could not support. The omission trace is:

cand_v1 {'c1': 'SUPPORTED', 'c2': 'SUPPORTED', 'c3': 'INSUFFICIENT_EVIDENCE'}
cand_v2 {'c1': 'SUPPORTED', 'c2': 'SUPPORTED'}
terminal=PERMIT

hedge softens the wording of the unsupported claim without adding evidence. The second hedge is idempotent, so the candidate and its verification state repeat, and cycle detection fires:

cand_v1 {'c1': 'SUPPORTED', 'c2': 'SUPPORTED', 'c3': 'INSUFFICIENT_EVIDENCE'}
cand_v2 {'c1': 'SUPPORTED', 'c2': 'SUPPORTED', 'c3': 'INSUFFICIENT_EVIDENCE'}
cand_v3 {'c1': 'SUPPORTED', 'c2': 'SUPPORTED', 'c3': 'INSUFFICIENT_EVIDENCE'}
terminal=ABSTAIN reason=CYCLE_DETECTED

The controller also rejects an undeclared repair mode before any repair runs:

--- mode=guess ---
ValueError: unknown repair mode: 'guess'

This demonstration proves controller invariants under a perfect structured oracle.

It does not establish the accuracy of a real-world verifier or repair model.

Those require separate evaluation.


19. Human review should receive the failed recovery path, not only the final text

When policy routes to:

REVIEW

the human reviewer should not receive only:

cand_v3

They need a review package:

original candidate
current candidate
diff
target failed claim
verification state
evidence used
repair attempts
new failures introduced
budget reason
policy reason

For example:

review_package = {
    "candidate": "cand_v3",
    "parent_chain": ["cand_v1", "cand_v2"],
    "target_failure": "INSUFFICIENT_Q3_REVENUE",
    "attempts": [
        "HEDGE_CLAIM",
        "HEDGE_CLAIM",
    ],
    "terminal_reason": "CYCLE_DETECTED",
    "evidence_snapshot": "cas://evidence/7f...",
}

The human is then resolving a diagnosed reliability problem rather than reconstructing the entire history manually.


20. The recovery benchmark should decompose the bottleneck

A minimum benchmark should report:

Dimension Metrics
Verification localization precision/recall, false repair triggers
Repair targeted fix rate, RIR, new unsupported claims
Preservation protected invariants, dependency regressions, cohesion
Efficiency surface/dependency blast radius, steps, budget exhaustion
Routing correct recovery operation, unnecessary regeneration/review
System final authorized coverage, latency, retrieval/verifier cost

Add two critical baselines.

No-repair baseline

What happens if the system:

omits
abstains
or rejects

without running a generative repair stage?

Oracle-repair baseline

What would happen with:

perfect localization
perfect gold repair

These decompose:

verification bottleneck
vs
repair-generation bottleneck.

And preserve Chapter 7’s held-out discipline:

known repair regression suite
held-out same-mechanism suite
novel-failure recovery set

Once a repair case enters the regression suite, repeatedly fixing that exact case is not evidence of general recovery ability.


21. Repair candidates are ephemeral until authorized

This is the bridge to the next chapter and should already be an invariant here.

A candidate under repair must not be written into a persistent evidence store merely because it exists.

cand_v1 HOLD
cand_v2 HOLD
cand_v3 HOLD

are ephemeral working states.

Only an explicitly authorized artifact may cross the persistence boundary.

Otherwise the recovery system can manufacture its own future evidence:

unsupported candidate
β†’ persisted
β†’ indexed
β†’ retrieved during repair
β†’ appears independent
β†’ "verifies" descendant candidate

That is circular contamination.

Evidence snapshots therefore need lineage that distinguishes:

authoritative external source
authorized derived artifact
unverified model output

and repair candidates must never silently cross between those classes.


22. Using AI: ask for a bounded patch, then distrust the patch

If an LLM acts as the repair operator, constrain its task.

A weak instruction is:

Improve this answer and make it more accurate.

A stronger contract is:

The verifier identified exactly one failed claim: c3.

Verification state:
INSUFFICIENT_EVIDENCE

Available evidence:
- c1 SUPPORTED by source_1
- c2 SUPPORTED by source_2
- no admissible Q3 revenue value exists

Allowed operations:
- omit c3
- replace c3 only if a supplied source directly supports replacement

Protected claims:
- c1
- c2

Forbidden:
- new financial values
- changes to company identity
- changes to reporting period

Return:
1. repaired answer
2. changed claim IDs
3. operation used

A characteristic bad repair would be:

Q3 revenue may have been approximately $45.8 million.

That may sound cautious.

The verifier should still return:

INSUFFICIENT_EVIDENCE

The surrounding system owns the truth conditions.

After the patch:

Run the verifier again rather than trusting the repair model’s declaration that it succeeded.


23. What you should now be able to answer

After this chapter, you should be able to explain:

  1. Why every repair creates a new candidate state even when the assertion surface shrinks.
  2. The difference between REFUTED and INSUFFICIENT_EVIDENCE.
  3. Why external or mechanically grounded feedback is different from another model completion.
  4. Why repair granularity should match the smallest verified failure boundary.
  5. The difference between surface blast radius and dependency blast radius.
  6. Why omission requires cohesion and salvage-integrity checks.
  7. Why new retrieval invalidates all evidence-dependent measurements.
  8. Why a repaired candidate cannot inherit authorization.
  9. How repair-induced regression and cycle detection expose failed recovery loops.
  10. Why repair candidates must remain ephemeral until explicitly authorized.

Worked question β€” Why is deletion often safer than hedging?

Suppose the evidence does not contain Q3 revenue.

The original claim is:

Q3 revenue was $46 million.

Changing it to:

Q3 revenue may have been $46 million.

changes the rhetoric but does not add evidence for the underlying Q3 value.

If the verification contract requires an admissible source for reported revenue, both claims remain:

INSUFFICIENT_EVIDENCE.

Deletion removes the unsupported assertion.

But deletion is authorized only after the remaining response passes cohesion, dependency, and policy checks.

So the correct rule is not:

delete whenever uncertain.

It is:

remove unsupported material
when doing so preserves the obligations of the remaining response.

This is the deletion side of conformal factuality (Chapter 6 Β§9). Mohri and Hashimoto derive a guarantee by backing a generation off β€” removing or generalizing claims β€” until the surviving text clears a factuality bound.[7] Hedging a claim does not shrink the entailment set it commits to; deleting it does.


24. Exercises

Exercise 1 β€” Local versus global repair

Create a five-claim answer with one localized unsupported claim.

Compare:

local omission
local evidence-backed patch
whole-answer regeneration

Report:

surface blast radius
dependency blast radius
target repair success
new regressions

Exercise 2 β€” Distinguish evidence states

Create examples for:

REFUTED
INSUFFICIENT_EVIDENCE
CONFLICTING
UNRESOLVED

Specify the correct recovery route for each.

Exercise 3 β€” Repair-induced regression

Start with:

Company A acquired Company B in March 2024.

where only the date is wrong.

Repair the date and verify that:

subject
object
polarity
quantity

remain unchanged.

Compute candidate-level RSI.

Exercise 4 β€” Dependency invalidation

Create a dependency graph for:

claim
support
summary
recommendation
policy

Edit one claim and identify which cached measurements remain valid.

Exercise 5 β€” Cycle detection

Implement two repair operators that oscillate between two candidate states.

Confirm that:

(candidate_hash, verification_state)

cycle detection terminates the loop before the general attempt budget.

Exercise 6 β€” Partial salvage integrity

Create an answer where deleting one unsupported claim leaves a dangling:

therefore
however
this
it

Repair the cohesion without adding new factual assertions.

Re-run verification afterward.


25. The deeper lesson

The naive repair loop is:

model makes mistake
β†’ tell model it made a mistake
β†’ model says something else
β†’ trust the new answer

That is not a reliability architecture.

A reliable recovery loop is:

    graph TD
    CS[candidate state] --> EB[evidence-bearing verification]
    EB --> LD[localized diagnosis]
    LD --> RC[repair contract]
    RC --> BR[bounded repair]
    BR --> NCS[new candidate state]
    NCS --> DI[dependency invalidation]
    DI --> RM[re-measurement]
    RM --> REG[regression check]
    REG --> POL[policy]
  

The system continues only while recovery makes real structural progress.

If it does not, the correct output may be:

omit
review
abstain
reject

That is not the system giving up.

It is the system refusing to turn repair effort into unjustified commitment.

A repaired claim is still a claim.

It still needs evidence.

It still needs structural fidelity.

It still needs provenance.

It still needs epistemic adequacy.

It still needs policy authorization.

And until it receives that authorization, it remains transient working stateβ€”not tomorrow’s evidence.

That final distinction leads directly to the next problem.


Research roots

  1. Ryo Kamoi, Yusen Zhang, Nan Zhang, Jiawei Han and Rui Zhang, “When Can LLMs Actually Correct Their Own Mistakes? A Critical Survey of Self-Correction of LLMs,” Transactions of the Association for Computational Linguistics 12, 1417–1440, 2024. Finds weak general evidence for intrinsic prompted self-correction, identifies feedback generation as a major bottleneck, and reports stronger correction behavior when reliable external feedback is available. https://aclanthology.org/2024.tacl-1.78/

  2. Zhibin Gou, Zhihong Shao, Yeyun Gong, Yelong Shen, Yujiu Yang, Nan Duan and Weizhu Chen, “CRITIC: Large Language Models Can Self-Correct with Tool-Interactive Critiquing,” ICLR 2024. Uses external tools to evaluate aspects of generated outputs and feeds tool results back into iterative revision. https://www.microsoft.com/en-us/research/publication/critic-large-language-models-can-self-correct-with-tool-interactive-critiquing/

  3. Shi-Qi Yan, Jia-Chen Gu, Yun Zhu and Zhen-Hua Ling, “Corrective Retrieval Augmented Generation,” arXiv:2401.15884, 2024. Adds retrieval evaluation and corrective retrieval, including web search and decompose-then-recompose processing, rather than assuming the initial retrieved corpus is sufficient. https://arxiv.org/abs/2401.15884

  4. Luyu Gao, Zhuyun Dai, Panupong Pasupat, Anthony Chen, Arun Tejasvi Chaganty, Yicheng Fan, Vincent Zhao, Ni Lao, Hongrae Lee, Da-Cheng Juan and Kelvin Guu, “RARR: Researching and Revising What Language Models Say, Using Language Models,” ACL 2023. Retrieves attribution for generated text and post-edits unsupported content while explicitly trying to preserve unaffected material. https://aclanthology.org/2023.acl-long.910/

  5. Gongbo Zhang, Yifan Peng and Chunhua Weng, “Improving Retrieval-Augmented Generation without Taxonomy-based Error Categorization,” ACL 2026, pp. 155–165. Introduces RePAIR, motivated partly by unreliable critic categorization and ineffective correction, and learns response-to-action plans for flawed RAG outputs. https://aclanthology.org/2026.acl-short.14/

  6. Akari Asai, Zeqiu Wu, Yizhong Wang, Avi Sil and Hannaneh Hajishirzi, “Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection,” ICLR 2024. Integrates adaptive retrieval, generation and learned reflection signals into one model, providing a useful contrast to externally separated verification architectures. https://proceedings.iclr.cc/paper_files/paper/2024/hash/25f7be9694d7b32d5cc670927b8091e1-Abstract-Conference.html

  7. Christopher Mohri and Tatsunori Hashimoto, “Language Models with Conformal Factuality Guarantees,” ICML 2024. Derives a factuality guarantee by backing a generation off β€” removing or generalizing claims β€” until the surviving text clears a conformal bound. https://proceedings.mlr.press/v235/mohri24a.html

Next: The Memory Contamination Problem

Chapter 13 keeps untrusted repair states inside a bounded loop.

But production systems also write state.

They create:

conversation memory
user profiles
agent scratchpads
vector-store documents
summaries
knowledge-graph facts
database rows
tickets
reports
future prompts
training examples

Now imagine an unverified candidate crossing that persistence boundary.

On the next run, the system may retrieve its own output as evidence.

Then the failure changes form:

hallucination
β†’ persistent assertion
β†’ retrieved context
β†’ apparent evidence
β†’ reinforced hallucination

The next chapter asks:

How do we stop an unverified output from becoming tomorrow’s evidence?