Skip to content

fix(cron): trust agent output when channel is unresolved without explicit delivery#92817

Merged
vincentkoc merged 1 commit into
openclaw:mainfrom
fsdwen:fix/90664-cron-nochannel-policy
Jun 15, 2026
Merged

fix(cron): trust agent output when channel is unresolved without explicit delivery#92817
vincentkoc merged 1 commit into
openclaw:mainfrom
fsdwen:fix/90664-cron-nochannel-policy

Conversation

@fsdwen

@fsdwen fsdwen commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Summary

--no-deliver cron jobs that encounter recoverable tool warnings were marked status: error even when the agent successfully produced a final answer.

The basic fix (deliveryRequested === false) was already implemented on main, but it missed the edge case where deliveryRequested is undefined — which happens in the run-executor.ts code path where the field is typed ?: boolean.

Fix

One character in src/cron/isolated-agent/channel-output-policy.ts:

- return { preferFinalAssistantVisibleText: opts?.deliveryRequested === false };
+ return { preferFinalAssistantVisibleText: opts?.deliveryRequested !== true };

When no channel exists, trust the agent's final visible text unless delivery was explicitly requested (=== true). false, undefined, and missing opts all mean "not requested" → allow the rescue path.

This closes the gap left by the earlier fix: === false works for run.ts (where deliveryRequested is always boolean), but fails for run-executor.ts (where it's ?: boolean and can be undefined).

Files changed

  • src/cron/isolated-agent/channel-output-policy.ts: +1/-1
  • src/cron/isolated-agent/channel-output-policy.test.ts: +10 (undefined + missing opts cases)

Related

Fixes #90664

Context: @TurboTheTurtle confirmed the basic === false fix was already on main but missed the undefined edge case in run-executor.ts (June 13 comment).

Real behavior proof

  • Behavior addressed: resolveCronChannelOutputPolicy returns false when deliveryRequested is undefined or not passed — === false only matches explicit false, but ?: boolean means undefined is a real runtime value in run-executor.ts
  • Real environment tested: Linux Node 24, production code imported via node --import tsx
  • Exact steps or command run after this patch:
    $ node --import tsx -e "
    import { resolveCronChannelOutputPolicy } from './src/cron/isolated-agent/channel-output-policy.js';
    console.log('undefined:', (await resolveCronChannelOutputPolicy(undefined, { deliveryRequested: undefined })).preferFinalAssistantVisibleText);
    console.log('no opts:', (await resolveCronChannelOutputPolicy(undefined)).preferFinalAssistantVisibleText);
    "
  • Evidence after fix:
    $ node --import tsx -e "
    import { resolveCronChannelOutputPolicy } from './src/cron/isolated-agent/channel-output-policy.js';
    const r = (v) => resolveCronChannelOutputPolicy(undefined, v);
    console.log('false:    ', (await r({ deliveryRequested: false })).preferFinalAssistantVisibleText);
    console.log('true:     ', (await r({ deliveryRequested: true })).preferFinalAssistantVisibleText);
    console.log('undefined:', (await r({ deliveryRequested: undefined })).preferFinalAssistantVisibleText);
    console.log('no opts:  ', (await resolveCronChannelOutputPolicy(undefined)).preferFinalAssistantVisibleText);
    "
    false:     true
    true:      false
    undefined: true    ← was false before the fix
    no opts:   true    ← was false before the fix
  • Observed result after fix: false, undefined, and missing opts all correctly return true — the rescue path in resolveCronPayloadOutcome is no longer blocked for --no-deliver cron when deliveryRequested comes through run-executor.ts as undefined. Explicit true (delivery requested) still correctlys returns false.
  • What was not tested: Full --no-deliver cron run with a real agent producing recoverable tool warnings via the run-executor.ts path; the function-level edge case is verified through direct import

🤖 Generated with Claude Code

…icit delivery

resolveCronChannelOutputPolicy checked deliveryRequested === false
when there is no channel. Since deliveryRequested is optional
(?: boolean), undefined and missing opts both returned false,
blocking the hasRecoveredToolWarning rescue path for --no-deliver
cron runs whose agent recovered successfully.

Change === false to !== true: when no channel exists, prefer the
agent's final visible text unless delivery was explicitly
requested.

Fixes openclaw#90664

Co-Authored-By: Claude Fable 5 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added size: XS proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 14, 2026
@clawsweeper

clawsweeper Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 13, 2026, 9:19 PM ET / 01:19 UTC.

Summary
The PR changes unresolved-channel cron output policy so missing or undefined deliveryRequested is treated like no explicit delivery, and adds regression coverage for those cases.

PR surface: Source 0, Tests +10. Total +10 across 2 files.

Reproducibility: yes. for the helper edge: current main returns false when the no-channel policy is called with undefined or missing options. No for the full user workflow: the normal product caller I found already passes a boolean deliveryRequested.

Review metrics: none identified.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🐚 platinum hermit
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

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

Rank-up moves:

  • [P2] Confirm whether omitted deliveryRequested is an accepted internal call shape, or frame this PR as defensive helper semantics rather than the remaining user-facing cron fix.

Risk before merge

  • [P1] Source inspection found the normal product caller already passes a boolean deliveryRequested, so the undefined/missing-options case is a defensive helper edge rather than a fully proven current user workflow.
  • [P2] The supplied proof directly verifies the changed helper behavior, but it does not include a full --no-deliver cron run through run-executor with recoverable tool warnings.

Maintainer options:

  1. Decide the mitigation before merge
    Accept the PR only if maintainers want absent deliveryRequested to mean no explicit delivery at the helper boundary; otherwise close the linked issue against the existing boolean-path fix and leave this edge out.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] The remaining question is maintainer judgment about whether the helper should treat omitted options as no explicit delivery; there is no narrow repair needed on the PR branch.

Security
Cleared: The diff only changes cron policy logic and colocated tests; it does not touch workflows, dependencies, credentials, package metadata, install scripts, or other supply-chain surfaces.

Review details

Best possible solution:

Accept the PR only if maintainers want absent deliveryRequested to mean no explicit delivery at the helper boundary; otherwise close the linked issue against the existing boolean-path fix and leave this edge out.

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

Yes for the helper edge: current main returns false when the no-channel policy is called with undefined or missing options. No for the full user workflow: the normal product caller I found already passes a boolean deliveryRequested.

Is this the best way to solve the issue?

Unclear as a fix for the linked user issue because the main cron path already appears to cover bare no-deliver runs with an explicit false value. As a defensive helper semantic, the PR is narrow and preserves explicit delivery-requested behavior.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add P3: The patch is a low-risk defensive cron helper cleanup because the normal runtime caller already passes a boolean in current main.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal output from importing production code with Node 24 and showing the changed undefined/no-options helper result; this proves the changed function behavior, though not the full cron workflow.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes after-fix terminal output from importing production code with Node 24 and showing the changed undefined/no-options helper result; this proves the changed function behavior, though not the full cron workflow.

Label justifications:

  • P3: The patch is a low-risk defensive cron helper cleanup because the normal runtime caller already passes a boolean in current main.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes after-fix terminal output from importing production code with Node 24 and showing the changed undefined/no-options helper result; this proves the changed function behavior, though not the full cron workflow.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal output from importing production code with Node 24 and showing the changed undefined/no-options helper result; this proves the changed function behavior, though not the full cron workflow.
Evidence reviewed

PR surface:

Source 0, Tests +10. Total +10 across 2 files.

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

What I checked:

  • Repository policy read: Read the full root AGENTS.md and applied the OpenClaw PR review rules for current-main behavior, proof, security review, likely-owner history, and clean read-only inspection. (AGENTS.md:1, b3dc27403498)
  • Repository policy read to EOF: Confirmed AGENTS.md has 279 lines and read the remainder through EOF. (AGENTS.md:261, b3dc27403498)
  • Scoped policy check: No scoped AGENTS.md exists under src/cron, and the only maintainer note present is Telegram-specific, so no additional scoped cron note applied.
  • Current main helper behavior: Current main returns preferFinalAssistantVisibleText only when opts.deliveryRequested is exactly false, so undefined or omitted options currently return false in the no-channel branch. (src/cron/isolated-agent/channel-output-policy.ts:24, b3dc27403498)
  • Normal runtime caller passes a boolean: The prepared cron context stores deliveryRequested as a boolean and the normal run.ts caller forwards that boolean into executeCronRun, which limits proof that the undefined edge is currently user-facing. (src/cron/isolated-agent/run.ts:495, b3dc27403498)
  • Normal executor call forwards the prepared boolean: run.ts passes prepared.context.deliveryRequested into executeCronRun, and rg found no other production caller of executeCronRun or createCronPromptExecutor outside run-executor and tests. (src/cron/isolated-agent/run.ts:1366, b3dc27403498)

Likely related people:

  • ai-hpc: Authored the current-main commit that changed the no-channel policy from a hard false default to the deliveryRequested === false behavior this PR extends. (role: recent area contributor; confidence: high; commits: 4eb4b87c8ede; files: src/cron/isolated-agent/channel-output-policy.ts, src/cron/isolated-agent/channel-output-policy.test.ts, src/cron/isolated-agent/run.ts)
  • shakkernerd: GitHub commit metadata lists Shakker as the committer for the current-main cron policy commit that introduced the optional deliveryRequested path. (role: committer of current behavior; confidence: medium; commits: 4eb4b87c8ede; files: src/cron/isolated-agent/channel-output-policy.ts, src/cron/isolated-agent/run-executor.ts)
  • steipete: Recent GitHub path history shows repeated cron isolated-agent and output policy work, including the original move of cron output policy to channel plugins and helper/docs passes around this surface. (role: feature-history contributor; confidence: medium; commits: 40719bcb7462, 93e75f646fff, 1e7510ae103e; files: src/cron/isolated-agent/channel-output-policy.ts, src/cron/isolated-agent/helpers.ts, src/cron/isolated-agent/run.ts)
  • openperf: Opened the earlier focused PR for the same no-deliver tool-warning recovery issue that led to the current-main boolean policy path. (role: source PR author for prior related fix; confidence: medium; commits: b83756ddd7b9; files: src/cron/isolated-agent/channel-output-policy.ts, src/cron/isolated-agent/channel-output-policy.test.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.

@fsdwen

fsdwen commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

@vincentkoc would you mind reviewing this? 1-char fix for #90664 — closes the edge case that the earlier fix missed in the path. Thanks!

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels Jun 14, 2026
@vincentkoc
vincentkoc merged commit b90f7d2 into openclaw:main Jun 15, 2026
214 of 222 checks passed
@vincentkoc vincentkoc self-assigned this Jun 15, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 16, 2026
…icit delivery (openclaw#92817)

resolveCronChannelOutputPolicy checked deliveryRequested === false
when there is no channel. Since deliveryRequested is optional
(?: boolean), undefined and missing opts both returned false,
blocking the hasRecoveredToolWarning rescue path for --no-deliver
cron runs whose agent recovered successfully.

Change === false to !== true: when no channel exists, prefer the
agent's final visible text unless delivery was explicitly
requested.

Fixes openclaw#90664

Co-authored-by: Claude Fable 5 <[email protected]>
crh-code pushed a commit to crh-code/openclaw that referenced this pull request Jun 18, 2026
…icit delivery (openclaw#92817)

resolveCronChannelOutputPolicy checked deliveryRequested === false
when there is no channel. Since deliveryRequested is optional
(?: boolean), undefined and missing opts both returned false,
blocking the hasRecoveredToolWarning rescue path for --no-deliver
cron runs whose agent recovered successfully.

Change === false to !== true: when no channel exists, prefer the
agent's final visible text unless delivery was explicitly
requested.

Fixes openclaw#90664

Co-authored-by: Claude Fable 5 <[email protected]>
badgerbees pushed a commit to badgerbees/openclaw that referenced this pull request Jul 8, 2026
…icit delivery (openclaw#92817)

resolveCronChannelOutputPolicy checked deliveryRequested === false
when there is no channel. Since deliveryRequested is optional
(?: boolean), undefined and missing opts both returned false,
blocking the hasRecoveredToolWarning rescue path for --no-deliver
cron runs whose agent recovered successfully.

Change === false to !== true: when no channel exists, prefer the
agent's final visible text unless delivery was explicitly
requested.

Fixes openclaw#90664

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

Labels

P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

2 participants