fix(webkit): [ENG-47001] close the token-check guardrail gap and canonicalize v4 syntax - #849
Merged
isaque-bock-azion merged 21 commits intoAug 10, 2026
Merged
Conversation
…-check guardrails typography-raw-length, leading-raw, tracking-raw, font-family-raw, animate-arbitrary and motion-hardcoded keyed on a literal '[', so the canonical v4 paren syntax (duration-(--x), animate-(--x), text-(length:--x), font-(family-name:--x), leading-(--x), tracking-(--x)) walked straight through the typography / motion / animation gates. Each now matches both spellings. Regression tests pin both forms and assert the widened guards stay silent on a plain canonical token (bg-(--primary)).
…tax repo-wide Decision A: standardize on Tailwind v4's paren shorthand for design-token values (bg-(--primary), text-(length:--text-body-md), z-1), so IntelliSense stops flagging every styled line with suggestCanonicalClasses. The two spellings compile to byte-identical CSS. A codemod (scripts/codemods/canonicalize-tw-v4.mjs) rewrites the three safe families across packages/webkit/src, apps/storybook, .specs, packages/webkit/docs, .claude/**, cli-templates and packages/theme: A prop-[var(--x)] -> prop-(--x) (2470) B prop-[type:var(--x)] -> prop-(type:--x) (29) E z-[<int>] -> z-<int> (51) It provably leaves two families bracketed, because the paren form emits no CSS for them (silent style loss, no build or lint error): C custom-property declarations [--x:var(--y)] D expression values / var-with-fallback w-[calc(var(--a)*2)], bg-[var(--x,var(--y))] canonicalize-tw-v4.test.mjs pins the A/B/E conversions and the C/D skips. The decision is recorded in .claude/rules/styling.md and mirrored into the shipped cli-templates styling rule; DESIGN.md and the scaffolder examples teach the paren form. apps/icons-gallery (Tailwind v3) is untouched.
The canonicalization sweep is applied and committed, so the one-shot codemod (scripts/codemods/canonicalize-tw-v4.mjs) and its skip-proof test are no longer needed — the permanent protection is the token-check guardrail tests plus the CI visual baselines (which prove the A/B/E conversions are byte-identical). Also removes the explanatory comments from the guardrail tests.
…weep The canonicalization changed class-string lengths, so prettier re-wraps a few :class attributes and the token-check test. Formatting only — no behavior change.
isaque-bock-azion
force-pushed
the
feat/ENG-47001-canonical-tailwind-v4-syntax
branch
from
August 5, 2026 14:15
e3624ee to
1e4c351
Compare
Conflicts resolved by keeping main's semantics with the branch's canonical Tailwind v4 paren token syntax; flow-anchor's PORT_CLASS (new from main) canonicalized to match flow-node's.
isaque-bock-azion
force-pushed
the
feat/ENG-47001-canonical-tailwind-v4-syntax
branch
from
August 5, 2026 17:31
2274681 to
2f16087
Compare
Two spots merged in from main still used the bracket syntax for fallback-less var() tokens; convert them to the parenthesis shorthand the sweep standardizes on.
Conflicts from the calendar field-contract refactor resolved by keeping main's semantics with the branch's canonical Tailwind v4 paren token syntax; fallback-carrying forms stay in bracket notation.
isaque-bock-azion
force-pushed
the
feat/ENG-47001-canonical-tailwind-v4-syntax
branch
from
August 5, 2026 17:46
487a29b to
1ad0b35
Compare
… merges Merges f24330a/17f4244b kept the branch-side tab-view-item/list and panel shells, silently dropping main's Figma pill fix (#857) and the Panel max-h-full scroll bound (#835) while taking main's updated visual baselines — so the TabView snapshots failed CI. Restore main's semantics in the branch's canonical token syntax, and canonicalize the standalone story + spec line that came in bracketed.
Brings the Menu compound (#853); menu-item resolved keeping main's semantics in canonical token syntax, the retired menu-item spec deleted, the compound's new files canonicalized and the catalog regenerated.
isaque-bock-azion
marked this pull request as draft
August 6, 2026 14:32
… sweep The sweep canonicalized token syntax inside spec bodies without recomputing the checksum: frontmatter, which would make the enforce-spec-exists write-gate block every affected component after merge. Recomputed mechanically with the engine's own bodyChecksum() (.claude/hooks/_lib/spec.mjs), as suggested in review. 28 of the 63 resealed specs were already mismatched on origin/main (pre-existing, unrelated to this branch); the reseal heals those too. .specs/_template.md keeps its placeholder.
isaque-bock-azion
force-pushed
the
feat/ENG-47001-canonical-tailwind-v4-syntax
branch
from
August 10, 2026 12:57
e96a261 to
73993c7
Compare
isaque-bock-azion
marked this pull request as ready for review
August 10, 2026 13:07
guilherme-santana-azion
approved these changes
Aug 10, 2026
herbert-julio-azion
approved these changes
Aug 10, 2026
isaque-bock-azion
deleted the
feat/ENG-47001-canonical-tailwind-v4-syntax
branch
August 10, 2026 14:20
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.
ENG-47001 — canonicalize Tailwind v4 class syntax + close the token-check guardrail gap
Decision A (adopt the canonical syntax) — recorded in
.claude/rules/styling.mdand mirrored into the shippedcli-templatesstyling rule.The load-bearing fix — guardrails (ships regardless of the codemod)
Six token-checks keyed on a literal
[, so the canonical v4 paren spelling walked straight through the typography / motion / animation gates:typography-raw-lengthtext-(length:--text-…)leading-rawleading-(--…)tracking-rawtracking-(--…)font-family-rawfont-(family-name:--…)animate-arbitraryanimate-(--…)motion-hardcodedduration-(--…)Each now matches both spellings. Regression tests (
packages/webkit/test/eslint-plugin/token-checks.test.mjs) pin every paren form named in the acceptance criteria and assert the widened guards stay silent on a plain canonical token (bg-(--primary)).The sweep
Three families the real v4 compiler proves emit byte-identical CSS were rewritten across
packages/webkit/src,apps/storybook,.specs,packages/webkit/docs,.claude/**,cli-templates,packages/theme:prop-[var(--x)]→prop-(--x)prop-[type:var(--x)]→prop-(type:--x)z-[N]→z-NTwo families are left bracketed — the paren form emits no CSS for them (silent style loss, no build/lint error):
[--table-row-bg:var(--bg-surface)]w-[calc(var(--a)*2)],bg-[var(--x,var(--y))], gradients, box-shadowsThe rewrite was done with a one-time codemod (not retained in the tree): it only converted a bracket whose content is exactly
var(--token)(family A) ortype:var(--token)with a letter-leading type (family B), so C and D could not match by construction — verified at apply-time (no C/D var-bracket changed) and permanently backstopped by the CI visual baselines, since any C/D breakage would change the rendered CSS.Also
DESIGN.md,COMPONENT_REQUIREMENTS.md,component-scaffold, the rule set,.specs).apps/icons-gallery(Tailwind v3) untouched.Notes for the reviewer / follow-ups
node_modules, sowebkit:lint,type-check,storybook:build, the Vitest browser suite and visual baselines were not run locally — they run here. A/B/E compile byte-identically, so any baseline diff means the sweep broke something (the net for a C/D-style silent loss). The node guardrail suite is green:10/10.tailwindcss ^3.4.19audit: no root Tailwind config and no root/sub-package consumer under pnpm's strict isolation (icons-gallerydeclares its own v3) → stale. Not removed here because regeneratingpnpm-lock.yamlneeds pnpm; recommend a follow-up that removestailwindcss/@tailwindcss/typography/autoprefixerfrom the root and reinstalls.packages/theme/dist/v4/globals.cssis a generated artifact (do not editbanner); its one stale bracket-form comment regenerates on the nexttheme:build:tokens— the source (build-tokens.mjs) is already canonical.How to test
grep -rnE '\[(([a-z-]+):)?var\(--[A-Za-z0-9-]+\)\]|\bz-\[[0-9]+\]' packages/webkit/src apps/storybook .specspnpm storybook:devand spot-check a few components (Button, Switch, Sidebar, Breadcrumb): rendering must be identical tomain, since the paren and bracket spellings compile to byte-identical CSS. CI's visual baselines assert this for every story.