@salesforce/afv-skills 1.14.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/applying-slds/SKILL.md +322 -0
- package/skills/applying-slds/checklists.md +83 -0
- package/skills/applying-slds/examples.md +283 -0
- package/skills/applying-slds/guidance/README.md +83 -0
- package/skills/applying-slds/guidance/blueprints-index.md +213 -0
- package/skills/applying-slds/guidance/icons-guidance.md +186 -0
- package/skills/applying-slds/guidance/overviews/borders.md +236 -0
- package/skills/applying-slds/guidance/overviews/color.md +266 -0
- package/skills/applying-slds/guidance/overviews/display-density.md +366 -0
- package/skills/applying-slds/guidance/overviews/icons.md +240 -0
- package/skills/applying-slds/guidance/overviews/illustrations.md +235 -0
- package/skills/applying-slds/guidance/overviews/shadows.md +176 -0
- package/skills/applying-slds/guidance/overviews/spacing.md +216 -0
- package/skills/applying-slds/guidance/overviews/typography.md +323 -0
- package/skills/applying-slds/guidance/overviews/utilities.md +542 -0
- package/skills/applying-slds/guidance/slds-development-guide.md +288 -0
- package/skills/applying-slds/guidance/styling-hooks/borders.md +202 -0
- package/skills/applying-slds/guidance/styling-hooks/color/expressive-palette-hooks.md +153 -0
- package/skills/applying-slds/guidance/styling-hooks/color/index.md +171 -0
- package/skills/applying-slds/guidance/styling-hooks/color/semantic/accent-hooks.md +204 -0
- package/skills/applying-slds/guidance/styling-hooks/color/semantic/feedback-hooks.md +768 -0
- package/skills/applying-slds/guidance/styling-hooks/color/semantic/surface-hooks.md +337 -0
- package/skills/applying-slds/guidance/styling-hooks/color/system-hooks.md +132 -0
- package/skills/applying-slds/guidance/styling-hooks/index.md +327 -0
- package/skills/applying-slds/guidance/styling-hooks/shadows.md +238 -0
- package/skills/applying-slds/guidance/styling-hooks/spacing.md +254 -0
- package/skills/applying-slds/guidance/styling-hooks/typography.md +448 -0
- package/skills/applying-slds/guidance/utilities/alignment.md +119 -0
- package/skills/applying-slds/guidance/utilities/borders.md +131 -0
- package/skills/applying-slds/guidance/utilities/box.md +125 -0
- package/skills/applying-slds/guidance/utilities/color.md +165 -0
- package/skills/applying-slds/guidance/utilities/dark-mode.md +111 -0
- package/skills/applying-slds/guidance/utilities/description-list.md +168 -0
- package/skills/applying-slds/guidance/utilities/floats.md +117 -0
- package/skills/applying-slds/guidance/utilities/grid.md +264 -0
- package/skills/applying-slds/guidance/utilities/horizontal-list.md +110 -0
- package/skills/applying-slds/guidance/utilities/hyphenation.md +84 -0
- package/skills/applying-slds/guidance/utilities/index.md +205 -0
- package/skills/applying-slds/guidance/utilities/interactions.md +89 -0
- package/skills/applying-slds/guidance/utilities/layout.md +109 -0
- package/skills/applying-slds/guidance/utilities/line-clamp.md +131 -0
- package/skills/applying-slds/guidance/utilities/margin.md +155 -0
- package/skills/applying-slds/guidance/utilities/media-object.md +161 -0
- package/skills/applying-slds/guidance/utilities/name-value-list.md +152 -0
- package/skills/applying-slds/guidance/utilities/padding.md +155 -0
- package/skills/applying-slds/guidance/utilities/position.md +177 -0
- package/skills/applying-slds/guidance/utilities/print.md +114 -0
- package/skills/applying-slds/guidance/utilities/scrollable.md +126 -0
- package/skills/applying-slds/guidance/utilities/sizing.md +190 -0
- package/skills/applying-slds/guidance/utilities/themes.md +121 -0
- package/skills/applying-slds/guidance/utilities/truncate.md +127 -0
- package/skills/applying-slds/guidance/utilities/typography.md +166 -0
- package/skills/applying-slds/guidance/utilities/vertical-list.md +166 -0
- package/skills/applying-slds/guidance/utilities/visibility.md +228 -0
- package/skills/applying-slds/metadata/README.md +84 -0
- package/skills/applying-slds/metadata/blueprints/components/accordion.yaml +304 -0
- package/skills/applying-slds/metadata/blueprints/components/activity-timeline.yaml +92 -0
- package/skills/applying-slds/metadata/blueprints/components/alert.yaml +103 -0
- package/skills/applying-slds/metadata/blueprints/components/app-launcher.yaml +94 -0
- package/skills/applying-slds/metadata/blueprints/components/avatar-group.yaml +81 -0
- package/skills/applying-slds/metadata/blueprints/components/avatar.yaml +97 -0
- package/skills/applying-slds/metadata/blueprints/components/badges.yaml +102 -0
- package/skills/applying-slds/metadata/blueprints/components/brand-band.yaml +198 -0
- package/skills/applying-slds/metadata/blueprints/components/breadcrumbs.yaml +95 -0
- package/skills/applying-slds/metadata/blueprints/components/builder-header.yaml +192 -0
- package/skills/applying-slds/metadata/blueprints/components/button-groups.yaml +82 -0
- package/skills/applying-slds/metadata/blueprints/components/button-icons.yaml +295 -0
- package/skills/applying-slds/metadata/blueprints/components/buttons.yaml +230 -0
- package/skills/applying-slds/metadata/blueprints/components/cards.yaml +124 -0
- package/skills/applying-slds/metadata/blueprints/components/carousel.yaml +140 -0
- package/skills/applying-slds/metadata/blueprints/components/chat.yaml +179 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox-button-group.yaml +192 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox-button.yaml +204 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox-toggle.yaml +177 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox.yaml +108 -0
- package/skills/applying-slds/metadata/blueprints/components/color-picker.yaml +172 -0
- package/skills/applying-slds/metadata/blueprints/components/combobox.yaml +136 -0
- package/skills/applying-slds/metadata/blueprints/components/counter.yaml +147 -0
- package/skills/applying-slds/metadata/blueprints/components/data-tables.yaml +157 -0
- package/skills/applying-slds/metadata/blueprints/components/datepickers.yaml +130 -0
- package/skills/applying-slds/metadata/blueprints/components/datetime-picker.yaml +155 -0
- package/skills/applying-slds/metadata/blueprints/components/docked-composer.yaml +201 -0
- package/skills/applying-slds/metadata/blueprints/components/docked-form-footer.yaml +161 -0
- package/skills/applying-slds/metadata/blueprints/components/docked-utility-bar.yaml +175 -0
- package/skills/applying-slds/metadata/blueprints/components/drop-zone.yaml +115 -0
- package/skills/applying-slds/metadata/blueprints/components/dueling-picklist.yaml +196 -0
- package/skills/applying-slds/metadata/blueprints/components/dynamic-icons.yaml +128 -0
- package/skills/applying-slds/metadata/blueprints/components/dynamic-menu.yaml +141 -0
- package/skills/applying-slds/metadata/blueprints/components/expandable-section.yaml +115 -0
- package/skills/applying-slds/metadata/blueprints/components/expression.yaml +143 -0
- package/skills/applying-slds/metadata/blueprints/components/feeds.yaml +125 -0
- package/skills/applying-slds/metadata/blueprints/components/file-selector.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/files.yaml +119 -0
- package/skills/applying-slds/metadata/blueprints/components/form-element.yaml +145 -0
- package/skills/applying-slds/metadata/blueprints/components/global-header.yaml +120 -0
- package/skills/applying-slds/metadata/blueprints/components/global-navigation.yaml +100 -0
- package/skills/applying-slds/metadata/blueprints/components/icons.yaml +138 -0
- package/skills/applying-slds/metadata/blueprints/components/illustration.yaml +205 -0
- package/skills/applying-slds/metadata/blueprints/components/input.yaml +151 -0
- package/skills/applying-slds/metadata/blueprints/components/list-builder.yaml +127 -0
- package/skills/applying-slds/metadata/blueprints/components/lookups.yaml +132 -0
- package/skills/applying-slds/metadata/blueprints/components/map.yaml +118 -0
- package/skills/applying-slds/metadata/blueprints/components/menus.yaml +134 -0
- package/skills/applying-slds/metadata/blueprints/components/modals.yaml +152 -0
- package/skills/applying-slds/metadata/blueprints/components/notifications.yaml +88 -0
- package/skills/applying-slds/metadata/blueprints/components/page-headers.yaml +135 -0
- package/skills/applying-slds/metadata/blueprints/components/panels.yaml +149 -0
- package/skills/applying-slds/metadata/blueprints/components/path.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/picklist.yaml +125 -0
- package/skills/applying-slds/metadata/blueprints/components/pills.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/popovers.yaml +120 -0
- package/skills/applying-slds/metadata/blueprints/components/progress-bar.yaml +110 -0
- package/skills/applying-slds/metadata/blueprints/components/progress-indicator.yaml +133 -0
- package/skills/applying-slds/metadata/blueprints/components/progress-ring.yaml +102 -0
- package/skills/applying-slds/metadata/blueprints/components/prompt.yaml +126 -0
- package/skills/applying-slds/metadata/blueprints/components/publishers.yaml +178 -0
- package/skills/applying-slds/metadata/blueprints/components/radio-button-group.yaml +172 -0
- package/skills/applying-slds/metadata/blueprints/components/radio-group.yaml +112 -0
- package/skills/applying-slds/metadata/blueprints/components/rich-text-editor.yaml +135 -0
- package/skills/applying-slds/metadata/blueprints/components/scoped-notifications.yaml +188 -0
- package/skills/applying-slds/metadata/blueprints/components/scoped-tabs.yaml +97 -0
- package/skills/applying-slds/metadata/blueprints/components/select.yaml +127 -0
- package/skills/applying-slds/metadata/blueprints/components/setup-assistant.yaml +152 -0
- package/skills/applying-slds/metadata/blueprints/components/slider.yaml +111 -0
- package/skills/applying-slds/metadata/blueprints/components/spinners.yaml +135 -0
- package/skills/applying-slds/metadata/blueprints/components/split-view.yaml +112 -0
- package/skills/applying-slds/metadata/blueprints/components/summary-detail.yaml +103 -0
- package/skills/applying-slds/metadata/blueprints/components/tabs.yaml +138 -0
- package/skills/applying-slds/metadata/blueprints/components/textarea.yaml +116 -0
- package/skills/applying-slds/metadata/blueprints/components/tiles.yaml +108 -0
- package/skills/applying-slds/metadata/blueprints/components/timepicker.yaml +111 -0
- package/skills/applying-slds/metadata/blueprints/components/toast.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/tooltips.yaml +107 -0
- package/skills/applying-slds/metadata/blueprints/components/tree-grid.yaml +116 -0
- package/skills/applying-slds/metadata/blueprints/components/trees.yaml +116 -0
- package/skills/applying-slds/metadata/blueprints/components/trial-bar.yaml +112 -0
- package/skills/applying-slds/metadata/blueprints/components/vertical-navigation.yaml +130 -0
- package/skills/applying-slds/metadata/blueprints/components/vertical-tabs.yaml +140 -0
- package/skills/applying-slds/metadata/blueprints/components/visual-picker.yaml +150 -0
- package/skills/applying-slds/metadata/blueprints/components/welcome-mat.yaml +136 -0
- package/skills/applying-slds/metadata/hooks-index.json +6272 -0
- package/skills/applying-slds/metadata/icon-metadata.json +38466 -0
- package/skills/applying-slds/metadata/utilities-index.json +21912 -0
- package/skills/applying-slds/references/component-selection.md +112 -0
- package/skills/applying-slds/references/icons-decision-guide.md +124 -0
- package/skills/applying-slds/references/styling-decision-guide.md +228 -0
- package/skills/applying-slds/references/utilities-quick-ref.md +125 -0
- package/skills/applying-slds/scripts/search-blueprints.cjs +117 -0
- package/skills/applying-slds/scripts/search-hooks.cjs +139 -0
- package/skills/applying-slds/scripts/search-icons.cjs +174 -0
- package/skills/applying-slds/scripts/search-utilities.cjs +161 -0
- package/skills/generating-custom-lightning-type/SKILL.md +17 -39
- package/skills/generating-custom-lightning-type/assets/primitive-types-and-constraints.md +41 -0
- package/skills/generating-custom-lightning-type/references/widget-rendition.md +124 -0
- package/skills/investigating-agentforce-architecture/README.md +156 -0
- package/skills/investigating-agentforce-architecture/SKILL.md +230 -0
- package/skills/investigating-agentforce-architecture/assets/cli/describe_sobject.yaml +16 -0
- package/skills/investigating-agentforce-architecture/assets/cli/describe_tooling_sobject.yaml +17 -0
- package/skills/investigating-agentforce-architecture/assets/cli/list_metadata_genaiprompttemplate.yaml +17 -0
- package/skills/investigating-agentforce-architecture/assets/cli/org_display.yaml +15 -0
- package/skills/investigating-agentforce-architecture/assets/cli/retrieve_genai_plugin.yaml +18 -0
- package/skills/investigating-agentforce-architecture/assets/cli/show_access_token.yaml +27 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/action_tree.mmd +20 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/data_flow.mmd +19 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/dependency_graph.mmd +19 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/invocation_sequence.mmd +20 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/planner_state.mmd +18 -0
- package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_names.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/bot_definition_details.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/bot_version_lookup.soql +4 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_by_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_ids_by_names.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_view_by_durable_ids.soql +4 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_metadata_by_id.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/functions_by_plugins.soql +5 -0
- package/skills/investigating-agentforce-architecture/assets/soql/planner_attrs_by_parent_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/planner_bundle_functions.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/planner_definition_by_agent_chain.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/plugin_functions_by_plugin_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/plugin_instructions_by_plugin_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/plugins_by_planner.soql +4 -0
- package/skills/investigating-agentforce-architecture/references/architecture_sections.md +243 -0
- package/skills/investigating-agentforce-architecture/references/contract.json +244 -0
- package/skills/investigating-agentforce-architecture/references/soql_fields.md +512 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/__init__.py +1 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/fs_guard.py +329 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/paths.py +110 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/runtime.py +59 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/sql.py +10 -0
- package/skills/investigating-agentforce-architecture/scripts/cache_check.py +234 -0
- package/skills/investigating-agentforce-architecture/scripts/config.py +131 -0
- package/skills/investigating-agentforce-architecture/scripts/fetch_soql.py +689 -0
- package/skills/investigating-agentforce-architecture/scripts/finalize.py +295 -0
- package/skills/investigating-agentforce-architecture/scripts/main.py +2835 -0
- package/skills/investigating-agentforce-architecture/scripts/metadata_listing.py +265 -0
- package/skills/investigating-agentforce-architecture/scripts/parallel_retrieve.py +69 -0
- package/skills/investigating-agentforce-architecture/scripts/parse_bundle.py +215 -0
- package/skills/investigating-agentforce-architecture/scripts/parse_wave.py +845 -0
- package/skills/investigating-agentforce-architecture/scripts/probe_channels.py +302 -0
- package/skills/investigating-agentforce-architecture/scripts/render_architecture.py +1043 -0
- package/skills/investigating-agentforce-architecture/scripts/resolve_bot.py +255 -0
- package/skills/investigating-agentforce-architecture/scripts/resolve_invocation_target.py +130 -0
- package/skills/investigating-agentforce-architecture/scripts/rest_client.py +763 -0
- package/skills/investigating-agentforce-architecture/scripts/retrieve_planner.py +13 -0
- package/skills/investigating-agentforce-architecture/scripts/sf_cli.py +242 -0
- package/skills/investigating-agentforce-architecture/scripts/soql_loader.py +253 -0
- package/skills/investigating-agentforce-architecture/scripts/summarize_tree.py +143 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/__init__.py +0 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/_bootstrap.py +23 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/__init__.py +0 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/genai_payloads.py +400 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check.py +307 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check_main.py +283 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_config.py +115 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_end_to_end_fixture.py +651 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_finalize.py +278 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_flow_children_inflation.py +582 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_fs_guard.py +113 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_iterative_wave_b.py +478 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_main_pipeline.py +3359 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parallel_retrieve.py +131 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_bundle.py +400 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave.py +644 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_classifiers.py +224 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_helpers.py +380 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_main.py +397 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_per_branch_visited.py +244 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_channels.py +359 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_cli_recipes.py +185 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_render_architecture.py +810 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_bot.py +203 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_creds.py +157 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_invocation_target.py +145 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_rest_client.py +1253 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_runtime_override.py +100 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_sf_cli.py +261 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_signature_stamping.py +466 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_soql_loader.py +501 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_summarize_tree.py +241 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_write_emit_ctx.py +480 -0
- package/skills/investigating-agentforce-architecture/tools/emit_env.py +157 -0
- package/skills/investigating-agentforce-architecture/tools/emit_result.py +262 -0
- package/skills/investigating-agentforce-architecture/tools/sanitize.py +33 -0
- package/skills/investigating-agentforce-architecture/tools/write_emit_ctx.py +332 -0
- package/skills/investigating-agentforce-d360/README.md +123 -0
- package/skills/investigating-agentforce-d360/SKILL.md +163 -0
- package/skills/investigating-agentforce-d360/assets/dc/app_generation.sql +51 -0
- package/skills/investigating-agentforce-d360/assets/dc/content_category.sql +44 -0
- package/skills/investigating-agentforce-d360/assets/dc/content_quality.sql +41 -0
- package/skills/investigating-agentforce-d360/assets/dc/discover_sessions.sql +36 -0
- package/skills/investigating-agentforce-d360/assets/dc/feedback.sql +47 -0
- package/skills/investigating-agentforce-d360/assets/dc/feedback_details.sql +38 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_records.sql +45 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_request_llm.sql +50 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_request_metadata.sql +44 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_request_tags.sql +42 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_requests.sql +89 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_responses.sql +43 -0
- package/skills/investigating-agentforce-d360/assets/dc/generations.sql +52 -0
- package/skills/investigating-agentforce-d360/assets/dc/interactions.sql +53 -0
- package/skills/investigating-agentforce-d360/assets/dc/messages.sql +53 -0
- package/skills/investigating-agentforce-d360/assets/dc/messaging_session.sql +37 -0
- package/skills/investigating-agentforce-d360/assets/dc/moment_interactions.sql +34 -0
- package/skills/investigating-agentforce-d360/assets/dc/moments.sql +39 -0
- package/skills/investigating-agentforce-d360/assets/dc/participants.sql +48 -0
- package/skills/investigating-agentforce-d360/assets/dc/sessions.sql +78 -0
- package/skills/investigating-agentforce-d360/assets/dc/steps.sql +64 -0
- package/skills/investigating-agentforce-d360/assets/dc/tag_associations.sql +46 -0
- package/skills/investigating-agentforce-d360/assets/dc/tag_definition_associations.sql +37 -0
- package/skills/investigating-agentforce-d360/assets/dc/tag_definitions.sql +50 -0
- package/skills/investigating-agentforce-d360/assets/dc/tags.sql +37 -0
- package/skills/investigating-agentforce-d360/assets/dc/telemetry_spans.sql +55 -0
- package/skills/investigating-agentforce-d360/references/artifacts.md +50 -0
- package/skills/investigating-agentforce-d360/references/dc_dmo_fields.md +823 -0
- package/skills/investigating-agentforce-d360/references/dc_pipeline_contract.md +608 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/__init__.py +2 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/cli_override.py +98 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/fs_guard.py +334 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/paths.py +155 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/runtime.py +59 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/sql.py +14 -0
- package/skills/investigating-agentforce-d360/scripts/assemble_dc.py +1624 -0
- package/skills/investigating-agentforce-d360/scripts/config.py +45 -0
- package/skills/investigating-agentforce-d360/scripts/dc.py +188 -0
- package/skills/investigating-agentforce-d360/scripts/discover_sessions.py +556 -0
- package/skills/investigating-agentforce-d360/scripts/fetch_dc.py +1045 -0
- package/skills/investigating-agentforce-d360/scripts/render_dc.py +1750 -0
- package/skills/investigating-agentforce-d360/scripts/resolve_session.py +264 -0
- package/skills/investigating-agentforce-d360/scripts/storage.py +92 -0
- package/skills/investigating-agentforce-d360/scripts/tests/__init__.py +0 -0
- package/skills/investigating-agentforce-d360/scripts/tests/_bootstrap.py +15 -0
- package/skills/investigating-agentforce-d360/scripts/tests/fixtures/__init__.py +0 -0
- package/skills/investigating-agentforce-d360/scripts/tests/fixtures/synthetic_session.py +424 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_bootstrap_and_mode.py +115 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct.py +220 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct_integration.py +158 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_helpers.py +287 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_integration.py +247 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_dc_and_resolve_session.py +433 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions.py +458 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions_grep_ci.py +193 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_helpers.py +266 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_identity.py +528 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_main.py +251 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall.py +229 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall_full.py +283 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_identity_coherence.py +327 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_branches.py +256 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_gateway_direct.py +130 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_helpers.py +291 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_integration.py +220 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_planner_llm_calls.py +284 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_show_prompts_gating.py +215 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_from_disk.py +100 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_session_main.py +149 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_runtime_override.py +104 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape.py +95 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape_dropped_by_stdm.py +85 -0
- package/skills/managing-managed-event-subscription/SKILL.md +152 -0
- package/skills/managing-managed-event-subscription/assets/managed-event-subscription-template.xml +20 -0
- package/skills/managing-managed-event-subscription/references/delete-guide.md +57 -0
- package/skills/managing-managed-event-subscription/references/topic-name-formats.md +26 -0
- package/skills/managing-managed-event-subscription/references/update-constraints.md +30 -0
- package/skills/uplifting-components-to-slds2/SKILL.md +3 -2
- package/skills/uplifting-components-to-slds2/references/color-hooks-decision-guide.md +30 -9
- package/skills/uplifting-components-to-slds2/references/examples.md +24 -6
- package/skills/validating-slds/SKILL.md +262 -0
- package/skills/validating-slds/references/quality-checks.md +308 -0
- package/skills/validating-slds/references/report-format.md +302 -0
- package/skills/validating-slds/scripts/analyze-quality.cjs +521 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SLDS Quality Analyzer
|
|
5
|
+
*
|
|
6
|
+
* Analyzes CSS and HTML files for SLDS quality issues beyond what the linter catches.
|
|
7
|
+
*
|
|
8
|
+
* Usage: node analyze-quality.cjs <component-path> [--hooks-index <path>]
|
|
9
|
+
*
|
|
10
|
+
* Output: JSON with findings categorized by severity
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
function resolveHooksIndexPath(args) {
|
|
17
|
+
const idx = args.indexOf('--hooks-index');
|
|
18
|
+
if (idx !== -1 && idx + 1 < args.length) {
|
|
19
|
+
return path.resolve(args[idx + 1]);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let HOOKS_INDEX_PATH = null;
|
|
25
|
+
|
|
26
|
+
// Severity levels
|
|
27
|
+
const CRITICAL = 'critical';
|
|
28
|
+
const WARNING = 'warning';
|
|
29
|
+
const INFO = 'info';
|
|
30
|
+
|
|
31
|
+
// Detection patterns
|
|
32
|
+
// NOTE: Checks that the SLDS linter already handles are excluded here to avoid
|
|
33
|
+
// double-counting. The linter covers: slds/class-override (L001),
|
|
34
|
+
// slds/lwc-token-to-slds-hook (L002), slds/no-hardcoded-values (L003).
|
|
35
|
+
// This script focuses on what the linter does NOT catch.
|
|
36
|
+
const PATTERNS = {
|
|
37
|
+
// CSS patterns (linter-complementary only)
|
|
38
|
+
css: {
|
|
39
|
+
missingFallback: {
|
|
40
|
+
pattern: /var\(--slds-g-[^,)]+\)/g,
|
|
41
|
+
severity: CRITICAL,
|
|
42
|
+
id: 'T002',
|
|
43
|
+
message: 'SLDS hook without fallback value',
|
|
44
|
+
recommendation: 'Add fallback: var(--slds-g-color-surface-1, #fff)'
|
|
45
|
+
},
|
|
46
|
+
important: {
|
|
47
|
+
pattern: /!important/g,
|
|
48
|
+
severity: WARNING,
|
|
49
|
+
id: 'Q001',
|
|
50
|
+
message: '!important declaration found',
|
|
51
|
+
recommendation: 'Remove !important, use proper specificity'
|
|
52
|
+
},
|
|
53
|
+
magicPixels: {
|
|
54
|
+
pattern: /\b(?:margin(?:-[a-z-]+)?|padding(?:-[a-z-]+)?|gap|row-gap|column-gap)\s*:\s*(\d+)px\b(?![^;]*var\()/g,
|
|
55
|
+
severity: WARNING,
|
|
56
|
+
id: 'T021',
|
|
57
|
+
message: 'Magic pixel value not using spacing hook',
|
|
58
|
+
recommendation: 'Use var(--slds-g-spacing-*) or utility class'
|
|
59
|
+
},
|
|
60
|
+
highZindex: {
|
|
61
|
+
pattern: /z-index\s*:\s*(\d{3,})/g,
|
|
62
|
+
severity: WARNING,
|
|
63
|
+
id: 'Q021',
|
|
64
|
+
message: 'High z-index value',
|
|
65
|
+
recommendation: 'Use defined z-index scale'
|
|
66
|
+
},
|
|
67
|
+
outlineNone: {
|
|
68
|
+
pattern: /outline\s*:\s*none/g,
|
|
69
|
+
severity: WARNING,
|
|
70
|
+
id: 'A021',
|
|
71
|
+
message: 'Focus outline removed without alternative',
|
|
72
|
+
recommendation: 'Provide alternative focus indicator'
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
// JS patterns (inline styles and dynamic class manipulation)
|
|
76
|
+
js: {
|
|
77
|
+
inlineStyleJS: {
|
|
78
|
+
pattern: /\.style\.\w+\s*=/g,
|
|
79
|
+
severity: WARNING,
|
|
80
|
+
id: 'Q025',
|
|
81
|
+
message: 'Inline style manipulation in JavaScript',
|
|
82
|
+
recommendation: 'Use CSS classes instead of direct style property assignment'
|
|
83
|
+
},
|
|
84
|
+
classListManipulation: {
|
|
85
|
+
pattern: /\.classList\.(add|remove|toggle)\(\s*['"]slds-/g,
|
|
86
|
+
severity: WARNING,
|
|
87
|
+
id: 'Q012',
|
|
88
|
+
message: 'Dynamic SLDS class manipulation in JavaScript',
|
|
89
|
+
recommendation: 'Prefer declarative class bindings; avoid manipulating slds-* classes directly'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
// HTML patterns
|
|
93
|
+
html: {
|
|
94
|
+
inlineStyle: {
|
|
95
|
+
pattern: /style\s*=\s*["'][^"']+["']/gi,
|
|
96
|
+
severity: WARNING,
|
|
97
|
+
id: 'Q002',
|
|
98
|
+
message: 'Inline style attribute',
|
|
99
|
+
recommendation: 'Move styles to CSS file'
|
|
100
|
+
},
|
|
101
|
+
lightningInputNoLabel: {
|
|
102
|
+
pattern: /<lightning-input(?![^>]*\blabel\b)[^>]*>/gi,
|
|
103
|
+
severity: CRITICAL,
|
|
104
|
+
id: 'A001',
|
|
105
|
+
message: 'Lightning input without label attribute',
|
|
106
|
+
recommendation: 'Add label attribute to lightning-input'
|
|
107
|
+
},
|
|
108
|
+
iconNoAlt: {
|
|
109
|
+
pattern: /<lightning-icon(?![^>]*alternative-text)[^>]*>/gi,
|
|
110
|
+
severity: CRITICAL,
|
|
111
|
+
id: 'A004',
|
|
112
|
+
message: 'Icon without alternative-text',
|
|
113
|
+
recommendation: 'Add alternative-text (or empty string for decorative)'
|
|
114
|
+
},
|
|
115
|
+
imgNoAlt: {
|
|
116
|
+
pattern: /<img(?![^>]*\balt\b)[^>]*>/gi,
|
|
117
|
+
severity: CRITICAL,
|
|
118
|
+
id: 'A005',
|
|
119
|
+
message: 'Image without alt attribute',
|
|
120
|
+
recommendation: 'Add alt attribute'
|
|
121
|
+
},
|
|
122
|
+
positiveTabindex: {
|
|
123
|
+
pattern: /tabindex\s*=\s*["']([1-9]\d*)["']/gi,
|
|
124
|
+
severity: WARNING,
|
|
125
|
+
id: 'A020',
|
|
126
|
+
message: 'Positive tabindex value',
|
|
127
|
+
recommendation: 'Use tabindex="0" or "-1" only'
|
|
128
|
+
},
|
|
129
|
+
clickableDiv: {
|
|
130
|
+
pattern: /<div[^>]*onclick[^>]*>/gi,
|
|
131
|
+
severity: WARNING,
|
|
132
|
+
id: 'A022',
|
|
133
|
+
message: 'Div with click handler instead of button',
|
|
134
|
+
recommendation: 'Use <button> or <lightning-button> for interactive elements'
|
|
135
|
+
},
|
|
136
|
+
nativeInput: {
|
|
137
|
+
pattern: /<input\s/gi,
|
|
138
|
+
severity: WARNING,
|
|
139
|
+
id: 'C001',
|
|
140
|
+
message: 'Native input element',
|
|
141
|
+
recommendation: 'Consider <lightning-input> for built-in labeling and validation'
|
|
142
|
+
},
|
|
143
|
+
nativeButton: {
|
|
144
|
+
pattern: /<button\s(?![^>]*class\s*=\s*["'][^"']*slds-button)/gi,
|
|
145
|
+
severity: WARNING,
|
|
146
|
+
id: 'C002',
|
|
147
|
+
message: 'Native button element',
|
|
148
|
+
recommendation: 'Consider <lightning-button> for SLDS styling consistency (suppressed if slds-button class present)'
|
|
149
|
+
},
|
|
150
|
+
nativeSelect: {
|
|
151
|
+
pattern: /<select\s/gi,
|
|
152
|
+
severity: WARNING,
|
|
153
|
+
id: 'C004',
|
|
154
|
+
message: 'Native select element',
|
|
155
|
+
recommendation: 'Consider <lightning-combobox> for consistency'
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Find all files with given extensions in directory
|
|
162
|
+
*/
|
|
163
|
+
function findFiles(dir, extensions) {
|
|
164
|
+
const files = [];
|
|
165
|
+
|
|
166
|
+
function walk(currentDir) {
|
|
167
|
+
try {
|
|
168
|
+
const items = fs.readdirSync(currentDir);
|
|
169
|
+
for (const item of items) {
|
|
170
|
+
const fullPath = path.join(currentDir, item);
|
|
171
|
+
const stat = fs.statSync(fullPath);
|
|
172
|
+
|
|
173
|
+
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
|
|
174
|
+
walk(fullPath);
|
|
175
|
+
} else if (stat.isFile()) {
|
|
176
|
+
const ext = path.extname(item).toLowerCase();
|
|
177
|
+
if (extensions.includes(ext)) {
|
|
178
|
+
files.push(fullPath);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} catch (err) {
|
|
183
|
+
// Skip directories we can't read
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
walk(dir);
|
|
188
|
+
return files;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Analyze a single file
|
|
193
|
+
*/
|
|
194
|
+
function analyzeFile(filePath, patterns) {
|
|
195
|
+
const findings = [];
|
|
196
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
197
|
+
const lines = content.split('\n');
|
|
198
|
+
|
|
199
|
+
for (const [name, config] of Object.entries(patterns)) {
|
|
200
|
+
const regex = new RegExp(config.pattern.source, config.pattern.flags);
|
|
201
|
+
let match;
|
|
202
|
+
|
|
203
|
+
while ((match = regex.exec(content)) !== null) {
|
|
204
|
+
// Find line number
|
|
205
|
+
const beforeMatch = content.substring(0, match.index);
|
|
206
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
207
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
208
|
+
|
|
209
|
+
findings.push({
|
|
210
|
+
id: config.id,
|
|
211
|
+
severity: config.severity,
|
|
212
|
+
file: filePath,
|
|
213
|
+
line: lineNumber,
|
|
214
|
+
column: match.index - beforeMatch.lastIndexOf('\n'),
|
|
215
|
+
match: match[0].substring(0, 50),
|
|
216
|
+
message: config.message,
|
|
217
|
+
recommendation: config.recommendation,
|
|
218
|
+
context: lineContent.trim().substring(0, 80)
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return findings;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Analyze heading hierarchy in HTML
|
|
228
|
+
*/
|
|
229
|
+
function analyzeHeadings(filePath) {
|
|
230
|
+
const findings = [];
|
|
231
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
232
|
+
const headingRegex = /<h([1-6])[^>]*>/gi;
|
|
233
|
+
const headings = [];
|
|
234
|
+
let match;
|
|
235
|
+
|
|
236
|
+
while ((match = headingRegex.exec(content)) !== null) {
|
|
237
|
+
headings.push({
|
|
238
|
+
level: parseInt(match[1]),
|
|
239
|
+
index: match.index
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Check for skipped levels
|
|
244
|
+
for (let i = 1; i < headings.length; i++) {
|
|
245
|
+
const prev = headings[i - 1].level;
|
|
246
|
+
const curr = headings[i].level;
|
|
247
|
+
|
|
248
|
+
if (curr > prev + 1) {
|
|
249
|
+
const beforeMatch = content.substring(0, headings[i].index);
|
|
250
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
251
|
+
|
|
252
|
+
findings.push({
|
|
253
|
+
id: 'A010',
|
|
254
|
+
severity: WARNING,
|
|
255
|
+
file: filePath,
|
|
256
|
+
line: lineNumber,
|
|
257
|
+
message: `Skipped heading level: h${prev} to h${curr}`,
|
|
258
|
+
recommendation: `Use h${prev + 1} instead of h${curr}`
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return findings;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Load valid hook tokens from hooks-index.json
|
|
268
|
+
*/
|
|
269
|
+
let _validHooks = null;
|
|
270
|
+
function loadValidHooks() {
|
|
271
|
+
if (_validHooks) return _validHooks;
|
|
272
|
+
if (!HOOKS_INDEX_PATH) return null;
|
|
273
|
+
try {
|
|
274
|
+
const data = JSON.parse(fs.readFileSync(HOOKS_INDEX_PATH, 'utf-8'));
|
|
275
|
+
_validHooks = new Set(data.hooks.map(h => h.token));
|
|
276
|
+
} catch {
|
|
277
|
+
console.error(`WARNING: Could not load hooks-index.json at ${HOOKS_INDEX_PATH}`);
|
|
278
|
+
console.error('Invented-hook detection (T051) will be skipped.');
|
|
279
|
+
_validHooks = null;
|
|
280
|
+
}
|
|
281
|
+
return _validHooks;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Check for invented hooks (T051) — hooks referenced in CSS that don't exist in metadata
|
|
286
|
+
*/
|
|
287
|
+
function analyzeInventedHooks(filePath) {
|
|
288
|
+
const findings = [];
|
|
289
|
+
const validHooks = loadValidHooks();
|
|
290
|
+
if (!validHooks) return findings; // skip if metadata unavailable
|
|
291
|
+
|
|
292
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
293
|
+
const lines = content.split('\n');
|
|
294
|
+
const hookRef = /var\((--slds-g-[^,)]+)/g;
|
|
295
|
+
let match;
|
|
296
|
+
|
|
297
|
+
while ((match = hookRef.exec(content)) !== null) {
|
|
298
|
+
const hookName = match[1].trim();
|
|
299
|
+
if (!validHooks.has(hookName)) {
|
|
300
|
+
const beforeMatch = content.substring(0, match.index);
|
|
301
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
302
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
303
|
+
|
|
304
|
+
findings.push({
|
|
305
|
+
id: 'T051',
|
|
306
|
+
severity: CRITICAL,
|
|
307
|
+
file: filePath,
|
|
308
|
+
line: lineNumber,
|
|
309
|
+
match: hookName,
|
|
310
|
+
message: `Invented hook — "${hookName}" does not exist in hooks-index.json`,
|
|
311
|
+
recommendation: 'Verify the hook exists via: node scripts/search-hooks.cjs --prefix "' + hookName + '"',
|
|
312
|
+
context: lineContent.trim().substring(0, 80)
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return findings;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Check for hook pairing issues
|
|
322
|
+
*/
|
|
323
|
+
function analyzeHookPairing(filePath) {
|
|
324
|
+
const findings = [];
|
|
325
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
326
|
+
|
|
327
|
+
// Find all background hooks
|
|
328
|
+
const bgHookRegex = /--slds-g-color-(surface|accent|success|warning|error|info)(?:-container)?-\d/g;
|
|
329
|
+
const textHookRegex = /--slds-g-color-on-(surface|accent|success|warning|error|info)(?:-container)?-\d/g;
|
|
330
|
+
|
|
331
|
+
const bgHooks = content.match(bgHookRegex) || [];
|
|
332
|
+
const textHooks = content.match(textHookRegex) || [];
|
|
333
|
+
|
|
334
|
+
// Extract families
|
|
335
|
+
const bgFamilies = new Set(bgHooks.map(h => {
|
|
336
|
+
const match = h.match(/--slds-g-color-(\w+(?:-container)?)-\d/);
|
|
337
|
+
return match ? match[1] : null;
|
|
338
|
+
}).filter(Boolean));
|
|
339
|
+
|
|
340
|
+
const textFamilies = new Set(textHooks.map(h => {
|
|
341
|
+
const match = h.match(/--slds-g-color-on-(\w+(?:-container)?)-\d/);
|
|
342
|
+
return match ? match[1] : null;
|
|
343
|
+
}).filter(Boolean));
|
|
344
|
+
|
|
345
|
+
// Check for mismatches
|
|
346
|
+
for (const bgFamily of bgFamilies) {
|
|
347
|
+
const expectedTextFamily = bgFamily.replace('-container', '');
|
|
348
|
+
if (!textFamilies.has(expectedTextFamily) && !textFamilies.has(bgFamily)) {
|
|
349
|
+
findings.push({
|
|
350
|
+
id: 'T010',
|
|
351
|
+
severity: WARNING,
|
|
352
|
+
file: filePath,
|
|
353
|
+
message: `Background hook family '${bgFamily}' may lack matching text hook`,
|
|
354
|
+
recommendation: `Pair with --slds-g-color-on-${expectedTextFamily}-*`
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return findings;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Calculate scores from findings
|
|
364
|
+
*/
|
|
365
|
+
function calculateScores(findings) {
|
|
366
|
+
const weights = {
|
|
367
|
+
[CRITICAL]: 10,
|
|
368
|
+
[WARNING]: 3,
|
|
369
|
+
[INFO]: 1
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// NOTE: Linter findings (L001, L002, L003) come from the SLDS linter output,
|
|
373
|
+
// not from this script. They should be merged in by the calling agent.
|
|
374
|
+
// This script only produces findings for the other categories.
|
|
375
|
+
const categories = {
|
|
376
|
+
theming: { issues: 0, ids: ['T002', 'T010', 'T011', 'T021', 'T051'] },
|
|
377
|
+
accessibility: { issues: 0, ids: ['A001', 'A004', 'A005', 'A010', 'A020', 'A021', 'A022'] },
|
|
378
|
+
codeQuality: { issues: 0, ids: ['Q001', 'Q002', 'Q012', 'Q021', 'Q025'] },
|
|
379
|
+
componentUsage: { issues: 0, ids: ['C001', 'C002', 'C004'] }
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// Count weighted issues per category
|
|
383
|
+
for (const finding of findings) {
|
|
384
|
+
const weight = weights[finding.severity];
|
|
385
|
+
for (const [category, config] of Object.entries(categories)) {
|
|
386
|
+
if (config.ids.includes(finding.id)) {
|
|
387
|
+
config.issues += weight;
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Calculate scores
|
|
394
|
+
const scores = {};
|
|
395
|
+
for (const [category, config] of Object.entries(categories)) {
|
|
396
|
+
scores[category] = Math.max(0, 100 - config.issues);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return scores;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Get grade from score
|
|
404
|
+
*/
|
|
405
|
+
function getGrade(score) {
|
|
406
|
+
if (score >= 90) return 'A';
|
|
407
|
+
if (score >= 80) return 'B';
|
|
408
|
+
if (score >= 70) return 'C';
|
|
409
|
+
if (score >= 60) return 'D';
|
|
410
|
+
return 'F';
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Main analysis function
|
|
415
|
+
*/
|
|
416
|
+
function analyze(componentPath) {
|
|
417
|
+
const resolvedPath = path.resolve(componentPath);
|
|
418
|
+
|
|
419
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
420
|
+
console.error(`Error: Path does not exist: ${resolvedPath}`);
|
|
421
|
+
process.exit(1);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const findings = [];
|
|
425
|
+
|
|
426
|
+
// Find and analyze CSS files
|
|
427
|
+
const cssFiles = findFiles(resolvedPath, ['.css']);
|
|
428
|
+
for (const file of cssFiles) {
|
|
429
|
+
findings.push(...analyzeFile(file, PATTERNS.css));
|
|
430
|
+
findings.push(...analyzeHookPairing(file));
|
|
431
|
+
findings.push(...analyzeInventedHooks(file));
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Find and analyze HTML files
|
|
435
|
+
const htmlFiles = findFiles(resolvedPath, ['.html']);
|
|
436
|
+
for (const file of htmlFiles) {
|
|
437
|
+
findings.push(...analyzeFile(file, PATTERNS.html));
|
|
438
|
+
findings.push(...analyzeHeadings(file));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Find and analyze JS files
|
|
442
|
+
const jsFiles = findFiles(resolvedPath, ['.js']);
|
|
443
|
+
for (const file of jsFiles) {
|
|
444
|
+
findings.push(...analyzeFile(file, PATTERNS.js));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Calculate scores
|
|
448
|
+
const scores = calculateScores(findings);
|
|
449
|
+
|
|
450
|
+
// Organize findings by severity
|
|
451
|
+
const organized = {
|
|
452
|
+
critical: findings.filter(f => f.severity === CRITICAL),
|
|
453
|
+
warning: findings.filter(f => f.severity === WARNING),
|
|
454
|
+
info: findings.filter(f => f.severity === INFO)
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
// Calculate total lines for complexity classification
|
|
458
|
+
let totalLines = 0;
|
|
459
|
+
for (const file of [...cssFiles, ...htmlFiles, ...jsFiles]) {
|
|
460
|
+
totalLines += fs.readFileSync(file, 'utf-8').split('\n').length;
|
|
461
|
+
}
|
|
462
|
+
const totalFiles = cssFiles.length + htmlFiles.length + jsFiles.length;
|
|
463
|
+
let complexity = 'small';
|
|
464
|
+
if (totalFiles >= 7 || totalLines >= 500) complexity = 'large';
|
|
465
|
+
else if (totalFiles >= 3 || totalLines >= 100) complexity = 'medium';
|
|
466
|
+
|
|
467
|
+
// Build result
|
|
468
|
+
const result = {
|
|
469
|
+
component: path.basename(resolvedPath),
|
|
470
|
+
path: resolvedPath,
|
|
471
|
+
timestamp: new Date().toISOString(),
|
|
472
|
+
complexity: {
|
|
473
|
+
classification: complexity,
|
|
474
|
+
totalFiles,
|
|
475
|
+
totalLines
|
|
476
|
+
},
|
|
477
|
+
note: "These are automated category scores only. Combine them with SLDS linter results and the required Step 3 manual review gate in SKILL.md before making a final ship recommendation.",
|
|
478
|
+
scores: {
|
|
479
|
+
theming: { score: scores.theming, grade: getGrade(scores.theming) },
|
|
480
|
+
accessibility: { score: scores.accessibility, grade: getGrade(scores.accessibility) },
|
|
481
|
+
codeQuality: { score: scores.codeQuality, grade: getGrade(scores.codeQuality) },
|
|
482
|
+
componentUsage: { score: scores.componentUsage, grade: getGrade(scores.componentUsage) }
|
|
483
|
+
},
|
|
484
|
+
findings: organized,
|
|
485
|
+
summary: {
|
|
486
|
+
filesAnalyzed: totalFiles,
|
|
487
|
+
cssFiles: cssFiles.length,
|
|
488
|
+
htmlFiles: htmlFiles.length,
|
|
489
|
+
jsFiles: jsFiles.length,
|
|
490
|
+
totalLines,
|
|
491
|
+
critical: organized.critical.length,
|
|
492
|
+
warnings: organized.warning.length,
|
|
493
|
+
info: organized.info.length
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
return result;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// CLI entry point
|
|
501
|
+
if (require.main === module) {
|
|
502
|
+
const args = process.argv.slice(2);
|
|
503
|
+
const positionalArgs = args.filter((a, i) => !a.startsWith('--') && (i === 0 || !args[i - 1].startsWith('--')));
|
|
504
|
+
|
|
505
|
+
if (positionalArgs.length === 0) {
|
|
506
|
+
console.log('SLDS Quality Analyzer');
|
|
507
|
+
console.log('Usage: node analyze-quality.cjs <component-path> [--hooks-index <path>]');
|
|
508
|
+
console.log('');
|
|
509
|
+
console.log('Options:');
|
|
510
|
+
console.log(' --hooks-index <path> Path to hooks-index.json (optional; enables T051 invented-hook detection)');
|
|
511
|
+
console.log('');
|
|
512
|
+
console.log('Output: JSON analysis of SLDS quality issues');
|
|
513
|
+
process.exit(0);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
HOOKS_INDEX_PATH = resolveHooksIndexPath(args);
|
|
517
|
+
const result = analyze(positionalArgs[0]);
|
|
518
|
+
console.log(JSON.stringify(result, null, 2));
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
module.exports = { analyze, PATTERNS };
|