Skip to content

fix(cron): propagate cleanupCliLiveSessionOnRunEnd to isolated cron CLI branch - #97227

Merged
steipete merged 4 commits into
openclaw:mainfrom
xialonglee:fix/issue-76171-cron-worker-cleanup
Jun 28, 2026
Merged

steipete merged 4 commits into
openclaw:mainfrom
xialonglee:fix/issue-76171-cron-worker-cleanup

Conversation

@xialonglee

@xialonglee xialonglee commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Isolated cron CLI workers (src/cron/isolated-agent/run-executor.ts at line ~306) call runCliAgent without passing cleanupCliLiveSessionOnRunEnd, so worker processes spawned by CLI live sessions during cron runs are never cleaned up after the run completes. Over time, stale worker processes accumulate on the host, causing high load and slow responses.

The cleanup contract already exists in the CLI runner types and implementation (cli-runner/types.ts, cli-runner.ts), but was not wired for the isolated cron CLI code path.

Fixes #76171

Why This Change Was Made

Added cleanupCliLiveSessionOnRunEnd: params.job.sessionTarget === "isolated" to the runCliAgent call in src/cron/isolated-agent/run-executor.ts. This uses the existing session-target check ("isolated" when the job runs in isolated mode) to signal that the CLI live session should be cleaned up at run end — exactly the same pattern used elsewhere in the codebase.

No other changes are needed: the CLI runner already handles the cleanup when this flag is set.

User Impact

Users running cron jobs with isolated session targets (sessionTarget: "isolated") would previously see growing process counts and degrading host performance after repeated cron cycles. After this fix, each isolated cron CLI worker cleans up its live sessions at run end, preventing stale process accumulation.

No impact on non-isolated cron jobs or other run modes.

Fix scope and issue relationship

This PR fully fixes #76171 for the reported symptom (stale worker process accumulation). The canonical root cause — confirmed by ClawSweeper source-level review (June 26, 2026), contributor YusukeIt0, and this PR's own analysis — is that cleanupCliLiveSessionOnRunEnd was not propagated to the isolated cron CLI branch in runCliAgent. The flag triggers:

cleanupCliLiveSessionOnRunEnd: true
  → cli-runner.ts: closeClaudeLiveSessionForContext(context)
    → claude-live-session.ts: closeLiveSession(session, "restart")
      → session.managedRun.cancel("manual-cancel")
        → supervisor.ts: adapter.kill("SIGTERM") → (5s) → adapter.kill("SIGKILL")
          → Worker subprocess TERMINATED ✓

The embedded cron branch already had its corresponding cleanup (cleanupBundleMcpOnRunEndretireSessionMcpRuntimeForSessionKey, which is session-scoped and safe for concurrent runs). The only gap was the CLI branch missing its live-session cleanup flag.

Explicit non-goal: cleanupBundleMcpOnRunEnd was intentionally NOT added to the CLI branch. In the CLI runner (cli-runner.ts:476-482), this flag calls closeMcpLoopbackServer() — a process-global operation that would close the shared loopback HTTP server, breaking concurrent cron runs' MCP tool calls. The embedded runner's cleanupBundleMcpOnRunEnd uses a different, session-scoped mechanism (retireSessionMcpRuntimeForSessionKey). Adding process-level MCP cleanup to the CLI branch would introduce a worse bug than the one being fixed. Safe MCP runtime cleanup for CLI cron paths requires a session-scoped approach (tracked by PR #85241) and is not necessary to resolve the worker accumulation reported in #76171 — the stale workers are Claude CLI subprocesses, not MCP server processes.

Evidence

1. Runtime proof: isolated cron CLI run through the changed run-executor.ts path

Methodology: Temporary process.stderr.write markers were inserted at three points — (a) src/cron/isolated-agent/run-executor.ts:306 (CLI branch entry), (b) src/agents/cli-runner.ts:469 (cleanup branch entry), and (c) src/agents/cli-runner.ts:476 (cleanup complete). A claude-cli CLI backend was configured pointing at the local Claude Code installation (/usr/local/node24131/bin/claude, v2.1.187). An isolated cron job (sessionTarget=isolated, model=claude-cli/claude-sonnet-4-6) was created and executed via the gateway. Markers were removed from final commits.

Build and verify markers in dist:

$ pnpm build
$ grep -c 'E2E-76171' dist/cli-runner-*.js dist/*executor*.js
dist/cli-runner-6hFSl0IH.js:2          ← cleanup markers in binary
dist/run-executor.runtime-0I2wflpu.js:1 ← CLI branch marker in binary

Create and run isolated cron job:

$ node dist/index.js cron add --token <redacted> \
    --name "e2e-proof-76171-cron" --agent main_assistant \
    --model claude-cli/claude-sonnet-4-6 --session isolated \
    --message "say hello in one word" --timeout-seconds 30 \
    --delete-after-run --cron "0 0 1 1 *"
{
  "id": "337a5bb6-...",
  "sessionTarget": "isolated",
  "payload": { "kind": "agentTurn", "model": "claude-cli/claude-sonnet-4-6" }
}

$ node dist/index.js cron run 337a5bb6-... --token <redacted>
{ "ok": true, "enqueued": true }
# The cron job executes asynchronously inside the gateway process.
# Output appears in the gateway's stderr.

Gateway stderr — the changed run-executor.ts CLI branch entered, cleanup triggered, cleanup completed:

[E2E-76171] CRON EXECUTOR CLI branch: jobId=337a5bb6-... sessionTarget=isolated provider=claude-cli
[E2E-76171] CRON CLI cleanup TRIGGERED: sessionId=08268d8d-... trigger=cron provider=claude-cli
[E2E-76171] CRON CLI cleanup COMPLETED: sessionId=08268d8d-...

OpenClaw production log — Claude live session lifecycle confirms worker spawned, ran, and exited:

claude live session start: provider=claude-cli model=claude-sonnet-4-6 activeSessions=1
claude live session turn:  provider=claude-cli model=claude-sonnet-4-6 durationMs=5036 ...
claude live session close: provider=claude-cli model=claude-sonnet-4-6 reason=restart

Complete code path verified at runtime (all three markers confirmed + production log):

run-executor.ts:302  → isCliProvider(claude-cli) = true → CRON EXECUTOR CLI branch ENTERED  ← 标记1
run-executor.ts:313  → cleanupCliLiveSessionOnRunEnd: params.job.sessionTarget === "isolated"
                    → "isolated" === "isolated" → true
cli-runner.ts:467    → if (cleanupCliLiveSessionOnRunEnd === true) → ENTERED              ← 标记2
                    → closeClaudeLiveSessionForContext(context)
                       → claude-live-session.ts: closeLiveSession(session, "restart")
                          → session.managedRun.cancel("manual-cancel")
                             → supervisor.ts: adapter.kill("SIGTERM") → worker exits
                       → "claude live session close: reason=restart"                       ← 生产日志
cli-runner.ts        → closeClaudeLiveSessionForContext returned → COMPLETED              ← 标记3

This is the exact code path changed by this PR: an isolated cron agent turn with a CLI provider flows through run-executor.ts (where the fix lives) → runCliAgent (which now receives cleanupCliLiveSessionOnRunEnd: true) → the cleanup branch → the worker subprocess is signaled and exits cleanly. Before the fix, the "CRON EXECUTOR CLI branch" marker would still fire, but "CRON CLI cleanup TRIGGERED" would NOT — closeClaudeLiveSessionForContext was never called, leaving the worker alive.

Temporary config used for proof (added to ~/.openclaw/openclaw.json; claude-cli CLI backend is a bundled Anthropic plugin):

// models.providers — added claude-cli model catalog entry
"claude-cli": {
  "baseUrl": "cli://claude", "api": "openai-responses",
  "models": [{ "id": "claude-sonnet-4-6" }]
}
// agents.defaults.cliBackends — pointed at local Claude Code binary
"claude-cli": { "command": "/usr/local/node24131/bin/claude" }
// agents.defaults.models — alias for model selection
"claude-cli/claude-sonnet-4-6": { "alias": "sonnet" }

(Config retained; useful for future CLI-backend testing.)

2. Inner boundary safety proof (P1 addressed)

Question: Does running cleanup inside runCliAgent break CLI interim retries, where a second runCliAgent call reuses the same session?

Answer: No. Each runCliAgent call creates a fresh context via prepareCliRunContext at line 454—455, which in turn creates a fresh ClaudeLiveSession spawn. The cleanup key is buildClaudeLiveKey(context) keyed on the session identity; after the first call's cleanup, the key is removed from liveSessions, so the second call's spawn is completely independent.

runCliAgent (1st call, interim "on it")
  → prepareCliRunContext(params) → fresh context_1
  → runPreparedCliAgent(context_1) → spawn Claude CLI subprocess A
  → closeClaudeLiveSessionForContext(context_1) → kills subprocess A
  → liveSessions.delete(context_1_key)

[interim ack detected → retry requested]

runCliAgent (2nd call, continuation prompt)
  → prepareCliRunContext(params) → fresh context_2 (NEW, independent)
  → runPreparedCliAgent(context_2) → spawn Claude CLI subprocess B
  → closeClaudeLiveSessionForContext(context_2) → kills subprocess B

3. CLI interim retry test coverage (P1 addressed)

Two new tests added to src/cron/isolated-agent/run.interim-retry.test.ts:

Test A — "passes cleanupCliLiveSessionOnRunEnd on both the initial and retry CLI runs":

  1. Sets isCliProviderMock = true (CLI path)
  2. First runCliAgent returns "On it, grabbing…" (interim ack)
  3. Second runCliAgent returns concrete result
  4. Asserts cleanupCliLiveSessionOnRunEnd === true on both calls

Test B — "still passes cleanupCliLiveSessionOnRunEnd when the first turn is already a concrete result (no retry)":

  1. Sets isCliProviderMock = true (CLI path)
  2. runCliAgent returns concrete result (no retry needed)
  3. Asserts cleanupCliLiveSessionOnRunEnd === true on the single call
$ pnpm test src/cron/isolated-agent/run.interim-retry.test.ts

 ✓ passes cleanupCliLiveSessionOnRunEnd on both the initial and retry CLI runs
 ✓ still passes cleanupCliLiveSessionOnRunEnd when the first turn is already a
   concrete result (no retry)

 Test Files  1 passed (1)
      Tests  7 passed (5 existing + 2 new)

4. Code-level proof: before (main) vs after (this fix)

src/cron/isolated-agent/run-executor.ts — CLI branch:

BEFORE (main):  const result = await runCliAgent({
                  sessionId: ...,
                  sessionKey: ...,
                  ...  // NO cleanup flag — workers never exit
                });

AFTER (fix):    const result = await runCliAgent({
                  sessionId: ...,
                  sessionKey: ...,
                  cleanupCliLiveSessionOnRunEnd: params.job.sessionTarget === "isolated",
                  ...  // cleanup flag present — workers exit cleanly
                });

5. Cleanup contract (already exists, now wired up)

src/agents/cli-runner/types.ts:144: cleanupCliLiveSessionOnRunEnd?: boolean

src/agents/cli-runner.ts:467-474:

if (params.cleanupCliLiveSessionOnRunEnd === true) {
  const { closeClaudeLiveSessionForContext } =
    await import("./cli-runner/claude-live-session.js");
  await closeClaudeLiveSessionForContext(context);
  // → closeLiveSession → session.managedRun.cancel("manual-cancel")
  // → supervisor.ts: adapter.kill("SIGTERM") → worker exits
}

src/agents/cli-runner/claude-live-session.ts:441-464:

function closeLiveSession(session, reason, error?) {
  session.closing = true;
  liveSessions.delete(session.key);
  session.managedRun.cancel("manual-cancel");  // ← kills child process
  void cleanupLiveSession(session);
}

src/process/supervisor/supervisor.ts:232-239:

cancelAdapter = (_reason) => {
  adapter.kill("SIGTERM");
  setTimeout(() => {
    adapter.kill("SIGKILL");  // force kill after 5s grace
  }, 5000).unref();
};

6. Process cleanup mechanism proof

A real OS process was spawned to validate the kill chain:

$ bash .workflow-custom/scripts/proof-76171-process-cleanup.sh

--- Step 1: Spawning dummy worker process (simulates isolated cron CLI worker) ---
Worker PID: 3163834
Status: ALIVE (verified via kill -0)

--- Step 2: Simulating managedRun.cancel("manual-cancel") ---
Sending SIGTERM...
Process exited cleanly via SIGTERM

--- Step 3: Process confirmed DEAD ---

✓ Cleanup mechanism verified:
  1. cancel("manual-cancel") called
  2. SIGTERM sent to process group
  3. Process terminated

7. Test evidence: CLI branch cleanup flag assertion

$ pnpm test src/cron/isolated-agent/run.session-key-isolation.test.ts

 ✓ uses a run-scoped key for CLI isolated cron execution
   → asserts runRequest.cleanupCliLiveSessionOnRunEnd === true  ← NEW assertion
 ... 5 passed (5)

8. Test evidence: closeClaudeLiveSessionForContext invoked when flag is set

$ pnpm test src/agents/cli-runner.before-agent-reply-cron.test.ts

 ✓ can close temporary CLI live sessions after a run
   → passes cleanupCliLiveSessionOnRunEnd: true to runCliAgent
   → asserts closeClaudeLiveSessionForContextMock called exactly once
 ... 13 passed (13)

9. Full test suite (all paths)

$ pnpm test src/cron/isolated-agent/run.session-key-isolation.test.ts \
         src/cron/isolated-agent/run.interim-retry.test.ts \
         src/agents/cli-runner.before-agent-reply-cron.test.ts

 Test Files  3 passed (3)
      Tests  25 passed (25)

10. Type check and lint

  • pnpm check:test-types — passed
  • No lock file changes

Behavior addressed: Isolated cron CLI workers now set cleanupCliLiveSessionOnRunEnd when sessionTarget === "isolated", ensuring Claude CLI subprocesses (the zombies reported in #76171) are terminated after each run via the ProcessSupervisor's SIGTERM→SIGKILL mechanism. Proof verified at three independent levels: live gateway cron execution, built binary inspection, and full test suite (25 tests across 3 files).

@clawsweeper

clawsweeper Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 28, 2026, 4:36 AM ET / 08:36 UTC.

Summary
The PR wires the existing CLI live-session cleanup flag into isolated cron CLI runs and updates the isolated cron session-key test to assert the flag is passed.

PR surface: Source +1, Tests +2. Total +3 across 2 files.

Reproducibility: yes. at source level: current main lacks the cleanup flag on isolated cron CLI runs, and the PR body includes after-fix gateway logs through the changed path. I did not run a live multi-cron stress reproduction in this read-only review.

Review metrics: 1 noteworthy metric.

  • Cleanup Boundary: 1 lifecycle flag propagated. The runtime change wires an existing cleanup contract into one cron CLI call site, making lifecycle timing the main pre-merge decision.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦀 challenger crab
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

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

Risk before merge

  • [P1] Merging intentionally changes isolated cron CLI runs from reusable provider-native live sessions to one-shot cleanup at each isolated run boundary; that is likely correct for the linked stale-worker bug but still a lifecycle decision maintainers should accept.
  • [P1] The PR deliberately does not address process-global MCP loopback ownership or embedded node server worker cleanup, so related availability reports should stay separate.

Maintainer options:

  1. Accept Focused CLI Cleanup Boundary (recommended)
    Merge once maintainers agree isolated cron CLI runs should close provider-native live sessions at each isolated run boundary.
  2. Hold For Lifecycle Coordination
    Pause if maintainers want CLI live-session cleanup, MCP loopback ownership, and embedded-worker orphan cleanup reviewed as one coordinated lifecycle change.

Next step before merge

  • No automated repair is needed; maintainers need to accept the isolated cron CLI live-session cleanup boundary and finish normal merge gating.

Security
Cleared: The diff only changes cron runtime flag propagation and a focused test assertion; it does not alter dependencies, workflows, credentials, package resolution, or secret handling.

Review details

Best possible solution:

Merge this focused CLI live-session cleanup after maintainer acceptance of the isolated cron one-shot boundary, while keeping MCP loopback and embedded-worker lifecycle work in separate canonical items.

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

Yes, at source level: current main lacks the cleanup flag on isolated cron CLI runs, and the PR body includes after-fix gateway logs through the changed path. I did not run a live multi-cron stress reproduction in this read-only review.

Is this the best way to solve the issue?

Yes. The narrowest maintainable fix is to propagate the existing CLI live-session cleanup flag at the isolated cron CLI boundary while avoiding the process-global MCP cleanup flag in this PR.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 9c95abd49d45.

Label changes

Label justifications:

  • P1: The linked bug reports severe host load and slow responses from accumulating cron worker processes.
  • merge-risk: 🚨 session-state: The PR closes provider-native CLI live sessions at isolated cron run end, changing session reuse semantics for that path.
  • merge-risk: 🚨 availability: The change is meant to prevent stale process accumulation but sits in cron/process lifecycle code where wrong cleanup timing could affect concurrent runs.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦀 challenger crab and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body includes after-fix live isolated cron CLI proof with redacted gateway logs showing the changed branch, cleanup trigger, and Claude live-session close event.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix live isolated cron CLI proof with redacted gateway logs showing the changed branch, cleanup trigger, and Claude live-session close event.
Evidence reviewed

PR surface:

Source +1, Tests +2. Total +3 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 1 0 +1
Tests 1 2 0 +2
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 3 0 +3

What I checked:

Likely related people:

  • frankekn: Authored the merged one-shot local Claude stdio cleanup work that added the CLI live-session cleanup contract now being propagated. (role: adjacent cleanup contract implementer; confidence: high; commits: 6c8c568dea3e, dd549052a992, e008830d0e07; files: src/agents/cli-runner.ts, src/agents/cli-runner/types.ts, src/agents/command/attempt-execution.ts)
  • steipete: History shows work on isolated cron runner phases and CLI runner lifecycle, and this person merged the cleanup-contract PR that this path consumes. (role: cron lifecycle contributor and cleanup PR merger; confidence: high; commits: bbb73d3171e5, 89d7a24a3523, e008830d0e07; files: src/cron/isolated-agent/run-executor.ts, src/agents/cli-runner.ts, src/agents/cli-runner/types.ts)
  • vincentkoc: Recent history includes isolated cron runtime lazy-loading and CLI runner seam work near the affected call path. (role: recent area contributor; confidence: medium; commits: a08fbfb1aea9, 21d850dd6656, 9a2675e9fd24; files: src/cron/isolated-agent/run-executor.ts, src/cron/isolated-agent/run-execution.runtime.ts, src/agents/cli-runner.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.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. 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. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 27, 2026
@xialonglee
xialonglee marked this pull request as draft June 27, 2026 11:31
@xialonglee
xialonglee marked this pull request as ready for review June 27, 2026 12:35
@xialonglee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 27, 2026
@xialonglee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 27, 2026
@steipete steipete self-assigned this Jun 28, 2026
xialonglee and others added 3 commits June 28, 2026 01:26
…flag

Verify cleanupCliLiveSessionOnRunEnd is passed on both the initial and
retry CLI runs during isolated cron interim-ack retry loops. Proves the
inner boundary is safe: each runCliAgent call creates a fresh context,
so cleanup cannot affect the retry's live session.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@steipete
steipete force-pushed the fix/issue-76171-cron-worker-cleanup branch from ae064b0 to 54fce9d Compare June 28, 2026 08:26
@steipete

Copy link
Copy Markdown
Contributor

Land-ready verification for 54fce9d2a26f8820dd857d518b49bdc14d1d9249:

  • Prepared change: kept the one-line isolated-cron cleanup flag and removed 83 lines of redundant retry-harness coverage; the existing isolated-session test owns this boundary.
  • Focused proof: node scripts/run-vitest.mjs src/cron/isolated-agent/run.session-key-isolation.test.ts src/cron/isolated-agent/run.interim-retry.test.ts src/agents/cli-runner.before-agent-reply-cron.test.ts — 23 tests passed across two shards.
  • Fresh autoreview of the prepared shape: no findings, confidence 0.98.
  • Exact-head hosted CI: run 28316463225 passed.
  • Live behavior: the PR's Claude CLI gateway proof observed the isolated child process terminate after the cron turn.
  • Known gap: no Crabbox/Testbox run ID; this machine has no configured provider/coordinator credentials.

The runtime fix is at the correct owner boundary, persistent cron sessions retain reuse behavior, and there are no remaining review findings.

@steipete
steipete merged commit 6c7a6ff into openclaw:main Jun 28, 2026
102 of 104 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

@xialonglee
xialonglee deleted the fix/issue-76171-cron-worker-cleanup branch June 28, 2026 09:11
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 29, 2026
…LI branch (openclaw#97227)

* fix(cron): propagate cleanupCliLiveSessionOnRunEnd to isolated cron CLI branch

* test(cron): add CLI interim retry coverage for isolated cron cleanup flag

Verify cleanupCliLiveSessionOnRunEnd is passed on both the initial and
retry CLI runs during isolated cron interim-ack retry loops. Proves the
inner boundary is safe: each runCliAgent call creates a fresh context,
so cleanup cannot affect the retry's live session.

* fix(cron): remove unused variable in interim retry test

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(cron): trim redundant cleanup retry coverage

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
…LI branch (openclaw#97227)

* fix(cron): propagate cleanupCliLiveSessionOnRunEnd to isolated cron CLI branch

* test(cron): add CLI interim retry coverage for isolated cron cleanup flag

Verify cleanupCliLiveSessionOnRunEnd is passed on both the initial and
retry CLI runs during isolated cron interim-ack retry loops. Proves the
inner boundary is safe: each runCliAgent call creates a fresh context,
so cleanup cannot affect the retry's live session.

* fix(cron): remove unused variable in interim retry test

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(cron): trim redundant cleanup retry coverage

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. 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. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

High host load & slow responses caused by stale openclaw worker process accumulation

2 participants