* fix(cron): clear delivery routing fields from cron edit
cron edit could set delivery channel/to/thread-id/account but could not unset them: an empty value (e.g. --to "") builds delivery.X = undefined, which is omitted from the JSON-RPC patch, so mergeCronDelivery never sees the key and the field is silently kept. The gateway RPC already accepts an explicit null to clear each field (CronDeliveryPatchSchema + mergeCronDelivery via normalizeOptionalString); the CLI just never sent it.
Add --clear-channel/--clear-to/--clear-thread-id/--clear-account, each emitting null (mirroring the existing --clear-model), with mutual-exclusion guards against the matching set flag and against --webhook.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cron): preserve delivery defaults when clearing routes
* fix(cron): validate cleared prefixed routes
---------
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
cron list/show printed "idle" for a job whose status is ok/error/skipped
when only lastRunStatus (the primary field) was set: formatStatus used
`lastStatus ?? "idle"` and omitted lastRunStatus, diverging from computeStatus
(the --json status resolver) whose JSDoc says it mirrors the human output.
Delete the duplicate formatStatus and render via the canonical computeStatus.
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clarifies cron edit --at help after maintainer rebase and preserves the Gateway-host timezone wording for cron --tz help.
Validation:
- git diff --check
- node scripts/run-vitest.mjs src/cli/cron-cli.test.ts
- local Codex autoreview clean, no actionable findings
Co-authored-by: rrrrrredy <rrrrrredy@users.noreply.github.com>
* fix(cron): report SQLite storage path in cron.status instead of legacy jobs.json
The `cron.status` gateway response returned `storePath` pointing to the
legacy `jobs.json` path, but cron jobs are actually stored in the shared
SQLite state database. This misled operators and agents into looking for
a JSON file that no longer exists.
- Add `storage: "sqlite"` and `sqlitePath` fields to CronStatusSummary
- Mark legacy `storePath` as @deprecated (kept for backward compat)
- Update CLI warning to prefer sqlitePath over storePath
- Add regression assertions in read-ops test
Fixes#91766
* fix(macos): prefer sqlitePath in cron status display
* fix(macos): add sqlitePath to CronSchedulerStatus type
Reject malformed or explicit empty Gateway RPC timeout values before opening Gateway calls, align the shared Gateway RPC omitted-timeout fallback with the 30000 ms CLI default, and validate explicit `cron add --timeout-seconds` values at the CLI boundary.
Carries forward the useful source work from #54646 and the earlier timeout-validation context from #40953. #60661 remains separate accepted-run timeout semantics work and is intentionally not folded into this change.
Validation:
- `npm run review-results -- /tmp/clownfish-check-27341769444`
- `git diff --check`
- OpenClaw PR checks on `ce7bd8b9388a5689b14ddc2b3a984f7b4647e5ca`: 132 pass, 0 pending, 0 failing
- ClawSweeper re-review: https://github.com/openclaw/clawsweeper/actions/runs/27344244608
Co-authored-by: RayRuan <43744645+ruanrrn@users.noreply.github.com>
Co-authored-by: Homeran <11574611+comeran@users.noreply.github.com>
* fix(cron): reject durations that overflow to a non-finite value
parseDurationMs guarded the parsed mantissa but returned Math.floor(n * factor)
with no finite check on the product. A finite mantissa times a large unit factor
(e.g. "1e302d", factor 86_400_000) overflows to Infinity, which was returned as
the millisecond value. Reject a non-finite result instead, matching the existing
contract that already rejects non-finite / non-positive mantissas.
Fixes#83906.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: rerun flaky runner checks
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds `tsIso`, `runAtIso`, and `nextRunAtIso` to the JSON output of the `cron runs` command. This enhancement derives local-offset ISO 8601 strings from the existing numeric timestamps purely at the display layer, matching the diagnostic log format. The underlying SQLite storage, protocol schema, and raw numeric fields remain completely unchanged to ensure strict backward compatibility.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add command-backed cron jobs with timeout-safe process-tree cleanup for shell wrappers. Ensures POSIX command jobs run in a killable process group, adds Windows tree cleanup fallback handling, and covers timeout cleanup behind sh -lc.
Extract shared normalization/coercion helpers into private @openclaw/normalization-core workspace package while preserving existing plugin SDK helper subpaths.\n\nAlso keeps direct normalization-core imports internal, wires UI/build/loader resolution, and replaces the slow PR network CodeQL lane with a fast added-line boundary scan while retaining full CodeQL for scheduled/manual runs.\n\nVerification: local moved tests, plugin SDK boundary tests, extension loader tests, agents-support shard, UI build/test, build artifacts, lint, workflow guards, autoreview, and GitHub CI passed on PR head 963d893715.
Summary:
- Adds a 50-page and advancing-`nextOffset` guard to `loadCronJobForShow`, exports that helper for regression tests, and adds an unreleased changelog entry.
- Reproducibility: yes. Current main is source-reproducible because `loadCronJobForShow` loops while `hasMore` ... ed numeric `nextOffset`; the PR discussion also includes terminal before/after proof for the same CLI path.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 7828b4bdae.
- Required merge gates passed before the squash merge.
Prepared head SHA: 7828b4bdae
Review: https://github.com/openclaw/openclaw/pull/83989#issuecomment-4484474655
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
* feat(cron): add computed status field to --json output
`openclaw cron list --json` and `openclaw cron show <id> --json` now
include a top-level `status` field on each job object, computed from
enabled + state.runningAtMs + state.lastRunStatus.
Values: "disabled" | "running" | "ok" | "error" | "skipped" | "idle"
This matches the human-readable status column already shown by
`cron list` and `cron show` (without --json), making it easier for
external tooling (dashboards, ops gateways) to determine job state
without re-implementing the derivation logic.
The raw state object is preserved unchanged for backward compatibility.
* fix: preserve lastStatus fallback + add changelog entry
Address ClawSweeper review findings:
- P2: Fall back to deprecated state.lastStatus when lastRunStatus is
absent, matching the existing formatStatus behavior for legacy jobs.
- P3: Add CHANGELOG.md entry under Unreleased for this user-facing
CLI feature.
* fix: address lint errors - add braces and avoid spread-in-map
---------
Co-authored-by: Rodin <rodin@forgedthought.ai>
Co-authored-by: claw <claw@weiker.me>
Summary:
- This PR adds optional `agentId` filtering to `cron.list`, auto-fills it for agent tool calls, exposes `openclaw cron list --agent`, updates generated protocol clients, docs, changelog, tests, and prompt fixtures.
- Reproducibility: yes. The motivating behavior is source-reproducible on current main because cron tool, CLI, ... e list paths do not accept or apply `agentId`; the PR diff adds that path with focused regression coverage.
Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: chore: regenerate protocol schema after adding agentId to CronListParams
- Included post-review commit in the final squash: feat(cron): add agentId filtering to cron list
Validation:
- ClawSweeper review passed for head 35b692bc97.
- Required merge gates passed before the squash merge.
Prepared head SHA: 35b692bc97
Review: https://github.com/openclaw/openclaw/pull/77602#issuecomment-4375631700
Co-authored-by: zhanggttry <zhanggttry@163.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
* fix(cron): warn when --agent is not specified on cron add
Warn users when creating a cron job without specifying the --agent flag,
so they know the job will run with the default agent (main).
Fixes#42196
* fix(cron): warn when cron add omits --agent
* fix(cron): name default agent in warning
---------
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Several `openclaw <parent>` commands (channels, plugins, approvals, devices,
cron, mcp) were exiting with code 1 when invoked bare, while printing the
same help-style content that `<parent> --help` produces (which exits 0).
This broke `&&` chains and surfaced a misleading
`ELIFECYCLE Command failed with exit code 1.` line under pnpm.
Add a small `applyParentDefaultHelpAction(cmd)` helper in
`src/cli/program/parent-default-help.ts` that attaches a default action
which prints the parent's own help and sets `process.exitCode = 0`. The
helper is a no-op when the parent already has its own action (e.g.
`agents` defaulting to `agents list`), so existing intentional defaults
are preserved.
Apply it to the six core parents listed in #73077.