Source code for ralph.agents.idle_watchdog.waiting_status_event

"""Waiting status event for idle watchdog corroboration."""

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass, field
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .waiting_status_kind import WaitingStatusKind


[docs] @dataclass(frozen=True) class WaitingStatusEvent: """Structured status event emitted by IdleWatchdog during WAITING_ON_CHILD deferral. This dataclass is frozen so subscribers cannot accidentally mutate shared state. The ``diagnostic`` dict is a forward-compatible extension point for Phase 3 corroborating signals (workspace_event_delta, oldest_child_seconds, scoped_child_active, etc.). This plan ships only the throttle, transition, suspicion, and hard-stop summary semantics; Phase 3 fields are out of scope. Attributes: kind: The type of event (ENTERED, PROGRESS, SUSPECTED_FROZEN, EXITED, HARD_STOP). cumulative_seconds: Cumulative WAITING_ON_CHILD seconds across the session so far. current_run_seconds: Seconds spent in the current WAITING_ON_CHILD run. idle_elapsed_seconds: Seconds since last record_activity() call. ceiling_seconds: The active WAITING_ON_CHILD ceiling for this event. suspect_threshold_seconds: The suspect_waiting_on_child_seconds threshold, or None. diagnostic: Optional dict of extra diagnostic keys for HARD_STOP events. subagent_activity: Optional short string (truncated to 200 chars by the watchdog at write time) describing the most recent child-progress observation recorded via ``record_subagent_work``. The watchdog captures the latest raw line so operators see which subagent activity was current at the moment of the event (fires, transitions, suspicion, progress). ``None`` when no subagent observation has happened yet. Optional with a default so existing positional callers continue to work without changes. last_subagent_progress_at: Optional monotonic timestamp of the most recent subagent observation that populated ``subagent_activity``. Mirrors the watchdog's ``last_subagent_progress_at`` channel-evidence timestamp so every emitted event carries BOTH the textual description and when it was last observed. Optional with a default so existing positional callers continue to work without changes. current_subagent_tool_call: Optional parsed ``verb:`` prefix from ``subagent_activity`` (the current tool call the subagent is executing). Mirrors the watchdog's ``diagnostic_snapshot()["current_subagent_tool_call"]`` field so both surfaces carry the same parsed value. Optional with a default so existing positional callers continue to work without changes. """ kind: WaitingStatusKind cumulative_seconds: float current_run_seconds: float idle_elapsed_seconds: float ceiling_seconds: float suspect_threshold_seconds: float | None diagnostic: dict[str, str | int | float | bool | list[object]] = field(default_factory=dict) subagent_activity: str | None = None last_subagent_progress_at: float | None = None current_subagent_tool_call: str | None = None
WaitingStatusListener = Callable[[WaitingStatusEvent], None]