Skip to content

fix(acceptance): match field names by \p{ID_Continue} boundary, not raw substring#201

Open
agjs wants to merge 1 commit into
mainfrom
fix/field-mention-word-boundary
Open

fix(acceptance): match field names by \p{ID_Continue} boundary, not raw substring#201
agjs wants to merge 1 commit into
mainfrom
fix/field-mention-word-boundary

Conversation

@agjs

@agjs agjs commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Found by a proactive bug-hunt. fieldIsMentioned (acceptance-spec.ts) associated a field with a plan constraint via constraintLower.includes(field.name.toLowerCase()) — a raw substring match. A short field name is then matched by any longer word that merely contains it (id inside valid, age inside manage), fabricating a spurious negative acceptance test case for a field the constraint never mentions.

Fix: guard the match with lookarounds over \p{ID_Continue} — the exact Unicode identifier-continue property — for both the raw and humanized forms. A match is rejected only when glued to an adjacent identifier char, killing the substring case across ASCII, non-ASCII (âge in préâge), combining marks (age+U+0301), and Other_ID_Continue glue (_, digits, ZWJ), while still matching names that begin/end with a non-identifier char (price$, $ref) or are non-ASCII whole words (âge). \b/\w stay ASCII-only under /u.

fieldIsMentioned is now exported and unit-tested — positive, negative (id-in-valid, age-in-manage), and full boundary coverage (empirically verified \p{ID_Continue} membership incl. ZWJ/ZWNJ/middle-dot in Bun).

Panel: PASS (4/4). Existing acceptance-spec suite unaffected; full suite green; typecheck + lint clean.

`fieldIsMentioned` (acceptance-spec.ts) associated a field with a plan constraint via
`constraintLower.includes(field.name.toLowerCase())` — a raw SUBSTRING match. A short field
name is then matched by any longer word that merely contains it: `id` inside `valid`, `age`
inside `manage`, so a constraint like "must be a valid email" wrongly reports field `id` as
mentioned and fabricates a spurious negative acceptance case for it.

Match on WORD BOUNDARIES instead (`\b<name>\b`, escaped), for both the raw and humanized
forms. Genuine whole-word mentions (`email` in "a valid email", the humanized "first name"
of `firstName`) still match; substring false positives no longer do.

`fieldIsMentioned` is now exported and unit-tested (positive: email / name / humanized
firstName; negative: id-in-valid, age-in-manage, and an unrelated word). Existing
acceptance-spec suite unaffected (12 pass); typecheck + lint clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant