Conversation
…ssibility-analyzer-for fix: reweight accessibility analyzer for CEM-realistic scoring
…ty scanner Phase 2 of the helixir health system: - Multi-dimensional scoring engine (11 dimensions, enterprise-grade algorithm) - Source-level accessibility scanner: regex-based analysis of component source files detecting ARIA bindings, keyboard handlers, focus management, form internals, live regions, and screen reader support patterns - CEM schema hardened for real-world manifests (Lion, Vaadin edge cases) - Source file resolution with 5 strategies (direct .ts/.js, src/ prefix, .component.ts convention) - Real-world validation against 5 official WC library source repos (Shoelace, Spectrum, PatternFly, Vaadin, Lion) - 1538 tests, all passing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds inheritance chain following to the source-level accessibility scanner. The scanner now traces CEM superclass/mixin declarations and follows a11y-relevant imports to scan the FULL inheritance chain — not just the component's leaf file. Key additions: - mixin-resolver.ts: resolves CEM superclass/mixin module paths to files, follows a11y-relevant imports (FocusMixin, FormControlMixin, etc.), classifies architecture (inline/mixin-heavy/controller-based/hybrid) - CEM schema: added superclass, mixins, inheritedFrom fields - analyzeSourceAccessibilityDeep(): chain-aware scoring with per-source breakdown showing which file contributed which patterns Results against real libraries (shallow → deep): Vaadin: 24 → 62/100 (+38 points, mixin-heavy architecture) Spectrum: 48 → 57/100 (+9 points, hybrid architecture) Lion: 23 → 28/100 (+5 points, needs deeper package resolution) Shoelace: 61 → 64/100 (+3 points, inline architecture) PatternFly: 44 → 45/100 (+1 point, inline architecture) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Material Web (Google, 97), Carbon (IBM, 110), Fluent UI (Microsoft, 41), Wired Elements (26), Ionic (97), and Porsche Design System (91) to the source-level accessibility scanner test suite. Total: 812 components across 11 libraries covering Lit, FAST, Stencil, and vanilla architectures. Also fix CEM member name schema to handle undefined names in generated CEMs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Calcite (Esri/Lumina), UI5 (SAP), and Elix (vanilla) bring the test arsenal to 14 libraries and 1,162 components. Elix proves the deep scanner's value: 0/100 shallow → 61/100 deep (+61 points) because ALL a11y patterns live in mixins like KeyboardMixin, AriaListMixin, and FormElementMixin — invisible to single-file scanning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Analyzers (type-coverage, api-surface, event-architecture, css-architecture) now return null when there's no data to score (0 members, 0 events, 0 CSS properties). These dimensions are excluded from the weighted average instead of getting free perfect scores. Also fixes 7 TypeScript build errors in audit-report, benchmark, and compare handlers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
WalkthroughThis PR adds a multi-dimensional component health scoring system (11 dimensions), source-level accessibility scanning with inheritance/mixin resolution, four new analyzers, config migration to helixir.mcp.json with legacy fallback, audit JSONL reporting, CLI/tool integration, many tests, and bumps version to 0.3.0. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Config
participant Analyzer
participant Scorer
participant AuditGen
Client->>Config: loadConfig()
Config->>Config: check helixir.mcp.json
alt primary exists
Config->>Config: parse primary
else fallback
Config->>Config: check mcpwc.config.json
Config->>Config: emit deprecation warning
Config->>Config: parse legacy
end
Config-->>Client: return config
Client->>Analyzer: analyzeSourceAccessibility(config, decl)
Analyzer->>Analyzer: resolveComponentSourceFilePath(decl)
Analyzer->>Analyzer: scanSourceForA11yPatterns(source)
Analyzer->>Analyzer: scoreSourceMarkers(markers)
Analyzer-->>Client: SourceAccessibilityResult
Client->>Scorer: scoreComponentMultiDimensional(config, decl)
Scorer->>Scorer: compute CEM-native dimensions (analyzers)
Scorer->>Scorer: read history for external dimensions
Scorer->>Scorer: computeWeightedScore & calculateGrade
Scorer-->>Client: MultiDimensionalHealth
Client->>AuditGen: generateAuditReport(config, decls)
AuditGen->>Scorer: scoreComponentMultiDimensional (per decl)
AuditGen->>AuditGen: aggregate summary & write JSONL
AuditGen-->>Client: lines[], summary
sequenceDiagram
participant Source as Source File
participant Resolver as MixinResolver
participant Scanner as Scanner
participant Aggregator as Aggregator
Resolver->>Resolver: resolveInheritanceChain(componentSource)
Resolver->>Source: read component source
Resolver->>Scanner: scanSourceForA11yPatterns(source)
Scanner-->>Resolver: SourceA11yMarkers
loop each superclass/mixin
Resolver->>Resolver: resolveModulePath(import)
Resolver->>Source: read inherited source
Resolver->>Scanner: scanSourceForA11yPatterns(source)
Scanner-->>Resolver: SourceA11yMarkers
end
Resolver->>Aggregator: aggregateMarkers(all sources)
Aggregator->>Aggregator: merge markers & classify architecture
Aggregator-->>Resolver: InheritanceChainResult
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/tools/health.test.ts (1)
110-131: 🧹 Nitpick | 🔵 TrivialConsider adding handler test for audit_library.
The existing tests cover definition presence but there's no
handleHealthCalltest for theaudit_librarytool. If handler behavior is tested elsewhere (e.g.,audit-report.test.ts), this is fine. Otherwise, consider adding coverage for the handler dispatch path.Would you like me to generate a test case for
handleHealthCall('audit_library', ...)or open an issue to track this?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/tools/health.test.ts` around lines 110 - 131, Add a unit test that verifies the handler dispatch for the "audit_library" tool by calling handleHealthCall('audit_library', ...) with a representative input and asserting the expected outcome (or that the correct handler was invoked); locate the handler by the handleHealthCall function and the "audit_library" entry in HEALTH_TOOL_DEFINITIONS, mock any external dependencies or the audit library handler as done for other tools in tests (e.g., mirror existing patterns used for score_component or analyze_accessibility), and place the test alongside the other HEALTH_TOOL_DEFINITIONS tests so the tool definition presence and dispatch behavior are both covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.automaker/memory/architecture.md:
- Around line 477-489: Clarify the adjacent, seemingly contradictory notes by
explicitly stating their contexts: update the entry that mentions replacing
existsSync with async access() to reference the async refactor of parseTokens
(e.g., "use fs/promises.access() when converting parseTokens or other
already-async functions to avoid blocking"), and update the entry that defends
retaining existsSync to note it's for simple synchronous guard checks (e.g.,
"retain existsSync for trivial boolean guards where introducing async try/catch
would harm readability"); reference the symbols existsSync, access(),
fs/promises, and parseTokens so readers can see when each approach applies.
In @.automaker/memory/gotchas.md:
- Around line 114-152: Several new "#### [Gotcha]" headings in the
.automaker/memory/gotchas.md block are missing a blank line above them (MD022);
insert a single blank line immediately before each "#### [Gotcha]" heading
occurrence (the headings starting with "#### [Gotcha] A feature branch..." and
the subsequent seven gotcha entries) so every "####" heading is preceded by an
empty line, preserving existing text and spacing around the surrounding
paragraphs.
In @.automaker/memory/security.md:
- Around line 289-311: The file violates MD022 and MD047: add a blank line
before each top-level heading (insert a newline immediately above "Response SLA
tiered as 48h acknowledgment + 7-day status update rather than a single flat SLA
(2026-03-12)", above "Response SLA..."'s subsequent headings like "Gotcha]
Supported versions table...", and above the "[Pattern] pnpm audit is run with
--audit-level=high..." heading) so all headings are surrounded by a blank line,
and ensure the file ends with exactly one trailing newline character (terminate
after the final line rather than leaving it without a newline or with extra
blank lines).
In `@CHANGELOG.md`:
- Around line 3-7: The changelog for v0.3.0 only documents the /update-helixir
slash command but omits major features; update CHANGELOG.md to include concise
entries under v0.3.0 for multi-dimensional health scoring, source-level
accessibility analysis, the new MCP tools (score_component_multi_dimensional,
score_all_multi_dimensional, audit_library), and the config migration
utility/notes, ensuring each bullet references the corresponding feature name or
command and briefly summarizes its purpose and impact.
In `@packages/core/src/handlers/accessibility.ts`:
- Around line 103-107: The current logic treats any CSS custom property whose
name contains "role" as evidence of ARIA role support (ariaRoleInCss), which
wrongly awards accessibility points for purely styling tokens; remove the
cssProperties-based detection by deleting the ariaRoleInCss variable and update
the hasAriaRole computation to rely only on ariaRoleInDesc and
ariaRoleFromTagName (i.e., set hasAriaRole = ariaRoleInDesc ||
ariaRoleFromTagName), ensuring no CSS token names are used to infer ARIA
behavior (adjust or remove any related references to ariaRoleInCss in the
surrounding code).
In `@packages/core/src/handlers/analyzers/api-surface.ts`:
- Around line 41-47: The current reflectedCount uses
Math.max(fieldsWithAttribute.length, fieldsReflecting.length) which undercounts
when different fields have attribute and reflects; change the calculation to
count the union of fields that have either a non-empty attribute or reflects ===
true by deriving a single collection (e.g., filter fields by (m) => (typeof
m.attribute === 'string' && m.attribute.length > 0) || m.reflects === true or
build a Set of unique field identifiers) and use its length for reflectedCount
before computing attrScore; update references to
fieldsWithAttribute/fieldsReflecting as needed so attrScore uses that union
length.
In `@packages/core/src/handlers/analyzers/css-architecture.ts`:
- Around line 39-51: The token naming regex used in tokenPattern is too strict
(currently /^--[a-z]+-[a-z]/) and rejects valid custom properties with digits or
uppercase letters; update tokenPattern to a more permissive pattern such as
/^--[A-Za-z][A-Za-z0-9]*-/ so prefixes can include letters (any case) and digits
while still enforcing the required hyphenated namespace; update the occurrence
in the css-architecture analyzer (variables tokenPattern, wellNamedProps,
tokenScore) and any related tests or documentation to reflect the relaxed
pattern.
In `@packages/core/src/handlers/analyzers/source-accessibility.ts`:
- Around line 170-177: The existence check in tryReadFile causes a TOCTOU race
and is redundant; simplify tryReadFile by removing the existsSync(filePath)
branch and just attempt to await readFile(filePath, 'utf-8') inside the
try/catch, returning the file contents on success and null on any thrown error
so the function behavior and signature (tryReadFile) remain the same.
In `@packages/core/src/handlers/audit-report.ts`:
- Around line 92-96: The file write using writeFile when options?.outputPath is
set can throw and currently bubbles up; wrap the write in a try-catch so the
handler returns the computed lines and summary even if writing fails.
Concretely, around the block that resolves outputFile
(resolve(config.projectRoot, options.outputPath)) and calls await
writeFile(outputFile, lines.join('\n') + '\n', 'utf-8'), catch any error, attach
or include the error message in the handler's response (e.g., return or include
an exportError field alongside lines and summary) and ensure the function still
returns the computed data (lines and summary) when a write error occurs. Ensure
you reference options?.outputPath, outputFile, writeFile, lines and summary when
implementing the catch handling so callers can access both the computed report
and the write failure details.
In `@packages/core/src/handlers/dimensions.ts`:
- Around line 173-181: The logic in the lowCritical block allows a less
restrictive cap to overwrite a stricter one: change the comparison that sets
gradeCap so we only replace gradeCap with newCap when newCap is strictly more
restrictive (i.e., a better/stricter cap) than the existing gradeCap;
specifically, in the block referencing lowCritical, measuredCritical, gradeCap,
and gradeOrdinal, invert the comparison (or otherwise compare ordinals
correctly) so newCap is applied only if gradeOrdinal(newCap) indicates a
stricter cap than gradeOrdinal(gradeCap), keeping the strictest cap across
checks and leaving notes.push as-is.
In `@packages/core/src/handlers/health.ts`:
- Around line 776-795: When populating dimensions from historyEntry, validate
historyEntry.confidence before casting: read const conf =
historyEntry.confidence and set confidence to conf if conf === 'verified' ||
conf === 'heuristic', otherwise fall back to a safe default (e.g., 'verified');
update the object pushed into dimensions to use that validated value so
unexpected or misspelled confidence strings from historyBreakdown cannot produce
an invalid state.
In `@packages/core/src/tools/health.ts`:
- Around line 248-260: The call to scoreAllComponentsMultiDimensional is missing
the cem argument causing source-level accessibility analysis to fail; update the
call in the score_all_components branch to pass the previously loaded cem (from
const cemData = await loadCemData(config, cem))—i.e., change
scoreAllComponentsMultiDimensional(config, declarations) to include cem as the
third parameter so it matches the other call pattern (and keeps
analyzeSourceAccessibility working), ensuring any related uses of
ScoreAllComponentsArgsSchema.parse and createSuccessResponse remain unchanged.
- Around line 287-292: The call to scoreAllComponentsMultiDimensional inside
handleHealthCall is passing the original cem parameter (which may be undefined)
instead of the loaded CEM data variable cemData, causing source-level
accessibility analysis to be skipped when cem was not provided; change the
argument from cem to cemData so the function receives the loaded CEM data, and
scan for any other places in handleHealthCall that still reference cem where
cemData should be used (e.g., the call site of
scoreAllComponentsMultiDimensional and any subsequent uses of CEM data).
In `@tests/config-rename.test.ts`:
- Around line 10-18: Remove the redundant vi.unstubAllEnvs() call from the
beforeEach block and keep the single cleanup call in afterEach; update the
tests/config-rename.test.ts beforeEach so it only initializes tmpDir with
mkdtempSync(join(tmpdir(), 'helixir-rename-test-')) and leaves
vi.unstubAllEnvs() in afterEach to perform environment cleanup between tests.
In `@tests/handlers/deep-source-accessibility.test.ts`:
- Around line 366-383: The forEach callbacks for logging top and bottom scorers
use concise arrow bodies that implicitly return the result of console.log,
triggering the lint rule; update the two forEach calls on the sorted and bottom
arrays to use block arrow functions with an explicit statement body (e.g., (s)
=> { console.log(...); }) so they do not implicitly return a value, referencing
the sorted variable and bottom variable used in those callbacks.
In `@tests/handlers/multi-dimensional-health.test.ts`:
- Around line 109-123: Replace the weak LOW_TYPE_COVERAGE_DECL test fixture with
a variant derived from PERFECT_DECL that only strips type metadata (keep all
other fields identical) so the test actually isolates Type Coverage loss; update
the test to run the handler/validator with this new fixture, assert that the
returned score is capped to the expected Type Coverage cap value, and explicitly
assert that result.gradingNotes contains the expected note about the cap
(reference symbols: create NEW_LOW_TYPE_FROM_PERFECT or reuse PERFECT_DECL to
build the fixture, check result.gradingNotes and the returned grade value).
In `@tests/handlers/source-accessibility-real-libs.test.ts`:
- Around line 244-254: The test only validates the first five declarations
because it uses allDecls.slice(0, 5); update the test to iterate over the full
allDecls array instead of the sliced sample so every declaration is verified;
change the loop that calls analyzeSourceAccessibility(fakeConfig, cem, decl) to
run for each decl in allDecls (or use a direct array iteration/assertion) and
assert expect(result).toBeNull() for each to prevent regressions after the first
five entries.
- Around line 23-25: This ESM test file uses __dirname when computing
HELIX_ROOT, HELIX_CEM_PATH, and HELIX_HAS_SOURCE but never defines it; add an
ESM-compatible __dirname initialization at the top of the module by importing
fileURLToPath (from 'url') and dirname (from 'path') and setting const __dirname
= dirname(fileURLToPath(import.meta.url)); then the existing resolve(...) calls
that produce HELIX_ROOT, HELIX_CEM_PATH and HELIX_HAS_SOURCE will work without
throwing a ReferenceError.
- Around line 186-189: The forEach callback on tiers.excellent is using an
expression-bodied arrow that implicitly returns console.log (forEach callbacks
must not return values); change the expression-bodied arrow to a block-bodied
arrow for the .forEach call so the callback becomes { console.log(...) } instead
of the implicit-return form—do the same for the other .forEach at the later
block to satisfy the useIterableCallbackReturn rule while keeping the same
logging behavior.
In `@tests/handlers/source-accessibility-wc-libraries.test.ts`:
- Around line 149-167: The forEach callbacks that currently use concise arrow
bodies and implicitly return the result of console.log (in the tiers.excellent
.forEach and tiers.low .forEach blocks) should be converted to block arrow
functions to avoid implicit returns: replace .forEach((s) => console.log(...))
with .forEach((s) => { console.log(...); }) for both the top scorers
(tiers.excellent) and lowest interactive scorers (tiers.low) iterations so they
no longer return a value and satisfy the useIterableCallbackReturn lint rule.
---
Outside diff comments:
In `@tests/tools/health.test.ts`:
- Around line 110-131: Add a unit test that verifies the handler dispatch for
the "audit_library" tool by calling handleHealthCall('audit_library', ...) with
a representative input and asserting the expected outcome (or that the correct
handler was invoked); locate the handler by the handleHealthCall function and
the "audit_library" entry in HEALTH_TOOL_DEFINITIONS, mock any external
dependencies or the audit library handler as done for other tools in tests
(e.g., mirror existing patterns used for score_component or
analyze_accessibility), and place the test alongside the other
HEALTH_TOOL_DEFINITIONS tests so the tool definition presence and dispatch
behavior are both covered.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 677c992b-3d35-4a03-92c4-609facf024a1
📒 Files selected for processing (39)
.automaker/memory/api.md.automaker/memory/architecture.md.automaker/memory/gotchas.md.automaker/memory/performance.md.automaker/memory/security.md.automaker/memory/testing.md.automaker/memory/validation.md.changeset/add-update-helixir-command.mdCHANGELOG.mdpackage.jsonpackages/core/src/config.tspackages/core/src/handlers/accessibility.tspackages/core/src/handlers/analyzers/api-surface.tspackages/core/src/handlers/analyzers/css-architecture.tspackages/core/src/handlers/analyzers/event-architecture.tspackages/core/src/handlers/analyzers/index.tspackages/core/src/handlers/analyzers/mixin-resolver.tspackages/core/src/handlers/analyzers/source-accessibility.tspackages/core/src/handlers/analyzers/type-coverage.tspackages/core/src/handlers/audit-report.tspackages/core/src/handlers/benchmark.tspackages/core/src/handlers/cem.tspackages/core/src/handlers/compare.tspackages/core/src/handlers/dimensions.tspackages/core/src/handlers/health.tspackages/core/src/handlers/index.tspackages/core/src/tools/health.tstests/config-rename.test.tstests/handlers/accessibility.test.tstests/handlers/analyzers.test.tstests/handlers/audit-report.test.tstests/handlers/deep-source-accessibility.test.tstests/handlers/dimensions.test.tstests/handlers/multi-dimensional-health.test.tstests/handlers/source-accessibility-real-libs.test.tstests/handlers/source-accessibility-wc-libraries.test.tstests/handlers/source-accessibility.test.tstests/integration/server.test.tstests/tools/health.test.ts
💤 Files with no reviewable changes (1)
- .changeset/add-update-helixir-command.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.changeset/multi-dimensional-health-scoring.md:
- Line 5: Add a top-level H1 as the first line of the file so markdownlint MD041
is satisfied: insert a heading such as "# Multi-dimensional health scoring
engine" (or similar descriptive H1) at the very top of
.changeset/multi-dimensional-health-scoring.md before the body text "Add
multi-dimensional health scoring engine with source-level accessibility
analysis".
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7d0f636c-6bde-44b7-8e81-57e028438896
📒 Files selected for processing (1)
.changeset/multi-dimensional-health-scoring.md
Update pnpm overrides to patch flatted (>=3.4.0), hono (>=4.12.7), and undici (>=7.24.0). Restore pnpm-workspace.yaml so overrides apply to the github-action sub-package. Regenerated lockfile — 0 vulnerabilities. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tories Excludes .automaker/, build/, pnpm-lock.yaml, .changeset/, .worktrees/, .husky/, coverage/, node_modules/, and source maps from code review. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
This release transforms helixir from a single-score CEM documentation checker into a multi-dimensional component health scoring engine with source-level accessibility analysis. The scoring system now evaluates components across 6 independently-weighted dimensions with an enterprise grade algorithm, and can read actual component source code to measure real accessibility implementation — not just what the CEM metadata happens to capture.
What changed
Multi-dimensional scoring engine — Components are now scored across 6 CEM-native dimensions (with 5 external dimensions ready for future data sources):
Each dimension produces sub-metrics with individual scores, making it clear exactly where a component is strong or weak.
Enterprise grade algorithm — Grades (A–F) are not just a score threshold. Critical dimension gates prevent gaming:
Source-level accessibility scanner — The CEM standard captures ~20% of real accessibility implementation. The other 80% lives in source code: ARIA template bindings, keyboard handlers, focus management, form internals, live regions. helixir now reads component source files (located via CEM module paths) and scans for 7 categories of accessibility patterns using framework-agnostic regexes:
aria-checked=${this.checked},.ariaLabel,setAttribute('aria-...')role="button",setAttribute('role', ...)@keydown=,addEventListener('key...), key switch blocks.focus(),tabindex,aria-activedescendant, focus trapsattachInternals(),static formAssociated,setFormValuearia-live,role="alert",aria-atomicaria-hidden,.sr-only,aria-labelledbyWhen source is available, accessibility scoring blends 30% CEM + 70% source (source is ground truth). When source isn't available, CEM-only scoring still works — graceful degradation.
Deep mixin-aware scanning — Many component libraries implement accessibility in shared mixins and base classes, not in each component file. The deep scanner follows CEM superclass/mixin declarations and a11y-relevant import statements through the full inheritance chain (depth-limited to prevent infinite loops). It aggregates accessibility markers across all files in the chain and classifies component architecture as
inline,mixin-heavy,controller-based, orhybrid.Honest scoring for empty CEM data — Previously, components with no members/events/CSS properties in their CEM received perfect 100/100 scores (the analyzer defaulted to full points when dividing by zero). This inflated scores for libraries with poor CEM metadata. Now, analyzers return
nullwhen there's nothing to evaluate, and those dimensions are excluded from the weighted average entirely — same principle as not penalizing presentational components for lacking accessibility patterns.CEM accessibility reweight — The CEM-based accessibility analyzer was reweighted to stop penalizing libraries for data the CEM standard doesn't capture. ARIA attributes and keyboard handling (which almost no CEM generator extracts) were moved to "bonus" points. The reweight reflects what CEM can actually measure vs. what requires source scanning.
New MCP tools
score_component_multi_dimensional— Full 11-dimension scoring for a single componentscore_all_multi_dimensional— Score every component in the libraryaudit_library— JSONL audit report generation (one JSON line per component)New files
handlers/dimensions.tshandlers/analyzers/source-accessibility.tshandlers/analyzers/mixin-resolver.tshandlers/analyzers/type-coverage.tshandlers/analyzers/api-surface.tshandlers/analyzers/css-architecture.tshandlers/analyzers/event-architecture.tshandlers/audit-report.tsTest coverage
1640 tests, all passing. New test files:
tests/handlers/dimensions.test.ts— 363 lines, grade algorithm edge cases, weighted scoring, critical dimension gatestests/handlers/multi-dimensional-health.test.ts— 374 lines, full scoring pipeline integrationtests/handlers/analyzers.test.ts— 301 lines, all 4 CEM-native analyzerstests/handlers/source-accessibility.test.ts— 400 lines, regex pattern detection across frameworkstests/handlers/deep-source-accessibility.test.ts— 490 lines, mixin chain resolution, deep vs shallow comparison across 14 real-world librariestests/handlers/source-accessibility-wc-libraries.test.ts— 425 lines, full source scanning against real library repostests/handlers/source-accessibility-real-libs.test.ts— 282 lines, integration tests against real CEMstests/handlers/audit-report.test.ts— 184 lines, JSONL generation and summary aggregationtests/config-rename.test.ts— 115 lines, config file rename migrationtests/handlers/accessibility.test.ts— +179 lines for reweighted scoringConfig changes
mcp-wc.jsontohelixir.mcp.json(with backward-compatible migration)config.tsupdated with new fields:healthHistoryDir,tsconfigPath,tokensPath,cdnBase,watchValidated against 14 real-world component libraries
The source scanner and multi-dimensional scoring have been validated against full source repos of: Shoelace, PatternFly Elements, Lion, Vaadin, Spectrum (Adobe), Material Web (Google), Carbon (IBM), Fluent UI (Microsoft), Wired Elements, Ionic, Porsche Design System, Calcite (Esri), UI5 (SAP), and Elix. These cover Lit, FAST, Stencil, vanilla, and hybrid architectures — confirming the scanner works across all major web component frameworks.
Test plan
npx vitest run— 1640/1640 tests passnpm run build— 0 TypeScript errorsprettier --check .— all files formatted🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Configuration
Documentation
Version