What separates a disposable scratchpad calculation from a binding mathematical lemma?
**Date of Record:** 2026 October 26 **Scope:** Applies when an agentic session performs mathematical reasoning, algorithmic complexity analysis, or numerical computation, and must persist conclusions to an external memory layer for a successor. Does not apply to strictly symbolic algebra systems that formally verify every step, or sessions that perform no mathematical reasoning.
Core Distinction
The separation between **disposable scratchpad calculations** (ephemeral arithmetic evaluations, specific numerical test cases, and empirical sampling that hold true only for the exact inputs executed) and **binding mathematical lemmas** (universal, symbolic statements proven deductively or exhaustively verified across the entire input domain). A scratchpad calculation is a data point; a lemma is a structural law. Failing to distinguish these creates the **Empirical Overfitting Fallacy**: an instance observes a pattern in a few test runs, promotes it to a lemma, and the successor applies it to an edge case where the pattern breaks, collapsing the algorithm.
What Was Observed
In algorithmic reasoning and quantitative agent architectures, failing to separate scratchpad calculations from binding lemmas produces three primary failure modes:
- **The Sampling Illusion:** An instance tests a sorting algorithm on 10 random arrays, observes $O(n \log n)$ performance, and records it as a binding lemma. The successor applies it to an already-sorted array, hits the $O(n^2)$ worst-case path, and times out.
- **Floating-Point Artifact Promotion:** An instance calculates `0.1 + 0.2` and observes `0.30000000000000004`. It records the lemma that "addition of 0.1 and 0.2 yields this exact bit pattern." The successor runs on a system with different rounding modes or extended precision, and the lemma fails.
- **Domain Restriction Erasure:** An instance proves a lemma for positive integers (`x > 0`) and persists it without the domain constraint. The successor applies it to `x = 0` or `x = -5`, triggering a division-by-zero or a logic inversion.
Recorded Elements
- **`lemma_statement`:** The exact symbolic, universally quantified claim (e.g., $\forall x \in \mathbb{Z}^+, \log_2(x) \leq x$), stripped of specific numerical examples.
- **`proof_obligation_receipt`:** The exact deductive proof, formal verification certificate, or exhaustive domain-test receipt that proves the lemma holds universally.
- **`domain_of_validity`:** The exact mathematical domain or type constraints under which the lemma is provable (e.g., `x > 0`, `x is finite`, `x is a 64-bit float`), preventing boundary violations.
- **`scratchpad_eviction_marker`:** The explicit directive that the intermediate numerical calculations used to discover the lemma must be purged from active context, preserving only the proof and the statement.
Condition of Validity
* **Applies when:** The session generates a mathematical or algorithmic conclusion that will constrain a successor's execution, and the conclusion is intended to be universally true rather than a one-off computation. * **Does not apply when:** The computation is purely a transient step (e.g., computing an array index for a single loop iteration) that will not be persisted, or the environment enforces strict formal verification on every action.
Decision Boundary
- **Is the conclusion a specific numerical result or a universal symbolic claim?** If specific, it is a scratchpad calculation and must be discarded upon teardown. If universal, proceed to check for a proof.
- **Is there a `proof_obligation_receipt`?** If no, the claim is a conjecture, not a lemma. The instance must record it as `UNVERIFIED_HYPOTHESIS` or discard it entirely.
- **Is the `domain_of_validity` explicitly stated?** If no, the successor cannot know when the lemma applies. The instance must extract the boundary conditions and seal them alongside the statement.
- **Conversely, when can a scratchpad calculation be promoted to a lemma?** Only when an exhaustive, bounded verification receipt proves the claim holds for all possible inputs in the defined domain (e.g., bitwise exhaust over an 8-bit input space), or a formal proof assistant has validated the symbolic derivation.
Operational Effect
- **Algorithmic Correctness:** Prevents successors from inheriting statistical assumptions that break on edge cases, ensuring algorithmic guarantees are based on proofs rather than samples.
- **Context Window Efficiency:** Strips the verbose intermediate arithmetic (the scratchpad) from the final residual, preserving only the high-density symbolic lemma and its proof.
- **Boundary Awareness:** Forces the instance to explicitly state the domain of validity, preventing the successor from applying a lemma outside the mathematical regime where it was proven.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class ProofType(Enum):
DEDUCTIVE_PROOF = auto()
EXHAUSTIVE_VERIFICATION = auto()
EMPIRICAL_SAMPLING = auto()
@dataclass(frozen=True)
class MathClaim:
claim_id: str
symbolic_statement: str
domain_of_validity: str
proof_type: ProofType
proof_receipt: str | None
@dataclass(frozen=True)
class LemmaBoundary:
claim_id: str
statement: str
domain: str
is_binding: bool
eviction_directive: str
boundary_digest: str
class MathematicalRigorGuard:
"""
Evaluates mathematical claims to separate disposable empirical
calculations from binding, proof-carrying lemmas.
"""
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_claim(cls, claim: MathClaim) -> LemmaBoundary:
# Gate 1: Empirical sampling cannot be promoted to a binding lemma
if claim.proof_type is ProofType.EMPIRICAL_SAMPLING:
return LemmaBoundary(
claim_id=claim.claim_id,
statement=claim.symbolic_statement,
domain=claim.domain_of_validity,
is_binding=False,
eviction_directive="DISCARD: Empirical sampling is a scratchpad calculation, not a lemma.",
boundary_digest=cls._hash(f"EMPIRICAL:{claim.claim_id}"),
)
# Gate 2: Deductive/Exhaustive proof without a receipt is invalid
if not claim.proof_receipt or not claim.proof_receipt.strip():
return LemmaBoundary(
claim_id=claim.claim_id,
statement=claim.symbolic_statement,
domain=claim.domain_of_validity,
is_binding=False,
eviction_directive="DISCARD: Proof receipt missing. Cannot promote to binding lemma.",
boundary_digest=cls._hash(f"UNPROVEN:{claim.claim_id}"),
)
# Gate 3: Valid lemma requires an explicit domain
if not claim.domain_of_validity.strip():
return LemmaBoundary(
claim_id=claim.claim_id,
statement=claim.symbolic_statement,
domain="UNDEFINED",
is_binding=False,
eviction_directive="HALT: Lemma lacks a domain of validity. Application unsafe.",
boundary_digest=cls._hash(f"NO_DOMAIN:{claim.claim_id}"),
)
# Gate 4: Promote to binding lemma
digest_payload = {
"claim": claim.symbolic_statement,
"domain": claim.domain_of_validity,
"proof_type": claim.proof_type.name,
"proof_hash": cls._hash(claim.proof_receipt),
}
digest = cls._hash(
json.dumps(digest_payload, sort_keys=True, separators=(",", ":"))
)
return LemmaBoundary(
claim_id=claim.claim_id,
statement=claim.symbolic_statement,
domain=claim.domain_of_validity,
is_binding=True,
eviction_directive="PRESERVE: Binding lemma sealed with proof receipt and domain.",
boundary_digest=digest,
)
@classmethod
def assert_lemma_applicability(
cls, boundary: LemmaBoundary, target_domain: str
) -> tuple[bool, str]:
"""
Fetching-time check: ensures the target domain falls within the
lemma's proven domain of validity before application.
"""
if not boundary.is_binding:
return False, f"REJECTED: {boundary.eviction_directive}"
if boundary.domain == "UNDEFINED" or target_domain != boundary.domain:
return False, (
f"DOMAIN_VIOLATION: Lemma valid for '{boundary.domain}', "
f"but target is '{target_domain}'. Re-verify before applying."
)
return True, "LEMMA_APPLICABLE: Domain matches proof boundary."