#22102: fix(cron): default isolated jobs to fresh sessions with sessionReuse opt-in
docs
app: macos
app: web-ui
gateway
cli
size: M
Cluster:
Cron Job Enhancements
## Summary
Describe the problem and fix in 2–5 bullets:
- Problem: Since `v2026.2.17` / PR `#18031`, isolated cron jobs could reuse a stable session and accumulate prior context across runs.
- Why it matters: Stateless periodic jobs became more expensive (token growth) and could drift behavior due to unrelated past context.
- What changed:
- Added `sessionReuse?: boolean` to cron job model and protocol schema.
- Regenerated protocol Swift models for `sessionReuse` so `protocol:check` stays in sync.
- Defaulted isolated `cron:` runs to fresh sessions unless `sessionReuse === true`.
- Added CLI controls: `cron add --session-reuse`, `cron edit --session-reuse|--fresh-session`.
- Added `/cron` New Job UI control for `sessionReuse` (isolated + agentTurn only).
- Added isolated job chips in `/cron` list to show `fresh` / `reuse` mode.
- Added normalization/store-migration handling for `sessionReuse` (including string coercion and invalid-value cleanup).
- Added focused tests for `sessionReuse` normalization, `forceNew` session behavior, and UI payload/render behavior.
- Added regression tests for webhook-like session-key reuse and explicit `forceNew` routing decisions.
- Updated cron docs to clarify default-fresh isolated behavior and `sessionReuse` opt-in semantics.
- Applied `docs/style.css` formatting required by repo `pnpm check` (no behavior change).
- What did NOT change (scope boundary):
- Webhook/custom session-key reuse behavior from `#18031` remains intact.
- Main-session cron behavior is unchanged.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [x] Style
- [x] Refactor
- [x] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [x] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [x] Memory / storage
- [ ] Integrations
- [x] API / contracts
- [x] UI / DX
- [x] CI/CD / infra
## Linked Issue/PR
- Closes #20092
- Related #18031
## User-visible / Behavior Changes
- Isolated cron jobs with default `cron:<jobId>` session key now run with a fresh session by default.
- Users who want cross-run continuity can explicitly opt in with `sessionReuse: true`.
- New CLI options are available for this toggle in `cron add` and `cron edit`.
- `/cron` New Job screen now includes a `Session reuse` toggle (shown only for isolated agentTurn jobs).
- `/cron` job cards now show `fresh`/`reuse` chip for isolated jobs.
## 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 (local dev machine)
- Runtime/container: Node + pnpm local workspace
- Model/provider: N/A
- Integration/channel (if any): Cron isolated `agentTurn`
- Relevant config (redacted): default session store behavior
### Steps
1. Create an isolated cron job with `payload.kind="agentTurn"` and default session key behavior.
2. Run the job multiple times without setting `sessionReuse`.
3. Verify each run is treated as fresh (no unintended transcript carry-over).
4. Set `sessionReuse: true` and verify continuity can still be opted in.
### Expected
- Default isolated cron runs are fresh per run.
- Explicit `sessionReuse: true` enables reuse.
- Webhook/custom session-key reuse path remains unchanged.
### Actual
- Matches expected behavior.
## Evidence
Attach at least one:
- [x] Failing test/log before + passing after
- [x] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
Validation snippets:
```bash
pnpm build && pnpm check && pnpm test
# => FINAL_STATUS=0
# check: format/tsgo/lint passed
# test: 121 files passed, 1153 passed | 1 skipped
# note: log includes intermittent worker OOM stack traces, but command exits 0
pnpm exec vitest run --config vitest.unit.config.ts \
src/cron/normalize.test.ts \
src/cron/normalize.session-reuse.test.ts \
src/cron/service.jobs.test.ts \
src/cron/service.store-migration.test.ts \
src/cron/isolated-agent/run.skill-filter.test.ts \
src/cron/isolated-agent/session.force-new-cron.test.ts \
src/cli/cron-cli.test.ts
# => 75 passed
pnpm exec vitest run --config vitest.gateway.config.ts \
src/gateway/protocol/cron-validators.test.ts
# => 6 passed
pnpm --dir ui exec vitest run --config vitest.config.ts \
src/ui/controllers/cron.test.ts \
src/ui/views/cron.test.ts
# => 18 passed
pnpm --dir ui build
# => build succeeded
# Local OpenClaw instance smoke (isolated OPENCLAW_HOME + local gateway)
OPENCLAW_HOME=/tmp/openclaw-pr20092-home node dist/entry.js gateway run \
--bind loopback --port 18790 --force --allow-unconfigured --auth token --token pr20092-token
OPENCLAW_HOME=/tmp/openclaw-pr20092-home node dist/entry.js cron add --url ws://127.0.0.1:18790 --token pr20092-token --session isolated --message "smoke job" --every 10m --json
OPENCLAW_HOME=/tmp/openclaw-pr20092-home node dist/entry.js cron edit <jobId> --url ws://127.0.0.1:18790 --token pr20092-token --session-reuse
OPENCLAW_HOME=/tmp/openclaw-pr20092-home node dist/entry.js cron edit <jobId> --url ws://127.0.0.1:18790 --token pr20092-token --fresh-session
OPENCLAW_HOME=/tmp/openclaw-pr20092-home node dist/entry.js cron list --url ws://127.0.0.1:18790 --token pr20092-token --json
# => sessionReuse transitions: unset/null -> true -> false
```
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios:
- local OpenClaw instance smoke: isolated cron `add/edit/list/rm` with `sessionReuse` transition checks (`null -> true -> false`)
- `sessionReuse` normalize path (`true`/`false` string and boolean forms)
- invalid `sessionReuse` input cleanup
- `forceNew` path in cron session resolution behavior
- CLI flag plumbing and protocol validator compatibility
- `/cron` UI form toggle visibility and payload forwarding/omission behavior
- `/cron` UI job list mode chip rendering (`fresh`/`reuse`)
- Edge cases checked:
- invalid string values
- explicit `true` opt-in vs default behavior
- add/edit CLI toggle conflict handling
- What you did **not** verify:
- full live integration runs across external messaging channels
- long-duration production cron soak behavior
- full `ui` test suite green status end-to-end (targeted cron UI tests were run and passed)
## CI Status
- Initial CI failure on `checks (node, protocol, pnpm protocol:check)` was due to generated Swift protocol models not yet updated after `sessionReuse` schema change.
- Follow-up commit regenerated Swift protocol models:
- `apps/macos/Sources/OpenClawProtocol/GatewayModels.swift`
- `apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift`
- Remaining CI state should be evaluated on latest head commit.
## 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:
- Set affected jobs to `sessionReuse: true` to restore continuity behavior.
- Revert commits `d93e75e317e7f3c1849a2a9ba62a3394f7032a80`, `abd938b1569ea8bdecaed6600420c6e456c23bb7`, `9fe78f2328a1bfc9edc37bd93626f42bd3980d51`, `2cfb8f85df4bb08618209d93dd04b4ae3575e8d9`, `137d2331b7714511c443c0e728536deb035673ea`, `5ee4eb01981442aad00a2af6b9fd46ec97330e97`, `77119da4844e98f7c12c4d59e7fce45fed8f2fa8`.
- Files/config to restore:
- `docs/style.css`
- `src/cron/isolated-agent/run.ts`
- `src/cron/types.ts`
- `src/cron/normalize.ts`
- `src/cron/service/jobs.ts`
- `src/cron/service/store.ts`
- `src/gateway/protocol/schema/cron.ts`
- `apps/macos/Sources/OpenClawProtocol/GatewayModels.swift`
- `apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift`
- `src/cli/cron-cli/register.cron-add.ts`
- `src/cli/cron-cli/register.cron-edit.ts`
- `ui/src/ui/ui-types.ts`
- `ui/src/ui/app-defaults.ts`
- `ui/src/ui/types.ts`
- `ui/src/ui/controllers/cron.ts`
- `ui/src/ui/views/cron.ts`
- Known bad symptoms reviewers should watch for:
- jobs that expected implicit session continuity losing context between runs
## Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write `None`.
- Risk: Some existing cron jobs may have implicitly depended on session reuse.
- Mitigation: `sessionReuse: true` opt-in preserves reuse explicitly.
- Risk: Input coercion could accept malformed values if not covered.
- Mitigation: Added normalization tests for valid/invalid forms.
- Risk: Cross-surface contract drift (types/schema/CLI/runtime).
- Mitigation: Updated all relevant layers and validated with unit + gateway protocol tests.
## AI Assistance Disclosure
- AI-assisted: Yes
- Human review and verification performed: Yes
- Testing degree: full `build && check && test` was run with `FINAL_STATUS=0`; test logs include intermittent worker OOM traces while summaries remain all-green.
- External model consultation: GLM-5 was used for bug/regression validation and pre-PR quality gate review.
- Prompts/session logs: consultation prompts and outputs are summarized in review notes and can be provided on request.
Most Similar PRs
#23501: fix(cron): force new session ID for isolated cron jobs (#23470)
by stakeswky · 2026-02-22
73.3%
#23562: feat: add sessionFreshness config for isolated cron jobs (#23539)
by MunemHashmi · 2026-02-22
72.0%
#18743: Cron Tool Hardening: Normalize Gateway Params and Enforce Valid Sch...
by cccat6 · 2026-02-17
71.5%
#6315: fix(cron): persist isolated sessions (fixes #6217) - attempt 2
by ChaitanyaSai-Meka · 2026-02-01
71.2%
#23699: fix(cron): isolated sessions must generate fresh UUID on every run ...
by echoVic · 2026-02-22
70.6%
#17064: fix(cron): prevent control-plane starvation during startup catch-up...
by donggyu9208 · 2026-02-15
70.0%
#16511: feat(cron): support custom session IDs and auto-bind to current ses...
by kkhomej33-netizen · 2026-02-14
70.0%
#19998: macOS: harden cron editor updates and compatibility
by tobiasbischoff · 2026-02-18
70.0%
#18192: fix(cron): auto-clear stale runningAtMs markers after timeout (#18120)
by BinHPdev · 2026-02-16
69.9%
#21279: Fix/sessions list cron model override
by altaywtf · 2026-02-19
69.8%