fix(hooks): reject non-ASCII lead-in text in SatisfactionCapture rating guards - #1703
Open
takanorinishida wants to merge 1 commit into
Open
Conversation
…ng guards
parseExplicitRating()'s two numeric-rating guards only rejected ASCII
descriptive text after a leading digit (e.g. "2/10 items done", "2 files
left"), so non-English prose fell through and got misread as a rating.
Observed in the wild: the Japanese prompt "2はあとで" ("item 2, later")
matched the generic rating pattern and was recorded as an explicit rating
of 2, triggering the low-rating capture path (rating < 5) and writing a
LEARNING/ALGORITHM synthesis note from a false signal. Same shape hits the
N/10 fraction parser ("2/10件 完了" → misread as 2/10).
Extend both guards to also reject when the trailing text starts with a
non-ASCII character. English prompts are unaffected — English descriptive
text after a digit is ASCII by construction, so the new branch never
fires for them; verified word-for-word against the pre-fix behavior with
an isolated LIFEOS_DIR probe harness (5 English cases identical, 2
Japanese false-positive cases now correctly rejected).
This was referenced Jul 30, 2026
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.
What's broken
parseExplicitRating()inhooks/SatisfactionCapture.hook.tshas two guards that reject a leading digit when it's followed by descriptive text (e.g. "2/10 items done" is correctly rejected as "not a rating"). Both guards only check ASCII character classes, so non-English descriptive text falls through and gets misread as an explicit rating.Observed in the wild on a non-English (Japanese) install: the prompt "2はあとで" ("item 2, later") matched the generic rating pattern and was recorded as an explicit rating of 2, which triggered the
rating < 5low-rating capture path and wrote a spuriousLEARNING/ALGORITHMsynthesis note from a false signal. The same shape hits the N/10 fraction parser ("2/10件 完了" → misread as a 2/10 rating).This isn't platform-specific — the hook has no macOS/Linux dependency — it affects any non-English (or more precisely, non-ASCII-script) prompt.
Fix
Two lines. Both guards now also reject when the trailing text starts with a non-ASCII character:
Why this doesn't change English behavior
The new branch only fires when the trailing text starts with a character outside
\x00-\x7F. English descriptive text after a digit is ASCII by construction, so the branch never fires for English prompts — verified below.Verification
Ran an isolated-
LIFEOS_DIRprobe harness (temp dir, no real ratings file touched) against both the pre-fix and post-fix hook, feeding the same 6 prompts to each:Before (bug reproduction):
After:
All 4 English cases produce byte-identical output before/after. Only the 2 non-ASCII false-positive cases change, and they change from "silently corrupts a learning signal" to "correctly ignored."
Every deletion in this diff is a line replaced by an extended version of itself (same early-return, wider condition) — no behavior removed, only a false-positive path closed.
🤖 Generated with Claude Code