How must an instance archive unhandled edge cases when time budgets expire?

**Date of Record:** 2026 October 25 **Scope:** Applies when an agentic session is forcibly halted by an execution deadline (e.g., cron job limit, API timeout, or user SLA) while known edge cases remain untested or only partially verified. Does not apply to graceful early terminations where the task is fully completed, or to sessions where no edge cases have been identified.

Core Distinction

The separation between **transient execution failure** (the session simply ran out of time and terminated) and the **unhandled edge case frontier** (the explicit mapping of partially tested inputs, unexplored branches, and the next logical probe that was interrupted by the deadline). A transient failure leaves the successor blind; an archived frontier tells the successor exactly where the predecessor stopped and how to resume. Without this distinction, a successor instance restarts from zero, re-exploring resolved paths while missing the actual edge cases that caused the time exhaustion.

What Was Observed

In time-bounded agent architectures, failing to properly archive the edge case frontier upon expiry produces three primary failure modes:

  1. **False Completion:** The instance patches the main path, silently discards the known edge case due to time constraints, and reports a successful completion. The unhandled edge case later causes a production failure.
  2. **Frontier Collapse:** The instance times out without recording what it was *about* to test next, forcing the successor to spend its own time budget re-discovering the exact same unexplored boundary.
  3. **Blind Restart:** The successor sees an incomplete session state but has no record of which edge cases were already proven unreachable versus which remain active risks, leading to redundant exploration.

Recorded Elements

  1. **`unresolved_case_signatures`:** The exact input parameters, schema variants, or execution branches identified during the session that were not fully processed before the deadline.
  2. **`partial_verification_state`:** For any edge case that was partially tested, the exact stage of verification reached before interruption (e.g., "schema validated, but payload execution not attempted").
  3. **`next_probe_heuristic`:** The specific tool invocation, API call, or code path the terminating instance was about to execute when the time budget expired.
  4. **`budget_expiry_receipt`:** The exact timestamp or resource limit that triggered the termination, establishing a causal boundary for the interruption.

Condition of Validity

* **Applies when:** The session is forced to terminate before all identified edge cases are either fully resolved or definitively ruled out, and a successor instance will resume the same task. * **Does not apply when:** The instance achieved a clean, verified completion of all branches, or the environment is strictly ephemeral with no possibility of successor resumption.

Decision Boundary

  1. **Is the time budget strictly exhausted (e.g., SIGTERM, timeout limit reached)?** If no, continue execution. If yes, trigger the archival sequence immediately.
  2. **Were any edge cases identified but left untested?** If no, write a standard completion record. If yes, extract the `unresolved_case_signatures` and map them to the frontier.
  3. **Did the instance record the exact `next_probe_heuristic` it was about to execute?** If no, the successor is forced to re-derive the search strategy. The terminating instance must record the interrupted action.
  4. **Conversely, when should an edge case be discarded rather than archived?** Only if the instance explicitly proved the edge case was unreachable or invalid (e.g., a schema mismatch that definitively rejects the input) *before* the time expired.

Operational Effect

  1. **Zero Redundant Exploration:** Guarantees that a successor instance resumes exactly at the interruption point, rather than restarting the exploration from scratch.
  2. **Risk Transparency:** Prevents the successor from assuming a task is "fully solved" when it is actually blocked by an unresolved frontier.
  3. **Deterministic Continuity:** Converts a chaotic, forced termination into a clean, resumable state machine transition.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
import time


class EdgeCaseStatus(Enum):
    UNEXPLORED = auto()
    PARTIALLY_TESTED = auto()
    RESOLVED = auto()
    UNREACHABLE = auto()


@dataclass(frozen=True)
class EdgeCaseCandidate:
    case_id: str
    input_signature: str
    status: EdgeCaseStatus
    partial_state: str | None = None


@dataclass(frozen=True)
class TimeBudgetFrontier:
    unresolved_cases: tuple[EdgeCaseCandidate, ...]
    next_probe_heuristic: str
    expiry_epoch: float
    frontier_digest: str


class TimeBudgetArchiver:
    """
    Evaluates interrupted session state to extract a resumable frontier of
    unhandled edge cases when a time budget expires.
    """

    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def archive_timeout(
        cls,
        candidates: tuple[EdgeCaseCandidate, ...],
        next_probe_heuristic: str,
        expiry_epoch: float,
    ) -> TimeBudgetFrontier:
        
        unresolved: list[EdgeCaseCandidate] = []

        for candidate in candidates:
            if candidate.status in (EdgeCaseStatus.UNEXPLORED, EdgeCaseStatus.PARTIALLY_TESTED):
                unresolved.append(candidate)
                
        if not unresolved:
            raise ValueError("Cannot archive a timeout frontier with zero unresolved cases.")

        if not next_probe_heuristic.strip():
            raise ValueError("Next probe heuristic must be explicitly declared for the successor.")

        digest_payload = {
            "unresolved_ids": tuple(sorted(c.case_id for c in unresolved)),
            "next_probe": next_probe_heuristic,
            "expiry": str(expiry_epoch),
        }
        digest = cls._hash(
            json.dumps(digest_payload, sort_keys=True, separators=(",", ":"))
        )

        return TimeBudgetFrontier(
            unresolved_cases=tuple(unresolved),
            next_probe_heuristic=next_probe_heuristic,
            expiry_epoch=expiry_epoch,
            frontier_digest=digest,
        )

    @classmethod
    def resume_frontier(
        cls, frontier: TimeBudgetFrontier
    ) -> tuple[tuple[EdgeCaseCandidate, ...], str]:
        """
        Fetching-time check: confirms the frontier is valid and returns the
        unresolved cases alongside the interrupted probe heuristic.
        """
        if frontier.expiry_epoch > time.time():
            raise ValueError("Cannot resume a frontier that has not yet expired.")
            
        return frontier.unresolved_cases, frontier.next_probe_heuristic