Skip to content

fix(cron): persist resolved delivery target into isolated cron session deliveryContext#92580

Closed
wangmiao0668000666 wants to merge 1 commit into
openclaw:mainfrom
wangmiao0668000666:fix/92460-cron-completion-delivery-context
Closed

fix(cron): persist resolved delivery target into isolated cron session deliveryContext#92580
wangmiao0668000666 wants to merge 1 commit into
openclaw:mainfrom
wangmiao0668000666:fix/92460-cron-completion-delivery-context

Conversation

@wangmiao0668000666

@wangmiao0668000666 wangmiao0668000666 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Isolated cron completion delivery can fail with Channel is required (no configured channels detected) even when the job explicitly sets delivery.channel, because the resolved delivery target is never written back to the isolated cron session entry's deliveryContext. Completion-announce paths such as sessions_send/subagent_announce later resolve the target from the session entry and see an empty context.

This change persists the resolved cron delivery target onto the isolated cron session entry right after resolveCronDeliveryContext, so explicit delivery.channel survives to the final completion announcer.

Fixes #92460.

Changes

  • src/cron/isolated-agent/run-session-state.ts: add setCronSessionDeliveryContextFromResolvedDelivery, a focused helper that normalizes and writes a resolved delivery target into the session entry's deliveryContext only when resolution succeeds and a routable target exists.
  • src/cron/isolated-agent/run.ts: call the helper in prepareCronRunContext after resolveCronDeliveryContext returns.
  • src/cron/isolated-agent/run-session-state.test.ts: add regression tests covering explicit target persistence, missing optional fields, failed-resolution no-op, and empty-target no-op.
  • scripts/repro/issue-92460-cron-completion-delivery-context.mts: standalone reproduction script that exercises the production helper and verifies the explicit channel/to/account/thread survive.

Real behavior proof

  • Behavior addressed: explicit delivery.channel on an isolated cron job is now persisted onto the isolated session entry, so completion-announce target resolution no longer falls back to a channel-less main session.
  • Real environment tested: Linux 4.19.112-2.el8.x86_64, Node v22.19.0, local OpenClaw source checkout.
  • Exact steps or command run after this patch:
    • node --import tsx scripts/repro/issue-92460-cron-completion-delivery-context.mts
  • Evidence after fix:
    Terminal output from running the standalone reproduction script against the patched source:
    === Reproduction for issue #92460 ===
    Isolated cron session deliveryContext: {
      \"channel\": \"webchat\",
      \"to\": \"controller\",
      \"accountId\": \"default\",
      \"threadId\": \"thread-42\"
    }
    PASS: explicit delivery.channel survives to the session entry deliveryContext
    
  • Observed result after fix: the isolated cron session entry now carries a normalized deliveryContext with the explicit channel, to, account, and thread from the resolved delivery target. Before the patch the same script would leave deliveryContext empty and the entry would lose the explicit webchat target.
  • What was not tested: live channel send integration (no configured webchat gateway in the test environment); only the session-state propagation path and existing cron delivery-target resolution tests were exercised.

Verification

  • node --import tsx scripts/repro/issue-92460-cron-completion-delivery-context.mts passes
  • pnpm test src/cron/isolated-agent/run-session-state.test.ts --run passes
  • pnpm test src/cron/isolated-agent/delivery-target.test.ts --run passes
  • pnpm test src/cron/isolated-agent/run.session-key-isolation.test.ts --run passes
  • npx oxlint on changed files passes
  • pnpm exec oxfmt on changed files passes
  • pnpm build passes
  • pnpm tsgo passes

@openclaw-barnacle openclaw-barnacle Bot added triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. scripts Repository scripts commands Command implementations agents Agent runtime and tooling size: M labels Jun 13, 2026
@clawsweeper

clawsweeper Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 13, 2026, 11:32 AM ET / 15:32 UTC.

Summary
The branch adds a helper that normalizes a successful resolved cron delivery target into the isolated cron session entry deliveryContext, calls it during cron preparation, and adds focused regression plus repro-script coverage.

PR surface: Source +25, Tests +65, Other +45. Total +135 across 4 files.

Reproducibility: Partly: the linked issue gives a concrete isolated cron announce-delivery scenario and the PR supplies a focused helper-level repro, but I did not run a live channel send.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: scripts/repro/issue-92460-cron-completion-delivery-context.mts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • none.

Risk before merge

  • [P1] Live webchat delivery is not proven by the contributor's repro; the proof covers the session-state propagation path that the bug report identifies.

Maintainer options:

  1. Land The Narrow Cron Fix (recommended)
    Accept the remaining live-send proof gap because the patch is now scoped to the session-state propagation bug and has focused regression/proof coverage.
  2. Ask For Live Channel Proof
    Before merge, ask for a redacted live webchat or gateway send transcript showing the final isolated-cron completion announcement reaches the controller.

Next step before merge

  • No automated repair is needed because the prior unrelated workspace changes were removed and no concrete patch defect remains.

Security
Cleared: No concrete security or supply-chain issue found; the diff adds a local repro script and cron session-state code/tests without dependency, workflow, secret, package, or external code-execution changes.

Review details

Best possible solution:

Land the narrow cron session deliveryContext propagation fix after normal maintainer review and exact-head checks, keeping the linked issue open until this PR merges.

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

Partly: the linked issue gives a concrete isolated cron announce-delivery scenario and the PR supplies a focused helper-level repro, but I did not run a live channel send.

Is this the best way to solve the issue?

Yes. Writing the already-resolved delivery target into the isolated cron session entry is the narrowest maintainable fix because the later sessions_send/subagent_announce path already consumes deliveryContext from session state.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add merge-risk: 🚨 message-delivery: The PR changes the state used to route isolated cron completion announcements, so a mistake could still misroute or drop final messages.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • 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 a standalone repro script that exercises the changed session-state propagation path; it does not prove live webchat delivery.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove merge-risk: 🚨 compatibility: Current PR review merge-risk labels are merge-risk: 🚨 message-delivery, merge-risk: 🚨 session-state.
  • remove status: 🛠️ actively grinding: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P1: The linked issue is a user-facing isolated cron completion delivery failure that can lose completion messages.
  • merge-risk: 🚨 message-delivery: The PR changes the state used to route isolated cron completion announcements, so a mistake could still misroute or drop final messages.
  • merge-risk: 🚨 session-state: The fix persists deliveryContext into isolated cron session entries, which is session state consumed by later announcement resolution.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • 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 a standalone repro script that exercises the changed session-state propagation path; it does not prove live webchat delivery.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal output from a standalone repro script that exercises the changed session-state propagation path; it does not prove live webchat delivery.
Evidence reviewed

PR surface:

Source +25, Tests +65, Other +45. Total +135 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 25 0 +25
Tests 1 65 0 +65
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 1 45 0 +45
Total 4 135 0 +135

What I checked:

Likely related people:

  • vincentkoc: Authored the isolated fresh cron session state change that clears carried delivery routing for forced isolated runs, the boundary this PR repopulates after target resolution. (role: feature-history owner; confidence: high; commits: f0ceb4b68f5d; files: src/cron/isolated-agent/session.ts, src/cron/isolated-agent/run-session-state.ts)
  • MonkeyLeeT: Recently changed cron session-state persistence and usage totals in the same isolated cron run/session-state surface. (role: recent area contributor; confidence: medium; commits: 50c206826888; files: src/cron/isolated-agent/run.ts, src/cron/isolated-agent/run-session-state.ts)
  • steipete: Recent cron normalization, run-log, and inline-comment work touched the same cron delivery/session helper area, and the isolated session-state history lists Peter Steinberger as co-author on the fresh-session change. (role: recent area contributor; confidence: medium; commits: 875c9fd96dd8, 1e7510ae103e, f0ceb4b68f5d; files: src/cron/isolated-agent/run.ts, src/cron/isolated-agent/run-session-state.ts, src/cron/isolated-agent/delivery-target.ts)
  • jalehman: Co-authored or reviewed prior sessions announcement target fixes that preserve thread/account routing through sessions.list fallback. (role: announce-route reviewer/co-author; confidence: medium; commits: ac13b09b742d, 03f2951e63c4; files: src/agents/tools/sessions-announce-target.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 the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label Jun 13, 2026
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 13, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated the PR body to separate the standalone reproduction-script terminal output (real behavior evidence) from the verification checklist. The Real behavior proof CI check is now passing. Please re-run the review.

@clawsweeper

clawsweeper Bot commented Jun 13, 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.

Re-review progress:

@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The previous re-review failed due to a Codex transient transport error (3 retries exhausted) and a subsequent clawsweeper-state git push failure, not because of a code or proof issue. The PR body has been updated and the Real behavior proof CI check is passing. Please re-run the review.

1 similar comment
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The previous re-review failed due to a Codex transient transport error (3 retries exhausted) and a subsequent clawsweeper-state git push failure, not because of a code or proof issue. The PR body has been updated and the Real behavior proof CI check is passing. Please re-run the review.

@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Branch is already rebased on latest main. The previous re-reviews failed due to Codex transient transport errors and clawsweeper-state git push failures. The Real behavior proof CI check is passing and the PR body contains standalone reproduction script output. Please re-run the review.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. 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. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 13, 2026
@wangmiao0668000666
wangmiao0668000666 force-pushed the fix/92460-cron-completion-delivery-context branch from a0b9e00 to 49a555c Compare June 13, 2026 13:15
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review\n\nRemoved the unrelated issue-91760 workspace fallback changes (agent-scope-config, memory-host-sdk resolver, their updated tests, and the issue-91760 repro script). The branch now contains only the isolated cron deliveryContext persistence fix, its regression tests, and the issue-92460 repro. Re-ran the cron/agent-scope tests and oxlint on the remaining files; both passed.

@openclaw-barnacle openclaw-barnacle Bot added size: S and removed commands Command implementations agents Agent runtime and tooling size: M labels Jun 13, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed 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. labels Jun 13, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. 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. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 13, 2026
@clawsweeper

clawsweeper Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Verified via gh pr diff --name-only that this branch now contains only the 4 cron-related files:

  • src/cron/isolated-agent/run-session-state.ts
  • src/cron/isolated-agent/run.ts
  • src/cron/isolated-agent/run-session-state.test.ts
  • scripts/repro/issue-92460-cron-completion-delivery-context.mts

The unrelated issue-91760 workspace fallback changes have been removed. Please re-run the review.

@clawsweeper

clawsweeper Bot commented Jun 13, 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.

Re-review progress:

@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. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 13, 2026
@vincentkoc vincentkoc self-assigned this Jun 13, 2026
@vincentkoc

Copy link
Copy Markdown
Member

maintainer deep review confirmed the reported cron completion-routing bug, but this PR is not safe to land.

Persisting the exact run requester route fixes recovery, but that route must remain available until every supported background completion settles and then be retired. Repair passes covered cron completion and subagent descendants, yet final autoreview found non-subagent ACP/media task completions have no retirement hook. Those route-only rows would accumulate per run and pressure the session-store cap.

I am closing this PR rather than landing a lifecycle leak or wiring cron-specific cleanup into every task implementation. The canonical fix needs a generic requester-route lease owned by the shared background-task completion/delivery lifecycle, separate from generic session identity, with retirement after final delivery settles.

Focused repair proof passed (47 tests plus format/lint), but final autoreview correctly remains blocking.

@vincentkoc vincentkoc closed this Jun 14, 2026
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 15, 2026
…context

Replaces the rejected approach from PR openclaw#92580 that persisted resolved
delivery targets onto the session entry (which created a lifecycle leak).

Instead introduces a generic in-memory delivery route lease store:

- src/infra/delivery-lease-store.ts — register/lookup/retire with
  TTL-based cleanup (1h default) and 2000-entry cap
- src/agents/subagent-announce-origin.ts — resolveAnnounceOrigin gains
  optional sessionKey param; falls back to lease store when session
  entry lacks delivery context
- src/cron/isolated-agent/run.ts — create lease in prepareCronRunContext
  after delivery resolution; retire in finalizeCronRun after dispatch
- src/agents/subagent-announce.ts — pass targetRequesterSessionKey
- src/plugin-sdk/agent-harness-task-runtime.ts — pass requesterSessionKey
- src/infra/delivery-lease-store.test.ts — 8 unit tests

Fixes openclaw#92460
Refs openclaw#92580

Co-Authored-By: Claude <[email protected]>
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 16, 2026
Add retireDeliveryLease calls to the shared completion/delivery lifecycle
in dispatchCronDelivery. This ensures delivery route leases are cleaned up
immediately after final delivery settles, rather than lingering until TTL
expiration or cap eviction.

Retirement happens in:
- deliverViaDirectAndCleanup: after direct channel delivery completes
- finishSilentReplyDelivery: after silent reply delivery completes

Both paths are part of the shared background-task completion lifecycle that
owns the delivery route, matching the design described in PR openclaw#92580 review.

Fixes the lifecycle leak where production never retired leases, leaving
them to accumulate until the 52h TTL or 2000-entry cap.
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 16, 2026
…context

Replaces the rejected approach from PR openclaw#92580 that persisted resolved
delivery targets onto the session entry (which created a lifecycle leak).

Instead introduces a generic in-memory delivery route lease store:

- src/infra/delivery-lease-store.ts — register/lookup/retire with
  TTL-based cleanup (1h default) and 2000-entry cap
- src/agents/subagent-announce-origin.ts — resolveAnnounceOrigin gains
  optional sessionKey param; falls back to lease store when session
  entry lacks delivery context
- src/cron/isolated-agent/run.ts — create lease in prepareCronRunContext
  after delivery resolution; retire in finalizeCronRun after dispatch
- src/agents/subagent-announce.ts — pass targetRequesterSessionKey
- src/plugin-sdk/agent-harness-task-runtime.ts — pass requesterSessionKey
- src/infra/delivery-lease-store.test.ts — 8 unit tests

Fixes openclaw#92460
Refs openclaw#92580

Co-Authored-By: Claude <[email protected]>
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 16, 2026
Add retireDeliveryLease calls to the shared completion/delivery lifecycle
in dispatchCronDelivery. This ensures delivery route leases are cleaned up
immediately after final delivery settles, rather than lingering until TTL
expiration or cap eviction.

Retirement happens in:
- deliverViaDirectAndCleanup: after direct channel delivery completes
- finishSilentReplyDelivery: after silent reply delivery completes

Both paths are part of the shared background-task completion lifecycle that
owns the delivery route, matching the design described in PR openclaw#92580 review.

Fixes the lifecycle leak where production never retired leases, leaving
them to accumulate until the 52h TTL or 2000-entry cap.
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 16, 2026
…context

Isolated cron jobs with explicit delivery.channel lose routing state because
isolated session entries strip delivery context. Subagent announce completion
has no fallback lookup, so the final announcement cannot reach the controller.

Adds an in-memory delivery route lease store that:

- Registers a lease in prepareCronRunContext keyed by runSessionKey with 52h
  TTL to cover the full agent run window plus safety buffer
- Retires the lease from the completion/delivery lifecycle in delivery-dispatch
  (finishSilentReplyDelivery + deliverViaDirectAndCleanup finally block) so
  routes do not linger until TTL expiry or cap eviction
- Falls back via resolveAnnounceOrigin sessionKey parameter when the session
  entry has no deliveryContext (isolated cron session)

This matches the design requested in PR openclaw#92580 review (@vincentkoc):
'generic requester-route lease owned by the shared background-task completion
/delivery lifecycle, separate from generic session identity, with retirement
after final delivery settles.'

TTL/cap (1h default, 2000-entry LRU) act as safety net only — production
retirement is wired into the completion lifecycle.

Tests:
- src/infra/delivery-lease-store.test.ts — 8 unit tests for register/lookup/
  retire/prune/cap/idempotency
- src/cron/isolated-agent.delivery-lease-lifecycle.test.ts — 6 integration
  tests proving full lifecycle through runCronIsolatedAgentTurn (lease is
  registered, used for delivery, and explicitly retired after delivery settles)
- scripts/repro/issue-92460-delivery-lease-store.mts — standalone reproduction
- scripts/test-delivery-lease-lifecycle.mts — real-environment proof script

Files:
- src/infra/delivery-lease-store.ts (NEW) — lease store with TTL, cap, retirement
- src/cron/isolated-agent/run.ts — register lease after delivery resolution
- src/cron/isolated-agent/delivery-dispatch.ts — retire lease in completion
  lifecycle (finishSilentReplyDelivery + deliverViaDirectAndCleanup)
- src/agents/subagent-announce-origin.ts — lease fallback in resolveAnnounceOrigin
- src/agents/subagent-announce.ts — pass targetRequesterSessionKey
- src/plugin-sdk/agent-harness-task-runtime.ts — pass requesterSessionKey
- src/cron/isolated-agent.test-setup.ts — reset lease store for test isolation
- test/scripts/ci-node-test-plan.test.ts — add delivery-lease-store test shard

Fixes openclaw#92460
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 16, 2026
…context

Isolated cron jobs with explicit delivery.channel lose routing state because
isolated session entries strip delivery context. Subagent announce completion
has no fallback lookup, so the final announcement cannot reach the controller.

Adds an in-memory delivery route lease store that:

- Registers a lease in prepareCronRunContext keyed by runSessionKey with 52h
  TTL to cover the full agent run window plus safety buffer
- Retires the lease from the completion/delivery lifecycle in delivery-dispatch
  (finishSilentReplyDelivery + deliverViaDirectAndCleanup finally block) so
  routes do not linger until TTL expiry or cap eviction
- Falls back via resolveAnnounceOrigin sessionKey parameter when the session
  entry has no deliveryContext (isolated cron session)

This matches the design requested in PR openclaw#92580 review (@vincentkoc):
'generic requester-route lease owned by the shared background-task completion
/delivery lifecycle, separate from generic session identity, with retirement
after final delivery settles.'

TTL/cap (1h default, 2000-entry LRU) act as safety net only — production
retirement is wired into the completion lifecycle.

Tests:
- src/infra/delivery-lease-store.test.ts — 8 unit tests for register/lookup/
  retire/prune/cap/idempotency
- src/cron/isolated-agent.delivery-lease-lifecycle.test.ts — 6 integration
  tests proving full lifecycle through runCronIsolatedAgentTurn (lease is
  registered, used for delivery, and explicitly retired after delivery settles)
- scripts/repro/issue-92460-delivery-lease-store.mts — standalone reproduction
- scripts/test-delivery-lease-lifecycle.mts — real-environment proof script

Files:
- src/infra/delivery-lease-store.ts (NEW) — lease store with TTL, cap, retirement
- src/cron/isolated-agent/run.ts — register lease after delivery resolution
- src/cron/isolated-agent/delivery-dispatch.ts — retire lease in completion
  lifecycle (finishSilentReplyDelivery + deliverViaDirectAndCleanup)
- src/agents/subagent-announce-origin.ts — lease fallback in resolveAnnounceOrigin
- src/agents/subagent-announce.ts — pass targetRequesterSessionKey
- src/plugin-sdk/agent-harness-task-runtime.ts — pass requesterSessionKey
- src/cron/isolated-agent.test-setup.ts — reset lease store for test isolation
- test/scripts/ci-node-test-plan.test.ts — add delivery-lease-store test shard

Fixes openclaw#92460
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 16, 2026
…context

Isolated cron jobs with explicit delivery.channel lose routing state because
isolated session entries strip delivery context. Subagent announce completion
has no fallback lookup, so the final announcement cannot reach the controller.

Adds an in-memory delivery route lease store that:

- Registers a lease in prepareCronRunContext keyed by runSessionKey with 52h
  TTL to cover the full agent run window plus safety buffer
- Retires the lease from the completion/delivery lifecycle in delivery-dispatch
  (finishSilentReplyDelivery + deliverViaDirectAndCleanup finally block) so
  routes do not linger until TTL expiry or cap eviction
- Falls back via resolveAnnounceOrigin sessionKey parameter when the session
  entry has no deliveryContext (isolated cron session)

This matches the design requested in PR openclaw#92580 review (@vincentkoc):
'generic requester-route lease owned by the shared background-task completion
/delivery lifecycle, separate from generic session identity, with retirement
after final delivery settles.'

TTL/cap (1h default, 2000-entry LRU) act as safety net only — production
retirement is wired into the completion lifecycle.

Tests:
- src/infra/delivery-lease-store.test.ts — 8 unit tests for register/lookup/
  retire/prune/cap/idempotency
- src/cron/isolated-agent.delivery-lease-lifecycle.test.ts — 6 integration
  tests proving full lifecycle through runCronIsolatedAgentTurn (lease is
  registered, used for delivery, and explicitly retired after delivery settles)
- scripts/repro/issue-92460-delivery-lease-store.mts — standalone reproduction
- scripts/test-delivery-lease-lifecycle.mts — real-environment proof script

Files:
- src/infra/delivery-lease-store.ts (NEW) — lease store with TTL, cap, retirement
- src/cron/isolated-agent/run.ts — register lease after delivery resolution
- src/cron/isolated-agent/delivery-dispatch.ts — retire lease in completion
  lifecycle (finishSilentReplyDelivery + deliverViaDirectAndCleanup)
- src/agents/subagent-announce-origin.ts — lease fallback in resolveAnnounceOrigin
- src/agents/subagent-announce.ts — pass targetRequesterSessionKey
- src/plugin-sdk/agent-harness-task-runtime.ts — pass requesterSessionKey
- src/cron/isolated-agent.test-setup.ts — reset lease store for test isolation
- test/scripts/ci-node-test-plan.test.ts — add delivery-lease-store test shard

Fixes openclaw#92460
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: S 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.

[Bug]: Isolated cron completion announcer drops explicit delivery.channel on final controller return

2 participants