prodex 0.28.0

OpenAI profile pooling and safe auto-rotate for Codex CLI and Claude Code
Documentation
use super::*;

mod diagnosis;
mod parsing;
mod render;
mod state;

#[allow(unused_imports)]
pub(crate) use diagnosis::{runtime_doctor_marker_count, runtime_doctor_top_facet};
#[allow(unused_imports)]
pub(crate) use parsing::{read_runtime_log_tail, summarize_runtime_log_tail};
#[allow(unused_imports)]
pub(crate) use render::{
    runtime_doctor_fields, runtime_doctor_fields_for_summary, runtime_doctor_json_value,
};
#[allow(unused_imports)]
pub(crate) use state::{
    collect_runtime_doctor_state, collect_runtime_doctor_summary, runtime_doctor_degraded_routes,
};

const RUNTIME_DOCTOR_FACETS: &[&str] = &[
    "lane",
    "route",
    "profile",
    "reason",
    "transport",
    "family",
    "client",
    "tool_surface",
    "continuation",
    "origin",
    "warning",
    "quota_source",
    "quota_band",
    "five_hour_status",
    "weekly_status",
    "affinity",
    "context",
    "event",
    "stage",
    "state",
    "source",
];

const RUNTIME_DOCTOR_MARKERS: &[&str] = &[
    "runtime_proxy_queue_overloaded",
    "runtime_proxy_active_limit_reached",
    "runtime_proxy_lane_limit_reached",
    "runtime_proxy_overload_backoff",
    "runtime_proxy_admission_wait_started",
    "runtime_proxy_admission_recovered",
    "runtime_proxy_queue_wait_started",
    "runtime_proxy_queue_recovered",
    "profile_inflight_saturated",
    "upstream_connect_timeout",
    "upstream_connect_dns_error",
    "upstream_tls_handshake_error",
    "upstream_connect_error",
    "precommit_budget_exhausted",
    "profile_retry_backoff",
    "profile_transport_backoff",
    "profile_circuit_open",
    "profile_circuit_half_open_probe",
    "profile_health",
    "profile_latency",
    "profile_bad_pairing",
    "previous_response_not_found",
    "previous_response_negative_cache",
    "compact_committed_owner",
    "compact_followup_owner",
    "compact_fresh_fallback_blocked",
    "compact_pressure_shed",
    "compact_lineage_released",
    "selection_pick",
    "selection_skip_current",
    "selection_skip_affinity",
    "responses_pre_send_skip",
    "websocket_pre_send_skip",
    "quota_release_profile_affinity",
    "quota_critical_floor_before_send",
    "upstream_usage_limit_passthrough",
    "compat_request_surface",
    "compat_warning",
    "websocket_reuse_skip_quota_exhausted",
    "websocket_reuse_watchdog",
    "websocket_precommit_frame_timeout",
    "stream_read_error",
    "local_writer_error",
    "first_upstream_chunk",
    "first_local_chunk",
    "state_save_ok",
    "state_save_skipped",
    "state_save_error",
    "state_save_queued",
    "continuation_journal_save_ok",
    "continuation_journal_save_error",
    "continuation_journal_save_queued",
    "runtime_proxy_restore_counts",
    "runtime_proxy_startup_audit",
    "profile_probe_refresh_queued",
    "profile_probe_refresh_start",
    "profile_probe_refresh_ok",
    "profile_probe_refresh_error",
    "quota_blocked_affinity_released",
];

const RUNTIME_DOCTOR_COUNT_FIELD_ROWS: &[(&str, &str)] = &[
    ("Queue overload", "runtime_proxy_queue_overloaded"),
    ("Active limit", "runtime_proxy_active_limit_reached"),
    ("Lane limit", "runtime_proxy_lane_limit_reached"),
    ("Overload backoff", "runtime_proxy_overload_backoff"),
    ("Pre-commit budget", "precommit_budget_exhausted"),
    ("Responses pre-send skips", "responses_pre_send_skip"),
    ("Websocket pre-send skips", "websocket_pre_send_skip"),
    (
        "Quota critical floor pre-send",
        "quota_critical_floor_before_send",
    ),
    (
        "Upstream usage-limit passthrough",
        "upstream_usage_limit_passthrough",
    ),
    ("Retry backoff", "profile_retry_backoff"),
    ("Transport backoff", "profile_transport_backoff"),
    ("Route circuits", "profile_circuit_open"),
    ("Health penalties", "profile_health"),
    ("Latency penalties", "profile_latency"),
    ("Bad pairing", "profile_bad_pairing"),
    ("Prev not found", "previous_response_not_found"),
    ("Prev negative cache", "previous_response_negative_cache"),
    ("Compact guard", "compact_fresh_fallback_blocked"),
    ("Compact shed", "compact_pressure_shed"),
    ("Selection picks", "selection_pick"),
    ("Selection skips", "selection_skip_current"),
    ("WS reuse watchdog", "websocket_reuse_watchdog"),
    (
        "WS first-frame timeouts",
        "websocket_precommit_frame_timeout",
    ),
    ("Stream read errors", "stream_read_error"),
    ("Writer errors", "local_writer_error"),
    ("State save errors", "state_save_error"),
    ("Cont journal err", "continuation_journal_save_error"),
    ("State save ok", "state_save_ok"),
    ("Cont journal ok", "continuation_journal_save_ok"),
    ("State save skipped", "state_save_skipped"),
    ("Startup audit", "runtime_proxy_startup_audit"),
    ("Admission recovered", "runtime_proxy_admission_recovered"),
    ("Queue recovered", "runtime_proxy_queue_recovered"),
    ("Probe refresh", "profile_probe_refresh_start"),
    ("Probe refresh errors", "profile_probe_refresh_error"),
    ("Compat samples", "compat_request_surface"),
];

const RUNTIME_DOCTOR_SELECTION_PRESSURE_MARKERS: &[&str] = &[
    "selection_pick",
    "selection_skip_current",
    "selection_skip_affinity",
    "precommit_budget_exhausted",
];

const RUNTIME_DOCTOR_TRANSPORT_PRESSURE_MARKERS: &[&str] = &[
    "stream_read_error",
    "upstream_connect_timeout",
    "upstream_connect_dns_error",
    "upstream_tls_handshake_error",
    "upstream_connect_error",
    "profile_transport_backoff",
    "profile_circuit_open",
    "profile_circuit_half_open_probe",
    "websocket_precommit_frame_timeout",
    "local_writer_error",
];

const RUNTIME_DOCTOR_PERSISTENCE_PRESSURE_MARKERS: &[&str] =
    &["state_save_error", "continuation_journal_save_error"];

const RUNTIME_DOCTOR_ACTIVE_PERSISTENCE_MARKERS: &[&str] = &["state_save_skipped"];

const RUNTIME_DOCTOR_ACTIVE_QUOTA_REFRESH_MARKERS: &[&str] =
    &["profile_probe_refresh_start", "profile_probe_refresh_ok"];

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn summarize_runtime_log_tail_understands_json_lines() {
        let tail = br#"{"timestamp":"2026-04-08 10:00:00.000 +00:00","message":"request=7 profile_health profile=main route=responses score=4","fields":{"request":"7","profile":"main","route":"responses","score":"4"}}"#;
        let summary = summarize_runtime_log_tail(tail);

        assert_eq!(summary.line_count, 1);
        assert_eq!(
            summary.marker_counts.get("profile_health").copied(),
            Some(1)
        );
        assert_eq!(
            summary.first_timestamp.as_deref(),
            Some("2026-04-08 10:00:00.000 +00:00")
        );
        assert_eq!(
            summary
                .marker_last_fields
                .get("profile_health")
                .and_then(|fields| fields.get("profile"))
                .map(String::as_str),
            Some("main")
        );
    }
}