Skip to content

fix(control-ui): exclude disabled cron jobs from Overview failed count#95723

Merged
openclaw-clownfish[bot] merged 1 commit into
openclaw:mainfrom
ZengWen-DT:fix/95716-overview-disabled-cron-failed-count
Jun 23, 2026
Merged

fix(control-ui): exclude disabled cron jobs from Overview failed count#95723
openclaw-clownfish[bot] merged 1 commit into
openclaw:mainfrom
ZengWen-DT:fix/95716-overview-disabled-cron-failed-count

Conversation

@ZengWen-DT

Copy link
Copy Markdown
Contributor

What Problem This Solves

The Control UI Overview counted a cron job as a current failure whenever its
state.lastRunStatus === "error", with no check on whether the job is still
active. Both the Overview "failed cron" card hint and the attention-items list
shared this gap. As a result, a job that previously failed and was then
intentionally disabled (enabled: false, nextRunAtMs: null) kept being
reported as an active operational problem purely because of its retained
historical error state. This makes a retired job look like a live incident and
erodes trust in Overview as a current-actionability surface. Fixes #95716.

Why This Change Was Made

Overview health is about current actionability. A disabled job cannot run
again, so a stale lastRunStatus: "error" on it is history, not an active
failure. The adjacent "overdue jobs" computation already gates on j.enabled;
the failed-cron count was the inconsistent one. Rather than duplicate the
enabled && status === "error" check across the two surfaces (which previously
each inlined the predicate), this adds one shared isCronJobActiveFailure
helper in cron-status.ts so both surfaces stay in sync. Per-job detail views
keep showing the historical status through resolveCronJobLastRunStatus, which
is left unchanged.

User Impact

  • Disabled cron jobs that previously errored no longer inflate the Overview
    "N failed" badge or raise an "N cron jobs failed" attention callout.
  • Enabled jobs whose last run errored are still counted, unchanged.
  • Per-job views still display the historical error status, so no information
    is lost.
  • Control UI only; no config, schema, gateway protocol, or scheduler behavior
    changes.

Evidence

New colocated unit test ui/src/ui/cron-status.test.ts (3 cases) passing via the
repo runner:

$ node scripts/run-vitest.mjs ui/src/ui/cron-status.test.ts
 Test Files  1 passed (1)
      Tests  3 passed (3)

Before/after on a harness driving the real exported functions with the exact
job state from the issue (one disabled-after-failure job + one active failing
job):

disabled job historical status: error
OLD failed-count: 2 -> [ '81fc999f-0cf1-4cfe-aabb-8326f673d575', 'active' ]
NEW failed-count: 1 -> [ 'active' ]

The disabled job is dropped from the count while its historical error status
is still reported for detail views; the active failing job is unchanged.

Formatting (oxfmt --check) and oxlint clean on all four touched files.


AI-assisted.

Overview surfaces counted any job whose lastRunStatus was "error" as a
current failure, so an intentionally disabled job that previously failed
kept inflating the top-level "failed cron" badge and attention callout.

Add a shared isCronJobActiveFailure predicate that gates the error status
on enabled, matching the adjacent overdue filter, and use it in both the
overview card and the attention items list. Historical status stays
visible in detail views via resolveCronJobLastRunStatus.
@clawsweeper

clawsweeper Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 22, 2026, 8:43 PM ET / 00:43 UTC.

Summary
This PR adds a shared Control UI cron active-failure predicate and uses it for the Overview failed-count card and attention item, with a colocated unit test.

PR surface: Source +6, Tests +40. Total +46 across 4 files.

Reproducibility: yes. at source level: current main's two Overview aggregations filter only on resolved historical error status, so a disabled job retaining lastRunStatus: "error" enters both summaries. I did not run a browser UI scenario in this read-only pass.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #95716
Summary: This PR is the explicit candidate fix for the canonical disabled-cron Overview false-failure issue; older cron false-failure reports are related but do not own this exact UI aggregation bug.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Next step before merge

  • No automated repair job is needed because this PR is already the open candidate fix and I found no narrow code defect for automation to repair.

Security
Cleared: The diff only changes Control UI TypeScript/helper tests and does not touch dependencies, workflows, credentials, package metadata, or code-execution surfaces.

Review details

Best possible solution:

Land this or an equivalent small UI fix after normal gates so Overview active-failure summaries ignore disabled historical errors while detail and filter surfaces preserve historical run status.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main's two Overview aggregations filter only on resolved historical error status, so a disabled job retaining lastRunStatus: "error" enters both summaries. I did not run a browser UI scenario in this read-only pass.

Is this the best way to solve the issue?

Yes: centralizing job.enabled && historical status is error in cron-status.ts is the narrow maintainable fix for current-actionability surfaces while leaving detail views and filters on historical status.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 43f2b61f3b01.

Label changes

Label changes:

  • add P2: This is a normal-priority Control UI behavior fix for misleading operational status with limited blast radius.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal before/after output from a harness using the exported functions with the reported disabled-after-error job, plus focused unit coverage.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes copied terminal before/after output from a harness using the exported functions with the reported disabled-after-error job, plus focused unit coverage.

Label justifications:

  • P2: This is a normal-priority Control UI behavior fix for misleading operational status with limited blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes copied terminal before/after output from a harness using the exported functions with the reported disabled-after-error job, plus focused unit coverage.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal before/after output from a harness using the exported functions with the reported disabled-after-error job, plus focused unit coverage.
Evidence reviewed

PR surface:

Source +6, Tests +40. Total +46 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 3 12 6 +6
Tests 1 40 0 +40
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 52 6 +46

What I checked:

  • Repository policy read: Read the full root AGENTS.md and scoped ui/AGENTS.md; the root review-depth policy affected this review, while the scoped UI i18n guidance did not apply to the touched files. (AGENTS.md:7, 43f2b61f3b01)
  • Current main attention summary still counts disabled historical errors: On current main, buildAttentionItems filters failed cron jobs only by resolved last-run status equal to error, with no enabled check before raising the attention item. (ui/src/ui/app-settings.ts:944, 43f2b61f3b01)
  • Current main Overview card still uses the same broad predicate: The Overview card failedCronCount currently counts every job whose resolved historical last-run status is error. (ui/src/ui/views/overview-cards.ts:137, 43f2b61f3b01)
  • PR centralizes the active-failure predicate: The PR head adds isCronJobActiveFailure as job.enabled plus historical error status, preserving resolveCronJobLastRunStatus for detail/history consumers. (ui/src/ui/cron-status.ts:14, ee7fbdfc3cbc)
  • PR applies the predicate to both affected Overview surfaces: The PR head switches both buildAttentionItems and renderOverviewCards to filter with isCronJobActiveFailure. (ui/src/ui/app-settings.ts:944, ee7fbdfc3cbc)
  • Focused regression coverage added: The new test covers enabled error jobs, disabled jobs retaining historical error status, and non-error or unknown states. (ui/src/ui/cron-status.test.ts:21, ee7fbdfc3cbc)

Likely related people:

  • BunsDev: Authored and merged the dashboard-v2 views refactor that introduced the modular Overview cards/attention surfaces where this aggregation lives. (role: overview surface introducer; confidence: medium; commits: f76a3c5225bb, 3bbbe33a1b91; files: ui/src/ui/views/overview-cards.ts, ui/src/ui/views/overview.ts, ui/src/ui/app-settings.ts)
  • Takhoffman: Authored the full cron edit parity and compact filters work that shaped the cron UI/types/status path used by the affected Overview state. (role: cron UI feature contributor; confidence: medium; commits: 77c3b142a966; files: ui/src/ui/types.ts, ui/src/ui/views/cron.ts, ui/src/ui/controllers/cron.ts)
  • omarshahine: Recently changed the Overview dashboard and attention-item paths adjacent to the failed-cron summary while adding the Model Auth card. (role: recent overview contributor; confidence: medium; commits: 507b7189177a; files: ui/src/ui/views/overview-cards.ts, ui/src/ui/app-settings.ts, ui/src/ui/model-auth-helpers.ts)
  • vincentkoc: Recent blame on the affected lines points to carried-forward release/refactor commits, making this a useful routing signal but not the original feature source. (role: recent area contributor; confidence: low; commits: e9756f9e71b5, c645ec4555c0; files: ui/src/ui/app-settings.ts, ui/src/ui/views/overview-cards.ts, ui/src/ui/cron-status.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jun 23, 2026
@openclaw-clownfish
openclaw-clownfish Bot merged commit 9fa14ff into openclaw:main Jun 23, 2026
111 of 119 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 23, 2026
…aw#95723)

Overview surfaces counted any job whose lastRunStatus was "error" as a
current failure, so an intentionally disabled job that previously failed
kept inflating the top-level "failed cron" badge and attention callout.

Add a shared isCronJobActiveFailure predicate that gates the error status
on enabled, matching the adjacent overdue filter, and use it in both the
overview card and the attention items list. Historical status stays
visible in detail views via resolveCronJobLastRunStatus.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Overview counts disabled cron jobs as failed when their last run ended in error

1 participant