Skip to content

fix(cron): migrate legacy string schedule/command cron store jobs#31926

Merged
steipete merged 2 commits intoopenclaw:mainfrom
bmendonca3:bm/cron-legacy-shape-trim-crash
Mar 2, 2026
Merged

fix(cron): migrate legacy string schedule/command cron store jobs#31926
steipete merged 2 commits intoopenclaw:mainfrom
bmendonca3:bm/cron-legacy-shape-trim-crash

Conversation

@bmendonca3
Copy link

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: cron store migration did not handle legacy jobs where schedule was a plain cron string and payload existed only as top-level command, so those jobs entered schedule-error loops instead of being normalized.
  • Why it matters: affected jobs can repeatedly log schedule computation failures and auto-disable, and legacy entries remain inconsistent in persisted store shape.
  • What changed: ensureLoaded now migrates string schedule to { kind: "cron", expr }, infers payload from legacy top-level command, normalizes missing/invalid sessionTarget, and strips legacy top-level command/timeout fields during migration.
  • What did NOT change (scope boundary): no cron runtime execution semantics were changed beyond store-shape normalization; no delivery/timer/refire behavior changes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Legacy cron entries persisted as:
    • schedule: "<cron expr>"
    • top-level command
      are now normalized on load and persisted as canonical cron jobs.
  • Scheduler no longer emits per-tick schedule-compute warnings for this legacy shape.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node v22, Vitest
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): cron store fixture under temp path

Steps

  1. Create a cron store file with a legacy entry:
    • schedule: "0 */2 * * *"
    • command: "bash /tmp/imessage-refresh.sh"
    • no payload and no sessionTarget.
  2. Start CronService against that store.
  3. Inspect persisted store and scheduler warnings.

Expected

  • Job is migrated to canonical shape.
  • No schedule-compute warning loop for missing cron expression structure.

Actual

  • Before fix: string schedule remained unmigrated and triggered schedule-compute failure path.
  • After fix: job is normalized and no schedule warning is emitted for this shape.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Before (same test on this branch before fix):

  • pnpm vitest src/cron/service.store.migration.test.ts -t "#18445"
  • Failure: expected migrated object but received raw string "0 */2 * * *".

After:

  • pnpm vitest src/cron/service.store.migration.test.ts
  • pnpm vitest src/cron/store.test.ts src/cron/service.issue-13992-regression.test.ts src/cron/service/jobs.schedule-error-isolation.test.ts

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • legacy string schedule migrates to canonical cron schedule object.
    • command-only legacy payload migrates to payload.kind="systemEvent".
    • missing/invalid sessionTarget infers deterministically from payload kind.
    • legacy command/timeout top-level fields are removed after migration.
    • no schedule-warning log is produced for this legacy shape during migration/start.
  • Edge cases checked:
    • existing cron store migration tests still pass.
    • schedule error isolation tests still pass.
  • What you did not verify:
    • full repo-wide pnpm check gate currently fails on upstream due an unrelated existing TypeScript error in extensions/zalouser/src/monitor.ts.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this commit or restore pre-migration cron store snapshot (jobs.json.bak) if needed.
  • Files/config to restore: cron store file at configured storePath.
  • Known bad symptoms reviewers should watch for: unexpected payload/sessionTarget normalization on malformed legacy entries.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: legacy entries with intentionally custom/non-canonical fields may now be normalized more aggressively (sessionTarget, top-level legacy fields removed).
    • Mitigation: migration only targets known legacy fields, has focused regression coverage, and preserves canonical runtime fields.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

Migrated legacy cron jobs with string schedule fields and top-level command payloads to canonical store format, preventing schedule-error loops.

Key changes:

  • String schedules (e.g., "0 */2 * * *") now converted to { kind: "cron", expr: "0 */2 * * *" } objects
  • Legacy command field inferred as payload.kind="systemEvent" with text from command
  • sessionTarget normalized to "main" or "isolated" based on payload kind (systemEvent → main, agentTurn → isolated)
  • Legacy command and timeout top-level fields stripped after migration

Migration flow:

  1. Schedule string → object conversion happens first
  2. Payload inference from command if payload missing
  3. SessionTarget normalization based on inferred payload kind
  4. Legacy field cleanup

The test comprehensively verifies all migration aspects including no schedule-compute warnings after migration.

Confidence Score: 5/5

  • Safe to merge - focused migration fix with comprehensive test coverage
  • The changes are well-scoped to legacy store normalization, order of operations is correct (schedule conversion → payload inference → sessionTarget normalization → legacy field cleanup), comprehensive test coverage verifies all migration aspects, and no changes to runtime execution semantics beyond store shape normalization
  • No files require special attention

Last reviewed commit: 5475fdb

@steipete steipete force-pushed the bm/cron-legacy-shape-trim-crash branch from 5475fdb to 2fe63e9 Compare March 2, 2026 19:55
@steipete steipete merged commit b1cc8ff into openclaw:main Mar 2, 2026
@steipete
Copy link
Contributor

steipete commented Mar 2, 2026

Landed via temp rebase onto main.

  • Gate: pnpm -s vitest run src/cron/service.store.migration.test.ts
  • Land commit: 2fe63e9
  • Merge commit: b1cc8ff

Thanks @bmendonca3!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: legacy cron store job shape (schedule string + command) can trigger scheduler .trim errors and hide jobs from cron list

2 participants