Skip to content

fix(cron): restore persistent session targets#98947

Merged
steipete merged 1 commit into
mainfrom
codex/restore-cron-session-persistence
Jul 2, 2026
Merged

fix(cron): restore persistent session targets#98947
steipete merged 1 commit into
mainfrom
codex/restore-cron-session-persistence

Conversation

@steipete

@steipete steipete commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Related: #98121

Follow-up to PR #98755. Pinned-base context: PR #98812.

What Problem This Solves

Fixes an issue where users scheduling cron work in current or session:<id> would unexpectedly lose persistent session history because every agent-turn cron target was changed to a detached fresh run. The merged change also caused deterministic session-state and shared run-context failures on exact-head CI.

Why This Change Was Made

Cron jobs now follow the clarified product contract: a job normally runs in the session it was created from, while only an explicitly isolated job requests a detached fresh session. This restores the shipped canonical persistence path across target resolution, session identity, storage, prompt caching, run-context ownership, task drill-down, gateway wiring, tests, and docs, while retaining the independently valid stale childless-task cancellation from PR #98755.

The approved patch originated as head 69cb904aaceeeb8be8448be7157b16e66e411123, parent 27104c1afb13af39e675f637b5812b12a7088ba7, tree cdec0b484879ceba63e6542835587e9da60e9f55. The single required main sync produced the textually equivalent head f160075c36e8e1c925e1148236d50492486ecc11, parented directly on main 2913d3aee90c79bc420129606b3912662359723d, with tree 889530c73c8426dc61d9fd6bcb42e889718547e9. A wrapper-created ancestry-only head a5ddfe7eda69b77cc177f93aa923476f82a7230e was replaced with f160075c… using an exact force-with-lease. The live PR remains 17 files, +90/-187, with stable patch ID 94180b4fcbf752cfa56db33df28bf4620ef633a2 and full-index diff SHA-256 bf7396ac69911e288ba1e0fd3f20cfee1b19e44e3b35f855cf65bea0a0b751d9.

User Impact

Recurring cron workflows can again build on prior context in current and named session:<id> sessions. isolated jobs remain fresh and detached, and main-session cron behavior is unchanged.

Evidence

Contributor credit: Ethan Sarif-Kattan (@EthanSK) supplied the original report and discussion in issue #98121. Ayaan Zaidi (@obviyus) authored PR #98755, including the stale childless-task cancellation retained here.

AI-assisted: yes, prepared and independently reviewed with Codex under Peter Steinberger's explicit product-contract and landing approval.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime size: M maintainer Maintainer-authored PR labels Jul 2, 2026
@steipete steipete self-assigned this Jul 2, 2026
@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 2, 2026, 2:47 AM ET / 06:47 UTC.

Summary
The PR changes cron agent-turn session targeting so current and session:<id> jobs run in persistent sessions while isolated remains detached, with related docs and regression tests.

PR surface: Source -34, Tests -63, Docs 0. Total -97 across 17 files.

Reproducibility: yes. Source inspection shows PR head still reports isolated run-scoped session keys but gateway cleanup no longer uses them, and task child-session resolution mishandles session:<id> and isolated-with-sessionKey cases.

Review metrics: 1 noteworthy metric.

  • Cron target semantics: 2 restored, 1 retained. current and session:<id> return to persistent session execution while isolated remains fresh, which is the user-visible contract maintainers need to notice before merge.

Stored data model
Persistent data-model change detected: serialized state: src/cron/isolated-agent.session-identity.test.ts, serialized state: src/cron/isolated-agent/session.test.ts, serialized state: src/cron/isolated-agent/session.ts, serialized state: src/cron/session-target.test.ts, serialized state: src/cron/session-target.ts, unknown-data-model-change: src/cron/isolated-agent/session.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: canonical
Canonical: #98947
Summary: This PR is the canonical follow-up for restoring persistent cron session targets after the merged detach PR; adjacent cron/live-chat and gateway saturation issues remain related but distinct.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🌊 off-meta tidepool
Patch quality: 🧂 unranked krab
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Restore execution-session tracking for isolated cron browser cleanup.
  • Resolve task child-session keys from sessionTarget: "session:<id>" when job.sessionKey is absent, without misrouting isolated jobs that carry a creator session key.

Risk before merge

  • [P1] Restoring persistent current and session:<id> cron targets keeps the intentional tradeoff that a scheduled job can share a named session with a live chat when the user chooses that target.
  • [P1] As patched, isolated cron runs that open browser tabs can leave those tabs tracked/open after completion because cleanup no longer follows the actual run session key.
  • [P1] As patched, cron task rows can point to the wrong session or lose childSessionKey, breaking task drill-down to the transcript actually used.

Maintainer options:

  1. Fix session-key regressions before merge (recommended)
    Restore execution-session cleanup tracking and make task child-session resolution distinguish isolated run keys from persistent session:<id> targets.
  2. Land after explicit session-policy signoff
    Maintainers can accept the persistent-session tradeoff once the mechanical regressions are fixed and the PR evidence still proves isolated remains fresh.
  3. Pause for stricter cron policy
    If sharing live chat sessions from cron is no longer acceptable, pause this branch and design a separate target or migration instead of restoring persistent sessions unchanged.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Fix the cron session-key regressions in PR 98947: keep gateway browser cleanup tracking the actual isolated execution/result session key, resolve task child sessions from `sessionTarget: "session:<id>"` when no separate `job.sessionKey` exists, and ensure isolated jobs with a creator `sessionKey` still record the generated cron run session for task drill-down. Add focused regression tests in `src/gateway/server-cron.test.ts` and `src/cron/service/timer.regression.test.ts`; run `node scripts/run-vitest.mjs src/gateway/server-cron.test.ts src/cron/service/timer.test.ts src/cron/service/timer.regression.test.ts` and `git diff --check`.

Next step before merge

  • [P1] There are narrow, file-level repairs in gateway cleanup and cron task child-session resolution that an automated repair lane can attempt before maintainer signoff.

Security
Cleared: No concrete security or supply-chain regression was found; the diff changes cron/session logic, docs, and tests without dependency, workflow, permission, download, or secret-handling changes.

Review findings

  • [P2] Clean up the actual isolated run session — src/gateway/server-cron.ts:492
  • [P2] Resolve persistent targets from sessionTarget — src/cron/service/task-runs.ts:52-53
  • [P2] Route isolated task drill-down to the cron run — src/cron/service/task-runs.ts:47-50
Review details

Best possible solution:

Land the persistent-session restoration only after repairing isolated cleanup and task child-session resolution, while keeping isolated as the documented fresh/background escape hatch.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection shows PR head still reports isolated run-scoped session keys but gateway cleanup no longer uses them, and task child-session resolution mishandles session:<id> and isolated-with-sessionKey cases.

Is this the best way to solve the issue?

No, not yet. Restoring persistent cron sessions is the right policy direction if maintainers accept the tradeoff, but the branch needs the cleanup and task drill-down repairs before it is the best merge shape.

Full review comments:

  • [P2] Clean up the actual isolated run session — src/gateway/server-cron.ts:492
    Isolated cron runs still report a per-run session key, but this cleanup now always uses the pre-run cron:<jobId> key. Browser tab cleanup is exact-key based, so tabs opened under the run key can remain tracked/open after completion.
    Confidence: 0.92
  • [P2] Resolve persistent targets from sessionTarget — src/cron/service/task-runs.ts:52-53
    A persisted job can carry its actual target only as sessionTarget: "session:<id>". Returning undefined when job.sessionKey is absent makes task rows lose childSessionKey, so task drill-down cannot open the transcript the run used.
    Confidence: 0.89
  • [P2] Route isolated task drill-down to the cron run — src/cron/service/task-runs.ts:47-50
    When an isolated cron job also carries a creator sessionKey, this early return records task drill-down against the creator chat even though gateway execution uses the generated cron:<jobId> run session. Only persistent session:<id> targets should prefer that explicit binding.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 2913d3aee90c.

Label changes

Label changes:

  • add P1: The PR targets a real cron session-state/message-delivery regression and still has merge-blocking session cleanup and task drill-down defects.
  • add merge-risk: 🚨 message-delivery: The restored persistent-session behavior affects cron/live-chat interactions that can make replies appear delayed or contaminated when users target a live chat session.
  • add merge-risk: 🚨 session-state: The diff changes which session keys own cron transcripts, prompt-cache affinity, run contexts, cleanup, and task drill-down.
  • add merge-risk: 🚨 availability: The isolated cleanup regression can leave browser tabs or resources tracked after cron runs complete.

Label justifications:

  • P1: The PR targets a real cron session-state/message-delivery regression and still has merge-blocking session cleanup and task drill-down defects.
  • merge-risk: 🚨 session-state: The diff changes which session keys own cron transcripts, prompt-cache affinity, run contexts, cleanup, and task drill-down.
  • merge-risk: 🚨 message-delivery: The restored persistent-session behavior affects cron/live-chat interactions that can make replies appear delayed or contaminated when users target a live chat session.
  • merge-risk: 🚨 availability: The isolated cleanup regression can leave browser tabs or resources tracked after cron runs complete.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🌊 off-meta tidepool and patch quality is 🧂 unranked krab.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The PR is protected with the maintainer label, so the external-contributor real-behavior proof gate is not applied in this review.
Evidence reviewed

PR surface:

Source -34, Tests -63, Docs 0. Total -97 across 17 files.

View PR surface stats
Area Files Added Removed Net
Source 7 37 71 -34
Tests 8 42 105 -63
Docs 2 11 11 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 17 90 187 -97

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs src/gateway/server-cron.test.ts src/cron/service/timer.test.ts src/cron/service/timer.regression.test.ts.
  • [P1] git diff --check.

What I checked:

Likely related people:

  • Ayaan Zaidi: Blame and the merged predecessor PR history connect this person to the same gateway cleanup, task-run, and session-target paths now being partially reversed. (role: introduced current-main detached cron behavior; confidence: high; commits: bc7f9a36ec55, 3558391a75fd; files: src/gateway/server-cron.ts, src/cron/service/task-runs.ts, src/cron/session-target.ts)
  • Peter Steinberger: The current PR body states explicit product-contract approval, and recent history shows adjacent cron/session helper work. (role: recent area contributor and product-contract sponsor; confidence: medium; commits: f160075c36e8, 39bcf695dce4; files: src/gateway/server-cron.ts, src/cron/session-target.ts, docs/automation/cron-jobs.md)
  • Vignesh Natarajan: Earlier git history shows multiple cron session-key and wake-target routing changes in the gateway cron area. (role: adjacent cron routing contributor; confidence: medium; commits: c20ef582cb4b, a25850359059, f988abf202e3; files: src/gateway/server-cron.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 69cb904aac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 491 to +492
await cleanupBrowserSessionsForLifecycleEnd({
sessionKeys: [cleanupSessionKey],
sessionKeys: [sessionKey],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use actual isolated run session for browser cleanup

When an isolated cron job opens browser tabs, the browser tool tracks them under the run key passed into the agent (agent:<id>:cron:<job>:run:<sessionId>), but this cleanup now always sends the pre-run target key (cron:<jobId>). Since browser cleanup matches exact session keys, isolated cron runs no longer close their tracked tabs at completion; keep using the execution/result session key for isolated runs.

Useful? React with 👍 / 👎.

Comment on lines +52 to +53
if (params.job.sessionTarget !== "isolated") {
return undefined;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve session targets for task drill-down

For jobs created with sessionTarget: "session:<id>" but without a separate sessionKey field (for example CLI --session session:...), this branch returns undefined even though the cron run executes in that persistent session. The task ledger then loses childSessionKey, so task drill-down cannot open the transcript the run actually used; parse the key from sessionTarget before dropping non-isolated jobs.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 2, 2026
Cron jobs run in the session they were created from unless the job explicitly requests an isolated fresh session.
@steipete
steipete requested a review from a team as a code owner July 2, 2026 06:34
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord channel: imessage Channel integration: imessage channel: matrix Channel integration: matrix channel: mattermost Channel integration: mattermost channel: nostr Channel integration: nostr channel: telegram Channel integration: telegram app: android App: android app: ios App: ios app: web-ui App: web-ui extensions: memory-core Extension: memory-core scripts Repository scripts agents Agent runtime and tooling extensions: nvidia extensions: vercel-ai-gateway extensions: fal extensions: qa-lab extensions: memory-wiki extensions: anthropic-vertex extensions: ollama labels Jul 2, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f160075c36

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +46 to +50
const explicitSessionKey = params.job.sessionKey?.trim();
if (explicitSessionKey) {
// Explicit session bindings must win over generated cron session keys so
// task drill-down opens the same transcript the cron run actually used.
return explicitSessionKey;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Route isolated task drill-down to the cron run

When an isolated cron job also carries a creator sessionKey for delivery context, this early return records the task ledger against that creator chat instead of the isolated cron transcript. The gateway still executes sessionTarget: "isolated" jobs with the generated cron:${job.id} key, so task drill-down for those jobs opens the wrong session and misses the run output; only persistent session:<id> targets should prefer their explicit session binding here.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 High-priority user-facing bug, regression, or broken workflow. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 2, 2026
@steipete
steipete merged commit be5906e into main Jul 2, 2026
140 of 153 checks passed
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. label Jul 2, 2026
@steipete
steipete deleted the codex/restore-cron-session-persistence branch July 2, 2026 06:48
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. label Jul 2, 2026
@steipete

steipete commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. label Jul 2, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 3, 2026
Cron jobs run in the session they were created from unless the job explicitly requests an isolated fresh session.

Co-authored-by: Peter Steinberger <[email protected]>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
Cron jobs run in the session they were created from unless the job explicitly requests an isolated fresh session.

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant