@salesforce/afv-skills 1.58.0 → 1.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/agentforce-architecture-analyze/SKILL.md +66 -17
- package/skills/agentforce-architecture-analyze/assets/cli/show_access_token.yaml +4 -7
- package/skills/agentforce-architecture-analyze/references/contract.json +1 -1
- package/skills/agentforce-architecture-analyze/scripts/emit_env.py +2 -2
- package/skills/agentforce-architecture-analyze/scripts/main.py +40 -44
- package/skills/agentforce-architecture-analyze/scripts/rest_client.py +11 -3
- package/skills/agentforce-architecture-analyze/scripts/sf_cli.py +77 -10
- package/skills/agentforce-architecture-analyze/scripts/tests/test_end_to_end_fixture.py +1 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_flow_children_inflation.py +1 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_main_pipeline.py +53 -2
- package/skills/agentforce-architecture-analyze/scripts/tests/test_resolve_creds.py +184 -36
- package/skills/agentforce-architecture-analyze/scripts/tests/test_rest_client.py +17 -0
- package/skills/agentforce-architecture-analyze/scripts/tests/test_sf_cli.py +165 -11
- package/skills/agentforce-architecture-analyze/scripts/tests/test_skill_md_pipeline_block.py +319 -0
- package/skills/agentforce-bot-upgrade/SKILL.md +3 -1
- package/skills/agentforce-d360-analyze/SKILL.md +28 -10
- package/skills/agentforce-d360-analyze/scripts/dc.py +200 -50
- package/skills/agentforce-d360-analyze/scripts/discover_sessions.py +10 -6
- package/skills/agentforce-d360-analyze/scripts/fetch_dc.py +22 -6
- package/skills/agentforce-d360-analyze/scripts/resolve_session.py +21 -13
- package/skills/agentforce-d360-analyze/scripts/tests/test_dc_and_resolve_session.py +298 -76
- package/skills/agentforce-d360-analyze/scripts/tests/test_default_target_org.py +432 -0
- package/skills/agentforce-d360-analyze/scripts/tests/test_discover_sessions.py +1 -1
- package/skills/agentforce-d360-analyze/scripts/tests/test_resolve_session_main.py +9 -3
- package/skills/agentforce-d360-analyze/scripts/tests/test_skill_md_prefix_block.py +176 -0
- package/skills/agentforce-generate/SKILL.md +21 -1
- package/skills/agentforce-generate/references/known-issues.md +51 -1
- package/skills/agentforce-generate/references/legacy-nga-regression-eval.md +547 -0
- package/skills/agentforce-generate/references/upgrade-legacy-agent-to-agentscript.md +577 -0
- package/skills/agentforce-generate/scripts/upgrade-legacy-nga-analyze.py +404 -0
- package/skills/agentforce-generate/scripts/upgrade-legacy-nga-run-trials.sh +58 -0
- package/skills/agentforce-persona-generate/SKILL.md +505 -0
- package/skills/agentforce-persona-generate/assets/checklist-template.md +100 -0
- package/skills/agentforce-persona-generate/assets/persona-encoding-template.md +252 -0
- package/skills/agentforce-persona-generate/assets/persona-template.md +229 -0
- package/skills/agentforce-persona-generate/assets/sample-dialog-template.md +50 -0
- package/skills/agentforce-persona-generate/assets/workshop-outline-template.md +97 -0
- package/skills/agentforce-persona-generate/examples/concierge-persona.md +189 -0
- package/skills/agentforce-persona-generate/examples/concierge-sample-dialog.md +70 -0
- package/skills/agentforce-persona-generate/examples/drover-persona.md +194 -0
- package/skills/agentforce-persona-generate/examples/drover-sample-dialog.md +62 -0
- package/skills/agentforce-persona-generate/examples/steady-hand-persona.md +188 -0
- package/skills/agentforce-persona-generate/examples/steady-hand-sample-dialog.md +68 -0
- package/skills/agentforce-persona-generate/examples/yt-persona.md +195 -0
- package/skills/agentforce-persona-generate/examples/yt-sample-dialog.md +66 -0
- package/skills/agentforce-persona-generate/references/attributions.md +36 -0
- package/skills/agentforce-persona-generate/references/interaction-design-notes.md +30 -0
- package/skills/agentforce-persona-generate/references/persona-encoding-guide.md +566 -0
- package/skills/agentforce-persona-generate/references/persona-framework.md +796 -0
- package/skills/agentforce-persona-generate/references/refinement-mappings.md +31 -0
- package/skills/agentforce-persona-generate/references/scoring-rubric.md +58 -0
- package/skills/agentforce-persona-generate/references/voice-catalog.json +2327 -0
- package/skills/agentforce-persona-generate/references/workshop-question-policy.md +90 -0
- package/skills/agentforce-persona-generate/references/workshop-scenario-seeds.md +119 -0
- package/skills/agentforce-persona-generate/scripts/parse_agent_yaml.py +223 -0
- package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +17 -27
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +7 -17
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +47 -63
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +10 -13
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -46
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +4 -21
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +58 -82
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +16 -315
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +9 -24
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -44
- package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +11 -63
- package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +2 -1
- package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +2 -1
- package/skills/data360-schema-get/SKILL.md +3 -3
- package/skills/design-systems-slds-validate/references/report-format.md +1 -1
- package/skills/dx-app-analytics-query/SKILL.md +8 -8
- package/skills/dx-org-manage/SKILL.md +1 -0
- package/skills/dx-org-shape-manage/SKILL.md +1 -0
- package/skills/dx-org-snapshot-manage/SKILL.md +172 -0
- package/skills/dx-org-snapshot-manage/examples/create_error_output.json +16 -0
- package/skills/dx-org-snapshot-manage/examples/create_success_output.json +19 -0
- package/skills/dx-org-snapshot-manage/examples/delete_output.json +9 -0
- package/skills/dx-org-snapshot-manage/examples/get_output.json +19 -0
- package/skills/dx-org-snapshot-manage/examples/list_output.json +36 -0
- package/skills/dx-org-snapshot-manage/references/cli_flags.md +179 -0
- package/skills/dx-org-snapshot-manage/references/snapshot_usage.md +55 -0
- package/skills/dx-org-trial-expiration-check/SKILL.md +1 -1
- package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +2 -2
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +7 -5
- package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +11 -11
- package/skills/experience-content-media-image-generate/SKILL.md +83 -0
- package/skills/experience-content-media-image-generate/scripts/download-image.sh +84 -0
- package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -12
- package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md +3 -3
- package/skills/experience-ui-bundle-app-coordinate/references/phase-execution-pattern.md +9 -7
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.mjs +132 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.mjs +62 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.mjs +71 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.mjs +95 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.mjs +78 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.mjs +21 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.mjs +28 -0
- package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +3 -1
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.mjs +40 -0
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +7 -5
- package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.mjs +70 -0
- package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.mjs +76 -0
- package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.mjs +115 -0
- package/skills/experience-ui-bundle-metadata-generate/SKILL.md +7 -3
- package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +1 -1
- package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +1 -1
- package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.mjs +43 -0
- package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.mjs +131 -0
- package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.mjs +152 -0
- package/skills/experience-ui-bundle-mfa-configure/references/branding.md +10 -6
- package/skills/external-diagram-mermaid-generate/SKILL.md +12 -12
- package/skills/field-service-data-capture-migrate/references/component-mapping.md +1 -1
- package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +1 -2
- package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +1 -0
- package/skills/field-service-data-capture-migrate/references/transformer-rules.md +1 -1
- package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +12 -1
- package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +4 -1
- package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -1
- package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +233 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/accounting-setup.md +117 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/billing-rules-config.md +237 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/billing-settings.md +271 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/demo-policy-config.md +138 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/org-defaults.md +64 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/permissions-config.md +226 -0
- package/skills/insurance-brokerage-agency-billing-configure/references/prerequisites.md +142 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +3 -2
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +3 -3
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +68 -45
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +17 -18
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +16 -3
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +16 -13
- package/skills/marketing-message-test/SKILL.md +194 -0
- package/skills/marketing-message-test/references/api-contract.md +333 -0
- package/skills/omnistudio-callable-apex-generate/SKILL.md +3 -3
- package/skills/omnistudio-datamapper-generate/SKILL.md +6 -6
- package/skills/omnistudio-datapacks-deploy/SKILL.md +11 -11
- package/skills/omnistudio-dependencies-analyze/SKILL.md +5 -5
- package/skills/omnistudio-epc-catalog-generate/SKILL.md +6 -6
- package/skills/omnistudio-flexcard-generate/SKILL.md +6 -6
- package/skills/omnistudio-integration-procedure-generate/SKILL.md +6 -6
- package/skills/omnistudio-omniscript-generate/SKILL.md +6 -5
- package/skills/platform-apex-logs-debug/SKILL.md +1 -0
- package/skills/platform-metadata-deploy/SKILL.md +1 -0
- package/skills/platform-models-api-configure/SKILL.md +5 -5
- package/skills/platform-soql-query/SKILL.md +1 -0
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +17 -6
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +107 -192
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +6 -6
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +49 -20
- package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +4 -4
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +224 -290
- package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +295 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -1
- package/skills/service-itsm-slack-itservice-configure/SKILL.md +2 -1
- package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +2 -2
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +20 -13
- package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +5 -55
- package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +0 -38
- package/skills/service-omni-command-center-analyze/SKILL.md +2 -3
- package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
- package/skills/tableau-next-asset-create/README.md +65 -0
- package/skills/tableau-next-asset-create/SKILL.md +409 -0
- package/skills/tableau-next-asset-create/references/admin-users.md +149 -0
- package/skills/tableau-next-asset-create/references/ai-readiness.md +355 -0
- package/skills/tableau-next-asset-create/references/alerts.md +111 -0
- package/skills/tableau-next-asset-create/references/build-workflow.md +819 -0
- package/skills/tableau-next-asset-create/references/dashboard-authoring.md +302 -0
- package/skills/tableau-next-asset-create/references/dashboard-design-principles.md +352 -0
- package/skills/tableau-next-asset-create/references/data-transform-gotchas.md +210 -0
- package/skills/tableau-next-asset-create/references/data-understanding.md +387 -0
- package/skills/tableau-next-asset-create/references/deep-reference-index.md +74 -0
- package/skills/tableau-next-asset-create/references/destructive-operations.md +62 -0
- package/skills/tableau-next-asset-create/references/edit-dashboard.md +273 -0
- package/skills/tableau-next-asset-create/references/edit-visualization.md +529 -0
- package/skills/tableau-next-asset-create/references/empty-source-handling.md +104 -0
- package/skills/tableau-next-asset-create/references/ingest-and-metric-gotchas.md +638 -0
- package/skills/tableau-next-asset-create/references/insight-bundle.md +69 -0
- package/skills/tableau-next-asset-create/references/large-flat-file-handling.md +331 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_envelope.json +54 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_shared-widget-fields.json +122 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/add_page.json +29 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/delete_page.json +27 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json +11 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget_to_page.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/place_widget_on_page.json +30 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_dashboard.json +16 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_page.json +26 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/rename_page.json +28 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/save_dashboard.json +18 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/undo.json +11 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_button_widget.json +69 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_container_widget.json +88 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_filter_widget.json +146 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_metric_widget.json +78 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_navigation_widget.json +80 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_parameter_widget.json +160 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_text_widget.json +103 -0
- package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_visualization_widget.json +68 -0
- package/skills/tableau-next-asset-create/references/sdm-tool-reference.md +721 -0
- package/skills/tableau-next-asset-create/references/semantic-query-and-enrichment.md +355 -0
- package/skills/tableau-next-asset-create/references/shared-gates.md +322 -0
- package/skills/tableau-next-asset-create/references/sharing-and-promotion.md +306 -0
- package/skills/tableau-next-asset-create/references/tasks/ai-readiness-audit.md +51 -0
- package/skills/tableau-next-asset-create/references/tasks/analyze-data.md +48 -0
- package/skills/tableau-next-asset-create/references/tasks/build-dashboard.md +66 -0
- package/skills/tableau-next-asset-create/references/tasks/build-end-to-end.md +73 -0
- package/skills/tableau-next-asset-create/references/tasks/create-data-transform.md +51 -0
- package/skills/tableau-next-asset-create/references/tasks/create-viz.md +58 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-dashboard.md +80 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-sdm.md +106 -0
- package/skills/tableau-next-asset-create/references/tasks/edit-viz.md +40 -0
- package/skills/tableau-next-asset-create/references/tasks/enrich-model.md +68 -0
- package/skills/tableau-next-asset-create/references/tasks/ingest-flat-file.md +68 -0
- package/skills/tableau-next-asset-create/references/tasks/manage-alert.md +35 -0
- package/skills/tableau-next-asset-create/references/tasks/profile-dataset.md +47 -0
- package/skills/tableau-next-asset-create/references/tasks/promote-or-reuse.md +46 -0
- package/skills/tableau-next-asset-create/references/tasks/provision-user.md +39 -0
- package/skills/tableau-next-asset-create/references/tasks/query-model.md +92 -0
- package/skills/tableau-next-asset-create/references/tasks/review-verified-questions.md +42 -0
- package/skills/tableau-next-asset-create/references/tasks/share-asset.md +37 -0
- package/skills/tableau-next-asset-create/references/verified-questions.md +125 -0
- package/skills/tableau-next-asset-create/references/viz-authoring.md +992 -0
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.sh +0 -42
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +0 -26
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.sh +0 -35
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.sh +0 -47
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.sh +0 -33
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.sh +0 -20
- package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +0 -15
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +0 -30
- package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.sh +0 -37
- package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.sh +0 -66
- package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.sh +0 -58
- package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +0 -30
- package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +0 -73
- package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +0 -118
- package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +0 -102
|
@@ -0,0 +1,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
|
+
}
|
package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json
ADDED
|
@@ -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
|
+
}
|