fix(createTokens): follow a {alias} reached through a segment path#589
Merged
Conversation
The segment-path branch of resolve() assigned a terminal value to the
result without following a trailing {alias}, so a dotted-segment lookup
landing on an alias string returned the raw '{alias}' instead of its
resolved value. The leaf-value branch already re-resolved terminal
aliases; the segment branch now mirrors it, reusing the visited set so
circular detection still holds.
Surfaces through useTheme, which resolves theme colors through a
flat: true token table: a palette entry that is itself an alias,
referenced by a theme via a dotted alias, previously produced an
unresolved {alias} (dropped by the CSS brace guard, or leaked literally
to consumers reading theme.colors directly).
Ref #566 (Group A, item #1)
Regression tests for the #566 fix: a {alias} reached through a dotted segment lookup must be followed (single hop and multi-hop chain), and a circular reference reached that way must be detected rather than leaking a raw {alias}. All three fail against the pre-fix segment branch.
johnleider
marked this pull request as ready for review
July 14, 2026 23:29
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.
Extracts the RB-5 root fix from #566 (Group A, item #1) as a minimal, RC-scoped patch. Only the segment-path alias correctness is here; #566's other three changes (direct-
TokenAlias-literal semantics, outer-key caching,resolve<T>type param) stay in that PR for post-RC.The bug
resolve()'s segment-path branch assigned the terminal value toresultwithout following a trailing{alias}. A dotted-segment lookup that lands on an alias string returned the raw'{alias}'instead of its resolved value. The leaf-value branch already re-resolved terminal aliases; the segment branch didn't.Why it matters for RC
useThemeresolves theme colors through aflat: truetoken table, where nested groups are stored whole and addressed by segment. A palette entry that is itself an alias, referenced by a theme via a dotted alias, produced an unresolved{alias}:ThemeAdapter.generate()'sUNSAFE_CSSguard rejects any value containing{/}, so the CSS variable went missing (wrong/unset color).theme.colors.value(inline:style, canvas, handing colors to another lib) it leaked the literal{alias}string.useThemeis markedstable, so this is a frozen-surface correctness bug. Fix is at the single source (createTokens.resolve); nouseThemechange needed.The fix
Mirror the leaf branch's terminal alias-follow into the segment branch, reusing the
visitedset so circular detection still holds:Tests
Three regression cases under
segment-path terminal alias (#566)— single-hop resolution, multi-hop chain, and a circular reference reached through a segment path. All three fail against the pre-fix branch (return raw{alias}; the circular case bypasses detection entirely) and pass with the fix.Verification
createTokensunit suite 253/253;useTheme/useFeatures/useLocale/usePermissions304/304pnpm typecheckclean (0/paper/genesis);knip+sherifcleanRelationship to open PRs
resolve()refactor; if fix(createTokens): follow segment-path aliases, return direct TokenAlias literals, cache chained resolves #566 lands first, close this. If this lands first, fix(createTokens): follow segment-path aliases, return direct TokenAlias literals, cache chained resolves #566 rebases (its unified branch subsumes the change).