From 8f2ef9dc9bb493bdd22fffeaaa39ea092b49f611 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Wed, 1 Jul 2026 15:58:56 +0800 Subject: [PATCH] docs(hook-protocol): matcher's invalid-regex handling is SILENT, not bridge-logged MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review noted the module docs promised an invalid regex is "logged by the bridge", but matchesMatcher only returns `false` — callers cannot distinguish a genuine non-match from a compile failure, so a typo'd pattern silently disables that matcher with no warning. Both bridges call matchesMatcher directly, so no log happens anywhere. Correct the docs to state the silence explicitly; surfacing bad config would need a diagnostic-returning variant or parse-time validation, marked TODO(matcher-diagnostics). No behavior change. --- packages/hooks/hook-protocol/src/matcher.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/hooks/hook-protocol/src/matcher.ts b/packages/hooks/hook-protocol/src/matcher.ts index 4ce3e4b62d..ee1dd324b3 100644 --- a/packages/hooks/hook-protocol/src/matcher.ts +++ b/packages/hooks/hook-protocol/src/matcher.ts @@ -9,8 +9,11 @@ * - `codex`: every pattern is an unanchored regex (no literal fast path). * * Both treat an absent / empty / `'*'` pattern as match-all, and both treat an - * invalid regex as a non-match (the bridge logs it; a broken matcher must not - * throw into the loop). + * invalid regex as a non-match: a broken matcher selects nothing rather than + * throwing into the loop. This is SILENT — the boolean return cannot distinguish + * "did not match" from "failed to compile", so a typo'd pattern (e.g. `[`) + * quietly disables that matcher with no warning. Surfacing bad config would need + * a diagnostic-returning variant or parse-time validation (`TODO(matcher-diagnostics)`). * * @module @deepseek-ai/dsh-hook-protocol/matcher */ @@ -43,7 +46,9 @@ export function matchesMatcher(matcher: string | undefined, query: string, mode: return new RegExp(pattern).test(query) } catch { // Invalid regex: a broken matcher selects nothing rather than throwing into - // the agent loop. The bridge is responsible for surfacing the bad config. + // the agent loop. This is silent — callers get `false`, indistinguishable + // from a genuine non-match, so a typo'd pattern quietly disables the matcher. + // Surfacing it needs a diagnostic-returning variant (TODO(matcher-diagnostics)). return false } }