Skip to content

bug(diagnose): cron summary/overview reads last_status at wrong depth — failing list always empty #665

Description

@IceyLiu

Bug

diagnose cron summary and diagnose overview compute the failing list
by reading last_status at the top level of each job object:

// cmd_diagnose.rs:764 (cron_summary) and :783 (cron_overview)
job.get("last_status").and_then(Value::as_str)

But CronJobResponse serializes run-state fields nested under state:

// crates/aionui-api-types/src/cron.rs:129-140
pub struct CronJobResponse {
    pub id: String,
    pub enabled: bool,
    // ...
    pub state: CronJobStateDto,  // last_status is HERE, not top-level
}

// cron.rs:113-127
pub struct CronJobStateDto {
    pub last_status: Option<String>,
    // ...
}

job.get("last_status") always returns None, so failing is always an
empty list — even when jobs have actually failed. cron_overview also
copies last_error from the wrong level (cmd_diagnose.rs:792).

Impact

  • diagnose overview's cron.failing is always [].
  • diagnose cron summary's failing is always [].
  • The butler's troubleshooting skill relies on cron.failing for initial
    triage. When it's always empty the agent never flags cron failures from
    the overview pass.

Fix

Read from the nested state object:

job.get("state")
    .and_then(|s| s.get("last_status"))
    .and_then(Value::as_str)

Same pattern for last_error in cron_overview.

Discovered by

2026-07-22 butler drift audit. The asset-side workaround (pointing agents
to all[].state.last_status) is in PR #664, but the real fix is here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions