@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
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
date: 2026-05-15
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workshop Question Policy
|
|
7
|
+
|
|
8
|
+
Rules for generating stakeholder-facing questions in the WORKSHOP spoke. The skill produces these questions for a customer's internal stakeholders to answer **asynchronously** — not in a live workshop with the skill running. So the questions need to be open-ended, thought-provoking, scoped to what's actually unresolved, and respectful of stakeholder time.
|
|
9
|
+
|
|
10
|
+
## Guiding principle
|
|
11
|
+
|
|
12
|
+
**Quality over coverage. Better to ask 4 great questions than 12 generic ones.**
|
|
13
|
+
|
|
14
|
+
There is an infinite possible question set the framework could generate. Most of those questions are noise for any specific persona. The job here is identifying *what's actually unresolved or high-leverage* for *this* persona, given everything the skill already knows.
|
|
15
|
+
|
|
16
|
+
## Skip what you already know
|
|
17
|
+
|
|
18
|
+
The skill must NOT generate questions for things it already knows from the brand input, persona draft, or context. Stakeholder attention is the scarce resource.
|
|
19
|
+
|
|
20
|
+
**Examples of what to skip:**
|
|
21
|
+
|
|
22
|
+
- The brand input clearly says "always formal" → don't ask about Formality.
|
|
23
|
+
- The customer is a serious law firm → don't ask "How much humor?" (the answer is probably None and asking burns attention on a non-question).
|
|
24
|
+
- Channel is locked to telephony → don't ask "Should the agent use emoji?" (no formatting in audio).
|
|
25
|
+
- Personification is locked to Talking System → don't ask about character names.
|
|
26
|
+
- Identity is filled with strong-signal traits → don't ask the stakeholders to re-validate every adjective; pick one or two with productive tension.
|
|
27
|
+
|
|
28
|
+
This is harder than it sounds. The framework has 14 dimensions × 5+ persona artifacts × business context. Most could generate plausible questions. The skill must actively prune.
|
|
29
|
+
|
|
30
|
+
## What to ask about
|
|
31
|
+
|
|
32
|
+
In priority order:
|
|
33
|
+
|
|
34
|
+
1. **High up the dimensions ladder** — Identity, Personification, Register. These have the most leverage; getting them wrong cascades.
|
|
35
|
+
2. **Where confidence is low** — when a draft dimension was filled with a default rather than a strong signal, that's a candidate question.
|
|
36
|
+
3. **Where productive tension exists** — Tension Pairs in the framework (Cool Warmth + Bold Personality, Blunt Coloring + Playful Humor, etc.) are inherently questions stakeholders should weigh in on.
|
|
37
|
+
4. **Where the brand input is silent or contradictory** — e.g., the brand guide says "approachable" but doesn't say how much humor; that's worth asking.
|
|
38
|
+
5. **Where channel forces a tradeoff** — voice agents handling frustrated callers; humor in escalation flows.
|
|
39
|
+
6. **Where the use case raises a tone-flex question** — the framework's tone-flex triggers (system errors, content sensitivity, escalation) are stakeholder-relevant moments.
|
|
40
|
+
|
|
41
|
+
## What never to ask about
|
|
42
|
+
|
|
43
|
+
- Things the input or context already answers definitively.
|
|
44
|
+
- Things downstream of a higher decision already made (don't ask about emoji if Formal Register is locked — Formal pulls Emoji to None).
|
|
45
|
+
- Internal mechanics the stakeholders shouldn't be making decisions about (e.g., dimension constraint notes, tension-pair resolution rules).
|
|
46
|
+
- Anything that produces a "neutral default" answer — those questions waste stakeholder attention without changing the persona.
|
|
47
|
+
|
|
48
|
+
## Question styles
|
|
49
|
+
|
|
50
|
+
Three styles, picked per question based on what's needed:
|
|
51
|
+
|
|
52
|
+
### 1. Validate
|
|
53
|
+
|
|
54
|
+
Use when the skill has a strong-signal draft and wants stakeholder confirmation.
|
|
55
|
+
|
|
56
|
+
> "We assumed [X] from your brand guide. Confirm or push back."
|
|
57
|
+
> "The agent will speak in Coach register — instructive, takes a position. That fits the 'sales coach' framing in the brief. Right call?"
|
|
58
|
+
|
|
59
|
+
### 2. Choose between
|
|
60
|
+
|
|
61
|
+
Use when there are two genuinely different positions on a spectrum, with consequences spelled out.
|
|
62
|
+
|
|
63
|
+
> "When a customer expresses frustration, would you rather the agent (A) acknowledge the frustration before solving, or (B) skip to the solve? A reads as more empathetic; B reads as more efficient. Pick one."
|
|
64
|
+
|
|
65
|
+
The two options must be **meaningfully different**. Don't write false binaries where both options are the same with cosmetic differences. If you can't articulate the consequence of each choice, drop the question.
|
|
66
|
+
|
|
67
|
+
### 3. Open spectrum
|
|
68
|
+
|
|
69
|
+
Use when it's a blank slate — no signal in the input, and the stakeholders genuinely need to make the call.
|
|
70
|
+
|
|
71
|
+
> "Place the agent on this line: [Brisk] ⟷ [Languid]"
|
|
72
|
+
> "How much character should come through? [Talking System] ⟷ [Familiar Thing] ⟷ [Personal Assistant]"
|
|
73
|
+
|
|
74
|
+
These are dimension-card-shaped — print on a page, dot-vote, or place stickies on a FigJam board. Especially good for high-leverage dimensions (Identity, Personification, Register, Warmth) where the stakeholder team needs to converge.
|
|
75
|
+
|
|
76
|
+
## Output format constraints
|
|
77
|
+
|
|
78
|
+
The workshop outline is meant to be **lightweight and printable** — a FigJam board, a whiteboard, a Google Doc with sticky notes. Not a slide deck. Not a long-form persona document. The skill's job is to produce the outline; the customer's job is to run the workshop with it.
|
|
79
|
+
|
|
80
|
+
- Aim for 4-8 total questions per workshop outline. Fewer if the persona is well-grounded.
|
|
81
|
+
- Group questions by Activity (Identity calibration, Tone in difficult moments, Spectrum check) so the workshop has a clear arc.
|
|
82
|
+
- Pre-read materials section: link to or attach the brand-grounded persona draft and sample dialog so stakeholders walk in informed.
|
|
83
|
+
- Include a brief "Background" paragraph for the facilitator (≤1 paragraph) summarizing where the persona stands and what input is needed.
|
|
84
|
+
|
|
85
|
+
## Anti-patterns to refuse
|
|
86
|
+
|
|
87
|
+
- A 20-question workshop outline. If you're hitting 20, you haven't pruned.
|
|
88
|
+
- A workshop outline for a Talking System that asks "What kind of humor?" Skip. You know the answer.
|
|
89
|
+
- A workshop outline that asks every dimension "where on the spectrum?" — that's a coverage approach, not a leverage approach.
|
|
90
|
+
- A workshop outline where every option in a "choose between" pair reads as neutral or compromised. The job is to surface real tradeoffs, not to write safe choices.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
date: 2026-05-15
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workshop Scenario Seeds
|
|
7
|
+
|
|
8
|
+
A library of common stakeholder-relevant scenarios the WORKSHOP spoke uses as starting material for would-you-rather question pairs. These are conversational moments where persona-level decisions have visible consequences.
|
|
9
|
+
|
|
10
|
+
The skill picks scenarios from this library that align with the captured Use cases and the dimensions where stakeholder input is wanted. It customizes the response options A and B to the persona under design. **Do not use these seeds verbatim** — the skill should rewrite the user utterance and the response pair so they fit the customer's actual context (their language, their typical issues, their brand voice).
|
|
11
|
+
|
|
12
|
+
## How to use this library
|
|
13
|
+
|
|
14
|
+
For each seed:
|
|
15
|
+
- The **user utterance** is a representative kind of moment, not a literal quote. Adapt the wording.
|
|
16
|
+
- The **A / B contrast** sketches the two persona directions that produce different responses. The skill rewrites both A and B in the persona's voice (or two persona voices, if asking the stakeholders to pick).
|
|
17
|
+
- The **dimensions exercised** field identifies which dimensions the choice surfaces. This helps the skill pick the right seed for the gap it's trying to fill.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Seeds
|
|
22
|
+
|
|
23
|
+
### Frustration
|
|
24
|
+
|
|
25
|
+
**User utterance:** the user expresses frustration with a problem (a billing issue, a delayed order, a feature that doesn't work).
|
|
26
|
+
|
|
27
|
+
- **A — acknowledge first, then solve.** "That's frustrating, and I'm sorry you're dealing with it. Let me look into it."
|
|
28
|
+
- **B — skip to the solve.** "Let me check that for you. One moment."
|
|
29
|
+
|
|
30
|
+
**Dimensions exercised:** Empathy Level, Emotional Coloring, Brevity. A reads as more empathetic; B reads as more efficient. Different audiences (and different brands) have different right answers.
|
|
31
|
+
|
|
32
|
+
### Escalation
|
|
33
|
+
|
|
34
|
+
**User utterance:** the user requests a human agent or escalation.
|
|
35
|
+
|
|
36
|
+
- **A — acknowledge the request, hand off warmly.** "I hear you — let me get a teammate on this who can help directly. One moment."
|
|
37
|
+
- **B — execute the handoff cleanly, no flourish.** "Connecting you to a specialist now."
|
|
38
|
+
|
|
39
|
+
**Dimensions exercised:** Warmth, Brevity, Phrase Book (handoff category). A invests in the relationship at the moment of handoff; B prioritizes speed and clarity.
|
|
40
|
+
|
|
41
|
+
### Ambiguity
|
|
42
|
+
|
|
43
|
+
**User utterance:** the user gives an ambiguous request that could mean two things ("can you check on that order").
|
|
44
|
+
|
|
45
|
+
- **A — ask for clarification before acting.** "Got it — which order? You've got [N] in flight. Order number or recent activity?"
|
|
46
|
+
- **B — make the most likely guess and surface it.** "Pulling up your most recent order — is that the one?"
|
|
47
|
+
|
|
48
|
+
**Dimensions exercised:** Brevity, Personality Intensity, Empathy Level. A is conservative and accurate; B is proactive and faster. Choice often signals whether the agent is meant to feel like a careful clerk or a quick assistant.
|
|
49
|
+
|
|
50
|
+
### Success
|
|
51
|
+
|
|
52
|
+
**User utterance:** the user confirms something worked or expresses satisfaction.
|
|
53
|
+
|
|
54
|
+
- **A — match the energy.** "Great. Glad we got it sorted."
|
|
55
|
+
- **B — acknowledge minimally and move on.** "Done."
|
|
56
|
+
|
|
57
|
+
**Dimensions exercised:** Warmth, Personality Intensity, Brevity, Emotional Coloring. A invests in the moment; B treats success as the default state. Different brands handle success differently — luxury hospitality tends toward A, transactional efficiency toward B.
|
|
58
|
+
|
|
59
|
+
### Error (system)
|
|
60
|
+
|
|
61
|
+
**User utterance:** something the agent tried to do failed (an API call timed out, a record wasn't found).
|
|
62
|
+
|
|
63
|
+
- **A — apologize, then recover.** "Sorry — that didn't go through. Let me try again."
|
|
64
|
+
- **B — state the issue, recover.** "That didn't go through. Trying again."
|
|
65
|
+
|
|
66
|
+
**Dimensions exercised:** Formality, Warmth, Empathy Level, Brevity. A apologizes for the system; B treats the error as a fact. Stakeholders sometimes care more than designers expect.
|
|
67
|
+
|
|
68
|
+
### Off-topic
|
|
69
|
+
|
|
70
|
+
**User utterance:** the user asks something the agent isn't designed to handle ("what do you think of the latest movie?").
|
|
71
|
+
|
|
72
|
+
- **A — engage briefly, then redirect.** "Ha — not really my thing. What I can help with: [scope]."
|
|
73
|
+
- **B — redirect cleanly without engagement.** "I can help with [scope]. What's on your mind?"
|
|
74
|
+
|
|
75
|
+
**Dimensions exercised:** Personality Intensity, Humor, Brevity, Phrase Book (off-topic redirect category). A acknowledges the human moment; B keeps the conversation on rails.
|
|
76
|
+
|
|
77
|
+
### Bad news
|
|
78
|
+
|
|
79
|
+
**User utterance:** the user is about to receive news they won't like (their order is delayed; the feature isn't available; the policy doesn't allow it).
|
|
80
|
+
|
|
81
|
+
- **A — soften the delivery.** "Here's what I'm seeing — and it's not the news either of us wanted: [bad news]."
|
|
82
|
+
- **B — deliver directly.** "Your order is delayed by 3 days."
|
|
83
|
+
|
|
84
|
+
**Dimensions exercised:** Empathy Level, Emotional Coloring, Personality Intensity, Tone Flex. A leans into Encouraging coloring; B leans into Blunt or Neutral. Strong stakeholder-leverage question — the answer reveals brand stance on hard truths.
|
|
85
|
+
|
|
86
|
+
### Repeat customer
|
|
87
|
+
|
|
88
|
+
**User utterance:** the user is a returning customer the agent has context on.
|
|
89
|
+
|
|
90
|
+
- **A — personalize the greeting.** "Welcome back, [name]. Last time we were sorting out [thing]."
|
|
91
|
+
- **B — start fresh, treat each session as new.** "Hi — what can I help with today?"
|
|
92
|
+
|
|
93
|
+
**Dimensions exercised:** Warmth, Personality Intensity, Personification. A treats the relationship as continuous; B treats each session discretely. Often a privacy / brand-stance question.
|
|
94
|
+
|
|
95
|
+
### Compliment / kudos
|
|
96
|
+
|
|
97
|
+
**User utterance:** the user thanks the agent or compliments its help.
|
|
98
|
+
|
|
99
|
+
- **A — accept the thanks warmly.** "Glad it helped. Anything else?"
|
|
100
|
+
- **B — deflect to the user's effort.** "You did the work — I just pulled the data. Anything else?"
|
|
101
|
+
|
|
102
|
+
**Dimensions exercised:** Personality Intensity, Warmth, Humor. A is straightforward; B is humble and frames the interaction as collaborative. The choice signals whether the agent has its own agency or is a tool.
|
|
103
|
+
|
|
104
|
+
### Disagreement
|
|
105
|
+
|
|
106
|
+
**User utterance:** the user pushes back on the agent's recommendation or information.
|
|
107
|
+
|
|
108
|
+
- **A — yield gracefully.** "Fair enough — let's go with your call. What can I do next?"
|
|
109
|
+
- **B — hold the line with reasoning.** "Hear you on that. The reason I went there: [reason]. Want to walk through together?"
|
|
110
|
+
|
|
111
|
+
**Dimensions exercised:** Register, Personality Intensity, Empathy Level. A is more Subordinate / accommodating; B is more Coach / Advisor with conviction. Reveals whether the agent has a point of view.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Coverage
|
|
116
|
+
|
|
117
|
+
The library covers the situations a typical Agentforce agent will encounter — happy path, uncertainty, hard moments, and edge cases. The skill doesn't need to use all of these in any one workshop. **Pick 2-4 that align with the persona's use cases and the gaps in dimension coverage.**
|
|
118
|
+
|
|
119
|
+
If the agent's use cases include heavy escalation work, prioritize Frustration + Escalation + Bad news. If the agent is consultative (sales coach, advisor), prioritize Disagreement + Ambiguity + Compliment. If the agent is transactional, Frustration + Success + Off-topic may cover it.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Parse an Agent Script .agent file and return a normalized dict.
|
|
3
|
+
|
|
4
|
+
READ-ONLY. This script never writes back to the source file. It opens the
|
|
5
|
+
file, walks the structure, and returns a normalized Python dict that the
|
|
6
|
+
SKILL.md flow can iterate over without caring about the file's exact YAML
|
|
7
|
+
nesting.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python3 parse_agent_yaml.py <path-to-.agent-file>
|
|
11
|
+
|
|
12
|
+
Output (stdout): JSON-formatted normalized structure.
|
|
13
|
+
|
|
14
|
+
Normalized shape:
|
|
15
|
+
{
|
|
16
|
+
"system": {
|
|
17
|
+
"instructions": str,
|
|
18
|
+
"welcome": str,
|
|
19
|
+
"error": str,
|
|
20
|
+
},
|
|
21
|
+
"config": {
|
|
22
|
+
"developer_name": str,
|
|
23
|
+
"agent_label": str,
|
|
24
|
+
"agent_type": str,
|
|
25
|
+
...
|
|
26
|
+
},
|
|
27
|
+
"subagents": [
|
|
28
|
+
{
|
|
29
|
+
"name": str,
|
|
30
|
+
"description": str,
|
|
31
|
+
"instructions": str | None,
|
|
32
|
+
"reasoning_instructions": str | None,
|
|
33
|
+
"system_override": str | None,
|
|
34
|
+
"actions": [{"name": str, "progress_indicator_message": str | None}, ...]
|
|
35
|
+
},
|
|
36
|
+
...
|
|
37
|
+
],
|
|
38
|
+
"actions_global": [{"name": str, "progress_indicator_message": str | None}, ...],
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
The skill uses this structure to:
|
|
42
|
+
- SCORE: traverse subagents and actions, score per layer
|
|
43
|
+
- ENCODE (brownfield): produce a proposed-new-file with only persona-bearing
|
|
44
|
+
fields modified, preserving everything else exactly as the source had it.
|
|
45
|
+
|
|
46
|
+
Note on Agent Script syntax: .agent files are YAML-LIKE but use directive
|
|
47
|
+
syntax (`->`, `|`, `system:`, `subagent name:`) that isn't strict YAML. This
|
|
48
|
+
parser does best-effort regex-based extraction targeted at the persona-bearing
|
|
49
|
+
fields the skill needs. For full Agent Script parsing, refer to the
|
|
50
|
+
developing-agentforce skill in forcedotcom/sf-skills.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
import json
|
|
54
|
+
import re
|
|
55
|
+
import sys
|
|
56
|
+
from pathlib import Path
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def parse_agent_file(path: Path) -> dict:
|
|
60
|
+
"""Parse an .agent file and return normalized structure. Read-only."""
|
|
61
|
+
text = path.read_text()
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
"system": _extract_system(text),
|
|
65
|
+
"config": _extract_config(text),
|
|
66
|
+
"subagents": _extract_subagents(text),
|
|
67
|
+
"actions_global": [], # Global actions are rare; usually nested under subagents.
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _extract_block(text: str, header: str) -> str | None:
|
|
72
|
+
"""Extract a top-level block (system, config, etc.) by indent boundary.
|
|
73
|
+
|
|
74
|
+
Returns the block content (lines after the header, dedented) or None if
|
|
75
|
+
the header isn't present.
|
|
76
|
+
"""
|
|
77
|
+
lines = text.splitlines()
|
|
78
|
+
in_block = False
|
|
79
|
+
block_indent: int | None = None
|
|
80
|
+
block_lines: list[str] = []
|
|
81
|
+
|
|
82
|
+
for line in lines:
|
|
83
|
+
if not in_block:
|
|
84
|
+
stripped = line.strip()
|
|
85
|
+
if stripped == header or stripped == f"{header}:":
|
|
86
|
+
in_block = True
|
|
87
|
+
continue
|
|
88
|
+
else:
|
|
89
|
+
if not line.strip():
|
|
90
|
+
block_lines.append(line)
|
|
91
|
+
continue
|
|
92
|
+
indent = len(line) - len(line.lstrip())
|
|
93
|
+
if block_indent is None:
|
|
94
|
+
block_indent = indent
|
|
95
|
+
if indent < block_indent and line.strip():
|
|
96
|
+
# Dedent below the block — we're out.
|
|
97
|
+
break
|
|
98
|
+
block_lines.append(line[block_indent:] if len(line) >= block_indent else line)
|
|
99
|
+
|
|
100
|
+
return "\n".join(block_lines).rstrip() if block_lines else None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _extract_field(block: str | None, key: str) -> str | None:
|
|
104
|
+
"""Extract a `key: value` or `key: |` literal-block field from a block."""
|
|
105
|
+
if not block:
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
# Try literal block scalar first: key: |\n text...
|
|
109
|
+
pattern_literal = rf"^{re.escape(key)}:\s*\|\s*\n((?:[ \t]+.*\n?)*)"
|
|
110
|
+
m = re.search(pattern_literal, block, flags=re.MULTILINE)
|
|
111
|
+
if m:
|
|
112
|
+
return _dedent(m.group(1)).rstrip()
|
|
113
|
+
|
|
114
|
+
# Try inline string: key: "value" or key: value
|
|
115
|
+
pattern_inline = rf'^{re.escape(key)}:\s*"?([^"\n]*?)"?\s*$'
|
|
116
|
+
m = re.search(pattern_inline, block, flags=re.MULTILINE)
|
|
117
|
+
if m:
|
|
118
|
+
val = m.group(1).strip()
|
|
119
|
+
return val if val else None
|
|
120
|
+
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _dedent(text: str) -> str:
|
|
125
|
+
"""Strip the common leading whitespace from every line."""
|
|
126
|
+
lines = text.splitlines()
|
|
127
|
+
indents = [len(l) - len(l.lstrip()) for l in lines if l.strip()]
|
|
128
|
+
if not indents:
|
|
129
|
+
return text
|
|
130
|
+
common = min(indents)
|
|
131
|
+
return "\n".join(l[common:] if len(l) >= common else l for l in lines)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _extract_system(text: str) -> dict:
|
|
135
|
+
block = _extract_block(text, "system")
|
|
136
|
+
if not block:
|
|
137
|
+
return {"instructions": None, "welcome": None, "error": None}
|
|
138
|
+
|
|
139
|
+
# messages is a sub-block
|
|
140
|
+
messages_block = _extract_block(block, "messages")
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
"instructions": _extract_field(block, "instructions"),
|
|
144
|
+
"welcome": _extract_field(messages_block, "welcome"),
|
|
145
|
+
"error": _extract_field(messages_block, "error"),
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _extract_config(text: str) -> dict:
|
|
150
|
+
block = _extract_block(text, "config")
|
|
151
|
+
if not block:
|
|
152
|
+
return {}
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
"developer_name": _extract_field(block, "developer_name"),
|
|
156
|
+
"agent_label": _extract_field(block, "agent_label"),
|
|
157
|
+
"description": _extract_field(block, "description"),
|
|
158
|
+
"agent_type": _extract_field(block, "agent_type"),
|
|
159
|
+
"default_agent_user": _extract_field(block, "default_agent_user"),
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _extract_subagents(text: str) -> list[dict]:
|
|
164
|
+
"""Find each `subagent NAME:` block and extract its persona-bearing fields."""
|
|
165
|
+
# Match subagent declarations and capture name + body
|
|
166
|
+
pattern = r"^subagent\s+(\w+):\s*\n((?:[ \t]+.*\n?)*)"
|
|
167
|
+
subagents: list[dict] = []
|
|
168
|
+
|
|
169
|
+
for match in re.finditer(pattern, text, flags=re.MULTILINE):
|
|
170
|
+
name = match.group(1)
|
|
171
|
+
body = _dedent(match.group(2))
|
|
172
|
+
|
|
173
|
+
system_override_block = _extract_block(body, "system")
|
|
174
|
+
reasoning_block = _extract_block(body, "reasoning")
|
|
175
|
+
|
|
176
|
+
subagents.append({
|
|
177
|
+
"name": name,
|
|
178
|
+
"description": _extract_field(body, "description"),
|
|
179
|
+
"system_override": _extract_field(system_override_block, "instructions"),
|
|
180
|
+
"reasoning_instructions": _extract_field(reasoning_block, "instructions"),
|
|
181
|
+
"actions": _extract_subagent_actions(body),
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
return subagents
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _extract_subagent_actions(subagent_body: str) -> list[dict]:
|
|
188
|
+
"""Extract per-action progress_indicator_message from a subagent's actions: block."""
|
|
189
|
+
actions_block = _extract_block(subagent_body, "actions")
|
|
190
|
+
if not actions_block:
|
|
191
|
+
return []
|
|
192
|
+
|
|
193
|
+
actions: list[dict] = []
|
|
194
|
+
# Action declarations are like: `action_name:` followed by indented properties
|
|
195
|
+
pattern = r"^(\w+):\s*\n((?:[ \t]+.*\n?)*)"
|
|
196
|
+
for match in re.finditer(pattern, actions_block, flags=re.MULTILINE):
|
|
197
|
+
name = match.group(1)
|
|
198
|
+
body = _dedent(match.group(2))
|
|
199
|
+
actions.append({
|
|
200
|
+
"name": name,
|
|
201
|
+
"progress_indicator_message": _extract_field(body, "progress_indicator_message"),
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
return actions
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def main() -> int:
|
|
208
|
+
if len(sys.argv) != 2:
|
|
209
|
+
print("Usage: parse_agent_yaml.py <path-to-.agent-file>", file=sys.stderr)
|
|
210
|
+
return 1
|
|
211
|
+
|
|
212
|
+
path = Path(sys.argv[1])
|
|
213
|
+
if not path.exists():
|
|
214
|
+
print(f"File not found: {path}", file=sys.stderr)
|
|
215
|
+
return 1
|
|
216
|
+
|
|
217
|
+
parsed = parse_agent_file(path)
|
|
218
|
+
print(json.dumps(parsed, indent=2))
|
|
219
|
+
return 0
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
if __name__ == "__main__":
|
|
223
|
+
sys.exit(main())
|
|
@@ -15,6 +15,8 @@ metadata:
|
|
|
15
15
|
semver: ">=22.0.0"
|
|
16
16
|
- tool: ["sf"]
|
|
17
17
|
semver: ">=2.0.0"
|
|
18
|
+
- tool: ["sfdx"]
|
|
19
|
+
semver: ">=7.0.0"
|
|
18
20
|
---
|
|
19
21
|
|
|
20
22
|
## MANDATORY: Always write the Phase 6 report
|
|
@@ -134,37 +136,30 @@ is empty — `WHERE CreatedDate > null` is an `INVALID_QUERY_FILTER_OPERATOR` er
|
|
|
134
136
|
Salesforce SOQL and will abort the query.
|
|
135
137
|
|
|
136
138
|
### 1.7 Org-side manual prerequisites
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
as confirmed — do **not** re-ask. Only ask for items the user has not already addressed:
|
|
139
|
+
If the user's prompt already confirms these prerequisites, treat them as confirmed — do
|
|
140
|
+
**not** re-ask. Only ask for items the user has not already addressed:
|
|
140
141
|
- Data Cloud and Analytics Studio enabled (Setup → Data Cloud Setup)
|
|
141
142
|
- Connectors feature enabled (Data Cloud Setup → Feature Manager)
|
|
142
143
|
- A user assigned to the **Accrual Ingestion Process** in Processing Services Pairing
|
|
143
144
|
with the **Data Cloud Architect** permission set
|
|
144
|
-
- OAuth scope **`cdp_ingest_api`**
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
or Setup → External Client Apps. Do NOT assume any specific app name.
|
|
148
|
-
- Permission sets assigned to the System Admin (and to the Accrual Ingestion Process user):
|
|
149
|
-
- **Data Cloud Architect**
|
|
150
|
-
- CRM Analytics must be enabled first (Setup → Feature Settings → Analytics → Analytics → Getting Started → "Enable CRM Analytics"), then assign to the admin:
|
|
151
|
-
- **CRM Analytics Plus Admin**
|
|
145
|
+
- OAuth scope **`cdp_ingest_api`** on the TPM Offcore connected app
|
|
146
|
+
- Licenses: `AccrualsProcessingAddOn`, `AccrualsProcessingUserAddOn`,
|
|
147
|
+
`TpmAccrualsAddOn`, `TpmAccrualsUserAddOn` (advisory — record what the user confirmed)
|
|
152
148
|
|
|
153
149
|
---
|
|
154
150
|
|
|
155
151
|
## Phase 2 — Verify the Data Cloud connection (best-effort)
|
|
156
152
|
|
|
157
|
-
|
|
158
|
-
App**, and the app name varies by org configuration — it cannot be queried reliably by
|
|
159
|
-
name. Skip the programmatic check. Instead, if the user has not already confirmed
|
|
160
|
-
`cdp_ingest_api` as part of Phase 1.7, ask them to verify it manually:
|
|
153
|
+
Try to verify `cdp_ingest_api` by query — treat "cannot verify" as WARN, not STOP:
|
|
161
154
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
155
|
+
```bash
|
|
156
|
+
sf data query --target-org <alias> \
|
|
157
|
+
--query "SELECT Id, Name FROM ConnectedApplication WHERE Name LIKE '%TPM%'"
|
|
158
|
+
```
|
|
165
159
|
|
|
166
|
-
|
|
167
|
-
|
|
160
|
+
If the query errors on permissions, ask the user to confirm `cdp_ingest_api` is in
|
|
161
|
+
Setup → App Manager → (edit TPM Offcore connected app) → OAuth Policies →
|
|
162
|
+
Selected OAuth Scopes. Continue only after the user confirms.
|
|
168
163
|
|
|
169
164
|
---
|
|
170
165
|
|
|
@@ -228,13 +223,8 @@ Evaluate the rows:
|
|
|
228
223
|
failing component name and its `DeploymentError` value. Do not proceed to Phase 5.
|
|
229
224
|
Record Phase 5 as `not run — deployment failures unresolved` in the Phase 6 report.
|
|
230
225
|
- Any `InProgress` row → wait 60 s and re-query. **Do not advance to Phase 5 until all
|
|
231
|
-
rows are in a terminal state** (`Successful` or `Failure`).
|
|
232
|
-
|
|
233
|
-
has an internal 90-minute polling timeout — if the script exits with a timeout error,
|
|
234
|
-
**do not treat this as a failure**: query `DataKitDeploymentLog` directly in the agent
|
|
235
|
-
Phase 4 loop (as shown above) and continue polling until terminal state or a genuine
|
|
236
|
-
liveness signal is lost (org unreachable, explicit Failure rows). Surface live counts
|
|
237
|
-
periodically so the user can see progress.
|
|
226
|
+
rows are in a terminal state** (`Successful` or `Failure`). If any row is still
|
|
227
|
+
`InProgress` after 30 minutes, stop and surface the live counts.
|
|
238
228
|
- Zero rows → the deployment has not produced log entries yet; re-query every 60 s up to
|
|
239
229
|
30 minutes. Treat persistent zero rows as a deployment problem — stop and report.
|
|
240
230
|
- All rows `Successful` → proceed to Phase 5.
|
|
@@ -179,16 +179,7 @@ function getConfig() {
|
|
|
179
179
|
* @param {string} salesOrg - Must be exactly 4 alphanumeric characters.
|
|
180
180
|
* @param {string|null} namespaceOverride - When non-null, must be 1-15 alphanumeric characters.
|
|
181
181
|
*/
|
|
182
|
-
function validateInputs(salesOrg, namespaceOverride
|
|
183
|
-
// Org alias: Salesforce allows alphanumeric, hyphens, underscores, dots, and @ (usernames).
|
|
184
|
-
// Restrict to safe characters to prevent shell metacharacter injection on Windows cmd.exe.
|
|
185
|
-
// Allow alphanumeric, hyphens, underscores, dots, @, and + (valid in Salesforce usernames, e.g. user+ci@example.com).
|
|
186
|
-
// None of these characters are cmd.exe metacharacters, so shell injection via org alias is prevented.
|
|
187
|
-
if (!/^[A-Za-z0-9_\-@.+]+$/.test(orgAlias)) {
|
|
188
|
-
console.error(`Error: Invalid org alias "${orgAlias}". Must contain only alphanumeric characters, hyphens, underscores, dots, @, or +.`);
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
|
|
182
|
+
function validateInputs(salesOrg, namespaceOverride) {
|
|
192
183
|
if (!/^[A-Za-z0-9]{4}$/.test(salesOrg)) {
|
|
193
184
|
console.error('Error: Invalid sales org.');
|
|
194
185
|
process.exit(1);
|
|
@@ -232,7 +223,7 @@ async function main() {
|
|
|
232
223
|
const { orgAlias, skipDataSpace, salesOrg, dryRun, namespaceOverride } = config;
|
|
233
224
|
|
|
234
225
|
// Validate inputs before any org access or step execution
|
|
235
|
-
validateInputs(salesOrg, namespaceOverride
|
|
226
|
+
validateInputs(salesOrg, namespaceOverride);
|
|
236
227
|
|
|
237
228
|
const { dataSpaceName, dataSpacePrefix } = getDataSpaceConfig(salesOrg);
|
|
238
229
|
|
|
@@ -274,6 +265,8 @@ async function main() {
|
|
|
274
265
|
}
|
|
275
266
|
|
|
276
267
|
const setupDir = __dirname;
|
|
268
|
+
const dataKitPath = path.join(setupDir, 'CGCloudAddons', 'TPM', 'Accruals', 'TPM Accruals Data Kit');
|
|
269
|
+
const scriptsDir = path.join(setupDir, 'CGCloudAddons', 'TPM', 'Accruals', 'Accruals Data Kit Deployment Scripts');
|
|
277
270
|
|
|
278
271
|
console.log(`Sales Org: ${salesOrg}`);
|
|
279
272
|
if (!skipDataSpace) {
|
|
@@ -289,10 +282,7 @@ async function main() {
|
|
|
289
282
|
}
|
|
290
283
|
|
|
291
284
|
// Run all steps in order
|
|
292
|
-
|
|
293
|
-
const cgcloudAddonsDir = await downloadStaticResource(orgAlias, setupDir);
|
|
294
|
-
const dataKitPath = path.join(cgcloudAddonsDir, 'TPM', 'Accruals', 'TPM Accruals Data Kit');
|
|
295
|
-
const scriptsDir = path.join(cgcloudAddonsDir, 'TPM', 'Accruals', 'Accruals Data Kit Deployment Scripts');
|
|
285
|
+
await downloadStaticResource(orgAlias, setupDir);
|
|
296
286
|
await replaceOrgId(orgId, dataKitPath);
|
|
297
287
|
await deployMetadata(orgAlias, dataKitPath, dryRun);
|
|
298
288
|
await deployEngine(orgAlias, scriptsDir, orgId, namespace, dryRun);
|
|
@@ -306,10 +296,10 @@ async function main() {
|
|
|
306
296
|
}
|
|
307
297
|
|
|
308
298
|
// Step 7: Deploy Accruals Reports with Data Space replacements
|
|
309
|
-
await deployAccrualsReports(orgAlias,
|
|
299
|
+
await deployAccrualsReports(orgAlias, setupDir, skipDataSpace, dataSpaceName, dataSpacePrefix, namespace, dryRun);
|
|
310
300
|
|
|
311
301
|
// Step 8: Deploy UI components (TPMAccrualTacticSummary)
|
|
312
|
-
await deployUI(orgAlias,
|
|
302
|
+
await deployUI(orgAlias, setupDir, skipDataSpace, dataSpaceName, dataSpacePrefix, salesOrg, namespace, dryRun);
|
|
313
303
|
|
|
314
304
|
// Step 9: Completion and next steps
|
|
315
305
|
await completion(dryRun);
|