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.
Bug
diagnose cron summaryanddiagnose overviewcompute thefailinglistby reading
last_statusat the top level of each job object:But
CronJobResponseserializes run-state fields nested understate:job.get("last_status")always returnsNone, sofailingis always anempty list — even when jobs have actually failed.
cron_overviewalsocopies
last_errorfrom the wrong level (cmd_diagnose.rs:792).Impact
diagnose overview'scron.failingis always[].diagnose cron summary'sfailingis always[].cron.failingfor initialtriage. When it's always empty the agent never flags cron failures from
the overview pass.
Fix
Read from the nested
stateobject:Same pattern for
last_errorincron_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.