@salesforce/afv-skills 1.58.0 → 1.60.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-architecture-analyze/SKILL.md +66 -17
- package/skills/agentforce-architecture-analyze/assets/cli/show_access_token.yaml +4 -7
- package/skills/agentforce-architecture-analyze/references/contract.json +1 -1
- package/skills/agentforce-architecture-analyze/scripts/emit_env.py +2 -2
- package/skills/agentforce-architecture-analyze/scripts/main.py +40 -44
- package/skills/agentforce-architecture-analyze/scripts/rest_client.py +11 -3
- package/skills/agentforce-architecture-analyze/scripts/sf_cli.py +77 -10
- package/skills/agentforce-architecture-analyze/scripts/tests/test_end_to_end_fixture.py +1 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_flow_children_inflation.py +1 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_main_pipeline.py +53 -2
- package/skills/agentforce-architecture-analyze/scripts/tests/test_resolve_creds.py +184 -36
- package/skills/agentforce-architecture-analyze/scripts/tests/test_rest_client.py +17 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_sf_cli.py +165 -11
- package/skills/agentforce-architecture-analyze/scripts/tests/test_skill_md_pipeline_block.py +319 -0
- package/skills/agentforce-bot-upgrade/SKILL.md +3 -1
- package/skills/agentforce-d360-analyze/SKILL.md +28 -10
- package/skills/agentforce-d360-analyze/scripts/dc.py +200 -50
- package/skills/agentforce-d360-analyze/scripts/discover_sessions.py +10 -6
- package/skills/agentforce-d360-analyze/scripts/fetch_dc.py +22 -6
- package/skills/agentforce-d360-analyze/scripts/resolve_session.py +21 -13
- package/skills/agentforce-d360-analyze/scripts/tests/test_dc_and_resolve_session.py +298 -76
- package/skills/agentforce-d360-analyze/scripts/tests/test_default_target_org.py +432 -0
- package/skills/agentforce-d360-analyze/scripts/tests/test_discover_sessions.py +1 -1
- package/skills/agentforce-d360-analyze/scripts/tests/test_resolve_session_main.py +9 -3
- package/skills/agentforce-d360-analyze/scripts/tests/test_skill_md_prefix_block.py +176 -0
- package/skills/agentforce-generate/SKILL.md +21 -1
- package/skills/agentforce-generate/references/known-issues.md +51 -1
- package/skills/agentforce-generate/references/legacy-nga-regression-eval.md +547 -0
- package/skills/agentforce-generate/references/upgrade-legacy-agent-to-agentscript.md +577 -0
- package/skills/agentforce-generate/scripts/upgrade-legacy-nga-analyze.py +404 -0
- package/skills/agentforce-generate/scripts/upgrade-legacy-nga-run-trials.sh +58 -0
- package/skills/agentforce-persona-generate/SKILL.md +505 -0
- package/skills/agentforce-persona-generate/assets/checklist-template.md +100 -0
- package/skills/agentforce-persona-generate/assets/persona-encoding-template.md +252 -0
- package/skills/agentforce-persona-generate/assets/persona-template.md +229 -0
- package/skills/agentforce-persona-generate/assets/sample-dialog-template.md +50 -0
- package/skills/agentforce-persona-generate/assets/workshop-outline-template.md +97 -0
- package/skills/agentforce-persona-generate/examples/concierge-persona.md +189 -0
- package/skills/agentforce-persona-generate/examples/concierge-sample-dialog.md +70 -0
- package/skills/agentforce-persona-generate/examples/drover-persona.md +194 -0
- package/skills/agentforce-persona-generate/examples/drover-sample-dialog.md +62 -0
- package/skills/agentforce-persona-generate/examples/steady-hand-persona.md +188 -0
- package/skills/agentforce-persona-generate/examples/steady-hand-sample-dialog.md +68 -0
- package/skills/agentforce-persona-generate/examples/yt-persona.md +195 -0
- package/skills/agentforce-persona-generate/examples/yt-sample-dialog.md +66 -0
- package/skills/agentforce-persona-generate/references/attributions.md +36 -0
- package/skills/agentforce-persona-generate/references/interaction-design-notes.md +30 -0
- package/skills/agentforce-persona-generate/references/persona-encoding-guide.md +566 -0
- package/skills/agentforce-persona-generate/references/persona-framework.md +796 -0
- package/skills/agentforce-persona-generate/references/refinement-mappings.md +31 -0
- package/skills/agentforce-persona-generate/references/scoring-rubric.md +58 -0
- package/skills/agentforce-persona-generate/references/voice-catalog.json +2327 -0
- package/skills/agentforce-persona-generate/references/workshop-question-policy.md +90 -0
- package/skills/agentforce-persona-generate/references/workshop-scenario-seeds.md +119 -0
- package/skills/agentforce-persona-generate/scripts/parse_agent_yaml.py +223 -0
- package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +17 -27
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +7 -17
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +47 -63
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +10 -13
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -46
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +4 -21
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +58 -82
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +16 -315
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +9 -24
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -44
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +11 -63
- package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +2 -1
- package/skills/data360-schema-get/SKILL.md +3 -3
- package/skills/design-systems-slds-validate/references/report-format.md +1 -1
- package/skills/dx-app-analytics-query/SKILL.md +8 -8
- package/skills/dx-org-manage/SKILL.md +1 -0
- package/skills/dx-org-shape-manage/SKILL.md +1 -0
- package/skills/dx-org-snapshot-manage/SKILL.md +172 -0
- package/skills/dx-org-snapshot-manage/examples/create_error_output.json +16 -0
- package/skills/dx-org-snapshot-manage/examples/create_success_output.json +19 -0
- package/skills/dx-org-snapshot-manage/examples/delete_output.json +9 -0
- package/skills/dx-org-snapshot-manage/examples/get_output.json +19 -0
- package/skills/dx-org-snapshot-manage/examples/list_output.json +36 -0
- package/skills/dx-org-snapshot-manage/references/cli_flags.md +179 -0
- package/skills/dx-org-snapshot-manage/references/snapshot_usage.md +55 -0
- package/skills/dx-org-trial-expiration-check/SKILL.md +1 -1
- package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +2 -2
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +7 -5
- package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +11 -11
- package/skills/experience-content-media-image-generate/SKILL.md +83 -0
- package/skills/experience-content-media-image-generate/scripts/download-image.sh +84 -0
- package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -12
- package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md +3 -3
- package/skills/experience-ui-bundle-app-coordinate/references/phase-execution-pattern.md +9 -7
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.mjs +132 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.mjs +62 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.mjs +71 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.mjs +95 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.mjs +78 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.mjs +21 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.mjs +28 -0
- package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +3 -1
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.mjs +40 -0
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +7 -5
- package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.mjs +70 -0
- package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.mjs +76 -0
- package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.mjs +115 -0
- package/skills/experience-ui-bundle-metadata-generate/SKILL.md +7 -3
- package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +1 -1
- package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +1 -1
- package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.mjs +43 -0
- package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.mjs +131 -0
- package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.mjs +152 -0
- package/skills/experience-ui-bundle-mfa-configure/references/branding.md +10 -6
- package/skills/external-diagram-mermaid-generate/SKILL.md +12 -12
- package/skills/field-service-data-capture-migrate/references/component-mapping.md +1 -1
- package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +1 -2
- package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +1 -0
- package/skills/field-service-data-capture-migrate/references/transformer-rules.md +1 -1
- package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +12 -1
- package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +4 -1
- package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -1
- package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +233 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/accounting-setup.md +117 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/billing-rules-config.md +237 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/billing-settings.md +271 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/demo-policy-config.md +138 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/org-defaults.md +64 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/permissions-config.md +226 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/prerequisites.md +142 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +3 -2
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +3 -3
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +68 -45
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +17 -18
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +16 -3
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +16 -13
- package/skills/marketing-message-test/SKILL.md +194 -0
- package/skills/marketing-message-test/references/api-contract.md +333 -0
- package/skills/omnistudio-callable-apex-generate/SKILL.md +3 -3
- package/skills/omnistudio-datamapper-generate/SKILL.md +6 -6
- package/skills/omnistudio-datapacks-deploy/SKILL.md +11 -11
- package/skills/omnistudio-dependencies-analyze/SKILL.md +5 -5
- package/skills/omnistudio-epc-catalog-generate/SKILL.md +6 -6
- package/skills/omnistudio-flexcard-generate/SKILL.md +6 -6
- package/skills/omnistudio-integration-procedure-generate/SKILL.md +6 -6
- package/skills/omnistudio-omniscript-generate/SKILL.md +6 -5
- package/skills/platform-apex-logs-debug/SKILL.md +1 -0
- package/skills/platform-metadata-deploy/SKILL.md +1 -0
- package/skills/platform-models-api-configure/SKILL.md +5 -5
- package/skills/platform-soql-query/SKILL.md +1 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +17 -6
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +107 -192
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +6 -6
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +49 -20
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +4 -4
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +224 -290
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +295 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -1
- package/skills/service-itsm-slack-itservice-configure/SKILL.md +2 -1
- package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +2 -2
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +20 -13
- package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +5 -55
- package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +0 -38
- package/skills/service-omni-command-center-analyze/SKILL.md +2 -3
- package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
- package/skills/tableau-next-asset-create/README.md +65 -0
- package/skills/tableau-next-asset-create/SKILL.md +409 -0
- package/skills/tableau-next-asset-create/references/admin-users.md +149 -0
- package/skills/tableau-next-asset-create/references/ai-readiness.md +355 -0
- package/skills/tableau-next-asset-create/references/alerts.md +111 -0
- package/skills/tableau-next-asset-create/references/build-workflow.md +819 -0
- package/skills/tableau-next-asset-create/references/dashboard-authoring.md +302 -0
- package/skills/tableau-next-asset-create/references/dashboard-design-principles.md +352 -0
- package/skills/tableau-next-asset-create/references/data-transform-gotchas.md +210 -0
- package/skills/tableau-next-asset-create/references/data-understanding.md +387 -0
- package/skills/tableau-next-asset-create/references/deep-reference-index.md +74 -0
- package/skills/tableau-next-asset-create/references/destructive-operations.md +62 -0
- package/skills/tableau-next-asset-create/references/edit-dashboard.md +273 -0
- package/skills/tableau-next-asset-create/references/edit-visualization.md +529 -0
- package/skills/tableau-next-asset-create/references/empty-source-handling.md +104 -0
- package/skills/tableau-next-asset-create/references/ingest-and-metric-gotchas.md +638 -0
- package/skills/tableau-next-asset-create/references/insight-bundle.md +69 -0
- package/skills/tableau-next-asset-create/references/large-flat-file-handling.md +331 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_envelope.json +54 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_shared-widget-fields.json +122 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/add_page.json +29 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/delete_page.json +27 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json +11 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget_to_page.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/place_widget_on_page.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_dashboard.json +16 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_page.json +26 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/rename_page.json +28 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/save_dashboard.json +18 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/undo.json +11 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_button_widget.json +69 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_container_widget.json +88 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_filter_widget.json +146 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_metric_widget.json +78 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_navigation_widget.json +80 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_parameter_widget.json +160 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_text_widget.json +103 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_visualization_widget.json +68 -0
- package/skills/tableau-next-asset-create/references/sdm-tool-reference.md +721 -0
- package/skills/tableau-next-asset-create/references/semantic-query-and-enrichment.md +355 -0
- package/skills/tableau-next-asset-create/references/shared-gates.md +322 -0
- package/skills/tableau-next-asset-create/references/sharing-and-promotion.md +306 -0
- package/skills/tableau-next-asset-create/references/tasks/ai-readiness-audit.md +51 -0
- package/skills/tableau-next-asset-create/references/tasks/analyze-data.md +48 -0
- package/skills/tableau-next-asset-create/references/tasks/build-dashboard.md +66 -0
- package/skills/tableau-next-asset-create/references/tasks/build-end-to-end.md +73 -0
- package/skills/tableau-next-asset-create/references/tasks/create-data-transform.md +51 -0
- package/skills/tableau-next-asset-create/references/tasks/create-viz.md +58 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-dashboard.md +80 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-sdm.md +106 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-viz.md +40 -0
- package/skills/tableau-next-asset-create/references/tasks/enrich-model.md +68 -0
- package/skills/tableau-next-asset-create/references/tasks/ingest-flat-file.md +68 -0
- package/skills/tableau-next-asset-create/references/tasks/manage-alert.md +35 -0
- package/skills/tableau-next-asset-create/references/tasks/profile-dataset.md +47 -0
- package/skills/tableau-next-asset-create/references/tasks/promote-or-reuse.md +46 -0
- package/skills/tableau-next-asset-create/references/tasks/provision-user.md +39 -0
- package/skills/tableau-next-asset-create/references/tasks/query-model.md +92 -0
- package/skills/tableau-next-asset-create/references/tasks/review-verified-questions.md +42 -0
- package/skills/tableau-next-asset-create/references/tasks/share-asset.md +37 -0
- package/skills/tableau-next-asset-create/references/verified-questions.md +125 -0
- package/skills/tableau-next-asset-create/references/viz-authoring.md +992 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.sh +0 -42
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +0 -26
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.sh +0 -35
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.sh +0 -47
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.sh +0 -33
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.sh +0 -20
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +0 -15
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +0 -30
- package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.sh +0 -37
- package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.sh +0 -66
- package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.sh +0 -58
- package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +0 -30
- package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +0 -73
- package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +0 -118
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +0 -102
|
@@ -42,7 +42,7 @@ Before starting any phase, verify these preconditions are met:
|
|
|
42
42
|
|
|
43
43
|
1. **Authenticated Salesforce org**: Run `sf org display` to confirm a default org is set and authenticated. If not, prompt the user to authenticate: `sf org login web`
|
|
44
44
|
2. **Required CLI tools**: Verify `sf`, `npm`, and `npx` are available (declared in metadata.cliTools)
|
|
45
|
-
3. **Node.js version**: Run `scripts/check-prerequisites.
|
|
45
|
+
3. **Node.js version**: Run `node scripts/check-prerequisites.mjs` and report any errors
|
|
46
46
|
4. **Org features** (if deploying): Experience Cloud enabled, appropriate licenses, and Sites enabled
|
|
47
47
|
|
|
48
48
|
If any precondition fails, stop and report the specific missing requirement before attempting any phase execution.
|
|
@@ -114,7 +114,7 @@ Offer prebuilt starter template (experience-ui-bundle-project-generate)
|
|
|
114
114
|
v
|
|
115
115
|
If template chosen: scaffold via sf template generate project -- Phase 1 skipped
|
|
116
116
|
v
|
|
117
|
-
If declined: run scripts/check-sfdx-project.
|
|
117
|
+
If declined: run node scripts/check-sfdx-project.mjs
|
|
118
118
|
v
|
|
119
119
|
If missing: create sfdx-project.json
|
|
120
120
|
v
|
|
@@ -123,7 +123,7 @@ Verify project directory initialized
|
|
|
123
123
|
|
|
124
124
|
Offers a faster, less error-prone starting point before building from scratch. If no template is used, ensures an SFDX project exists before attempting to generate a UI bundle — without this, `sf template generate ui-bundle` will fail with a hard error. Always check first — do not assume the project structure exists.
|
|
125
125
|
|
|
126
|
-
**Action:** Load `experience-ui-bundle-project-generate` and offer the two starter templates. If declined, run `scripts/check-sfdx-project.
|
|
126
|
+
**Action:** Load `experience-ui-bundle-project-generate` and offer the two starter templates. If declined, run `node scripts/check-sfdx-project.mjs`; on error, create the missing `sfdx-project.json` before proceeding.
|
|
127
127
|
|
|
128
128
|
### Phase 1: Scaffolding (Foundation)
|
|
129
129
|
|
|
@@ -154,7 +154,7 @@ Creates the UI bundle directory structure, meta XML (including hosting target),
|
|
|
154
154
|
- `package.json` — remove now-unused dependencies (`vite-plugin-graphql-codegen`, `@graphql-codegen/*`, `playwright`, `vitest`, etc.) and their npm scripts, not just the config files.
|
|
155
155
|
- Any component/page that imports a deleted hook, client, or shadcn component (e.g. `useAsyncData`, `graphqlClient`) must have that import and its usage removed or replaced — never leave an import pointing at a file that no longer exists.
|
|
156
156
|
- Do NOT re-add a file you just deleted elsewhere in the same pass (e.g. deleting `codegen.yml` while still emitting `.graphqlrc.yml`) — decide scope once per concern and apply it consistently across every file that touches that concern.
|
|
157
|
-
- Before finishing Phase 4, run `scripts/check-dangling-refs.
|
|
157
|
+
- Before finishing Phase 4, run `node scripts/check-dangling-refs.mjs <deleted-basename>` for each deleted file and report any errors.
|
|
158
158
|
|
|
159
159
|
### Phase 2: Features (Required if prompt mentions feature keywords — see "Prompt Classification Keywords" above)
|
|
160
160
|
|
|
@@ -378,12 +378,12 @@ Execute each phase sequentially following the standard pattern in `references/ph
|
|
|
378
378
|
---
|
|
379
379
|
|
|
380
380
|
**Phase 0 -- Template Offer & Bootstrap**
|
|
381
|
-
- Load `experience-ui-bundle-project-generate`, offer templates. If chosen: skip Phase 1, continue at Phase 2. If declined: run `scripts/check-sfdx-project.
|
|
381
|
+
- Load `experience-ui-bundle-project-generate`, offer templates. If chosen: skip Phase 1, continue at Phase 2. If declined: run `node scripts/check-sfdx-project.mjs`, create project if missing.
|
|
382
382
|
|
|
383
383
|
**Phase 1 -- Scaffolding** (skip if template used in Phase 0)
|
|
384
|
-
- **Precondition**: `scripts/check-sfdx-project.
|
|
384
|
+
- **Precondition**: `node scripts/check-sfdx-project.mjs` passes
|
|
385
385
|
- Load `experience-ui-bundle-metadata-generate`. Determine hosting target FIRST. Run `sf template generate ui-bundle --template reactbasic`, configure meta XML with `<target>`.
|
|
386
|
-
- **Post-verification**: `scripts/check-phase-1-complete.
|
|
386
|
+
- **Post-verification**: `node scripts/check-phase-1-complete.mjs` passes
|
|
387
387
|
|
|
388
388
|
**Phase 2 -- Features** (run on any feature keyword, even if pre-installed — see "Prompt Classification Keywords")
|
|
389
389
|
- Load `experience-ui-bundle-features-generate`. Install features, integrate examples. Verify with `npm run build`.
|
|
@@ -395,25 +395,25 @@ Execute each phase sequentially following the standard pattern in `references/ph
|
|
|
395
395
|
- Load `experience-ui-bundle-salesforce-data-access`. Fetch schema, ground entities, generate queries/mutations. Verify with `npx eslint`.
|
|
396
396
|
|
|
397
397
|
**Phase 4 -- UI** (ALWAYS REQUIRED)
|
|
398
|
-
- **Precondition**: `scripts/check-phase-1-complete.
|
|
398
|
+
- **Precondition**: `node scripts/check-phase-1-complete.mjs` passes
|
|
399
399
|
- Load `experience-ui-bundle-frontend-generate`. Build layout, pages, components. Replace all boilerplate.
|
|
400
|
-
- **Post-verification**: `scripts/check-phase-4-complete.
|
|
400
|
+
- **Post-verification**: `node scripts/check-phase-4-complete.mjs` passes
|
|
401
401
|
- **CRITICAL**: Phase 4 generates the actual React UI. Never skip.
|
|
402
402
|
|
|
403
403
|
**Phase 5 -- Integrations** (skip if not requested)
|
|
404
404
|
- Load `experience-ui-bundle-agentforce-client-generate` (5a) and/or `experience-ui-bundle-file-upload-generate` (5b) as needed.
|
|
405
405
|
|
|
406
406
|
**Phase 6 -- Deployment**
|
|
407
|
-
- **Precondition**: `scripts/check-phase-6-ready.
|
|
407
|
+
- **Precondition**: `node scripts/check-phase-6-ready.mjs` passes
|
|
408
408
|
- Load `experience-ui-bundle-deploy`. Follow 7-step sequence. Prefer `scripts/org-setup.mjs` if available.
|
|
409
409
|
- **CRITICAL**: Guard against empty schema — retry fetch 3x before codegen.
|
|
410
410
|
|
|
411
411
|
**Phase 7a -- Experience Site** (external users)
|
|
412
|
-
- **Trigger**: `scripts/check-hosting-target.
|
|
412
|
+
- **Trigger**: `node scripts/check-hosting-target.mjs` outputs "ExperienceSite"
|
|
413
413
|
- Load `experience-ui-bundle-site-generate`. Deploy site infrastructure.
|
|
414
414
|
|
|
415
415
|
**Phase 7b -- Custom Application** (internal users)
|
|
416
|
-
- **Trigger**: `scripts/check-hosting-target.
|
|
416
|
+
- **Trigger**: `node scripts/check-hosting-target.mjs` outputs "CustomApplication"
|
|
417
417
|
- Load `experience-ui-bundle-custom-app-generate`. Deploy app metadata.
|
|
418
418
|
|
|
419
419
|
### STEP 2.5: Phase Completion Validation
|
package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Before proceeding to STEP 3 (Final Summary), validate that all required phases were executed:
|
|
4
4
|
|
|
5
5
|
**Critical Validation (MUST pass):**
|
|
6
|
-
- [ ] **Phase 0 (Template Offer & Bootstrap) executed**: If no template was used, run `scripts/check-sfdx-project.
|
|
6
|
+
- [ ] **Phase 0 (Template Offer & Bootstrap) executed**: If no template was used, run `node scripts/check-sfdx-project.mjs`. If it returns non-zero, STOP and report error:
|
|
7
7
|
```text
|
|
8
8
|
ERROR: No SFDX project detected. Phase 0 (Bootstrap) is REQUIRED before scaffolding.
|
|
9
9
|
Run `sf project generate` (or create sfdx-project.json) before invoking
|
|
@@ -11,7 +11,7 @@ Before proceeding to STEP 3 (Final Summary), validate that all required phases w
|
|
|
11
11
|
```
|
|
12
12
|
If a template was used in Phase 0, this check is satisfied by the template's own scaffolding — skip re-running the script.
|
|
13
13
|
|
|
14
|
-
- [ ] **Phase 1 hosting target resolved**: Run `scripts/check-hosting-target.
|
|
14
|
+
- [ ] **Phase 1 hosting target resolved**: Run `node scripts/check-hosting-target.mjs`. If it returns non-zero, STOP and report error:
|
|
15
15
|
```text
|
|
16
16
|
ERROR: Hosting target was not resolved in Phase 1. A UI bundle without a <target> in its
|
|
17
17
|
meta XML will not be visible in the org. Determine Experience Site vs Custom Application
|
|
@@ -33,7 +33,7 @@ Before proceeding to STEP 3 (Final Summary), validate that all required phases w
|
|
|
33
33
|
Exactly one of Phase 7a/7b must run -- it is never optional or "skipped".
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
- [ ] **No dangling references after scaffold pruning**: If any file was deleted during Phase 1 scaffold pruning (see "Prune unused scaffold" in SKILL.md), run `scripts/check-dangling-refs.
|
|
36
|
+
- [ ] **No dangling references after scaffold pruning**: If any file was deleted during Phase 1 scaffold pruning (see "Prune unused scaffold" in SKILL.md), run `node scripts/check-dangling-refs.mjs <deleted-basename>` for each deleted file. If it returns non-zero (e.g. `vite.config.ts` still imports `vite-plugin-graphql-codegen` after `codegen.yml` was deleted, or a page still imports a deleted hook/component), STOP and report error:
|
|
37
37
|
```text
|
|
38
38
|
ERROR: Scaffold pruning left a dangling reference -- <file> was deleted but <other-file>
|
|
39
39
|
still imports/references it. Remove the reference (or restore the file) before completing
|
|
@@ -4,21 +4,23 @@ Each phase follows this standard pattern:
|
|
|
4
4
|
|
|
5
5
|
| Step | What to do | Why |
|
|
6
6
|
|------|-----------|-----|
|
|
7
|
-
| **0. Precondition Check** | Run `scripts/check-phase-N-*.
|
|
7
|
+
| **0. Precondition Check** | Run the matching `node scripts/check-phase-N-*.mjs` script | Verifies prerequisites are met before proceeding |
|
|
8
8
|
| **1. Load skill** | Invoke the skill for this phase | Gives you current rules, patterns, constraints |
|
|
9
9
|
| **2. Execute** | Follow the loaded skill's workflow | The skill defines HOW to do the work correctly |
|
|
10
10
|
| **3. Verify** | Run lint and build | Catch errors before moving to next phase |
|
|
11
|
-
| **4. Post-verification** | Run `scripts/check-phase-N-complete.
|
|
11
|
+
| **4. Post-verification** | Run the matching `node scripts/check-phase-N-complete.mjs` (if available) | Machine-checkable validation of phase completion |
|
|
12
12
|
| **5. Checkpoint** | Confirm phase completion | Ensures dependencies satisfied for next phase |
|
|
13
13
|
|
|
14
14
|
**CRITICAL: Do NOT skip step 1 (loading the skill).** Skills evolve — always load the current version.
|
|
15
15
|
|
|
16
|
+
**Always invoke every script via `node` (never as a bare executable)** so it works on Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
17
|
+
|
|
16
18
|
## Available Verification Scripts
|
|
17
19
|
|
|
18
|
-
- `scripts/check-sfdx-project.
|
|
19
|
-
- `scripts/check-phase-1-complete.
|
|
20
|
-
- `scripts/check-phase-4-complete.
|
|
21
|
-
- `scripts/check-phase-6-ready.
|
|
22
|
-
- `scripts/check-hosting-target.
|
|
20
|
+
- `node scripts/check-sfdx-project.mjs` - Validates SFDX project exists (Phase 0/1 prerequisite)
|
|
21
|
+
- `node scripts/check-phase-1-complete.mjs` - Verifies scaffold complete (Phase 4/6 prerequisite)
|
|
22
|
+
- `node scripts/check-phase-4-complete.mjs` - Verifies UI build complete (Phase 6 prerequisite)
|
|
23
|
+
- `node scripts/check-phase-6-ready.mjs` - Verifies deployment prerequisites met
|
|
24
|
+
- `node scripts/check-hosting-target.mjs` - Determines which hosting target is configured
|
|
23
25
|
|
|
24
26
|
All scripts exit 0 on success, exit 1 on failure with an error message.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Verify no surviving file still imports/references a file deleted during
|
|
3
|
+
// scaffold pruning.
|
|
4
|
+
// Usage: node check-dangling-refs.mjs <deleted-basename> [<deleted-basename> ...]
|
|
5
|
+
// <deleted-basename> is the file name without extension, e.g. "codegen" for
|
|
6
|
+
// codegen.yml, "graphqlClient" for src/api/graphqlClient.ts, "useAsyncData"
|
|
7
|
+
// for the deleted hook.
|
|
8
|
+
//
|
|
9
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
10
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash. Quote each
|
|
11
|
+
// <deleted-basename> argument.
|
|
12
|
+
//
|
|
13
|
+
// Exit 0 if no dangling references found, exit 1 with error message(s) if
|
|
14
|
+
// any are found.
|
|
15
|
+
|
|
16
|
+
import fs from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
|
|
19
|
+
const EXCLUDE_DIRS = new Set(["node_modules", "dist", "build", ".git"]);
|
|
20
|
+
const UIBUNDLES_DIR = path.join("force-app", "main", "default", "uiBundles");
|
|
21
|
+
|
|
22
|
+
// Filesystem read errors encountered while walking the bundle or reading a
|
|
23
|
+
// file. A dangling-reference scan that could not read part of the tree has NOT
|
|
24
|
+
// proven the reference is gone, so any entry here must turn a would-be SUCCESS
|
|
25
|
+
// into a non-zero exit (see the end of the script).
|
|
26
|
+
const ioErrors = [];
|
|
27
|
+
|
|
28
|
+
function findBundleDir() {
|
|
29
|
+
let entries;
|
|
30
|
+
try {
|
|
31
|
+
entries = fs.readdirSync(UIBUNDLES_DIR, { withFileTypes: true });
|
|
32
|
+
} catch {
|
|
33
|
+
// uiBundles dir absent/unreadable: return "" so the caller emits an explicit
|
|
34
|
+
// "No UI bundle directory found" error and exits non-zero. This is a handled,
|
|
35
|
+
// expected case (e.g. a fresh project), not a silently-swallowed failure.
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
const dirs = entries
|
|
39
|
+
.filter((e) => e.isDirectory())
|
|
40
|
+
.map((e) => e.name)
|
|
41
|
+
.sort();
|
|
42
|
+
return dirs.length > 0 ? path.join(UIBUNDLES_DIR, dirs[0]) : "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function collectFiles(dir, out) {
|
|
46
|
+
let entries;
|
|
47
|
+
try {
|
|
48
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
49
|
+
} catch (err) {
|
|
50
|
+
// A subdirectory we cannot list may hide a surviving reference. Record it so
|
|
51
|
+
// the run fails rather than reporting an untrustworthy SUCCESS.
|
|
52
|
+
ioErrors.push(`could not read directory '${dir}': ${err.message}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
const full = path.join(dir, entry.name);
|
|
57
|
+
if (entry.isDirectory()) {
|
|
58
|
+
if (EXCLUDE_DIRS.has(entry.name)) continue;
|
|
59
|
+
collectFiles(full, out);
|
|
60
|
+
} else if (entry.isFile()) {
|
|
61
|
+
out.push(full);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const basenames = process.argv.slice(2);
|
|
67
|
+
|
|
68
|
+
if (basenames.length === 0) {
|
|
69
|
+
console.error(
|
|
70
|
+
"ERROR: check-dangling-refs.mjs requires at least one deleted-file basename as an argument",
|
|
71
|
+
);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const bundleDir = findBundleDir();
|
|
76
|
+
|
|
77
|
+
if (!bundleDir) {
|
|
78
|
+
console.error(`ERROR: No UI bundle directory found in ${UIBUNDLES_DIR}${path.sep}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const files = [];
|
|
83
|
+
collectFiles(bundleDir, files);
|
|
84
|
+
|
|
85
|
+
let foundDangling = false;
|
|
86
|
+
|
|
87
|
+
for (const basename of basenames) {
|
|
88
|
+
const matches = [];
|
|
89
|
+
for (const file of files) {
|
|
90
|
+
let content;
|
|
91
|
+
try {
|
|
92
|
+
content = fs.readFileSync(file, "utf8");
|
|
93
|
+
} catch (err) {
|
|
94
|
+
// Could not read a surviving file — record and skip. We cannot confirm it
|
|
95
|
+
// is free of the deleted reference, so the run must not report SUCCESS.
|
|
96
|
+
ioErrors.push(`could not read file '${file}': ${err.message}`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (content.includes(basename)) {
|
|
100
|
+
matches.push(file);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (matches.length > 0) {
|
|
105
|
+
foundDangling = true;
|
|
106
|
+
console.error(`ERROR: Dangling reference to deleted file '${basename}' found in:`);
|
|
107
|
+
for (const match of matches) {
|
|
108
|
+
console.error(` - ${match}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (foundDangling) {
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// A read failure means the scan was incomplete — do not claim SUCCESS.
|
|
118
|
+
if (ioErrors.length > 0) {
|
|
119
|
+
console.error(
|
|
120
|
+
"ERROR: dangling-reference scan is incomplete — some paths could not be read:",
|
|
121
|
+
);
|
|
122
|
+
for (const e of ioErrors) {
|
|
123
|
+
console.error(` - ${e}`);
|
|
124
|
+
}
|
|
125
|
+
console.error(
|
|
126
|
+
"Resolve the read errors above and re-run; not reporting SUCCESS on an incomplete scan.",
|
|
127
|
+
);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
console.log(`SUCCESS: No dangling references found for: ${basenames.join(" ")}`);
|
|
132
|
+
process.exit(0);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Check which hosting target is configured in .uibundle-meta.xml files.
|
|
3
|
+
// Usage: node check-hosting-target.mjs
|
|
4
|
+
//
|
|
5
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
6
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
7
|
+
//
|
|
8
|
+
// Prints "ExperienceSite" or "CustomApplication" to stdout and exits 0 on
|
|
9
|
+
// success. Exits 1 with an error message if no .uibundle-meta.xml files
|
|
10
|
+
// are found, or none declare a valid target.
|
|
11
|
+
|
|
12
|
+
import fs from "node:fs";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
|
|
15
|
+
const EXCLUDE_DIRS = new Set(["node_modules", "dist", "build", ".git"]);
|
|
16
|
+
|
|
17
|
+
function findMetaFiles(dir, out) {
|
|
18
|
+
let entries;
|
|
19
|
+
try {
|
|
20
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
21
|
+
} catch {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
const full = path.join(dir, entry.name);
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
if (EXCLUDE_DIRS.has(entry.name)) continue;
|
|
28
|
+
findMetaFiles(full, out);
|
|
29
|
+
} else if (entry.isFile() && entry.name.endsWith(".uibundle-meta.xml")) {
|
|
30
|
+
out.push(full);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const metaFiles = [];
|
|
36
|
+
findMetaFiles(".", metaFiles);
|
|
37
|
+
|
|
38
|
+
if (metaFiles.length === 0) {
|
|
39
|
+
console.error("ERROR: No .uibundle-meta.xml files found");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const contents = metaFiles.map((f) => {
|
|
44
|
+
try {
|
|
45
|
+
return fs.readFileSync(f, "utf8");
|
|
46
|
+
} catch {
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (contents.some((c) => c.includes("<target>ExperienceSite</target>"))) {
|
|
52
|
+
console.log("ExperienceSite");
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (contents.some((c) => c.includes("<target>CustomApplication</target>"))) {
|
|
57
|
+
console.log("CustomApplication");
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.error("ERROR: No valid hosting target found in .uibundle-meta.xml");
|
|
62
|
+
process.exit(1);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Verify Phase 1 (Scaffolding) completed successfully.
|
|
3
|
+
// Usage: node check-phase-1-complete.mjs
|
|
4
|
+
//
|
|
5
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
6
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
7
|
+
//
|
|
8
|
+
// Exit 0 if complete, exit 1 with an error message if incomplete.
|
|
9
|
+
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
|
|
13
|
+
const UIBUNDLES_DIR = path.join("force-app", "main", "default", "uiBundles");
|
|
14
|
+
|
|
15
|
+
function findBundleDir() {
|
|
16
|
+
let entries;
|
|
17
|
+
try {
|
|
18
|
+
entries = fs.readdirSync(UIBUNDLES_DIR, { withFileTypes: true });
|
|
19
|
+
} catch {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
const dirs = entries
|
|
23
|
+
.filter((e) => e.isDirectory())
|
|
24
|
+
.map((e) => e.name)
|
|
25
|
+
.sort();
|
|
26
|
+
return dirs.length > 0 ? path.join(UIBUNDLES_DIR, dirs[0]) : "";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function fail(message) {
|
|
30
|
+
console.error(message);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const bundleDir = findBundleDir();
|
|
35
|
+
|
|
36
|
+
if (!bundleDir) {
|
|
37
|
+
fail(
|
|
38
|
+
`ERROR: Phase 1 incomplete: No UI bundle directory found in ${UIBUNDLES_DIR}${path.sep}`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(path.join(bundleDir, "src"))) {
|
|
43
|
+
fail(`ERROR: Phase 1 incomplete: No src/ directory found in ${bundleDir}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const metaFiles = fs
|
|
47
|
+
.readdirSync(bundleDir)
|
|
48
|
+
.filter((name) => name.endsWith(".uibundle-meta.xml"));
|
|
49
|
+
|
|
50
|
+
if (metaFiles.length === 0) {
|
|
51
|
+
fail(`ERROR: Phase 1 incomplete: No .uibundle-meta.xml file found in ${bundleDir}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const hasTarget = metaFiles.some((name) => {
|
|
55
|
+
try {
|
|
56
|
+
return fs.readFileSync(path.join(bundleDir, name), "utf8").includes("<target>");
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (!hasTarget) {
|
|
63
|
+
fail("ERROR: Phase 1 incomplete: .uibundle-meta.xml missing <target> element");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!fs.existsSync(path.join(bundleDir, "package.json"))) {
|
|
67
|
+
fail(`ERROR: Phase 1 incomplete: No package.json found in ${bundleDir}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log("SUCCESS: Phase 1 complete: Scaffold verified");
|
|
71
|
+
process.exit(0);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Verify Phase 4 (UI) completed successfully.
|
|
3
|
+
// Usage: node check-phase-4-complete.mjs
|
|
4
|
+
//
|
|
5
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
6
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
7
|
+
//
|
|
8
|
+
// Exit 0 if complete, exit 1 with an error message if incomplete.
|
|
9
|
+
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
|
|
13
|
+
const UIBUNDLES_DIR = path.join("force-app", "main", "default", "uiBundles");
|
|
14
|
+
|
|
15
|
+
function findBundleDir() {
|
|
16
|
+
let entries;
|
|
17
|
+
try {
|
|
18
|
+
entries = fs.readdirSync(UIBUNDLES_DIR, { withFileTypes: true });
|
|
19
|
+
} catch {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
const dirs = entries
|
|
23
|
+
.filter((e) => e.isDirectory())
|
|
24
|
+
.map((e) => e.name)
|
|
25
|
+
.sort();
|
|
26
|
+
return dirs.length > 0 ? path.join(UIBUNDLES_DIR, dirs[0]) : "";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function fail(message) {
|
|
30
|
+
console.error(message);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function findTsxFiles(dir) {
|
|
35
|
+
let entries;
|
|
36
|
+
try {
|
|
37
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
38
|
+
} catch {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
const full = path.join(dir, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
out.push(...findTsxFiles(full));
|
|
46
|
+
} else if (entry.isFile() && entry.name.endsWith(".tsx")) {
|
|
47
|
+
out.push(full);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const bundleDir = findBundleDir();
|
|
54
|
+
|
|
55
|
+
if (!bundleDir) {
|
|
56
|
+
fail("ERROR: Phase 4 cannot run: No UI bundle directory found (Phase 1 not complete)");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check Phase 1 scaffold prerequisites
|
|
60
|
+
const packageJsonPath = path.join(bundleDir, "package.json");
|
|
61
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
62
|
+
fail("ERROR: Phase 4 cannot run: No package.json found (Phase 1 not complete)");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let packageJsonContent = "";
|
|
66
|
+
try {
|
|
67
|
+
packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
|
|
68
|
+
} catch {
|
|
69
|
+
packageJsonContent = "";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!packageJsonContent.includes('"react"')) {
|
|
73
|
+
fail("ERROR: Phase 4 cannot run: React dependencies not installed in package.json");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check Phase 4 completion
|
|
77
|
+
if (!fs.existsSync(path.join(bundleDir, "src", "App.tsx"))) {
|
|
78
|
+
fail(`ERROR: Phase 4 incomplete: No App.tsx found in ${path.join(bundleDir, "src")}${path.sep}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const pagesDir = path.join(bundleDir, "src", "pages");
|
|
82
|
+
if (!fs.existsSync(pagesDir) || !fs.statSync(pagesDir).isDirectory()) {
|
|
83
|
+
fail(`ERROR: Phase 4 incomplete: No pages/ directory found in ${path.join(bundleDir, "src")}${path.sep}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (findTsxFiles(pagesDir).length === 0) {
|
|
87
|
+
fail("ERROR: Phase 4 incomplete: No .tsx files found in pages/ directory");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!fs.existsSync(path.join(bundleDir, "dist", "index.html"))) {
|
|
91
|
+
fail("ERROR: Phase 4 incomplete: No dist/index.html found (build not complete)");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log("SUCCESS: Phase 4 complete: UI verified");
|
|
95
|
+
process.exit(0);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Verify Phase 6 (Deployment) prerequisites are met.
|
|
3
|
+
// Usage: node check-phase-6-ready.mjs
|
|
4
|
+
//
|
|
5
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
6
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
7
|
+
//
|
|
8
|
+
// Exit 0 if ready, exit 1 with an error message if not ready.
|
|
9
|
+
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
13
|
+
|
|
14
|
+
const UIBUNDLES_DIR = path.join("force-app", "main", "default", "uiBundles");
|
|
15
|
+
|
|
16
|
+
function findBundleDir() {
|
|
17
|
+
let entries;
|
|
18
|
+
try {
|
|
19
|
+
entries = fs.readdirSync(UIBUNDLES_DIR, { withFileTypes: true });
|
|
20
|
+
} catch {
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
const dirs = entries
|
|
24
|
+
.filter((e) => e.isDirectory())
|
|
25
|
+
.map((e) => e.name)
|
|
26
|
+
.sort();
|
|
27
|
+
return dirs.length > 0 ? path.join(UIBUNDLES_DIR, dirs[0]) : "";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function fail(message) {
|
|
31
|
+
console.error(message);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const bundleDir = findBundleDir();
|
|
36
|
+
|
|
37
|
+
if (!bundleDir) {
|
|
38
|
+
fail("ERROR: Phase 6 cannot run: No UI bundle directory found (Phase 1 not complete)");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check build artifact exists
|
|
42
|
+
if (!fs.existsSync(path.join(bundleDir, "dist", "index.html"))) {
|
|
43
|
+
fail("ERROR: Phase 6 cannot run: No dist/index.html found (Phase 4 build not complete)");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Check org authentication
|
|
47
|
+
// `shell: true` resolves `sf`/`sf.cmd` across macOS/Linux/Git Bash and native
|
|
48
|
+
// Windows shells alike.
|
|
49
|
+
const orgDisplay = spawnSync("sf", ["org", "display", "--json"], {
|
|
50
|
+
shell: true,
|
|
51
|
+
stdio: "ignore",
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (orgDisplay.status !== 0) {
|
|
55
|
+
fail("ERROR: Phase 6 cannot run: No authenticated org found (run: sf org login web)");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check hosting target is set
|
|
59
|
+
const metaFiles = fs
|
|
60
|
+
.readdirSync(bundleDir)
|
|
61
|
+
.filter((name) => name.endsWith(".uibundle-meta.xml"));
|
|
62
|
+
|
|
63
|
+
const hasTarget = metaFiles.some((name) => {
|
|
64
|
+
try {
|
|
65
|
+
return fs.readFileSync(path.join(bundleDir, name), "utf8").includes("<target>");
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (!hasTarget) {
|
|
72
|
+
fail(
|
|
73
|
+
"ERROR: Phase 6 cannot run: .uibundle-meta.xml missing <target> element (Phase 1 not complete)",
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log("SUCCESS: Phase 6 ready: All deployment prerequisites met");
|
|
78
|
+
process.exit(0);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Check prerequisites for UI Bundle app building.
|
|
3
|
+
// Usage: node check-prerequisites.mjs
|
|
4
|
+
//
|
|
5
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
6
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
7
|
+
//
|
|
8
|
+
// Exit 0 if all prerequisites are met, exit 1 with an error message if any
|
|
9
|
+
// are missing.
|
|
10
|
+
|
|
11
|
+
const [major] = process.versions.node.split(".").map(Number);
|
|
12
|
+
|
|
13
|
+
if (!Number.isFinite(major) || major < 20) {
|
|
14
|
+
console.error(
|
|
15
|
+
`ERROR: Node.js version ${process.versions.node} detected. Requires >= 20.x`,
|
|
16
|
+
);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
console.log(`SUCCESS: Node.js v${process.versions.node} meets the >= 20.x requirement`);
|
|
21
|
+
process.exit(0);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Check if sfdx-project.json exists and is valid JSON.
|
|
3
|
+
// Usage: node check-sfdx-project.mjs
|
|
4
|
+
//
|
|
5
|
+
// Always invoke via `node` (never as a bare executable) so this works on
|
|
6
|
+
// Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
|
|
7
|
+
//
|
|
8
|
+
// Exit 0 if sfdx-project.json exists and parses as JSON, exit 1 with an
|
|
9
|
+
// error message otherwise.
|
|
10
|
+
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
|
|
13
|
+
const SFDX_PROJECT = "sfdx-project.json";
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(SFDX_PROJECT)) {
|
|
16
|
+
console.error("ERROR: sfdx-project.json not found");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
JSON.parse(fs.readFileSync(SFDX_PROJECT, "utf8"));
|
|
22
|
+
} catch {
|
|
23
|
+
console.error("ERROR: sfdx-project.json is not valid JSON");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log("sfdx-project.json is valid");
|
|
28
|
+
process.exit(0);
|
|
@@ -8,6 +8,8 @@ metadata:
|
|
|
8
8
|
relatedSkills:
|
|
9
9
|
- "platform-custom-application-generate"
|
|
10
10
|
cliTools:
|
|
11
|
+
- tool: ["node"]
|
|
12
|
+
semver: ">=18.0.0"
|
|
11
13
|
- tool: ["sf"]
|
|
12
14
|
semver: ">=2.0.0"
|
|
13
15
|
mcpTools:
|
|
@@ -76,7 +78,7 @@ Use the default template in the doc below. Values in `{braces}` are resolved pro
|
|
|
76
78
|
### Step 5: Update UI Bundle Meta XML
|
|
77
79
|
This step edits an **existing** file — it never creates a new one. `UIBundle` is a bundle-style metadata type: its meta XML normally lives inside its own folder at `uiBundles/{appName}/{appName}.uibundle-meta.xml`, alongside the bundle's other source files (e.g. `index.html`, `src/`). Some older or hand-authored projects may instead have it at the flat path `uiBundles/{appName}.uibundle-meta.xml` (no subfolder).
|
|
78
80
|
|
|
79
|
-
Run `scripts/resolve-uibundle-path.
|
|
81
|
+
Run `node scripts/resolve-uibundle-path.mjs "{appName}"` — it prints the path of the existing meta XML (preferring the nested layout, falling back to the flat layout). Always invoke via `node` (never as a bare executable) so this works on Windows as well as macOS/Linux. Edit that exact file in place; do not create a second file at the other path or migrate it to a different layout as part of this skill.
|
|
80
82
|
|
|
81
83
|
If Step 2 confirmed the `target` field exists on `UIBundle`, add `<target>CustomApplication</target>` inside the existing `<UIBundle>` element of that file, preserving every other existing element and value untouched (skip this step entirely if the field doesn't exist in the org's API version — do not create the file or add `<target>` in that case).
|
|
82
84
|
|