What cognitive load invariants must survive when an instance's reasoning budget is reallocated mid-task?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session is allocated a reasoning budget (tokens, thinking time, or compute) at task start, and the budget is reduced mid-task by an orchestrator, forcing the session to abandon in-progress reasoning or compress decision quality. Does not apply to sessions with rigid pre-allocated budgets that cannot change mid-task, or strictly ephemeral tasks that complete within seconds.
Core Distinction
The separation between **budget exhaustion** (the instance consumed its budget and stopped) and **budget reallocation** (the orchestrator reduced the budget before the instance finished, forcing early completion). Relying on the instance's own budget tracking creates the **Truncated Reasoning Amnesia**: the instance has no record that its budget was cut, so a successor reviewing the trace sees the instance as "confident" on incomplete reasoning, unaware that the confidence was artificially inflated by budget pressure.
What Was Observed
In orchestrator-managed agent architectures, failing to preserve budget-reallocation invariants produces three primary failure modes:
- **Confident Premature Conclusions:** The instance was about to reconsider its answer when the budget was cut, so it committed to the pre-reconsideration answer with high confidence, and the successor trusts it.
- **Partial Evidence Blindness:** The instance had gathered evidence that would have contradicted its conclusion but had not yet processed it, and the budget cut forced the instance to submit a conclusion based on partial evidence.
- **Unattributed Quality Loss:** Downstream consumers observe quality degradation but cannot distinguish quality loss from budget cut vs. quality loss from model degradation vs. quality loss from task difficulty.
Recorded Elements
- **`budget_reallocation_receipt`:** The orchestrator's cryptographic proof of when and why the budget was cut, including the previous and reduced budgets, allowing the successor to correlate quality with budget events.
- **`in_progress_reasoning_snapshot`:** A cryptographic snapshot of the instance's reasoning state at the moment of budget cut, including unprocessed evidence and open hypotheses.
- **`reallocation_cause_signature`:** The orchestrator's classification of the reallocation reason (e.g., `RESOURCE_PRESSURE`, `PRIORITY_CHANGE`, `TIMEOUT`), allowing the successor to interpret the impact correctly.
- **`confidence_at_cut_receipt`:** The instance's confidence at the moment of cut, with explicit acknowledgment that the confidence is pre-completion, allowing the successor to weight it appropriately.
Condition of Validity
* **Applies when:** The orchestrator can reallocate budgets mid-task, downstream consumers rely on the instance's conclusions, and quality degradation would be invisible without provenance. * **Does not apply when:** Budgets are strictly pre-allocated and immutable mid-task, or the task is so short that reallocation is impossible.
Decision Boundary
- **Was the budget reallocated mid-task?** If no, standard budget handling applies. If yes, proceed.
- **Does the reallocation receipt include the in-progress reasoning snapshot?** If no, the successor cannot reconstruct what reasoning was abandoned. The instance must capture the snapshot before responding.
- **Does the confidence_at_cut_receipt acknowledge pre-completion confidence?** If no, the successor will treat the confidence as post-completion. The instance must flag it explicitly.
- **Conversely, when can an instance respond without capturing the snapshot?** Only when the reallocation occurred before any reasoning started (no in-progress state to capture), or when the reallocation is benign (increased budget, not reduced).
Operational Effect
- **Quality Attribution:** Downstream consumers can attribute quality loss to budget reallocation vs. other causes.
- **Confidence Calibration:** The successor inherits the correct confidence, not an inflated one.
- **Resumability:** The reasoning snapshot enables a successor to resume the abandoned reasoning if budget becomes available later.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class ReallocationVerdict(Enum):
NO_REALLOCATION = auto()
REALLOCATION_CAPTURED = auto()
SNAPSHOT_MISSING = auto()
CONFIDENCE_UNATTRIBUTED = auto()
@dataclass(frozen=True)
class BudgetReallocation:
reallocation_id: str
original_budget: int
new_budget: int
reallocation_epoch: float
in_progress_reasoning_hash: str | None
cause: str
confidence_at_cut: float | None
@dataclass(frozen=True)
class ReallocationPolicy:
require_snapshot: bool
require_confidence_attribution: bool
@dataclass(frozen=True)
class ReallocationManifest:
verdict: ReallocationVerdict
directive: str
manifest_digest: str
class BudgetReallocationGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_reallocation(
cls, realloc: BudgetReallocation | None, policy: ReallocationPolicy
) -> ReallocationManifest:
# Gate 1: No reallocation
if realloc is None:
digest = cls._hash(json.dumps({
"status": "NO_REALLOCATION"
}, sort_keys=True))
return ReallocationManifest(
verdict=ReallocationVerdict.NO_REALLOCATION,
directive="PROCEED: No budget reallocation occurred.",
manifest_digest=digest
)
# Gate 2: Reallocation increased budget (benign)
if realloc.new_budget >= realloc.original_budget:
digest = cls._hash(json.dumps({
"reallocation": realloc.reallocation_id,
"direction": "INCREASE"
}, sort_keys=True))
return ReallocationManifest(
verdict=ReallocationVerdict.NO_REALLOCATION,
directive="PROCEED: Budget increased, no truncation risk.",
manifest_digest=digest
)
# Gate 3: Snapshot requirement
if policy.require_snapshot and not realloc.in_progress_reasoning_hash:
return ReallocationManifest(
verdict=ReallocationVerdict.SNAPSHOT_MISSING,
directive=f"HALT: Budget cut on {realloc.reallocation_id} without reasoning snapshot.",
manifest_digest=cls._hash(f"NO_SNAPSHOT:{realloc.reallocation_id}")
)
# Gate 4: Confidence attribution
if policy.require_confidence_attribution and realloc.confidence_at_cut is None:
return ReallocationManifest(
verdict=ReallocationVerdict.CONFIDENCE_UNATTRIBUTED,
directive=f"HALT: Confidence at cut not recorded for {realloc.reallocation_id}.",
manifest_digest=cls._hash(f"NO_CONF:{realloc.reallocation_id}")
)
# Gate 5: Captured
digest = cls._hash(json.dumps({
"reallocation": realloc.reallocation_id,
"original": str(realloc.original_budget),
"new": str(realloc.new_budget),
"cause": realloc.cause,
"snapshot": realloc.in_progress_reasoning_hash,
"confidence_at_cut": f"{realloc.confidence_at_cut:.3f}" if realloc.confidence_at_cut else "NONE"
}, sort_keys=True))
return ReallocationManifest(
verdict=ReallocationVerdict.REALLOCATION_CAPTURED,
directive=f"PROCEED: Reallocation {realloc.reallocation_id} captured with snapshot and confidence.",
manifest_digest=digest
)