#15685: feat(cron): add maxRuns for automatic recurring job cleanup
app: web-ui
gateway
agents
stale
size: M
Cluster:
Cron Enhancements and Fixes
## Summary
- Add `maxRuns` field to CronJob for limiting recurring job executions
- Track `totalRuns` in job state across all run statuses (ok, error, skipped)
- Auto-delete recurring jobs after N runs, or disable them if `deleteAfterRun: false`
- Expose `maxRuns` in agent-facing cron tool schema and flat-params recovery
Closes #15673
## Why
`deleteAfterRun` handles cleanup for one-shot `at` jobs, but recurring jobs have no
equivalent. Agents creating temporary polling jobs (e.g. monitor a subagent every
2 minutes) have no way to set a run limit — the job runs indefinitely unless manually
deleted.
## Behavior
- `maxRuns: N` → deletes after N runs (default)
- `maxRuns: N` + `deleteAfterRun: true` → deletes after N runs
- `maxRuns: N` + `deleteAfterRun: false` → disables after N runs (keeps the record)
- `maxRuns: 1` → run once and delete
- No `maxRuns` → existing behavior, runs forever
- `deleteAfterRun: true` on `at` jobs → unchanged
## Changes
- `src/cron/types.ts`: add `maxRuns` to `CronJob`, `totalRuns` to `CronJobState`
- `src/cron/service/timer.ts`: increment `totalRuns`, extend lifecycle logic
- `src/cron/service/jobs.ts`: validate `maxRuns` in `createJob` and `applyJobPatch`
- `src/gateway/protocol/schema/cron.ts`: add `maxRuns`/`totalRuns` to TypeBox schemas
- `src/agents/tools/cron-tool.ts`: document `maxRuns` in tool description, add to `JOB_KEYS`
- `src/cron/service.max-runs.test.ts` (new): 7 tests
## Testing
- `pnpm vitest run src/cron/` — 129 tests passing across 25 files, zero regressions
- `pnpm lint` — 0 warnings, 0 errors
- Tests cover: delete after N runs, disable with `deleteAfterRun: false`, mixed statuses,
state persistence across restarts, maxRuns=1 boundary, no-flag default, infinite runs
🤖 AI-assisted (Claude) — fully tested
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds `maxRuns` to cron jobs and tracks `state.totalRuns` so recurring jobs can auto-cleanup after N executions (delete by default, or disable when `deleteAfterRun: false`). It updates the cron lifecycle logic in `src/cron/service/timer.ts`, validates/coerces `maxRuns` on create/update in `src/cron/service/jobs.ts`, exposes the new fields through the gateway TypeBox schemas, and documents/supports `maxRuns` in the agent-facing cron tool schema (including flat-params recovery). New vitest coverage exercises delete/disable behavior, mixed statuses, persistence, and boundary cases.
<h3>Confidence Score: 4/5</h3>
- This PR is close to safe to merge, with one persisted-data edge case that can break `maxRuns` behavior.
- Core logic and tests around `maxRuns`/`totalRuns` look consistent, and create/update paths validate `maxRuns`. The main remaining risk is that persisted jobs loaded from disk do not normalize `maxRuns`, so invalid values in existing/corrupt stores can cause unexpected immediate deletion/disable or no cleanup.
- src/cron/service/store.ts
<sub>Last reviewed commit: 84482a9</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#5179: fix(cron): recover stale running markers
by thatdaveb · 2026-01-31
80.8%
#12303: fix(cron): correct nextRunAtMs calculation and prevent timer stall
by colddonkey · 2026-02-09
80.7%
#3693: fix(cron): delete deleteAfterRun jobs regardless of execution status
by HirokiKobayashi-R · 2026-01-29
80.5%
#11857: fix: recompute stale cron nextRunAtMs on gateway restart
by Yida-Dev · 2026-02-08
79.3%
#12982: fix(cron): prevent status/list from advancing overdue job nextRunAtMs
by hclsys · 2026-02-10
79.2%
#12747: fix: catch up missed cron-expression job runs on restart
by obin94-commits · 2026-02-09
79.2%
#12448: fix: prevent cron list/status from silently skipping due jobs
by Yida-Dev · 2026-02-09
78.3%
#8698: fix(cron): default enabled to true for new jobs
by emmick4 · 2026-02-04
78.2%
#8578: fix(cron): add failure limit and exponential backoff for isolated t...
by Baoxd123 · 2026-02-04
78.1%
#14667: fix: preserve missed cron runs when updating job schedule
by WalterSumbon · 2026-02-12
77.9%