Phone hit kit: pin the className expression, not its source text #140

Merged
void merged 2 commits from void/phone-hit-kit-strict into dev 2026-11-13 08:28:36 +00:00
Member

Tightens the PhoneHit class pin in src/app/phoneHitTestKit.ts. The class reader now parses with the TypeScript compiler API (TSX): className must appear once, with no JSX spread after it, and be the bare PhoneHit* identifier (imported unaliased from styles/PhoneHit.css), a classNames/clsx/cx call with it as a direct argument, or a template with it as a direct span. Everything else reads as no class: string literals, conditionals, object keys, nested templates, typeof, assignment, comma, arrow, member access, duplicate className.

want in expectPhoneHitClasses is (string|null)[]: null means the button must carry no PhoneHit class.

Soul (two rounds) falsified the regex reader; the AST reader held against its attack harness and 15 mutants. Known gaps: an inner-scope shadowing binding next to the real import, import type; drawnPx/sizeProp still read tag text with regex.

Nothing deployed.

🤖 Generated with Claude Code

Tightens the PhoneHit class pin in src/app/phoneHitTestKit.ts. The class reader now parses with the TypeScript compiler API (TSX): className must appear once, with no JSX spread after it, and be the bare PhoneHit* identifier (imported unaliased from styles/PhoneHit.css), a classNames/clsx/cx call with it as a direct argument, or a template with it as a direct span. Everything else reads as no class: string literals, conditionals, object keys, nested templates, typeof, assignment, comma, arrow, member access, duplicate className. `want` in expectPhoneHitClasses is `(string|null)[]`: null means the button must carry no PhoneHit class. Soul (two rounds) falsified the regex reader; the AST reader held against its attack harness and 15 mutants. Known gaps: an inner-scope shadowing binding next to the real import, `import type`; drawnPx/sizeProp still read tag text with regex. Nothing deployed. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Phone hit kit: read the className expression, not its source text
Some checks failed
Build pull request / Build pull request (pull_request) Has been cancelled
d13cbc9b2e
A PhoneHit name inside a string, built by concatenation, behind ?:/&&/||/??, or
followed by a props spread that can override className no longer satisfies the pin.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Phone hit kit: read IconButton className off the TypeScript AST
All checks were successful
Build pull request / Build pull request (pull_request) Successful in 3m53s
4eaa6f9c55
className must appear once, with no spread after it, as the imported PhoneHit*
identifier bare, a classNames/clsx/cx direct argument, or a template span, and
the identifier must occur nowhere else in the expression. Tag enumeration uses
the same AST. expectPhoneHitClasses takes (string|null)[] (null = no class), as
the phone-hit-pages branch does, and is exercised by a test on a temp source.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
void merged commit 0f7faa902c into dev 2026-11-13 08:28:36 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/Ratatoskr!140
No description provided.