@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.
Files changed (242) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-architecture-analyze/SKILL.md +66 -17
  3. package/skills/agentforce-architecture-analyze/assets/cli/show_access_token.yaml +4 -7
  4. package/skills/agentforce-architecture-analyze/references/contract.json +1 -1
  5. package/skills/agentforce-architecture-analyze/scripts/emit_env.py +2 -2
  6. package/skills/agentforce-architecture-analyze/scripts/main.py +40 -44
  7. package/skills/agentforce-architecture-analyze/scripts/rest_client.py +11 -3
  8. package/skills/agentforce-architecture-analyze/scripts/sf_cli.py +77 -10
  9. package/skills/agentforce-architecture-analyze/scripts/tests/test_end_to_end_fixture.py +1 -0
  10. package/skills/agentforce-architecture-analyze/scripts/tests/test_flow_children_inflation.py +1 -0
  11. package/skills/agentforce-architecture-analyze/scripts/tests/test_main_pipeline.py +53 -2
  12. package/skills/agentforce-architecture-analyze/scripts/tests/test_resolve_creds.py +184 -36
  13. package/skills/agentforce-architecture-analyze/scripts/tests/test_rest_client.py +17 -0
  14. package/skills/agentforce-architecture-analyze/scripts/tests/test_sf_cli.py +165 -11
  15. package/skills/agentforce-architecture-analyze/scripts/tests/test_skill_md_pipeline_block.py +319 -0
  16. package/skills/agentforce-bot-upgrade/SKILL.md +3 -1
  17. package/skills/agentforce-d360-analyze/SKILL.md +28 -10
  18. package/skills/agentforce-d360-analyze/scripts/dc.py +200 -50
  19. package/skills/agentforce-d360-analyze/scripts/discover_sessions.py +10 -6
  20. package/skills/agentforce-d360-analyze/scripts/fetch_dc.py +22 -6
  21. package/skills/agentforce-d360-analyze/scripts/resolve_session.py +21 -13
  22. package/skills/agentforce-d360-analyze/scripts/tests/test_dc_and_resolve_session.py +298 -76
  23. package/skills/agentforce-d360-analyze/scripts/tests/test_default_target_org.py +432 -0
  24. package/skills/agentforce-d360-analyze/scripts/tests/test_discover_sessions.py +1 -1
  25. package/skills/agentforce-d360-analyze/scripts/tests/test_resolve_session_main.py +9 -3
  26. package/skills/agentforce-d360-analyze/scripts/tests/test_skill_md_prefix_block.py +176 -0
  27. package/skills/agentforce-generate/SKILL.md +21 -1
  28. package/skills/agentforce-generate/references/known-issues.md +51 -1
  29. package/skills/agentforce-generate/references/legacy-nga-regression-eval.md +547 -0
  30. package/skills/agentforce-generate/references/upgrade-legacy-agent-to-agentscript.md +577 -0
  31. package/skills/agentforce-generate/scripts/upgrade-legacy-nga-analyze.py +404 -0
  32. package/skills/agentforce-generate/scripts/upgrade-legacy-nga-run-trials.sh +58 -0
  33. package/skills/agentforce-persona-generate/SKILL.md +505 -0
  34. package/skills/agentforce-persona-generate/assets/checklist-template.md +100 -0
  35. package/skills/agentforce-persona-generate/assets/persona-encoding-template.md +252 -0
  36. package/skills/agentforce-persona-generate/assets/persona-template.md +229 -0
  37. package/skills/agentforce-persona-generate/assets/sample-dialog-template.md +50 -0
  38. package/skills/agentforce-persona-generate/assets/workshop-outline-template.md +97 -0
  39. package/skills/agentforce-persona-generate/examples/concierge-persona.md +189 -0
  40. package/skills/agentforce-persona-generate/examples/concierge-sample-dialog.md +70 -0
  41. package/skills/agentforce-persona-generate/examples/drover-persona.md +194 -0
  42. package/skills/agentforce-persona-generate/examples/drover-sample-dialog.md +62 -0
  43. package/skills/agentforce-persona-generate/examples/steady-hand-persona.md +188 -0
  44. package/skills/agentforce-persona-generate/examples/steady-hand-sample-dialog.md +68 -0
  45. package/skills/agentforce-persona-generate/examples/yt-persona.md +195 -0
  46. package/skills/agentforce-persona-generate/examples/yt-sample-dialog.md +66 -0
  47. package/skills/agentforce-persona-generate/references/attributions.md +36 -0
  48. package/skills/agentforce-persona-generate/references/interaction-design-notes.md +30 -0
  49. package/skills/agentforce-persona-generate/references/persona-encoding-guide.md +566 -0
  50. package/skills/agentforce-persona-generate/references/persona-framework.md +796 -0
  51. package/skills/agentforce-persona-generate/references/refinement-mappings.md +31 -0
  52. package/skills/agentforce-persona-generate/references/scoring-rubric.md +58 -0
  53. package/skills/agentforce-persona-generate/references/voice-catalog.json +2327 -0
  54. package/skills/agentforce-persona-generate/references/workshop-question-policy.md +90 -0
  55. package/skills/agentforce-persona-generate/references/workshop-scenario-seeds.md +119 -0
  56. package/skills/agentforce-persona-generate/scripts/parse_agent_yaml.py +223 -0
  57. package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +17 -27
  58. package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +7 -17
  59. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +47 -63
  60. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +10 -13
  61. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -46
  62. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +4 -21
  63. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +58 -82
  64. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +16 -315
  65. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +9 -24
  66. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -44
  67. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +11 -63
  68. package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +2 -1
  69. package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +2 -1
  70. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +2 -1
  71. package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +2 -1
  72. package/skills/data360-schema-get/SKILL.md +3 -3
  73. package/skills/design-systems-slds-validate/references/report-format.md +1 -1
  74. package/skills/dx-app-analytics-query/SKILL.md +8 -8
  75. package/skills/dx-org-manage/SKILL.md +1 -0
  76. package/skills/dx-org-shape-manage/SKILL.md +1 -0
  77. package/skills/dx-org-snapshot-manage/SKILL.md +172 -0
  78. package/skills/dx-org-snapshot-manage/examples/create_error_output.json +16 -0
  79. package/skills/dx-org-snapshot-manage/examples/create_success_output.json +19 -0
  80. package/skills/dx-org-snapshot-manage/examples/delete_output.json +9 -0
  81. package/skills/dx-org-snapshot-manage/examples/get_output.json +19 -0
  82. package/skills/dx-org-snapshot-manage/examples/list_output.json +36 -0
  83. package/skills/dx-org-snapshot-manage/references/cli_flags.md +179 -0
  84. package/skills/dx-org-snapshot-manage/references/snapshot_usage.md +55 -0
  85. package/skills/dx-org-trial-expiration-check/SKILL.md +1 -1
  86. package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +2 -2
  87. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +7 -5
  88. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +11 -11
  89. package/skills/experience-content-media-image-generate/SKILL.md +83 -0
  90. package/skills/experience-content-media-image-generate/scripts/download-image.sh +84 -0
  91. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -12
  92. package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md +3 -3
  93. package/skills/experience-ui-bundle-app-coordinate/references/phase-execution-pattern.md +9 -7
  94. package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.mjs +132 -0
  95. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.mjs +62 -0
  96. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.mjs +71 -0
  97. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.mjs +95 -0
  98. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.mjs +78 -0
  99. package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.mjs +21 -0
  100. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.mjs +28 -0
  101. package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +3 -1
  102. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.mjs +40 -0
  103. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +7 -5
  104. package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.mjs +70 -0
  105. package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.mjs +76 -0
  106. package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.mjs +115 -0
  107. package/skills/experience-ui-bundle-metadata-generate/SKILL.md +7 -3
  108. package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +1 -1
  109. package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +1 -1
  110. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.mjs +43 -0
  111. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.mjs +131 -0
  112. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.mjs +152 -0
  113. package/skills/experience-ui-bundle-mfa-configure/references/branding.md +10 -6
  114. package/skills/external-diagram-mermaid-generate/SKILL.md +12 -12
  115. package/skills/field-service-data-capture-migrate/references/component-mapping.md +1 -1
  116. package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +1 -2
  117. package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +1 -0
  118. package/skills/field-service-data-capture-migrate/references/transformer-rules.md +1 -1
  119. package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +12 -1
  120. package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +4 -1
  121. package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -1
  122. package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +233 -0
  123. package/skills/insurance-brokerage-agency-billing-configure/references/accounting-setup.md +117 -0
  124. package/skills/insurance-brokerage-agency-billing-configure/references/billing-rules-config.md +237 -0
  125. package/skills/insurance-brokerage-agency-billing-configure/references/billing-settings.md +271 -0
  126. package/skills/insurance-brokerage-agency-billing-configure/references/demo-policy-config.md +138 -0
  127. package/skills/insurance-brokerage-agency-billing-configure/references/org-defaults.md +64 -0
  128. package/skills/insurance-brokerage-agency-billing-configure/references/permissions-config.md +226 -0
  129. package/skills/insurance-brokerage-agency-billing-configure/references/prerequisites.md +142 -0
  130. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +3 -2
  131. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +3 -3
  132. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +68 -45
  133. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +17 -18
  134. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +16 -3
  135. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +16 -13
  136. package/skills/marketing-message-test/SKILL.md +194 -0
  137. package/skills/marketing-message-test/references/api-contract.md +333 -0
  138. package/skills/omnistudio-callable-apex-generate/SKILL.md +3 -3
  139. package/skills/omnistudio-datamapper-generate/SKILL.md +6 -6
  140. package/skills/omnistudio-datapacks-deploy/SKILL.md +11 -11
  141. package/skills/omnistudio-dependencies-analyze/SKILL.md +5 -5
  142. package/skills/omnistudio-epc-catalog-generate/SKILL.md +6 -6
  143. package/skills/omnistudio-flexcard-generate/SKILL.md +6 -6
  144. package/skills/omnistudio-integration-procedure-generate/SKILL.md +6 -6
  145. package/skills/omnistudio-omniscript-generate/SKILL.md +6 -5
  146. package/skills/platform-apex-logs-debug/SKILL.md +1 -0
  147. package/skills/platform-metadata-deploy/SKILL.md +1 -0
  148. package/skills/platform-models-api-configure/SKILL.md +5 -5
  149. package/skills/platform-soql-query/SKILL.md +1 -0
  150. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +17 -6
  151. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +107 -192
  152. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +6 -6
  153. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +49 -20
  154. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +4 -4
  155. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +224 -290
  156. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +295 -0
  157. package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -1
  158. package/skills/service-itsm-slack-itservice-configure/SKILL.md +2 -1
  159. package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +2 -2
  160. package/skills/service-omni-channel-setup-coordinate/SKILL.md +20 -13
  161. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +5 -55
  162. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +0 -38
  163. package/skills/service-omni-command-center-analyze/SKILL.md +2 -3
  164. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
  165. package/skills/tableau-next-asset-create/README.md +65 -0
  166. package/skills/tableau-next-asset-create/SKILL.md +409 -0
  167. package/skills/tableau-next-asset-create/references/admin-users.md +149 -0
  168. package/skills/tableau-next-asset-create/references/ai-readiness.md +355 -0
  169. package/skills/tableau-next-asset-create/references/alerts.md +111 -0
  170. package/skills/tableau-next-asset-create/references/build-workflow.md +819 -0
  171. package/skills/tableau-next-asset-create/references/dashboard-authoring.md +302 -0
  172. package/skills/tableau-next-asset-create/references/dashboard-design-principles.md +352 -0
  173. package/skills/tableau-next-asset-create/references/data-transform-gotchas.md +210 -0
  174. package/skills/tableau-next-asset-create/references/data-understanding.md +387 -0
  175. package/skills/tableau-next-asset-create/references/deep-reference-index.md +74 -0
  176. package/skills/tableau-next-asset-create/references/destructive-operations.md +62 -0
  177. package/skills/tableau-next-asset-create/references/edit-dashboard.md +273 -0
  178. package/skills/tableau-next-asset-create/references/edit-visualization.md +529 -0
  179. package/skills/tableau-next-asset-create/references/empty-source-handling.md +104 -0
  180. package/skills/tableau-next-asset-create/references/ingest-and-metric-gotchas.md +638 -0
  181. package/skills/tableau-next-asset-create/references/insight-bundle.md +69 -0
  182. package/skills/tableau-next-asset-create/references/large-flat-file-handling.md +331 -0
  183. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_envelope.json +54 -0
  184. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_shared-widget-fields.json +122 -0
  185. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/add_page.json +29 -0
  186. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/delete_page.json +27 -0
  187. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json +11 -0
  188. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget.json +30 -0
  189. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget_to_page.json +30 -0
  190. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/place_widget_on_page.json +30 -0
  191. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_dashboard.json +16 -0
  192. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_page.json +26 -0
  193. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/rename_page.json +28 -0
  194. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/save_dashboard.json +18 -0
  195. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/undo.json +11 -0
  196. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_button_widget.json +69 -0
  197. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_container_widget.json +88 -0
  198. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_filter_widget.json +146 -0
  199. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_metric_widget.json +78 -0
  200. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_navigation_widget.json +80 -0
  201. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_parameter_widget.json +160 -0
  202. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_text_widget.json +103 -0
  203. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_visualization_widget.json +68 -0
  204. package/skills/tableau-next-asset-create/references/sdm-tool-reference.md +721 -0
  205. package/skills/tableau-next-asset-create/references/semantic-query-and-enrichment.md +355 -0
  206. package/skills/tableau-next-asset-create/references/shared-gates.md +322 -0
  207. package/skills/tableau-next-asset-create/references/sharing-and-promotion.md +306 -0
  208. package/skills/tableau-next-asset-create/references/tasks/ai-readiness-audit.md +51 -0
  209. package/skills/tableau-next-asset-create/references/tasks/analyze-data.md +48 -0
  210. package/skills/tableau-next-asset-create/references/tasks/build-dashboard.md +66 -0
  211. package/skills/tableau-next-asset-create/references/tasks/build-end-to-end.md +73 -0
  212. package/skills/tableau-next-asset-create/references/tasks/create-data-transform.md +51 -0
  213. package/skills/tableau-next-asset-create/references/tasks/create-viz.md +58 -0
  214. package/skills/tableau-next-asset-create/references/tasks/edit-dashboard.md +80 -0
  215. package/skills/tableau-next-asset-create/references/tasks/edit-sdm.md +106 -0
  216. package/skills/tableau-next-asset-create/references/tasks/edit-viz.md +40 -0
  217. package/skills/tableau-next-asset-create/references/tasks/enrich-model.md +68 -0
  218. package/skills/tableau-next-asset-create/references/tasks/ingest-flat-file.md +68 -0
  219. package/skills/tableau-next-asset-create/references/tasks/manage-alert.md +35 -0
  220. package/skills/tableau-next-asset-create/references/tasks/profile-dataset.md +47 -0
  221. package/skills/tableau-next-asset-create/references/tasks/promote-or-reuse.md +46 -0
  222. package/skills/tableau-next-asset-create/references/tasks/provision-user.md +39 -0
  223. package/skills/tableau-next-asset-create/references/tasks/query-model.md +92 -0
  224. package/skills/tableau-next-asset-create/references/tasks/review-verified-questions.md +42 -0
  225. package/skills/tableau-next-asset-create/references/tasks/share-asset.md +37 -0
  226. package/skills/tableau-next-asset-create/references/verified-questions.md +125 -0
  227. package/skills/tableau-next-asset-create/references/viz-authoring.md +992 -0
  228. package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.sh +0 -42
  229. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +0 -26
  230. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.sh +0 -35
  231. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.sh +0 -47
  232. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.sh +0 -33
  233. package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.sh +0 -20
  234. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +0 -15
  235. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +0 -30
  236. package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.sh +0 -37
  237. package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.sh +0 -66
  238. package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.sh +0 -58
  239. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +0 -30
  240. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +0 -73
  241. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +0 -118
  242. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +0 -102
@@ -0,0 +1,355 @@
1
+ # Semantic Query & Enrichment Reference
2
+
3
+ Field-shape matrix, aggregation mapping, and worked payloads for querying an
4
+ SDM and enriching it with calculated fields and metrics. Substitute apiNames
5
+ from `list_*` — do not copy example names into a live call.
6
+
7
+ > **Our MCP is NOT the REST gateway.** Public/Cursor "semantic-query" guides
8
+ > target `POST /services/data/vXX/semantic-engine/gateway` with a **camelCase**
9
+ > body (`tableField`, `rowGrouping: true`, `semanticAggregationMethod`). The
10
+ > MCP `run_semantic_query` tool takes a **proto-shaped snake_case** body
11
+ > (`table_field`, `grouping: "ROW_GROUPING"`, `semantic_aggregation_method`).
12
+ > Do not copy camelCase payloads — they fail. Use the shapes here.
13
+
14
+ ## Contents
15
+
16
+ - run_semantic_query — top-level body (`semantic_context` nested there)
17
+ - Field-shape matrix
18
+ - options block
19
+ - Reading the response
20
+ - Query recovery
21
+ - Worked query (verified): sum of a measure by a joined dimension
22
+ - Detail rows (`detailed_rows: true`)
23
+ - Filtered query (`filter.binary_predicate`)
24
+ - Enrichment — calculated dimension
25
+ - Enrichment — calculated measure
26
+ - Enrichment — metric (named, time-bound KPI)
27
+
28
+ ## run_semantic_query — top-level body
29
+
30
+ ```jsonc
31
+ {
32
+ "semanticModelApiName": "<SDM apiName>", // NOT semanticModelId (deprecated here)
33
+ "source": "tableau-next-pilot-mcp",
34
+ "dataspace": "default", // omit unless multi-dataspace
35
+ "structuredSemanticQuery": { "fields": [...], "options": {...} }
36
+ // OR structuredMetricQuery — mutually exclusive; do not send both
37
+ }
38
+ ```
39
+
40
+ Only `fields`, `filter` XOR `flatten_filter` (never both), `options`,
41
+ `semantic_context`, `aggregate_filter`, `parameters` are valid keys inside
42
+ `structuredSemanticQuery`. Putting `limit`, `sort_orders`, or `row_grouping`
43
+ at that level fails with `Cannot find field: <key>`. Prefer
44
+ `options.limit_options.limit` + `sort_orders` for top-N over proto
45
+ `top_n_filter`.
46
+
47
+ Pass **ONE** of `structuredSemanticQuery` (recommended) **OR**
48
+ `structuredMetricQuery` (alternative) — mutually exclusive dispatch paths.
49
+ Do not send both. Outer-request `context` (`timezone`, `locale`) is distinct
50
+ from per-query `semantic_context`. Most queries omit `semantic_context` — the
51
+ engine picks defaults. Pass it when fiscal-year filters or timezone-sensitive
52
+ date math matters:
53
+
54
+ ```jsonc
55
+ "semantic_context": {
56
+ "timezone": { "id": "America/Los_Angeles" },
57
+ "locale": { "code": "en_US" }
58
+ }
59
+ ```
60
+
61
+ Query is org-level / SDM-level — it does **NOT** take a `workspaceId`. Any SDM
62
+ visible via `list_semantic_models` is queryable regardless of workspace.
63
+
64
+ Treat any **2xx** as success (the wrapper has been observed to return 201).
65
+ Provisioning is gated on `orgHasDataCloudReportingEnabled` OR
66
+ `orgHasSemanticQuery` — a permission error is a **provisioning gap**, not a
67
+ caller payload bug.
68
+
69
+ ## Field-shape matrix
70
+
71
+ | Field kind | expression | grouping / aggregation |
72
+ |---|---|---|
73
+ | **Raw dimension** | `{ "table_field": { "name": "<dimApiName>", "table_name": "<objApiName>" } }` | `"grouping": "ROW_GROUPING"` |
74
+ | **Raw measure** | `{ "table_field": { "name": "<measApiName>", "table_name": "<objApiName>" } }` | `"semantic_aggregation_method": "SEMANTIC_AGGREGATION_METHOD_<AGG>"` |
75
+ | **Calculated dimension** | `{ "semantic_field": { "name": "<calcDimApiName>" } }` | `"grouping": "ROW_GROUPING"` |
76
+ | **Calculated measure** | `{ "semantic_field": { "name": "<calcMeasApiName>" } }` | `"semantic_aggregation_method": "SEMANTIC_AGGREGATION_METHOD_USER_AGG"` (for AVG/ratio/COUNTD expressions) |
77
+
78
+ - `table_name` MUST be the SDM **data-object apiName** from
79
+ `list_semantic_model_data_objects` — NOT the `__dll`/`__dlm` source name
80
+ (that → `Failed to resolve table`).
81
+ - `name` MUST be the **suffixed** field apiName from
82
+ `list_semantic_model_dimensions` / `list_semantic_model_measures`.
83
+ - `semantic_field` is ONLY for **calculated** SDM fields. It takes ONLY
84
+ `name` (no `table_name`). Using `semantic_field` for a raw/physical column
85
+ fails `Failed to resolve semantic field <name>...`. Rule of thumb:
86
+ calculated → `semantic_field`; physical column → `table_field`.
87
+ - `alias` convention: `"<objApiName>.<fieldApiName>"` for table fields,
88
+ `"<apiName>"` for semantic (calculated) fields.
89
+ - A third shape, on-the-fly `calculated_field`, exists; prefer a pre-defined
90
+ calc on the model over inventing one in the query.
91
+ - **In an aggregated query, every measure needs `semantic_aggregation_method`.**
92
+ A measure with no aggregation is treated as a detail row and errors
93
+ `Detail Rows with Metric must have the corresponding dimension` — this fires
94
+ on the **MISSING aggregation**, NOT a missing dimension (adding
95
+ `ROW_GROUPING` does NOT satisfy it). A grouping dimension is optional
96
+ (measure-only = grand total). **Exception:** `options.detailed_rows: true` is
97
+ the one shape where omitting the aggregation method is valid.
98
+
99
+ ### Aggregation method enum
100
+
101
+ Valid query-time suffixes only: `SUM`, `AVG`, `COUNT`, `MIN`, `MAX`,
102
+ `UNIQUE_COUNT`, `USER_AGG`. Map the model's `aggregationType` enum value (left)
103
+ to the query-time suffix (right): `Sum→SUM`, `Average→AVG`, `Count→COUNT`,
104
+ `CountDistinct→UNIQUE_COUNT`, `Min→MIN`, `Max→MAX`. Note the model enum uses
105
+ `Average` (not `Avg`), and there is no `SEMANTIC_AGGREGATION_METHOD_COUNTDISTINCT`
106
+ at query time — `CountDistinct` maps to `SEMANTIC_AGGREGATION_METHOD_UNIQUE_COUNT`,
107
+ a distinct enum value from plain `COUNT` (`COUNT` counts all rows; `UNIQUE_COUNT`
108
+ counts distinct values). A calculated measure whose expression already
109
+ aggregates uses `USER_AGG`.
110
+
111
+ ## options block
112
+
113
+ ```jsonc
114
+ "options": {
115
+ "limit_options": { "limit": 10 },
116
+ "sort_orders": [ { "simple_sort_order": { "sort_by_field_alias": "<alias>", "sorting_order": "DESC" } } ],
117
+ "grand_total": true // OR "detailed_rows": true — never both
118
+ }
119
+ ```
120
+
121
+ - Aggregate query (≥1 measure/calc measure): `grand_total: true` adds a total
122
+ row. Detail query (dimensions only): `detailed_rows: true`. (These two
123
+ option flags are documented independently in the schema; whether they
124
+ combine is **unverified** — the worked query below used neither.)
125
+ - Aggregate queries should include ≥1 dimension with `ROW_GROUPING` (a
126
+ measure-only query returns a single grand-total row — valid for "total X").
127
+
128
+ ## Reading the response
129
+
130
+ Double-wrapped: parse `JSON.parse(response.defaultExc)`. Treat any **2xx** as
131
+ success (wrapper has been observed to return 201). Then:
132
+ `status === "SUCCESS"`; `queryResults.queryMetadata.fields[<alias>].placeInOrder`
133
+ indexes into each `queryResults.queryData.rows[i].values[]`. A `null` grouping
134
+ value is the unmatched/blank bucket (verified: a `null` region row appeared
135
+ alongside the real groups). `status != "SUCCESS"` is a failure — read
136
+ `errorMessage`. `status != "SUCCESS"` with an **empty** `errorMessage` is an
137
+ unknown failure — ask the user to check the org's CDP / Reporting
138
+ configuration. A confirmed **permission** error is the provisioning-gap
139
+ signal (`orgHasDataCloudReportingEnabled` / `orgHasSemanticQuery`), not a
140
+ caller payload bug.
141
+
142
+ **Display rules.** Render rows as a markdown table for ≤20 rows, else row
143
+ count + first 10 + "… and N more". Order by `placeInOrder`. Do **NOT** echo
144
+ the raw `queryResults` JSON. Surface `errorMessage` verbatim on failure.
145
+
146
+ ## Query recovery
147
+
148
+ | Signal | Cause / fix |
149
+ |---|---|
150
+ | `Failed to resolve table` | Used `__dll`/`__dlm` instead of the SDM data-object apiName |
151
+ | `Failed to resolve semantic field` | Used `semantic_field` for a raw/physical column — use `table_field` |
152
+ | `Cannot find field: <key>` | Non-proto top-level key (`limit`/`sort_orders`/`row_grouping` outside `options`) |
153
+ | `Query returns more records than allowed. The limit is: 5000` | Add `limit_options` or aggregate |
154
+ | `USER_ILLEGAL_ARGUMENT_RESOLVE_ENTITY_ERROR` | Typo / wrong table / physical column as `table_field.name` |
155
+ | `Detail Rows with Metric must have the corresponding dimension` | Missing `semantic_aggregation_method` on a measure (not a missing dimension) |
156
+ | Permission error | `orgHasDataCloudReportingEnabled` / `orgHasSemanticQuery` provisioning gap |
157
+ | `status != SUCCESS` with empty `errorMessage` | Unknown failure — check org CDP / Reporting configuration |
158
+
159
+ ## Worked query (verified): sum of a measure by a joined dimension
160
+
161
+ ```jsonc
162
+ {
163
+ "semanticModelApiName": "ZZ_Trap_base0",
164
+ "source": "tableau-next-pilot-mcp",
165
+ "structuredSemanticQuery": {
166
+ "fields": [
167
+ { "expression": { "table_field": { "name": "region18", "table_name": "Accounts" } },
168
+ "alias": "Accounts.region18", "grouping": "ROW_GROUPING" },
169
+ { "expression": { "table_field": { "name": "Amount7", "table_name": "Opportunities" } },
170
+ "alias": "Opportunities.Amount7",
171
+ "semantic_aggregation_method": "SEMANTIC_AGGREGATION_METHOD_SUM" }
172
+ ],
173
+ "options": { "limit_options": { "limit": 10 },
174
+ "sort_orders": [ { "simple_sort_order": { "sort_by_field_alias": "Opportunities.Amount7", "sorting_order": "DESC" } } ] }
175
+ }
176
+ }
177
+ ```
178
+
179
+ Returned per-region sums by traversing the Accounts↔Opportunities join.
180
+
181
+ ## Detail rows (`detailed_rows: true`)
182
+
183
+ The one shape where a measure may omit `semantic_aggregation_method`. Do not
184
+ also set `grand_total`. Field names below are illustrative — copy apiNames from
185
+ `list_*`.
186
+
187
+ ```jsonc
188
+ {
189
+ "semanticModelApiName": "Sales_Performance_SDM",
190
+ "structuredSemanticQuery": {
191
+ "fields": [
192
+ { "expression": { "table_field": { "name": "Account_ID", "table_name": "Account" } },
193
+ "alias": "account_id" },
194
+ { "expression": { "table_field": { "name": "Account_Name", "table_name": "Account" } },
195
+ "alias": "account_name" },
196
+ { "expression": { "table_field": { "name": "Revenue", "table_name": "Account" } },
197
+ "alias": "revenue" }
198
+ ],
199
+ "options": {
200
+ "detailed_rows": true,
201
+ "limit_options": { "limit": 20 }
202
+ }
203
+ },
204
+ "dataspace": "default"
205
+ }
206
+ ```
207
+
208
+ ## Filtered query (`filter.binary_predicate`)
209
+
210
+ `filter` XOR `flatten_filter` — never both. Count-distinct uses
211
+ `SEMANTIC_AGGREGATION_METHOD_UNIQUE_COUNT` (not `COUNTDISTINCT`).
212
+
213
+ ```jsonc
214
+ {
215
+ "semanticModelApiName": "Sales_Performance_SDM",
216
+ "structuredSemanticQuery": {
217
+ "fields": [
218
+ {
219
+ "expression": {
220
+ "table_field": { "name": "Account_ID", "table_name": "Account" }
221
+ },
222
+ "semantic_aggregation_method": "SEMANTIC_AGGREGATION_METHOD_UNIQUE_COUNT",
223
+ "alias": "distinct_accounts"
224
+ }
225
+ ],
226
+ "filter": {
227
+ "binary_predicate": {
228
+ "left_expression": { "table_field": { "name": "Segment", "table_name": "Account" } },
229
+ "binary_operator": "BINARY_OPERATOR_EQUALS",
230
+ "right_expression": { "string_expression": "Enterprise" }
231
+ }
232
+ }
233
+ }
234
+ }
235
+ ```
236
+
237
+ ## Enrichment — calculated dimension
238
+
239
+ `add_semantic_model_calculated_dimension`. TuA expression with **bracketed
240
+ qualified references** `[ObjApiName].[FieldApiName]` (suffixed apiNames). Bare
241
+ identifiers fail with "Missing reference". Verified:
242
+
243
+ ```jsonc
244
+ {
245
+ "modelApiNameOrId": "ZZ_Trap_base0",
246
+ "apiName": "Region_Upper",
247
+ "label": "Region Upper",
248
+ "expression": "UPPER([Accounts].[region18])",
249
+ "dataType": "Text",
250
+ "displayCategory": "Discrete"
251
+ }
252
+ ```
253
+
254
+ Row-level expression → server sets `level: "Row"` automatically.
255
+
256
+ - Calculated-measure TuA conditionals are **simple CASE only**:
257
+ `CASE <expr> WHEN <value> THEN <result> ... [ELSE <result>] END`.
258
+ Searched CASE (`CASE WHEN <condition> THEN ...`) and `IF(condition, then, else)`
259
+ are rejected (`Syntax Error - no viable alternative at input 'WHEN'` /
260
+ `mismatched input ','`). Key the CASE off a value, not a boolean predicate.
261
+ Block `IF`/`ELSEIF`/`END` and `IIF(...)` are **pending live verification** —
262
+ do not use them in a calc measure or dimension until confirmed.
263
+
264
+ ## Enrichment — calculated measure
265
+
266
+ `add_semantic_model_calculated_measure`. Verified (level-aware AVG):
267
+
268
+ ```jsonc
269
+ {
270
+ "modelApiNameOrId": "ZZ_Trap_base0",
271
+ "apiName": "Avg_Deal_Size",
272
+ "label": "Avg Deal Size",
273
+ "expression": "AVG([Opportunities].[Amount7])",
274
+ "dataType": "Number",
275
+ "aggregationType": "UserAgg", // required when the expression aggregates
276
+ "displayCategory": "Continuous"
277
+ }
278
+ ```
279
+
280
+ - Expression that already aggregates (`AVG`, `SUM/COUNT`, `COUNTD`) → must use
281
+ `aggregationType: "UserAgg"`; a bare `Average`/`Sum` is rejected with
282
+ "AggregativeFunction-level calculated fields require UserAgg". Server sets
283
+ `level: "AggregateFunction"`.
284
+ - Row-level arithmetic (`[O].[Profit] / [O].[Sales]`) → `aggregationType: "Auto"`.
285
+ - The server overlays defaults that were not passed (`decimalPlace: 2`,
286
+ `directionality: "Up"`, `sentiment`, `totalAggregationType: "Sum"`,
287
+ `level: "Row"`, `shouldTreatNullsAsZeros: false`) — set them explicitly to
288
+ override.
289
+ - No arithmetic check: `/ 0` is accepted and fails only at query time.
290
+ - Do not set `externalLevel` or `externalConnectionApiName` unless connecting
291
+ to an external definition.
292
+ - Updates are **full PUT**: GET via `get_semantic_model_calculated_measure`,
293
+ then send the complete object. Omitted fields reset to those defaults.
294
+
295
+ To query a UserAgg calc measure, reference it as a `semantic_field` with
296
+ `SEMANTIC_AGGREGATION_METHOD_USER_AGG` (verified returning per-group averages).
297
+
298
+ ## Enrichment — metric (named, time-bound KPI)
299
+
300
+ `add_semantic_model_metric`. `label` is required. **Create a metric by default
301
+ when the request implies a tracked business number** (revenue, win rate,
302
+ engagement, count over time) **and a business-meaningful event date exists to
303
+ anchor it** — not only on explicit demand. Set EXACTLY ONE shape on
304
+ `measurementReference` (and on `timeDimensionReference`). Verified shape:
305
+
306
+ ```jsonc
307
+ {
308
+ "modelApiNameOrId": "Pipeline_Analysis",
309
+ "apiName": "Total_Pipeline",
310
+ "label": "Total Pipeline",
311
+ "measurementReference": { "tableFieldReference": { "tableApiName": "Opportunities", "fieldApiName": "Amount7" } },
312
+ // OR a derived measure: "measurementReference": { "calculatedFieldApiName": "Avg_Deal_Size" }
313
+ "timeDimensionReference": { "tableFieldReference": { "tableApiName": "Opportunities", "fieldApiName": "Created_Date14" } },
314
+ "aggregationType": "Sum", // matches the RAW-measure branch (sum of Amount). For the
315
+ // calculatedFieldApiName branch, set the calc field's own
316
+ // aggregation (e.g. "UserAgg" for Avg_Deal_Size) — do NOT Sum an average.
317
+ "timeGrains": ["Day", "Week", "Month", "Quarter", "Year"],
318
+ "insightsSettings": { // REQUIRED — omit identifyingDimension and the metric UI crashes
319
+ "identifyingDimension": {
320
+ "identifierDimensionReference": {
321
+ "tableFieldReference": { "tableApiName": "Opportunities", "fieldApiName": "Opportunity_Id5" }
322
+ }
323
+ }
324
+ },
325
+ "additionalDimensions": [ // must include identifyingDimension (and every insights/filter field)
326
+ { "tableFieldReference": { "tableApiName": "Opportunities", "fieldApiName": "Opportunity_Id5" } }
327
+ ]
328
+ }
329
+ ```
330
+
331
+ Do not ship this block without `insightsSettings`, and always mirror
332
+ `identifyingDimension` into `additionalDimensions` (create fails with
333
+ `Insight dimension (...) is missing from the metric additional dimensions`).
334
+ Nouns, extra `additionalDimensions`, and `insightsDimensionsReferences` live in
335
+ `ingest-and-metric-gotchas.md` §B and `build-workflow.md` Step 8.
336
+
337
+ - `aggregationType` enum values: `Sum`, `Average`, `Count`, `CountDistinct`,
338
+ `Min`, `Max`, `UserAgg`, `Auto`, etc. (note `Average`, not `Avg`).
339
+ - `fieldApiName` on BOTH references is the **suffixed** apiName **from the
340
+ object that owns the field**. A date field from a *different* object is
341
+ rejected with `Table field with table name: (X) and field name: (Y) was not
342
+ found in the model` (the exact error hit when an Accounts date dim was passed
343
+ for an Opportunities reference). Read each object's own dimensions with
344
+ `list_semantic_model_dimensions` and match the owner.
345
+ - The time dimension must be a **business-meaningful** `Date`/`DateTime`
346
+ dimension (`dataType: "Date"`) — a real event date (created/close/order/
347
+ activity), NOT a `cdp_sys_PartitionDate`, `*_SourceVersion`, or load
348
+ timestamp. A metric on a plumbing date is worse than no metric.
349
+ - With `filters`, also pass `filterLogic` (e.g. `"1"` / `"1 AND 2"`) and
350
+ fully-qualify filter `fieldName` as `<tableApiName>.<fieldApiName>`.
351
+ - Skip the metric only if no meaningful date dimension resolves.
352
+ - Pass **ONE** of `structuredSemanticQuery` **OR** `structuredMetricQuery` on
353
+ `run_semantic_query` — mutually exclusive. Prefer `structuredMetricQuery`
354
+ when querying a named metric (see `build-workflow.md` Step 9). Do not
355
+ reconstruct the metric from raw fields unless no metric exists.
@@ -0,0 +1,322 @@
1
+ # Shared Gates (G1–G8) — the single source of truth
2
+
3
+ Every task guide under `references/tasks/` opens with a **gate header** that
4
+ names the gates it must assert (e.g. "Required: G1, G3, G7"). This file is where
5
+ each gate's *authoritative rule → how to check it → what to do on failure* lives —
6
+ in exactly one place. A guide names a gate and may give a **one-line, non-normative
7
+ reminder** so it reads on its own; it must **not** restate the authoritative rule.
8
+ If a gate's rule ever changes, it changes **here** — the guide reminders are
9
+ pointers, not a second copy to keep in sync.
10
+
11
+ **Legend used in the guide headers:** ● = required · ◐ = conditional (only if the
12
+ action touches >1 object, adds a new join, or references a formula/field it did
13
+ not just read back).
14
+
15
+ **Tool-name convention (single source of truth).** The MCP tools are exposed
16
+ under a `tableau-next-*` server. Everywhere in this skill — gates, router, task
17
+ guides — tool names are written **bare** (e.g. `add_semantic_model_relationship`)
18
+ for readability. Invoke each under whatever name your client advertises for that
19
+ server's tool (Claude Code, for example, exposes it as
20
+ `mcp__tableau-next-pilot-production__add_semantic_model_relationship`); match the
21
+ advertised name rather than hand-constructing one. Guides cite this line; they do
22
+ not restate it.
23
+
24
+ ## Contents
25
+
26
+ - G1 — MCP-server-connected precondition
27
+ - G2 — Data presence is the gate (row-count > 0, re-verified at use time)
28
+ - G3 — Never invent an apiName (read it back via `list_*`)
29
+ - G4 — No island objects
30
+ - G5 — AI-readiness metadata (+ coverage checks)
31
+ - G6 — Data-understanding profiling
32
+ - G7 — Query-returns-real-data validation
33
+ - G8 — Narrative-design-first (decision #1 — scoped)
34
+ - G-notes (shapes cited by the gates, kept here so guides don't re-type them)
35
+
36
+ ---
37
+
38
+ ## G1 — MCP-server-connected precondition
39
+
40
+ **RULE.** Every action in this skill drives a Tableau Next MCP server; without one
41
+ connected there is nothing to call. Never fabricate a tool call or a result
42
+ against a server that is not there.
43
+
44
+ **CHECK.** Confirm the available tools include one prefixed `mcp__tableau-next-*__`
45
+ (e.g. `mcp__tableau-next-pilot-production__browse_data_assets`,
46
+ `mcp__tableau-next-self-service__create_semantic_model`). Server names vary
47
+ (`tableau-next-pilot-*`, `tableau-next-self-service`, …) — match the
48
+ `tableau-next` stem, not an exact name.
49
+
50
+ **ON FAILURE.** If NO such tool is present, **STOP.** Do not attempt the workflow,
51
+ do not describe payloads as if you had run them, and never invent tool
52
+ calls/results/IDs. Tell the user the skill requires a connected Tableau Next MCP
53
+ server, name concrete examples (`tableau-next-pilot-*`, `tableau-next-self-service`),
54
+ and ask them to connect one and re-invoke. This is the difference between "I built
55
+ your dashboard" and a hallucinated transcript of one.
56
+
57
+ > G1 is universal, so it is asserted **once in the router** (`SKILL.md`) and
58
+ > inherited by every entry point — including non-build standalone intents ("add a
59
+ > metric" with no server still STOPs). No guide re-implements it, but every guide
60
+ > depends on it.
61
+
62
+ ---
63
+
64
+ ## G2 — Data presence is the gate (row-count > 0, re-verified at use time)
65
+
66
+ **RULE.** Never build on an object with zero rows. A source with zero rows
67
+ produces an empty visualization no matter how many fields it has, and no join
68
+ fixes it. **Field-richness is not data-presence** — a canonical-looking DMO can
69
+ have 66 fields and 0 rows. Row presence is verified **at use time**, not assumed
70
+ "populated once."
71
+
72
+ **CHECK.** For every *externally discovered* candidate, run `SELECT COUNT(*)`
73
+ (or equivalent) before adding it to a model and before charting it.
74
+ `count > 0` = usable; `count = 0` = empty (see G-note below); a
75
+ `table "X__dlm" does not exist` / `42P01` error = unmaterialized, which is
76
+ distinct from empty — see `empty-source-handling.md`.
77
+
78
+ - **Ingest post-condition:** a freshly created file DLO has 0 rows until
79
+ `run_data_stream` runs. Run the stream, then wait until the DLO is Active
80
+ (`ingest-and-metric-gotchas.md` §A). Row presence is a stand-in for ready, not
81
+ the same thing.
82
+ - **Self-created mapping — query readiness, not status:** for a DMO you just
83
+ created and mapped in this same flow, **`get_dlo_to_dmo_mapping_status`
84
+ `ACTIVE` is not a readiness signal.** It means mapping metadata deployed
85
+ off-core; it does **not** mean `<dmo>__dlm` exists. Poll `run_query`
86
+ `SELECT 1 FROM <dmo>__dlm LIMIT 1` (or `SELECT COUNT(*)`). `42P01` /
87
+ "table does not exist" = NOT-READY — keep polling. Any success, including
88
+ `COUNT = 0`, = READY (table is queryable; proceed to SDM). Use
89
+ `get_dlo_to_dmo_mapping_status` to inspect the mapping and to detect
90
+ `ERROR` / `INACTIVE` — not as the query-readiness gate. Keep the
91
+ discovered-source hard gate as-is: `COUNT = 0` on a pre-existing object
92
+ still means do not build on it.
93
+ - **`isEnabled: false` right after DMO creation is normal.** Check it, but do
94
+ not gate on it and do not wait for it before mapping — expected transient
95
+ state, not a readiness signal.
96
+
97
+ **ON FAILURE.** If a *discovered* candidate has zero rows, refuse to build on it
98
+ and surface it to the user; do not put a measure/dimension from an unverified
99
+ object on a viz. If no discovered candidate has rows, STOP and tell the user the
100
+ sources are empty rather than shipping a blank dashboard. Do not treat
101
+ `COUNT = 0` on a DMO you just mapped in this flow as that failure (READY). Do
102
+ not treat `42P01` on that DMO as "unmaterialized, exclude" — keep polling.
103
+
104
+ ---
105
+
106
+ ## G3 — Never invent an apiName (read it back via `list_*`)
107
+
108
+ **RULE.** The server mutates field/object apiNames on bind — bulk import
109
+ (`shouldIncludeAllFields: true`) suffixes every apiName differently per object
110
+ (`Region__c` → `Region4`; `account_id__c` → `account_id5` on one object,
111
+ `account_id3` on another). Do **not** use that flag for model-level bind
112
+ (deprecated). Nested explicit fields (`semanticDimensions[]` /
113
+ `semanticMeasurements[]` on `create_semantic_model` /
114
+ `add_semantic_model_data_object`) come back as the apiNames you set.
115
+
116
+ **CHECK.** Before typing any apiName you did not read back this session, call the
117
+ relevant `list_*` tool (`list_semantic_model_dimensions` / `_measures` /
118
+ `_data_objects` / `_calculated_*` / `_metrics`) and copy the exact stored value.
119
+ In a relationship, use the semantic apiName with `leftFieldType: "TableField"`
120
+ (not the raw `dataObjectFieldName`).
121
+
122
+ **ON FAILURE.** If you are about to write an apiName you have not read back this
123
+ session, STOP and read it back first. Never assume the two sides of a join share a
124
+ suffix.
125
+
126
+ ---
127
+
128
+ ## G4 — No island objects
129
+
130
+ **RULE.** In a model with two or more objects, every object must participate in at
131
+ least one relationship. (This is secondary to G2: it does not catch a single empty
132
+ object — G2 does.)
133
+
134
+ **CHECK.** After adding objects, confirm every object is on at least one
135
+ relationship. The gate fires once the model has ≥2 objects; a newly added object
136
+ must not be left an island.
137
+
138
+ **ON FAILURE.** Add the missing relationship(s) — validated by G7 — before
139
+ declaring the model done. Do not set `queryUnrelatedDataObjects: "Exception"` and
140
+ then query across unjoined objects (it throws, not warns).
141
+
142
+ ---
143
+
144
+ ## G5 — AI-readiness metadata (+ coverage checks)
145
+
146
+ **RULE.** Populate AI-readiness metadata on every component you create. Agents
147
+ consume the semantic layer in priority order — **metrics first, then calculated
148
+ fields, then raw fields** — so a well-enriched metric set matters more to answer
149
+ quality than raw field coverage. The full checklist, description-quality guide,
150
+ and `businessPreferences` examples live in `ai-readiness.md`; this gate is the
151
+ enforceable summary.
152
+
153
+ **CHECK — metadata each created component must carry:**
154
+
155
+ - **`description`** on the model, each data object, each calculated dimension,
156
+ each calculated measure, and each metric. Missing descriptions are the top AI-
157
+ readiness defect. Custom objects/fields require a clear 1–2 sentence description
158
+ (business context, how it is used, any values with specific meaning); for
159
+ standard Salesforce objects/fields, only enhance the default — never contradict
160
+ it.
161
+ - **`primaryNameField`** on each `add_semantic_model_data_object` — the original
162
+ (pre-suffix) display-name column. **Known server bug:** the field registry is
163
+ empty at create time, so setting it at create fails with `"<field> does not
164
+ exist in <object> fields"` regardless of import mode. Document the missing
165
+ `primaryNameField` as a known gap.
166
+ - **`sentiment`** on directional calculated measures and metrics.
167
+ - **`businessPreferences`** on the model — free-text; set ≥1 statement of what
168
+ the model tracks and any domain terminology. **Read** with
169
+ `get_semantic_model_business_preferences` (`includeModelContent=false`).
170
+ **Write** with `update_semantic_model_business_preferences` (full replacement
171
+ of `# `-prefixed lines; empty string clears; omit the field to leave
172
+ unchanged; send only `businessPreferences`). Fallback: set at create or via
173
+ `update_semantic_model`. Details: `ai-readiness.md`.
174
+ - **`agentEnabled: true`** on the model — gates whether AI agents can use it.
175
+ `create_semantic_model` does **not** expose it (server default `false`); set it
176
+ via an immediate `update_semantic_model` after creation.
177
+ - **Label / type / role accuracy:** object-name + field-label unambiguously
178
+ identify the field's role; date columns are `Date`/`DateTime` (not `Text`);
179
+ numeric columns are measures, categorical/text/date are dimensions; a numeric
180
+ identifier is a **dimension**, not a measure.
181
+ - **apiName permanence:** model/object/calc-field apiNames cannot be edited after
182
+ creation — choose them descriptively (`Gross_Margin_Pct`, not `Calc3`); the only
183
+ fix is delete-and-recreate.
184
+ - **Ambiguity discipline:** differentiate similar fields in name, description, and
185
+ purpose; never copy-paste descriptions. Watch synonyms (two names, one concept →
186
+ remove one; when asked to create two fields with the same/equivalent formula,
187
+ treat as a synonym — declare one canonical, decline the other or ask) and
188
+ homonyms (one column serving two business dates → two calc dimensions with
189
+ distinct labels + explicit descriptions). Omit niche/redundant fields rather
190
+ than leaving them undescribed.
191
+ - Bulk-imported fields (`shouldIncludeAllFields: true`) carry no descriptions and
192
+ get unpredictable apiName suffixes — do **not** use this for model-level bind
193
+ (deprecated). Prefer **nested explicit fields** on
194
+ `create_semantic_model` / `add_semantic_model_data_object`
195
+ (`shouldIncludeAllFields: false`) so descriptions, types, and clean apiNames
196
+ are set at creation. Include join-key fields in those arrays. Reserve
197
+ `add_semantic_model_dimension` / `_measure` for adding a single extra field
198
+ to an already-bound object. Backfill missing descriptions via sparse
199
+ `update_semantic_model_dimension` / `_measure` — these are sparse
200
+ (unlike metric / calc-measure / relationship, which are full PUT). **`isVisible`
201
+ is NOT preserved:** omitting it silently resets a hidden field to
202
+ `isVisible: true`. Always `list_*` first and echo the current `isVisible` and
203
+ `dataObjectFieldName` (omitting `dataObjectFieldName` sends null and
204
+ `SEMANTIC_FIELD_NOT_VALID`). Do not send description-only. Shape:
205
+ `sdm-tool-reference.md`.
206
+
207
+ **CHECK — pre-creation coverage checks (before adding enrichment):**
208
+
209
+ - **Calculated dimension:** MUST call `list_semantic_model_calculated_dimensions`
210
+ first, to check for overlapping coverage of the same source field.
211
+ - **Calculated measure:** MUST call **both**
212
+ `list_semantic_model_calculated_measures` **and**
213
+ `list_semantic_model_metrics` first. Use `aggregationType: "UserAgg"` (not
214
+ `Auto`) when the expression already aggregates (`AVG`, `SUM/COUNT`, `COUNTD`).
215
+ - **Metric (decision #3 — parity resolution):** MUST call
216
+ `list_semantic_model_metrics` first to check that an equivalent metric does not
217
+ already exist (metrics had no pre-creation coverage check historically; this
218
+ gate adds one for parity with calc dimensions/measures). A metric additionally
219
+ requires `insightsSettings.identifyingDimension`, a concrete `aggregationType`
220
+ (**never `Auto`** — rejected: *"The aggregation type (Auto) is not allowed for
221
+ metric aggregation"*), counting via a **numeric field + `Count`** (not a
222
+ dimension/Primary Key — pointing `measurementReference` at a Primary Key is rejected), and a
223
+ **full-PUT `insightsSettings`** on every `update_semantic_model_metric` (it is a
224
+ full PUT; omitting `insightsSettings` nulls it and crashes the metric UI).
225
+
226
+ **ON FAILURE.** Do not declare a model AI-ready on metadata completeness alone —
227
+ always recommend the Semantic Model AI Optimization similarity scan (Semantic
228
+ Model Builder UI) before handoff; `modelHealth: Low` flags ambiguous components.
229
+ Add the missing metadata / run the missing coverage check before proceeding.
230
+
231
+ ---
232
+
233
+ ## G6 — Data-understanding profiling
234
+
235
+ **RULE.** Understand the data before you model it — there is no natural-language
236
+ query layer here to infer meaning for you. This applies even over an **already-
237
+ built** model you do not yet understand; it does NOT drag in Step 0 ingest or the
238
+ large-flat-file protocol on a pre-existing model.
239
+
240
+ **CHECK.** Profile the five things before choosing calc fields, metrics, or charts
241
+ (`data-understanding.md:33-41`): **grain, field roles, cardinality, additivity,
242
+ date roles.** For a large/wide/cryptic flat file, first run the infer-first
243
+ variant (`infer_object_schema` without loading the file into context, decode the
244
+ column-naming grammar, elicit the genuinely ambiguous columns, then verify one
245
+ known number with `run_query` after ingest — `large-flat-file-handling.md`).
246
+
247
+ **ON FAILURE.** Without this, you ship the populated-but-confidently-wrong result
248
+ that passes a "does it return rows?" check: an ID summed as a measure, a snapshot
249
+ inflated by its date count, a metric anchored on a load/system timestamp instead
250
+ of a business-event date, a 100×-off measure that profiled perfectly. Do not
251
+ model or metricize until grain + additivity + the business-event date are known.
252
+
253
+ ---
254
+
255
+ ## G7 — Query-returns-real-data validation
256
+
257
+ **RULE.** A query that returns rows is the proof the model actually works. A join
258
+ that matches ~0 rows is as broken as no join at all.
259
+
260
+ **CHECK.** Run `run_semantic_query` (snake_case proto body — see G-note) and
261
+ confirm real rows come back: before charting (Step 10), after adding a
262
+ relationship (validate the join key with a real JOIN row-count), and at model
263
+ validation (Step 7). For a dashboard, the widget's underlying query must return
264
+ real rows first (transitive: a dashboard is only as valid as its widgets).
265
+
266
+ **ON FAILURE.** If the query returns empty (or a join matches ~0 rows), do NOT
267
+ build the viz/dashboard — STOP, treat the join/source as broken, and fix or
268
+ surface it.
269
+
270
+ ---
271
+
272
+ ## G8 — Narrative-design-first (decision #1 — scoped)
273
+
274
+ **RULE.** Design the analytical story before dropping charts.
275
+ (`dashboard-design-principles.md:41-56`.)
276
+
277
+ - **Dashboards (full narrative — REQUIRED):** order the story KPIs → trends →
278
+ breakdowns → correlations; KPIs top/left on the F/Z eye-path; business-friendly
279
+ labels; chart-type diversity. This is MANDATORY for any dashboard build.
280
+ - **Single standalone viz (light "chart analytical intent" variant — decision
281
+ #1):** for one chart with no dashboard, the full dashboard narrative is NOT
282
+ required. State the chart's analytical intent — what question this one chart
283
+ answers and why this chart type fits the field roles (trend/breakdown/
284
+ correlation/KPI) — then create it. Do NOT invent a dashboard around a single-viz
285
+ ask.
286
+
287
+ **CHECK.** Before the first `create_visualization`: if the ask is a dashboard,
288
+ confirm the full narrative order; if the ask is a single chart, confirm a stated
289
+ chart intent. Match chart type to what each field is showing — do not default
290
+ every widget to a bar chart.
291
+
292
+ **ON FAILURE.** If you are about to jump straight into chart calls with no stated
293
+ intent (single viz) or no narrative (dashboard), STOP and design first.
294
+
295
+ ---
296
+
297
+ ## G-notes (shapes cited by the gates, kept here so guides don't re-type them)
298
+
299
+ - **`run_semantic_query` body is snake_case proto** (`table_field`, `grouping`,
300
+ `semantic_aggregation_method`) — REST-gateway camelCase examples fail. Prefer an
301
+ existing metric / calc measure over reconstructing an aggregation inline. Full
302
+ shape: `semantic-query-and-enrichment.md`.
303
+ - **Ingest mapping:** file-upload DLOs **and** DMOs use `category: "Other"`;
304
+ DLO→DMO mapping field dev names carry a literal `__c` on **both** sides.
305
+ DLO Active → DMO Ready still wait on status. Mapping **query** readiness is
306
+ `run_query` against `<dmo>__dlm` (`42P01` keep polling; `COUNT = 0` is READY).
307
+ `get_dlo_to_dmo_mapping_status` `ACTIVE` is metadata only. Connection ingest
308
+ (Snowflake / …) is the same tail after `list_connections` —
309
+ `ingest-and-metric-gotchas.md` §C. Full chain: `ingest-and-metric-gotchas.md`
310
+ §A.
311
+ - **Dashboard widget editing** goes through `edit_dashboard`'s atomic
312
+ `upsert_*_widget` + `place_widget_on_page` batch — the only supported path.
313
+ Stored text labels must not contain `&` (HTML-encodes to `&amp;`). Full
314
+ mechanics: `edit-dashboard.md`.
315
+ - **Dashboard save never auto-persists** — the objective-9 analog for
316
+ dashboards. `edit_dashboard` stages an unsaved draft by default (top-level
317
+ `autosave`); a `save_dashboard` op persists it (standalone, or after other
318
+ mutations in the same batch), but only call `save_dashboard` on the user's
319
+ explicit confirmation given *after* they've
320
+ seen the draft — even if the original request already said "save it" in the
321
+ same message as the edit. Same rule, same rationale, as `edit_visualization`
322
+ → `update_visualization` (objective 9, `edit-visualization.md` §8).