You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#3064 made the inventory check symmetric and #3646 kept it globally enforced. Both fixed the plumbing — whether the two halves agree and whether the gate runs. This is the third gap in the same file, and it is semantic: what the gate is able to detect at all.
The severity model only recognizes raw interactive primitives:
1. A hand-rolled replacement for a shipped Astryx component scores aligned. It renders no raw control, so it is indistinguishable from a genuinely aligned file — and the inventory then certifies it. A surface added this way reads | … | none | aligned — no raw controls; no Astryx JSX usage | aligned |, moving the totals from aligned 212 to aligned 213. The rule as stated in docs/astryx-alignment-inventory.md:36 is "Raw <button> / <input> / <select> with Astryx twin" — it covers wrong primitive, not redundant component.
2. ASTRYX_COMPONENTS is a hand-maintained second representation of what Astryx ships. It holds 47 names; @astryxdesign/core/dist has 107 component directories. Timestamp is absent, so it appears 0 times across all 214 rows even though packages/ui/src/chat-turn.tsx imports and renders it. ChatMessage, ChatMessageMetadata, and Thumbnail are invisible the same way — so removing an Astryx component from a file leaves its row byte-identical, which is how this surfaced.
Desired outcome
Derive the known-component set from @astryxdesign/core instead of maintaining a second list, so the "Astryx used" column is a true record and design-system additions are picked up without a manual edit. This is the same root cause Astryx surface inventory check is one-directional and not wired into CI #3064 identified — a generated artifact whose input is hand-maintained drifts in whichever half the author forgets.
Add a severity tier for "re-implements a component Astryx already provides", so swapping an Astryx component for a local equivalent is visible in review.
Problem
#3064 made the inventory check symmetric and #3646 kept it globally enforced. Both fixed the plumbing — whether the two halves agree and whether the gate runs. This is the third gap in the same file, and it is semantic: what the gate is able to detect at all.
The severity model only recognizes raw interactive primitives:
1. A hand-rolled replacement for a shipped Astryx component scores
aligned. It renders no raw control, so it is indistinguishable from a genuinely aligned file — and the inventory then certifies it. A surface added this way reads| … | none | aligned — no raw controls; no Astryx JSX usage | aligned |, moving the totals fromaligned 212toaligned 213. The rule as stated indocs/astryx-alignment-inventory.md:36is "Raw<button>/<input>/<select>with Astryx twin" — it covers wrong primitive, not redundant component.2.
ASTRYX_COMPONENTSis a hand-maintained second representation of what Astryx ships. It holds 47 names;@astryxdesign/core/disthas 107 component directories.Timestampis absent, so it appears 0 times across all 214 rows even thoughpackages/ui/src/chat-turn.tsximports and renders it.ChatMessage,ChatMessageMetadata, andThumbnailare invisible the same way — so removing an Astryx component from a file leaves its row byte-identical, which is how this surfaced.Desired outcome
@astryxdesign/coreinstead of maintaining a second list, so the "Astryx used" column is a true record and design-system additions are picked up without a manual edit. This is the same root cause Astryx surface inventory check is one-directional and not wired into CI #3064 identified — a generated artifact whose input is hand-maintained drifts in whichever half the author forgets.Found while reviewing #3681.
AI use: Claude Code assisted with source and issue investigation; the analysis and conclusions are my own.