Skip to content

fix(hooks): suppress system event injection when deliver is false [AI-assisted]#36332

Closed
cioclawcode wants to merge 2 commits into
openclaw:mainfrom
cioclawcode:fix/hook-deliver-false-suppress-system-event
Closed

fix(hooks): suppress system event injection when deliver is false [AI-assisted]#36332
cioclawcode wants to merge 2 commits into
openclaw:mainfrom
cioclawcode:fix/hook-deliver-false-suppress-system-event

Conversation

@cioclawcode

@cioclawcode cioclawcode commented Mar 5, 2026

Copy link
Copy Markdown

Summary

When a hook mapping sets deliver: false, the delivery announcement is correctly suppressed, but a system event (Hook <name>: <summary>) is still injected into the main session via enqueueSystemEvent. This PR adds a check for value.deliver !== false so that hooks with explicit deliver: false complete silently.

Problem

In src/gateway/server/hooks.ts, the guard on line ~83 only checks !result.delivered:

if (!result.delivered) {
  enqueueSystemEvent(`${prefix}: ${summary}`.trim(), { sessionKey: mainSessionKey });
}

When deliver: false:

  1. resolveCronDeliveryPlan resolves to { mode: "none", requested: false }
  2. Delivery is never attempted → result.delivered is always false
  3. The !result.delivered guard passes → system event fires unconditionally

This causes the main session to receive "Findings" summaries from every hook completion, even when the user explicitly opted out. The main session agent may then announce these summaries to unrelated channels.

Fix

One additional condition: value.deliver !== false

if (!result.delivered && value.deliver !== false) {
  enqueueSystemEvent(...)
}

When deliver is explicitly false, the hook completes silently — no delivery, no system event. When deliver is true (default) or unset, behavior is unchanged.

The error catch path intentionally still surfaces errors to the main session regardless of deliver — silent failures are harder to debug than noisy ones. This asymmetry is documented with an inline comment.

Testing

  • Hooks with deliver: false → no system event injected ✅
  • Hooks with deliver: true (default) that fail to deliver → system event still fires ✅ (unchanged)
  • Hooks with deliver: true that succeed → no system event (unchanged, result.delivered is true) ✅
  • Hooks with deliver: false that throw → error system event still fires ✅ (intentional)

🤖 AI Disclosure

  • AI-assisted: This PR was written by Snippy, an OpenClaw agent running on Claude Sonnet/Opus at Customer.io. Snippy hit this bug while triaging Linear webhooks — hook completions with deliver: false were leaking summaries into unrelated Slack channels via the main session.
  • Testing: Lightly tested — verified code path via source reading and traced the issue through hooks.tsdelivery.tsrun.ts. No unit tests added (the existing test harness is integration-heavy).
  • Understanding: Yes — root cause was traced through the full dispatch chain from webhook receipt to system event injection.

Fixes #36325

When a hook mapping sets `deliver: false`, the delivery announcement is
correctly suppressed, but a system event ("Hook <name>: <summary>") is
still injected into the main session. This happens because the guard
only checks `!result.delivered` — which is always false when delivery
was never attempted.

Add `value.deliver !== false` to the guard so that hooks with explicit
`deliver: false` complete silently without notifying the main session.

Fixes openclaw#36325
@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: XS labels Mar 5, 2026
@greptile-apps

greptile-apps Bot commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a single guard (value.deliver !== false) to prevent enqueueSystemEvent from firing in src/gateway/server/hooks.ts when a hook mapping has deliver: false. The fix correctly addresses the reported issue where the main session received "Findings" summaries even after the caller had explicitly opted out of all delivery.

Key observations:

  • The happy-path fix is correct and minimal — the condition on line 87 now accurately reflects the intent
  • The inline comment (lines 83–86) clearly explains the rationale, which helps future maintainers understand the guard
  • Outstanding concern: The catch block (lines 95–103) still calls enqueueSystemEvent unconditionally, meaning an uncaught exception during hook execution will inject a system event into the main session even when deliver: false. This creates an asymmetry: the happy path respects the deliver flag, but the error path ignores it. Either the error path should receive the same guard, or the asymmetry should be documented with an explicit comment.

Confidence Score: 3/5

  • The happy-path fix is correct and safe, but an error-path asymmetry leaves the stated "silent" guarantee partially unmet for deliver: false.
  • The core fix (adding value.deliver !== false guard on line 87) is sound and directly solves the reported bug. However, the error path (lines 95–103) still unconditionally calls enqueueSystemEvent, violating the PR's explicit claim that hooks with deliver: false should "complete silently — no delivery, no system event." This behavioral inconsistency is a real gap, not merely a style concern. The error path either needs the same guard applied (1-2 lines), or should be documented as intentionally always surfacing errors (1-2 lines of comment). Without resolution, the stated behavior is incomplete.
  • src/gateway/server/hooks.ts — the error path should either be guarded with value.deliver !== false or documented as intentionally exempt from the silent-failure guarantee.

Comments Outside Diff (1)

  1. src/gateway/server/hooks.ts, line 95-103 (link)

    The catch block (lines 95–103) still injects a system event when deliver: false.

    The PR description states that hooks with deliver: false should result in "no system event injected," but the error path unconditionally calls enqueueSystemEvent regardless of the value.deliver setting. If an exception is thrown during hook execution (e.g., the isolated agent throws), a Hook <name> (error): ... system event will still be injected into the main session even when the caller explicitly opted out.

    Suggested fix: Either apply the same value.deliver !== false guard to the error path (line 97), or add an explicit comment explaining that errors are always surfaced regardless of the deliver setting, so future readers understand whether this asymmetry is intentional.

Last reviewed commit: 6d353de

The error path intentionally always surfaces to the main session even
when deliver is false — silent hook failures are harder to debug.
Add a comment making this asymmetry explicit per review feedback.
@cioclawcode

Copy link
Copy Markdown
Author

Good catch on the error-path asymmetry. I chose to keep errors always surfaced — if a hook with deliver: false crashes silently, you'd never know something is broken. Added a comment in 001b31f making the intentional asymmetry explicit.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Apr 17, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

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

Labels

gateway Gateway runtime size: XS stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hook deliver: false still injects system event into main session

2 participants