Source code for ralph.agents.idle_watchdog.watchdog_fire_reason

"""Enumeration of reasons the idle watchdog fires."""

from enum import StrEnum


[docs] class WatchdogFireReason(StrEnum): """Why the watchdog decided to fire. IdleWatchdog reasons (in-stream): NO_OUTPUT_DEADLINE, NO_OUTPUT_AT_START, CHILDREN_PERSIST_TOO_LONG, SESSION_CEILING_EXCEEDED, REPEATED_IDENTICAL_TOOL_CALL, STRICTLY_STUCK. PostExitWatchdog reasons (post-exit): PROCESS_EXIT_HANG, DESCENDANT_HANG. """ NO_OUTPUT_DEADLINE = "no_output_deadline" NO_OUTPUT_AT_START = "no_output_at_start" STALLED_AFTER_TOOL_RESULT = "stalled_after_tool_result" REPEATED_ERROR_LOOP = "repeated_error_loop" REPEATED_IDENTICAL_TOOL_CALL = "repeated_identical_tool_call" CHILDREN_PERSIST_TOO_LONG = "children_persist_too_long" NO_PROGRESS_QUIET = "no_progress_quiet" # Orthogonal ceiling for stuck-but-alive jobs. Fires when the # corroborator reports ``alive_by`` in # ``{OS_DESCENDANT_ONLY_STALE_PROGRESS, CPU_IDLE_WHILE_ALIVE, # LOG_STALE_WHILE_ALIVE}`` AND no first-party channel is fresh # for ``no_progress_quiet_strictly_stuck_seconds``. Independent of # ``NO_PROGRESS_QUIET`` (which requires ``alive_by is None``). # The import-time assertion in idle_watchdog.py locks the enum # set so a future PR cannot silently drop this value. STRICTLY_STUCK = "strictly_stuck" SESSION_CEILING_EXCEEDED = "session_ceiling_exceeded" PROCESS_EXIT_HANG = "process_exit_hang" DESCENDANT_HANG = "descendant_hang" # Diagnostic-only reason. The watchdog NEVER produces FIRE for this # reason; it is the StuckKind that the classifier returned when a # candidate fire was deferred. Surfaced on the watchdog's # last_fire_reason property for post-mortem diagnostics so an # operator can see WHY a would-be fire was deferred. The # import-time assertion in idle_watchdog.py locks the enum set so a # future PR cannot silently add or remove a reason. DEFERRED_BY_STUCK_CLASSIFIER = "deferred_by_stuck_classifier"