fix(icons): correct two retired lucide spellings on registration icon meta - #7590
Merged
Merged
Conversation
… meta `ui:page` declared `icon: 'Layout'` and `record:alert` declared `icon: 'AlertTriangle'`. lucide retires a spelling by dropping it from the runtime `icons` record while keeping the deprecated named export, so both names still import and still type-check while resolving to nothing through any resolver that reads that record. Behaviour-neutral by identity, measured against the installed lucide 1.31.0: `Layout === icons['PanelsTopLeft']` and `AlertTriangle === icons['TriangleAlert']` are both true, so the repair cannot substitute one glyph for another. The kebab spellings are the only ones live on BOTH surfaces: `PanelsTopLeft` and `TriangleAlert` are record keys but are absent from the dynamic `iconNames` list, which is kebab-case only. Nothing is retired and no gate is extended. Part of #5936 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMrWaQw3XS5DxTHxp4yRyC
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-project-manager
marked this pull request as ready for review
September 4, 2026 03:21
os-project-manager
deleted the
claude/issue-5936-retired-icon-spellings
branch
September 4, 2026 03:36
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.
Part of #5936
Clause-②: no — this diff changes two authored VALUES and reaches no declaration. No key is declared or removed, no accept set moves, no gate is extended. Determined from the diff itself: two lines, both the right-hand side of an existing
icon:property inside an existing registration meta object.What changed
Two component registrations declared lucide spellings that lucide has retired:
packages/components/src/renderers/layout/page.tsx(ui:page)icon: 'Layout'icon: 'panels-top-left'packages/plugin-detail/src/index.tsx(record:alert)icon: 'AlertTriangle'icon: 'triangle-alert'Plus one changeset. Nothing else.
git diff --statis2 files changed, 2 insertions(+), 2 deletions(-)before the changeset.The load-bearing measurement: behaviour-neutral BY IDENTITY
lucide retires a spelling by dropping it from the runtime
iconsrecord while keeping the deprecated named export pointing at the very same glyph object. So the repair cannot substitute one glyph for another — that is what makes it landable without a contract review, and it is measured against the installed lucide 1.31.0 rather than asserted:Membership, resolved through the seam's own tokeniser (
renderers/action/resolve-icon.ts):Every zero-answering query above is printed beside a control in the same query shape that fires.
Neutral in all three resolution worlds, which is why it is correct whichever way the open half of #5936 is decided:
null, new resolves to that shared object; a repair, never a substitution;iconNames, 2025 names, retired aliases included) — both spellings already resolved, to the same glyph;Why the kebab spellings. They are the only ones live on BOTH surfaces. Measured:
iconNamesis kebab-case only, so a PascalCase record key is absent from it. The card's prescribed spellings are therefore also the strictly safer ones.The gate reading, and an honest correction
scripts/check-lucide-icon-record-names.mjsis green both before and after, with identical counters (182 judged names). It does not go red on the old spellings, because it deliberately does not judge a component registration'siconmeta — which is exactly what #5936 says, and this PR does not change it.That green is a real reading and not a dead instrument, proven two ways in the same run shape:
1. Lit control — the same retired spelling on a site the gate DOES judge. Put
'Layout'into the anchorediconMapinpackages/plugin-view/src/ObjectView.tsx:The gate derives
panels-top-leftby identity, independently corroborating the measurement above.2. Ablation — the retired spellings put back at the two sites in this PR. Gate exit
0, and every counter identical to the repaired tree:authored icon names judged: 148,anchored map entries judged: 34,182total.Both ablations ran under
trap ... EXIT INT TERMwith absolute paths. Each mutation was proven on disk before any result was read (anchored fixed-string counts plusgit hash-objectdiffering from the HEAD blob), and each restore was proven BY STATE —git diff HEADempty AND on-disk blob equal to the HEAD blob, restored viagit checkout HEAD -- ABSOLUTE_PATH. The mutated blobs round-tripped byte-exactly to the pre-repair blobs (0c14df03c,b9451e00f), so the ablation is provably the exact inverse of the repair.Verification
Gate union re-run after the final commit, at
fadfd6e06, tree clean:Every exit code captured by redirect-then-read, never through a pipe, and each verdict line above is the gate's own.
pnpm exec vitest run packages/components/ packages/plugin-detail/from the repo root (the package-scoped form is refused byscripts/vitest-invocation-guard.mjs): 360 test files passed, 3333 tests passed, 0 failures. Both changed packages in full, not a subset.packages/componentsandpackages/plugin-detail, bothtsc --noEmit && tsc -p tsconfig.test.json, bothDone.Scope: 2 of 47 workspace projectsconfirms the filter matched rather than silently matching nothing.dist.patchfor the two packages was written instead, because the "no consumer anywhere" reading is Locate the consumer of a registration'siconmeta before extending the icon gate to it — zero read points in objectui AND objectstack, so two suspect spellings stay undetermined #5936's ADR-0049 retirement PREMISE and not a proof of absence, so declaring "releases nothing" would lean on exactly the premise this slice is fenced away from.Declared narrowing (one)
Lint.
eslintwas run on the two changed files rather than repo-wide: 2 files linted (count from--format json), 0 errors, 42 warnings, all pre-existing and none on the changed lines. The three things that make this a measurement rather than a skipped run:files: ['**/*.{ts,tsx}']ineslint.config.js), not guessed — and eslint's own membership answer was exercised in both directions (--print-configresolves 117 rules for each changed file; anode_modulespath comes backFile ignored by default);--format json;tseslint.configs.recommended, notrecommendedTypeChecked, and declares noproject/projectService. Every rule is therefore per-file, so a string-literal change inside these two files cannot move the verdict of any untouched file. A repo-wide run could not have caught anything this run did not.CI runs the full farm regardless.
What is deliberately NOT here
#5936 has a second half that this PR does not touch and must not be read as having settled:
iconmeta (scope item 3) — the relayed reading found no record-reading consumer to justify it.iconmeta should itself be retired (scope item 4) is ADR-0049 territory and stays with the maintainer. The card stays open for it, which is why this isPart of #5936and notFixes.🤖 Generated with Claude Code
Generated by Claude Code
Generated by Claude Code