fix(hookify): replace hand-rolled YAML parser + fix new_text field on Write#54873
Open
adelaidasofia wants to merge 1 commit intoanthropics:mainfrom
Open
fix(hookify): replace hand-rolled YAML parser + fix new_text field on Write#54873adelaidasofia wants to merge 1 commit intoanthropics:mainfrom
adelaidasofia wants to merge 1 commit intoanthropics:mainfrom
Conversation
…on Write
Two bugs discovered via a full regression harness (39 test cases):
1. config_loader: Hand-rolled YAML parser double-escaped backslashes
Pattern `"\\d{8}"` in double-quoted YAML should load as `\d{8}` (regex
digit). The custom parser stored it as `\\d{8}` (literal backslash+d),
silently breaking any rule that used `\d`, `\w`, `\s`, `\b`, or `\[`
in its pattern. Replaced with `yaml.safe_load` + a YAMLError guard.
Side-effect: unquoted patterns starting with `[` or `\` (e.g.
`pattern: [A-Z].*` or `pattern: \[owner::]`) now correctly raise a
YAMLError. Rule authors must single-quote such patterns, which is
standard YAML practice and is now documented in the authoring guide.
2. rule_engine: `new_text` field on Write tool returned empty string
`_extract_field('new_text', 'Write', tool_input)` called
`tool_input.get('new_string', '')` — but Write uses `content`, not
`new_string`. Any rule using `field: new_text` on a Write event
silently never fired. Fixed to fall back to `content` when `new_string`
is absent, matching the existing behaviour of `field: content`.
This was referenced May 1, 2026
4 tasks
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
Two silent bugs discovered via a full regression harness (39 test cases across all hookify rules):
Bug 1 —
config_loader.py: hand-rolled YAML parser double-escapes backslashesThe custom parser in
extract_frontmatterstripped surrounding quotes but did not process YAML escape sequences. In double-quoted YAML,\\dmeans one backslash + d (i.e.\d, a regex digit class). The old parser stored the raw characters between the quotes — two backslashes + d — so the compiled regex pattern matched a literal\dstring instead of a digit.Impact: Any hookify rule using
\d,\w,\s,\b, or\[in a double-quotedpattern:value silently never fired. The rule loaded without error; the condition just always returned False.Fix: Replace the 85-line hand-rolled parser with
yaml.safe_load+ aYAMLErrorguard. Four lines.Side-effect / authoring note: Unquoted YAML patterns starting with
[(e.g.pattern: [A-Z].*) are now correctly rejected as YAML flow sequences — this was always invalid YAML that the old parser accidentally tolerated. Rule authors must single-quote such patterns:pattern: '[A-Z].*'. This is standard YAML practice.Bug 2 —
rule_engine.py:new_textfield on Write returns empty string_extract_field('new_text', 'Write', tool_input)calledtool_input.get('new_string', ''). The Write tool stores its content undercontent, notnew_string(that's Edit). So any rule withfield: new_texton afileevent silently never fired when the tool was Write.Fix: One-line change — fall back to
contentwhennew_stringis absent, matching the existing behaviour offield: content.Test plan
session-close-sonnet-check(uses\d{8}pattern) — was silently broken, now fires correctlywarn-exclamation-marks(uses[A-Z]pattern, single-quoted after authoring fix) — fires correctlyblock-em-dash,warn-external-prose-humanizer— verified with Write tool usingfield: new_text🤖 Generated with Claude Code