feat(limitless-mcp): complete the lint catalog — 57/57 detectors#35
Merged
Conversation
…(51→53/57)
Both opt-in (defaultOn:false), so the default lint stays precise:
- default-variant-is-base-tuple (components): uses the enrichment's
defaultVariantTuple already gathered in Wave 10b; flags a COMPONENT_SET
whose default variant isn't each axis's first-authored (base) option.
"base" is a house convention, hence opt-in.
- multi-brand-alias-discipline (theming, config {brandPrefix, roles?}):
pure over the alias graph. A brandable semantic (accent/action/… role)
should alias THROUGH a brand/* token so re-branding is a single-layer
swap; flags one whose chain reaches a primitive without a brand hop. The
brand layer itself is exempt. Only meaningful for multi-brand DSs, so
opt-in + requires the brand layer declared via config.
+3 tests. Only the 4 data-dependent rules remain pending (need plugin
gather for instance overrides / dev resources / frame fingerprints /
exportAsync sampling). 41 tests pass; golden still 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…4/57) The rule's real job (info) is to FLAG color tokens whose alias-resolved contrast is untrustworthy — i.e. TRANSLUCENT paints that composite over their backdrop. Alpha is already in the snapshot's colour values, so this needs no exportAsync/pixel-sampling in the gather (which the design panel rightly flagged as the heaviest/riskiest path). Resolves each semantic fg/bg/border token's alias chain to its raw alpha and flags alpha < 1, pointing the user at pixel sampling for those specific tokens. +1 test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the plugin lint_run with three bounded gathers (all degrade to silent on an old plugin; a NEW plugin always emits the keys — even [] — so undefined=not-gathered vs []=scanned-clean): - no-instance-restyle-override (components, warn): scans INSTANCE nodes (INSTANCE_SCAN_BUDGET=20k, MAX_RESTYLED_INSTANCES=300) and emits ONLY TOP-LEVEL instances carrying STYLE overrides (fills/strokes/effects/ *StyleId) — nested instances are skipped so a restyle isn't double-reported on its container. Membership == the finding. - component-set-has-code-mapping (code-output, warn): getDevResourcesAsync per COMPONENT_SET, batched via Promise.all + capped (120). CONDITIONAL on adoption — only flags missing mappings once SOME set has one, so a team not using Code Connect isn't spammed; capped/errored sets are undefined and excluded from numerator+denominator. - detached-component-frame-signal (components, info, OPT-IN): name-prefilters the FRAME population by collision with a standalone-component name, then flags an EXACT name + direct-child-type-sequence match. Both fingerprints must be complete (childCount===seq.length) so a capped >40-child seq never yields a partial-prefix false match. Opt-in given inherent heuristic noise. Every new array is capped + *Truncated-flagged; truncation causes false negatives only, never a fabricated finding. Server types + detectors in lockstep. +3 tests (45 total); golden still 0. Detector coverage now 57/57 — the entire canonical catalog is implemented. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6-lens adversarial review (refute-by-default): 3 confirmed, 3 refuted (instance scan, detached-frame, default-variant, backward-compat, and contrast-fallback all held). 1. component-set-has-code-mapping (medium+low, same root): the plugin sourced hasCodeMapping from getDevResourcesAsync, which returns ANY Dev Mode link (Storybook/Jira/docs) — NOT Code Connect. So one stray link on one set tripped the adoption gate and spammed a false finding on every other set, and the suggested remedy (set_code_mapping) writes a disjoint server-side store so the warning never cleared. Fix: make the rule opt-in (defaultOn:false) and reword it honestly as a dev-resource-presence proxy (not Code Connect); drop the misdirected set_code_mapping remedy. 2. multi-brand-alias-discipline (medium): the multi-hop alias walk advanced via Object.values(target.valuesByMode)[0] — the target's FIRST mode regardless of the mode being followed — making results order-dependent and able to fabricate a finding on per-mode-divergent chains. Fix: thread the current mode through the walk (fall back to first mode only when absent), mirroring resolveColor/resolveAlpha. Added a multi-hop per-mode-divergent regression test that fails under the old collapse. Server-only (no plugin change); neither rule changes a default lint (both opt-in). 46 tests pass; golden still 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Completes the design-system lint catalog to 57/57 detectors — the 6 rules deferred in PR #34, implemented across two waves with the same test-first + adversarial-review discipline.
Wave 11a — offline rules (opt-in)
default-variant-is-base-tuple— reuses thedefaultVariantTuplegathered in Wave 10bmulti-brand-alias-discipline— pure alias-graph,config {brandPrefix, roles?}contrast-fallback-export-sampling— reframed as offline: flags translucent (alpha<1) tokens via existing colour data (noexportAsync)Wave 11b — plugin-gather rules
no-instance-restyle-override(warn) — bounded INSTANCE scan; top-level-only, style-fields-onlycomponent-set-has-code-mapping(opt-in) —getDevResourcesAsync, adoption-gated, honestly worded as a dev-resource proxydetached-component-frame-signal(opt-in info) — name-prefiltered exact name+child-type-seq matchQuality
getDevResourcesAsync≠Code-Connect gate defeat (now opt-in + honest) and the multi-brand first-mode-collapse bug (now mode-threaded)rule_failures: [], precise low-noise findings (2 real instance restyles, 0 false positives on detached-frame/default-variant/code-mapping, 24 accurate translucent-token infos), the new instance/dev-resource/frame gather runs clean across 48 pages with no timeoutEvery new gather is bounded (cap +
*Truncatedflag; truncation ⇒ false-negatives only). All opinionated/house-style rules aredefaultOn:false, keeping the default lint precise (advise, don't dictate).🤖 Generated with Claude Code