test: add adversarial unit tests for hooks system#8
Merged
mattapperson merged 1 commit intofeat/hooks-managerfrom Apr 3, 2026
Merged
test: add adversarial unit tests for hooks system#8mattapperson merged 1 commit intofeat/hooks-managerfrom
mattapperson merged 1 commit intofeat/hooks-managerfrom
Conversation
81 edge-case tests covering handler chain execution, manager lifecycle, tool matchers, resolver normalization, and async output detection. Surfaces real issues: filter throws bypass error handling, global RegExp stateful .test(), and function matcher lacking boolean coercion.
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.
Summary
isAsyncOutputtype guardFindings surfaced
These tests document (not fix) real edge cases in the current implementation:
matchesTool— no boolean coercion: Function matchers returning truthy non-booleans (e.g.1,null) pass the raw value through instead oftrue/false. Works with truthiness checks but fails strict=== truecomparisons.matchesTool— global RegExp stateful.test(): Using a/gRegExp as a matcher causes alternating match/no-match results due tolastIndexstate. The test documents this footgun.executeHandlerChain— filter throws bypass error handling: Throwing filters propagate unhandled (they execute outside thetryblock), unlike throwing handlers which are caught in non-strict mode.Re-entrant emit: A handler that registers a new handler mid-emit causes the new handler to execute in the same chain (since the for-loop reads
entries.lengthdynamically).block: ""(empty string) triggers short-circuit:isBlockTriggeredcheckstypeof value === 'string', so empty strings count as blocks — potentially surprising.Test files
hooks-emit-adversarial.test.tshooks-manager-adversarial.test.tshooks-matchers-adversarial.test.tshooks-resolve-adversarial.test.tshooks-types-adversarial.test.tsTest plan
pnpm build) passes