feat(plugins): add cron reconciliation lifecycle hook#104191
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b93299d02c
ℹ️ 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".
| }, | ||
| cron: runtimeState.cronState.cron, | ||
| cronState: runtimeState.cronState, | ||
| cronReconciliation, |
There was a problem hiding this comment.
Gate startup reconciliation on plugin readiness
When the gateway is started in deferred sidecar mode (the CLI selects this for OPENCLAW_SKIP_CHANNELS/OPENCLAW_SKIP_PROVIDERS), startGatewayPostAttachRuntime returns before plugin sidecars finish loading, but this post-ready timer can still start cron and complete cron_reconciled after only 250ms. If plugin loading takes longer, getGlobalHookRunner() has no newly loaded cron_reconciled handlers yet, so an external scheduler plugin misses its only startup baseline until a later cron reload or gateway restart.
Useful? React with 👍 / 👎.
b93299d to
f2976f2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f2976f273c
ℹ️ 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".
| if (params.isClosing() || generation !== lifecycleGeneration) { | ||
| return; | ||
| } | ||
| await params.runHook(event, { |
There was a problem hiding this comment.
Add a timeout for serialized cron_reconciled hooks
When a cron_reconciled handler has no configured hooks.timeoutMs and its promise never settles (for example an external scheduler RPC hangs), this await leaves dispatchTail unresolved, so every later startup/reload reconciliation is queued behind it and no plugin receives the fresh cron baseline until the gateway restarts. The hook runner only applies default timeouts to named hooks in DEFAULT_VOID_HOOK_TIMEOUT_MS_BY_HOOK, and this new hook is not one of them, so the serialized lifecycle needs its own bounded timeout or default hook budget.
Useful? React with 👍 / 👎.
|
Codex review: stale review; fresh review needed. Summary Next step Review history (1 earlier review cycle)
|
f2976f2 to
30fdbfa
Compare
|
Land-ready at exact head The typed Proof:
Known proof gaps: none for the core lifecycle contract. An external scheduler adapter is intentionally follow-up work; #103736 remains the separate reload publication/atomicity issue. |
|
Merged via squash.
|
* feat(plugins): add cron reconciliation lifecycle hook * chore(plugin-sdk): refresh api baseline * fix(plugin-sdk): update public export budget
Closes #104082
Related: #103736 (the separate hot-reload publication/atomicity issue is not changed by this PR).
What Problem This Solves
Plugins that project OpenClaw cron jobs into an external scheduler have no authoritative lifecycle point after the Gateway has loaded durable cron state and reconciled exit watchers.
gateway_startcan run too early, whilecron_changedis a coalescible change hint rather than a complete-state baseline.Why This Change Was Made
This adds a typed
cron_reconciledobservation hook after scheduler startup and every scheduler replacement on config reload. The event exposes only the reconciliation reason and effective enabled state; plugins read the exact reconciled scheduler throughctx.getCron(). Generation guards, serialized delivery, and shutdown invalidation suppress stale callbacks without introducing retries, durability, or plugin-only replay.User Impact
Plugin authors can reliably rebuild a complete external cron projection after Gateway startup or scheduler replacement. Disabled cron emits
enabled: false, allowing adapters to clear stale external wakes, whilecron_changedremains available for low-latency incremental hints.Evidence
f2976f273c9648010fcde3ed5ff7161c409bfe36: 141 focused gateway/plugin test executions andpnpm plugin-sdk:api:checkpassed on Blacksmith Testboxtbx_01kx7tqqvxah2ms4g68ek1d7pp(Actions run).plugin-sdk-surface-reporttests andpnpm plugin-sdk:api:checkpassed on Blacksmith Testboxtbx_01kx7vcdpjxe3w3vdc5j8g1wk1(Actions run).30fdbfa92b1c630f393a000e2cc7bfd2823abac2; the interveningorigin/mainfiles are outside this PR's gateway/plugin/SDK surface. Exact-head hosted CI is the landing gate.pnpm check:changed,pnpm check:docs, andpnpm buildpassed; the build included the Plugin SDK export check.IDENTITY/USERtemplate routes introduced onorigin/main; those paths are outside this PR diff.git diff --checkpassed.AI-assisted: yes; maintainer-directed and manually audited.