Skip to content

fix(parser-react): decode HTML entities in rendered-text extraction (6F.10, A16)#52

Merged
officialCodeWork merged 1 commit into
developmentfrom
build/phase-6f/step-6f.10-html-entities
Jul 15, 2026
Merged

fix(parser-react): decode HTML entities in rendered-text extraction (6F.10, A16)#52
officialCodeWork merged 1 commit into
developmentfrom
build/phase-6f/step-6f.10-html-entities

Conversation

@officialCodeWork

Copy link
Copy Markdown
Owner

Step 6F.10 — HTML-entity rendered-text noise (failure mode A16, new)

Self-found validating 0.4.0 on Grafana's frontend. Rendered text that is an HTML entity —  , ", >, ", ·, <, › — survived into renderedText as a junk token ( →"nbsp", "→"34", >→"gt"), creating spurious matches. Worse, a numeric entity like "→"34" let a gibberish query that shares those digits ("zzqwxnomatch12345") match. On the Grafana graph there were 26  , 4 ", plus single "/>/</·/›.

Fix — decode in extraction, not scoring

New packages/parser-react/src/entities.tsdecodeEntities(text) resolves the HTML entities React decodes at render time:

  • Numeric decimal (") and hex (") generically, with surrogate/range guards.
  • Named from a curated map (markup, whitespace, punctuation, symbols, currency, accented Latin-1). Unknown names are left verbatim — React renders &foobar; literally, so we never guess.

extractRenderedText decodes JSX text and quoted attribute values (the two surfaces React HTML-decodes); JS string/template literals stay untouched because React renders {"&nbsp;"} literally. Decoded entities become the character React actually renders, which the normalizer then strips: &nbsp;→space→dropped, &gt;/&#34;/&middot;→punctuation that normalizes to empty. So an entity-only component yields no discriminating match target — verified: EntitySpacer.renderedText = ["\"", ">", "·", "<", "›"], zero alphanumeric tokens.

The core isLowSignal/hasMatchSignal guards (A14/A15) remain the backstop; the primary fix lives in extraction as the tracker specified.

Tests

  • Fixture eval/fixtures/a16-html-entities — entity-only EntitySpacer + real QuotaNotice. Asserts: numeric-entity token 34, named-entity token nbsp, and digit-sharing gibberish zzqwxnomatch12345 (which pre-fix matched via &#34;→"34") all decline no-signal; the real query lands on QuotaNotice and isn't poisoned by the digit-sharing gibberish.
  • 7 new parser-react unit tests (4 decode + 3 fixture integration), 136 total.

Verification

  • pnpm eval304 pass · 0 fail · 0 xfail · 0 unexpected-pass, gate OK, all metrics 1.000.
  • pnpm test → all packages green (core 59, parser-react 136, agent-sdk 19, mcp 6, cli 5, vision 3).
  • pnpm -r typecheck → clean.

TRACKER 6F.10 marked done; docs/failure-modes.md A16 already documented. Only 6F.6 (test-coverage, data-blocked) remains in phase 6F.

🤖 Generated with Claude Code

…6F.10, A16)

Self-found validating 0.4.0 on Grafana's frontend: rendered text that is an
HTML entity (`&nbsp;`, `&#34;`, `&gt;`, `&quot;`, `&middot;`, `&lt;`,
`&rsaquo;`) survived into `renderedText` as a junk token (`nbsp`, `34`, `gt`),
creating spurious matches — and a numeric entity like `&#34;`→"34" let a
gibberish query sharing those digits ("zzqwxnomatch12345") match.

New `entities.ts` decodes the HTML entities React resolves at render time
(numeric decimal/hex generically, named entities from a curated map; unknown
names left verbatim, matching React). `extractRenderedText` decodes JSX text
and quoted attribute values — the surfaces React HTML-decodes — while JS
string/template literals stay untouched. Decoded entities become the character
React renders, which the normalizer strips as punctuation/whitespace, so an
entity-only component yields no discriminating match target.

New fixture `a16-html-entities`: the entity-only component produces no target,
and the named-entity token, numeric-entity token, and digit-sharing gibberish
all decline `no-signal` while a real query still lands on the real component.
7 new parser-react tests (136 total); eval 304/0/0/0, gate OK, metrics 1.000.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@officialCodeWork
officialCodeWork merged commit 0c58a85 into development Jul 15, 2026
1 check passed
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.

2 participants