@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,69 @@
1
+ # Insight bundle and metric render — app-only payloads
2
+
3
+ Cited from `tasks/build-dashboard.md` and `dashboard-authoring.md`. **Not a
4
+ first hop. Not a user dispatch.** Do not call these because a chat user said
5
+ "generate insights."
6
+
7
+ The MCP tools are namespaced per server — names here are bare; use whichever
8
+ server prefix is connected.
9
+
10
+ ---
11
+
12
+ ## `generate_insight_bundle`
13
+
14
+ Produces a Tableau Next insight bundle (live value, trend, and status) for a
15
+ **dashboard metric widget**.
16
+
17
+ **Internal / app-only.** `visibility=app` hides it from the model's tool
18
+ list. Intended for the MCP app renderer via `app.callServerTool()`, **not**
19
+ for the model to invoke on a user chat turn.
20
+
21
+ The renderer forwards the metric definition it already holds. The server
22
+ delegates to the internal insights service via a named-credential callout;
23
+ the org JWT is **minted server-side**. Do **not** mint or pass a browser JWT.
24
+
25
+ Access also requires permission to view Tableau dashboards (plus the Analytics
26
+ family's org-level Tableau / semantic-layer check).
27
+
28
+ ### Body (opaque JSON, forwarded verbatim)
29
+
30
+ Connect does not reshape the body. Field set tracks
31
+ `GenerateInsightBundleRequest`:
32
+
33
+ - `input` — metric bundle input (metric reference + evaluation context:
34
+ measurement/metric, grain, filters, time range the widget is showing)
35
+ - `options` — which artifacts to compute (value, trend/comparison,
36
+ status/threshold)
37
+ - `models` — inline semantic model(s) keyed by API name when the caller
38
+ supplies the definition instead of a stored SDM
39
+
40
+ ### Returns (forwarded verbatim)
41
+
42
+ Unknown nested fields are preserved for the renderer:
43
+
44
+ - `bundle` — live value, trend/comparison series, status/threshold
45
+ - `submetric` — resolved sub-metric when the metric is decomposed
46
+ - `sdm` — resolved semantic-model context
47
+ - `timeRange` / `unifiedTimeRange` — effective range(s) the bundle used
48
+
49
+ ### Live 404 is backend, not a payload bug
50
+
51
+ Orgs have returned `UNEXPECTED_ERROR` / `RuntimeException: Post to
52
+ /v2/internal/bundle status failed. status code: 404` even with a real
53
+ metric + model. The same 404 appears via `render_metric` (same backend
54
+ endpoint). **Do not retry as if the body were wrong.** Document the
55
+ failure; do not invent a "correct" JWT or SDM pin to work around it.
56
+
57
+ ---
58
+
59
+ ## `render_metric`
60
+
61
+ Render a semantic metric **card**: current value, trend, forecast, and
62
+ insights. Pass the metric `apiName` and the semantic model's `apiName`.
63
+ Returns a fully-primed insight-bundle envelope (`sdm` + `bundle` +
64
+ `submetric` + resolved `timeRange` + filters + layout) for the
65
+ metric-standalone MCP renderer. First paint needs no extra client
66
+ round-trips.
67
+
68
+ Same `/v2/internal/bundle` backend family as `generate_insight_bundle` —
69
+ a 404 there is the service, not a missing `apiName`.
@@ -0,0 +1,331 @@
1
+ # Large / wide flat files — infer, decode, elicit (before ingesting)
2
+
3
+ ## Gates → `shared-gates.md`
4
+
5
+ Required **G1, G6** (entry point 3 — infer a large/cryptic file's schema),
6
+ asserted from `profile-dataset.md`. G1: a `mcp__tableau-next-*__` tool must be
7
+ connected because this workflow uses `infer_object_schema`. G6 is this file's
8
+ entire content: infer the fields and types, decode their likely roles, then use
9
+ `run_query` after ingest for value-level profiling.
10
+
11
+ Load this **first**, before any ingestion, whenever the user points at a CSV/Excel
12
+ file that is **large** (tens of MB+ / >100k rows) or **wide** (dozens of columns),
13
+ or whose columns are cryptically named. The failure this prevents is twofold: (1)
14
+ reading an 80 MB file into context and blowing the window, and (2) authoring a
15
+ dashboard off **guessed** column meanings — charting the wrong thing with full
16
+ confidence.
17
+
18
+ > Tableau Desktop teaches "profile the datasource before you build." The
19
+ > published-datasource case lets you lean on its metadata. For a **raw uploaded
20
+ > CSV**, call `infer_object_schema` before creating the data stream and use the
21
+ > returned fields and types as the profile. Same profile-first discipline,
22
+ > earlier stage.
23
+ > After ingestion, normal SDM profiling (`data-understanding.md`) resumes.
24
+
25
+ > **Where ingestion and the SDM build happen.** This reference covers the *file*
26
+ > and the *model's meaning*; the actual ingest chain
27
+ > (`get_upload_connection` → `infer_object_schema` → `create_data_stream` →
28
+ > `run_data_stream` → wait DLO Active → SCHEMA REALITY CHECK + real Primary
29
+ > Key read-back → `create_data_model_object` → wait DMO Ready →
30
+ > `create_dlo_to_dmo_mapping` → inspect mapping status → poll `run_query`
31
+ > until `<dmo>__dlm` exists (`ACTIVE` is metadata only))
32
+ > and the SDM / metric / visualization build are the **workflow steps in this
33
+ > skill's `SKILL.md`**. References below to **"Step 0" and "Step 10"** and to
34
+ > **`viz-authoring.md` / `dashboard-authoring.md` /
35
+ > `semantic-query-and-enrichment.md`** point at that
36
+ > workflow and those sibling reference files — load them when you move from
37
+ > *understanding* the data to *building* on it.
38
+
39
+ The three disciplines below are a hard sequence: **infer → decode → elicit**,
40
+ and only then create the data stream (Step 0). Do not skip ahead on a file whose
41
+ schema you have not inferred and confirmed.
42
+
43
+ ---
44
+
45
+ ## Contents
46
+
47
+ - 1. Infer the schema, never read the whole file
48
+ - 2. Decode the naming convention before asking anything
49
+ - 3. Elicitation gate — ASK before authoring (hard stop)
50
+ - 4. Snapshot / panel files — find the grain, dedup to latest
51
+ - 5. Verify before you author — a hard gate, not a nicety
52
+ - Common mistakes
53
+
54
+ ---
55
+
56
+ ## 1. Infer the schema, never read the whole file
57
+
58
+ Never `Read` the whole file and never paste it into context. Use the standard
59
+ upload flow only far enough to obtain a server-inferred schema:
60
+
61
+ 1. Call `get_upload_connection` with `connectorType: "UploadedFiles"`.
62
+ 2. Use the exact `parentDirectory`, `importDirectory`, file name, and file type
63
+ from the upload flow. For Excel, call `list_data_connection_objects` first and
64
+ infer each selected sheet separately.
65
+ 3. Call `infer_object_schema` for the file or sheet. Do not recreate, trim, or
66
+ normalize the opaque directory values.
67
+ 4. Inspect every returned field's name, type, and, for Date/DateTime fields,
68
+ `format` and `originalType`. Present the inferred fields and wait for the user
69
+ to confirm or adjust types, primary key, and skipped columns before
70
+ `create_data_stream`.
71
+
72
+ `infer_object_schema` is the source of truth for CSV quoting and type inference.
73
+ Do not add a local parsing or profiling step. If the inferred schema leaves a
74
+ field's business meaning ambiguous, handle it through the decode and elicitation
75
+ steps below. Once the DLO is materialized, use `run_query` for value-level checks
76
+ such as row count, null count, distinct count, min/max, date distribution, and
77
+ sample values. Those checks operate on the platform-parsed table and cannot be
78
+ silently shifted by embedded delimiters.
79
+
80
+ Read query results as gates, not trivia: a **non-trivial null rate** on a date or
81
+ metric column means it may not be a clean anchor; disagreeing distinct counts
82
+ between candidate IDs mean the keys do not define the same grain; and a numeric
83
+ ID rendered in scientific notation may already have lost precision. Surface each
84
+ issue and confirm the intended key/type before authoring.
85
+
86
+ ---
87
+
88
+ ## 2. Decode the naming convention before asking anything
89
+
90
+ Wide enterprise extracts almost always follow a column-naming **grammar**.
91
+ Decode it from the header inventory alone — that resolves most columns for free
92
+ and shrinks what you have to ask the user about to the genuinely ambiguous
93
+ residue. Look for:
94
+
95
+ - **Repeated prefixes** = entity/family groupings (`ACCT_*` = account
96
+ attributes; `LOGIN_*`, `EXPORT_*` = behavior families).
97
+ - **Repeated suffixes** = a metric grammar across a window or aggregation:
98
+ - `_7D / _30D / _90D` → a trailing-window flag or value (7/30/90-day).
99
+ - `_TOT_` → an event **count** in the window; `_DISTINCT_` → distinct count;
100
+ `_LAST_TS` / `_LTD` → a last-event timestamp / life-to-date marker.
101
+ - `_IND` / `_FLG` → boolean indicator; `_TXT` / `_NM` / `_DESC` → label
102
+ dimension; `_NUM` / `_CNT` / `_AMT` → measure.
103
+ - **Numbered sequences** (`..._LVL_01..10_NM`) = a hierarchy unrolled into columns.
104
+
105
+ Write the decode down (a small table mapping prefix/suffix → meaning) and infer
106
+ each column's **role** (dimension / measure / date / id) from it. You will be
107
+ right about most. The point of decoding is not to *finish* understanding — it is
108
+ to **isolate the few columns the grammar can't explain**, which is exactly what
109
+ to ask the user about.
110
+
111
+ ---
112
+
113
+ ## 3. Elicitation gate — ASK before authoring (hard stop)
114
+
115
+ After decoding, you will have three kinds of column: **resolved** (the grammar
116
+ explains it), **load-bearing-but-ambiguous** (you need it for the requested
117
+ analysis but its definition lives in the user's head), and **requested-but-
118
+ absent** (the user asked for a metric with no backing column). The last two are a
119
+ **hard gate: STOP and ask the user before authoring anything.** Do not infer a
120
+ load-bearing definition and silently proceed.
121
+
122
+ Ask **targeted, bounded** questions — never "what do all these columns mean?" Ask
123
+ only about the residue, and propose your best guess so the user can confirm or
124
+ correct in one line:
125
+
126
+ - **Derived segment with no single column** (e.g. a "power user" segment, an
127
+ "active account" definition): *"I don't see a single `POWER_USER` column. How
128
+ do you define that segment — which columns/thresholds? My guess: `X_30D > 0`."*
129
+ - **Requested metric, no backing column** (e.g. "seats provisioned" when no such
130
+ column exists): say so explicitly and ask — *"There's no column for seats
131
+ provisioned in this file. Should I show it as an explicit 0 / N-A, drop it, or
132
+ is it derivable from a column I'm not recognizing?"* **Never fabricate a value
133
+ for an absent field.** (The default, per this skill, is to pause and ask; a
134
+ surfaced 0 / "field not present" is acceptable only with the user's say-so.)
135
+ - **Threshold / bucket definitions** (e.g. "daily-equivalent", tiering): confirm
136
+ the cutoffs — *"For 'at least daily-equivalent' over 30 days, I'll bucket
137
+ `EVENTS_TOT_30D >= 60` as ≥2/day and `30–59` as ~1/day. Correct?"*
138
+ - **Clean-but-conventional measure** — units/scale, sign, currency, window basis. A
139
+ column the grammar *did* resolve (`REVENUE_AMT`, `MARGIN`, `LOGIN_30D`) can still
140
+ carry an unstated convention that the type can't reveal: dollars vs cents, fraction
141
+ vs percent, negative-for-credit, mixed currency, or a trailing-30-day vs calendar
142
+ vs life-to-date window basis. Before summing/averaging it, confirm the convention —
143
+ *"Is `REVENUE_AMT` dollars or cents? Do credits go negative? Is `LOGIN_30D` a
144
+ trailing-30-day window as of the snapshot?"* This is the wide-file face of the
145
+ `data-understanding.md` gate's "clean-but-conventional" trigger; a 100×, sign-flipped,
146
+ or window-mismatched measure profiles perfectly and ships silently wrong.
147
+ - **Grain / dedup choice** (see §4): confirm which row wins per entity.
148
+ - **Ambiguous date semantics**: which date is the business event vs a snapshot/
149
+ load stamp.
150
+
151
+ Keep the batch small (the few that block authoring), propose guesses, and wait.
152
+ This is the single most leverage-y step for a wide unknown file: ten minutes of
153
+ questions prevents a confidently-wrong dashboard.
154
+
155
+ ---
156
+
157
+ ## 4. Snapshot / panel files — find the grain, dedup to latest
158
+
159
+ A very common wide-extract shape is a **daily (or periodic) snapshot**: a date
160
+ column (often `SNAP_DT`, `SNAPSHOT_DATE`, `AS_OF`, `PARTITION_DATE`) repeated across
161
+ every entity, so the grain is **entity × snapshot-date**, not entity. Identify the
162
+ candidate entity/date fields from the inferred schema, then validate it after
163
+ ingest with `run_query`:
164
+
165
+ ```text
166
+ distinct snapshot-dates × distinct entity-ids ≈ row count
167
+ ```
168
+
169
+ If that identity roughly holds, it's a panel/snapshot file. **Most exec KPIs want
170
+ "the current state per entity," which means deduping to the latest snapshot per
171
+ entity before aggregating.** Skipping the dedup multiplies every count by the
172
+ number of snapshots.
173
+
174
+ **The identity is necessary, not sufficient — confirm it's an as-of snapshot before
175
+ you dedup.** A once-per-period **transaction fact** (one row per order per day, one
176
+ row per invoice per period) satisfies `distinct dates × distinct entities ≈ rows`
177
+ just as well as a true daily snapshot, and deduping it to "latest per entity" would
178
+ **throw away real events** — the opposite of the snapshot fix. Two cheap
179
+ discriminators tell them apart:
180
+
181
+ - **Does the date repeat *identically* across entities?** In a real snapshot, the
182
+ date column is an **as-of stamp shared by the whole population** on a given load —
183
+ on any one snapshot date, (nearly) every still-active entity has exactly one row.
184
+ In a transaction fact the dates are **per-event and entity-specific** — entity A
185
+ transacts on the 3rd and 9th, entity B on the 5th, and most (date, entity) pairs
186
+ don't exist. Profile it: `rows-per-(date) ≈ active-entity-count` and
187
+ `rows-per-(entity) ≈ snapshot-count` → snapshot; sparse, ragged per-entity dates →
188
+ transaction fact (don't dedup; it's already event grain — anchor on the event
189
+ date). Use grouped `run_query` results to distinguish these shapes.
190
+ - **Profile rows-per-snapshot-date before trusting `max(date)`.** A snapshot's
191
+ **final** date is often a **short or partial load** (the extract ran mid-day, or
192
+ the last partition is still filling). If the latest date has materially fewer rows
193
+ than the prior dates, `max(date)` dedups to a **truncated population** and every
194
+ headline under-reports. Check the tail of the per-date counts; if the last
195
+ snapshot is short, dedup to the last *complete* snapshot (and say so in the source
196
+ line), or flag it to the user. Use `run_query` grouped by the inferred snapshot
197
+ date field; do not build a separate local parser.
198
+
199
+ The robust rule is **dedup to `max(snapshot_date)` per entity-id**. Validate that
200
+ rule with `run_query`, then implement it in Tableau Next as described below so it
201
+ continues to apply after refresh.
202
+
203
+ Do **not** assume all entities share the same latest date — some may have dropped
204
+ out earlier; `max` per entity is correct even when, in a given extract, every
205
+ row happens to land on the same final date. State the dedup rule to the user as
206
+ part of the source line (e.g. *"latest row per account by SNAP_DT"*).
207
+
208
+ **Implementing dedup in Tableau Next — the in-platform recipe.** The file ingests
209
+ whole as the DLO (Step 0); you then expose the deduped grain to the SDM *in the
210
+ model* so the dashboard stays live and re-dedups on every refresh (never by
211
+ pre-trimming the file offline — that ships a snapshot that can't refresh). The
212
+ authorable path is a **latest-flag calculated dimension + a metric filter**, in
213
+ three steps:
214
+
215
+ 1. **A constant `As_Of_Date` calc dimension** — `add_semantic_model_calculated_dimension`
216
+ with `expression: "DATE(\"<max-snapshot-date>\")"`, `dataType: "Date"`,
217
+ `displayCategory: "Continuous"`. This is the single as-of anchor every snapshot
218
+ metric will point its (required) `timeDimensionReference` at (see the box below
219
+ and `data-understanding.md` "Anchoring a snapshot metric").
220
+ 2. **A Text latest-flag calc dimension** — e.g.
221
+ `IF [Obj].[SNAP_DT] = DATE("<max>") THEN "Y" ELSE "N" END`, `dataType: "Text"`,
222
+ `displayCategory: "Discrete"`. **Author the flag as a `Text` "Y"/"N" value, not a
223
+ raw `Date` comparison** — a snapshot metric filters on the flag value, so it needs
224
+ to be a discrete scalar the filter can match, not a date. For a per-entity-correct
225
+ latest (entities that dropped out early still keep their own last row), compute the
226
+ max **per entity** when shaping the flag rather than hardcoding the global max.
227
+ 3. **Filter every snapshot metric to the flag** — `filters: [{ fieldName:
228
+ "<Obj>.<Latest_Flag>", ... }]` with `filterLogic`, so the metric counts only the
229
+ one-row-per-entity latest population.
230
+
231
+ Pre-deduping the CSV locally and ingesting the trimmed file *will* also produce
232
+ correct one-shot numbers, but the resulting dashboard cannot refresh from a
233
+ re-uploaded extract — reserve it for a throwaway local readout, not a delivered
234
+ asset.
235
+
236
+ **Plan the dashboard shape NOW: snapshot → KPI cards, not charts.** An adoption /
237
+ health request over a deduped snapshot resolves into **rates, counts, and window
238
+ flags** — all of which become **calculated** measures/dimensions. A calc *measure*
239
+ can back a **metric** (and thus a KPI card), but the chart tools
240
+ (`create_timeseries_viz` / `create_comparative_viz` / `create_relationship_viz`,
241
+ `viz-authoring.md`) put **native** fields on their shelves — a calc dimension
242
+ or calc measure does not chart directly. So report these as metric widgets.
243
+
244
+ > **And anchor those KPI metrics on a constant as-of date, not a per-row
245
+ > timestamp.** A metric's time anchor is **required** and the card renders the
246
+ > **latest period**, so a deduped snapshot (one as-of moment) must collapse into a
247
+ > single bucket: create a constant `DATE("<as-of>")` calc dimension and point every
248
+ > snapshot metric's `timeDimensionReference` at it. Anchoring on a per-row
249
+ > `LAST_*_TS` / "last activity" attribute scatters the population across months,
250
+ > orphans null-timestamp rows, and makes the card under-report the true total. Full
251
+ > doctrine + the post-authoring one-bucket check: `data-understanding.md`
252
+ > "Anchoring a snapshot metric."
253
+
254
+ So the right deliverable is a **KPI-card dashboard** — metric widgets laid out per
255
+ `dashboard-authoring.md` ("Build the dashboard") — with a chart only where a
256
+ **native** field carries it. If a derived **segment** must appear on a chart axis
257
+ (not just as a number), it has to be a **native column** — and the cheapest place to
258
+ create it is **right here, at the DLO→DMO modelling step**, alongside the
259
+ latest-flag selection (see `data-understanding.md` "materialize segments as native
260
+ columns"). Decide native-vs-calc while you're shaping the deduped object; you cannot
261
+ retrofit a native column after a chart fails at Step 10.
262
+
263
+ ---
264
+
265
+ ## 5. Verify before you author — a hard gate, not a nicety
266
+
267
+ This is a **hard gate, exactly like the §3 elicitation stop**: do not author a
268
+ single widget until it passes. A decode can be wrong in ways that profile cleanly
269
+ and survive every earlier step — a mis-read suffix, a wrong dedup key, a column
270
+ shifted by an embedded comma — and the *only* thing that catches them is
271
+ reproducing a number you can check against ground truth. Skipping this ships a
272
+ dashboard that is plausibly, confidently wrong. Three checks, all before authoring:
273
+
274
+ **(a) Reproduce one headline number the user already knows** — a population count,
275
+ a top-line %. If your decode is right it matches *exactly*; if it doesn't, your
276
+ column understanding is wrong and every metric built on it would be wrong — fix the
277
+ decode (or re-ask, §3) first. **No external number to check against?** (Common for a
278
+ brand-new extract — "what's in this file?") Then manufacture ground truth from the
279
+ materialized table itself: reproduce the population with two independent
280
+ `run_query` aggregations (deduped population vs `COUNT(DISTINCT pk)`) and
281
+ reconcile any two columns that should agree. (b) and (c)
282
+ below are **mandatory regardless** of whether the user supplied a number.
283
+
284
+ **(b) Verify the population independently — don't let the ratio hide a wrong
285
+ denominator.** A percentage can come out right with *both* its numerator and
286
+ denominator wrong (3,140/8,250 and 3,768/9,900 are both ~38%). So check the
287
+ denominator on its own terms: assert the deduped population equals the distinct
288
+ entity count — compare the deduped population with
289
+ `COUNT(DISTINCT entity_id)` in separate `run_query` checks — and reproduce the
290
+ **numerator and the denominator separately**, not just their ratio.
291
+ A matching ratio over an unverified population is not a passed gate.
292
+
293
+ **(c) Spot-check one entity end-to-end.** Pick one real entity, trace it from raw
294
+ rows → dedup-to-latest → its contribution to the headline metric, and confirm each
295
+ step by hand. This is what catches a mis-decoded suffix that an aggregate can't:
296
+ the file-wide total was *computed from* the mis-decode, so it agrees with itself —
297
+ only walking one entity through the actual values exposes that `_TOT_30D` was a
298
+ distinct-count, not an event-count, or that the "latest" row you kept isn't the one
299
+ you meant.
300
+
301
+ Cheap insurance, stated concretely: *"deduped population = 8,250 = COUNT(DISTINCT
302
+ EMP_ID); `LOGIN_30D` truthy = 3,140; 3,140/8,250 = 38.06%; spot-check emp 4471 →
303
+ 3 raw snapshot rows, latest = 2026-06-09, `LOGIN_30D` = 1 → counted once."* That
304
+ one block confirms the decode, the population, and the per-row semantics at once.
305
+ Carry the verified numbers forward as the source-of-truth the dashboard's calc
306
+ measures/metrics must reproduce — and after authoring, re-query the live metric to
307
+ confirm it still returns them (`data-understanding.md` one-bucket check).
308
+
309
+ ---
310
+
311
+ ## Common mistakes
312
+
313
+ 1. **Reading the file into context.** An 80 MB CSV does not belong in the window.
314
+ Infer its schema with `infer_object_schema` (§1).
315
+ 2. **Adding a local parsing step.** Use the inferred schema for fields/types and
316
+ `run_query` against the materialized table for value-level profiling.
317
+ 3. **Authoring on guessed column meanings.** Decode the grammar (§2), then **ask**
318
+ about the residue (§3). Don't infer a load-bearing segment definition silently.
319
+ 4. **Fabricating an absent metric.** A requested field with no backing column is a
320
+ question for the user (surface as 0 / N-A only with their say-so), never an
321
+ invented value.
322
+ 5. **Aggregating a snapshot file without deduping.** entity×date grain inflates
323
+ every count by the snapshot count — dedup to latest per entity first (§4).
324
+ 6. **Assuming all entities share the latest snapshot date.** Use `max` per
325
+ entity; some entities drop out earlier.
326
+ 7. **Building before verifying — treating §5 as optional.** Verification is a hard
327
+ gate, not a nicety: reproduce a number the user knows, **verify the denominator
328
+ independently** (a right-looking ratio can hide a wrong population), and
329
+ **spot-check one entity end-to-end** (an aggregate computed from a mis-decode
330
+ agrees with itself — only one traced entity exposes it). All three before you
331
+ author (§5).
@@ -0,0 +1,54 @@
1
+ {
2
+ "note": "edit_dashboard's live MCP input schema, split by operation for cheap lookup. This file is the envelope only (dashboardIdOrApiName + autosave + operations + minorVersion). Each operations[] item is discriminated by its 'operation' field — read the sibling file named '<operation-value>.json' in this same directory for that operation's exact required fields, properties, and a worked example. Don't guess a payload shape from prose when you can Read the fragment. Cross-cutting widget fields (actions, dynamicTokens, style blocks, receive-sources, conditional formatting) shared by every upsert_*_widget op live once in '_shared-widget-fields.json' — read it alongside a widget op when you need one of those fields.",
3
+ "type": "object",
4
+ "additionalProperties": false,
5
+ "required": ["dashboardIdOrApiName", "operations", "minorVersion"],
6
+ "properties": {
7
+ "dashboardIdOrApiName": {
8
+ "type": "string",
9
+ "description": "The id (0FK...) or apiName of the dashboard the operations apply to. REQUIRED."
10
+ },
11
+ "autosave": {
12
+ "type": "boolean",
13
+ "default": false,
14
+ "description": "Batch-wide persistence mode (top-level — NOT per-operation). false (default) stages the final dashboard as an unsaved draft; true persists once after every operation succeeds. Ignored when a save_dashboard, undo, or discard_dashboard control operation determines the outcome."
15
+ },
16
+ "operations": {
17
+ "type": "array",
18
+ "minItems": 1,
19
+ "description": "Ordered, non-empty list of operations applied atomically in order (all-or-nothing). Each item is one operation, discriminated by its 'operation' field. For upsert_*_widget: provide widget.id to fully replace that persisted widget (also requires widget.name and widget.type to match it); omit id to create a new widget. An ID-less same-name widget may be replaced only when it is an unsaved draft. Each upsert is a complete replacement (omitted fields are dropped) and does not place the widget or change existing placements.",
20
+ "items": {
21
+ "type": "object",
22
+ "required": ["operation"],
23
+ "description": "One operation. Look up its full shape by filename: '<operation>.json' in this directory, where <operation> is this item's 'operation' value."
24
+ }
25
+ },
26
+ "minorVersion": {
27
+ "type": "integer",
28
+ "description": "Minor version supported for the API. Always send -1 (latest supported minor version) — the single-value enum forces this so a compliant client always emits it. NOT a dashboard revision.",
29
+ "enum": [-1],
30
+ "default": -1
31
+ }
32
+ },
33
+ "operationSchemaFiles": [
34
+ "upsert_text_widget.json",
35
+ "upsert_button_widget.json",
36
+ "upsert_container_widget.json",
37
+ "upsert_filter_widget.json",
38
+ "upsert_parameter_widget.json",
39
+ "upsert_visualization_widget.json",
40
+ "upsert_metric_widget.json",
41
+ "upsert_navigation_widget.json",
42
+ "place_widget_on_page.json",
43
+ "remove_widget_from_page.json",
44
+ "remove_widget_from_dashboard.json",
45
+ "move_widget_to_page.json",
46
+ "move_widget.json",
47
+ "add_page.json",
48
+ "rename_page.json",
49
+ "delete_page.json",
50
+ "save_dashboard.json",
51
+ "undo.json",
52
+ "discard_dashboard.json"
53
+ ]
54
+ }
@@ -0,0 +1,122 @@
1
+ {
2
+ "note": "Cross-cutting optional fields shared by every upsert_*_widget operation in this directory: widget.actions, widget.dynamicTokens, and the style/receive-source/conditional-formatting building blocks several widgets' parameters reference by name below. This file is not an operation itself — read it alongside whichever upsert_*_widget.json you're using when you need one of these fields. Everything here is optional; omitting it is always valid.",
3
+ "widgetLevelFields": {
4
+ "description": "Every widget type also accepts an optional top-level widget.description (human-readable, distinct from widget.label). Omitted from the per-widget files for brevity — assume it's always available.",
5
+ "actions": {
6
+ "type": "array",
7
+ "description": "Interactions triggered by the widget on click or select. Each item is one of the 5 action types below, discriminated by actionType.",
8
+ "items": { "oneOf": ["NavigateAction", "FlowAction", "ParameterAction", "FilterAction", "RecordAction"] }
9
+ },
10
+ "dynamicTokens": {
11
+ "type": "object",
12
+ "description": "Dynamic tokens keyed by token name, referenced elsewhere on the widget (e.g. from text content, or a metric's tokenSpec).",
13
+ "additionalProperties": {
14
+ "type": "object",
15
+ "properties": {
16
+ "id": { "type": "string" },
17
+ "name": { "type": "string" },
18
+ "label": { "type": "string" },
19
+ "description": { "type": "string" },
20
+ "type": { "type": "string", "enum": ["query", "insights", "reference", "metric"] },
21
+ "source": { "type": "object", "description": "WidgetDataSource { id, name }." },
22
+ "tokenSpec": { "type": "object", "description": "Shape depends on type; keyed by setting name." }
23
+ }
24
+ }
25
+ }
26
+ },
27
+ "actionTypes": {
28
+ "NavigateAction": {
29
+ "required": ["actionType", "eventType"],
30
+ "properties": {
31
+ "actionType": { "const": "navigate" },
32
+ "eventType": { "enum": ["click", "select"] },
33
+ "parameters": {
34
+ "field": "string, optional",
35
+ "label": "string, optional",
36
+ "includeState": "boolean, optional — carry current dashboard filter/parameter state into the destination",
37
+ "destination": "NavigateDestination — oneOf: {type:\"url\", target} | {type:\"page\", target} | {type:\"dashboard\", target, pageName} | {type:\"metricdetails\", target:{tokenName}}"
38
+ }
39
+ },
40
+ "example": { "actionType": "navigate", "eventType": "click", "parameters": { "destination": { "type": "page", "target": "page_2" } } }
41
+ },
42
+ "FlowAction": {
43
+ "required": ["actionType", "eventType"],
44
+ "properties": {
45
+ "actionType": { "const": "flow" },
46
+ "eventType": { "enum": ["click", "select"] },
47
+ "parameters": {
48
+ "flowName": "string — API name of the flow to run",
49
+ "showDialog": "boolean, optional",
50
+ "attributes": "object keyed by flow variable name -> FlowAttribute { inputDataType, inputData: {inputType:\"static\", value} | {inputType:\"dynamic\", widgetId, widgetField, selectionType: \"result\"|\"selection\"} }"
51
+ }
52
+ },
53
+ "example": { "actionType": "flow", "eventType": "click", "parameters": { "flowName": "Escalate_Opportunity" } }
54
+ },
55
+ "ParameterAction": {
56
+ "required": ["actionType", "eventType"],
57
+ "properties": {
58
+ "actionType": { "const": "parameter" },
59
+ "eventType": { "enum": ["click", "select"] },
60
+ "parameters": {
61
+ "parameter": "value to set on the target parameter widget",
62
+ "sourceFieldAPIName": "string, optional",
63
+ "sourceObjectAPIName": "string, optional"
64
+ }
65
+ },
66
+ "example": { "actionType": "parameter", "eventType": "select", "parameters": { "parameter": "West" } }
67
+ },
68
+ "FilterAction": {
69
+ "required": ["actionType", "eventType"],
70
+ "properties": {
71
+ "actionType": { "const": "filter" },
72
+ "eventType": { "enum": ["click", "select"] },
73
+ "parameters": {
74
+ "filter": "{ tokenName: string }",
75
+ "sourceFieldAPIName": "string, optional",
76
+ "sourceObjectAPIName": "string, optional"
77
+ }
78
+ },
79
+ "example": { "actionType": "filter", "eventType": "select", "parameters": { "filter": { "tokenName": "region_filter" } } }
80
+ },
81
+ "RecordAction": {
82
+ "required": ["actionType", "eventType"],
83
+ "properties": {
84
+ "actionType": { "const": "recordaction" },
85
+ "eventType": { "enum": ["click", "select"] },
86
+ "parameters": {
87
+ "field": "{ fieldKey: string }",
88
+ "recordId": "{ fieldKey: string }",
89
+ "actions": "[{ apiName: string }] — RecordActionInfo list"
90
+ }
91
+ },
92
+ "example": { "actionType": "recordaction", "eventType": "click", "parameters": { "recordId": { "fieldKey": "Id" }, "actions": [{ "apiName": "Log_a_Call" }] } }
93
+ }
94
+ },
95
+ "styleBlocks": {
96
+ "WidgetStyle": { "backgroundColor": "hex", "borderEdges": "string[], e.g. [\"top\",\"bottom\",\"left\",\"right\"]", "borderColor": "hex", "borderWidth": "integer px", "borderRadius": "integer px" },
97
+ "ButtonStyle": { "extends": "WidgetStyle", "fontColor": "hex", "textStyle": "string[], e.g. [\"bold\",\"italic\",\"underline\"]" },
98
+ "ContainerStyle": { "extends": "WidgetStyle", "background": "BackgroundParameters — { alignmentX, alignmentY, imageScale: fitToWidth|fitToHeight|fill|original, opacity: 0-100 }" },
99
+ "VisualizationStyle": { "extends": "WidgetStyle", "textColor": "hex", "lineColor": "hex", "headerBackgroundColor": "hex", "textSize": "integer" },
100
+ "MetricStyle": { "extends": "WidgetStyle", "textColor": "hex" },
101
+ "WidgetTextStyle": { "fontSize": "integer", "fontColor": "hex", "textStyle": "string[]" },
102
+ "ToggleTextStyle": { "alignmentX": "string", "alignmentY": "string", "fontSize": "integer" },
103
+ "ToggleDefaultStyle": { "fontColor": "hex", "textStyle": "string[]" },
104
+ "ToggleSelectedStyle": { "backgroundColor": "hex", "fontColor": "hex", "textStyle": "string[]" },
105
+ "NavigationLabelStyle": { "id": "string", "name": "string", "label": "string", "description": "string", "fontSize": "integer", "alignmentX": "string", "alignmentY": "string" }
106
+ },
107
+ "receiveSources": {
108
+ "receiveFilterSource": {
109
+ "filterMode": "all | include | exclude | none",
110
+ "widgetIds": "string[], optional",
111
+ "publishers": "[{ widgetId, fieldName, objectName, source:{id,name} }], optional — explicit FilterPublisher list"
112
+ },
113
+ "receiveParameterSource": {
114
+ "parameterMode": "all | include | exclude | none",
115
+ "publishers": "[{ widgetId, parameterName }], optional — ParameterPublisher list"
116
+ }
117
+ },
118
+ "conditionalFormatting": {
119
+ "ConditionalFormattingRule": { "name": "string", "formatBasedOn": "string — field or value the rule keys on", "formattingType": "\"single_color\" (only current enum value)", "buckets": "ConditionalFormattingBucket[]" },
120
+ "ConditionalFormattingBucket": { "operator": "greater_than | greater_than_or_equal_to | less_than | less_than_or_equal_to | equals | between", "value": "array", "attributes": "TextContentAttributes — the styling applied when this bucket matches" }
121
+ }
122
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "title": "add_page",
3
+ "type": "object",
4
+ "additionalProperties": false,
5
+ "required": ["operation", "page"],
6
+ "properties": {
7
+ "operation": { "const": "add_page" },
8
+ "layoutName": {
9
+ "type": "string",
10
+ "description": "Dev name of the layout to add the page to. Optional; defaults to the first layout."
11
+ },
12
+ "page": {
13
+ "type": "object",
14
+ "description": "The new page.",
15
+ "required": ["name"],
16
+ "properties": {
17
+ "id": { "type": "string", "description": "Optional page id (rarely needed to author; usually server-assigned)." },
18
+ "name": { "type": "string", "description": "Page dev name, e.g. \"page_2\". Keep the page_N sequence contiguous." },
19
+ "label": { "type": "string", "description": "Display label / tab title, e.g. \"Details\"." },
20
+ "description": { "type": "string", "description": "Optional page description." },
21
+ "navigationHidden": { "type": "boolean", "description": "Whether the page is hidden from navigation." }
22
+ }
23
+ }
24
+ },
25
+ "example": {
26
+ "operation": "add_page",
27
+ "page": { "name": "page_2", "label": "Details" }
28
+ }
29
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "title": "delete_page",
3
+ "type": "object",
4
+ "additionalProperties": false,
5
+ "required": ["operation", "page"],
6
+ "properties": {
7
+ "operation": { "const": "delete_page" },
8
+ "layoutName": {
9
+ "type": "string",
10
+ "description": "Dev name of the layout the page is in. Optional; defaults to the first layout."
11
+ },
12
+ "page": {
13
+ "type": "object",
14
+ "description": "Identifies the page to delete by name.",
15
+ "required": ["name"],
16
+ "properties": {
17
+ "id": { "type": "string", "description": "Optional page id (rarely needed to author; usually server-assigned)." },
18
+ "name": { "type": "string", "description": "Dev name of the page to delete." },
19
+ "description": { "type": "string", "description": "Optional page description (not needed to identify the page — name is sufficient)." }
20
+ }
21
+ }
22
+ },
23
+ "example": {
24
+ "operation": "delete_page",
25
+ "page": { "name": "page_2" }
26
+ }
27
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "title": "discard_dashboard",
3
+ "type": "object",
4
+ "additionalProperties": false,
5
+ "required": ["operation"],
6
+ "properties": {
7
+ "operation": { "const": "discard_dashboard" }
8
+ },
9
+ "description": "Control operation. Standalone (sole operation in the batch): discards the staged draft, reverting to the last persisted state. In a mixed batch: ignores all other operations in that batch (only the discard takes effect).",
10
+ "example": { "operation": "discard_dashboard" }
11
+ }