Repository navigation
Closed
Labels
P2Normal priority bug or improvement with limited blast radius.Normal priority bug or improvement with limited blast radius.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.User-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.leverLever delivery tracking issueLever delivery tracking issue
Description
Lane 5 of 5 for #2071. Filed by a Copilot agent.
Problem: in CronPage.xaml.cs (~238-252), the 90 s Task.Delay continuation reads the _runningJobIds HashSet off the UI thread. It also carries no run identity. So if a job finishes and the user runs it again, the first run's timer clears the newer run's "running" state.
Fix: record a token per run. When the timer fires, check it and clear the state on the UI thread, only if the token still matches.
Coordinate with: #2032, which also changes CronPage.
Done when:
- a unit test on the extracted run tracker shows a stale timer does not clear a newer run
- the required validation passes
Reacted by clawsweeper
Metadata
Metadata
Assignees
Labels
P2Normal priority bug or improvement with limited blast radius.Normal priority bug or improvement with limited blast radius.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.User-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.leverLever delivery tracking issueLever delivery tracking issue
Type
Fields
Priority
None yet
Projects
- StatusShow more project fieldsBacklog
Activity
clawsweeper commentedon Nov 8, 2026
Codex review: this still needs some work.
Summary
Keep open: current main still permits an earlier run's safety timer to clear a newer run's state, and this collaborator-authored issue requires maintainer judgment before closure.
Reproducibility: Source establishes the sequence: complete run A, start run B before A's 90-second timeout, then let A's callback clear B by the shared job ID; no builds, tests, or live reproduction were run.
Next step
Coordinate the protected audit lane with the pending page replacement, then establish a failing stale-timer regression and guard UI-thread cleanup with per-run identity.
Review details
Best possible solution:
Keep run identity and timeout cleanup under UI-thread ownership so stale callbacks leave newer runs and their refresh loops untouched.
Do we have a high-confidence way to reproduce the issue?
Source establishes the sequence: complete run A, start run B before A's 90-second timeout, then let A's callback clear B by the shared job ID; no builds, tests, or live reproduction were run.
Is this the best way to solve the issue?
A per-run token checked inside the dispatched callback directly addresses the defect; moving only the HashSet lookup onto the UI thread would leave stale-run cleanup possible.
AGENTS.md: found and applied where relevant.
Remaining risk / open question:
Codex review notes: model internal, reasoning medium; reviewed against e70292487958.
Label changes
Label changes:
P2: A source-proven race affects manual cron status and action gating without evidence of a blocked core workflow or failed job execution.impact:ux-friction: A newer run can lose its running indicator and refresh loop while job actions become available prematurely.issue-rating: 🦞 diamond lobster: Current issue advisory state selects this label.clawsweeper:source-repro: Current issue advisory state selects this label.Label justifications:
P2: A source-proven race affects manual cron status and action gating without evidence of a blocked core workflow or failed job execution.impact:ux-friction: A newer run can lose its running indicator and refresh loop while job actions become available prematurely.Evidence reviewed
What I checked:
src/OpenClaw.Tray.WinUI/Pages/CronPage.xaml.cs:238, e70292487958)src/OpenClaw.Tray.WinUI/Pages/CronPage.xaml.cs:312, e70292487958)tests/OpenClaw.Tray.Tests/CronRunningLatchTests.cs:5, e70292487958)src/OpenClaw.Tray.WinUI/Pages/CronPage.xaml.cs:312, 638386ed73ae)How this review workflow works
@clawsweeper re-reviewcomments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.@clawsweeper re-reviewor@clawsweeper re-runon an open PR or issue to request a fresh review only.@clawsweeper reviewto request a fresh review only.@clawsweeper explainto ask for more context, or@clawsweeper stopto stop active automation.Reviewed November 8, 2026, 1:29 AM ET / 06:29 UTC.
shanselman commentedon Nov 11, 2026
Hi, I'm a Copilot triage agent doing an overnight sweep (not Scott). A heads-up for whoever owns this lane, no action needed from me.
On current
mainthe code this issue describes is gone. The 90 sTask.Delaycontinuation and the_runningJobIdsset inCronPage.xaml.cswere replaced when #1893 (feat(automations): native Automations page with web parity) landed. Run ownership now lives inAutomationsStore.RunNowAsync(src/OpenClaw.Shared/Cron/AutomationsStore.cs):RunInvocation, and the acknowledgement and failure callbacks only act ifOwnsRun(jobId, invocation)still matchesOwnsWatcher(jobId, cts)still matches, so an older timer should not clear a newer runAutomationsStoreConcurrencyTestsalready covers related ordering:LateAcknowledgementCannotRetireOrReplaceANewerInvocationandSuccessiveRunsRequireTheAcceptedRunIdDespiteStaleHistoryAndListStateWhat I did not do: run the app or reproduce the old race. This is from reading
mainonly. I also could not find a test that exercises the safety-timeout path specifically (theOwnsWatcherguard), so that might be a small follow-up if the owner wants a direct regression for the original scenario.If a maintainer agrees this is covered, it looks ready to close. I'm leaving that decision to you, and I'm not closing anything. Related: #2082 (fix: keep older Run Now attempts from clearing newer runs) targets the same old code and no longer applies.
bkudiess commentedon Nov 13, 2026
Closing as fixed by #1893 (feat(automations): native Automations page with web parity).
AutomationsStoregives each Run Now its own invocation, and the safety timeout checks that it still owns the job before clearing it, so an older attempt can no longer clear a newer run. The superseded fix in #2082 is closed; details are in #2082 (comment).