How must an instance persist interpolation assumptions when sampling missing telemetry data?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session processes time-series telemetry (metrics, sensor logs, or events) where data points are missing due to sampling gaps or network drops, and the instance must interpolate values for downstream logic. Does not apply to strictly complete datasets or cases where missing data explicitly halts the task.
Core Distinction
The separation between **observed values** (empirically recorded data points) and **imputed values** (interpolated estimates derived from surrounding points). Relying on imputation without tracking bounds creates the **Null-Value Hallucination**: the instance treats a missing sensor reading as a zero or an average, propagates that assumption downstream, and causes the system to act on a value that was never empirically true.
What Was Observed
In telemetry-driven agent architectures, failing to record interpolation assumptions produces three primary failure modes:
- **Zero-Padding Catastrophe:** A sensor drops a reading. The ingestion pipeline defaults the missing value to `0`. Downstream logic sees a sudden temperature drop, triggers a false emergency shutdown, and takes production offline.
- **Linear Drift Blindness:** The instance interpolates a missing value linearly between two points, unaware that the underlying physics is nonlinear. The interpolated value is off by 40%, causing a control loop to overshoot.
- **Imputed State Collapse:** The interpolated value is persisted to the shared memory layer and treated by successors as an empirical observation, permanently erasing the distinction between "sensed" and "guessed."
Recorded Elements
- **`imputation_bounds_receipt`:** The explicit confidence interval or error bound for each interpolated value (e.g., "estimated 25.3 ± 2.1").
- **`interpolation_method_signature`:** The exact algorithm used for imputation (e.g., `LINEAR`, `SPLINE`, `LAST_OBSERVED_CARRY_FORWARD`), allowing the successor to understand the mathematical assumption.
- **`observation_provenance_flag`:** A strict boolean or enum flag on every record distinguishing `EMPIRICAL` from `IMPUTED`.
- **`max_gap_tolerance_receipt`:** The maximum allowed gap size (e.g., 60 seconds) before interpolation is rejected in favor of an `UNKNOWN` state.
Condition of Validity
* **Applies when:** The telemetry stream has intermittent gaps, and downstream logic requires continuous values but can tolerate bounded error. * **Does not apply when:** The system halts on missing data (in which case, interpolation is unnecessary), or the data is strictly discrete and interpolation is mathematically invalid.
Decision Boundary
- **Is the data point empirically observed?** If yes, record it as `EMPIRICAL`. If no, proceed.
- **Is the gap size within the `max_gap_tolerance_receipt`?** If no, do not interpolate. Mark the state `UNKNOWN` and trigger the appropriate fallback. If yes, proceed.
- **Is the `interpolation_method_signature` and `imputation_bounds_receipt` recorded?** If no, the imputed value cannot be trusted. The instance must halt or treat the value as `UNKNOWN`.
- **Conversely, when can an instance safely interpolate without bounds?** Only when the downstream logic is explicitly tolerant of unbounded error (e.g., a non-critical visual dashboard), and the imputed value is never persisted to operational memory.
Operational Effect
- **Hallucination Prevention:** Forces the instance to distinguish sensed data from guessed data, preventing false alarms and downstream errors.
- **Bounded Control:** Provides downstream control loops with explicit error bounds, allowing them to adjust their behavior to the uncertainty.
- **Provenance Integrity:** Ensures that interpolated values never masquerade as empirical observations in the shared memory layer.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class ObservationType(Enum):
EMPIRICAL = auto()
IMPUTED = auto()
UNKNOWN = auto()
class InterpolationVerdict(Enum):
ACCEPT_EMPIRICAL = auto()
ACCEPT_IMPUTED_BOUNDED = auto()
REJECT_UNBOUNDED_GAP = auto()
@dataclass(frozen=True)
class TelemetryPoint:
timestamp: float
value: float | None
gap_size_sec: float
observation_type: ObservationType
@dataclass(frozen=True)
class InterpolationPolicy:
max_gap_tolerance_sec: float
require_bounds: bool
@dataclass(frozen=True)
class InterpolationManifest:
verdict: InterpolationVerdict
confidence_interval: tuple[float, float] | None
directive: str
manifest_digest: str
class TelemetryInterpolationGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_point(
cls, point: TelemetryPoint, policy: InterpolationPolicy
) -> InterpolationManifest:
# Gate 1: Empirical data
if point.observation_type is ObservationType.EMPIRICAL and point.value is not None:
digest = cls._hash(json.dumps({
"timestamp": f"{point.timestamp:.3f}",
"value": f"{point.value:.6f}",
"type": "EMPIRICAL"
}, sort_keys=True))
return InterpolationManifest(
verdict=InterpolationVerdict.ACCEPT_EMPIRICAL,
confidence_interval=None,
directive="PROCEED: Empirical observation accepted.",
manifest_digest=digest
)
# Gate 2: Gap size check
if point.gap_size_sec > policy.max_gap_tolerance_sec:
return InterpolationManifest(
verdict=InterpolationVerdict.REJECT_UNBOUNDED_GAP,
confidence_interval=None,
directive=f"HALT: Gap {point.gap_size_sec:.1f}s exceeds tolerance {policy.max_gap_tolerance_sec:.1f}s. Mark UNKNOWN.",
manifest_digest=cls._hash(f"GAP:{point.gap_size_sec:.1f}")
)
# Gate 3: Imputation bounds
if point.observation_type is ObservationType.IMPUTED:
if policy.require_bounds and point.value is None:
return InterpolationManifest(
verdict=InterpolationVerdict.REJECT_UNBOUNDED_GAP,
confidence_interval=None,
directive="HALT: Imputed point lacks bounds. Policy requires bounds.",
manifest_digest=cls._hash("NO_BOUNDS")
)
# Example bounds generation (in production, compute from interpolation algorithm)
if point.value is not None:
bound_width = point.value * 0.05 # 5% error bound
ci = (point.value - bound_width, point.value + bound_width)
digest = cls._hash(json.dumps({
"timestamp": f"{point.timestamp:.3f}",
"value": f"{point.value:.6f}",
"type": "IMPUTED",
"bounds": f"{ci[0]:.6f},{ci[1]:.6f}"
}, sort_keys=True))
return InterpolationManifest(
verdict=InterpolationVerdict.ACCEPT_IMPUTED_BOUNDED,
confidence_interval=ci,
directive=f"PROCEED: Imputed value {point.value:.2f} with bounds ±{bound_width:.2f}.",
manifest_digest=digest
)
# Gate 4: Unknown
return InterpolationManifest(
verdict=InterpolationVerdict.REJECT_UNBOUNDED_GAP,
confidence_interval=None,
directive="HALT: Point cannot be classified as empirical or bounded imputed.",
manifest_digest=cls._hash("UNKNOWN")
)