Skip to content

Feat/add cron execution hook clean#29682

Open
Patrick-Barletta wants to merge 2 commits intoopenclaw:mainfrom
Patrick-Barletta:feat/add-cron-execution-hook-clean
Open

Feat/add cron execution hook clean#29682
Patrick-Barletta wants to merge 2 commits intoopenclaw:mainfrom
Patrick-Barletta:feat/add-cron-execution-hook-clean

Conversation

@Patrick-Barletta
Copy link
Copy Markdown
Contributor

Summary

  • Problem: Plugins had no way to observe when cron jobs complete, preventing behavioral tracking and monitoring integrations
  • Why it matters: Essential for trust scoring systems and monitoring plugins that need to track scheduled task execution for dimension calculation and reliability metrics
  • What changed: Added cron_execution hook that fires after cron jobs complete, providing cronName, success status, and duration
  • What did NOT change: No changes to cron execution logic, scheduling, or error handling - purely additive observability

Change Type

  • Feature
  • Bug fix
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations (plugin hooks)
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • None

User-visible / Behavior Changes

For plugin developers:

  • New cron_execution hook available in plugin API
  • Hook fires after each cron job completes with event data:
    • cronName: Job identifier
    • success: Boolean (derived from status === "ok" && !error)
    • durationMs: Execution time
    • sessionId, status, error: Additional metadata

For end users:

  • None (purely plugin-facing API)

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Windows 11
  • Runtime: Node.js v24.13.1
  • Config: Cron job configured in openclaw.json

Steps

  1. Install plugin that listens to cron_execution hook
  2. Configure a cron job in OpenClaw
  3. Wait for cron execution or trigger manually
  4. Check plugin logs for hook event

Expected

  • Plugin receives cron_execution event with cronName, success, durationMs
  • Hook fires exactly once per cron completion
  • No impact on cron execution timing or error handling

Actual

  • ✅ Hook fires after cron completion
  • ✅ Event data includes all expected fields
  • ✅ No performance degradation in cron execution

Evidence

  • Trace/log snippets
  • Failing test/log before + passing after

Before: Plugins could not observe cron executions - no hook available

After:

Cron execution recorded as session: daily-backup success=true duration=1234ms

Implementation in server-cron.ts:

// Dispatch cron_execution hook for plugins
if (hookRunner?.hasHooks("cron_execution")) {
  hookRunner.runCronExecution({
    jobId: evt.jobId,
    cronName: job?.name ?? evt.jobId,
    success,
    durationMs: evt.durationMs,
    status: evt.status,
    error: evt.error,
    sessionId: evt.sessionId,
  }, {});
}

Human Verification

Verified scenarios:

  • ✅ Cron job succeeds → hook fires with success=true
  • ✅ Cron job fails → hook fires with success=false
  • ✅ Multiple plugins can listen to same hook
  • ✅ Hook errors don't crash cron execution (caught in hookRunner)
  • ✅ Event data matches expected schema

Edge cases checked:

  • ✅ Hook fires even if no plugins registered (no-op)
  • ✅ Plugin hook handler throws → cron execution continues
  • ✅ Long-running cron → durationMs accurately measured

What I did NOT verify:

  • Webhook delivery interaction (orthogonal feature)
  • Cron scheduling edge cases (unchanged)
  • Cross-platform compatibility beyond Windows (needs CI)

Compatibility / Migration

  • Backward compatible? Yes (additive only)
  • Config/env changes? No
  • Migration needed? No

Existing plugins continue working without changes. New plugins can opt-in to cron_execution hook.

Failure Recovery

How to disable/revert quickly:

  • Comment out hookRunner.runCronExecution() call in server-cron.ts
  • No config changes needed - hook is opt-in for plugins

Files to restore:

  • src/gateway/server-cron.ts (remove lines ~270-290 in onEvent handler)

Known bad symptoms:

  • If hook runner crashes: cron jobs would fail to complete (logged warning in onEvent)
  • Mitigation: Hook execution is wrapped in try/catch with error logging

Risks and Mitigations

  • Risk: Plugin hook handlers block cron completion handler

    • Mitigation: Hook runner executes async handlers with Promise.all and catches errors; fire-and-forget pattern prevents blocking
  • Risk: High-frequency cron jobs + heavy plugin hooks cause memory/perf issues

    • Mitigation: Hook execution is async and non-blocking; plugins responsible for their own throttling/buffering
  • Risk: Event payload includes sensitive cron job data

    • Mitigation: Only includes job metadata (name, status, duration) - no task content or results exposed

Add `cron_execution` plugin hook that fires when a cron job completes.

- Add `cron_execution` to `PluginHookName` type
- Add `PluginHookCronExecutionEvent` with job metadata (jobId, cronName, success, duration, error)
- Dispatch hook in `server-cron.ts` when `action === "finished"`
- Hook fires after cron job execution with success status derived from `status === "completed" && !error`

Enables plugins to observe cron job executions for trust tracking, logging, and monitoring.
- Add runCronExecution method to hooks.ts and export it
- Import PluginHookCronExecutionEvent type in hooks.ts
- Fix cron success check to use 'ok' status instead of 'completed'
- Use hookRunner.runCronExecution() instead of runVoidHook()
- Add type annotation for error parameter in catch block
@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime size: S labels Feb 28, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

Added cron_execution hook that fires after cron jobs complete, providing plugins with observability into scheduled task execution. The implementation follows existing gateway hook patterns (gateway_start, gateway_stop) and includes proper error handling.

Key changes:

  • New hook type cron_execution added to plugin type system with event schema including jobId, cronName, success, durationMs, status, error, and sessionId
  • Hook dispatch integrated into cron completion handler in server-cron.ts with fire-and-forget execution pattern
  • Success determination logic: status === "ok" && !evt.error
  • Fallback handling: uses job?.name ?? evt.jobId when job name unavailable

Implementation quality:

  • Proper null safety with optional chaining (hookRunner?.hasHooks, job?.name)
  • Error handling via .catch() with warning logs prevents hook failures from crashing cron execution
  • Consistent with existing hook patterns (uses runVoidHook like other gateway hooks)
  • Fire-and-forget execution prevents blocking webhook delivery or run log persistence

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk - purely additive observability feature with proper error handling
  • Score of 5 (safe to merge) reflects: additive-only changes with no modifications to existing cron execution logic, proper error handling that prevents hook failures from affecting cron operations, follows established patterns from gateway_start/gateway_stop hooks, good null safety with optional chaining, and comprehensive manual testing coverage per PR description
  • No files require special attention - implementation is clean and follows existing patterns

Last reviewed commit: 16b3c99

thomasxm pushed a commit to thomasxm/openclaw that referenced this pull request Feb 28, 2026
…cation, hook bridge

Comprehensive cron subsystem reliability overhaul addressing 9 open issues:

**Configurable retry policy (openclaw#29527, openclaw#29546)**
- Extract backoff logic into `retry-policy.ts` with configurable `cron.retryBackoff`
  schedule and `cron.stuckRunTimeoutMs` config fields
- Classify execution errors as transient (retry with backoff) or terminal
  (disable job immediately) to prevent futile retry storms
- Add Zod validation for new config fields

**Fix delivery status reporting (openclaw#29660)**
- `resolveDeliveryStatus` now accepts `deliveryAttempted` and returns
  "not-delivered" when delivery was attempted but not confirmed
- Add explicit `delivered: false` to all error paths in delivery-dispatch.ts
- Pass `deliveryAttempted` through the full result chain

**Configurable response prefix (openclaw#29687)**
- Add `responsePrefix` to CronServiceDeps (defaults to "Cron")
- Use dep-injected prefix for main session summary messages

**Strip directive tags from cron output (openclaw#29646)**
- Strip `[[reply_to_current]]`, `[[reply_to:<id>]]`, `[[audio_as_voice]]`
  from isolated cron run output before delivery

**Startup schedule preservation (openclaw#29690)**
- Use maintenance-only recompute in `start()` to avoid advancing past-due
  `nextRunAtMs` values for jobs that `runMissedJobs` intentionally skipped
- Clear `nextRunAtMs` for interrupted jobs so they get fresh schedule computation

**Internal hook bridge (openclaw#29682)**
- Add "cron" to `InternalHookEventType` with `CronExecutionHookEvent` type
- Bridge `emitJobFinished` to `triggerInternalHook` so extensions can react
  to cron job completions (alerting, chaining, etc.)
- Add `isCronExecutionEvent` type guard

**Per-job skip-if-active flag (openclaw#29659)**
- Add `skipIfRunActive?: boolean` to CronJob type for semantic overlap prevention

Tests: 290 cron tests + 21 new retry-policy tests pass.

Fixes: openclaw#29527, openclaw#29546, openclaw#29601, openclaw#29646, openclaw#29659, openclaw#29660, openclaw#29682, openclaw#29687, openclaw#29690
@Takhoffman
Copy link
Copy Markdown
Contributor

Thanks for the contribution.

Closing this PR because it adds a new plugin hook surface (cron_execution) which is feature expansion, not docs/prompt/heartbeat hygiene.

For this workstream we are avoiding new extension points and prioritizing stability and operator clarity improvements only.

@Takhoffman Takhoffman closed this Mar 1, 2026
@Takhoffman Takhoffman reopened this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants