fix(hooks): suppress silent shared-hook fallback while preserving error surfacing#1502
Open
BingqingLyu wants to merge 7 commits into
Open
fix(hooks): suppress silent shared-hook fallback while preserving error surfacing#1502BingqingLyu wants to merge 7 commits into
BingqingLyu wants to merge 7 commits into
Conversation
…or surfacing The shared-hook fallback in dispatchAgentHook previously keyed off !result.delivered alone to decide whether to inject a system event into the main session. This conflates outward delivery state with main-session announcement policy, causing silent/no-op hooks (deliver:false) and delivery-attempted hooks to leak fallback summaries into main. Replace the single-boolean gate with a compatibility-bridge helper (shouldAnnounceHookResultToMain) that respects: - result.status !== "ok" → always surface errors (even if announceToMain is false — errors override explicit suppression) - result.announceToMain (explicit policy, forward-compatible) - value.deliver === false → silent on success - result.delivered → no duplicate - result.deliveryAttempted → no fallback for async-ack paths Also fix the generic fallback label (both success and catch paths) so default name "Hook" no longer renders as "Hook Hook".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes openclaw#55704
Summary
This PR fixes the shared-hook fallback seam in
dispatchAgentHook.Today, successful hook outcomes can still fall back into the main session based on
!result.delivered, which is too coarse for shared hooks. In practice this can leak silent/no-op hook work into the main session even when the hook lane was intended to stay quiet.This change replaces the old one-bit success-path check with a small compatibility bridge that:
deliver:falseshared hooks silentstatus:"error"resultsIt also cleans up the generic fallback label so default hook names no longer render as
Hook Hook.Why
This is a broader hooks-local generalization of the narrower
deliver:falseslice tracked in openclaw#36325.Related lineage:
NO_REPLYhook path did not setdelivered:truedeliver: falsestill injects system event into main session openclaw/openclaw#36325 - open narrowdeliver:falseleakThis PR also addresses the review concern on openclaw#49234: the narrow
value.deliver !== falseguard can hide real non-throw hook failures. This patch preserves error observability by always surfacingstatus !== "ok"results.What changed
Production code
shouldAnnounceHookResultToMain(...)insrc/gateway/server/hooks.tsif (!result.delivered)fallback gate with a compatibility-bridge decision:result.status !== "ok"-> always surface (errors override everything, including explicitannounceToMain: false)announceToMainpolicy can win when presentdeliver:falsehooks stay silentresult.delivered === true-> no duplicate fallbackresult.deliveryAttempted === true-> no fallbackformatHookPrefix(...)to fix theHook Hooklabel in both success and catch pathsannounceToMain?: booleanas a forward-compatible field onRunCronAgentTurnResultwhile preserving upstreamdelivery?: CronDeliveryTraceTests
Added 8 targeted gateway hook tests covering:
deliver:falsesuccess via direct/hooks/agent-> no main-session fallbackdeliver:falsesuccess via mapped hook (Gmail normalizer pattern) -> no main-session fallbackdeliver:falsenon-throwstatus:"error"-> still surfacesdeliveryAttempted:true+delivered:false-> no duplicate fallbackannounceToMain:true-> fallback still works when requestedannounceToMain:false+ narration/trailingNO_REPLY-> suppressedannounceToMain:false+status:"error"-> error still surfaces (documents the override)Hook: ...notHook Hook: ...Tests use a deterministic async flush helper (
flushHookDispatch) instead of fixed-delaysetTimeoutsleeps for negative assertions.Rebase refresh
Refreshed onto current
mainon 2026-04-23. Thesrc/cron/isolated-agent/run.types.tsconflict was additive: the rebased branch keeps bothannounceToMain?: booleanand upstreamdelivery?: CronDeliveryTrace.Test plan
Passed locally after the rebase:
Also attempted
pnpm checklocally. It passed prod typecheck, lint, conflict-marker, import-cycle, and related guards, then failed inscripts/check-no-runtime-action-load-config.mjson this Windows workspace because the guard constructedH:\H:\Code\OpenClaw\openclaw\extensions. CI is rerunning on the force-pushed head.