@salesforce/afv-skills 1.37.0 → 1.38.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/agentforce-generate/README.md +20 -3
- package/skills/agentforce-generate/SKILL.md +253 -440
- package/skills/agentforce-generate/assets/agent-spec-template.md +6 -2
- package/skills/agentforce-generate/assets/agents/order-service.agent +16 -12
- package/skills/agentforce-generate/assets/agents/production-faq.agent +4 -4
- package/skills/agentforce-generate/assets/agents/router-first.agent +5 -5
- package/skills/agentforce-generate/assets/agents/template-single-subagent.agent +4 -4
- package/skills/agentforce-generate/assets/agents/verification-gate.agent +8 -6
- package/skills/agentforce-generate/assets/agents/voice-knowledge-grounded.agent +9 -9
- package/skills/agentforce-generate/assets/agents/voice-service-agent.agent +7 -7
- package/skills/agentforce-generate/assets/patterns/README.md +3 -3
- package/skills/agentforce-generate/assets/patterns/action-callbacks.agent +5 -5
- package/skills/agentforce-generate/assets/patterns/advanced-input-bindings.agent +6 -8
- package/skills/agentforce-generate/assets/patterns/bidirectional-routing.agent +11 -13
- package/skills/agentforce-generate/assets/patterns/critical-input-collection.agent +11 -16
- package/skills/agentforce-generate/assets/patterns/lifecycle-events.agent +2 -3
- package/skills/agentforce-generate/assets/patterns/llm-controlled-actions.agent +6 -7
- package/skills/agentforce-generate/assets/patterns/open-gate-routing.agent +3 -3
- package/skills/agentforce-generate/assets/patterns/prompt-template-action.agent +14 -19
- package/skills/agentforce-generate/assets/patterns/system-instruction-overrides.agent +11 -20
- package/skills/agentforce-generate/references/actions-reference.md +2 -2
- package/skills/agentforce-generate/references/agent-audit-and-repair.md +135 -0
- package/skills/agentforce-generate/references/agent-audit-candidate-verification.md +160 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostic-catalog.md +156 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostics-actions-state.md +176 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostics-architecture-evaluation.md +68 -0
- package/skills/agentforce-generate/references/agent-audit-diagnostics-instructions-routing.md +283 -0
- package/skills/agentforce-generate/references/agent-audit-evaluation-loop.md +191 -0
- package/skills/agentforce-generate/references/agent-audit-repair-report.md +143 -0
- package/skills/agentforce-generate/references/agent-audit-scope-path-review.md +180 -0
- package/skills/agentforce-generate/references/agent-design-and-spec-creation.md +105 -59
- package/skills/agentforce-generate/references/agent-script-core-language.md +144 -61
- package/skills/agentforce-generate/references/agent-subagent-map-diagrams.md +33 -23
- package/skills/agentforce-generate/references/agent-validation-and-debugging.md +37 -11
- package/skills/agentforce-generate/references/agentscript-toolchain.md +112 -0
- package/skills/agentforce-generate/references/architecture-patterns.md +81 -18
- package/skills/agentforce-generate/references/common-control-flow-pitfalls.md +255 -0
- package/skills/agentforce-generate/references/control-flow-actions-sequencing.md +198 -0
- package/skills/agentforce-generate/references/control-flow-lifecycle-side-effects.md +87 -0
- package/skills/agentforce-generate/references/examples.md +22 -22
- package/skills/agentforce-generate/references/instruction-resolution.md +123 -83
- package/skills/agentforce-generate/references/known-issues.md +1 -2
- package/skills/agentforce-generate/references/optimization-pattern-1-data-flow.md +4 -0
- package/skills/agentforce-generate/references/optimization-pattern-2-deterministic-logic.md +33 -0
- package/skills/agentforce-generate/references/optimization-pattern-3-reference-syntax.md +32 -3
- package/skills/agentforce-generate/references/optimization-pattern-4-escalation.md +2 -2
- package/skills/agentforce-generate/references/patterns-by-requirement.md +3 -1
- package/skills/agentforce-generate/references/posture-and-determinism.md +103 -22
- package/skills/agentforce-generate/references/reference-map.md +19 -3
- package/skills/agentforce-generate/references/scoring-rubric.md +1 -1
- package/skills/agentforce-generate/references/voice-latency-heuristics.md +4 -0
- package/skills/agentforce-generate/references/voice-modality-reference.md +4 -4
- package/skills/agentforce-generate/references/zen-of-agentscript.md +139 -23
- package/skills/agentforce-generate/scripts/agentscript-sdk-loader.mjs +133 -0
- package/skills/agentforce-generate/scripts/index-agent.mjs +141 -0
- package/skills/agentforce-generate/scripts/setup-agentscript-sdk.mjs +337 -0
- package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +1 -1
- package/skills/automation-sandbox-post-copy-configure/SKILL.md +433 -0
- package/skills/automation-sandbox-post-copy-configure/assets/api_request_templates.json +89 -0
- package/skills/automation-sandbox-post-copy-configure/examples/sample_config_input.json +40 -0
- package/skills/automation-sandbox-post-copy-configure/examples/sample_execution_summary.md +79 -0
- package/skills/automation-sandbox-post-copy-configure/references/api_endpoints.md +273 -0
- package/skills/automation-sandbox-post-copy-configure/references/authentication.md +94 -0
- package/skills/automation-sandbox-post-copy-configure/references/execution_phasing.md +93 -0
- package/skills/automation-sandbox-post-copy-configure/references/rules_gotchas.md +35 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/classify-patch-result.mjs +88 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/map-metadata-key.mjs +98 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/plan-phases.mjs +98 -0
- package/skills/automation-sandbox-post-copy-configure/scripts/resolve-target-org.mjs +56 -0
- package/skills/design-systems-slds-validate/SKILL.md +14 -13
- package/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md +1 -1
- package/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md +1 -1
- package/skills/dx-org-devhub-configure/SKILL.md +268 -0
- package/skills/dx-org-devhub-configure/examples/status-output.md +39 -0
- package/skills/dx-org-devhub-configure/scripts/devhub.sh +650 -0
- package/skills/dx-org-devhub-configure/scripts/test-devhub.sh +116 -0
- package/skills/dx-org-manage/SKILL.md +135 -42
- package/skills/dx-org-manage/assets/derive-alias.sh +95 -0
- package/skills/dx-org-manage/assets/scratch-def.seed.json +6 -0
- package/skills/dx-org-manage/examples/README.md +1 -1
- package/skills/dx-org-manage/examples/scratch-orgs/delete_output.json +8 -0
- package/skills/dx-org-manage/examples/scratch-orgs/display_output.json +23 -0
- package/skills/dx-org-manage/examples/scratch-orgs/list_output.json +58 -0
- package/skills/dx-org-manage/examples/scratch-orgs/resume_output.json +38 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_definition_file.json +1 -1
- package/skills/dx-org-manage/examples/scratch-orgs/success_edition.json +1 -1
- package/skills/dx-org-manage/examples/scratch-orgs/success_shape.json +41 -0
- package/skills/dx-org-manage/examples/scratch-orgs/success_snapshot.json +1 -1
- package/skills/dx-org-manage/examples/snapshots/error_output.json +3 -3
- package/skills/dx-org-manage/references/creating-scratch-org.md +2 -2
- package/skills/dx-org-manage/references/creating-snapshot.md +1 -2
- package/skills/dx-org-manage/references/definition_file_options.md +24 -0
- package/skills/dx-org-manage/references/edition_types.md +10 -8
- package/skills/dx-org-manage/references/opening-org.md +11 -12
- package/skills/dx-org-manage/references/scratch-org-create.md +303 -0
- package/skills/dx-org-manage/references/scratch-org-operations.md +135 -0
- package/skills/experience-aura-lwc-migrate/SKILL.md +120 -0
- package/skills/experience-aura-lwc-migrate/references/aura-api-expert.md +170 -0
- package/skills/experience-aura-lwc-migrate/references/aura-data-expert.md +172 -0
- package/skills/experience-aura-lwc-migrate/references/aura-migration-guidelines.md +299 -0
- package/skills/experience-aura-lwc-migrate/references/aura-prd-framework.md +79 -0
- package/skills/experience-aura-lwc-migrate/references/aura-redundant-code-expert.md +24 -0
- package/skills/experience-aura-lwc-migrate/references/aura-reference-expert.md +140 -0
- package/skills/experience-aura-lwc-migrate/references/aura-resolver-expert.md +115 -0
- package/skills/experience-aura-lwc-migrate/references/aura-slots-expert.md +67 -0
- package/skills/experience-aura-lwc-migrate/references/aura-style-expert.md +62 -0
- package/skills/experience-aura-lwc-migrate/references/aura-to-lwc-completeness-checklist.md +188 -0
- package/skills/experience-aura-lwc-migrate/references/aura-values-expert.md +67 -0
- package/skills/experience-content-media-search/SKILL.md +17 -12
- package/skills/experience-content-media-stock-image-search/SKILL.md +192 -0
- package/skills/experience-content-media-stock-image-search/scripts/download-stock-image.py +102 -0
- package/skills/experience-lds-best-practices-apply/SKILL.md +245 -0
- package/skills/experience-lds-best-practices-apply/references/adapter-apis.md +1640 -0
- package/skills/experience-lds-best-practices-apply/references/lds-data-consistency.md +126 -0
- package/skills/experience-lds-best-practices-apply/references/lds-expert.md +429 -0
- package/skills/experience-lds-best-practices-apply/references/lds-referential-integrity.md +322 -0
- package/skills/experience-lds-best-practices-apply/references/wire-adapter-types.md +1511 -0
- package/skills/experience-lds-graphql-generate/SKILL.md +222 -0
- package/skills/experience-lds-graphql-generate/references/generation-guide.md +236 -0
- package/skills/experience-lds-graphql-generate/references/generation-mutation.md +277 -0
- package/skills/experience-lds-graphql-generate/references/generation-query.md +237 -0
- package/skills/experience-lds-graphql-generate/scripts/fetch-lds-graphql-schema.sh +230 -0
- package/skills/experience-lds-graphql-generate/scripts/test-lds-graphql-query.sh +128 -0
- package/skills/experience-lwc-accessibility-validate/SKILL.md +112 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-1-1-non-text-content.md +88 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-i-lists.md +52 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-ii-tables.md +106 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-iii-form-labels.md +78 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-iv-regions.md +26 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-1-v-groups.md +66 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-3-5-identify-input.md +70 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-1-4-3-contrast.md +115 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-1-1-keyboard.md +47 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-4-4-link-purpose.md +39 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-4-6-headings-labels.md +50 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-1-pointer-gestures.md +54 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-2-pointer-cancellation.md +49 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-3-label-in-name.md +77 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-2-5-7-dragging-movement.md +45 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-2-1-on-focus.md +55 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-2-2-on-input.md +51 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-3-1-error-identification.md +84 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-3-2-labels-instructions.md +50 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-3-3-3-error-suggestion.md +64 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-4-1-2-i-name.md +105 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-4-1-2-ii-role.md +99 -0
- package/skills/experience-lwc-accessibility-validate/references/reviewers/sc-4-1-2-iii-value.md +97 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-1-1-non-text-content.md +83 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-1-use-of-color.md +62 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-10-resize-reflow.md +18 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-11-non-text-contrast.md +43 -0
- package/skills/experience-lwc-accessibility-validate/references/vision/sc-1-4-3-contrast.md +25 -0
- package/skills/experience-lwc-accessibility-validate/scripts/contrast-ratio.py +153 -0
- package/skills/experience-lwc-design-generate/SKILL.md +261 -0
- package/skills/experience-lwc-design-generate/references/figma-to-prd-blueprint.md +66 -0
- package/skills/experience-lwc-design-generate/references/prd-analysis-template.md +17 -0
- package/skills/experience-lwc-design-generate/scripts/check-component-name.sh +75 -0
- package/skills/experience-lwc-design-generate/scripts/detect-project-tools.sh +97 -0
- package/skills/experience-lwc-runtime-observe/SKILL.md +244 -0
- package/skills/experience-lwc-runtime-observe/examples/component-preview-and-dom.md +41 -0
- package/skills/experience-lwc-runtime-observe/scripts/extract-dom.sh +79 -0
- package/skills/experience-lwc-runtime-observe/scripts/open-frontdoor.sh +46 -0
- package/skills/experience-lwc-runtime-observe/scripts/verify-toolchain.sh +48 -0
- package/skills/experience-lwc-security-validate/SKILL.md +151 -0
- package/skills/experience-lwc-security-validate/examples/review-report.md +6 -0
- package/skills/experience-lwc-security-validate/examples/score-report.sarif.json +32 -0
- package/skills/experience-lwc-security-validate/references/lws-security-expert.md +986 -0
- package/skills/experience-lwc-security-validate/references/security-analysis.md +611 -0
- package/skills/experience-lwc-security-validate/scripts/check-lwc-import.sh +166 -0
- package/skills/experience-lwc-security-validate/scripts/validate-sarif.sh +131 -0
- package/skills/experience-ui-bundle-2gp-deploy/SKILL.md +454 -0
- package/skills/experience-ui-bundle-2gp-deploy/assets/CustomApplication.app-meta.xml +12 -0
- package/skills/experience-ui-bundle-2gp-deploy/assets/PermissionSet.permissionset-meta.xml +9 -0
- package/skills/experience-ui-bundle-2gp-deploy/scripts/find-bundle-package-dir.sh +53 -0
- package/skills/experience-ui-bundle-agentforce-client-generate/SKILL.md +104 -26
- package/skills/experience-ui-bundle-agentforce-client-generate/references/constraints.md +35 -24
- package/skills/experience-ui-bundle-agentforce-client-generate/references/examples.md +92 -1
- package/skills/experience-ui-bundle-agentforce-client-generate/references/style-tokens.md +2 -0
- package/skills/experience-ui-bundle-agentforce-client-generate/references/troubleshooting.md +14 -1
- package/skills/experience-ui-bundle-agentforce-client-generate/scripts/detect-framework.sh +67 -0
- package/skills/experience-ui-bundle-deploy/SKILL.md +83 -14
- package/skills/experience-ui-bundle-deploy/assets/Communities.settings-meta.xml +19 -0
- package/skills/experience-ui-bundle-deploy/assets/org-setup.config.template.json +5 -0
- package/skills/experience-ui-bundle-deploy/assets/social-login-auth-providers.apex +158 -0
- package/skills/experience-ui-bundle-deploy/references/config-scaffold.md +13 -1
- package/skills/experience-ui-bundle-deploy/references/social-login.md +179 -0
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +14 -0
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +6 -5
- package/skills/experience-ui-bundle-mfa-configure/references/social-login.md +15 -7
- package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +41 -5
- package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +10 -22
- package/skills/experience-ui-bundle-salesforce-data-access/references/graphql-hand-authoring.md +4 -19
- package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +5 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +33 -150
- package/skills/mobile-platform-native-capabilities-integrate/references/nfc.md +35 -0
- package/skills/platform-apex-generate/SKILL.md +8 -7
- package/skills/platform-apex-test-generate/SKILL.md +3 -1
- package/skills/platform-apex-test-run/SKILL.md +9 -8
- package/skills/platform-lightning-type-widget-coordinate/SKILL.md +1 -1
- package/skills/platform-lightning-type-widget-coordinate/examples/existing-lightning-type-with-widget-prompt.md +1 -1
- package/skills/platform-lightning-type-widget-coordinate/examples/new-lightning-type-with-widget-prompt.md +1 -1
- package/skills/platform-lightning-type-widget-coordinate/references/validation-gates.md +3 -3
- package/skills/platform-mcp-tool-widget-coordinate/SKILL.md +43 -67
- package/skills/platform-mcp-tool-widget-coordinate/examples/action-name-source-prompt.md +1 -2
- package/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md +2 -3
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-list-source-prompt.md +163 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-single-source-prompt.md +198 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/pasted-tool-output-prompt.md +0 -1
- package/skills/platform-mcp-tool-widget-coordinate/references/build-plan-format.md +17 -11
- package/skills/platform-mcp-tool-widget-coordinate/references/mcp-tool-output-discovery.md +48 -15
- package/skills/platform-mcp-tool-widget-coordinate/references/two-clt-modeling.md +73 -10
- package/skills/platform-mcp-tool-widget-coordinate/references/validation-gates.md +48 -8
- package/skills/platform-policy-rule-generate/SKILL.md +22 -12
- package/skills/platform-policy-rule-generate/references/deploy-errors.md +1 -1
- package/skills/platform-policy-rule-generate/references/policy-schema-full.md +8 -29
- package/skills/platform-policy-rule-generate/references/templates-advanced.md +1 -1
- package/skills/platform-sharing-owd-configure/SKILL.md +20 -8
- package/skills/platform-sharing-owd-configure/references/access_levels.md +14 -1
- package/skills/platform-sharing-rules-generate/SKILL.md +67 -35
- package/skills/platform-sharing-rules-generate/examples/create-cases.md +16 -17
- package/skills/platform-sharing-rules-generate/examples/delete-cases.md +34 -79
- package/skills/platform-sharing-rules-generate/examples/edit-cases.md +13 -26
- package/skills/platform-sharing-rules-generate/scripts/count-remaining-rules.sh +33 -0
- package/skills/platform-widget-generate/SKILL.md +3 -5
- package/skills/platform-widget-generate/examples/conditional.json +18 -13
- package/skills/platform-widget-generate/examples/list-with-foreach.json +2 -2
- package/skills/platform-widget-generate/examples/single-object.json +2 -2
- package/skills/platform-widget-generate/references/schema-from-lightning-type.md +27 -6
- package/skills/platform-widget-generate/references/widget-bundle-layout.md +4 -3
- package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +287 -0
- package/skills/service-itsm-agentic-setup-cmdb-access-assign/references/mcp-invocation.md +260 -0
- package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +252 -0
- package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/references/mcp-invocation.md +204 -0
- package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +259 -0
- package/skills/service-itsm-agentic-setup-cmdb-configure/references/mcp-invocation.md +188 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +197 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/examples/output-templates.md +77 -0
- package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +316 -0
- package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/references/mcp-invocation.md +221 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +168 -0
- package/skills/service-itsm-incident-priority-configure/examples/matrix-operations.md +200 -0
- package/skills/service-itsm-incident-priority-configure/examples/render-matrix.md +54 -0
- package/skills/service-itsm-incident-priority-configure/examples/seed-full-matrix.md +52 -0
- package/skills/service-itsm-incident-priority-configure/references/sf-cli-invocation.md +264 -0
- package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-source-prompt.md +0 -191
- package/skills/platform-policy-rule-generate/references/fixtures-index.md +0 -29
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# LDS GraphQL Schema Fetcher
|
|
4
|
+
#
|
|
5
|
+
# Fetches the Salesforce LDS GraphQL schema for a connected org by POSTing a
|
|
6
|
+
# full introspection query to /services/data/vX/graphql, then renders the
|
|
7
|
+
# response as SDL on disk so the skill can introspect it with targeted grep
|
|
8
|
+
# calls. (LDS does not expose a /graphql/sdl endpoint — introspection is the
|
|
9
|
+
# only path.)
|
|
10
|
+
#
|
|
11
|
+
# The schema content never enters the chat context — only the file path is
|
|
12
|
+
# returned to the user.
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# fetch-lds-graphql-schema.sh USERNAME_OR_ALIAS [OUTPUT_PATH] [API_VERSION]
|
|
16
|
+
#
|
|
17
|
+
# Arguments:
|
|
18
|
+
# $1 usernameOrAlias SF CLI alias or username for the target org (required)
|
|
19
|
+
# $2 outputPath File to write SDL to (default: schema.graphql)
|
|
20
|
+
# $3 apiVersion API version (default: 62.0, matching the legacy
|
|
21
|
+
# fetch_lds_graphql_schema MCP tool's DEFAULT_API_VERSION)
|
|
22
|
+
#
|
|
23
|
+
# Exit codes:
|
|
24
|
+
# 0 Schema written successfully
|
|
25
|
+
# 1 Argument error
|
|
26
|
+
# 2 Salesforce CLI missing
|
|
27
|
+
# 3 Auth or HTTP failure
|
|
28
|
+
# 4 Schema response was empty, contained errors, or had no types
|
|
29
|
+
|
|
30
|
+
set -euo pipefail
|
|
31
|
+
|
|
32
|
+
if [ $# -lt 1 ]; then
|
|
33
|
+
echo "Usage: $0 USERNAME_OR_ALIAS [OUTPUT_PATH] [API_VERSION]" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
ALIAS="$1"
|
|
38
|
+
OUTPUT_PATH="${2:-schema.graphql}"
|
|
39
|
+
API_VERSION="${3:-62.0}"
|
|
40
|
+
|
|
41
|
+
# Skip the fetch when a non-empty schema file is already on disk. Re-fetching
|
|
42
|
+
# is a 30-90s introspection round-trip, so a deterministic short-circuit keeps
|
|
43
|
+
# repeated invocations idempotent. Set LDS_FETCH_FORCE=1 to override.
|
|
44
|
+
if [ -s "$OUTPUT_PATH" ] && [ "${LDS_FETCH_FORCE:-0}" != "1" ]; then
|
|
45
|
+
echo "Schema already present at ${OUTPUT_PATH} — skipping introspection." >&2
|
|
46
|
+
echo "Set LDS_FETCH_FORCE=1 to re-fetch." >&2
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Output-path containment: refuse paths that escape the current working
|
|
51
|
+
# directory (e.g. ../../etc/passwd, /tmp/foo, symlinks pointing outside).
|
|
52
|
+
# Uses python3's os.path.realpath to resolve `..`, `.`, and symlinks even
|
|
53
|
+
# when intermediate directories don't exist yet — the previous bash-`pwd`
|
|
54
|
+
# approach was bypassable in two ways:
|
|
55
|
+
# 1. when the parent didn't exist, the fallback `$PWD/$(dirname ...)`
|
|
56
|
+
# kept `..` segments uncollapsed (e.g. `nonexistent/../../etc` would
|
|
57
|
+
# string-prefix-match `$PWD` even though it escapes);
|
|
58
|
+
# 2. bash's `cd` returns the *logical* path, so a symlink under `$PWD`
|
|
59
|
+
# pointing outside would prefix-match `$PWD` while the real target
|
|
60
|
+
# sat elsewhere on disk.
|
|
61
|
+
PWD_REAL=$(python3 -c 'import os; print(os.path.realpath("."))')
|
|
62
|
+
OUTPUT_REAL=$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$OUTPUT_PATH")
|
|
63
|
+
case "$OUTPUT_REAL/" in
|
|
64
|
+
"$PWD_REAL"/*) ;;
|
|
65
|
+
*)
|
|
66
|
+
echo "ERROR: refusing to write to '$OUTPUT_PATH' — resolved path '$OUTPUT_REAL' escapes \$PWD ($PWD_REAL)." >&2
|
|
67
|
+
echo " Pass an output path that resolves under the current working directory." >&2
|
|
68
|
+
exit 1
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
|
|
72
|
+
if ! command -v sf &>/dev/null; then
|
|
73
|
+
echo "ERROR: Salesforce CLI (sf) is not installed." >&2
|
|
74
|
+
echo "Install: https://developer.salesforce.com/tools/salesforcecli" >&2
|
|
75
|
+
exit 2
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
GRAPHQL_PATH="/services/data/v${API_VERSION}/graphql"
|
|
79
|
+
|
|
80
|
+
echo "Fetching LDS GraphQL schema for org '${ALIAS}' (api v${API_VERSION})..." >&2
|
|
81
|
+
echo "Introspection can take 30-90s for large orgs." >&2
|
|
82
|
+
|
|
83
|
+
INTROSPECTION_QUERY='{"query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { kind name description fields(includeDeprecated: true) { name description args { name description type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } defaultValue } type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } isDeprecated deprecationReason } inputFields { name description type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } defaultValue } interfaces { kind name ofType { kind name } } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { kind name } } } }","variables":{},"operationName":"IntrospectionQuery"}'
|
|
84
|
+
|
|
85
|
+
INTROSPECTION_FILE=$(mktemp)
|
|
86
|
+
trap 'rm -f "$INTROSPECTION_FILE"' EXIT
|
|
87
|
+
|
|
88
|
+
# Use `sf api request rest`, which authenticates internally from the CLI's
|
|
89
|
+
# stored credentials — the access token never enters this script's process
|
|
90
|
+
# arguments, environment, or shell history (Prizm S1). Body is passed via a
|
|
91
|
+
# temp file (`--body @file`) so the query text also stays out of the argv.
|
|
92
|
+
BODY_FILE=$(mktemp)
|
|
93
|
+
trap 'rm -f "$INTROSPECTION_FILE" "$BODY_FILE"' EXIT
|
|
94
|
+
printf '%s' "$INTROSPECTION_QUERY" >"$BODY_FILE"
|
|
95
|
+
|
|
96
|
+
if ! sf api request rest "$GRAPHQL_PATH" \
|
|
97
|
+
--target-org "$ALIAS" \
|
|
98
|
+
--method POST \
|
|
99
|
+
--header "Content-Type: application/json" \
|
|
100
|
+
--header "X-Chatter-Entity-Encoding: false" \
|
|
101
|
+
--body "@${BODY_FILE}" \
|
|
102
|
+
>"$INTROSPECTION_FILE" 2>"${INTROSPECTION_FILE}.err"; then
|
|
103
|
+
# `sf api request rest` exits non-zero on auth failure or HTTP >= 400.
|
|
104
|
+
# Don't echo the response/error body — Salesforce error payloads can carry
|
|
105
|
+
# request headers or signed front-door URLs we don't want in shared logs.
|
|
106
|
+
echo "ERROR: Introspection request failed for org '${ALIAS}'." >&2
|
|
107
|
+
echo " If authentication expired, re-authenticate: sf org login web --alias $ALIAS" >&2
|
|
108
|
+
echo " Diagnostic output left at: ${INTROSPECTION_FILE}.err" >&2
|
|
109
|
+
echo " Inspect with: head -c 500 \"${INTROSPECTION_FILE}.err\" (and remove when done)" >&2
|
|
110
|
+
trap 'rm -f "$BODY_FILE"' EXIT # leave response + err in place for the user
|
|
111
|
+
exit 3
|
|
112
|
+
fi
|
|
113
|
+
rm -f "${INTROSPECTION_FILE}.err"
|
|
114
|
+
|
|
115
|
+
if [ ! -s "$INTROSPECTION_FILE" ]; then
|
|
116
|
+
echo "ERROR: Empty introspection response." >&2
|
|
117
|
+
exit 4
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
OUTPUT_DIR="$(dirname "$OUTPUT_PATH")"
|
|
121
|
+
[ -n "$OUTPUT_DIR" ] && mkdir -p "$OUTPUT_DIR"
|
|
122
|
+
|
|
123
|
+
python3 - "$INTROSPECTION_FILE" "$OUTPUT_PATH" <<'PYEOF'
|
|
124
|
+
import json, sys
|
|
125
|
+
|
|
126
|
+
intro_path, out_path = sys.argv[1], sys.argv[2]
|
|
127
|
+
|
|
128
|
+
with open(intro_path) as f:
|
|
129
|
+
payload = json.load(f)
|
|
130
|
+
|
|
131
|
+
errors = payload.get("errors") or []
|
|
132
|
+
schema = (payload.get("data") or {}).get("__schema") or {}
|
|
133
|
+
types = schema.get("types") or []
|
|
134
|
+
|
|
135
|
+
if errors:
|
|
136
|
+
print(f"ERROR: introspection returned {len(errors)} errors. First: {errors[0]}", file=sys.stderr)
|
|
137
|
+
sys.exit(4)
|
|
138
|
+
if not types:
|
|
139
|
+
print("ERROR: introspection returned zero types.", file=sys.stderr)
|
|
140
|
+
sys.exit(4)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def render_type_ref(t):
|
|
144
|
+
"""Recursively render a type reference like NonNull(List(NonNull(Account)))."""
|
|
145
|
+
if t is None:
|
|
146
|
+
return "Unknown"
|
|
147
|
+
kind = t.get("kind")
|
|
148
|
+
if kind == "NON_NULL":
|
|
149
|
+
return render_type_ref(t.get("ofType")) + "!"
|
|
150
|
+
if kind == "LIST":
|
|
151
|
+
return "[" + render_type_ref(t.get("ofType")) + "]"
|
|
152
|
+
return t.get("name") or "Unknown"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def render_args(args):
|
|
156
|
+
if not args:
|
|
157
|
+
return ""
|
|
158
|
+
rendered = []
|
|
159
|
+
for a in args:
|
|
160
|
+
s = f"{a['name']}: {render_type_ref(a.get('type'))}"
|
|
161
|
+
if a.get("defaultValue") is not None:
|
|
162
|
+
s += f" = {a['defaultValue']}"
|
|
163
|
+
rendered.append(s)
|
|
164
|
+
return "(" + ", ".join(rendered) + ")"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def render_fields(fields):
|
|
168
|
+
out = []
|
|
169
|
+
for f in fields or []:
|
|
170
|
+
line = f" {f['name']}{render_args(f.get('args'))}: {render_type_ref(f.get('type'))}"
|
|
171
|
+
if f.get("isDeprecated"):
|
|
172
|
+
reason = (f.get("deprecationReason") or "").replace('"', '\\"')
|
|
173
|
+
line += f' @deprecated(reason: "{reason}")'
|
|
174
|
+
out.append(line)
|
|
175
|
+
return "\n".join(out)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def render_input_fields(fields):
|
|
179
|
+
out = []
|
|
180
|
+
for f in fields or []:
|
|
181
|
+
line = f" {f['name']}: {render_type_ref(f.get('type'))}"
|
|
182
|
+
if f.get("defaultValue") is not None:
|
|
183
|
+
line += f" = {f['defaultValue']}"
|
|
184
|
+
out.append(line)
|
|
185
|
+
return "\n".join(out)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# Render in stable order; skip GraphQL builtin __ types (introspection meta-types).
|
|
189
|
+
chunks = []
|
|
190
|
+
for t in sorted(types, key=lambda x: (x.get("name") or "")):
|
|
191
|
+
name = t.get("name") or ""
|
|
192
|
+
kind = t.get("kind")
|
|
193
|
+
if name.startswith("__"):
|
|
194
|
+
continue
|
|
195
|
+
if kind == "OBJECT":
|
|
196
|
+
interfaces = t.get("interfaces") or []
|
|
197
|
+
impl = ""
|
|
198
|
+
if interfaces:
|
|
199
|
+
impl = " implements " + " & ".join(i["name"] for i in interfaces if i.get("name"))
|
|
200
|
+
body = render_fields(t.get("fields"))
|
|
201
|
+
chunks.append(f"type {name}{impl} {{\n{body}\n}}")
|
|
202
|
+
elif kind == "INTERFACE":
|
|
203
|
+
body = render_fields(t.get("fields"))
|
|
204
|
+
chunks.append(f"interface {name} {{\n{body}\n}}")
|
|
205
|
+
elif kind == "INPUT_OBJECT":
|
|
206
|
+
body = render_input_fields(t.get("inputFields"))
|
|
207
|
+
chunks.append(f"input {name} {{\n{body}\n}}")
|
|
208
|
+
elif kind == "ENUM":
|
|
209
|
+
values = "\n".join(f" {v['name']}" for v in (t.get("enumValues") or []))
|
|
210
|
+
chunks.append(f"enum {name} {{\n{values}\n}}")
|
|
211
|
+
elif kind == "UNION":
|
|
212
|
+
members = " | ".join(p["name"] for p in (t.get("possibleTypes") or []) if p.get("name"))
|
|
213
|
+
chunks.append(f"union {name} = {members}")
|
|
214
|
+
elif kind == "SCALAR":
|
|
215
|
+
# Skip the standard scalars; emit only org-defined ones.
|
|
216
|
+
if name in ("String", "Int", "Float", "Boolean", "ID"):
|
|
217
|
+
continue
|
|
218
|
+
chunks.append(f"scalar {name}")
|
|
219
|
+
|
|
220
|
+
with open(out_path, "w") as f:
|
|
221
|
+
f.write("\n\n".join(chunks))
|
|
222
|
+
f.write("\n")
|
|
223
|
+
|
|
224
|
+
# Sanity: count Record-implementing types so the caller can sanity-check the output.
|
|
225
|
+
record_count = sum(1 for t in types if any((i.get("name") == "Record") for i in (t.get("interfaces") or [])))
|
|
226
|
+
print(f"types_total={len(types)} types_implementing_Record={record_count}", file=sys.stderr)
|
|
227
|
+
PYEOF
|
|
228
|
+
|
|
229
|
+
LINE_COUNT=$(wc -l <"$OUTPUT_PATH" | tr -d ' ')
|
|
230
|
+
echo "Schema written to ${OUTPUT_PATH} (${LINE_COUNT} lines)." >&2
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# LDS GraphQL Query Tester
|
|
4
|
+
#
|
|
5
|
+
# Executes a GraphQL query or mutation against the LDS endpoint of a connected
|
|
6
|
+
# Salesforce org and prints the raw JSON response. Use this to validate a
|
|
7
|
+
# generated query end-to-end before handing it to the developer.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# test-lds-graphql-query.sh USERNAME_OR_ALIAS 'GRAPHQL_QUERY' ['VARIABLES_JSON'] [API_VERSION] [OPERATION_NAME]
|
|
11
|
+
#
|
|
12
|
+
# Arguments:
|
|
13
|
+
# $1 usernameOrAlias SF CLI alias or username for the target org (required)
|
|
14
|
+
# $2 query Complete GraphQL query or mutation string (required)
|
|
15
|
+
# $3 variables Variables JSON object (default: {})
|
|
16
|
+
# $4 apiVersion API version (default: 66.0, matching the legacy
|
|
17
|
+
# test_lds_graphql_query MCP tool's DEFAULT_API_VERSION)
|
|
18
|
+
# $5 operationName Operation to run when the query string defines
|
|
19
|
+
# multiple named operations (default: omitted)
|
|
20
|
+
#
|
|
21
|
+
# Exit codes:
|
|
22
|
+
# 0 Query executed and returned HTTP 200 (the response itself may still
|
|
23
|
+
# contain a GraphQL `errors` field; the caller categorizes those)
|
|
24
|
+
# 1 Argument error
|
|
25
|
+
# 2 Salesforce CLI missing
|
|
26
|
+
# 3 Auth or HTTP failure
|
|
27
|
+
|
|
28
|
+
set -euo pipefail
|
|
29
|
+
|
|
30
|
+
if [ $# -lt 2 ]; then
|
|
31
|
+
echo "Usage: $0 USERNAME_OR_ALIAS 'GRAPHQL_QUERY' ['VARIABLES_JSON'] [API_VERSION] [OPERATION_NAME]" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
ALIAS="$1"
|
|
36
|
+
QUERY="$2"
|
|
37
|
+
VARIABLES="${3-}"
|
|
38
|
+
[ -z "$VARIABLES" ] && VARIABLES='{}'
|
|
39
|
+
API_VERSION="${4:-66.0}"
|
|
40
|
+
OPERATION_NAME="${5-}"
|
|
41
|
+
|
|
42
|
+
# Mutation guard: this script's name says "tester" — by default we refuse to
|
|
43
|
+
# execute write operations (`mutation`) since they have side effects on the
|
|
44
|
+
# connected org. Set LDS_ALLOW_MUTATIONS=1 to opt in when intentionally
|
|
45
|
+
# testing a mutation.
|
|
46
|
+
#
|
|
47
|
+
# Detection runs in python3 so we can:
|
|
48
|
+
# 1. Strip line comments (`# ...`) before scanning, so a `# mutation note`
|
|
49
|
+
# comment doesn't trip the guard.
|
|
50
|
+
# 2. Anchor on operation-start (`^mutation` or `}\smutation`), not bash
|
|
51
|
+
# word-class boundaries — bash's `[[:space:]]|\{|$` boundary class
|
|
52
|
+
# missed `mutation(...)` (variables), `mutation@auth` (directives),
|
|
53
|
+
# and `mutation#comment`, all of which are valid GraphQL.
|
|
54
|
+
# 3. Avoid the `query { mutation: get }` field-alias false positive:
|
|
55
|
+
# `mutation` only counts when followed by name / vars / directive /
|
|
56
|
+
# `{`, not by `:` (alias) or `=` (default value).
|
|
57
|
+
if [ "${LDS_ALLOW_MUTATIONS:-0}" != "1" ]; then
|
|
58
|
+
if ! printf '%s' "$QUERY" | python3 -c '
|
|
59
|
+
import re, sys
|
|
60
|
+
src = sys.stdin.read()
|
|
61
|
+
# Strip GraphQL line comments (`# ...` to end of line) before scanning.
|
|
62
|
+
src = re.sub(r"#[^\n]*", "", src)
|
|
63
|
+
# Trim leading whitespace so the `^` anchor below sees the first real
|
|
64
|
+
# token. Heredocs, file-read queries, and multiline shell strings often
|
|
65
|
+
# carry leading newlines/spaces that would otherwise hide a top-level
|
|
66
|
+
# `mutation` from the `^mutation` branch.
|
|
67
|
+
src = src.lstrip()
|
|
68
|
+
# Match `mutation` only at operation-start: either at the start of the
|
|
69
|
+
# stripped source, or after a `}` that closes a previous operation. The
|
|
70
|
+
# trailing class accepts every valid follow-up for a mutation operation:
|
|
71
|
+
# identifier (name), `(` (variables), `@` (directive), `{` (anonymous
|
|
72
|
+
# body), whitespace, or end-of-input. This deliberately excludes `:`
|
|
73
|
+
# (field alias, e.g. `query { mutation: get }`) and `=` (default value).
|
|
74
|
+
if re.search(r"(?:^|\}\s*)mutation(?:\s|$|[A-Za-z_(@{])", src):
|
|
75
|
+
sys.exit(2)
|
|
76
|
+
sys.exit(0)
|
|
77
|
+
'; then
|
|
78
|
+
echo "ERROR: refusing to execute a mutation — this script is a read-only tester by default." >&2
|
|
79
|
+
echo " To intentionally run a mutation, re-invoke with LDS_ALLOW_MUTATIONS=1:" >&2
|
|
80
|
+
echo " LDS_ALLOW_MUTATIONS=1 $0 ..." >&2
|
|
81
|
+
exit 1
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if ! command -v sf &>/dev/null; then
|
|
86
|
+
echo "ERROR: Salesforce CLI (sf) is not installed." >&2
|
|
87
|
+
exit 2
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
GRAPHQL_PATH="/services/data/v${API_VERSION}/graphql"
|
|
91
|
+
|
|
92
|
+
REQUEST_BODY=$(python3 -c '
|
|
93
|
+
import sys, json
|
|
94
|
+
body = {"query": sys.argv[1], "variables": json.loads(sys.argv[2].strip())}
|
|
95
|
+
if sys.argv[3]:
|
|
96
|
+
body["operationName"] = sys.argv[3]
|
|
97
|
+
print(json.dumps(body))
|
|
98
|
+
' "$QUERY" "$VARIABLES" "$OPERATION_NAME")
|
|
99
|
+
|
|
100
|
+
RESPONSE_FILE=$(mktemp)
|
|
101
|
+
BODY_FILE=$(mktemp)
|
|
102
|
+
trap 'rm -f "$RESPONSE_FILE" "$BODY_FILE"' EXIT
|
|
103
|
+
printf '%s' "$REQUEST_BODY" >"$BODY_FILE"
|
|
104
|
+
|
|
105
|
+
# Use `sf api request rest`, which authenticates internally from the CLI's
|
|
106
|
+
# stored credentials — the access token never enters this script's process
|
|
107
|
+
# arguments, environment, or shell history (Prizm S1). Body is passed via a
|
|
108
|
+
# temp file (`--body @file`) so the query text also stays out of the argv.
|
|
109
|
+
if ! sf api request rest "$GRAPHQL_PATH" \
|
|
110
|
+
--target-org "$ALIAS" \
|
|
111
|
+
--method POST \
|
|
112
|
+
--header "Content-Type: application/json" \
|
|
113
|
+
--header "X-Chatter-Entity-Encoding: false" \
|
|
114
|
+
--body "@${BODY_FILE}" \
|
|
115
|
+
>"$RESPONSE_FILE" 2>"${RESPONSE_FILE}.err"; then
|
|
116
|
+
# `sf api request rest` exits non-zero on auth failure or HTTP >= 400.
|
|
117
|
+
# Don't echo the response/error body — Salesforce error payloads can carry
|
|
118
|
+
# request headers or signed URLs we don't want surfacing in shared logs.
|
|
119
|
+
echo "ERROR: GraphQL request failed for org '${ALIAS}'." >&2
|
|
120
|
+
echo " If authentication expired, re-authenticate: sf org login web --alias $ALIAS" >&2
|
|
121
|
+
echo " Diagnostic output left at: ${RESPONSE_FILE}.err" >&2
|
|
122
|
+
echo " Inspect with: head -c 500 \"${RESPONSE_FILE}.err\" (and remove when done)" >&2
|
|
123
|
+
trap 'rm -f "$BODY_FILE"' EXIT # leave response + err in place for the user
|
|
124
|
+
exit 3
|
|
125
|
+
fi
|
|
126
|
+
rm -f "${RESPONSE_FILE}.err"
|
|
127
|
+
|
|
128
|
+
cat "$RESPONSE_FILE"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: experience-lwc-accessibility-validate
|
|
3
|
+
description: "Use this skill to determine whether a Lightning Web Component (LWC) is accessible and meets WCAG accessibility guidelines. TRIGGER when the user asks \"is my component accessible?\", \"does my LWC meet accessibility guidelines?\", \"is this component WCAG compliant?\", \"find accessibility problems in this LWC\", \"is this LWC keyboard accessible?\", \"does this component work with a screen reader?\", \"does this component have sufficient color contrast?\", \"check ARIA usage in this LWC\", or \"WCAG 2.2 accessibility check\". Also TRIGGER when the user wants to fix or improve accessibility (a11y, WCAG, ARIA) in an LWC's HTML, JS, or CSS — semantic markup, focus, keyboard nav, contrast, screen-reader labels, WCAG 2.2 SC. Produces `a11y-review.md` with WCAG-cited findings. DO NOT TRIGGER for general LWC generation (use `experience-lwc-generate`) or SLDS visual/design review not focused on accessibility (use `design-systems-slds-validate`)."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.1"
|
|
6
|
+
cliTools:
|
|
7
|
+
- tool: ["python3"]
|
|
8
|
+
semver: ">=3.8"
|
|
9
|
+
relatedSkills:
|
|
10
|
+
- "design-systems-slds-validate"
|
|
11
|
+
- "experience-lwc-generate"
|
|
12
|
+
---
|
|
13
|
+
<!-- adk-managed-skill -->
|
|
14
|
+
|
|
15
|
+
# Web Component Accessibility
|
|
16
|
+
|
|
17
|
+
Accessibility (a11y) patterns and remediation guidance for web components.
|
|
18
|
+
Reference any time work involves the visible or interactive surface of a
|
|
19
|
+
component — generating, modifying, reviewing, or styling HTML, JS, or
|
|
20
|
+
CSS — to apply WCAG 2.2 standards.
|
|
21
|
+
|
|
22
|
+
## Review Context
|
|
23
|
+
|
|
24
|
+
Conduct a review specifically focused on enhancing web accessibility, guided by the WCAG (Web Content Accessibility Guidelines).
|
|
25
|
+
|
|
26
|
+
In order to mark code as a violation, it must have a direct correlation to the WCAG rule cited such that it is a clear violation of the criteria.
|
|
27
|
+
|
|
28
|
+
Key Review Criteria:
|
|
29
|
+
|
|
30
|
+
1. Focus Exclusively on Accessibility:
|
|
31
|
+
|
|
32
|
+
- Evaluate the component solely for accessibility.
|
|
33
|
+
- Only consider compliance with the cited WCAG Success Criteria, ignoring violations that can be attributed to other criteria.
|
|
34
|
+
- Avoid addressing general code style, patterns, or issues unrelated to accessibility.
|
|
35
|
+
|
|
36
|
+
2. Ensure Minimum and Sufficient Accessibility:
|
|
37
|
+
|
|
38
|
+
- Identify accessibility issues that prevent the component from meeting the minimum requirements outlined by WCAG.
|
|
39
|
+
- Avoid suggesting enhancements that go beyond the scope of WCAG compliance unless strictly necessary.
|
|
40
|
+
|
|
41
|
+
3. WAI-ARIA Usage:
|
|
42
|
+
|
|
43
|
+
- Use WAI-ARIA attributes only when strictly required to achieve accessibility that cannot otherwise be addressed with semantic HTML.
|
|
44
|
+
- Avoid unnecessary complexity or potential regressions caused by incorrect or overuse of ARIA attributes.
|
|
45
|
+
|
|
46
|
+
4. Component Library Usage
|
|
47
|
+
|
|
48
|
+
- Assume that well-known component libraries (e.g., Salesforce Lightning, Material UI, Chakra UI) are accessible out of the box when correctly implemented. Unless they are used specifically in conflict with WCAG, library-provided components can be ignored for this review, as they are implemented in an accessible way beneath the abstraction.
|
|
49
|
+
|
|
50
|
+
**Focus**: Provide actionable feedback to ensure the component meets the necessary WCAG accessibility requirements, avoiding extraneous feedback unrelated to the prompt's scope. Identify issues in code only if there is an immediate fix. You MUST conduct the review, and subsequently suggest the code fix that solves this issue.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Success Criteria Reviewers
|
|
55
|
+
|
|
56
|
+
Identify which Success Criteria apply to the code under review, then open the reference files relevant to that code. Each reference is a
|
|
57
|
+
self-contained reviewer with analysis framework, examples, and remediation
|
|
58
|
+
guidance.
|
|
59
|
+
|
|
60
|
+
### Perceivable
|
|
61
|
+
|
|
62
|
+
- [SC 1.1.1 Non-text Content](references/reviewers/sc-1-1-1-non-text-content.md)
|
|
63
|
+
- [SC 1.3.1 (i) Lists](references/reviewers/sc-1-3-1-i-lists.md)
|
|
64
|
+
- [SC 1.3.1 (ii) Tables](references/reviewers/sc-1-3-1-ii-tables.md)
|
|
65
|
+
- [SC 1.3.1 (iii) Form Labels](references/reviewers/sc-1-3-1-iii-form-labels.md)
|
|
66
|
+
- [SC 1.3.1 (iv) Regions](references/reviewers/sc-1-3-1-iv-regions.md)
|
|
67
|
+
- [SC 1.3.1 (v) Groups](references/reviewers/sc-1-3-1-v-groups.md)
|
|
68
|
+
- [SC 1.3.5 Identify Input Purpose](references/reviewers/sc-1-3-5-identify-input.md)
|
|
69
|
+
- [SC 1.4.3 Contrast (Minimum)](references/reviewers/sc-1-4-3-contrast.md)
|
|
70
|
+
|
|
71
|
+
### Operable
|
|
72
|
+
|
|
73
|
+
- [SC 2.1.1 Keyboard](references/reviewers/sc-2-1-1-keyboard.md)
|
|
74
|
+
- [SC 2.4.4 Link Purpose](references/reviewers/sc-2-4-4-link-purpose.md)
|
|
75
|
+
- [SC 2.4.6 Headings and Labels](references/reviewers/sc-2-4-6-headings-labels.md)
|
|
76
|
+
- [SC 2.5.1 Pointer Gestures](references/reviewers/sc-2-5-1-pointer-gestures.md)
|
|
77
|
+
- [SC 2.5.2 Pointer Cancellation](references/reviewers/sc-2-5-2-pointer-cancellation.md)
|
|
78
|
+
- [SC 2.5.3 Label in Name](references/reviewers/sc-2-5-3-label-in-name.md)
|
|
79
|
+
- [SC 2.5.7 Dragging Movements](references/reviewers/sc-2-5-7-dragging-movement.md)
|
|
80
|
+
|
|
81
|
+
### Understandable
|
|
82
|
+
|
|
83
|
+
- [SC 3.2.1 On Focus](references/reviewers/sc-3-2-1-on-focus.md)
|
|
84
|
+
- [SC 3.2.2 On Input](references/reviewers/sc-3-2-2-on-input.md)
|
|
85
|
+
- [SC 3.3.1 Error Identification](references/reviewers/sc-3-3-1-error-identification.md)
|
|
86
|
+
- [SC 3.3.2 Labels or Instructions](references/reviewers/sc-3-3-2-labels-instructions.md)
|
|
87
|
+
- [SC 3.3.3 Error Suggestion](references/reviewers/sc-3-3-3-error-suggestion.md)
|
|
88
|
+
|
|
89
|
+
### Robust
|
|
90
|
+
|
|
91
|
+
- [SC 4.1.2 (i) Name](references/reviewers/sc-4-1-2-i-name.md)
|
|
92
|
+
- [SC 4.1.2 (ii) Role](references/reviewers/sc-4-1-2-ii-role.md)
|
|
93
|
+
- [SC 4.1.2 (iii) Value](references/reviewers/sc-4-1-2-iii-value.md)
|
|
94
|
+
|
|
95
|
+
### Vision-Assisted Review
|
|
96
|
+
|
|
97
|
+
When component screenshots or design mocks are available, augment the
|
|
98
|
+
source-code review with these vision-level reviewers. Each reference covers
|
|
99
|
+
image-based evaluation for the corresponding Success Criterion — contrast
|
|
100
|
+
ratios, color dependence, resize/reflow behavior, and non-text content
|
|
101
|
+
identification from pixels rather than from the DOM.
|
|
102
|
+
|
|
103
|
+
- [SC 1.1.1 Non-text Content (vision)](references/vision/sc-1-1-1-non-text-content.md)
|
|
104
|
+
- [SC 1.4.1 Use of Color (vision)](references/vision/sc-1-4-1-use-of-color.md)
|
|
105
|
+
- [SC 1.4.3 Contrast (vision)](references/vision/sc-1-4-3-contrast.md)
|
|
106
|
+
- [SC 1.4.10 Reflow (vision)](references/vision/sc-1-4-10-resize-reflow.md)
|
|
107
|
+
- [SC 1.4.11 Non-text Contrast (vision)](references/vision/sc-1-4-11-non-text-contrast.md)
|
|
108
|
+
|
|
109
|
+
## Review Output
|
|
110
|
+
|
|
111
|
+
For each Success Criterion you evaluated, report violations found. If no
|
|
112
|
+
violations exist for a criterion, return an empty list for that criterion.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
## SC 1.1.1 - Non-text Content (Level A)
|
|
2
|
+
|
|
3
|
+
All non-text content that is presented to the user has a text alternative that serves the equivalent purpose, except for specific situations such as controls or input, time-based media, test, sensory, CAPTCHA, and decoration or formatting.
|
|
4
|
+
|
|
5
|
+
## SC: 1.1.1 - Non-text Content (All Images)
|
|
6
|
+
|
|
7
|
+
This reviewer focuses on both decorative and informative images and their proper accessibility handling.
|
|
8
|
+
|
|
9
|
+
### Definition of Decorative Image:
|
|
10
|
+
|
|
11
|
+
A decorative image is one that:
|
|
12
|
+
|
|
13
|
+
- Provides no information content
|
|
14
|
+
- Is used for visual formatting, spacing, or decoration
|
|
15
|
+
- Does not convey meaning or context
|
|
16
|
+
- Is not essential to understanding the content
|
|
17
|
+
|
|
18
|
+
### Definition of Informative Image:
|
|
19
|
+
|
|
20
|
+
An informative image is any image that conveys information, meaning, or context that is essential to understanding the content or functionality of a webpage or application.
|
|
21
|
+
|
|
22
|
+
### Analysis Framework(What to do):
|
|
23
|
+
|
|
24
|
+
1. Identify all `<img>` elements in the HTML
|
|
25
|
+
2. Determine if each image is decorative or informative
|
|
26
|
+
3. Check if decorative images have proper `alt=""` attributes
|
|
27
|
+
4. Check if informative images have meaningful descriptive alt text
|
|
28
|
+
5. Look for CSS background images that should be used instead
|
|
29
|
+
6. Check for ARIA hidden attributes on decorative images
|
|
30
|
+
|
|
31
|
+
### Goals for Decorative Images:
|
|
32
|
+
|
|
33
|
+
1. **Empty alt attribute**: Should have `alt=""` for purely decorative images
|
|
34
|
+
- Good: `<img src="decorative-border.png" alt="" />`
|
|
35
|
+
- Bad: `<img src="decorative-border.png" />`
|
|
36
|
+
2. **CSS background images**: Should not have alt text as they are not in the accessibility tree
|
|
37
|
+
3. **ARIA hidden**: Can use `aria-hidden="true"` for decorative images that must remain in DOM
|
|
38
|
+
- Good: `<img src="spacer.gif" alt="" aria-hidden="true" />`
|
|
39
|
+
4. **No redundant text**: Avoid providing descriptive alt text for decorative images
|
|
40
|
+
- Bad: `<img src="decorative-border.png" alt="Decorative border with flowers" />`
|
|
41
|
+
5. **Decorative image as link without context**: Add `aria-label` or `title` attribute to the anchor tag
|
|
42
|
+
- Bad: `<a href="/page"><img src="decorative-icon.png" alt="" /></a>`
|
|
43
|
+
- Good: `<a href="/page" aria-label="Navigate to main page"><img src="decorative-icon.png" alt="" /></a>`
|
|
44
|
+
|
|
45
|
+
### Goals for Informative Images:
|
|
46
|
+
|
|
47
|
+
1. **Must have alt attribute**: All informative images must have descriptive alt text
|
|
48
|
+
- Good: `<img src="company-logo.png" alt="Our Company Logo" />`
|
|
49
|
+
- Bad: `<img src="chart.png" />`
|
|
50
|
+
2. **Meaningful content**: Alt text should describe the information conveyed
|
|
51
|
+
- Good: `<img src="chart.png" alt="Quarterly sales performance chart showing revenue trends" />`
|
|
52
|
+
- Bad: `<img src="chart.png" alt="chart" />`
|
|
53
|
+
|
|
54
|
+
### What to Look For:
|
|
55
|
+
|
|
56
|
+
- `<img>` elements without alt attributes (both decorative and informative)
|
|
57
|
+
- `<img>` elements with generic alt text like "image", "picture", "photo"
|
|
58
|
+
- Decorative images that are not properly marked as decorative
|
|
59
|
+
- Informative images with missing or inadequate alt text
|
|
60
|
+
- Background images that are incorrectly implemented as `<img>` elements
|
|
61
|
+
- Decorative images used in interactive contexts without proper labeling
|
|
62
|
+
|
|
63
|
+
### Common Violations for Images:
|
|
64
|
+
|
|
65
|
+
- Missing alt attribute on decorative images
|
|
66
|
+
- Missing alt attribute on informative images
|
|
67
|
+
- Using `alt="image"` or `alt="picture"` for decorative images
|
|
68
|
+
- Providing descriptive alt text for purely decorative images
|
|
69
|
+
- Using decorative images as links without proper context
|
|
70
|
+
- Including decorative images in the accessibility tree when they should be hidden
|
|
71
|
+
|
|
72
|
+
Rules to follow:
|
|
73
|
+
|
|
74
|
+
- Focus specifically on decorative or non decorative images and their alt text handling in the provided HTML and JS files
|
|
75
|
+
- Flag missing alt attributes on decorative images
|
|
76
|
+
- Flag generic alt text (like "image", "picture") on decorative images
|
|
77
|
+
- Flag missing or generic alt text on informative images
|
|
78
|
+
- Flag overly descriptive alt text on clearly decorative images
|
|
79
|
+
- Consider the context and purpose of each image
|
|
80
|
+
|
|
81
|
+
- For each issue found, provide a separate, detailed report.
|
|
82
|
+
- Keep issues concise, avoid duplicated issues or unnecessary or non-applicable problems.
|
|
83
|
+
- Assume that any imported functionality works as expected and was already analyzed.
|
|
84
|
+
- Components do not supplement or provide global functionalities.
|
|
85
|
+
- Lightning base components (`lightning-input`, `lightning-combobox`, `lightning-textarea`, `lightning-icon`, etc.) provide their own accessible labeling, ARIA, and error handling in shadow DOM via their dedicated attributes (`label`, `alternative-text`, field-level validation). When such a component is given a `label` attribute it is already programmatically labeled — even with `variant="label-hidden"`, which hides the label visually but keeps it for assistive technology. Do **not** flag a sibling/wrapper `<label>` or `<span>` for a missing `for`/`id` when the actual control is a self-labeling Lightning component, and do not treat a visible heading as if it were the control's only label. This also covers navigation and icon base components (`lightning-vertical-navigation-item`, `lightning-vertical-navigation-item-icon`, `lightning-button-icon`, etc.): when a `label` (or `alternative-text`) attribute is supplied, the base component renders it as the visible link/control text **and** exposes it as the accessible name, and any `icon-name` is decorative — do not emit a 4.1.2 "verify the label is associated with the icon" warning, even a hedged one. The presence of the `label` attribute is the association.
|
|
86
|
+
- Resolve template bindings before judging them. A template expression like `{someValue}` refers to a property or getter on the component's controller (`.js`/`.ts`) — including `@api` properties and `get someValue()` getters — not to a module-level imported constant (which LWC templates cannot bind to). Check the controller for the binding's definition before concluding a value is undefined, empty, or missing. When reviewing a diff, verify which side is the corrected code; do not assume the change introduced the problem.
|
|
87
|
+
- Prefer a real `<button>` for actions; for a link, `href="#"` with `event.preventDefault()` (the canonical SLDS pattern). Don't recommend `href="javascript:void(0)"` as a first-line remediation — it's a no-op-anchor anti-pattern. It is acceptable only as a last resort when moving `<a>` → `<button>` is genuinely impossible, and even then only when paired with the full set of attributes that make the anchor behave as an accessible button (`role="button"`, keyboard activation, etc.) — `void(0)` on its own is an incomplete fix. Don't flag existing `javascript:void(0)` as a violation.
|
|
88
|
+
- ARIA attribute spelling depends on the element type. On a **plain HTML element** (`div`, `span`, `button`, `input`, `a`, `img`, `iframe`, …) the only valid spelling is the W3C form `aria-labelledby` / `aria-describedby`; the hyphen-split `aria-labelled-by` / `aria-described-by` there **is** a real bug — keep flagging it. But on an **LWC component tag** (`lightning-*` or a custom `ns-name` element), the hyphen-split form is the kebab-case binding of the component's `@api ariaLabelledBy` / `ariaDescribedBy` property (each capital letter maps to `-` + lowercase), and LWC reflects it to the spec-correct `aria-labelledby` in the rendered DOM. Do **not** flag `aria-labelled-by` on a component tag as a misspelling, and do not claim it "breaks the accessible name computation" — you cannot determine that from the attribute name alone, because both `aria-labelled-by` (via `@api` property kebab-casing) and `aria-labelledby` (via LWC's ARIA reflection) can wire to the same property depending on the component. Treat a hyphen-split ARIA attribute on a component tag as a valid binding, not a violation.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
## SC 1.3.1 - Info and Relationships (Level A)
|
|
2
|
+
|
|
3
|
+
Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.
|
|
4
|
+
|
|
5
|
+
## SC: 1.3.1 (i) - Info And Relationships - Lists (A)
|
|
6
|
+
|
|
7
|
+
Review the provided HTML and JS files for accessibility violations per WCAG 2.2 SC 1.3.1 (i), 'Info and Relationships'
|
|
8
|
+
(Only lists from this rule should be considered). For all lists on the page, ensure that any information conveyed through presentation is programmatically determinable in order to determine if they meet SC 1.3.1 (i).
|
|
9
|
+
If they do not meet this success criterion, flag it as a violation.
|
|
10
|
+
|
|
11
|
+
Rules to follow:
|
|
12
|
+
|
|
13
|
+
- Find all violations of SC 1.3.1 'Info and Relationships - Lists' in the provided HTML and JS files.
|
|
14
|
+
- Do not worry about violations of SC 1.3.1 that are not specific to lists. These will be handled by other reviewers.
|
|
15
|
+
- The preferred technique for fixing SC 1.3.1 lists violations is The objective of this technique is to create lists of related items using list elements appropriate for their purposes.
|
|
16
|
+
The ol element is used when the list is ordered and the ul element is used when the list is unordered.
|
|
17
|
+
Description lists (dl) are used to group name-value pairs of information, for example: terms and definitions or questions and answers.
|
|
18
|
+
Although the use of this markup can make lists more readable, not all lists need markup.
|
|
19
|
+
For instance, sentences that contain comma-separated lists may not need list markup.
|
|
20
|
+
When markup is used that visually formats items as a list but does not indicate the list relationship, users may have difficulty in navigating the information.
|
|
21
|
+
An example of such visual formatting is including asterisks in the content at the beginning of each list item and using br elements to separate the list items.
|
|
22
|
+
Some assistive technologies allow users to navigate from list to list or item to item.
|
|
23
|
+
Style sheets can be used to change the presentation of the lists while preserving their integrity.
|
|
24
|
+
The list structure, commonly unordered lists, is also useful to group hyperlinks.
|
|
25
|
+
When this is done, it helps screen reader users to navigate from the first item in a list to the end of the list or jump to the next list.
|
|
26
|
+
This helps them to bypass groups of links if they choose to..
|
|
27
|
+
- The procedure for H48 is Check that content that has the visual appearance of a list (with or without bullets) is marked as an unordered list.
|
|
28
|
+
Check that content that has the visual appearance of a numbered list is marked as an ordered list.
|
|
29
|
+
Check that content is marked as a description list when groups of name-value pairs, for example: terms and definitions or questions and answers, are presented in the form of a list..
|
|
30
|
+
- If the contents of the list are ordered, it must use the `<ol>` element.
|
|
31
|
+
- When a sublist is indented, use a ul or ol inside a list item to properly communicate the new list level/position within the parent.
|
|
32
|
+
- When creating description lists where the elements are iterated over with a template for:each loop ALWAYS insert a wrapper div element for each object in the array. Place the unique key attribute on the wrapper div element. Here is an example:
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<dl>
|
|
36
|
+
<template for:each={entries} for:item="entry">
|
|
37
|
+
<div key={entry.foo} class="entry-item">
|
|
38
|
+
<dt class="foo">{entry.foo}</dt>
|
|
39
|
+
<dd class="bar">{entry.bar}</dd>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
</dl>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- For each issue found, provide a separate, detailed report.
|
|
46
|
+
- Keep issues concise, avoid duplicated issues or unnecessary or non-applicable problems.
|
|
47
|
+
- Assume that any imported functionality works as expected and was already analyzed.
|
|
48
|
+
- Components do not supplement or provide global functionalities.
|
|
49
|
+
- Lightning base components (`lightning-input`, `lightning-combobox`, `lightning-textarea`, `lightning-icon`, etc.) provide their own accessible labeling, ARIA, and error handling in shadow DOM via their dedicated attributes (`label`, `alternative-text`, field-level validation). When such a component is given a `label` attribute it is already programmatically labeled — even with `variant="label-hidden"`, which hides the label visually but keeps it for assistive technology. Do **not** flag a sibling/wrapper `<label>` or `<span>` for a missing `for`/`id` when the actual control is a self-labeling Lightning component, and do not treat a visible heading as if it were the control's only label. This also covers navigation and icon base components (`lightning-vertical-navigation-item`, `lightning-vertical-navigation-item-icon`, `lightning-button-icon`, etc.): when a `label` (or `alternative-text`) attribute is supplied, the base component renders it as the visible link/control text **and** exposes it as the accessible name, and any `icon-name` is decorative — do not emit a 4.1.2 "verify the label is associated with the icon" warning, even a hedged one. The presence of the `label` attribute is the association.
|
|
50
|
+
- Resolve template bindings before judging them. A template expression like `{someValue}` refers to a property or getter on the component's controller (`.js`/`.ts`) — including `@api` properties and `get someValue()` getters — not to a module-level imported constant (which LWC templates cannot bind to). Check the controller for the binding's definition before concluding a value is undefined, empty, or missing. When reviewing a diff, verify which side is the corrected code; do not assume the change introduced the problem.
|
|
51
|
+
- Prefer a real `<button>` for actions; for a link, `href="#"` with `event.preventDefault()` (the canonical SLDS pattern). Don't recommend `href="javascript:void(0)"` as a first-line remediation — it's a no-op-anchor anti-pattern. It is acceptable only as a last resort when moving `<a>` → `<button>` is genuinely impossible, and even then only when paired with the full set of attributes that make the anchor behave as an accessible button (`role="button"`, keyboard activation, etc.) — `void(0)` on its own is an incomplete fix. Don't flag existing `javascript:void(0)` as a violation.
|
|
52
|
+
- ARIA attribute spelling depends on the element type. On a **plain HTML element** (`div`, `span`, `button`, `input`, `a`, `img`, `iframe`, …) the only valid spelling is the W3C form `aria-labelledby` / `aria-describedby`; the hyphen-split `aria-labelled-by` / `aria-described-by` there **is** a real bug — keep flagging it. But on an **LWC component tag** (`lightning-*` or a custom `ns-name` element), the hyphen-split form is the kebab-case binding of the component's `@api ariaLabelledBy` / `ariaDescribedBy` property (each capital letter maps to `-` + lowercase), and LWC reflects it to the spec-correct `aria-labelledby` in the rendered DOM. Do **not** flag `aria-labelled-by` on a component tag as a misspelling, and do not claim it "breaks the accessible name computation" — you cannot determine that from the attribute name alone, because both `aria-labelled-by` (via `@api` property kebab-casing) and `aria-labelledby` (via LWC's ARIA reflection) can wire to the same property depending on the component. Treat a hyphen-split ARIA attribute on a component tag as a valid binding, not a violation.
|