[plugin sdk] Add scheduled session turns#75588
Conversation
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path. Real behavior proof Next step before merge Review detailsBest possible solution: Retry the Codex review after fixing the execution failure. Do we have a high-confidence way to reproduce the issue? Unclear. The review failed before ClawSweeper could establish a reproduction path. Is this the best way to solve the issue? Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction. What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against eddf56361152. |
1f02f26 to
fe954ef
Compare
178a840 to
cc23de2
Compare
|
Fixed in |
cc23de2 to
a51d1e8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cc23de28b7
ℹ️ 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".
There was a problem hiding this comment.
Pull request overview
Adds a new Plugin SDK seam that lets bundled plugins schedule future session turns via the host cron surface, and deterministically clean them up by a plugin-owned tag, with contract coverage and SDK baseline updates.
Changes:
- Extend
OpenClawPluginApiwithscheduleSessionTurnandunscheduleSessionTurnsByTag, plus exported param/result types. - Implement host-side cron job name construction, scheduling, stale-unload rollback, and tag-based cleanup.
- Add focused contract tests and update SDK API baseline + changelog.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/plugins/types.ts | Adds new API methods and re-exports scheduling/unscheduling types. |
| src/plugins/registry.ts | Wires new API methods through the plugin registry with side-effect gating + active-registry protection. |
| src/plugins/host-hooks.ts | Defines new scheduling/unscheduling types (schedule union + params/results). |
| src/plugins/host-hook-workflow.ts | Implements cron payload construction, cron.add/cron.remove integration, name/tag logic, and tag cleanup via cron.list paging. |
| src/plugins/contracts/scheduled-turns.contract.test.ts | Contract tests for naming, cron payload validity, paging cleanup, stale rollback, and API wiring. |
| src/plugins/captured-registration.ts | Extends captured plugin registration test shim with the new API methods. |
| src/plugins/api-builder.ts | Adds handlers + no-op defaults for the new API methods. |
| src/plugin-sdk/plugin-test-api.ts | Extends test plugin API factory with the new async methods. |
| src/plugin-sdk/plugin-entry.ts | Re-exports new scheduling/unscheduling types from the SDK entry surface. |
| src/plugin-sdk/core.ts | Re-exports new scheduling/unscheduling types from the core SDK barrel. |
| docs/.generated/plugin-sdk-api-baseline.sha256 | Updates SDK API baseline hashes to reflect the new surface. |
| CHANGELOG.md | Documents the new bundled-plugin scheduling seam and tag-based unscheduling. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04a4332aae
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 35216dcf6f
ℹ️ 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".
|
Audit follow-up fixed in |
The "blocks registration-time" test was flaky in full-file runs because
setActivePluginRegistry queues cleanup via fire-and-forget dynamic
imports (cleanupPreviousPluginHostRegistry). When the prior test's
"wires schedule and unschedule" mock returned {ok:true} for cron.remove
without a `removed` field, the cleanup callback in
schedulePluginSessionTurn would throw, leaving the runtime scheduler-job
state map populated. The runtime-state cleanup loop then runs twice (in
runPluginHostCleanup at lines 406 and 430), and the second pass's
cron.remove call settles AFTER the prior test's afterEach mockReset,
contaminating the next test.
Two surgical fixes:
- Make the "wires schedule" mock return {ok:true,removed:true} for
cron.remove so the cleanup callback's didCronCleanupJob check passes,
the state-map entry gets deleted, and the duplicate cleanup pass
finds nothing to do.
- Defensively drain pending microtasks at the start of the failing test
and reset the mock again, so any remaining queued cleanup cannot
pollute the test's call-history assertion.
This is a test-only change; production runtime behavior is unchanged.
71093ce to
fa63242
Compare
|
Superseded by #80229, which now carries the combined proof and merge-ready consolidation branch. |
Why this matters
OpenClaw plugins increasingly need to create follow-up work that happens later, in the same session lane the user is already operating in: remind me in an hour, reopen this investigation tomorrow, schedule a follow-up agent turn after an approval window, or clean up a family of pending nudges when the workflow resolves.
Without a generic seam, plugin authors end up with two bad options:
This PR adds the narrow host-scheduler seam in the plugin SDK. Plugins can ask the host to schedule a future session turn and later clean up plugin-owned scheduled jobs by tag, while OpenClaw keeps ownership of cron naming, lifecycle, delivery routing, and cleanup semantics.
What kinds of plugins this could support
This seam is intentionally generic. It can support many plugin families without adding plugin-specific scheduling routes to core:
The important part: the plugin decides why the follow-up exists. OpenClaw only provides the bounded host seam for when it should happen and how it is cleaned up.
New SDK seam
This PR adds:
OpenClawPluginApi.scheduleSessionTurn(...)OpenClawPluginApi.unscheduleSessionTurnsByTag(...)at,delayMs, and cron schedulesregister()Example plugin usage:
Runtime architecture
The plugin owns the follow-up intent and tag taxonomy. OpenClaw owns the cron contract, namespacing, and actual future-turn delivery.
Safety and boundaries
This stays intentionally narrow:
scheduleSessionTurnandunscheduleSessionTurnsByTagstay callable afterregister()cron + deleteAfterRun: truecombinations are rejected instead of guessingThis is a scheduler seam for future session turns, not a generic host automation API.
What changed
OpenClawPluginApi.scheduleSessionTurnandunscheduleSessionTurnsByTagplus SDK exports for schedule/cleanup params and results.at,delayMs, and cron schedules, with optional delivery mode.:cleanup tags and rejectedcron + deleteAfterRun: trueinstead of silently widening the host contract.scheduleSessionTurnandunscheduleSessionTurnsByTagremain callable afterregister()so a real bundled plugin can capture them duringregister()and invoke them later from a registered callback/handler.## Unreleasedand regenerated the plugin-sdk API baseline after the rebase.Relationship to adjacent seams
This does not try to solve every workflow problem in one slice. It is intentionally narrower than session actions, run-context lifecycle, attachments, or SessionEntry projection. Those remain split into follow-up PRs so maintainers can review one host seam at a time.
Non-goals
Real behavior proof
Behavior or issue addressed:
This keeps the post-registration seam narrow while proving the scheduled-turn helpers work in a real host runtime. After this patch, a bundled plugin can capture
scheduleSessionTurnandunscheduleSessionTurnsByTagduringregister(), invoke them later from a registered callback/handler, create real host cron jobs, reject invalid cleanup inputs without widening the contract, and clean up the tagged jobs deterministically.Real environment tested:
On
2026-05-09, I started a real loopback gateway from/Users/lume/openclaw-review-worktrees/pr-75588-rebaseand loaded a real bundledproof-schedulerplugin throughloadOpenClawPlugins.Exact steps or command run after this patch:
proof-schedulerplugin and let it captureapi.scheduleSessionTurnplusapi.unscheduleSessionTurnsByTagduringregister().proof-scheduler.exerciseso the plugin exercised those captured helpers after registration.cron.listimmediately after scheduling to inspect the real host jobs.unscheduleSessionTurnsByTag, then calledcron.listagain to verify that the tagged jobs were gone.Evidence after fix:
7d2d8bf2-f028-4a44-ad08-c75fd966b965ca448912-25a0-4aec-9e87-88587464e0dctag: "bad:tag"case returnednull.cron + deleteAfterRun: truecase returnednull.cron.listimmediately after schedule showed two real host jobs namedplugin:proof-scheduler:tag:proof:agent:main:main:*, both targetingsession:agent:main:main, bothdeleteAfterRun: true, with delivery modesannounce/lastandnone, and with scheduledattimestamps2026-05-09T17:08:00.334Zand2026-05-09T17:09:00.356Z.{ removed: 2, failed: 0 }.cron.listafter cleanup returned[].Copied live output after fix:
Observed result after fix:
The real bundled plugin was able to use the two late-call helpers after
register()without reopening the rest of the plugin API. Real host cron jobs were created, visible incron.list, and then removed cleanly by the tagged cleanup path. Invalid cleanup tags and invalidcron + deleteAfterRun: truecombinations were rejected instead of silently widening the contract.What was not tested:
This proof did not cover a full user-facing UI flow or a long-lived production cron lifecycle across process restarts. The live proof here is intentionally limited to real post-registration helper capture, real host cron job creation/listing, invalid-input rejection, and tagged cleanup in a live OpenClaw runtime.
Validation
pnpm test src/plugins/contracts/scheduled-turns.contract.test.ts src/plugins/contracts/host-hooks.contract.test.tspnpm plugin-sdk:api:genpnpm plugin-sdk:api:checkpnpm lint:coregit diff --checknpm run check:no-conflict-markers